diff --git a/Client/core/CClientVariables.cpp b/Client/core/CClientVariables.cpp index ce823f07631..47f6845641d 100644 --- a/Client/core/CClientVariables.cpp +++ b/Client/core/CClientVariables.cpp @@ -298,6 +298,7 @@ void CClientVariables::LoadDefaults() DEFAULT("serverbrowser_size", CVector2D(720.0f, 495.0f)); // serverbrowser size DEFAULT("fps_limit", 100); // frame limiter DEFAULT("vsync", true); // vsync + DEFAULT("dxvk_enabled", 0); // vulkan rendering DEFAULT("chat_font", 2); // chatbox font type DEFAULT("chat_lines", 10); // chatbox lines DEFAULT("chat_color", CColor(0, 0, 0, 0)); // chatbox background color diff --git a/Client/core/CSettings.cpp b/Client/core/CSettings.cpp index d956181d5ca..f917555e448 100644 --- a/Client/core/CSettings.cpp +++ b/Client/core/CSettings.cpp @@ -234,6 +234,7 @@ void CSettings::ResetGuiPointers() m_pCheckBoxBlur = NULL; m_pCheckBoxCoronaReflections = NULL; m_pCheckBoxDynamicPedShadows = NULL; + m_pCheckBoxEnableDXVK = NULL; m_pFieldOfViewLabel = NULL; m_pFieldOfView = NULL; m_pFieldOfViewValueLabel = NULL; @@ -1245,6 +1246,12 @@ void CSettings::CreateGUI() m_pCheckBoxVSync = reinterpret_cast(pManager->CreateCheckBox(pTabVideo, _("V-Sync"), true)); m_pCheckBoxVSync->SetPosition(CVector2D(vecTemp.fX + vecSize.fX + 10.0f, vecTemp.fY + 3.0f)); m_pCheckBoxVSync->AutoSize(NULL, 20.0f); + m_pCheckBoxVSync->GetPosition(vecTemp, false); + m_pCheckBoxVSync->GetSize(vecSize); + + m_pCheckBoxEnableDXVK = reinterpret_cast(pManager->CreateCheckBox(pTabVideo, _("Enable Vulkan"), true)); + m_pCheckBoxEnableDXVK->SetPosition(CVector2D(vecTemp.fX + vecSize.fX + 10.0f, vecTemp.fY)); + m_pCheckBoxEnableDXVK->AutoSize(NULL, 20.0f); // Reset position to leftmost m_pFullscreenStyleLabel->GetPosition(vecTemp, false); @@ -2007,6 +2014,7 @@ void CSettings::CreateGUI() m_pCheckBoxWindowed->SetClickHandler(GUI_CALLBACK(&CSettings::OnWindowedClick, this)); m_pCheckBoxDPIAware->SetClickHandler(GUI_CALLBACK(&CSettings::OnDPIAwareClick, this)); m_pCheckBoxVSync->SetClickHandler(GUI_CALLBACK(&CSettings::OnVSyncClick, this)); + m_pCheckBoxEnableDXVK->SetClickHandler(GUI_CALLBACK(&CSettings::OnEnableVulkanClick, this)); m_pCheckBoxShowUnsafeResolutions->SetClickHandler(GUI_CALLBACK(&CSettings::ShowUnsafeResolutionsClick, this)); m_pButtonBrowserBlacklistAdd->SetClickHandler(GUI_CALLBACK(&CSettings::OnBrowserBlacklistAdd, this)); m_pButtonBrowserBlacklistRemove->SetClickHandler(GUI_CALLBACK(&CSettings::OnBrowserBlacklistRemove, this)); @@ -2340,6 +2348,11 @@ void CSettings::UpdateVideoTab() CVARS_GET("dynamic_ped_shadows", bDynamicPedShadows); m_pCheckBoxDynamicPedShadows->SetSelected(bDynamicPedShadows); + // Enable Vulkan + bool bEnableDXVK; + CVARS_GET("dxvk_enabled", bEnableDXVK); + m_pCheckBoxEnableDXVK->SetSelected(bEnableDXVK); + // Enable dynamic ped shadows checkbox if visual quality option is set to high or very high m_pCheckBoxDynamicPedShadows->SetEnabled(FxQuality >= 2); @@ -4555,6 +4568,10 @@ void CSettings::SaveData() CVARS_SET("dynamic_ped_shadows", bDynamicPedShadows); gameSettings->SetDynamicPedShadowsEnabled(bDynamicPedShadows); + // Enable Vulkan + bool bEnableDXVK = m_pCheckBoxEnableDXVK->GetSelected(); + CVARS_SET("dxvk_enabled", bEnableDXVK); + // Fast clothes loading if (CGUIListItem* pSelected = m_pFastClothesCombo->GetSelectedItem()) { @@ -5893,6 +5910,89 @@ bool CSettings::OnVSyncClick(CGUIElement* pElement) return true; } +static void VulkanNotSupportedCallBack(void* userdata, unsigned int uiButton); + +// +// OnEnableVulkanClick +// +bool CSettings::OnEnableVulkanClick(CGUIElement* pElement) +{ + if (!m_pCheckBoxEnableDXVK->GetSelected()) + { + CVARS_SET("dxvk_enabled", false); + CCore::GetSingleton().SaveConfig(); + ShowRestartQuestion(); + return true; + } + + if (GetApplicationSettingInt("dxvk", "files_ok") != 1) + { + m_pCheckBoxEnableDXVK->SetSelected(false); + + CQuestionBox* pQuestionBox = CCore::GetSingleton().GetLocalGUI()->GetMainMenu()->GetQuestionWindow(); + pQuestionBox->Reset(); + pQuestionBox->SetTitle(_("VULKAN FILES MISSING OR DAMAGED")); + pQuestionBox->SetMessage(_("The Vulkan files are missing or damaged,\nso this option cannot be enabled.")); + pQuestionBox->SetButton(0, _("OK")); + pQuestionBox->SetCallback(VulkanNotSupportedCallBack); + pQuestionBox->Show(); + return true; + } + + if (GetApplicationSettingInt("dxvk", "vulkan_supported") != 1) + { + m_pCheckBoxEnableDXVK->SetSelected(false); + + CQuestionBox* pQuestionBox = CCore::GetSingleton().GetLocalGUI()->GetMainMenu()->GetQuestionWindow(); + pQuestionBox->Reset(); + pQuestionBox->SetTitle(_("VULKAN NOT SUPPORTED")); + pQuestionBox->SetMessage(_("Vulkan is not available on your system,\nso this option cannot be enabled.")); + pQuestionBox->SetButton(0, _("OK")); + pQuestionBox->SetCallback(VulkanNotSupportedCallBack); + pQuestionBox->Show(); + return true; + } + + CQuestionBox* pQuestionBox = CCore::GetSingleton().GetLocalGUI()->GetMainMenu()->GetQuestionWindow(); + pQuestionBox->Reset(); + pQuestionBox->SetTitle(_("ENABLE VULKAN")); + pQuestionBox->SetMessage( + _("Vulkan can increase your frame rate by making better use of your graphics card.\n\n" + "When you first enable it, you may notice minor stuttering while the shader cache is built.\n" + "This is temporary and everything will run smoothly once the cache is complete.\n\n" + "Are you sure you want to enable Vulkan?")); + pQuestionBox->SetButton(0, _("No")); + pQuestionBox->SetButton(1, _("Yes")); + pQuestionBox->SetCallback(EnableVulkanQuestionCallBack, this); + pQuestionBox->Show(); + + return true; +} + +static void VulkanNotSupportedCallBack(void* userdata, unsigned int uiButton) +{ + CCore::GetSingleton().GetLocalGUI()->GetMainMenu()->GetQuestionWindow()->Reset(); +} + +void CSettings::EnableVulkanQuestionCallBack(void* userdata, unsigned int uiButton) +{ + CCore::GetSingleton().GetLocalGUI()->GetMainMenu()->GetQuestionWindow()->Reset(); + + auto* pSettings = static_cast(userdata); + if (!pSettings) + return; + + if (uiButton == 0) + { + pSettings->m_pCheckBoxEnableDXVK->SetSelected(false); + return; + } + + CVARS_SET("dxvk_enabled", true); + CCore::GetSingleton().SaveConfig(); + pSettings->ShowRestartQuestion(); +} + static void CPUAffinityQuestionCallBack(void* userdata, unsigned int button) { CCore::GetSingleton().GetLocalGUI()->GetMainMenu()->GetQuestionWindow()->Reset(); diff --git a/Client/core/CSettings.h b/Client/core/CSettings.h index 864feadb727..353c2c83e84 100644 --- a/Client/core/CSettings.h +++ b/Client/core/CSettings.h @@ -176,6 +176,7 @@ class CSettings CGUICheckBox* m_pCheckBoxBlur; CGUICheckBox* m_pCheckBoxCoronaReflections; CGUICheckBox* m_pCheckBoxDynamicPedShadows; + CGUICheckBox* m_pCheckBoxEnableDXVK; CGUILabel* m_pFieldOfViewLabel; CGUIScrollBar* m_pFieldOfView; CGUILabel* m_pFieldOfViewValueLabel; @@ -451,6 +452,7 @@ class CSettings bool OnWindowedClick(CGUIElement* pElement); bool OnDPIAwareClick(CGUIElement* pElement); bool OnVSyncClick(CGUIElement* pElement); + bool OnEnableVulkanClick(CGUIElement* pElement); bool OnShowAdvancedSettingDescription(CGUIElement* pElement); bool OnHideAdvancedSettingDescription(CGUIElement* pElement); bool OnTabChanged(CGUIElement* pElement); @@ -486,6 +488,8 @@ class CSettings void UpdateBorderlessAdjustmentControls(); void ResetGuiPointers(); + static void EnableVulkanQuestionCallBack(void* userdata, unsigned int uiButton); + unsigned int m_uiCaptureKey; bool m_bCaptureKey; bool m_bCaptureAxis; diff --git a/Client/core/premake5.lua b/Client/core/premake5.lua index a24fb436616..db91ee5905f 100644 --- a/Client/core/premake5.lua +++ b/Client/core/premake5.lua @@ -71,6 +71,10 @@ project "Client Core" "%[%{!wks.location}/../utils/gen_language_list.exe] %[%{!wks.location}/../Shared/data/MTA San Andreas/MTA/locale] %[languages.generated.h]" } + postbuildcommands { + "\"$(SolutionDir)..\\utils\\dxvk-1.10.3\\build-mta.bat\" \"$(SolutionDir)..\\Bin\\mta\\dxvk\"", + } + filter "architecture:not x86" flags { "ExcludeFromBuild" } diff --git a/Client/loader/D3DStuff.cpp b/Client/loader/D3DStuff.cpp index ca4401a2e91..fbb9ae4cf48 100644 --- a/Client/loader/D3DStuff.cpp +++ b/Client/loader/D3DStuff.cpp @@ -273,3 +273,246 @@ void EndD3DStuff() SAFE_RELEASE(pD3DDevice9); SAFE_RELEASE(pD3D9); } + +////////////////////////////////////////////////////////// +// +// DXVK (D3D9 -> Vulkan) support +// +////////////////////////////////////////////////////////// + +static const char* const DXVK_LIBRARY_NAMES[] = {"d3d9.dll", "dxgi.dll"}; + +static SString GetDXVKStageDir() +{ + return PathJoin(GetMTASAPath(), "mta", "dxvk"); +} + +static SString GetDXVKStageFile(const char* szFileName) +{ + return PathJoin(GetDXVKStageDir(), szFileName); +} + +static SString GetDXVKGtaDir() +{ + return UTF8FilePath(GetGameLaunchDirectory()); +} + +bool IsDXVKBinaryFile(const SString& strFilePath) +{ + if (!FileExists(strFilePath)) + return false; + + const SString strFileMd5 = CMD5Hasher::CalculateHexString(strFilePath); + for (const char* szName : DXVK_LIBRARY_NAMES) + { + const SString strStagePath = GetDXVKStageFile(szName); + if (FileExists(strStagePath) && CMD5Hasher::CalculateHexString(strStagePath).CompareI(strFileMd5)) + return true; + } + return false; +} + +static void RemovePlacedDXVKFiles() +{ + const SString strGtaLaunchDir = GetDXVKGtaDir(); + for (const char* szName : DXVK_LIBRARY_NAMES) + { + const SString strPath = PathJoin(strGtaLaunchDir, szName); + if (FileExists(strPath)) + { + FileDelete(strPath); + WriteDebugEvent(SString("DXVK: removed %s from GTA launch directory", *strPath)); + } + } +} + +static void CopyDXVKFileIfNeeded(const SString& strSrc, const SString& strDst) +{ + if (!FileExists(strSrc)) + return; + if (FileExists(strDst) && CMD5Hasher::CalculateHexString(strDst).CompareI(CMD5Hasher::CalculateHexString(strSrc))) + return; + CopyFileW(FromUTF8(strSrc).c_str(), FromUTF8(strDst).c_str(), FALSE); +} + +static bool ProbeD3D9Create(HMODULE hD3d9) +{ + using FnDirect3DCreate9 = IDirect3D9*(__stdcall*)(UINT); + FnDirect3DCreate9 pfnDirect3DCreate9 = nullptr; + if (!SharedUtil::TryGetProcAddress(hD3d9, "Direct3DCreate9", pfnDirect3DCreate9) || !pfnDirect3DCreate9) + return false; + + __try + { + if (IDirect3D9* pD3D9 = pfnDirect3DCreate9(D3D_SDK_VERSION)) + { + pD3D9->Release(); + return true; + } + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + } + return false; +} + +static bool ProbeVulkanSupport(const SString& strStageDir) +{ + const SString strStageD3d9 = PathJoin(strStageDir, "d3d9.dll"); + if (!FileExists(strStageD3d9)) + return false; + + const SString strFilesHash = CMD5Hasher::CalculateHexString(strStageD3d9) + CMD5Hasher::CalculateHexString(PathJoin(strStageDir, "dxgi.dll")); + if (GetApplicationSettingInt("dxvk", "vulkan_supported") == 1 && GetApplicationSetting("dxvk", "probe_file_hash") == strFilesHash) + return true; + + const SString strProbeD3d9 = PathJoin(strStageDir, SString("d3d9_probe_%d.dll", GetCurrentProcessId())); + if (!CopyFileW(FromUTF8(strStageD3d9).c_str(), FromUTF8(strProbeD3d9).c_str(), FALSE)) + return false; + + bool bSupported = false; + if (HMODULE hD3d9 = LoadLibraryExW(FromUTF8(strProbeD3d9).c_str(), NULL, LOAD_WITH_ALTERED_SEARCH_PATH)) + { + bSupported = ProbeD3D9Create(hD3d9); + FreeLibrary(hD3d9); + } + + FileDelete(strProbeD3d9); + + if (bSupported) + SetApplicationSetting("dxvk", "probe_file_hash", strFilesHash); + + return bSupported; +} + +static SString GetCoreConfigFilename() +{ + return CalcMTASAPath(PathJoin("mta", "config", "coreconfig.xml")); +} + +bool GetDXVKEnabledSetting() +{ + SString strCoreConfig; + FileLoad(GetCoreConfigFilename(), strCoreConfig); + return strCoreConfig.SplitRight("").Left(1) == "1"; +} + +void SetDXVKEnabledSetting(bool bEnable) +{ + const char* szFrom = bEnable ? "0" : "1"; + const char* szTo = bEnable ? "1" : "0"; + + SString strCoreConfig; + if (!FileLoad(GetCoreConfigFilename(), strCoreConfig) || !strCoreConfig.Contains(szFrom)) + return; + + strCoreConfig = strCoreConfig.Replace(szFrom, szTo); + FileSave(GetCoreConfigFilename(), strCoreConfig); + WriteDebugEvent(SString("DXVK: set dxvk_enabled=%d in coreconfig.xml", bEnable ? 1 : 0)); +} + +static bool IsValidDXVKBinary(const SString& strPath) +{ + if (FileSize(strPath) < 1000000) + return false; + + SString strData; + if (!FileLoad(strPath, strData) || strData.length() < 0x40) + return false; + + const unsigned char* pData = reinterpret_cast(strData.c_str()); + if (pData[0] != 'M' || pData[1] != 'Z') + return false; + + const unsigned int uiPe = pData[0x3C] | (pData[0x3D] << 8) | (pData[0x3E] << 16) | (static_cast(pData[0x3F]) << 24); + if (uiPe == 0 || uiPe + 6 > strData.length() || pData[uiPe] != 'P' || pData[uiPe + 1] != 'E' || pData[uiPe + 2] != 0 || pData[uiPe + 3] != 0) + return false; + + const unsigned short usMachine = static_cast(pData[uiPe + 4] | (pData[uiPe + 5] << 8)); + if (usMachine != 0x014C) + return false; + + return true; +} + +static SString VerifyDXVKStageFiles() +{ + for (const char* szName : DXVK_LIBRARY_NAMES) + { + const SString strPath = GetDXVKStageFile(szName); + if (!FileExists(strPath)) + return SString("%s is missing from mta\\dxvk", szName); + if (!IsValidDXVKBinary(strPath)) + return SString("%s is missing, corrupted or not a valid 32-bit binary", szName); + } + return ""; +} + +bool ManageDXVK() +{ + const bool bEnable = GetDXVKEnabledSetting(); + const SString strGtaLaunchDir = GetDXVKGtaDir(); + + const SString strVerifyProblem = VerifyDXVKStageFiles(); + const bool bFilesOk = strVerifyProblem.empty(); + + const bool bVulkanSupported = bFilesOk && ProbeVulkanSupport(GetDXVKStageDir()); + SetApplicationSetting("dxvk", "vulkan_supported", bVulkanSupported ? "1" : "0"); + SetApplicationSetting("dxvk", "files_ok", bFilesOk ? "1" : "0"); + + if (!bEnable) + { + RemovePlacedDXVKFiles(); + return true; + } + + if (!bFilesOk) + { + RemovePlacedDXVKFiles(); + WriteDebugEvent(SString("DXVK: %s - Vulkan files not usable", *strVerifyProblem)); + AddReportLog(7210, SString("DXVK: %s - Vulkan files not usable", *strVerifyProblem)); + + SetDXVKEnabledSetting(false); + AddReportLog(7215, "DXVK: Vulkan auto-disabled (files missing or damaged)"); + return true; + } + + if (!bVulkanSupported) + { + RemovePlacedDXVKFiles(); + WriteDebugEvent("DXVK: Vulkan not supported on this system"); + AddReportLog(7212, "DXVK: Vulkan not supported"); + + SetDXVKEnabledSetting(false); + AddReportLog(7213, "DXVK: Vulkan auto-disabled (not supported)"); + return true; + } + + for (const char* szName : DXVK_LIBRARY_NAMES) + { + const SString strGtaPath = PathJoin(strGtaLaunchDir, szName); + if (FileExists(strGtaPath) && !IsDXVKBinaryFile(strGtaPath)) + { + FileDelete(strGtaPath); + WriteDebugEvent(SString("DXVK: removed foreign %s from GTA launch directory", szName)); + AddReportLog(7211, SString("DXVK: removed foreign %s from GTA launch directory", szName)); + } + } + + MakeSureDirExists(strGtaLaunchDir); + CopyDXVKFileIfNeeded(GetDXVKStageFile("d3d9.dll"), PathJoin(strGtaLaunchDir, "d3d9.dll")); + CopyDXVKFileIfNeeded(GetDXVKStageFile("dxgi.dll"), PathJoin(strGtaLaunchDir, "dxgi.dll")); + + for (const char* szName : DXVK_LIBRARY_NAMES) + { + const SString strGtaPath = PathJoin(strGtaLaunchDir, szName); + if (FileExists(strGtaPath)) + { + SetApplicationSetting("diagnostics", SString("%s-dll-last-hash", szName), CMD5Hasher::CalculateHexString(strGtaPath)); + SetApplicationSetting("diagnostics", SString("%s-dll-not-again", szName), "yes"); + } + } + + WriteDebugEvent("DXVK: Vulkan supported - D3D9 will be translated to Vulkan"); + return true; +} diff --git a/Client/loader/D3DStuff.h b/Client/loader/D3DStuff.h index 16cd19ddc3a..39a40aa7036 100644 --- a/Client/loader/D3DStuff.h +++ b/Client/loader/D3DStuff.h @@ -15,3 +15,10 @@ void BeginD3DStuff(); void EndD3DStuff(); void LoaderResolveCrashHandlerExports(HMODULE coreModule) noexcept; + +bool ManageDXVK(); + +bool IsDXVKBinaryFile(const SString& strFilePath); + +bool GetDXVKEnabledSetting(); +void SetDXVKEnabledSetting(bool bEnable); diff --git a/Client/loader/MainFunctions.cpp b/Client/loader/MainFunctions.cpp index dd911f20737..e866099d119 100644 --- a/Client/loader/MainFunctions.cpp +++ b/Client/loader/MainFunctions.cpp @@ -729,6 +729,23 @@ void HandleNotUsedMainMenu() } } + if (GetDXVKEnabledSetting()) + { + SString strMessage = _("Are you having problems running MTA:SA?.\n\nDo you want to change the following setting?"); + strMessage += "\n" + _("Vulkan") + " -> " + _("Disabled"); + HideSplash(); + int iResponse = MessageBoxUTF8(NULL, strMessage, "MTA: San Andreas", MB_YESNO | MB_ICONQUESTION | MB_TOPMOST); + if (iResponse == IDYES) + { + SetDXVKEnabledSetting(false); + AddReportLog(9316, "Loader - HandleNotUsedMainMenu - User change to Vulkan disabled"); + } + else + { + AddReportLog(9317, "Loader - HandleNotUsedMainMenu - User said no to Vulkan disable"); + } + } + // Check for problem processes struct { @@ -1460,6 +1477,11 @@ void CheckDataFiles() ExitProcess(EXIT_ERROR); } + if (!ManageDXVK()) + { + ExitProcess(EXIT_ERROR); + } + // No-op known incompatible/broken d3d9.dll versions from the launch directory // By using file version we account for variants as well. The array is extendable, but primarily for D3D9.dll 6.3.9600.17415 (MTA top 5 crash) { @@ -1720,6 +1742,9 @@ void CheckDataFiles() if (!FileExists(library.absoluteFilePath)) continue; + if (IsDXVKBinaryFile(library.absoluteFilePath)) + continue; + library.appLastHash = SString("%s%s-dll-last-hash", directory.first, library.stem.c_str()); library.appDontRemind = SString("%s%s-dll-not-again", directory.first, library.stem.c_str()); @@ -2081,6 +2106,7 @@ int LaunchGame(SString strCmdLine) AddReportLog(7104, "Loader - Finishing"); WriteDebugEvent("Loader - Finishing"); + EndD3DStuff(); const DWORD rawExitCode = dwExitCode; diff --git a/Client/loader/premake5.lua b/Client/loader/premake5.lua index e1db452e78c..6f93debd233 100644 --- a/Client/loader/premake5.lua +++ b/Client/loader/premake5.lua @@ -48,6 +48,10 @@ project "Loader" "resource/splash.bmp" } + postbuildcommands { + "\"$(SolutionDir)..\\utils\\dxvk-1.10.3\\build-mta.bat\" \"$(SolutionDir)..\\Bin\\mta\\dxvk\"", + } + filter "architecture:not x86" flags { "ExcludeFromBuild" } diff --git a/Shared/installer/nightly.nsi b/Shared/installer/nightly.nsi index e72288c9c45..ff210085c6a 100644 --- a/Shared/installer/nightly.nsi +++ b/Shared/installer/nightly.nsi @@ -719,6 +719,10 @@ SectionGroup /e "$(INST_SEC_CLIENT)" SECGCLIENT File "${FILES_ROOT}\maetro32.dll" !endif + SetOutPath "$INSTDIR\MTA\dxvk" + File /nonfatal "${FILES_ROOT}\mta\dxvk\d3d9.dll" + File /nonfatal "${FILES_ROOT}\mta\dxvk\dxgi.dll" + # Added as per https://bitbucket.org/chromiumembedded/cef/commits/8424f166ccef # Not currently using \mta\cef\ due to https://github.com/chromiumembedded/cef/issues/3749#issuecomment-2278568964 (it's already crashing and likely won't remain supported) @@ -1150,6 +1154,7 @@ Section Uninstall RmDir /r "$INSTDIR\MTA\cgui" RmDir /r "$INSTDIR\MTA\data" RmDir /r "$INSTDIR\MTA\CEF" + RmDir /r "$INSTDIR\MTA\dxvk" RmDir /r "$INSTDIR\MTA\locale" Delete "$INSTDIR\MTA\*.dll" Delete "$INSTDIR\MTA\*.exe" diff --git a/utils/dxvk-1.10.3/.github/ISSUE_TEMPLATE/bug_report.md b/utils/dxvk-1.10.3/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000000..236add1f7e6 --- /dev/null +++ b/utils/dxvk-1.10.3/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,34 @@ +--- +name: Bug report +about: Report crashes, rendering issues etc. +title: '' +labels: '' +assignees: '' + +--- + +Please describe your issue as accurately as possible. If you run into a problem with a binary release, make sure to test with latest `master` as well. + +**Important:** When reporting an issue with a specific game or application, such as crashes or rendering issues, please include log files and, if possible, a D3D11/D3D9 Apitrace (see https://github.com/apitrace/apitrace) so that the issue can be reproduced. +In order to create a trace for **D3D11/D3D10**: Run `wine apitrace.exe trace -a dxgi YOURGAME.exe`. +In order to create a trace for **D3D9**: Follow https://github.com/doitsujin/dxvk/wiki/Making-a-Trace. +Preferably record the trace on Windows, or wined3d if possible. + +**Reports with no log files will be ignored.** + +### Software information +Name of the game, settings used etc. + +### System information +- GPU: +- Driver: +- Wine version: +- DXVK version: + +### Apitrace file(s) +- Put a link here + +### Log files +- d3d9.log: +- d3d11.log: +- dxgi.log: diff --git a/utils/dxvk-1.10.3/.github/workflows/artifacts.yml b/utils/dxvk-1.10.3/.github/workflows/artifacts.yml new file mode 100644 index 00000000000..b843d1aaf7d --- /dev/null +++ b/utils/dxvk-1.10.3/.github/workflows/artifacts.yml @@ -0,0 +1,35 @@ +name: Artifacts (Package) + +on: [push, pull_request, workflow_dispatch] + +jobs: + build-artifacts: + runs-on: ubuntu-20.04 + + steps: + - name: Checkout code + id: checkout-code + uses: actions/checkout@v2 + with: + submodules: recursive + fetch-depth: 0 + + - name: Setup problem matcher + uses: Joshua-Ashton/gcc-problem-matcher@v1 + + - name: Build release + id: build-release + uses: Joshua-Ashton/arch-mingw-github-action@v8 + with: + command: | + export VERSION_NAME="${GITHUB_REF##*/}-${GITHUB_SHA##*/}" + ./package-release.sh ${VERSION_NAME} build --no-package + echo "VERSION_NAME=${VERSION_NAME}" >> $GITHUB_ENV + + - name: Upload artifacts + id: upload-artifacts + uses: actions/upload-artifact@v2 + with: + name: dxvk-${{ env.VERSION_NAME }} + path: build/dxvk-${{ env.VERSION_NAME }} + if-no-files-found: error diff --git a/utils/dxvk-1.10.3/.github/workflows/test-build-windows.yml b/utils/dxvk-1.10.3/.github/workflows/test-build-windows.yml new file mode 100644 index 00000000000..67c3bfd6b33 --- /dev/null +++ b/utils/dxvk-1.10.3/.github/workflows/test-build-windows.yml @@ -0,0 +1,52 @@ +name: Test Builds on Windows + +on: [push, pull_request, workflow_dispatch] + +jobs: + build-set-windows: + runs-on: windows-2022 + + steps: + - name: Checkout code + id: checkout-code + uses: actions/checkout@v2 + with: + submodules: recursive + + - name: Setup glslangValidator + shell: pwsh + run: | + choco install vulkan-sdk -y + Write-Output "$([System.Environment]::GetEnvironmentVariable('VULKAN_SDK', 'Machine'))\Bin" ` + | Out-File -FilePath "${Env:GITHUB_PATH}" -Append + + - name: Setup Meson + shell: pwsh + run: pip install meson + + - name: Find Visual Studio + shell: pwsh + run: | + $installationPath = Get-VSSetupInstance ` + | Select-VSSetupInstance -Require Microsoft.VisualStudio.Workload.NativeDesktop -Latest ` + | Select-Object -ExpandProperty InstallationPath + Write-Output "VSDEVCMD=${installationPath}\Common7\Tools\VsDevCmd.bat" ` + | Out-File -FilePath "${Env:GITHUB_ENV}" -Append + + - name: Build MSVC x86 + shell: pwsh + run: | + & "${Env:COMSPEC}" /s /c "`"${Env:VSDEVCMD}`" -arch=x86 -host_arch=x64 -no_logo && set" ` + | % { , ($_ -Split '=', 2) } ` + | % { [System.Environment]::SetEnvironmentVariable($_[0], $_[1]) } + meson --buildtype release --backend vs2022 build-msvc-x86 + msbuild -m build-msvc-x86/dxvk.sln + + - name: Build MSVC x64 + shell: pwsh + run: | + & "${Env:COMSPEC}" /s /c "`"${Env:VSDEVCMD}`" -arch=x64 -host_arch=x64 -no_logo && set" ` + | % { , ($_ -Split '=', 2) } ` + | % { [System.Environment]::SetEnvironmentVariable($_[0], $_[1]) } + meson --buildtype release --backend vs2022 build-msvc-x64 + msbuild -m build-msvc-x64/dxvk.sln diff --git a/utils/dxvk-1.10.3/LICENSE b/utils/dxvk-1.10.3/LICENSE new file mode 100644 index 00000000000..a9d4337ea9b --- /dev/null +++ b/utils/dxvk-1.10.3/LICENSE @@ -0,0 +1,22 @@ + Copyright (c) 2017-2021 Philip Rebohle + Copyright (c) 2019-2021 Joshua Ashton + + zlib/libpng license + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +– The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + +– Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. + +– This notice may not be removed or altered from any source distribution. diff --git a/utils/dxvk-1.10.3/README.md b/utils/dxvk-1.10.3/README.md new file mode 100644 index 00000000000..8c02992a34a --- /dev/null +++ b/utils/dxvk-1.10.3/README.md @@ -0,0 +1,136 @@ +# DXVK + +A Vulkan-based translation layer for Direct3D 9/10/11 which allows running 3D applications on Linux using Wine. + +For the current status of the project, please refer to the [project wiki](https://github.com/doitsujin/dxvk/wiki). + +The most recent development builds can be found [here](https://github.com/doitsujin/dxvk/actions/workflows/artifacts.yml?query=branch%3Amaster). + +Release builds can be found [here](https://github.com/doitsujin/dxvk/releases). + +## How to use +In order to install a DXVK package obtained from the [release](https://github.com/doitsujin/dxvk/releases) page into a given wine prefix, run the following commands from within the DXVK directory: + +``` +export WINEPREFIX=/path/to/.wine-prefix +./setup_dxvk.sh install +``` + +This will **copy** the DLLs into the `system32` and `syswow64` directories of your wine prefix and set up the required DLL overrides. Pure 32-bit prefixes are also supported. + +The setup script optionally takes the following arguments: +- `--symlink`: Create symbolic links to the DLL files instead of copying them. This is especially useful for development. +- `--with-d3d10`: Install the `d3d10{_1}.dll` helper libraries. +- `--without-dxgi`: Do not install DXVK's DXGI implementation and use the one provided by wine instead. + +Verify that your application uses DXVK instead of wined3d by checking for the presence of the log file `d3d9.log` or `d3d11.log` in the application's directory, or by enabling the HUD (see notes below). + +In order to remove DXVK from a prefix, run the following command: +``` +export WINEPREFIX=/path/to/.wine-prefix +./setup_dxvk.sh uninstall +``` + +## Build instructions + +### Requirements: +- [wine 3.10](https://www.winehq.org/) or newer +- [Meson](https://mesonbuild.com/) build system (at least version 0.49) +- [Mingw-w64](https://www.mingw-w64.org) compiler and headers (at least version 8.0) +- [glslang](https://github.com/KhronosGroup/glslang) compiler + +### Building DLLs + +#### The simple way +Inside the DXVK directory, run: +``` +./package-release.sh master /your/target/directory --no-package +``` + +This will create a folder `dxvk-master` in `/your/target/directory`, which contains both 32-bit and 64-bit versions of DXVK, which can be set up in the same way as the release versions as noted above. + +In order to preserve the build directories for development, pass `--dev-build` to the script. This option implies `--no-package`. After making changes to the source code, you can then do the following to rebuild DXVK: +``` +# change to build.32 for 32-bit +cd /your/target/directory/build.64 +ninja install +``` + +#### Compiling manually +``` +# 64-bit build. For 32-bit builds, replace +# build-win64.txt with build-win32.txt +meson --cross-file build-win64.txt --buildtype release --prefix /your/dxvk/directory build.w64 +cd build.w64 +ninja install +``` + +The D3D9, D3D10, D3D11 and DXGI DLLs will be located in `/your/dxvk/directory/bin`. Setup has to be done manually in this case. + +### Notes on Vulkan drivers +Before reporting an issue, please check the [Wiki](https://github.com/doitsujin/dxvk/wiki/Driver-support) page on the current driver status and make sure you run a recent enough driver version for your hardware. + +### Online multi-player games +Manipulation of Direct3D libraries in multi-player games may be considered cheating and can get your account **banned**. This may also apply to single-player games with an embedded or dedicated multiplayer portion. **Use at your own risk.** + +### HUD +The `DXVK_HUD` environment variable controls a HUD which can display the framerate and some stat counters. It accepts a comma-separated list of the following options: +- `devinfo`: Displays the name of the GPU and the driver version. +- `fps`: Shows the current frame rate. +- `frametimes`: Shows a frame time graph. +- `submissions`: Shows the number of command buffers submitted per frame. +- `drawcalls`: Shows the number of draw calls and render passes per frame. +- `pipelines`: Shows the total number of graphics and compute pipelines. +- `memory`: Shows the amount of device memory allocated and used. +- `gpuload`: Shows estimated GPU load. May be inaccurate. +- `version`: Shows DXVK version. +- `api`: Shows the D3D feature level used by the application. +- `cs`: Shows worker thread statistics. +- `compiler`: Shows shader compiler activity +- `samplers`: Shows the current number of sampler pairs used *[D3D9 Only]* +- `scale=x`: Scales the HUD by a factor of `x` (e.g. `1.5`) + +Additionally, `DXVK_HUD=1` has the same effect as `DXVK_HUD=devinfo,fps`, and `DXVK_HUD=full` enables all available HUD elements. + +### Frame rate limit +The `DXVK_FRAME_RATE` environment variable can be used to limit the frame rate. A value of `0` uncaps the frame rate, while any positive value will limit rendering to the given number of frames per second. Alternatively, the configuration file can be used. + +### Device filter +Some applications do not provide a method to select a different GPU. In that case, DXVK can be forced to use a given device: +- `DXVK_FILTER_DEVICE_NAME="Device Name"` Selects devices with a matching Vulkan device name, which can be retrieved with tools such as `vulkaninfo`. Matches on substrings, so "VEGA" or "AMD RADV VEGA10" is supported if the full device name is "AMD RADV VEGA10 (LLVM 9.0.0)", for example. If the substring matches more than one device, the first device matched will be used. + +**Note:** If the device filter is configured incorrectly, it may filter out all devices and applications will be unable to create a D3D device. + +### State cache +DXVK caches pipeline state by default, so that shaders can be recompiled ahead of time on subsequent runs of an application, even if the driver's own shader cache got invalidated in the meantime. This cache is enabled by default, and generally reduces stuttering. + +The following environment variables can be used to control the cache: +- `DXVK_STATE_CACHE=0` Disables the state cache. +- `DXVK_STATE_CACHE_PATH=/some/directory` Specifies a directory where to put the cache files. Defaults to the current working directory of the application. + +### Debugging +The following environment variables can be used for **debugging** purposes. +- `VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation` Enables Vulkan debug layers. Highly recommended for troubleshooting rendering issues and driver crashes. Requires the Vulkan SDK to be installed on the host system. +- `DXVK_LOG_LEVEL=none|error|warn|info|debug` Controls message logging. +- `DXVK_LOG_PATH=/some/directory` Changes path where log files are stored. Set to `none` to disable log file creation entirely, without disabling logging. +- `DXVK_CONFIG_FILE=/xxx/dxvk.conf` Sets path to the configuration file. +- `DXVK_PERF_EVENTS=1` Enables use of the VK_EXT_debug_utils extension for translating performance event markers. + +## Troubleshooting +DXVK requires threading support from your mingw-w64 build environment. If you +are missing this, you may see "error: ‘std::cv_status’ has not been declared" +or similar threading related errors. + +On Debian and Ubuntu, this can be resolved by using the posix alternate, which +supports threading. For example, choose the posix alternate from these +commands: +``` +update-alternatives --config x86_64-w64-mingw32-gcc +update-alternatives --config x86_64-w64-mingw32-g++ +update-alternatives --config i686-w64-mingw32-gcc +update-alternatives --config i686-w64-mingw32-g++ +``` +For non debian based distros, make sure that your mingw-w64-gcc cross compiler +does have `--enable-threads=posix` enabled during configure. If your distro does +ship its mingw-w64-gcc binary with `--enable-threads=win32` you might have to +recompile locally or open a bug at your distro's bugtracker to ask for it. diff --git a/utils/dxvk-1.10.3/RELEASE b/utils/dxvk-1.10.3/RELEASE new file mode 100644 index 00000000000..587c5f0c730 --- /dev/null +++ b/utils/dxvk-1.10.3/RELEASE @@ -0,0 +1 @@ +1.10.3 diff --git a/utils/dxvk-1.10.3/build-mta.bat b/utils/dxvk-1.10.3/build-mta.bat new file mode 100644 index 00000000000..23222aa8779 --- /dev/null +++ b/utils/dxvk-1.10.3/build-mta.bat @@ -0,0 +1,146 @@ +@echo off + +setlocal EnableExtensions EnableDelayedExpansion + +set "TARGET=%~f1" +if "%TARGET%"=="" set "TARGET=%~dp0..\..\Bin\mta\dxvk" + +if exist "%~dp0d3d9.dll" if exist "%~dp0dxgi.dll" ( + echo [DXVK] Using ready-made d3d9.dll + dxgi.dll from %~dp0 + call :publish "%~dp0d3d9.dll" "%~dp0dxgi.dll" + if errorlevel 1 exit /b 1 + exit /b 0 +) + +where meson >nul 2>nul && where ninja >nul 2>nul && where i686-w64-mingw32-gcc >nul 2>nul && where glslangValidator >nul 2>nul && goto :detect_done + +set "TOOL_PATH=" +call :detect_tools +if defined TOOL_PATH set "PATH=!TOOL_PATH:~1!;!PATH!" + +where meson >nul 2>nul && where ninja >nul 2>nul && where i686-w64-mingw32-gcc >nul 2>nul && where glslangValidator >nul 2>nul && goto :detect_done +set "TOOL_PATH=" +call :deep_scan +if defined TOOL_PATH set "PATH=!TOOL_PATH:~1!;!PATH!" + +:detect_done +where meson >nul 2>nul || goto :missing +where ninja >nul 2>nul || goto :missing +where i686-w64-mingw32-gcc >nul 2>nul || goto :missing +where i686-w64-mingw32-g++ >nul 2>nul || goto :missing +where i686-w64-mingw32-windres >nul 2>nul || goto :missing +where glslangValidator >nul 2>nul || goto :missing + +echo [DXVK] Building d3d9.dll + dxgi.dll from source ^(utils\dxvk-1.10.3^)... + +set "SRC=%~dp0" +if "%SRC:~-1%"=="\" set "SRC=%SRC:~0,-1%" +set "BUILD=%SRC%\build.m32" +set "CROSS=%SRC%\build-win32.txt" + +if not exist "%BUILD%\build.ninja" ( + meson setup "%BUILD%" "%SRC%" --cross-file "%CROSS%" --buildtype release ^ + -Denable_d3d9=true -Denable_dxgi=true -Denable_d3d11=true -Denable_d3d10=false -Denable_tests=false ^ + -Dcpp_args="-include cstdint" + if errorlevel 1 goto :failed +) + +ninja -C "%BUILD%" src/d3d9/d3d9.dll src/dxgi/dxgi.dll +if errorlevel 1 ninja -C "%BUILD%" +if errorlevel 1 goto :failed + +i686-w64-mingw32-strip --strip-unneeded "%BUILD%\src\d3d9\d3d9.dll" +i686-w64-mingw32-strip --strip-unneeded "%BUILD%\src\dxgi\dxgi.dll" + +call :publish "%BUILD%\src\d3d9\d3d9.dll" "%BUILD%\src\dxgi\dxgi.dll" +if errorlevel 1 goto :failed +exit /b 0 + +:missing +echo [DXVK] Skipped - DXVK build tools not found ^(Meson, Ninja, MinGW-w64, glslang^). +echo [DXVK] Install them to build utils\dxvk-1.10.3 from source ^(see build-mta.bat header^). +exit /b 0 + +:failed +echo [DXVK] ERROR: DXVK build failed - see output above. +exit /b 1 + +:publish +if not exist "%TARGET%" mkdir "%TARGET%" +copy /Y "%~1" "%TARGET%\" >nul +if errorlevel 1 exit /b 1 +copy /Y "%~2" "%TARGET%\" >nul +if errorlevel 1 exit /b 1 + +echo [DXVK] d3d9.dll + dxgi.dll installed into %TARGET% +exit /b 0 + +:detect_tools +call :add_python_scripts "%APPDATA%\Python" +call :add_python_scripts "%LOCALAPPDATA%\Programs\Python" +call :add_python_scripts "%ProgramFiles%\Python" +call :add_python_scripts "%ProgramFiles(x86)%\Python" +if defined PYTHONHOME call :add_tool_dir "%PYTHONHOME%\Scripts" +if defined PYTHON_HOME call :add_tool_dir "%PYTHON_HOME%\Scripts" + +call :add_tool_dir "%USERPROFILE%\scoop\shims" +call :add_tool_dir "%LOCALAPPDATA%\Microsoft\WinGet\Links" +call :add_tool_dir "%ProgramData%\chocolatey\bin" + +call :add_tool_dir "C:\MinGW\bin" +call :add_tool_dir "C:\mingw\bin" +call :add_tool_dir "C:\mingw32\bin" + +call :add_tool_dir "C:\msys64\mingw32\bin" +call :add_tool_dir "C:\msys64\usr\bin" +call :add_tool_dir "C:\msys32\mingw32\bin" +call :add_tool_dir "%ProgramFiles%\msys64\mingw32\bin" +call :add_tool_dir "%ProgramFiles%\msys64\usr\bin" + +if defined VULKAN_SDK call :add_tool_dir "%VULKAN_SDK%\Bin" +if defined VULKAN_SDK call :add_tool_dir "%VULKAN_SDK%\bin" +call :add_sdk_versions "%ProgramFiles%\VulkanSDK" +call :add_sdk_versions "%ProgramFiles(x86)%\VulkanSDK" +call :add_sdk_versions "%LOCALAPPDATA%\VulkanSDK" +exit /b 0 + +:deep_scan +call :add_recursive "%USERPROFILE%\w64devkit" +call :add_recursive "C:\w64devkit" +call :add_recursive "C:\mingw-w64" +call :add_recursive "%USERPROFILE%\.local" +call :add_recursive "%USERPROFILE%\scoop\apps" +exit /b 0 + +:add_tool_dir +if not exist "%~1" exit /b 0 +if exist "%~1\meson.exe" goto :add_tool_dir_yes +if exist "%~1\ninja.exe" goto :add_tool_dir_yes +if exist "%~1\i686-w64-mingw32-gcc.exe" goto :add_tool_dir_yes +if exist "%~1\glslangValidator.exe" goto :add_tool_dir_yes +exit /b 0 +:add_tool_dir_yes +set "TOOL_PATH=!TOOL_PATH!;%~1" +exit /b 0 + +:add_python_scripts +if not exist "%~1" exit /b 0 +for /d %%V in ("%~1\Python*") do ( + if exist "%%V\Scripts\meson.exe" set "TOOL_PATH=!TOOL_PATH!;%%V\Scripts" + if exist "%%V\Scripts\ninja.exe" set "TOOL_PATH=!TOOL_PATH!;%%V\Scripts" +) +exit /b 0 + +:add_sdk_versions +if not exist "%~1" exit /b 0 +for /d %%V in ("%~1\*") do ( + if exist "%%V\Bin\glslangValidator.exe" set "TOOL_PATH=!TOOL_PATH!;%%V\Bin" +) +exit /b 0 + +:add_recursive +if not exist "%~1" exit /b 0 +for /r "%~1" %%F in (meson.exe ninja.exe i686-w64-mingw32-gcc.exe glslangValidator.exe) do ( + if exist "%%F" set "TOOL_PATH=!TOOL_PATH!;%%~dpF" +) +exit /b 0 \ No newline at end of file diff --git a/utils/dxvk-1.10.3/build-win32.txt b/utils/dxvk-1.10.3/build-win32.txt new file mode 100644 index 00000000000..40e9d47d701 --- /dev/null +++ b/utils/dxvk-1.10.3/build-win32.txt @@ -0,0 +1,15 @@ +[binaries] +c = 'i686-w64-mingw32-gcc' +cpp = 'i686-w64-mingw32-g++' +ar = 'i686-w64-mingw32-ar' +strip = 'i686-w64-mingw32-strip' +windres = 'i686-w64-mingw32-windres' + +[properties] +needs_exe_wrapper = true + +[host_machine] +system = 'windows' +cpu_family = 'x86' +cpu = 'x86' +endian = 'little' diff --git a/utils/dxvk-1.10.3/build-win64.txt b/utils/dxvk-1.10.3/build-win64.txt new file mode 100644 index 00000000000..8eb1b29d12d --- /dev/null +++ b/utils/dxvk-1.10.3/build-win64.txt @@ -0,0 +1,15 @@ +[binaries] +c = 'x86_64-w64-mingw32-gcc' +cpp = 'x86_64-w64-mingw32-g++' +ar = 'x86_64-w64-mingw32-ar' +strip = 'x86_64-w64-mingw32-strip' +windres = 'x86_64-w64-mingw32-windres' + +[properties] +needs_exe_wrapper = true + +[host_machine] +system = 'windows' +cpu_family = 'x86_64' +cpu = 'x86_64' +endian = 'little' diff --git a/utils/dxvk-1.10.3/d3d9.dll b/utils/dxvk-1.10.3/d3d9.dll new file mode 100644 index 00000000000..f079b382673 Binary files /dev/null and b/utils/dxvk-1.10.3/d3d9.dll differ diff --git a/utils/dxvk-1.10.3/dxgi.dll b/utils/dxvk-1.10.3/dxgi.dll new file mode 100644 index 00000000000..157da4bd23c Binary files /dev/null and b/utils/dxvk-1.10.3/dxgi.dll differ diff --git a/utils/dxvk-1.10.3/dxvk.conf b/utils/dxvk-1.10.3/dxvk.conf new file mode 100644 index 00000000000..ebab355717e --- /dev/null +++ b/utils/dxvk-1.10.3/dxvk.conf @@ -0,0 +1,569 @@ +# Create the VkSurface on the first call to IDXGISwapChain::Present, +# rather than when creating the swap chain. Some games that start +# rendering with a different graphics API may require this option, +# or otherwise the window may stay black. +# +# Supported values: True, False + +# dxgi.deferSurfaceCreation = False +# d3d9.deferSurfaceCreation = False + + +# Enforce a stricter maximum frame latency. Overrides the application +# setting specified by calling IDXGIDevice::SetMaximumFrameLatency. +# Setting this to 0 will have no effect. +# +# Supported values : 0 - 16 + +# dxgi.maxFrameLatency = 0 +# d3d9.maxFrameLatency = 0 + + +# Enables a frame rate limiter, unless the game is already +# limited to the same refresh rate by vertical synchronization. +# +# Supported values : Any non-negative integer + +# dxgi.maxFrameRate = 0 +# d3d9.maxFrameRate = 0 + + +# Override PCI vendor and device IDs reported to the application. Can +# cause the app to adjust behaviour depending on the selected values. +# +# Supported values: Any four-digit hex number. + +# dxgi.customDeviceId = 0000 +# dxgi.customVendorId = 0000 + +# d3d9.customDeviceId = 0000 +# d3d9.customVendorId = 0000 + + +# Override the reported device description +# +# Supported values: Any string. + +# dxgi.customDeviceDesc = "" +# d3d9.customDeviceDesc = "" + + +# Report Nvidia GPUs as AMD GPUs by default. This is enabled by default +# to work around issues with NVAPI, but may cause issues in some games. +# +# Supported values: True, False + +# dxgi.nvapiHack = True + + + +# Override maximum amount of device memory and shared system memory +# reported to the application. This may fix texture streaming issues +# in games that do not support cards with large amounts of VRAM. +# +# Supported values: Any number in Megabytes. + +# dxgi.maxDeviceMemory = 0 +# dxgi.maxSharedMemory = 0 + + +# Some games think we are on Intel given a lack of NVAPI or +# AGS/atiadlxx support. Report our device memory as shared memory, +# and some small amount for a "carveout". + +# Supported values: True, False + +# dxgi.emulateUMA = False + + +# Override back buffer count for the Vulkan swap chain. +# Setting this to 0 or less will have no effect. +# +# Supported values: Any number greater than or equal to 2. + +# dxgi.numBackBuffers = 0 +# d3d9.numBackBuffers = 0 + + +# Overrides synchronization interval (Vsync) for presentation. +# Setting this to 0 disables vertical synchronization entirely. +# A positive value 'n' will enable Vsync and repeat the same +# image n times, and a negative value will have no effect. +# +# Supported values: Any non-negative number + +# dxgi.syncInterval = -1 +# d3d9.presentInterval = -1 + + +# True enables the mailbox present mode in case regular Vsync is disabled. +# This should avoid tearing, but may be unsupported on some systems +# or require setting dxgi.numBackBuffers to a higher value in order +# to work properly. +# +# False enables the relaxed fifo present mode in case regular Vsync is enabled. +# This should result in tearing but reduce stutter if FPS are too low, +# but may be unsupported on some systems. +# +# Please do not report issues with this option. +# +# Supported values: Auto, True, False + +# dxgi.tearFree = Auto +# d3d9.tearFree = Auto + + +# Performs range check on dynamically indexed constant buffers in shaders. +# This may be needed to work around a certain type of game bug, but may +# also introduce incorrect behaviour. +# +# Supported values: True, False + +# d3d11.constantBufferRangeCheck = False + + +# Assume single-use mode for command lists created on deferred contexts. +# This may need to be disabled for some applications to avoid rendering +# issues, which may come at a significant performance cost. +# +# Supported values: True, False + +# d3d11.dcSingleUseMode = True + + +# Override the maximum feature level that a D3D11 device can be created +# with. Setting this to a higher value may allow some applications to run +# that would otherwise fail to create a D3D11 device. +# +# Supported values: 9_1, 9_2, 9_3, 10_0, 10_1, 11_0, 11_1 + +# d3d11.maxFeatureLevel = 11_1 + + +# Overrides the maximum allowed tessellation factor. This can be used to +# improve performance in titles which overuse tessellation. +# +# Supported values: Any number between 8 and 64 + +# d3d11.maxTessFactor = 0 + + +# Enables relaxed pipeline barriers around UAV writes. +# +# This may improve performance in some games, but may also introduce +# rendering issues. Please don't report bugs with the option enabled. +# +# Supported values: True, False + +# d3d11.relaxedBarriers = False + + +# Ignores barriers around UAV writes from fragment shaders. +# +# This may improve performance in some games, but may also introduce +# rendering issues. Please don't report bugs with the option enabled. +# +# Supported values: True, False + +# d3d11.ignoreGraphicsBarriers = False + + +# Overrides anisotropic filtering for all samplers. Set this to a positive +# value to enable AF for all samplers in the game, or to 0 in order to +# disable AF entirely. Negative values will have no effect. +# +# Supported values: Any number between 0 and 16 + +# d3d11.samplerAnisotropy = -1 +# d3d9.samplerAnisotropy = -1 + + +# Declares vertex positions as invariant in order to solve +# potential Z-fighting issues at a small performance cost. +# +# Supported values: True, False + +# d3d11.invariantPosition = True +# d3d9.invariantPosition = True + + +# Forces the sample count of all textures to 1, and performs +# the needed fixups in resolve operations and shaders. +# +# Supported values: True, False + +# d3d11.disableMsaa = False + + +# Clears workgroup memory in compute shaders to zero. Some games don't do +# this and rely on undefined behaviour. Enabling may reduce performance. +# +# Supported values: True, False + +# d3d11.zeroWorkgroupMemory = False + + +# Resource size limit for implicit discards, in kilobytes. For small staging +# resources mapped with MAP_WRITE, DXVK will sometimes allocate new backing +# storage in order to avoid GPU synchronization, so setting this too high +# may cause memory issues, setting it to -1 disables the feature. + +# d3d11.maxImplicitDiscardSize = 256 + + +# Resource size limit for buffer-mapped dynamic images, in kilobytes. +# A higher threshold may reduce memory usage and PCI-E bandwidth in +# some games, but may also increase GPU synchronizations. Setting it +# to -1 disables the feature. + +# d3d11.maxDynamicImageBufferSize = -1 + + +# Allocates dynamic resources with the given set of bind flags in +# cached system memory rather than uncached memory or host-visible +# VRAM, in order to allow fast readback from the CPU. This is only +# useful for buggy applications, and may reduce GPU-bound performance. +# +# Supported values: Any combination of the following: +# - v: Vertex buffers +# - i: Index buffers +# - c: Constant buffers +# - r: Shader resources +# - a: All dynamic resources + +# d3d11.cachedDynamicResources = "" + + +# Sets number of pipeline compiler threads. +# +# Supported values: +# - 0 to automatically determine the number of threads to use +# - any positive number to enforce the thread count + +# dxvk.numCompilerThreads = 0 + + +# Toggles raw SSBO usage. +# +# Uses storage buffers to implement raw and structured buffer +# views. Enabled by default on hardware which has a storage +# buffer offset alignment requirement of 4 Bytes (e.g. AMD). +# Enabling this may improve performance, but is not safe on +# hardware with higher alignment requirements. +# +# Supported values: +# - Auto: Don't change the default +# - True, False: Always enable / disable + +# dxvk.useRawSsbo = Auto + + +# Controls Nvidia HVV behaviour. +# +# Disables the host-visible, device-local heap on Nvidia drivers. This +# is used to avoid NVIDIA driver bug 3114283 on affected drivers, as +# well as in specific games on newer drivers.being enabled on all +# affected drivers. +# +# Supported values: +# - Auto: Don't change the default +# - True, False: Always enable / disable + +# dxvk.shrinkNvidiaHvvHeap = Auto + + +# Sets enabled HUD elements +# +# Behaves like the DXVK_HUD environment variable if the +# environment variable is not set, otherwise it will be +# ignored. The syntax is identical. + +# dxvk.hud = + + +# Reported shader model +# +# The shader model to state that we support in the device +# capabilities that the applicatation queries. +# +# Supported values: +# - 1: Shader Model 1 +# - 2: Shader Model 2 +# - 3: Shader Model 3 + +# d3d9.shaderModel = 3 + + +# Evict Managed on Unlock +# +# Decides whether we should evict managed resources from +# system memory when they are unlocked entirely. +# +# Supported values: +# - True, False: Always enable / disable + +# d3d9.evictManagedOnUnlock = False + + +# DPI Awareness +# +# Decides whether we should call SetProcessDPIAware on device +# creation. Helps avoid upscaling blur in modern Windows on +# Hi-DPI screens/devices. +# +# Supported values: +# - True, False: Always enable / disable + +# d3d9.dpiAware = True + + +# Strict Constant Copies +# +# Decides whether we should always copy defined constants to +# the UBO when relative addressing is used, or only when the +# relative addressing starts a defined constant. +# +# Supported values: +# - True, False: Always enable / disable + +# d3d9.strictConstantCopies = False + + +# Strict Pow +# +# Decides whether we have an opSelect for handling pow(0,0) = 0 +# otherwise it becomes undefined. +# +# Supported values: +# - True, False: Always enable / disable + +# d3d9.strictPow = True + + +# Lenient Clear +# +# Decides whether or not we fastpath clear anyway if we are close enough to +# clearing a full render target. +# +# Supported values: +# - True, False: Always enable / disable + +# d3d9.lenientClear = False + + +# Max available memory +# +# Changes the max initial value used in tracking and GetAvailableTextureMem +# Value in Megabytes +# +# Supported values: +# - Max Available Memory: Any int32_t +# - Memory Tracking Testing: True, False + +# d3d9.maxAvailableMemory = 4096 +# d3d9.memoryTrackTest = False + + +# Force enable/disable floating point quirk emulation +# +# Force toggle anything * 0 emulation +# Setting it to True will use a faster but less accurate approach that works for most games. +# Supported values: +# - True: Use a faster but less accurate approach. Good enough for most games +# - False: Disable float emulation completely +# - Strict: Use a slower but more correct approach. Necessary for some games +# - Auto: DXVK will pick automatically + +# d3d9.floatEmulation = Auto + + +# Enable dialog box mode +# +# Changes the default state of dialog box mode. +# *Disables* exclusive fullscreen when enabled. +# +# Supported values: +# - True, False: Always enable / disable + +# d3d9.enableDialogMode = False + +# Overrides the application's MSAA level on the swapchain +# +# Supported values: -1 (application) and 0 to 16 (user override) + +# d3d9.forceSwapchainMSAA = -1 + + +# Long Mad +# +# Should we make our Mads a FFma or do it the long way with an FMul and an FAdd? +# This solves some rendering bugs in games that have z-pass shaders which +# don't match entirely to the regular vertex shader in this way. +# +# Supported values: +# - True/False + +# d3d9.longMad = False + +# Alpha Test Wiggle Room +# +# Workaround for games using alpha test == 1.0, etc due to wonky interpolation or +# misc. imprecision on some vendors +# +# Supported values: +# - True/False + +# d3d9.alphaTestWiggleRoom = False + +# Device Local Constant Buffers +# +# Enables using device local, host accessible memory for constant buffers in D3D9. +# This tends to actually be slower for some reason on AMD, +# and the exact same performance on NVIDIA. +# +# Supported values: +# - True/False + +# d3d9.deviceLocalConstantBuffers = False + +# No Explicit Front Buffer +# +# Disables the front buffer +# +# Supported values: +# - True/False + +# d3d9.noExplicitFrontBuffer = False + +# Support DF formats +# +# Support the vendor extension DF floating point depth formats +# +# Supported values: +# - True/False + +# d3d9.supportDFFormats = True + +# Support X4R4G4B4 +# +# Support the X4R4G4B4 format. +# The Sims 2 is a horrible game made by complete morons. +# +# Supported values: +# - True/False + +# d3d9.supportX4R4G4B4 = True + +# Support D32 +# +# Support the D32 format. +# +# Supported values: +# - True/False + +# d3d9.supportD32 = True + +# Disable A8 as a Render Target +# +# Disable support for A8 format render targets +# Once again, The Sims 2 is a horrible game made by complete morons. +# +# Supported values: +# - True/False + +# d3d9.disableA8RT = False + +# Support for VCache Query +# +# Support for the vcache query +# Not very important as a user config. +# Used internally. +# +# Supported values: +# - True/False + +# Defaults to True if vendorId == 0x10de +# d3d9.supportVCache = True + +# Force Sampler Type Spec Constants +# +# Useful if games use the wrong image and sampler +# type combo like Halo: CE or Spellforce. +# Can fix rendering in older, broken games in some instances. +# +# Supported values: +# - True/False + +# d3d9.forceSamplerTypeSpecConstants = False + +# Force Aspect Ratio +# +# Only exposes modes with a given aspect ratio. +# Useful for titles that break if they see ultra-wide. +# +# Supported values: +# - Any ratio, ie. "16:9", "4:3" + +# d3d9.forceAspectRatio = "" + +# Allow Do Not Wait +# +# Allow the do not wait lock flag to be used +# Useful if some apps use this incorrectly. +# +# Supported values: +# - True/False + +# d3d9.allowDoNotWait = True + +# Allow Discard +# +# Allow the discard lock flag to be used +# Useful if some apps use this incorrectly. +# +# Supported values: +# - True/False + +# d3d9.allowDiscard = True + +# Enumerate by Displays +# +# Whether we should enumerate D3D9 adapters by display (windows behaviour) +# or by physical adapter. +# May be useful in PRIME setups. +# +# Supported values: +# - True/False + +# d3d9.enumerateByDisplays = True + +# APITrace Mode +# +# Makes all host visible buffers cached and coherent +# Improves performance when apitracing, but also can impact +# some dumb games. +# +# Supported values: +# - True/False + +# d3d9.apitraceMode = False + +# Seamless Cubes +# +# Don't use non seamless cube maps even if they are supported. +# Non seamless cubes are correct d3d9 behavior, but can produce worse looking edges. +# +# Supported values: +# - True/False + +# d3d9.seamlessCubes = False + +# Debug Utils +# +# Enables debug utils as this is off by default, this enables user annotations like BeginEvent()/EndEvent(). +# Alternatively could be enabled with DXVK_PERF_EVENTS=1 environment variable. +# +# Supported values: +# - True/False + +# dxvk.enableDebugUtils = False diff --git a/utils/dxvk-1.10.3/include/openvr/LICENSE b/utils/dxvk-1.10.3/include/openvr/LICENSE new file mode 100644 index 00000000000..acf1c011fc6 --- /dev/null +++ b/utils/dxvk-1.10.3/include/openvr/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2015, Valve Corporation +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/utils/dxvk-1.10.3/include/openvr/openvr.hpp b/utils/dxvk-1.10.3/include/openvr/openvr.hpp new file mode 100644 index 00000000000..34a390882c7 --- /dev/null +++ b/utils/dxvk-1.10.3/include/openvr/openvr.hpp @@ -0,0 +1,4323 @@ +#pragma once + +// openvr.h +//========= Copyright Valve Corporation ============// +// Dynamically generated file. Do not modify this file directly. + +#ifndef _OPENVR_API +#define _OPENVR_API + +#include + + + +// vrtypes.h +#ifndef _INCLUDE_VRTYPES_H +#define _INCLUDE_VRTYPES_H + +// Forward declarations to avoid requiring vulkan.h +struct VkDevice_T; +struct VkPhysicalDevice_T; +struct VkInstance_T; +struct VkQueue_T; + +// Forward declarations to avoid requiring d3d12.h +struct ID3D12Resource; +struct ID3D12CommandQueue; + +namespace vr +{ +#pragma pack( push, 8 ) + +typedef void* glSharedTextureHandle_t; +typedef int32_t glInt_t; +typedef uint32_t glUInt_t; + +// right-handed system +// +y is up +// +x is to the right +// -z is forward +// Distance unit is meters +struct HmdMatrix34_t +{ + float m[3][4]; +}; + +struct HmdMatrix44_t +{ + float m[4][4]; +}; + +struct HmdVector3_t +{ + float v[3]; +}; + +struct HmdVector4_t +{ + float v[4]; +}; + +struct HmdVector3d_t +{ + double v[3]; +}; + +struct HmdVector2_t +{ + float v[2]; +}; + +struct HmdQuaternion_t +{ + double w, x, y, z; +}; + +struct HmdQuaternionf_t +{ + float w, x, y, z; +}; + +struct HmdColor_t +{ + float r, g, b, a; +}; + +struct HmdQuad_t +{ + HmdVector3_t vCorners[ 4 ]; +}; + +struct HmdRect2_t +{ + HmdVector2_t vTopLeft; + HmdVector2_t vBottomRight; +}; + +/** Used to return the post-distortion UVs for each color channel. +* UVs range from 0 to 1 with 0,0 in the upper left corner of the +* source render target. The 0,0 to 1,1 range covers a single eye. */ +struct DistortionCoordinates_t +{ + float rfRed[2]; + float rfGreen[2]; + float rfBlue[2]; +}; + +enum EVREye +{ + Eye_Left = 0, + Eye_Right = 1 +}; + +enum ETextureType +{ + TextureType_DirectX = 0, // Handle is an ID3D11Texture + TextureType_OpenGL = 1, // Handle is an OpenGL texture name or an OpenGL render buffer name, depending on submit flags + TextureType_Vulkan = 2, // Handle is a pointer to a VRVulkanTextureData_t structure + TextureType_IOSurface = 3, // Handle is a macOS cross-process-sharable IOSurfaceRef + TextureType_DirectX12 = 4, // Handle is a pointer to a D3D12TextureData_t structure + TextureType_DXGISharedHandle = 5, // Handle is a HANDLE DXGI share handle, only supported for Overlay render targets. + // this texture is used directly by our renderer, so only perform atomic (copyresource or resolve) on it +}; + +enum EColorSpace +{ + ColorSpace_Auto = 0, // Assumes 'gamma' for 8-bit per component formats, otherwise 'linear'. This mirrors the DXGI formats which have _SRGB variants. + ColorSpace_Gamma = 1, // Texture data can be displayed directly on the display without any conversion (a.k.a. display native format). + ColorSpace_Linear = 2, // Same as gamma but has been converted to a linear representation using DXGI's sRGB conversion algorithm. +}; + +struct Texture_t +{ + void* handle; // See ETextureType definition above + ETextureType eType; + EColorSpace eColorSpace; +}; + +// Handle to a shared texture (HANDLE on Windows obtained using OpenSharedResource). +typedef uint64_t SharedTextureHandle_t; +#define INVALID_SHARED_TEXTURE_HANDLE ((vr::SharedTextureHandle_t)0) + +enum ETrackingResult +{ + TrackingResult_Uninitialized = 1, + + TrackingResult_Calibrating_InProgress = 100, + TrackingResult_Calibrating_OutOfRange = 101, + + TrackingResult_Running_OK = 200, + TrackingResult_Running_OutOfRange = 201, +}; + +typedef uint32_t DriverId_t; +static const uint32_t k_nDriverNone = 0xFFFFFFFF; + +static const uint32_t k_unMaxDriverDebugResponseSize = 32768; + +/** Used to pass device IDs to API calls */ +typedef uint32_t TrackedDeviceIndex_t; +static const uint32_t k_unTrackedDeviceIndex_Hmd = 0; +static const uint32_t k_unMaxTrackedDeviceCount = 64; +static const uint32_t k_unTrackedDeviceIndexOther = 0xFFFFFFFE; +static const uint32_t k_unTrackedDeviceIndexInvalid = 0xFFFFFFFF; + +/** Describes what kind of object is being tracked at a given ID */ +enum ETrackedDeviceClass +{ + TrackedDeviceClass_Invalid = 0, // the ID was not valid. + TrackedDeviceClass_HMD = 1, // Head-Mounted Displays + TrackedDeviceClass_Controller = 2, // Tracked controllers + TrackedDeviceClass_GenericTracker = 3, // Generic trackers, similar to controllers + TrackedDeviceClass_TrackingReference = 4, // Camera and base stations that serve as tracking reference points + TrackedDeviceClass_DisplayRedirect = 5, // Accessories that aren't necessarily tracked themselves, but may redirect video output from other tracked devices +}; + + +/** Describes what specific role associated with a tracked device */ +enum ETrackedControllerRole +{ + TrackedControllerRole_Invalid = 0, // Invalid value for controller type + TrackedControllerRole_LeftHand = 1, // Tracked device associated with the left hand + TrackedControllerRole_RightHand = 2, // Tracked device associated with the right hand + TrackedControllerRole_OptOut = 3, // Tracked device is opting out of left/right hand selection + TrackedControllerRole_Max = 4 +}; + + +/** describes a single pose for a tracked object */ +struct TrackedDevicePose_t +{ + HmdMatrix34_t mDeviceToAbsoluteTracking; + HmdVector3_t vVelocity; // velocity in tracker space in m/s + HmdVector3_t vAngularVelocity; // angular velocity in radians/s (?) + ETrackingResult eTrackingResult; + bool bPoseIsValid; + + // This indicates that there is a device connected for this spot in the pose array. + // It could go from true to false if the user unplugs the device. + bool bDeviceIsConnected; +}; + +/** Identifies which style of tracking origin the application wants to use +* for the poses it is requesting */ +enum ETrackingUniverseOrigin +{ + TrackingUniverseSeated = 0, // Poses are provided relative to the seated zero pose + TrackingUniverseStanding = 1, // Poses are provided relative to the safe bounds configured by the user + TrackingUniverseRawAndUncalibrated = 2, // Poses are provided in the coordinate system defined by the driver. It has Y up and is unified for devices of the same driver. You usually don't want this one. +}; + +typedef uint64_t WebConsoleHandle_t; +#define INVALID_WEB_CONSOLE_HANDLE ((vr::WebConsoleHandle_t)0) + +// Refers to a single container of properties +typedef uint64_t PropertyContainerHandle_t; +typedef uint32_t PropertyTypeTag_t; + +static const PropertyContainerHandle_t k_ulInvalidPropertyContainer = 0; +static const PropertyTypeTag_t k_unInvalidPropertyTag = 0; + +typedef PropertyContainerHandle_t DriverHandle_t; +static const PropertyContainerHandle_t k_ulInvalidDriverHandle = 0; + +// Use these tags to set/get common types as struct properties +static const PropertyTypeTag_t k_unFloatPropertyTag = 1; +static const PropertyTypeTag_t k_unInt32PropertyTag = 2; +static const PropertyTypeTag_t k_unUint64PropertyTag = 3; +static const PropertyTypeTag_t k_unBoolPropertyTag = 4; +static const PropertyTypeTag_t k_unStringPropertyTag = 5; + +static const PropertyTypeTag_t k_unHmdMatrix34PropertyTag = 20; +static const PropertyTypeTag_t k_unHmdMatrix44PropertyTag = 21; +static const PropertyTypeTag_t k_unHmdVector3PropertyTag = 22; +static const PropertyTypeTag_t k_unHmdVector4PropertyTag = 23; + +static const PropertyTypeTag_t k_unHiddenAreaPropertyTag = 30; +static const PropertyTypeTag_t k_unPathHandleInfoTag = 31; +static const PropertyTypeTag_t k_unActionPropertyTag = 32; +static const PropertyTypeTag_t k_unInputValuePropertyTag = 33; +static const PropertyTypeTag_t k_unWildcardPropertyTag = 34; +static const PropertyTypeTag_t k_unHapticVibrationPropertyTag = 35; +static const PropertyTypeTag_t k_unSkeletonPropertyTag = 36; + +static const PropertyTypeTag_t k_unOpenVRInternalReserved_Start = 1000; +static const PropertyTypeTag_t k_unOpenVRInternalReserved_End = 10000; + + +/** Each entry in this enum represents a property that can be retrieved about a +* tracked device. Many fields are only valid for one ETrackedDeviceClass. */ +enum ETrackedDeviceProperty +{ + Prop_Invalid = 0, + + // general properties that apply to all device classes + Prop_TrackingSystemName_String = 1000, + Prop_ModelNumber_String = 1001, + Prop_SerialNumber_String = 1002, + Prop_RenderModelName_String = 1003, + Prop_WillDriftInYaw_Bool = 1004, + Prop_ManufacturerName_String = 1005, + Prop_TrackingFirmwareVersion_String = 1006, + Prop_HardwareRevision_String = 1007, + Prop_AllWirelessDongleDescriptions_String = 1008, + Prop_ConnectedWirelessDongle_String = 1009, + Prop_DeviceIsWireless_Bool = 1010, + Prop_DeviceIsCharging_Bool = 1011, + Prop_DeviceBatteryPercentage_Float = 1012, // 0 is empty, 1 is full + Prop_StatusDisplayTransform_Matrix34 = 1013, + Prop_Firmware_UpdateAvailable_Bool = 1014, + Prop_Firmware_ManualUpdate_Bool = 1015, + Prop_Firmware_ManualUpdateURL_String = 1016, + Prop_HardwareRevision_Uint64 = 1017, + Prop_FirmwareVersion_Uint64 = 1018, + Prop_FPGAVersion_Uint64 = 1019, + Prop_VRCVersion_Uint64 = 1020, + Prop_RadioVersion_Uint64 = 1021, + Prop_DongleVersion_Uint64 = 1022, + Prop_BlockServerShutdown_Bool = 1023, + Prop_CanUnifyCoordinateSystemWithHmd_Bool = 1024, + Prop_ContainsProximitySensor_Bool = 1025, + Prop_DeviceProvidesBatteryStatus_Bool = 1026, + Prop_DeviceCanPowerOff_Bool = 1027, + Prop_Firmware_ProgrammingTarget_String = 1028, + Prop_DeviceClass_Int32 = 1029, + Prop_HasCamera_Bool = 1030, + Prop_DriverVersion_String = 1031, + Prop_Firmware_ForceUpdateRequired_Bool = 1032, + Prop_ViveSystemButtonFixRequired_Bool = 1033, + Prop_ParentDriver_Uint64 = 1034, + Prop_ResourceRoot_String = 1035, + Prop_RegisteredDeviceType_String = 1036, + Prop_InputProfilePath_String = 1037, // input profile to use for this device in the input system. Will default to tracking system name if this isn't provided + Prop_NeverTracked_Bool = 1038, // Used for devices that will never have a valid pose by design + Prop_NumCameras_Int32 = 1039, + Prop_CameraFrameLayout_Int32 = 1040, // EVRTrackedCameraFrameLayout value + + // Properties that are unique to TrackedDeviceClass_HMD + Prop_ReportsTimeSinceVSync_Bool = 2000, + Prop_SecondsFromVsyncToPhotons_Float = 2001, + Prop_DisplayFrequency_Float = 2002, + Prop_UserIpdMeters_Float = 2003, + Prop_CurrentUniverseId_Uint64 = 2004, + Prop_PreviousUniverseId_Uint64 = 2005, + Prop_DisplayFirmwareVersion_Uint64 = 2006, + Prop_IsOnDesktop_Bool = 2007, + Prop_DisplayMCType_Int32 = 2008, + Prop_DisplayMCOffset_Float = 2009, + Prop_DisplayMCScale_Float = 2010, + Prop_EdidVendorID_Int32 = 2011, + Prop_DisplayMCImageLeft_String = 2012, + Prop_DisplayMCImageRight_String = 2013, + Prop_DisplayGCBlackClamp_Float = 2014, + Prop_EdidProductID_Int32 = 2015, + Prop_CameraToHeadTransform_Matrix34 = 2016, + Prop_DisplayGCType_Int32 = 2017, + Prop_DisplayGCOffset_Float = 2018, + Prop_DisplayGCScale_Float = 2019, + Prop_DisplayGCPrescale_Float = 2020, + Prop_DisplayGCImage_String = 2021, + Prop_LensCenterLeftU_Float = 2022, + Prop_LensCenterLeftV_Float = 2023, + Prop_LensCenterRightU_Float = 2024, + Prop_LensCenterRightV_Float = 2025, + Prop_UserHeadToEyeDepthMeters_Float = 2026, + Prop_CameraFirmwareVersion_Uint64 = 2027, + Prop_CameraFirmwareDescription_String = 2028, + Prop_DisplayFPGAVersion_Uint64 = 2029, + Prop_DisplayBootloaderVersion_Uint64 = 2030, + Prop_DisplayHardwareVersion_Uint64 = 2031, + Prop_AudioFirmwareVersion_Uint64 = 2032, + Prop_CameraCompatibilityMode_Int32 = 2033, + Prop_ScreenshotHorizontalFieldOfViewDegrees_Float = 2034, + Prop_ScreenshotVerticalFieldOfViewDegrees_Float = 2035, + Prop_DisplaySuppressed_Bool = 2036, + Prop_DisplayAllowNightMode_Bool = 2037, + Prop_DisplayMCImageWidth_Int32 = 2038, + Prop_DisplayMCImageHeight_Int32 = 2039, + Prop_DisplayMCImageNumChannels_Int32 = 2040, + Prop_DisplayMCImageData_Binary = 2041, + Prop_SecondsFromPhotonsToVblank_Float = 2042, + Prop_DriverDirectModeSendsVsyncEvents_Bool = 2043, + Prop_DisplayDebugMode_Bool = 2044, + Prop_GraphicsAdapterLuid_Uint64 = 2045, + Prop_DriverProvidedChaperonePath_String = 2048, + Prop_ExpectedTrackingReferenceCount_Int32 = 2049, // expected number of sensors or basestations to reserve UI space for + Prop_ExpectedControllerCount_Int32 = 2050, // expected number of tracked controllers to reserve UI space for + Prop_NamedIconPathControllerLeftDeviceOff_String = 2051, // placeholder icon for "left" controller if not yet detected/loaded + Prop_NamedIconPathControllerRightDeviceOff_String = 2052, // placeholder icon for "right" controller if not yet detected/loaded + Prop_NamedIconPathTrackingReferenceDeviceOff_String = 2053, // placeholder icon for sensor/base if not yet detected/loaded + Prop_DoNotApplyPrediction_Bool = 2054, + Prop_CameraToHeadTransforms_Matrix34_Array = 2055, + Prop_DistortionMeshResolution_Int32 = 2056, // custom resolution of compositor calls to IVRSystem::ComputeDistortion + Prop_DriverIsDrawingControllers_Bool = 2057, + Prop_DriverRequestsApplicationPause_Bool = 2058, + Prop_DriverRequestsReducedRendering_Bool = 2059, + Prop_MinimumIpdStepMeters_Float = 2060, + Prop_AudioBridgeFirmwareVersion_Uint64 = 2061, + Prop_ImageBridgeFirmwareVersion_Uint64 = 2062, + Prop_ImuToHeadTransform_Matrix34 = 2063, + Prop_ImuFactoryGyroBias_Vector3 = 2064, + Prop_ImuFactoryGyroScale_Vector3 = 2065, + Prop_ImuFactoryAccelerometerBias_Vector3 = 2066, + Prop_ImuFactoryAccelerometerScale_Vector3 = 2067, + + // Properties that are unique to TrackedDeviceClass_Controller + Prop_AttachedDeviceId_String = 3000, + Prop_SupportedButtons_Uint64 = 3001, + Prop_Axis0Type_Int32 = 3002, // Return value is of type EVRControllerAxisType + Prop_Axis1Type_Int32 = 3003, // Return value is of type EVRControllerAxisType + Prop_Axis2Type_Int32 = 3004, // Return value is of type EVRControllerAxisType + Prop_Axis3Type_Int32 = 3005, // Return value is of type EVRControllerAxisType + Prop_Axis4Type_Int32 = 3006, // Return value is of type EVRControllerAxisType + Prop_ControllerRoleHint_Int32 = 3007, // Return value is of type ETrackedControllerRole + + // Properties that are unique to TrackedDeviceClass_TrackingReference + Prop_FieldOfViewLeftDegrees_Float = 4000, + Prop_FieldOfViewRightDegrees_Float = 4001, + Prop_FieldOfViewTopDegrees_Float = 4002, + Prop_FieldOfViewBottomDegrees_Float = 4003, + Prop_TrackingRangeMinimumMeters_Float = 4004, + Prop_TrackingRangeMaximumMeters_Float = 4005, + Prop_ModeLabel_String = 4006, + + // Properties that are used for user interface like icons names + Prop_IconPathName_String = 5000, // DEPRECATED. Value not referenced. Now expected to be part of icon path properties. + Prop_NamedIconPathDeviceOff_String = 5001, // {driver}/icons/icon_filename - PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others + Prop_NamedIconPathDeviceSearching_String = 5002, // {driver}/icons/icon_filename - PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others + Prop_NamedIconPathDeviceSearchingAlert_String = 5003, // {driver}/icons/icon_filename - PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others + Prop_NamedIconPathDeviceReady_String = 5004, // {driver}/icons/icon_filename - PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others + Prop_NamedIconPathDeviceReadyAlert_String = 5005, // {driver}/icons/icon_filename - PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others + Prop_NamedIconPathDeviceNotReady_String = 5006, // {driver}/icons/icon_filename - PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others + Prop_NamedIconPathDeviceStandby_String = 5007, // {driver}/icons/icon_filename - PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others + Prop_NamedIconPathDeviceAlertLow_String = 5008, // {driver}/icons/icon_filename - PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others + + // Properties that are used by helpers, but are opaque to applications + Prop_DisplayHiddenArea_Binary_Start = 5100, + Prop_DisplayHiddenArea_Binary_End = 5150, + Prop_ParentContainer = 5151, + + // Properties that are unique to drivers + Prop_UserConfigPath_String = 6000, + Prop_InstallPath_String = 6001, + Prop_HasDisplayComponent_Bool = 6002, + Prop_HasControllerComponent_Bool = 6003, + Prop_HasCameraComponent_Bool = 6004, + Prop_HasDriverDirectModeComponent_Bool = 6005, + Prop_HasVirtualDisplayComponent_Bool = 6006, + + // Properties that are set internally based on other information provided by drivers + Prop_ControllerType_String = 7000, + Prop_LegacyInputProfile_String = 7001, + + // Vendors are free to expose private debug data in this reserved region + Prop_VendorSpecific_Reserved_Start = 10000, + Prop_VendorSpecific_Reserved_End = 10999, + + Prop_TrackedDeviceProperty_Max = 1000000, +}; + +/** No string property will ever be longer than this length */ +static const uint32_t k_unMaxPropertyStringSize = 32 * 1024; + +/** Used to return errors that occur when reading properties. */ +enum ETrackedPropertyError +{ + TrackedProp_Success = 0, + TrackedProp_WrongDataType = 1, + TrackedProp_WrongDeviceClass = 2, + TrackedProp_BufferTooSmall = 3, + TrackedProp_UnknownProperty = 4, // Driver has not set the property (and may not ever). + TrackedProp_InvalidDevice = 5, + TrackedProp_CouldNotContactServer = 6, + TrackedProp_ValueNotProvidedByDevice = 7, + TrackedProp_StringExceedsMaximumLength = 8, + TrackedProp_NotYetAvailable = 9, // The property value isn't known yet, but is expected soon. Call again later. + TrackedProp_PermissionDenied = 10, + TrackedProp_InvalidOperation = 11, + TrackedProp_CannotWriteToWildcards = 12, +}; + +/** Allows the application to control what part of the provided texture will be used in the +* frame buffer. */ +struct VRTextureBounds_t +{ + float uMin, vMin; + float uMax, vMax; +}; + +/** Allows specifying pose used to render provided scene texture (if different from value returned by WaitGetPoses). */ +struct VRTextureWithPose_t : public Texture_t +{ + HmdMatrix34_t mDeviceToAbsoluteTracking; // Actual pose used to render scene textures. +}; + +struct VRTextureDepthInfo_t +{ + void* handle; // See ETextureType definition above + HmdMatrix44_t mProjection; + HmdVector2_t vRange; // 0..1 +}; + +struct VRTextureWithDepth_t : public Texture_t +{ + VRTextureDepthInfo_t depth; +}; + +struct VRTextureWithPoseAndDepth_t : public VRTextureWithPose_t +{ + VRTextureDepthInfo_t depth; +}; + +/** Allows the application to control how scene textures are used by the compositor when calling Submit. */ +enum EVRSubmitFlags +{ + // Simple render path. App submits rendered left and right eye images with no lens distortion correction applied. + Submit_Default = 0x00, + + // App submits final left and right eye images with lens distortion already applied (lens distortion makes the images appear + // barrel distorted with chromatic aberration correction applied). The app would have used the data returned by + // vr::IVRSystem::ComputeDistortion() to apply the correct distortion to the rendered images before calling Submit(). + Submit_LensDistortionAlreadyApplied = 0x01, + + // If the texture pointer passed in is actually a renderbuffer (e.g. for MSAA in OpenGL) then set this flag. + Submit_GlRenderBuffer = 0x02, + + // Do not use + Submit_Reserved = 0x04, + + // Set to indicate that pTexture is a pointer to a VRTextureWithPose_t. + // This flag can be combined with Submit_TextureWithDepth to pass a VRTextureWithPoseAndDepth_t. + Submit_TextureWithPose = 0x08, + + // Set to indicate that pTexture is a pointer to a VRTextureWithDepth_t. + // This flag can be combined with Submit_TextureWithPose to pass a VRTextureWithPoseAndDepth_t. + Submit_TextureWithDepth = 0x10, +}; + +/** Data required for passing Vulkan textures to IVRCompositor::Submit. +* Be sure to call OpenVR_Shutdown before destroying these resources. */ +struct VRVulkanTextureData_t +{ + uint64_t m_nImage; // VkImage + VkDevice_T *m_pDevice; + VkPhysicalDevice_T *m_pPhysicalDevice; + VkInstance_T *m_pInstance; + VkQueue_T *m_pQueue; + uint32_t m_nQueueFamilyIndex; + uint32_t m_nWidth, m_nHeight, m_nFormat, m_nSampleCount; +}; + +/** Data required for passing D3D12 textures to IVRCompositor::Submit. +* Be sure to call OpenVR_Shutdown before destroying these resources. */ +struct D3D12TextureData_t +{ + ID3D12Resource *m_pResource; + ID3D12CommandQueue *m_pCommandQueue; + uint32_t m_nNodeMask; +}; + +/** Status of the overall system or tracked objects */ +enum EVRState +{ + VRState_Undefined = -1, + VRState_Off = 0, + VRState_Searching = 1, + VRState_Searching_Alert = 2, + VRState_Ready = 3, + VRState_Ready_Alert = 4, + VRState_NotReady = 5, + VRState_Standby = 6, + VRState_Ready_Alert_Low = 7, +}; + +/** The types of events that could be posted (and what the parameters mean for each event type) */ +enum EVREventType +{ + VREvent_None = 0, + + VREvent_TrackedDeviceActivated = 100, + VREvent_TrackedDeviceDeactivated = 101, + VREvent_TrackedDeviceUpdated = 102, + VREvent_TrackedDeviceUserInteractionStarted = 103, + VREvent_TrackedDeviceUserInteractionEnded = 104, + VREvent_IpdChanged = 105, + VREvent_EnterStandbyMode = 106, + VREvent_LeaveStandbyMode = 107, + VREvent_TrackedDeviceRoleChanged = 108, + VREvent_WatchdogWakeUpRequested = 109, + VREvent_LensDistortionChanged = 110, + VREvent_PropertyChanged = 111, + VREvent_WirelessDisconnect = 112, + VREvent_WirelessReconnect = 113, + + VREvent_ButtonPress = 200, // data is controller + VREvent_ButtonUnpress = 201, // data is controller + VREvent_ButtonTouch = 202, // data is controller + VREvent_ButtonUntouch = 203, // data is controller + + VREvent_DualAnalog_Press = 250, // data is dualAnalog + VREvent_DualAnalog_Unpress = 251, // data is dualAnalog + VREvent_DualAnalog_Touch = 252, // data is dualAnalog + VREvent_DualAnalog_Untouch = 253, // data is dualAnalog + VREvent_DualAnalog_Move = 254, // data is dualAnalog + VREvent_DualAnalog_ModeSwitch1 = 255, // data is dualAnalog + VREvent_DualAnalog_ModeSwitch2 = 256, // data is dualAnalog + VREvent_DualAnalog_Cancel = 257, // data is dualAnalog + + VREvent_MouseMove = 300, // data is mouse + VREvent_MouseButtonDown = 301, // data is mouse + VREvent_MouseButtonUp = 302, // data is mouse + VREvent_FocusEnter = 303, // data is overlay + VREvent_FocusLeave = 304, // data is overlay + VREvent_Scroll = 305, // data is mouse + VREvent_TouchPadMove = 306, // data is mouse + VREvent_OverlayFocusChanged = 307, // data is overlay, global event + + VREvent_InputFocusCaptured = 400, // data is process DEPRECATED + VREvent_InputFocusReleased = 401, // data is process DEPRECATED + VREvent_SceneFocusLost = 402, // data is process + VREvent_SceneFocusGained = 403, // data is process + VREvent_SceneApplicationChanged = 404, // data is process - The App actually drawing the scene changed (usually to or from the compositor) + VREvent_SceneFocusChanged = 405, // data is process - New app got access to draw the scene + VREvent_InputFocusChanged = 406, // data is process + VREvent_SceneApplicationSecondaryRenderingStarted = 407, // data is process + VREvent_SceneApplicationUsingWrongGraphicsAdapter = 408, // data is process + VREvent_ActionBindingReloaded = 409, // data is process - The App that action binds reloaded for + + VREvent_HideRenderModels = 410, // Sent to the scene application to request hiding render models temporarily + VREvent_ShowRenderModels = 411, // Sent to the scene application to request restoring render model visibility + + VREvent_ConsoleOpened = 420, + VREvent_ConsoleClosed = 421, + + VREvent_OverlayShown = 500, + VREvent_OverlayHidden = 501, + VREvent_DashboardActivated = 502, + VREvent_DashboardDeactivated = 503, + VREvent_DashboardThumbSelected = 504, // Sent to the overlay manager - data is overlay + VREvent_DashboardRequested = 505, // Sent to the overlay manager - data is overlay + VREvent_ResetDashboard = 506, // Send to the overlay manager + VREvent_RenderToast = 507, // Send to the dashboard to render a toast - data is the notification ID + VREvent_ImageLoaded = 508, // Sent to overlays when a SetOverlayRaw or SetOverlayFromFile call finishes loading + VREvent_ShowKeyboard = 509, // Sent to keyboard renderer in the dashboard to invoke it + VREvent_HideKeyboard = 510, // Sent to keyboard renderer in the dashboard to hide it + VREvent_OverlayGamepadFocusGained = 511, // Sent to an overlay when IVROverlay::SetFocusOverlay is called on it + VREvent_OverlayGamepadFocusLost = 512, // Send to an overlay when it previously had focus and IVROverlay::SetFocusOverlay is called on something else + VREvent_OverlaySharedTextureChanged = 513, + //VREvent_DashboardGuideButtonDown = 514, // These are no longer sent + //VREvent_DashboardGuideButtonUp = 515, + VREvent_ScreenshotTriggered = 516, // Screenshot button combo was pressed, Dashboard should request a screenshot + VREvent_ImageFailed = 517, // Sent to overlays when a SetOverlayRaw or SetOverlayfromFail fails to load + VREvent_DashboardOverlayCreated = 518, + VREvent_SwitchGamepadFocus = 519, + + // Screenshot API + VREvent_RequestScreenshot = 520, // Sent by vrclient application to compositor to take a screenshot + VREvent_ScreenshotTaken = 521, // Sent by compositor to the application that the screenshot has been taken + VREvent_ScreenshotFailed = 522, // Sent by compositor to the application that the screenshot failed to be taken + VREvent_SubmitScreenshotToDashboard = 523, // Sent by compositor to the dashboard that a completed screenshot was submitted + VREvent_ScreenshotProgressToDashboard = 524, // Sent by compositor to the dashboard that a completed screenshot was submitted + + VREvent_PrimaryDashboardDeviceChanged = 525, + VREvent_RoomViewShown = 526, // Sent by compositor whenever room-view is enabled + VREvent_RoomViewHidden = 527, // Sent by compositor whenever room-view is disabled + + VREvent_Notification_Shown = 600, + VREvent_Notification_Hidden = 601, + VREvent_Notification_BeginInteraction = 602, + VREvent_Notification_Destroyed = 603, + + VREvent_Quit = 700, // data is process + VREvent_ProcessQuit = 701, // data is process + VREvent_QuitAborted_UserPrompt = 702, // data is process + VREvent_QuitAcknowledged = 703, // data is process + VREvent_DriverRequestedQuit = 704, // The driver has requested that SteamVR shut down + + VREvent_ChaperoneDataHasChanged = 800, + VREvent_ChaperoneUniverseHasChanged = 801, + VREvent_ChaperoneTempDataHasChanged = 802, + VREvent_ChaperoneSettingsHaveChanged = 803, + VREvent_SeatedZeroPoseReset = 804, + + VREvent_AudioSettingsHaveChanged = 820, + + VREvent_BackgroundSettingHasChanged = 850, + VREvent_CameraSettingsHaveChanged = 851, + VREvent_ReprojectionSettingHasChanged = 852, + VREvent_ModelSkinSettingsHaveChanged = 853, + VREvent_EnvironmentSettingsHaveChanged = 854, + VREvent_PowerSettingsHaveChanged = 855, + VREvent_EnableHomeAppSettingsHaveChanged = 856, + VREvent_SteamVRSectionSettingChanged = 857, + VREvent_LighthouseSectionSettingChanged = 858, + VREvent_NullSectionSettingChanged = 859, + VREvent_UserInterfaceSectionSettingChanged = 860, + VREvent_NotificationsSectionSettingChanged = 861, + VREvent_KeyboardSectionSettingChanged = 862, + VREvent_PerfSectionSettingChanged = 863, + VREvent_DashboardSectionSettingChanged = 864, + VREvent_WebInterfaceSectionSettingChanged = 865, + + VREvent_StatusUpdate = 900, + + VREvent_WebInterface_InstallDriverCompleted = 950, + + VREvent_MCImageUpdated = 1000, + + VREvent_FirmwareUpdateStarted = 1100, + VREvent_FirmwareUpdateFinished = 1101, + + VREvent_KeyboardClosed = 1200, + VREvent_KeyboardCharInput = 1201, + VREvent_KeyboardDone = 1202, // Sent when DONE button clicked on keyboard + + VREvent_ApplicationTransitionStarted = 1300, + VREvent_ApplicationTransitionAborted = 1301, + VREvent_ApplicationTransitionNewAppStarted = 1302, + VREvent_ApplicationListUpdated = 1303, + VREvent_ApplicationMimeTypeLoad = 1304, + VREvent_ApplicationTransitionNewAppLaunchComplete = 1305, + VREvent_ProcessConnected = 1306, + VREvent_ProcessDisconnected = 1307, + + VREvent_Compositor_MirrorWindowShown = 1400, + VREvent_Compositor_MirrorWindowHidden = 1401, + VREvent_Compositor_ChaperoneBoundsShown = 1410, + VREvent_Compositor_ChaperoneBoundsHidden = 1411, + + VREvent_TrackedCamera_StartVideoStream = 1500, + VREvent_TrackedCamera_StopVideoStream = 1501, + VREvent_TrackedCamera_PauseVideoStream = 1502, + VREvent_TrackedCamera_ResumeVideoStream = 1503, + VREvent_TrackedCamera_EditingSurface = 1550, + + VREvent_PerformanceTest_EnableCapture = 1600, + VREvent_PerformanceTest_DisableCapture = 1601, + VREvent_PerformanceTest_FidelityLevel = 1602, + + VREvent_MessageOverlay_Closed = 1650, + VREvent_MessageOverlayCloseRequested = 1651, + + VREvent_Input_HapticVibration = 1700, // data is hapticVibration + VREvent_Input_BindingLoadFailed = 1701, // data is process + VREvent_Input_BindingLoadSuccessful = 1702, // data is process + + // Vendors are free to expose private events in this reserved region + VREvent_VendorSpecific_Reserved_Start = 10000, + VREvent_VendorSpecific_Reserved_End = 19999, +}; + + +/** Level of Hmd activity */ +// UserInteraction_Timeout means the device is in the process of timing out. +// InUse = ( k_EDeviceActivityLevel_UserInteraction || k_EDeviceActivityLevel_UserInteraction_Timeout ) +// VREvent_TrackedDeviceUserInteractionStarted fires when the devices transitions from Standby -> UserInteraction or Idle -> UserInteraction. +// VREvent_TrackedDeviceUserInteractionEnded fires when the devices transitions from UserInteraction_Timeout -> Idle +enum EDeviceActivityLevel +{ + k_EDeviceActivityLevel_Unknown = -1, + k_EDeviceActivityLevel_Idle = 0, // No activity for the last 10 seconds + k_EDeviceActivityLevel_UserInteraction = 1, // Activity (movement or prox sensor) is happening now + k_EDeviceActivityLevel_UserInteraction_Timeout = 2, // No activity for the last 0.5 seconds + k_EDeviceActivityLevel_Standby = 3, // Idle for at least 5 seconds (configurable in Settings -> Power Management) +}; + + +/** VR controller button and axis IDs */ +enum EVRButtonId +{ + k_EButton_System = 0, + k_EButton_ApplicationMenu = 1, + k_EButton_Grip = 2, + k_EButton_DPad_Left = 3, + k_EButton_DPad_Up = 4, + k_EButton_DPad_Right = 5, + k_EButton_DPad_Down = 6, + k_EButton_A = 7, + + k_EButton_ProximitySensor = 31, + + k_EButton_Axis0 = 32, + k_EButton_Axis1 = 33, + k_EButton_Axis2 = 34, + k_EButton_Axis3 = 35, + k_EButton_Axis4 = 36, + + // aliases for well known controllers + k_EButton_SteamVR_Touchpad = k_EButton_Axis0, + k_EButton_SteamVR_Trigger = k_EButton_Axis1, + + k_EButton_Dashboard_Back = k_EButton_Grip, + + k_EButton_Max = 64 +}; + +inline uint64_t ButtonMaskFromId( EVRButtonId id ) { return 1ull << id; } + +/** used for controller button events */ +struct VREvent_Controller_t +{ + uint32_t button; // EVRButtonId enum +}; + + +/** used for simulated mouse events in overlay space */ +enum EVRMouseButton +{ + VRMouseButton_Left = 0x0001, + VRMouseButton_Right = 0x0002, + VRMouseButton_Middle = 0x0004, +}; + + +/** used for simulated mouse events in overlay space */ +struct VREvent_Mouse_t +{ + float x, y; // co-ords are in GL space, bottom left of the texture is 0,0 + uint32_t button; // EVRMouseButton enum +}; + +/** used for simulated mouse wheel scroll in overlay space */ +struct VREvent_Scroll_t +{ + float xdelta, ydelta; // movement in fraction of the pad traversed since last delta, 1.0 for a full swipe + uint32_t repeatCount; +}; + +/** when in mouse input mode you can receive data from the touchpad, these events are only sent if the users finger + is on the touchpad (or just released from it). These events are sent to overlays with the VROverlayFlags_SendVRTouchpadEvents + flag set. +**/ +struct VREvent_TouchPadMove_t +{ + // true if the users finger is detected on the touch pad + bool bFingerDown; + + // How long the finger has been down in seconds + float flSecondsFingerDown; + + // These values indicate the starting finger position (so you can do some basic swipe stuff) + float fValueXFirst; + float fValueYFirst; + + // This is the raw sampled coordinate without deadzoning + float fValueXRaw; + float fValueYRaw; +}; + +/** notification related events. Details will still change at this point */ +struct VREvent_Notification_t +{ + uint64_t ulUserValue; + uint32_t notificationId; +}; + +/** Used for events about processes */ +struct VREvent_Process_t +{ + uint32_t pid; + uint32_t oldPid; + bool bForced; +}; + + +/** Used for a few events about overlays */ +struct VREvent_Overlay_t +{ + uint64_t overlayHandle; + uint64_t devicePath; +}; + + +/** Used for a few events about overlays */ +struct VREvent_Status_t +{ + uint32_t statusState; // EVRState enum +}; + +/** Used for keyboard events **/ +struct VREvent_Keyboard_t +{ + char cNewInput[8]; // Up to 11 bytes of new input + uint64_t uUserValue; // Possible flags about the new input +}; + +struct VREvent_Ipd_t +{ + float ipdMeters; +}; + +struct VREvent_Chaperone_t +{ + uint64_t m_nPreviousUniverse; + uint64_t m_nCurrentUniverse; +}; + +/** Not actually used for any events */ +struct VREvent_Reserved_t +{ + uint64_t reserved0; + uint64_t reserved1; + uint64_t reserved2; + uint64_t reserved3; +}; + +struct VREvent_PerformanceTest_t +{ + uint32_t m_nFidelityLevel; +}; + +struct VREvent_SeatedZeroPoseReset_t +{ + bool bResetBySystemMenu; +}; + +struct VREvent_Screenshot_t +{ + uint32_t handle; + uint32_t type; +}; + +struct VREvent_ScreenshotProgress_t +{ + float progress; +}; + +struct VREvent_ApplicationLaunch_t +{ + uint32_t pid; + uint32_t unArgsHandle; +}; + +struct VREvent_EditingCameraSurface_t +{ + uint64_t overlayHandle; + uint32_t nVisualMode; +}; + +struct VREvent_MessageOverlay_t +{ + uint32_t unVRMessageOverlayResponse; // vr::VRMessageOverlayResponse enum +}; + +struct VREvent_Property_t +{ + PropertyContainerHandle_t container; + ETrackedDeviceProperty prop; +}; + +enum EDualAnalogWhich +{ + k_EDualAnalog_Left = 0, + k_EDualAnalog_Right = 1, +}; + +struct VREvent_DualAnalog_t +{ + float x, y; // coordinates are -1..1 analog values + float transformedX, transformedY; // transformed by the center and radius numbers provided by the overlay + EDualAnalogWhich which; +}; + +struct VREvent_HapticVibration_t +{ + uint64_t containerHandle; // property container handle of the device with the haptic component + uint64_t componentHandle; // Which haptic component needs to vibrate + float fDurationSeconds; + float fFrequency; + float fAmplitude; +}; + +struct VREvent_WebConsole_t +{ + WebConsoleHandle_t webConsoleHandle; +}; + +struct VREvent_InputBindingLoad_t +{ + vr::PropertyContainerHandle_t ulAppContainer; + uint64_t pathMessage; + uint64_t pathUrl; +}; + + +/** NOTE!!! If you change this you MUST manually update openvr_interop.cs.py */ +typedef union +{ + VREvent_Reserved_t reserved; + VREvent_Controller_t controller; + VREvent_Mouse_t mouse; + VREvent_Scroll_t scroll; + VREvent_Process_t process; + VREvent_Notification_t notification; + VREvent_Overlay_t overlay; + VREvent_Status_t status; + VREvent_Keyboard_t keyboard; + VREvent_Ipd_t ipd; + VREvent_Chaperone_t chaperone; + VREvent_PerformanceTest_t performanceTest; + VREvent_TouchPadMove_t touchPadMove; + VREvent_SeatedZeroPoseReset_t seatedZeroPoseReset; + VREvent_Screenshot_t screenshot; + VREvent_ScreenshotProgress_t screenshotProgress; + VREvent_ApplicationLaunch_t applicationLaunch; + VREvent_EditingCameraSurface_t cameraSurface; + VREvent_MessageOverlay_t messageOverlay; + VREvent_Property_t property; + VREvent_DualAnalog_t dualAnalog; + VREvent_HapticVibration_t hapticVibration; + VREvent_WebConsole_t webConsole; + VREvent_InputBindingLoad_t inputBinding; +} VREvent_Data_t; + + +#if defined(__linux__) || defined(__APPLE__) +// This structure was originally defined mis-packed on Linux, preserved for +// compatibility. +#pragma pack( push, 4 ) +#endif + +/** An event posted by the server to all running applications */ +struct VREvent_t +{ + uint32_t eventType; // EVREventType enum + TrackedDeviceIndex_t trackedDeviceIndex; + float eventAgeSeconds; + // event data must be the end of the struct as its size is variable + VREvent_Data_t data; +}; + +#if defined(__linux__) || defined(__APPLE__) +#pragma pack( pop ) +#endif + +enum EVRInputError +{ + VRInputError_None = 0, + VRInputError_NameNotFound = 1, + VRInputError_WrongType = 2, + VRInputError_InvalidHandle = 3, + VRInputError_InvalidParam = 4, + VRInputError_NoSteam = 5, + VRInputError_MaxCapacityReached = 6, + VRInputError_IPCError = 7, + VRInputError_NoActiveActionSet = 8, + VRInputError_InvalidDevice = 9, + VRInputError_InvalidSkeleton = 10, + VRInputError_InvalidBoneCount = 11, + VRInputError_InvalidCompressedData = 12, + VRInputError_NoData = 13, + VRInputError_BufferTooSmall = 14, + VRInputError_MismatchedActionManifest = 15, +}; + + +/** The mesh to draw into the stencil (or depth) buffer to perform +* early stencil (or depth) kills of pixels that will never appear on the HMD. +* This mesh draws on all the pixels that will be hidden after distortion. +* +* If the HMD does not provide a visible area mesh pVertexData will be +* NULL and unTriangleCount will be 0. */ +struct HiddenAreaMesh_t +{ + const HmdVector2_t *pVertexData; + uint32_t unTriangleCount; +}; + + +enum EHiddenAreaMeshType +{ + k_eHiddenAreaMesh_Standard = 0, + k_eHiddenAreaMesh_Inverse = 1, + k_eHiddenAreaMesh_LineLoop = 2, + + k_eHiddenAreaMesh_Max = 3, +}; + + +/** Identifies what kind of axis is on the controller at index n. Read this type +* with pVRSystem->Get( nControllerDeviceIndex, Prop_Axis0Type_Int32 + n ); +*/ +enum EVRControllerAxisType +{ + k_eControllerAxis_None = 0, + k_eControllerAxis_TrackPad = 1, + k_eControllerAxis_Joystick = 2, + k_eControllerAxis_Trigger = 3, // Analog trigger data is in the X axis +}; + + +/** contains information about one axis on the controller */ +struct VRControllerAxis_t +{ + float x; // Ranges from -1.0 to 1.0 for joysticks and track pads. Ranges from 0.0 to 1.0 for triggers were 0 is fully released. + float y; // Ranges from -1.0 to 1.0 for joysticks and track pads. Is always 0.0 for triggers. +}; + + +/** the number of axes in the controller state */ +static const uint32_t k_unControllerStateAxisCount = 5; + + +#if defined(__linux__) || defined(__APPLE__) +// This structure was originally defined mis-packed on Linux, preserved for +// compatibility. +#pragma pack( push, 4 ) +#endif + +/** Holds all the state of a controller at one moment in time. */ +struct VRControllerState001_t +{ + // If packet num matches that on your prior call, then the controller state hasn't been changed since + // your last call and there is no need to process it + uint32_t unPacketNum; + + // bit flags for each of the buttons. Use ButtonMaskFromId to turn an ID into a mask + uint64_t ulButtonPressed; + uint64_t ulButtonTouched; + + // Axis data for the controller's analog inputs + VRControllerAxis_t rAxis[ k_unControllerStateAxisCount ]; +}; +#if defined(__linux__) || defined(__APPLE__) +#pragma pack( pop ) +#endif + + +typedef VRControllerState001_t VRControllerState_t; + + +/** determines how to provide output to the application of various event processing functions. */ +enum EVRControllerEventOutputType +{ + ControllerEventOutput_OSEvents = 0, + ControllerEventOutput_VREvents = 1, +}; + + + +/** Collision Bounds Style */ +enum ECollisionBoundsStyle +{ + COLLISION_BOUNDS_STYLE_BEGINNER = 0, + COLLISION_BOUNDS_STYLE_INTERMEDIATE, + COLLISION_BOUNDS_STYLE_SQUARES, + COLLISION_BOUNDS_STYLE_ADVANCED, + COLLISION_BOUNDS_STYLE_NONE, + + COLLISION_BOUNDS_STYLE_COUNT +}; + +/** Allows the application to customize how the overlay appears in the compositor */ +struct Compositor_OverlaySettings +{ + uint32_t size; // sizeof(Compositor_OverlaySettings) + bool curved, antialias; + float scale, distance, alpha; + float uOffset, vOffset, uScale, vScale; + float gridDivs, gridWidth, gridScale; + HmdMatrix44_t transform; +}; + +/** used to refer to a single VR overlay */ +typedef uint64_t VROverlayHandle_t; + +static const VROverlayHandle_t k_ulOverlayHandleInvalid = 0; + +/** Errors that can occur around VR overlays */ +enum EVROverlayError +{ + VROverlayError_None = 0, + + VROverlayError_UnknownOverlay = 10, + VROverlayError_InvalidHandle = 11, + VROverlayError_PermissionDenied = 12, + VROverlayError_OverlayLimitExceeded = 13, // No more overlays could be created because the maximum number already exist + VROverlayError_WrongVisibilityType = 14, + VROverlayError_KeyTooLong = 15, + VROverlayError_NameTooLong = 16, + VROverlayError_KeyInUse = 17, + VROverlayError_WrongTransformType = 18, + VROverlayError_InvalidTrackedDevice = 19, + VROverlayError_InvalidParameter = 20, + VROverlayError_ThumbnailCantBeDestroyed = 21, + VROverlayError_ArrayTooSmall = 22, + VROverlayError_RequestFailed = 23, + VROverlayError_InvalidTexture = 24, + VROverlayError_UnableToLoadFile = 25, + VROverlayError_KeyboardAlreadyInUse = 26, + VROverlayError_NoNeighbor = 27, + VROverlayError_TooManyMaskPrimitives = 29, + VROverlayError_BadMaskPrimitive = 30, + VROverlayError_TextureAlreadyLocked = 31, + VROverlayError_TextureLockCapacityReached = 32, + VROverlayError_TextureNotLocked = 33, +}; + +/** enum values to pass in to VR_Init to identify whether the application will +* draw a 3D scene. */ +enum EVRApplicationType +{ + VRApplication_Other = 0, // Some other kind of application that isn't covered by the other entries + VRApplication_Scene = 1, // Application will submit 3D frames + VRApplication_Overlay = 2, // Application only interacts with overlays + VRApplication_Background = 3, // Application should not start SteamVR if it's not already running, and should not + // keep it running if everything else quits. + VRApplication_Utility = 4, // Init should not try to load any drivers. The application needs access to utility + // interfaces (like IVRSettings and IVRApplications) but not hardware. + VRApplication_VRMonitor = 5, // Reserved for vrmonitor + VRApplication_SteamWatchdog = 6,// Reserved for Steam + VRApplication_Bootstrapper = 7, // Start up SteamVR + + VRApplication_Max +}; + + +/** error codes for firmware */ +enum EVRFirmwareError +{ + VRFirmwareError_None = 0, + VRFirmwareError_Success = 1, + VRFirmwareError_Fail = 2, +}; + + +/** error codes for notifications */ +enum EVRNotificationError +{ + VRNotificationError_OK = 0, + VRNotificationError_InvalidNotificationId = 100, + VRNotificationError_NotificationQueueFull = 101, + VRNotificationError_InvalidOverlayHandle = 102, + VRNotificationError_SystemWithUserValueAlreadyExists = 103, +}; + + +/** Holds the transform for a single bone */ +struct VRBoneTransform_t +{ + HmdVector4_t position; + HmdQuaternionf_t orientation; +}; + + +/** error codes returned by Vr_Init */ + +// Please add adequate error description to https://developer.valvesoftware.com/w/index.php?title=Category:SteamVRHelp +enum EVRInitError +{ + VRInitError_None = 0, + VRInitError_Unknown = 1, + + VRInitError_Init_InstallationNotFound = 100, + VRInitError_Init_InstallationCorrupt = 101, + VRInitError_Init_VRClientDLLNotFound = 102, + VRInitError_Init_FileNotFound = 103, + VRInitError_Init_FactoryNotFound = 104, + VRInitError_Init_InterfaceNotFound = 105, + VRInitError_Init_InvalidInterface = 106, + VRInitError_Init_UserConfigDirectoryInvalid = 107, + VRInitError_Init_HmdNotFound = 108, + VRInitError_Init_NotInitialized = 109, + VRInitError_Init_PathRegistryNotFound = 110, + VRInitError_Init_NoConfigPath = 111, + VRInitError_Init_NoLogPath = 112, + VRInitError_Init_PathRegistryNotWritable = 113, + VRInitError_Init_AppInfoInitFailed = 114, + VRInitError_Init_Retry = 115, // Used internally to cause retries to vrserver + VRInitError_Init_InitCanceledByUser = 116, // The calling application should silently exit. The user canceled app startup + VRInitError_Init_AnotherAppLaunching = 117, + VRInitError_Init_SettingsInitFailed = 118, + VRInitError_Init_ShuttingDown = 119, + VRInitError_Init_TooManyObjects = 120, + VRInitError_Init_NoServerForBackgroundApp = 121, + VRInitError_Init_NotSupportedWithCompositor = 122, + VRInitError_Init_NotAvailableToUtilityApps = 123, + VRInitError_Init_Internal = 124, + VRInitError_Init_HmdDriverIdIsNone = 125, + VRInitError_Init_HmdNotFoundPresenceFailed = 126, + VRInitError_Init_VRMonitorNotFound = 127, + VRInitError_Init_VRMonitorStartupFailed = 128, + VRInitError_Init_LowPowerWatchdogNotSupported = 129, + VRInitError_Init_InvalidApplicationType = 130, + VRInitError_Init_NotAvailableToWatchdogApps = 131, + VRInitError_Init_WatchdogDisabledInSettings = 132, + VRInitError_Init_VRDashboardNotFound = 133, + VRInitError_Init_VRDashboardStartupFailed = 134, + VRInitError_Init_VRHomeNotFound = 135, + VRInitError_Init_VRHomeStartupFailed = 136, + VRInitError_Init_RebootingBusy = 137, + VRInitError_Init_FirmwareUpdateBusy = 138, + VRInitError_Init_FirmwareRecoveryBusy = 139, + VRInitError_Init_USBServiceBusy = 140, + VRInitError_Init_VRWebHelperStartupFailed = 141, + + VRInitError_Driver_Failed = 200, + VRInitError_Driver_Unknown = 201, + VRInitError_Driver_HmdUnknown = 202, + VRInitError_Driver_NotLoaded = 203, + VRInitError_Driver_RuntimeOutOfDate = 204, + VRInitError_Driver_HmdInUse = 205, + VRInitError_Driver_NotCalibrated = 206, + VRInitError_Driver_CalibrationInvalid = 207, + VRInitError_Driver_HmdDisplayNotFound = 208, + VRInitError_Driver_TrackedDeviceInterfaceUnknown = 209, + // VRInitError_Driver_HmdDisplayNotFoundAfterFix = 210, // not needed: here for historic reasons + VRInitError_Driver_HmdDriverIdOutOfBounds = 211, + VRInitError_Driver_HmdDisplayMirrored = 212, + + VRInitError_IPC_ServerInitFailed = 300, + VRInitError_IPC_ConnectFailed = 301, + VRInitError_IPC_SharedStateInitFailed = 302, + VRInitError_IPC_CompositorInitFailed = 303, + VRInitError_IPC_MutexInitFailed = 304, + VRInitError_IPC_Failed = 305, + VRInitError_IPC_CompositorConnectFailed = 306, + VRInitError_IPC_CompositorInvalidConnectResponse = 307, + VRInitError_IPC_ConnectFailedAfterMultipleAttempts = 308, + + VRInitError_Compositor_Failed = 400, + VRInitError_Compositor_D3D11HardwareRequired = 401, + VRInitError_Compositor_FirmwareRequiresUpdate = 402, + VRInitError_Compositor_OverlayInitFailed = 403, + VRInitError_Compositor_ScreenshotsInitFailed = 404, + VRInitError_Compositor_UnableToCreateDevice = 405, + + VRInitError_VendorSpecific_UnableToConnectToOculusRuntime = 1000, + VRInitError_VendorSpecific_WindowsNotInDevMode = 1001, + + VRInitError_VendorSpecific_HmdFound_CantOpenDevice = 1101, + VRInitError_VendorSpecific_HmdFound_UnableToRequestConfigStart = 1102, + VRInitError_VendorSpecific_HmdFound_NoStoredConfig = 1103, + VRInitError_VendorSpecific_HmdFound_ConfigTooBig = 1104, + VRInitError_VendorSpecific_HmdFound_ConfigTooSmall = 1105, + VRInitError_VendorSpecific_HmdFound_UnableToInitZLib = 1106, + VRInitError_VendorSpecific_HmdFound_CantReadFirmwareVersion = 1107, + VRInitError_VendorSpecific_HmdFound_UnableToSendUserDataStart = 1108, + VRInitError_VendorSpecific_HmdFound_UnableToGetUserDataStart = 1109, + VRInitError_VendorSpecific_HmdFound_UnableToGetUserDataNext = 1110, + VRInitError_VendorSpecific_HmdFound_UserDataAddressRange = 1111, + VRInitError_VendorSpecific_HmdFound_UserDataError = 1112, + VRInitError_VendorSpecific_HmdFound_ConfigFailedSanityCheck = 1113, + + VRInitError_Steam_SteamInstallationNotFound = 2000, +}; + +enum EVRScreenshotType +{ + VRScreenshotType_None = 0, + VRScreenshotType_Mono = 1, // left eye only + VRScreenshotType_Stereo = 2, + VRScreenshotType_Cubemap = 3, + VRScreenshotType_MonoPanorama = 4, + VRScreenshotType_StereoPanorama = 5 +}; + +enum EVRScreenshotPropertyFilenames +{ + VRScreenshotPropertyFilenames_Preview = 0, + VRScreenshotPropertyFilenames_VR = 1, +}; + +enum EVRTrackedCameraError +{ + VRTrackedCameraError_None = 0, + VRTrackedCameraError_OperationFailed = 100, + VRTrackedCameraError_InvalidHandle = 101, + VRTrackedCameraError_InvalidFrameHeaderVersion = 102, + VRTrackedCameraError_OutOfHandles = 103, + VRTrackedCameraError_IPCFailure = 104, + VRTrackedCameraError_NotSupportedForThisDevice = 105, + VRTrackedCameraError_SharedMemoryFailure = 106, + VRTrackedCameraError_FrameBufferingFailure = 107, + VRTrackedCameraError_StreamSetupFailure = 108, + VRTrackedCameraError_InvalidGLTextureId = 109, + VRTrackedCameraError_InvalidSharedTextureHandle = 110, + VRTrackedCameraError_FailedToGetGLTextureId = 111, + VRTrackedCameraError_SharedTextureFailure = 112, + VRTrackedCameraError_NoFrameAvailable = 113, + VRTrackedCameraError_InvalidArgument = 114, + VRTrackedCameraError_InvalidFrameBufferSize = 115, +}; + +enum EVRTrackedCameraFrameLayout +{ + EVRTrackedCameraFrameLayout_Mono = 0x0001, + EVRTrackedCameraFrameLayout_Stereo = 0x0002, + EVRTrackedCameraFrameLayout_VerticalLayout = 0x0010, // Stereo frames are Top/Bottom (left/right) + EVRTrackedCameraFrameLayout_HorizontalLayout = 0x0020, // Stereo frames are Left/Right +}; + +enum EVRTrackedCameraFrameType +{ + VRTrackedCameraFrameType_Distorted = 0, // This is the camera video frame size in pixels, still distorted. + VRTrackedCameraFrameType_Undistorted, // In pixels, an undistorted inscribed rectangle region without invalid regions. This size is subject to changes shortly. + VRTrackedCameraFrameType_MaximumUndistorted, // In pixels, maximum undistorted with invalid regions. Non zero alpha component identifies valid regions. + MAX_CAMERA_FRAME_TYPES +}; + +typedef uint64_t TrackedCameraHandle_t; +#define INVALID_TRACKED_CAMERA_HANDLE ((vr::TrackedCameraHandle_t)0) + +struct CameraVideoStreamFrameHeader_t +{ + EVRTrackedCameraFrameType eFrameType; + + uint32_t nWidth; + uint32_t nHeight; + uint32_t nBytesPerPixel; + + uint32_t nFrameSequence; + + TrackedDevicePose_t standingTrackedDevicePose; +}; + +// Screenshot types +typedef uint32_t ScreenshotHandle_t; + +static const uint32_t k_unScreenshotHandleInvalid = 0; + +/** Frame timing data provided by direct mode drivers. */ +struct DriverDirectMode_FrameTiming +{ + uint32_t m_nSize; // Set to sizeof( DriverDirectMode_FrameTiming ) + uint32_t m_nNumFramePresents; // number of times frame was presented + uint32_t m_nNumMisPresented; // number of times frame was presented on a vsync other than it was originally predicted to + uint32_t m_nNumDroppedFrames; // number of additional times previous frame was scanned out (i.e. compositor missed vsync) + uint32_t m_nReprojectionFlags; +}; + +enum EVSync +{ + VSync_None, + VSync_WaitRender, // block following render work until vsync + VSync_NoWaitRender, // do not block following render work (allow to get started early) +}; + +/** raw IMU data provided by IVRIOBuffer from paths to tracked devices with IMUs */ +enum Imu_OffScaleFlags +{ + OffScale_AccelX = 0x01, + OffScale_AccelY = 0x02, + OffScale_AccelZ = 0x04, + OffScale_GyroX = 0x08, + OffScale_GyroY = 0x10, + OffScale_GyroZ = 0x20, +}; + +struct ImuSample_t +{ + double fSampleTime; + HmdVector3d_t vAccel; + HmdVector3d_t vGyro; + uint32_t unOffScaleFlags; +}; + +#pragma pack( pop ) + +// figure out how to import from the VR API dll +#if defined(_WIN32) + +#ifdef VR_API_EXPORT +#define VR_INTERFACE extern "C" __declspec( dllexport ) +#else +#define VR_INTERFACE extern "C" __declspec( dllimport ) +#endif + +#elif defined(__GNUC__) || defined(COMPILER_GCC) || defined(__APPLE__) + +#ifdef VR_API_EXPORT +#define VR_INTERFACE extern "C" __attribute__((visibility("default"))) +#else +#define VR_INTERFACE extern "C" +#endif + +#else +#error "Unsupported Platform." +#endif + + +#if defined( _WIN32 ) +#define VR_CALLTYPE __cdecl +#else +#define VR_CALLTYPE +#endif + +} // namespace vr + +#endif // _INCLUDE_VRTYPES_H + + +// vrannotation.h +#ifdef API_GEN +# define VR_CLANG_ATTR(ATTR) __attribute__((annotate( ATTR ))) +#else +# define VR_CLANG_ATTR(ATTR) +#endif + +#define VR_METHOD_DESC(DESC) VR_CLANG_ATTR( "desc:" #DESC ";" ) +#define VR_IGNOREATTR() VR_CLANG_ATTR( "ignore" ) +#define VR_OUT_STRUCT() VR_CLANG_ATTR( "out_struct: ;" ) +#define VR_OUT_STRING() VR_CLANG_ATTR( "out_string: ;" ) +#define VR_OUT_ARRAY_CALL(COUNTER,FUNCTION,PARAMS) VR_CLANG_ATTR( "out_array_call:" #COUNTER "," #FUNCTION "," #PARAMS ";" ) +#define VR_OUT_ARRAY_COUNT(COUNTER) VR_CLANG_ATTR( "out_array_count:" #COUNTER ";" ) +#define VR_ARRAY_COUNT(COUNTER) VR_CLANG_ATTR( "array_count:" #COUNTER ";" ) +#define VR_ARRAY_COUNT_D(COUNTER, DESC) VR_CLANG_ATTR( "array_count:" #COUNTER ";desc:" #DESC ) +#define VR_BUFFER_COUNT(COUNTER) VR_CLANG_ATTR( "buffer_count:" #COUNTER ";" ) +#define VR_OUT_BUFFER_COUNT(COUNTER) VR_CLANG_ATTR( "out_buffer_count:" #COUNTER ";" ) +#define VR_OUT_STRING_COUNT(COUNTER) VR_CLANG_ATTR( "out_string_count:" #COUNTER ";" ) + +// ivrsystem.h +namespace vr +{ + +class IVRSystem +{ +public: + + + // ------------------------------------ + // Display Methods + // ------------------------------------ + + /** Suggested size for the intermediate render target that the distortion pulls from. */ + virtual void GetRecommendedRenderTargetSize( uint32_t *pnWidth, uint32_t *pnHeight ) = 0; + + /** The projection matrix for the specified eye */ + virtual HmdMatrix44_t GetProjectionMatrix( EVREye eEye, float fNearZ, float fFarZ ) = 0; + + /** The components necessary to build your own projection matrix in case your + * application is doing something fancy like infinite Z */ + virtual void GetProjectionRaw( EVREye eEye, float *pfLeft, float *pfRight, float *pfTop, float *pfBottom ) = 0; + + /** Gets the result of the distortion function for the specified eye and input UVs. UVs go from 0,0 in + * the upper left of that eye's viewport and 1,1 in the lower right of that eye's viewport. + * Returns true for success. Otherwise, returns false, and distortion coordinates are not suitable. */ + virtual bool ComputeDistortion( EVREye eEye, float fU, float fV, DistortionCoordinates_t *pDistortionCoordinates ) = 0; + + /** Returns the transform from eye space to the head space. Eye space is the per-eye flavor of head + * space that provides stereo disparity. Instead of Model * View * Projection the sequence is Model * View * Eye^-1 * Projection. + * Normally View and Eye^-1 will be multiplied together and treated as View in your application. + */ + virtual HmdMatrix34_t GetEyeToHeadTransform( EVREye eEye ) = 0; + + /** Returns the number of elapsed seconds since the last recorded vsync event. This + * will come from a vsync timer event in the timer if possible or from the application-reported + * time if that is not available. If no vsync times are available the function will + * return zero for vsync time and frame counter and return false from the method. */ + virtual bool GetTimeSinceLastVsync( float *pfSecondsSinceLastVsync, uint64_t *pulFrameCounter ) = 0; + + /** [D3D9 Only] + * Returns the adapter index that the user should pass into CreateDevice to set up D3D9 in such + * a way that it can go full screen exclusive on the HMD. Returns -1 if there was an error. + */ + virtual int32_t GetD3D9AdapterIndex() = 0; + + /** [D3D10/11 Only] + * Returns the adapter index that the user should pass into EnumAdapters to create the device + * and swap chain in DX10 and DX11. If an error occurs the index will be set to -1. + */ + virtual void GetDXGIOutputInfo( int32_t *pnAdapterIndex ) = 0; + + /** + * Returns platform- and texture-type specific adapter identification so that applications and the + * compositor are creating textures and swap chains on the same GPU. If an error occurs the device + * will be set to 0. + * pInstance is an optional parameter that is required only when textureType is TextureType_Vulkan. + * [D3D10/11/12 Only (D3D9 Not Supported)] + * Returns the adapter LUID that identifies the GPU attached to the HMD. The user should + * enumerate all adapters using IDXGIFactory::EnumAdapters and IDXGIAdapter::GetDesc to find + * the adapter with the matching LUID, or use IDXGIFactory4::EnumAdapterByLuid. + * The discovered IDXGIAdapter should be used to create the device and swap chain. + * [Vulkan Only] + * Returns the VkPhysicalDevice that should be used by the application. + * pInstance must be the instance the application will use to query for the VkPhysicalDevice. The application + * must create the VkInstance with extensions returned by IVRCompositor::GetVulkanInstanceExtensionsRequired enabled. + * [macOS Only] + * For TextureType_IOSurface returns the id that should be used by the application. + * On 10.13+ for TextureType_OpenGL returns the 'registryId' of the renderer which should be used + * by the application. See Apple Technical Q&A QA1168 for information on enumerating GL Renderers, and the + * new kCGLRPRegistryIDLow and kCGLRPRegistryIDHigh CGLRendererProperty values in the 10.13 SDK. + * Pre 10.13 for TextureType_OpenGL returns 0, as there is no dependable way to correlate the HMDs MTLDevice + * with a GL Renderer. + */ + virtual void GetOutputDevice( uint64_t *pnDevice, ETextureType textureType, VkInstance_T *pInstance = nullptr ) = 0; + + // ------------------------------------ + // Display Mode methods + // ------------------------------------ + + /** Use to determine if the headset display is part of the desktop (i.e. extended) or hidden (i.e. direct mode). */ + virtual bool IsDisplayOnDesktop() = 0; + + /** Set the display visibility (true = extended, false = direct mode). Return value of true indicates that the change was successful. */ + virtual bool SetDisplayVisibility( bool bIsVisibleOnDesktop ) = 0; + + // ------------------------------------ + // Tracking Methods + // ------------------------------------ + + /** The pose that the tracker thinks that the HMD will be in at the specified number of seconds into the + * future. Pass 0 to get the state at the instant the method is called. Most of the time the application should + * calculate the time until the photons will be emitted from the display and pass that time into the method. + * + * This is roughly analogous to the inverse of the view matrix in most applications, though + * many games will need to do some additional rotation or translation on top of the rotation + * and translation provided by the head pose. + * + * For devices where bPoseIsValid is true the application can use the pose to position the device + * in question. The provided array can be any size up to k_unMaxTrackedDeviceCount. + * + * Seated experiences should call this method with TrackingUniverseSeated and receive poses relative + * to the seated zero pose. Standing experiences should call this method with TrackingUniverseStanding + * and receive poses relative to the Chaperone Play Area. TrackingUniverseRawAndUncalibrated should + * probably not be used unless the application is the Chaperone calibration tool itself, but will provide + * poses relative to the hardware-specific coordinate system in the driver. + */ + virtual void GetDeviceToAbsoluteTrackingPose( ETrackingUniverseOrigin eOrigin, float fPredictedSecondsToPhotonsFromNow, VR_ARRAY_COUNT(unTrackedDevicePoseArrayCount) TrackedDevicePose_t *pTrackedDevicePoseArray, uint32_t unTrackedDevicePoseArrayCount ) = 0; + + /** Sets the zero pose for the seated tracker coordinate system to the current position and yaw of the HMD. After + * ResetSeatedZeroPose all GetDeviceToAbsoluteTrackingPose calls that pass TrackingUniverseSeated as the origin + * will be relative to this new zero pose. The new zero coordinate system will not change the fact that the Y axis + * is up in the real world, so the next pose returned from GetDeviceToAbsoluteTrackingPose after a call to + * ResetSeatedZeroPose may not be exactly an identity matrix. + * + * NOTE: This function overrides the user's previously saved seated zero pose and should only be called as the result of a user action. + * Users are also able to set their seated zero pose via the OpenVR Dashboard. + **/ + virtual void ResetSeatedZeroPose() = 0; + + /** Returns the transform from the seated zero pose to the standing absolute tracking system. This allows + * applications to represent the seated origin to used or transform object positions from one coordinate + * system to the other. + * + * The seated origin may or may not be inside the Play Area or Collision Bounds returned by IVRChaperone. Its position + * depends on what the user has set from the Dashboard settings and previous calls to ResetSeatedZeroPose. */ + virtual HmdMatrix34_t GetSeatedZeroPoseToStandingAbsoluteTrackingPose() = 0; + + /** Returns the transform from the tracking origin to the standing absolute tracking system. This allows + * applications to convert from raw tracking space to the calibrated standing coordinate system. */ + virtual HmdMatrix34_t GetRawZeroPoseToStandingAbsoluteTrackingPose() = 0; + + /** Get a sorted array of device indices of a given class of tracked devices (e.g. controllers). Devices are sorted right to left + * relative to the specified tracked device (default: hmd -- pass in -1 for absolute tracking space). Returns the number of devices + * in the list, or the size of the array needed if not large enough. */ + virtual uint32_t GetSortedTrackedDeviceIndicesOfClass( ETrackedDeviceClass eTrackedDeviceClass, VR_ARRAY_COUNT(unTrackedDeviceIndexArrayCount) vr::TrackedDeviceIndex_t *punTrackedDeviceIndexArray, uint32_t unTrackedDeviceIndexArrayCount, vr::TrackedDeviceIndex_t unRelativeToTrackedDeviceIndex = k_unTrackedDeviceIndex_Hmd ) = 0; + + /** Returns the level of activity on the device. */ + virtual EDeviceActivityLevel GetTrackedDeviceActivityLevel( vr::TrackedDeviceIndex_t unDeviceId ) = 0; + + /** Convenience utility to apply the specified transform to the specified pose. + * This properly transforms all pose components, including velocity and angular velocity + */ + virtual void ApplyTransform( TrackedDevicePose_t *pOutputPose, const TrackedDevicePose_t *pTrackedDevicePose, const HmdMatrix34_t *pTransform ) = 0; + + /** Returns the device index associated with a specific role, for example the left hand or the right hand. */ + virtual vr::TrackedDeviceIndex_t GetTrackedDeviceIndexForControllerRole( vr::ETrackedControllerRole unDeviceType ) = 0; + + /** Returns the controller type associated with a device index. */ + virtual vr::ETrackedControllerRole GetControllerRoleForTrackedDeviceIndex( vr::TrackedDeviceIndex_t unDeviceIndex ) = 0; + + // ------------------------------------ + // Property methods + // ------------------------------------ + + /** Returns the device class of a tracked device. If there has not been a device connected in this slot + * since the application started this function will return TrackedDevice_Invalid. For previous detected + * devices the function will return the previously observed device class. + * + * To determine which devices exist on the system, just loop from 0 to k_unMaxTrackedDeviceCount and check + * the device class. Every device with something other than TrackedDevice_Invalid is associated with an + * actual tracked device. */ + virtual ETrackedDeviceClass GetTrackedDeviceClass( vr::TrackedDeviceIndex_t unDeviceIndex ) = 0; + + /** Returns true if there is a device connected in this slot. */ + virtual bool IsTrackedDeviceConnected( vr::TrackedDeviceIndex_t unDeviceIndex ) = 0; + + /** Returns a bool property. If the device index is not valid or the property is not a bool type this function will return false. */ + virtual bool GetBoolTrackedDeviceProperty( vr::TrackedDeviceIndex_t unDeviceIndex, ETrackedDeviceProperty prop, ETrackedPropertyError *pError = 0L ) = 0; + + /** Returns a float property. If the device index is not valid or the property is not a float type this function will return 0. */ + virtual float GetFloatTrackedDeviceProperty( vr::TrackedDeviceIndex_t unDeviceIndex, ETrackedDeviceProperty prop, ETrackedPropertyError *pError = 0L ) = 0; + + /** Returns an int property. If the device index is not valid or the property is not a int type this function will return 0. */ + virtual int32_t GetInt32TrackedDeviceProperty( vr::TrackedDeviceIndex_t unDeviceIndex, ETrackedDeviceProperty prop, ETrackedPropertyError *pError = 0L ) = 0; + + /** Returns a uint64 property. If the device index is not valid or the property is not a uint64 type this function will return 0. */ + virtual uint64_t GetUint64TrackedDeviceProperty( vr::TrackedDeviceIndex_t unDeviceIndex, ETrackedDeviceProperty prop, ETrackedPropertyError *pError = 0L ) = 0; + + /** Returns a matrix property. If the device index is not valid or the property is not a matrix type, this function will return identity. */ + virtual HmdMatrix34_t GetMatrix34TrackedDeviceProperty( vr::TrackedDeviceIndex_t unDeviceIndex, ETrackedDeviceProperty prop, ETrackedPropertyError *pError = 0L ) = 0; + + /** Returns an array of one type of property. If the device index is not valid or the property is not a single value or an array of the specified type, + * this function will return 0. Otherwise it returns the number of bytes necessary to hold the array of properties. If unBufferSize is + * greater than the returned size and pBuffer is non-NULL, pBuffer is filled with the contents of array of properties. */ + virtual uint32_t GetArrayTrackedDeviceProperty( vr::TrackedDeviceIndex_t unDeviceIndex, ETrackedDeviceProperty prop, PropertyTypeTag_t propType, void *pBuffer, uint32_t unBufferSize, ETrackedPropertyError *pError = 0L ) = 0; + + /** Returns a string property. If the device index is not valid or the property is not a string type this function will + * return 0. Otherwise it returns the length of the number of bytes necessary to hold this string including the trailing + * null. Strings will always fit in buffers of k_unMaxPropertyStringSize characters. */ + virtual uint32_t GetStringTrackedDeviceProperty( vr::TrackedDeviceIndex_t unDeviceIndex, ETrackedDeviceProperty prop, VR_OUT_STRING() char *pchValue, uint32_t unBufferSize, ETrackedPropertyError *pError = 0L ) = 0; + + /** returns a string that corresponds with the specified property error. The string will be the name + * of the error enum value for all valid error codes */ + virtual const char *GetPropErrorNameFromEnum( ETrackedPropertyError error ) = 0; + + // ------------------------------------ + // Event methods + // ------------------------------------ + + /** Returns true and fills the event with the next event on the queue if there is one. If there are no events + * this method returns false. uncbVREvent should be the size in bytes of the VREvent_t struct */ + virtual bool PollNextEvent( VREvent_t *pEvent, uint32_t uncbVREvent ) = 0; + + /** Returns true and fills the event with the next event on the queue if there is one. If there are no events + * this method returns false. Fills in the pose of the associated tracked device in the provided pose struct. + * This pose will always be older than the call to this function and should not be used to render the device. + uncbVREvent should be the size in bytes of the VREvent_t struct */ + virtual bool PollNextEventWithPose( ETrackingUniverseOrigin eOrigin, VREvent_t *pEvent, uint32_t uncbVREvent, vr::TrackedDevicePose_t *pTrackedDevicePose ) = 0; + + /** returns the name of an EVREvent enum value */ + virtual const char *GetEventTypeNameFromEnum( EVREventType eType ) = 0; + + // ------------------------------------ + // Rendering helper methods + // ------------------------------------ + + /** Returns the hidden area mesh for the current HMD. The pixels covered by this mesh will never be seen by the user after the lens distortion is + * applied based on visibility to the panels. If this HMD does not have a hidden area mesh, the vertex data and count will be NULL and 0 respectively. + * This mesh is meant to be rendered into the stencil buffer (or into the depth buffer setting nearz) before rendering each eye's view. + * This will improve performance by letting the GPU early-reject pixels the user will never see before running the pixel shader. + * NOTE: Render this mesh with backface culling disabled since the winding order of the vertices can be different per-HMD or per-eye. + * Setting the bInverse argument to true will produce the visible area mesh that is commonly used in place of full-screen quads. The visible area mesh covers all of the pixels the hidden area mesh does not cover. + * Setting the bLineLoop argument will return a line loop of vertices in HiddenAreaMesh_t->pVertexData with HiddenAreaMesh_t->unTriangleCount set to the number of vertices. + */ + virtual HiddenAreaMesh_t GetHiddenAreaMesh( EVREye eEye, EHiddenAreaMeshType type = k_eHiddenAreaMesh_Standard ) = 0; + + // ------------------------------------ + // Controller methods + // ------------------------------------ + + /** Fills the supplied struct with the current state of the controller. Returns false if the controller index + * is invalid. */ + virtual bool GetControllerState( vr::TrackedDeviceIndex_t unControllerDeviceIndex, vr::VRControllerState_t *pControllerState, uint32_t unControllerStateSize ) = 0; + + /** fills the supplied struct with the current state of the controller and the provided pose with the pose of + * the controller when the controller state was updated most recently. Use this form if you need a precise controller + * pose as input to your application when the user presses or releases a button. */ + virtual bool GetControllerStateWithPose( ETrackingUniverseOrigin eOrigin, vr::TrackedDeviceIndex_t unControllerDeviceIndex, vr::VRControllerState_t *pControllerState, uint32_t unControllerStateSize, TrackedDevicePose_t *pTrackedDevicePose ) = 0; + + /** Trigger a single haptic pulse on a controller. After this call the application may not trigger another haptic pulse on this controller + * and axis combination for 5ms. */ + virtual void TriggerHapticPulse( vr::TrackedDeviceIndex_t unControllerDeviceIndex, uint32_t unAxisId, unsigned short usDurationMicroSec ) = 0; + + /** returns the name of an EVRButtonId enum value */ + virtual const char *GetButtonIdNameFromEnum( EVRButtonId eButtonId ) = 0; + + /** returns the name of an EVRControllerAxisType enum value */ + virtual const char *GetControllerAxisTypeNameFromEnum( EVRControllerAxisType eAxisType ) = 0; + + /** Returns true if this application is receiving input from the system. This would return false if + * system-related functionality is consuming the input stream. */ + virtual bool IsInputAvailable() = 0; + + /** Returns true SteamVR is drawing controllers on top of the application. Applications should consider + * not drawing anything attached to the user's hands in this case. */ + virtual bool IsSteamVRDrawingControllers() = 0; + + /** Returns true if the user has put SteamVR into a mode that is distracting them from the application. + * For applications where this is appropriate, the application should pause ongoing activity. */ + virtual bool ShouldApplicationPause() = 0; + + /** Returns true if SteamVR is doing significant rendering work and the game should do what it can to reduce + * its own workload. One common way to do this is to reduce the size of the render target provided for each eye. */ + virtual bool ShouldApplicationReduceRenderingWork() = 0; + + // ------------------------------------ + // Debug Methods + // ------------------------------------ + + /** Sends a request to the driver for the specified device and returns the response. The maximum response size is 32k, + * but this method can be called with a smaller buffer. If the response exceeds the size of the buffer, it is truncated. + * The size of the response including its terminating null is returned. */ + virtual uint32_t DriverDebugRequest( vr::TrackedDeviceIndex_t unDeviceIndex, const char *pchRequest, VR_OUT_STRING() char *pchResponseBuffer, uint32_t unResponseBufferSize ) = 0; + + // ------------------------------------ + // Firmware methods + // ------------------------------------ + + /** Performs the actual firmware update if applicable. + * The following events will be sent, if VRFirmwareError_None was returned: VREvent_FirmwareUpdateStarted, VREvent_FirmwareUpdateFinished + * Use the properties Prop_Firmware_UpdateAvailable_Bool, Prop_Firmware_ManualUpdate_Bool, and Prop_Firmware_ManualUpdateURL_String + * to figure our whether a firmware update is available, and to figure out whether its a manual update + * Prop_Firmware_ManualUpdateURL_String should point to an URL describing the manual update process */ + virtual vr::EVRFirmwareError PerformFirmwareUpdate( vr::TrackedDeviceIndex_t unDeviceIndex ) = 0; + + // ------------------------------------ + // Application life cycle methods + // ------------------------------------ + + /** Call this to acknowledge to the system that VREvent_Quit has been received and that the process is exiting. + * This extends the timeout until the process is killed. */ + virtual void AcknowledgeQuit_Exiting() = 0; + + /** Call this to tell the system that the user is being prompted to save data. This + * halts the timeout and dismisses the dashboard (if it was up). Applications should be sure to actually + * prompt the user to save and then exit afterward, otherwise the user will be left in a confusing state. */ + virtual void AcknowledgeQuit_UserPrompt() = 0; + +}; + +static const char * const IVRSystem_Version = "IVRSystem_019"; + +} + + +// ivrapplications.h +namespace vr +{ + + /** Used for all errors reported by the IVRApplications interface */ + enum EVRApplicationError + { + VRApplicationError_None = 0, + + VRApplicationError_AppKeyAlreadyExists = 100, // Only one application can use any given key + VRApplicationError_NoManifest = 101, // the running application does not have a manifest + VRApplicationError_NoApplication = 102, // No application is running + VRApplicationError_InvalidIndex = 103, + VRApplicationError_UnknownApplication = 104, // the application could not be found + VRApplicationError_IPCFailed = 105, // An IPC failure caused the request to fail + VRApplicationError_ApplicationAlreadyRunning = 106, + VRApplicationError_InvalidManifest = 107, + VRApplicationError_InvalidApplication = 108, + VRApplicationError_LaunchFailed = 109, // the process didn't start + VRApplicationError_ApplicationAlreadyStarting = 110, // the system was already starting the same application + VRApplicationError_LaunchInProgress = 111, // The system was already starting a different application + VRApplicationError_OldApplicationQuitting = 112, + VRApplicationError_TransitionAborted = 113, + VRApplicationError_IsTemplate = 114, // error when you try to call LaunchApplication() on a template type app (use LaunchTemplateApplication) + VRApplicationError_SteamVRIsExiting = 115, + + VRApplicationError_BufferTooSmall = 200, // The provided buffer was too small to fit the requested data + VRApplicationError_PropertyNotSet = 201, // The requested property was not set + VRApplicationError_UnknownProperty = 202, + VRApplicationError_InvalidParameter = 203, + }; + + /** The maximum length of an application key */ + static const uint32_t k_unMaxApplicationKeyLength = 128; + + /** these are the properties available on applications. */ + enum EVRApplicationProperty + { + VRApplicationProperty_Name_String = 0, + + VRApplicationProperty_LaunchType_String = 11, + VRApplicationProperty_WorkingDirectory_String = 12, + VRApplicationProperty_BinaryPath_String = 13, + VRApplicationProperty_Arguments_String = 14, + VRApplicationProperty_URL_String = 15, + + VRApplicationProperty_Description_String = 50, + VRApplicationProperty_NewsURL_String = 51, + VRApplicationProperty_ImagePath_String = 52, + VRApplicationProperty_Source_String = 53, + VRApplicationProperty_ActionManifestURL_String = 54, + + VRApplicationProperty_IsDashboardOverlay_Bool = 60, + VRApplicationProperty_IsTemplate_Bool = 61, + VRApplicationProperty_IsInstanced_Bool = 62, + VRApplicationProperty_IsInternal_Bool = 63, + VRApplicationProperty_WantsCompositorPauseInStandby_Bool = 64, + + VRApplicationProperty_LastLaunchTime_Uint64 = 70, + }; + + /** These are states the scene application startup process will go through. */ + enum EVRApplicationTransitionState + { + VRApplicationTransition_None = 0, + + VRApplicationTransition_OldAppQuitSent = 10, + VRApplicationTransition_WaitingForExternalLaunch = 11, + + VRApplicationTransition_NewAppLaunched = 20, + }; + + struct AppOverrideKeys_t + { + const char *pchKey; + const char *pchValue; + }; + + /** Currently recognized mime types */ + static const char * const k_pch_MimeType_HomeApp = "vr/home"; + static const char * const k_pch_MimeType_GameTheater = "vr/game_theater"; + + class IVRApplications + { + public: + + // --------------- Application management --------------- // + + /** Adds an application manifest to the list to load when building the list of installed applications. + * Temporary manifests are not automatically loaded */ + virtual EVRApplicationError AddApplicationManifest( const char *pchApplicationManifestFullPath, bool bTemporary = false ) = 0; + + /** Removes an application manifest from the list to load when building the list of installed applications. */ + virtual EVRApplicationError RemoveApplicationManifest( const char *pchApplicationManifestFullPath ) = 0; + + /** Returns true if an application is installed */ + virtual bool IsApplicationInstalled( const char *pchAppKey ) = 0; + + /** Returns the number of applications available in the list */ + virtual uint32_t GetApplicationCount() = 0; + + /** Returns the key of the specified application. The index is at least 0 and is less than the return + * value of GetApplicationCount(). The buffer should be at least k_unMaxApplicationKeyLength in order to + * fit the key. */ + virtual EVRApplicationError GetApplicationKeyByIndex( uint32_t unApplicationIndex, VR_OUT_STRING() char *pchAppKeyBuffer, uint32_t unAppKeyBufferLen ) = 0; + + /** Returns the key of the application for the specified Process Id. The buffer should be at least + * k_unMaxApplicationKeyLength in order to fit the key. */ + virtual EVRApplicationError GetApplicationKeyByProcessId( uint32_t unProcessId, VR_OUT_STRING() char *pchAppKeyBuffer, uint32_t unAppKeyBufferLen ) = 0; + + /** Launches the application. The existing scene application will exit and then the new application will start. + * This call is not valid for dashboard overlay applications. */ + virtual EVRApplicationError LaunchApplication( const char *pchAppKey ) = 0; + + /** Launches an instance of an application of type template, with its app key being pchNewAppKey (which must be unique) and optionally override sections + * from the manifest file via AppOverrideKeys_t + */ + virtual EVRApplicationError LaunchTemplateApplication( const char *pchTemplateAppKey, const char *pchNewAppKey, VR_ARRAY_COUNT( unKeys ) const AppOverrideKeys_t *pKeys, uint32_t unKeys ) = 0; + + /** launches the application currently associated with this mime type and passes it the option args, typically the filename or object name of the item being launched */ + virtual vr::EVRApplicationError LaunchApplicationFromMimeType( const char *pchMimeType, const char *pchArgs ) = 0; + + /** Launches the dashboard overlay application if it is not already running. This call is only valid for + * dashboard overlay applications. */ + virtual EVRApplicationError LaunchDashboardOverlay( const char *pchAppKey ) = 0; + + /** Cancel a pending launch for an application */ + virtual bool CancelApplicationLaunch( const char *pchAppKey ) = 0; + + /** Identifies a running application. OpenVR can't always tell which process started in response + * to a URL. This function allows a URL handler (or the process itself) to identify the app key + * for the now running application. Passing a process ID of 0 identifies the calling process. + * The application must be one that's known to the system via a call to AddApplicationManifest. */ + virtual EVRApplicationError IdentifyApplication( uint32_t unProcessId, const char *pchAppKey ) = 0; + + /** Returns the process ID for an application. Return 0 if the application was not found or is not running. */ + virtual uint32_t GetApplicationProcessId( const char *pchAppKey ) = 0; + + /** Returns a string for an applications error */ + virtual const char *GetApplicationsErrorNameFromEnum( EVRApplicationError error ) = 0; + + // --------------- Application properties --------------- // + + /** Returns a value for an application property. The required buffer size to fit this value will be returned. */ + virtual uint32_t GetApplicationPropertyString( const char *pchAppKey, EVRApplicationProperty eProperty, VR_OUT_STRING() char *pchPropertyValueBuffer, uint32_t unPropertyValueBufferLen, EVRApplicationError *peError = nullptr ) = 0; + + /** Returns a bool value for an application property. Returns false in all error cases. */ + virtual bool GetApplicationPropertyBool( const char *pchAppKey, EVRApplicationProperty eProperty, EVRApplicationError *peError = nullptr ) = 0; + + /** Returns a uint64 value for an application property. Returns 0 in all error cases. */ + virtual uint64_t GetApplicationPropertyUint64( const char *pchAppKey, EVRApplicationProperty eProperty, EVRApplicationError *peError = nullptr ) = 0; + + /** Sets the application auto-launch flag. This is only valid for applications which return true for VRApplicationProperty_IsDashboardOverlay_Bool. */ + virtual EVRApplicationError SetApplicationAutoLaunch( const char *pchAppKey, bool bAutoLaunch ) = 0; + + /** Gets the application auto-launch flag. This is only valid for applications which return true for VRApplicationProperty_IsDashboardOverlay_Bool. */ + virtual bool GetApplicationAutoLaunch( const char *pchAppKey ) = 0; + + /** Adds this mime-type to the list of supported mime types for this application*/ + virtual EVRApplicationError SetDefaultApplicationForMimeType( const char *pchAppKey, const char *pchMimeType ) = 0; + + /** return the app key that will open this mime type */ + virtual bool GetDefaultApplicationForMimeType( const char *pchMimeType, VR_OUT_STRING() char *pchAppKeyBuffer, uint32_t unAppKeyBufferLen ) = 0; + + /** Get the list of supported mime types for this application, comma-delimited */ + virtual bool GetApplicationSupportedMimeTypes( const char *pchAppKey, VR_OUT_STRING() char *pchMimeTypesBuffer, uint32_t unMimeTypesBuffer ) = 0; + + /** Get the list of app-keys that support this mime type, comma-delimited, the return value is number of bytes you need to return the full string */ + virtual uint32_t GetApplicationsThatSupportMimeType( const char *pchMimeType, VR_OUT_STRING() char *pchAppKeysThatSupportBuffer, uint32_t unAppKeysThatSupportBuffer ) = 0; + + /** Get the args list from an app launch that had the process already running, you call this when you get a VREvent_ApplicationMimeTypeLoad */ + virtual uint32_t GetApplicationLaunchArguments( uint32_t unHandle, VR_OUT_STRING() char *pchArgs, uint32_t unArgs ) = 0; + + // --------------- Transition methods --------------- // + + /** Returns the app key for the application that is starting up */ + virtual EVRApplicationError GetStartingApplication( VR_OUT_STRING() char *pchAppKeyBuffer, uint32_t unAppKeyBufferLen ) = 0; + + /** Returns the application transition state */ + virtual EVRApplicationTransitionState GetTransitionState() = 0; + + /** Returns errors that would prevent the specified application from launching immediately. Calling this function will + * cause the current scene application to quit, so only call it when you are actually about to launch something else. + * What the caller should do about these failures depends on the failure: + * VRApplicationError_OldApplicationQuitting - An existing application has been told to quit. Wait for a VREvent_ProcessQuit + * and try again. + * VRApplicationError_ApplicationAlreadyStarting - This application is already starting. This is a permanent failure. + * VRApplicationError_LaunchInProgress - A different application is already starting. This is a permanent failure. + * VRApplicationError_None - Go ahead and launch. Everything is clear. + */ + virtual EVRApplicationError PerformApplicationPrelaunchCheck( const char *pchAppKey ) = 0; + + /** Returns a string for an application transition state */ + virtual const char *GetApplicationsTransitionStateNameFromEnum( EVRApplicationTransitionState state ) = 0; + + /** Returns true if the outgoing scene app has requested a save prompt before exiting */ + virtual bool IsQuitUserPromptRequested() = 0; + + /** Starts a subprocess within the calling application. This + * suppresses all application transition UI and automatically identifies the new executable + * as part of the same application. On success the calling process should exit immediately. + * If working directory is NULL or "" the directory portion of the binary path will be + * the working directory. */ + virtual EVRApplicationError LaunchInternalProcess( const char *pchBinaryPath, const char *pchArguments, const char *pchWorkingDirectory ) = 0; + + /** Returns the current scene process ID according to the application system. A scene process will get scene + * focus once it starts rendering, but it will appear here once it calls VR_Init with the Scene application + * type. */ + virtual uint32_t GetCurrentSceneProcessId() = 0; + }; + + static const char * const IVRApplications_Version = "IVRApplications_006"; + +} // namespace vr + +// ivrsettings.h +namespace vr +{ + enum EVRSettingsError + { + VRSettingsError_None = 0, + VRSettingsError_IPCFailed = 1, + VRSettingsError_WriteFailed = 2, + VRSettingsError_ReadFailed = 3, + VRSettingsError_JsonParseFailed = 4, + VRSettingsError_UnsetSettingHasNoDefault = 5, // This will be returned if the setting does not appear in the appropriate default file and has not been set + }; + + // The maximum length of a settings key + static const uint32_t k_unMaxSettingsKeyLength = 128; + + class IVRSettings + { + public: + virtual const char *GetSettingsErrorNameFromEnum( EVRSettingsError eError ) = 0; + + // Returns true if file sync occurred (force or settings dirty) + virtual bool Sync( bool bForce = false, EVRSettingsError *peError = nullptr ) = 0; + + virtual void SetBool( const char *pchSection, const char *pchSettingsKey, bool bValue, EVRSettingsError *peError = nullptr ) = 0; + virtual void SetInt32( const char *pchSection, const char *pchSettingsKey, int32_t nValue, EVRSettingsError *peError = nullptr ) = 0; + virtual void SetFloat( const char *pchSection, const char *pchSettingsKey, float flValue, EVRSettingsError *peError = nullptr ) = 0; + virtual void SetString( const char *pchSection, const char *pchSettingsKey, const char *pchValue, EVRSettingsError *peError = nullptr ) = 0; + + // Users of the system need to provide a proper default in default.vrsettings in the resources/settings/ directory + // of either the runtime or the driver_xxx directory. Otherwise the default will be false, 0, 0.0 or "" + virtual bool GetBool( const char *pchSection, const char *pchSettingsKey, EVRSettingsError *peError = nullptr ) = 0; + virtual int32_t GetInt32( const char *pchSection, const char *pchSettingsKey, EVRSettingsError *peError = nullptr ) = 0; + virtual float GetFloat( const char *pchSection, const char *pchSettingsKey, EVRSettingsError *peError = nullptr ) = 0; + virtual void GetString( const char *pchSection, const char *pchSettingsKey, VR_OUT_STRING() char *pchValue, uint32_t unValueLen, EVRSettingsError *peError = nullptr ) = 0; + + virtual void RemoveSection( const char *pchSection, EVRSettingsError *peError = nullptr ) = 0; + virtual void RemoveKeyInSection( const char *pchSection, const char *pchSettingsKey, EVRSettingsError *peError = nullptr ) = 0; + }; + + //----------------------------------------------------------------------------- + static const char * const IVRSettings_Version = "IVRSettings_002"; + + //----------------------------------------------------------------------------- + // steamvr keys + static const char * const k_pch_SteamVR_Section = "steamvr"; + static const char * const k_pch_SteamVR_RequireHmd_String = "requireHmd"; + static const char * const k_pch_SteamVR_ForcedDriverKey_String = "forcedDriver"; + static const char * const k_pch_SteamVR_ForcedHmdKey_String = "forcedHmd"; + static const char * const k_pch_SteamVR_DisplayDebug_Bool = "displayDebug"; + static const char * const k_pch_SteamVR_DebugProcessPipe_String = "debugProcessPipe"; + static const char * const k_pch_SteamVR_DisplayDebugX_Int32 = "displayDebugX"; + static const char * const k_pch_SteamVR_DisplayDebugY_Int32 = "displayDebugY"; + static const char * const k_pch_SteamVR_SendSystemButtonToAllApps_Bool= "sendSystemButtonToAllApps"; + static const char * const k_pch_SteamVR_LogLevel_Int32 = "loglevel"; + static const char * const k_pch_SteamVR_IPD_Float = "ipd"; + static const char * const k_pch_SteamVR_Background_String = "background"; + static const char * const k_pch_SteamVR_BackgroundUseDomeProjection_Bool = "backgroundUseDomeProjection"; + static const char * const k_pch_SteamVR_BackgroundCameraHeight_Float = "backgroundCameraHeight"; + static const char * const k_pch_SteamVR_BackgroundDomeRadius_Float = "backgroundDomeRadius"; + static const char * const k_pch_SteamVR_GridColor_String = "gridColor"; + static const char * const k_pch_SteamVR_PlayAreaColor_String = "playAreaColor"; + static const char * const k_pch_SteamVR_ShowStage_Bool = "showStage"; + static const char * const k_pch_SteamVR_ActivateMultipleDrivers_Bool = "activateMultipleDrivers"; + static const char * const k_pch_SteamVR_DirectMode_Bool = "directMode"; + static const char * const k_pch_SteamVR_DirectModeEdidVid_Int32 = "directModeEdidVid"; + static const char * const k_pch_SteamVR_DirectModeEdidPid_Int32 = "directModeEdidPid"; + static const char * const k_pch_SteamVR_UsingSpeakers_Bool = "usingSpeakers"; + static const char * const k_pch_SteamVR_SpeakersForwardYawOffsetDegrees_Float = "speakersForwardYawOffsetDegrees"; + static const char * const k_pch_SteamVR_BaseStationPowerManagement_Bool = "basestationPowerManagement"; + static const char * const k_pch_SteamVR_NeverKillProcesses_Bool = "neverKillProcesses"; + static const char * const k_pch_SteamVR_SupersampleScale_Float = "supersampleScale"; + static const char * const k_pch_SteamVR_AllowAsyncReprojection_Bool = "allowAsyncReprojection"; + static const char * const k_pch_SteamVR_AllowReprojection_Bool = "allowInterleavedReprojection"; + static const char * const k_pch_SteamVR_ForceReprojection_Bool = "forceReprojection"; + static const char * const k_pch_SteamVR_ForceFadeOnBadTracking_Bool = "forceFadeOnBadTracking"; + static const char * const k_pch_SteamVR_DefaultMirrorView_Int32 = "defaultMirrorView"; + static const char * const k_pch_SteamVR_ShowMirrorView_Bool = "showMirrorView"; + static const char * const k_pch_SteamVR_MirrorViewGeometry_String = "mirrorViewGeometry"; + static const char * const k_pch_SteamVR_StartMonitorFromAppLaunch = "startMonitorFromAppLaunch"; + static const char * const k_pch_SteamVR_StartCompositorFromAppLaunch_Bool = "startCompositorFromAppLaunch"; + static const char * const k_pch_SteamVR_StartDashboardFromAppLaunch_Bool = "startDashboardFromAppLaunch"; + static const char * const k_pch_SteamVR_StartOverlayAppsFromDashboard_Bool = "startOverlayAppsFromDashboard"; + static const char * const k_pch_SteamVR_EnableHomeApp = "enableHomeApp"; + static const char * const k_pch_SteamVR_CycleBackgroundImageTimeSec_Int32 = "CycleBackgroundImageTimeSec"; + static const char * const k_pch_SteamVR_RetailDemo_Bool = "retailDemo"; + static const char * const k_pch_SteamVR_IpdOffset_Float = "ipdOffset"; + static const char * const k_pch_SteamVR_AllowSupersampleFiltering_Bool = "allowSupersampleFiltering"; + static const char * const k_pch_SteamVR_SupersampleManualOverride_Bool = "supersampleManualOverride"; + static const char * const k_pch_SteamVR_EnableLinuxVulkanAsync_Bool = "enableLinuxVulkanAsync"; + static const char * const k_pch_SteamVR_AllowDisplayLockedMode_Bool = "allowDisplayLockedMode"; + static const char * const k_pch_SteamVR_HaveStartedTutorialForNativeChaperoneDriver_Bool = "haveStartedTutorialForNativeChaperoneDriver"; + static const char * const k_pch_SteamVR_ForceWindows32bitVRMonitor = "forceWindows32BitVRMonitor"; + static const char * const k_pch_SteamVR_DebugInput = "debugInput"; + static const char * const k_pch_SteamVR_LegacyInputRebinding = "legacyInputRebinding"; + static const char * const k_pch_SteamVR_DebugInputBinding = "debugInputBinding"; + + //----------------------------------------------------------------------------- + // lighthouse keys + static const char * const k_pch_Lighthouse_Section = "driver_lighthouse"; + static const char * const k_pch_Lighthouse_DisableIMU_Bool = "disableimu"; + static const char * const k_pch_Lighthouse_DisableIMUExceptHMD_Bool = "disableimuexcepthmd"; + static const char * const k_pch_Lighthouse_UseDisambiguation_String = "usedisambiguation"; + static const char * const k_pch_Lighthouse_DisambiguationDebug_Int32 = "disambiguationdebug"; + static const char * const k_pch_Lighthouse_PrimaryBasestation_Int32 = "primarybasestation"; + static const char * const k_pch_Lighthouse_DBHistory_Bool = "dbhistory"; + static const char * const k_pch_Lighthouse_EnableBluetooth_Bool = "enableBluetooth"; + static const char * const k_pch_Lighthouse_PowerManagedBaseStations_String = "PowerManagedBaseStations"; + + //----------------------------------------------------------------------------- + // null keys + static const char * const k_pch_Null_Section = "driver_null"; + static const char * const k_pch_Null_SerialNumber_String = "serialNumber"; + static const char * const k_pch_Null_ModelNumber_String = "modelNumber"; + static const char * const k_pch_Null_WindowX_Int32 = "windowX"; + static const char * const k_pch_Null_WindowY_Int32 = "windowY"; + static const char * const k_pch_Null_WindowWidth_Int32 = "windowWidth"; + static const char * const k_pch_Null_WindowHeight_Int32 = "windowHeight"; + static const char * const k_pch_Null_RenderWidth_Int32 = "renderWidth"; + static const char * const k_pch_Null_RenderHeight_Int32 = "renderHeight"; + static const char * const k_pch_Null_SecondsFromVsyncToPhotons_Float = "secondsFromVsyncToPhotons"; + static const char * const k_pch_Null_DisplayFrequency_Float = "displayFrequency"; + + //----------------------------------------------------------------------------- + // user interface keys + static const char * const k_pch_UserInterface_Section = "userinterface"; + static const char * const k_pch_UserInterface_StatusAlwaysOnTop_Bool = "StatusAlwaysOnTop"; + static const char * const k_pch_UserInterface_MinimizeToTray_Bool = "MinimizeToTray"; + static const char * const k_pch_UserInterface_Screenshots_Bool = "screenshots"; + static const char * const k_pch_UserInterface_ScreenshotType_Int = "screenshotType"; + + //----------------------------------------------------------------------------- + // notification keys + static const char * const k_pch_Notifications_Section = "notifications"; + static const char * const k_pch_Notifications_DoNotDisturb_Bool = "DoNotDisturb"; + + //----------------------------------------------------------------------------- + // keyboard keys + static const char * const k_pch_Keyboard_Section = "keyboard"; + static const char * const k_pch_Keyboard_TutorialCompletions = "TutorialCompletions"; + static const char * const k_pch_Keyboard_ScaleX = "ScaleX"; + static const char * const k_pch_Keyboard_ScaleY = "ScaleY"; + static const char * const k_pch_Keyboard_OffsetLeftX = "OffsetLeftX"; + static const char * const k_pch_Keyboard_OffsetRightX = "OffsetRightX"; + static const char * const k_pch_Keyboard_OffsetY = "OffsetY"; + static const char * const k_pch_Keyboard_Smoothing = "Smoothing"; + + //----------------------------------------------------------------------------- + // perf keys + static const char * const k_pch_Perf_Section = "perfcheck"; + static const char * const k_pch_Perf_HeuristicActive_Bool = "heuristicActive"; + static const char * const k_pch_Perf_NotifyInHMD_Bool = "warnInHMD"; + static const char * const k_pch_Perf_NotifyOnlyOnce_Bool = "warnOnlyOnce"; + static const char * const k_pch_Perf_AllowTimingStore_Bool = "allowTimingStore"; + static const char * const k_pch_Perf_SaveTimingsOnExit_Bool = "saveTimingsOnExit"; + static const char * const k_pch_Perf_TestData_Float = "perfTestData"; + static const char * const k_pch_Perf_LinuxGPUProfiling_Bool = "linuxGPUProfiling"; + + //----------------------------------------------------------------------------- + // collision bounds keys + static const char * const k_pch_CollisionBounds_Section = "collisionBounds"; + static const char * const k_pch_CollisionBounds_Style_Int32 = "CollisionBoundsStyle"; + static const char * const k_pch_CollisionBounds_GroundPerimeterOn_Bool = "CollisionBoundsGroundPerimeterOn"; + static const char * const k_pch_CollisionBounds_CenterMarkerOn_Bool = "CollisionBoundsCenterMarkerOn"; + static const char * const k_pch_CollisionBounds_PlaySpaceOn_Bool = "CollisionBoundsPlaySpaceOn"; + static const char * const k_pch_CollisionBounds_FadeDistance_Float = "CollisionBoundsFadeDistance"; + static const char * const k_pch_CollisionBounds_ColorGammaR_Int32 = "CollisionBoundsColorGammaR"; + static const char * const k_pch_CollisionBounds_ColorGammaG_Int32 = "CollisionBoundsColorGammaG"; + static const char * const k_pch_CollisionBounds_ColorGammaB_Int32 = "CollisionBoundsColorGammaB"; + static const char * const k_pch_CollisionBounds_ColorGammaA_Int32 = "CollisionBoundsColorGammaA"; + + //----------------------------------------------------------------------------- + // camera keys + static const char * const k_pch_Camera_Section = "camera"; + static const char * const k_pch_Camera_EnableCamera_Bool = "enableCamera"; + static const char * const k_pch_Camera_EnableCameraInDashboard_Bool = "enableCameraInDashboard"; + static const char * const k_pch_Camera_EnableCameraForCollisionBounds_Bool = "enableCameraForCollisionBounds"; + static const char * const k_pch_Camera_EnableCameraForRoomView_Bool = "enableCameraForRoomView"; + static const char * const k_pch_Camera_BoundsColorGammaR_Int32 = "cameraBoundsColorGammaR"; + static const char * const k_pch_Camera_BoundsColorGammaG_Int32 = "cameraBoundsColorGammaG"; + static const char * const k_pch_Camera_BoundsColorGammaB_Int32 = "cameraBoundsColorGammaB"; + static const char * const k_pch_Camera_BoundsColorGammaA_Int32 = "cameraBoundsColorGammaA"; + static const char * const k_pch_Camera_BoundsStrength_Int32 = "cameraBoundsStrength"; + static const char * const k_pch_Camera_RoomViewMode_Int32 = "cameraRoomViewMode"; + + //----------------------------------------------------------------------------- + // audio keys + static const char * const k_pch_audio_Section = "audio"; + static const char * const k_pch_audio_OnPlaybackDevice_String = "onPlaybackDevice"; + static const char * const k_pch_audio_OnRecordDevice_String = "onRecordDevice"; + static const char * const k_pch_audio_OnPlaybackMirrorDevice_String = "onPlaybackMirrorDevice"; + static const char * const k_pch_audio_OffPlaybackDevice_String = "offPlaybackDevice"; + static const char * const k_pch_audio_OffRecordDevice_String = "offRecordDevice"; + static const char * const k_pch_audio_VIVEHDMIGain = "viveHDMIGain"; + + //----------------------------------------------------------------------------- + // power management keys + static const char * const k_pch_Power_Section = "power"; + static const char * const k_pch_Power_PowerOffOnExit_Bool = "powerOffOnExit"; + static const char * const k_pch_Power_TurnOffScreensTimeout_Float = "turnOffScreensTimeout"; + static const char * const k_pch_Power_TurnOffControllersTimeout_Float = "turnOffControllersTimeout"; + static const char * const k_pch_Power_ReturnToWatchdogTimeout_Float = "returnToWatchdogTimeout"; + static const char * const k_pch_Power_AutoLaunchSteamVROnButtonPress = "autoLaunchSteamVROnButtonPress"; + static const char * const k_pch_Power_PauseCompositorOnStandby_Bool = "pauseCompositorOnStandby"; + + //----------------------------------------------------------------------------- + // dashboard keys + static const char * const k_pch_Dashboard_Section = "dashboard"; + static const char * const k_pch_Dashboard_EnableDashboard_Bool = "enableDashboard"; + static const char * const k_pch_Dashboard_ArcadeMode_Bool = "arcadeMode"; + static const char * const k_pch_Dashboard_EnableWebUI = "webUI"; + static const char * const k_pch_Dashboard_EnableWebUIDevTools = "webUIDevTools"; + + //----------------------------------------------------------------------------- + // model skin keys + static const char * const k_pch_modelskin_Section = "modelskins"; + + //----------------------------------------------------------------------------- + // driver keys - These could be checked in any driver_ section + static const char * const k_pch_Driver_Enable_Bool = "enable"; + + //----------------------------------------------------------------------------- + // web interface keys + static const char* const k_pch_WebInterface_Section = "WebInterface"; + static const char* const k_pch_WebInterface_WebPort_String = "WebPort"; + + //----------------------------------------------------------------------------- + // tracking overrides - keys are device paths, values are the device paths their + // tracking/pose information overrides + static const char* const k_pch_TrackingOverride_Section = "TrackingOverrides"; + + //----------------------------------------------------------------------------- + // per-app keys - the section name for these is the app key itself. Some of these are prefixed by the controller type + static const char* const k_pch_App_BindingAutosaveURLSuffix_String = "AutosaveURL"; + static const char* const k_pch_App_BindingCurrentURLSuffix_String = "CurrentURL"; + static const char* const k_pch_App_NeedToUpdateAutosaveSuffix_Bool = "NeedToUpdateAutosave"; + static const char* const k_pch_App_ActionManifestURL_String = "ActionManifestURL"; + +} // namespace vr + +// ivrchaperone.h +namespace vr +{ + +#pragma pack( push, 8 ) + +enum ChaperoneCalibrationState +{ + // OK! + ChaperoneCalibrationState_OK = 1, // Chaperone is fully calibrated and working correctly + + // Warnings + ChaperoneCalibrationState_Warning = 100, + ChaperoneCalibrationState_Warning_BaseStationMayHaveMoved = 101, // A base station thinks that it might have moved + ChaperoneCalibrationState_Warning_BaseStationRemoved = 102, // There are less base stations than when calibrated + ChaperoneCalibrationState_Warning_SeatedBoundsInvalid = 103, // Seated bounds haven't been calibrated for the current tracking center + + // Errors + ChaperoneCalibrationState_Error = 200, // The UniverseID is invalid + ChaperoneCalibrationState_Error_BaseStationUninitialized = 201, // Tracking center hasn't be calibrated for at least one of the base stations + ChaperoneCalibrationState_Error_BaseStationConflict = 202, // Tracking center is calibrated, but base stations disagree on the tracking space + ChaperoneCalibrationState_Error_PlayAreaInvalid = 203, // Play Area hasn't been calibrated for the current tracking center + ChaperoneCalibrationState_Error_CollisionBoundsInvalid = 204, // Collision Bounds haven't been calibrated for the current tracking center +}; + + +/** HIGH LEVEL TRACKING SPACE ASSUMPTIONS: +* 0,0,0 is the preferred standing area center. +* 0Y is the floor height. +* -Z is the preferred forward facing direction. */ +class IVRChaperone +{ +public: + + /** Get the current state of Chaperone calibration. This state can change at any time during a session due to physical base station changes. **/ + virtual ChaperoneCalibrationState GetCalibrationState() = 0; + + /** Returns the width and depth of the Play Area (formerly named Soft Bounds) in X and Z. + * Tracking space center (0,0,0) is the center of the Play Area. **/ + virtual bool GetPlayAreaSize( float *pSizeX, float *pSizeZ ) = 0; + + /** Returns the 4 corner positions of the Play Area (formerly named Soft Bounds). + * Corners are in counter-clockwise order. + * Standing center (0,0,0) is the center of the Play Area. + * It's a rectangle. + * 2 sides are parallel to the X axis and 2 sides are parallel to the Z axis. + * Height of every corner is 0Y (on the floor). **/ + virtual bool GetPlayAreaRect( HmdQuad_t *rect ) = 0; + + /** Reload Chaperone data from the .vrchap file on disk. */ + virtual void ReloadInfo( void ) = 0; + + /** Optionally give the chaperone system a hit about the color and brightness in the scene **/ + virtual void SetSceneColor( HmdColor_t color ) = 0; + + /** Get the current chaperone bounds draw color and brightness **/ + virtual void GetBoundsColor( HmdColor_t *pOutputColorArray, int nNumOutputColors, float flCollisionBoundsFadeDistance, HmdColor_t *pOutputCameraColor ) = 0; + + /** Determine whether the bounds are showing right now **/ + virtual bool AreBoundsVisible() = 0; + + /** Force the bounds to show, mostly for utilities **/ + virtual void ForceBoundsVisible( bool bForce ) = 0; +}; + +static const char * const IVRChaperone_Version = "IVRChaperone_003"; + +#pragma pack( pop ) + +} + +// ivrchaperonesetup.h +namespace vr +{ + +enum EChaperoneConfigFile +{ + EChaperoneConfigFile_Live = 1, // The live chaperone config, used by most applications and games + EChaperoneConfigFile_Temp = 2, // The temporary chaperone config, used to live-preview collision bounds in room setup +}; + +enum EChaperoneImportFlags +{ + EChaperoneImport_BoundsOnly = 0x0001, +}; + +/** Manages the working copy of the chaperone info. By default this will be the same as the +* live copy. Any changes made with this interface will stay in the working copy until +* CommitWorkingCopy() is called, at which point the working copy and the live copy will be +* the same again. */ +class IVRChaperoneSetup +{ +public: + + /** Saves the current working copy to disk */ + virtual bool CommitWorkingCopy( EChaperoneConfigFile configFile ) = 0; + + /** Reverts the working copy to match the live chaperone calibration. + * To modify existing data this MUST be do WHILE getting a non-error ChaperoneCalibrationStatus. + * Only after this should you do gets and sets on the existing data. */ + virtual void RevertWorkingCopy() = 0; + + /** Returns the width and depth of the Play Area (formerly named Soft Bounds) in X and Z from the working copy. + * Tracking space center (0,0,0) is the center of the Play Area. */ + virtual bool GetWorkingPlayAreaSize( float *pSizeX, float *pSizeZ ) = 0; + + /** Returns the 4 corner positions of the Play Area (formerly named Soft Bounds) from the working copy. + * Corners are in clockwise order. + * Tracking space center (0,0,0) is the center of the Play Area. + * It's a rectangle. + * 2 sides are parallel to the X axis and 2 sides are parallel to the Z axis. + * Height of every corner is 0Y (on the floor). **/ + virtual bool GetWorkingPlayAreaRect( HmdQuad_t *rect ) = 0; + + /** Returns the number of Quads if the buffer points to null. Otherwise it returns Quads + * into the buffer up to the max specified from the working copy. */ + virtual bool GetWorkingCollisionBoundsInfo( VR_OUT_ARRAY_COUNT(punQuadsCount) HmdQuad_t *pQuadsBuffer, uint32_t* punQuadsCount ) = 0; + + /** Returns the number of Quads if the buffer points to null. Otherwise it returns Quads + * into the buffer up to the max specified. */ + virtual bool GetLiveCollisionBoundsInfo( VR_OUT_ARRAY_COUNT(punQuadsCount) HmdQuad_t *pQuadsBuffer, uint32_t* punQuadsCount ) = 0; + + /** Returns the preferred seated position from the working copy. */ + virtual bool GetWorkingSeatedZeroPoseToRawTrackingPose( HmdMatrix34_t *pmatSeatedZeroPoseToRawTrackingPose ) = 0; + + /** Returns the standing origin from the working copy. */ + virtual bool GetWorkingStandingZeroPoseToRawTrackingPose( HmdMatrix34_t *pmatStandingZeroPoseToRawTrackingPose ) = 0; + + /** Sets the Play Area in the working copy. */ + virtual void SetWorkingPlayAreaSize( float sizeX, float sizeZ ) = 0; + + /** Sets the Collision Bounds in the working copy. */ + virtual void SetWorkingCollisionBoundsInfo( VR_ARRAY_COUNT(unQuadsCount) HmdQuad_t *pQuadsBuffer, uint32_t unQuadsCount ) = 0; + + /** Sets the preferred seated position in the working copy. */ + virtual void SetWorkingSeatedZeroPoseToRawTrackingPose( const HmdMatrix34_t *pMatSeatedZeroPoseToRawTrackingPose ) = 0; + + /** Sets the preferred standing position in the working copy. */ + virtual void SetWorkingStandingZeroPoseToRawTrackingPose( const HmdMatrix34_t *pMatStandingZeroPoseToRawTrackingPose ) = 0; + + /** Tear everything down and reload it from the file on disk */ + virtual void ReloadFromDisk( EChaperoneConfigFile configFile ) = 0; + + /** Returns the preferred seated position. */ + virtual bool GetLiveSeatedZeroPoseToRawTrackingPose( HmdMatrix34_t *pmatSeatedZeroPoseToRawTrackingPose ) = 0; + + virtual void SetWorkingCollisionBoundsTagsInfo( VR_ARRAY_COUNT(unTagCount) uint8_t *pTagsBuffer, uint32_t unTagCount ) = 0; + virtual bool GetLiveCollisionBoundsTagsInfo( VR_OUT_ARRAY_COUNT(punTagCount) uint8_t *pTagsBuffer, uint32_t *punTagCount ) = 0; + + virtual bool SetWorkingPhysicalBoundsInfo( VR_ARRAY_COUNT(unQuadsCount) HmdQuad_t *pQuadsBuffer, uint32_t unQuadsCount ) = 0; + virtual bool GetLivePhysicalBoundsInfo( VR_OUT_ARRAY_COUNT(punQuadsCount) HmdQuad_t *pQuadsBuffer, uint32_t* punQuadsCount ) = 0; + + virtual bool ExportLiveToBuffer( VR_OUT_STRING() char *pBuffer, uint32_t *pnBufferLength ) = 0; + virtual bool ImportFromBufferToWorking( const char *pBuffer, uint32_t nImportFlags ) = 0; +}; + +static const char * const IVRChaperoneSetup_Version = "IVRChaperoneSetup_005"; + + +} + +// ivrcompositor.h +namespace vr +{ + +#pragma pack( push, 8 ) + +/** Errors that can occur with the VR compositor */ +enum EVRCompositorError +{ + VRCompositorError_None = 0, + VRCompositorError_RequestFailed = 1, + VRCompositorError_IncompatibleVersion = 100, + VRCompositorError_DoNotHaveFocus = 101, + VRCompositorError_InvalidTexture = 102, + VRCompositorError_IsNotSceneApplication = 103, + VRCompositorError_TextureIsOnWrongDevice = 104, + VRCompositorError_TextureUsesUnsupportedFormat = 105, + VRCompositorError_SharedTexturesNotSupported = 106, + VRCompositorError_IndexOutOfRange = 107, + VRCompositorError_AlreadySubmitted = 108, + VRCompositorError_InvalidBounds = 109, +}; + +/** Timing mode passed to SetExplicitTimingMode(); see that function for documentation */ +enum EVRCompositorTimingMode +{ + VRCompositorTimingMode_Implicit = 0, + VRCompositorTimingMode_Explicit_RuntimePerformsPostPresentHandoff = 1, + VRCompositorTimingMode_Explicit_ApplicationPerformsPostPresentHandoff = 2, +}; + +const uint32_t VRCompositor_ReprojectionReason_Cpu = 0x01; +const uint32_t VRCompositor_ReprojectionReason_Gpu = 0x02; +const uint32_t VRCompositor_ReprojectionAsync = 0x04; // This flag indicates the async reprojection mode is active, + // but does not indicate if reprojection actually happened or not. + // Use the ReprojectionReason flags above to check if reprojection + // was actually applied (i.e. scene texture was reused). + // NumFramePresents > 1 also indicates the scene texture was reused, + // and also the number of times that it was presented in total. + +/** Provides a single frame's timing information to the app */ +struct Compositor_FrameTiming +{ + uint32_t m_nSize; // Set to sizeof( Compositor_FrameTiming ) + uint32_t m_nFrameIndex; + uint32_t m_nNumFramePresents; // number of times this frame was presented + uint32_t m_nNumMisPresented; // number of times this frame was presented on a vsync other than it was originally predicted to + uint32_t m_nNumDroppedFrames; // number of additional times previous frame was scanned out + uint32_t m_nReprojectionFlags; + + /** Absolute time reference for comparing frames. This aligns with the vsync that running start is relative to. */ + double m_flSystemTimeInSeconds; + + /** These times may include work from other processes due to OS scheduling. + * The fewer packets of work these are broken up into, the less likely this will happen. + * GPU work can be broken up by calling Flush. This can sometimes be useful to get the GPU started + * processing that work earlier in the frame. */ + float m_flPreSubmitGpuMs; // time spent rendering the scene (gpu work submitted between WaitGetPoses and second Submit) + float m_flPostSubmitGpuMs; // additional time spent rendering by application (e.g. companion window) + float m_flTotalRenderGpuMs; // time between work submitted immediately after present (ideally vsync) until the end of compositor submitted work + float m_flCompositorRenderGpuMs; // time spend performing distortion correction, rendering chaperone, overlays, etc. + float m_flCompositorRenderCpuMs; // time spent on cpu submitting the above work for this frame + float m_flCompositorIdleCpuMs; // time spent waiting for running start (application could have used this much more time) + + /** Miscellaneous measured intervals. */ + float m_flClientFrameIntervalMs; // time between calls to WaitGetPoses + float m_flPresentCallCpuMs; // time blocked on call to present (usually 0.0, but can go long) + float m_flWaitForPresentCpuMs; // time spent spin-waiting for frame index to change (not near-zero indicates wait object failure) + float m_flSubmitFrameMs; // time spent in IVRCompositor::Submit (not near-zero indicates driver issue) + + /** The following are all relative to this frame's SystemTimeInSeconds */ + float m_flWaitGetPosesCalledMs; + float m_flNewPosesReadyMs; + float m_flNewFrameReadyMs; // second call to IVRCompositor::Submit + float m_flCompositorUpdateStartMs; + float m_flCompositorUpdateEndMs; + float m_flCompositorRenderStartMs; + + vr::TrackedDevicePose_t m_HmdPose; // pose used by app to render this frame +}; + +/** Cumulative stats for current application. These are not cleared until a new app connects, +* but they do stop accumulating once the associated app disconnects. */ +struct Compositor_CumulativeStats +{ + uint32_t m_nPid; // Process id associated with these stats (may no longer be running). + uint32_t m_nNumFramePresents; // total number of times we called present (includes reprojected frames) + uint32_t m_nNumDroppedFrames; // total number of times an old frame was re-scanned out (without reprojection) + uint32_t m_nNumReprojectedFrames; // total number of times a frame was scanned out a second time (with reprojection) + + /** Values recorded at startup before application has fully faded in the first time. */ + uint32_t m_nNumFramePresentsOnStartup; + uint32_t m_nNumDroppedFramesOnStartup; + uint32_t m_nNumReprojectedFramesOnStartup; + + /** Applications may explicitly fade to the compositor. This is usually to handle level transitions, and loading often causes + * system wide hitches. The following stats are collected during this period. Does not include values recorded during startup. */ + uint32_t m_nNumLoading; + uint32_t m_nNumFramePresentsLoading; + uint32_t m_nNumDroppedFramesLoading; + uint32_t m_nNumReprojectedFramesLoading; + + /** If we don't get a new frame from the app in less than 2.5 frames, then we assume the app has hung and start + * fading back to the compositor. The following stats are a result of this, and are a subset of those recorded above. + * Does not include values recorded during start up or loading. */ + uint32_t m_nNumTimedOut; + uint32_t m_nNumFramePresentsTimedOut; + uint32_t m_nNumDroppedFramesTimedOut; + uint32_t m_nNumReprojectedFramesTimedOut; +}; + +#pragma pack( pop ) + +/** Allows the application to interact with the compositor */ +class IVRCompositor +{ +public: + /** Sets tracking space returned by WaitGetPoses */ + virtual void SetTrackingSpace( ETrackingUniverseOrigin eOrigin ) = 0; + + /** Gets current tracking space returned by WaitGetPoses */ + virtual ETrackingUniverseOrigin GetTrackingSpace() = 0; + + /** Scene applications should call this function to get poses to render with (and optionally poses predicted an additional frame out to use for gameplay). + * This function will block until "running start" milliseconds before the start of the frame, and should be called at the last moment before needing to + * start rendering. + * + * Return codes: + * - IsNotSceneApplication (make sure to call VR_Init with VRApplicaiton_Scene) + * - DoNotHaveFocus (some other app has taken focus - this will throttle the call to 10hz to reduce the impact on that app) + */ + virtual EVRCompositorError WaitGetPoses( VR_ARRAY_COUNT(unRenderPoseArrayCount) TrackedDevicePose_t* pRenderPoseArray, uint32_t unRenderPoseArrayCount, + VR_ARRAY_COUNT(unGamePoseArrayCount) TrackedDevicePose_t* pGamePoseArray, uint32_t unGamePoseArrayCount ) = 0; + + /** Get the last set of poses returned by WaitGetPoses. */ + virtual EVRCompositorError GetLastPoses( VR_ARRAY_COUNT( unRenderPoseArrayCount ) TrackedDevicePose_t* pRenderPoseArray, uint32_t unRenderPoseArrayCount, + VR_ARRAY_COUNT( unGamePoseArrayCount ) TrackedDevicePose_t* pGamePoseArray, uint32_t unGamePoseArrayCount ) = 0; + + /** Interface for accessing last set of poses returned by WaitGetPoses one at a time. + * Returns VRCompositorError_IndexOutOfRange if unDeviceIndex not less than k_unMaxTrackedDeviceCount otherwise VRCompositorError_None. + * It is okay to pass NULL for either pose if you only want one of the values. */ + virtual EVRCompositorError GetLastPoseForTrackedDeviceIndex( TrackedDeviceIndex_t unDeviceIndex, TrackedDevicePose_t *pOutputPose, TrackedDevicePose_t *pOutputGamePose ) = 0; + + /** Updated scene texture to display. If pBounds is NULL the entire texture will be used. If called from an OpenGL app, consider adding a glFlush after + * Submitting both frames to signal the driver to start processing, otherwise it may wait until the command buffer fills up, causing the app to miss frames. + * + * OpenGL dirty state: + * glBindTexture + * + * Return codes: + * - IsNotSceneApplication (make sure to call VR_Init with VRApplicaiton_Scene) + * - DoNotHaveFocus (some other app has taken focus) + * - TextureIsOnWrongDevice (application did not use proper AdapterIndex - see IVRSystem.GetDXGIOutputInfo) + * - SharedTexturesNotSupported (application needs to call CreateDXGIFactory1 or later before creating DX device) + * - TextureUsesUnsupportedFormat (scene textures must be compatible with DXGI sharing rules - e.g. uncompressed, no mips, etc.) + * - InvalidTexture (usually means bad arguments passed in) + * - AlreadySubmitted (app has submitted two left textures or two right textures in a single frame - i.e. before calling WaitGetPoses again) + */ + virtual EVRCompositorError Submit( EVREye eEye, const Texture_t *pTexture, const VRTextureBounds_t* pBounds = 0, EVRSubmitFlags nSubmitFlags = Submit_Default ) = 0; + + /** Clears the frame that was sent with the last call to Submit. This will cause the + * compositor to show the grid until Submit is called again. */ + virtual void ClearLastSubmittedFrame() = 0; + + /** Call immediately after presenting your app's window (i.e. companion window) to unblock the compositor. + * This is an optional call, which only needs to be used if you can't instead call WaitGetPoses immediately after Present. + * For example, if your engine's render and game loop are not on separate threads, or blocking the render thread until 3ms before the next vsync would + * introduce a deadlock of some sort. This function tells the compositor that you have finished all rendering after having Submitted buffers for both + * eyes, and it is free to start its rendering work. This should only be called from the same thread you are rendering on. */ + virtual void PostPresentHandoff() = 0; + + /** Returns true if timing data is filled it. Sets oldest timing info if nFramesAgo is larger than the stored history. + * Be sure to set timing.size = sizeof(Compositor_FrameTiming) on struct passed in before calling this function. */ + virtual bool GetFrameTiming( Compositor_FrameTiming *pTiming, uint32_t unFramesAgo = 0 ) = 0; + + /** Interface for copying a range of timing data. Frames are returned in ascending order (oldest to newest) with the last being the most recent frame. + * Only the first entry's m_nSize needs to be set, as the rest will be inferred from that. Returns total number of entries filled out. */ + virtual uint32_t GetFrameTimings( Compositor_FrameTiming *pTiming, uint32_t nFrames ) = 0; + + /** Returns the time in seconds left in the current (as identified by FrameTiming's frameIndex) frame. + * Due to "running start", this value may roll over to the next frame before ever reaching 0.0. */ + virtual float GetFrameTimeRemaining() = 0; + + /** Fills out stats accumulated for the last connected application. Pass in sizeof( Compositor_CumulativeStats ) as second parameter. */ + virtual void GetCumulativeStats( Compositor_CumulativeStats *pStats, uint32_t nStatsSizeInBytes ) = 0; + + /** Fades the view on the HMD to the specified color. The fade will take fSeconds, and the color values are between + * 0.0 and 1.0. This color is faded on top of the scene based on the alpha parameter. Removing the fade color instantly + * would be FadeToColor( 0.0, 0.0, 0.0, 0.0, 0.0 ). Values are in un-premultiplied alpha space. */ + virtual void FadeToColor( float fSeconds, float fRed, float fGreen, float fBlue, float fAlpha, bool bBackground = false ) = 0; + + /** Get current fade color value. */ + virtual HmdColor_t GetCurrentFadeColor( bool bBackground = false ) = 0; + + /** Fading the Grid in or out in fSeconds */ + virtual void FadeGrid( float fSeconds, bool bFadeIn ) = 0; + + /** Get current alpha value of grid. */ + virtual float GetCurrentGridAlpha() = 0; + + /** Override the skybox used in the compositor (e.g. for during level loads when the app can't feed scene images fast enough) + * Order is Front, Back, Left, Right, Top, Bottom. If only a single texture is passed, it is assumed in lat-long format. + * If two are passed, it is assumed a lat-long stereo pair. */ + virtual EVRCompositorError SetSkyboxOverride( VR_ARRAY_COUNT( unTextureCount ) const Texture_t *pTextures, uint32_t unTextureCount ) = 0; + + /** Resets compositor skybox back to defaults. */ + virtual void ClearSkyboxOverride() = 0; + + /** Brings the compositor window to the front. This is useful for covering any other window that may be on the HMD + * and is obscuring the compositor window. */ + virtual void CompositorBringToFront() = 0; + + /** Pushes the compositor window to the back. This is useful for allowing other applications to draw directly to the HMD. */ + virtual void CompositorGoToBack() = 0; + + /** Tells the compositor process to clean up and exit. You do not need to call this function at shutdown. Under normal + * circumstances the compositor will manage its own life cycle based on what applications are running. */ + virtual void CompositorQuit() = 0; + + /** Return whether the compositor is fullscreen */ + virtual bool IsFullscreen() = 0; + + /** Returns the process ID of the process that is currently rendering the scene */ + virtual uint32_t GetCurrentSceneFocusProcess() = 0; + + /** Returns the process ID of the process that rendered the last frame (or 0 if the compositor itself rendered the frame.) + * Returns 0 when fading out from an app and the app's process Id when fading into an app. */ + virtual uint32_t GetLastFrameRenderer() = 0; + + /** Returns true if the current process has the scene focus */ + virtual bool CanRenderScene() = 0; + + /** Creates a window on the primary monitor to display what is being shown in the headset. */ + virtual void ShowMirrorWindow() = 0; + + /** Closes the mirror window. */ + virtual void HideMirrorWindow() = 0; + + /** Returns true if the mirror window is shown. */ + virtual bool IsMirrorWindowVisible() = 0; + + /** Writes all images that the compositor knows about (including overlays) to a 'screenshots' folder in the SteamVR runtime root. */ + virtual void CompositorDumpImages() = 0; + + /** Let an app know it should be rendering with low resources. */ + virtual bool ShouldAppRenderWithLowResources() = 0; + + /** Override interleaved reprojection logic to force on. */ + virtual void ForceInterleavedReprojectionOn( bool bOverride ) = 0; + + /** Force reconnecting to the compositor process. */ + virtual void ForceReconnectProcess() = 0; + + /** Temporarily suspends rendering (useful for finer control over scene transitions). */ + virtual void SuspendRendering( bool bSuspend ) = 0; + + /** Opens a shared D3D11 texture with the undistorted composited image for each eye. Use ReleaseMirrorTextureD3D11 when finished + * instead of calling Release on the resource itself. */ + virtual vr::EVRCompositorError GetMirrorTextureD3D11( vr::EVREye eEye, void *pD3D11DeviceOrResource, void **ppD3D11ShaderResourceView ) = 0; + virtual void ReleaseMirrorTextureD3D11( void *pD3D11ShaderResourceView ) = 0; + + /** Access to mirror textures from OpenGL. */ + virtual vr::EVRCompositorError GetMirrorTextureGL( vr::EVREye eEye, vr::glUInt_t *pglTextureId, vr::glSharedTextureHandle_t *pglSharedTextureHandle ) = 0; + virtual bool ReleaseSharedGLTexture( vr::glUInt_t glTextureId, vr::glSharedTextureHandle_t glSharedTextureHandle ) = 0; + virtual void LockGLSharedTextureForAccess( vr::glSharedTextureHandle_t glSharedTextureHandle ) = 0; + virtual void UnlockGLSharedTextureForAccess( vr::glSharedTextureHandle_t glSharedTextureHandle ) = 0; + + /** [Vulkan Only] + * return 0. Otherwise it returns the length of the number of bytes necessary to hold this string including the trailing + * null. The string will be a space separated list of-required instance extensions to enable in VkCreateInstance */ + virtual uint32_t GetVulkanInstanceExtensionsRequired( VR_OUT_STRING() char *pchValue, uint32_t unBufferSize ) = 0; + + /** [Vulkan only] + * return 0. Otherwise it returns the length of the number of bytes necessary to hold this string including the trailing + * null. The string will be a space separated list of required device extensions to enable in VkCreateDevice */ + virtual uint32_t GetVulkanDeviceExtensionsRequired( VkPhysicalDevice_T *pPhysicalDevice, VR_OUT_STRING() char *pchValue, uint32_t unBufferSize ) = 0; + + /** [ Vulkan/D3D12 Only ] + * There are two purposes for SetExplicitTimingMode: + * 1. To get a more accurate GPU timestamp for when the frame begins in Vulkan/D3D12 applications. + * 2. (Optional) To avoid having WaitGetPoses access the Vulkan queue so that the queue can be accessed from + * another thread while WaitGetPoses is executing. + * + * More accurate GPU timestamp for the start of the frame is achieved by the application calling + * SubmitExplicitTimingData immediately before its first submission to the Vulkan/D3D12 queue. + * This is more accurate because normally this GPU timestamp is recorded during WaitGetPoses. In D3D11, + * WaitGetPoses queues a GPU timestamp write, but it does not actually get submitted to the GPU until the + * application flushes. By using SubmitExplicitTimingData, the timestamp is recorded at the same place for + * Vulkan/D3D12 as it is for D3D11, resulting in a more accurate GPU time measurement for the frame. + * + * Avoiding WaitGetPoses accessing the Vulkan queue can be achieved using SetExplicitTimingMode as well. If this is desired, + * the application should set the timing mode to Explicit_ApplicationPerformsPostPresentHandoff and *MUST* call PostPresentHandoff + * itself. If these conditions are met, then WaitGetPoses is guaranteed not to access the queue. Note that PostPresentHandoff + * and SubmitExplicitTimingData will access the queue, so only WaitGetPoses becomes safe for accessing the queue from another + * thread. */ + virtual void SetExplicitTimingMode( EVRCompositorTimingMode eTimingMode ) = 0; + + /** [ Vulkan/D3D12 Only ] + * Submit explicit timing data. When SetExplicitTimingMode is true, this must be called immediately before + * the application's first vkQueueSubmit (Vulkan) or ID3D12CommandQueue::ExecuteCommandLists (D3D12) of each frame. + * This function will insert a GPU timestamp write just before the application starts its rendering. This function + * will perform a vkQueueSubmit on Vulkan so must not be done simultaneously with VkQueue operations on another thread. + * Returns VRCompositorError_RequestFailed if SetExplicitTimingMode is not enabled. */ + virtual EVRCompositorError SubmitExplicitTimingData() = 0; +}; + +static const char * const IVRCompositor_Version = "IVRCompositor_022"; + +} // namespace vr + + + +// ivrnotifications.h +namespace vr +{ + +#pragma pack( push, 8 ) + +// Used for passing graphic data +struct NotificationBitmap_t +{ + NotificationBitmap_t() + : m_pImageData( nullptr ) + , m_nWidth( 0 ) + , m_nHeight( 0 ) + , m_nBytesPerPixel( 0 ) + { + }; + + void *m_pImageData; + int32_t m_nWidth; + int32_t m_nHeight; + int32_t m_nBytesPerPixel; +}; + + +/** Be aware that the notification type is used as 'priority' to pick the next notification */ +enum EVRNotificationType +{ + /** Transient notifications are automatically hidden after a period of time set by the user. + * They are used for things like information and chat messages that do not require user interaction. */ + EVRNotificationType_Transient = 0, + + /** Persistent notifications are shown to the user until they are hidden by calling RemoveNotification(). + * They are used for things like phone calls and alarms that require user interaction. */ + EVRNotificationType_Persistent = 1, + + /** System notifications are shown no matter what. It is expected, that the ulUserValue is used as ID. + * If there is already a system notification in the queue with that ID it is not accepted into the queue + * to prevent spamming with system notification */ + EVRNotificationType_Transient_SystemWithUserValue = 2, +}; + +enum EVRNotificationStyle +{ + /** Creates a notification with minimal external styling. */ + EVRNotificationStyle_None = 0, + + /** Used for notifications about overlay-level status. In Steam this is used for events like downloads completing. */ + EVRNotificationStyle_Application = 100, + + /** Used for notifications about contacts that are unknown or not available. In Steam this is used for friend invitations and offline friends. */ + EVRNotificationStyle_Contact_Disabled = 200, + + /** Used for notifications about contacts that are available but inactive. In Steam this is used for friends that are online but not playing a game. */ + EVRNotificationStyle_Contact_Enabled = 201, + + /** Used for notifications about contacts that are available and active. In Steam this is used for friends that are online and currently running a game. */ + EVRNotificationStyle_Contact_Active = 202, +}; + +static const uint32_t k_unNotificationTextMaxSize = 256; + +typedef uint32_t VRNotificationId; + + + +#pragma pack( pop ) + +/** Allows notification sources to interact with the VR system + This current interface is not yet implemented. Do not use yet. */ +class IVRNotifications +{ +public: + /** Create a notification and enqueue it to be shown to the user. + * An overlay handle is required to create a notification, as otherwise it would be impossible for a user to act on it. + * To create a two-line notification, use a line break ('\n') to split the text into two lines. + * The pImage argument may be NULL, in which case the specified overlay's icon will be used instead. */ + virtual EVRNotificationError CreateNotification( VROverlayHandle_t ulOverlayHandle, uint64_t ulUserValue, EVRNotificationType type, const char *pchText, EVRNotificationStyle style, const NotificationBitmap_t *pImage, /* out */ VRNotificationId *pNotificationId ) = 0; + + /** Destroy a notification, hiding it first if it currently shown to the user. */ + virtual EVRNotificationError RemoveNotification( VRNotificationId notificationId ) = 0; + +}; + +static const char * const IVRNotifications_Version = "IVRNotifications_002"; + +} // namespace vr + + + +// ivroverlay.h +namespace vr +{ + + /** The maximum length of an overlay key in bytes, counting the terminating null character. */ + static const uint32_t k_unVROverlayMaxKeyLength = 128; + + /** The maximum length of an overlay name in bytes, counting the terminating null character. */ + static const uint32_t k_unVROverlayMaxNameLength = 128; + + /** The maximum number of overlays that can exist in the system at one time. */ + static const uint32_t k_unMaxOverlayCount = 64; + + /** The maximum number of overlay intersection mask primitives per overlay */ + static const uint32_t k_unMaxOverlayIntersectionMaskPrimitivesCount = 32; + + /** Types of input supported by VR Overlays */ + enum VROverlayInputMethod + { + VROverlayInputMethod_None = 0, // No input events will be generated automatically for this overlay + VROverlayInputMethod_Mouse = 1, // Tracked controllers will get mouse events automatically + VROverlayInputMethod_DualAnalog = 2, // Analog inputs from tracked controllers are turned into DualAnalog events + }; + + /** Allows the caller to figure out which overlay transform getter to call. */ + enum VROverlayTransformType + { + VROverlayTransform_Absolute = 0, + VROverlayTransform_TrackedDeviceRelative = 1, + VROverlayTransform_SystemOverlay = 2, + VROverlayTransform_TrackedComponent = 3, + }; + + /** Overlay control settings */ + enum VROverlayFlags + { + VROverlayFlags_None = 0, + + // The following only take effect when rendered using the high quality render path (see SetHighQualityOverlay). + VROverlayFlags_Curved = 1, + VROverlayFlags_RGSS4X = 2, + + // Set this flag on a dashboard overlay to prevent a tab from showing up for that overlay + VROverlayFlags_NoDashboardTab = 3, + + // Set this flag on a dashboard that is able to deal with gamepad focus events + VROverlayFlags_AcceptsGamepadEvents = 4, + + // Indicates that the overlay should dim/brighten to show gamepad focus + VROverlayFlags_ShowGamepadFocus = 5, + + // When in VROverlayInputMethod_Mouse you can optionally enable sending VRScroll_t + VROverlayFlags_SendVRScrollEvents = 6, + VROverlayFlags_SendVRTouchpadEvents = 7, + + // If set this will render a vertical scroll wheel on the primary controller, + // only needed if not using VROverlayFlags_SendVRScrollEvents but you still want to represent a scroll wheel + VROverlayFlags_ShowTouchPadScrollWheel = 8, + + // If this is set ownership and render access to the overlay are transferred + // to the new scene process on a call to IVRApplications::LaunchInternalProcess + VROverlayFlags_TransferOwnershipToInternalProcess = 9, + + // If set, renders 50% of the texture in each eye, side by side + VROverlayFlags_SideBySide_Parallel = 10, // Texture is left/right + VROverlayFlags_SideBySide_Crossed = 11, // Texture is crossed and right/left + + VROverlayFlags_Panorama = 12, // Texture is a panorama + VROverlayFlags_StereoPanorama = 13, // Texture is a stereo panorama + + // If this is set on an overlay owned by the scene application that overlay + // will be sorted with the "Other" overlays on top of all other scene overlays + VROverlayFlags_SortWithNonSceneOverlays = 14, + + // If set, the overlay will be shown in the dashboard, otherwise it will be hidden. + VROverlayFlags_VisibleInDashboard = 15, + }; + + enum VRMessageOverlayResponse + { + VRMessageOverlayResponse_ButtonPress_0 = 0, + VRMessageOverlayResponse_ButtonPress_1 = 1, + VRMessageOverlayResponse_ButtonPress_2 = 2, + VRMessageOverlayResponse_ButtonPress_3 = 3, + VRMessageOverlayResponse_CouldntFindSystemOverlay = 4, + VRMessageOverlayResponse_CouldntFindOrCreateClientOverlay= 5, + VRMessageOverlayResponse_ApplicationQuit = 6 + }; + + struct VROverlayIntersectionParams_t + { + HmdVector3_t vSource; + HmdVector3_t vDirection; + ETrackingUniverseOrigin eOrigin; + }; + + struct VROverlayIntersectionResults_t + { + HmdVector3_t vPoint; + HmdVector3_t vNormal; + HmdVector2_t vUVs; + float fDistance; + }; + + // Input modes for the Big Picture gamepad text entry + enum EGamepadTextInputMode + { + k_EGamepadTextInputModeNormal = 0, + k_EGamepadTextInputModePassword = 1, + k_EGamepadTextInputModeSubmit = 2, + }; + + // Controls number of allowed lines for the Big Picture gamepad text entry + enum EGamepadTextInputLineMode + { + k_EGamepadTextInputLineModeSingleLine = 0, + k_EGamepadTextInputLineModeMultipleLines = 1 + }; + + /** Directions for changing focus between overlays with the gamepad */ + enum EOverlayDirection + { + OverlayDirection_Up = 0, + OverlayDirection_Down = 1, + OverlayDirection_Left = 2, + OverlayDirection_Right = 3, + + OverlayDirection_Count = 4, + }; + + enum EVROverlayIntersectionMaskPrimitiveType + { + OverlayIntersectionPrimitiveType_Rectangle, + OverlayIntersectionPrimitiveType_Circle, + }; + + struct IntersectionMaskRectangle_t + { + float m_flTopLeftX; + float m_flTopLeftY; + float m_flWidth; + float m_flHeight; + }; + + struct IntersectionMaskCircle_t + { + float m_flCenterX; + float m_flCenterY; + float m_flRadius; + }; + + /** NOTE!!! If you change this you MUST manually update openvr_interop.cs.py and openvr_api_flat.h.py */ + typedef union + { + IntersectionMaskRectangle_t m_Rectangle; + IntersectionMaskCircle_t m_Circle; + } VROverlayIntersectionMaskPrimitive_Data_t; + + struct VROverlayIntersectionMaskPrimitive_t + { + EVROverlayIntersectionMaskPrimitiveType m_nPrimitiveType; + VROverlayIntersectionMaskPrimitive_Data_t m_Primitive; + }; + + class IVROverlay + { + public: + + // --------------------------------------------- + // Overlay management methods + // --------------------------------------------- + + /** Finds an existing overlay with the specified key. */ + virtual EVROverlayError FindOverlay( const char *pchOverlayKey, VROverlayHandle_t * pOverlayHandle ) = 0; + + /** Creates a new named overlay. All overlays start hidden and with default settings. */ + virtual EVROverlayError CreateOverlay( const char *pchOverlayKey, const char *pchOverlayName, VROverlayHandle_t * pOverlayHandle ) = 0; + + /** Destroys the specified overlay. When an application calls VR_Shutdown all overlays created by that app are + * automatically destroyed. */ + virtual EVROverlayError DestroyOverlay( VROverlayHandle_t ulOverlayHandle ) = 0; + + /** Specify which overlay to use the high quality render path. This overlay will be composited in during the distortion pass which + * results in it drawing on top of everything else, but also at a higher quality as it samples the source texture directly rather than + * rasterizing into each eye's render texture first. Because if this, only one of these is supported at any given time. It is most useful + * for overlays that are expected to take up most of the user's view (e.g. streaming video). + * This mode does not support mouse input to your overlay. */ + virtual EVROverlayError SetHighQualityOverlay( VROverlayHandle_t ulOverlayHandle ) = 0; + + /** Returns the overlay handle of the current overlay being rendered using the single high quality overlay render path. + * Otherwise it will return k_ulOverlayHandleInvalid. */ + virtual vr::VROverlayHandle_t GetHighQualityOverlay() = 0; + + /** Fills the provided buffer with the string key of the overlay. Returns the size of buffer required to store the key, including + * the terminating null character. k_unVROverlayMaxKeyLength will be enough bytes to fit the string. */ + virtual uint32_t GetOverlayKey( VROverlayHandle_t ulOverlayHandle, VR_OUT_STRING() char *pchValue, uint32_t unBufferSize, EVROverlayError *pError = 0L ) = 0; + + /** Fills the provided buffer with the friendly name of the overlay. Returns the size of buffer required to store the key, including + * the terminating null character. k_unVROverlayMaxNameLength will be enough bytes to fit the string. */ + virtual uint32_t GetOverlayName( VROverlayHandle_t ulOverlayHandle, VR_OUT_STRING() char *pchValue, uint32_t unBufferSize, EVROverlayError *pError = 0L ) = 0; + + /** set the name to use for this overlay */ + virtual EVROverlayError SetOverlayName( VROverlayHandle_t ulOverlayHandle, const char *pchName ) = 0; + + /** Gets the raw image data from an overlay. Overlay image data is always returned as RGBA data, 4 bytes per pixel. If the buffer is not large enough, width and height + * will be set and VROverlayError_ArrayTooSmall is returned. */ + virtual EVROverlayError GetOverlayImageData( VROverlayHandle_t ulOverlayHandle, void *pvBuffer, uint32_t unBufferSize, uint32_t *punWidth, uint32_t *punHeight ) = 0; + + /** returns a string that corresponds with the specified overlay error. The string will be the name + * of the error enum value for all valid error codes */ + virtual const char *GetOverlayErrorNameFromEnum( EVROverlayError error ) = 0; + + // --------------------------------------------- + // Overlay rendering methods + // --------------------------------------------- + + /** Sets the pid that is allowed to render to this overlay (the creator pid is always allow to render), + * by default this is the pid of the process that made the overlay */ + virtual EVROverlayError SetOverlayRenderingPid( VROverlayHandle_t ulOverlayHandle, uint32_t unPID ) = 0; + + /** Gets the pid that is allowed to render to this overlay */ + virtual uint32_t GetOverlayRenderingPid( VROverlayHandle_t ulOverlayHandle ) = 0; + + /** Specify flag setting for a given overlay */ + virtual EVROverlayError SetOverlayFlag( VROverlayHandle_t ulOverlayHandle, VROverlayFlags eOverlayFlag, bool bEnabled ) = 0; + + /** Sets flag setting for a given overlay */ + virtual EVROverlayError GetOverlayFlag( VROverlayHandle_t ulOverlayHandle, VROverlayFlags eOverlayFlag, bool *pbEnabled ) = 0; + + /** Sets the color tint of the overlay quad. Use 0.0 to 1.0 per channel. */ + virtual EVROverlayError SetOverlayColor( VROverlayHandle_t ulOverlayHandle, float fRed, float fGreen, float fBlue ) = 0; + + /** Gets the color tint of the overlay quad. */ + virtual EVROverlayError GetOverlayColor( VROverlayHandle_t ulOverlayHandle, float *pfRed, float *pfGreen, float *pfBlue ) = 0; + + /** Sets the alpha of the overlay quad. Use 1.0 for 100 percent opacity to 0.0 for 0 percent opacity. */ + virtual EVROverlayError SetOverlayAlpha( VROverlayHandle_t ulOverlayHandle, float fAlpha ) = 0; + + /** Gets the alpha of the overlay quad. By default overlays are rendering at 100 percent alpha (1.0). */ + virtual EVROverlayError GetOverlayAlpha( VROverlayHandle_t ulOverlayHandle, float *pfAlpha ) = 0; + + /** Sets the aspect ratio of the texels in the overlay. 1.0 means the texels are square. 2.0 means the texels + * are twice as wide as they are tall. Defaults to 1.0. */ + virtual EVROverlayError SetOverlayTexelAspect( VROverlayHandle_t ulOverlayHandle, float fTexelAspect ) = 0; + + /** Gets the aspect ratio of the texels in the overlay. Defaults to 1.0 */ + virtual EVROverlayError GetOverlayTexelAspect( VROverlayHandle_t ulOverlayHandle, float *pfTexelAspect ) = 0; + + /** Sets the rendering sort order for the overlay. Overlays are rendered this order: + * Overlays owned by the scene application + * Overlays owned by some other application + * + * Within a category overlays are rendered lowest sort order to highest sort order. Overlays with the same + * sort order are rendered back to front base on distance from the HMD. + * + * Sort order defaults to 0. */ + virtual EVROverlayError SetOverlaySortOrder( VROverlayHandle_t ulOverlayHandle, uint32_t unSortOrder ) = 0; + + /** Gets the sort order of the overlay. See SetOverlaySortOrder for how this works. */ + virtual EVROverlayError GetOverlaySortOrder( VROverlayHandle_t ulOverlayHandle, uint32_t *punSortOrder ) = 0; + + /** Sets the width of the overlay quad in meters. By default overlays are rendered on a quad that is 1 meter across */ + virtual EVROverlayError SetOverlayWidthInMeters( VROverlayHandle_t ulOverlayHandle, float fWidthInMeters ) = 0; + + /** Returns the width of the overlay quad in meters. By default overlays are rendered on a quad that is 1 meter across */ + virtual EVROverlayError GetOverlayWidthInMeters( VROverlayHandle_t ulOverlayHandle, float *pfWidthInMeters ) = 0; + + /** For high-quality curved overlays only, sets the distance range in meters from the overlay used to automatically curve + * the surface around the viewer. Min is distance is when the surface will be most curved. Max is when least curved. */ + virtual EVROverlayError SetOverlayAutoCurveDistanceRangeInMeters( VROverlayHandle_t ulOverlayHandle, float fMinDistanceInMeters, float fMaxDistanceInMeters ) = 0; + + /** For high-quality curved overlays only, gets the distance range in meters from the overlay used to automatically curve + * the surface around the viewer. Min is distance is when the surface will be most curved. Max is when least curved. */ + virtual EVROverlayError GetOverlayAutoCurveDistanceRangeInMeters( VROverlayHandle_t ulOverlayHandle, float *pfMinDistanceInMeters, float *pfMaxDistanceInMeters ) = 0; + + /** Sets the colorspace the overlay texture's data is in. Defaults to 'auto'. + * If the texture needs to be resolved, you should call SetOverlayTexture with the appropriate colorspace instead. */ + virtual EVROverlayError SetOverlayTextureColorSpace( VROverlayHandle_t ulOverlayHandle, EColorSpace eTextureColorSpace ) = 0; + + /** Gets the overlay's current colorspace setting. */ + virtual EVROverlayError GetOverlayTextureColorSpace( VROverlayHandle_t ulOverlayHandle, EColorSpace *peTextureColorSpace ) = 0; + + /** Sets the part of the texture to use for the overlay. UV Min is the upper left corner and UV Max is the lower right corner. */ + virtual EVROverlayError SetOverlayTextureBounds( VROverlayHandle_t ulOverlayHandle, const VRTextureBounds_t *pOverlayTextureBounds ) = 0; + + /** Gets the part of the texture to use for the overlay. UV Min is the upper left corner and UV Max is the lower right corner. */ + virtual EVROverlayError GetOverlayTextureBounds( VROverlayHandle_t ulOverlayHandle, VRTextureBounds_t *pOverlayTextureBounds ) = 0; + + /** Gets render model to draw behind this overlay */ + virtual uint32_t GetOverlayRenderModel( vr::VROverlayHandle_t ulOverlayHandle, VR_OUT_STRING() char *pchValue, uint32_t unBufferSize, HmdColor_t *pColor, vr::EVROverlayError *pError ) = 0; + + /** Sets render model to draw behind this overlay and the vertex color to use, pass null for pColor to match the overlays vertex color. + The model is scaled by the same amount as the overlay, with a default of 1m. */ + virtual vr::EVROverlayError SetOverlayRenderModel( vr::VROverlayHandle_t ulOverlayHandle, const char *pchRenderModel, const HmdColor_t *pColor ) = 0; + + /** Returns the transform type of this overlay. */ + virtual EVROverlayError GetOverlayTransformType( VROverlayHandle_t ulOverlayHandle, VROverlayTransformType *peTransformType ) = 0; + + /** Sets the transform to absolute tracking origin. */ + virtual EVROverlayError SetOverlayTransformAbsolute( VROverlayHandle_t ulOverlayHandle, ETrackingUniverseOrigin eTrackingOrigin, const HmdMatrix34_t *pmatTrackingOriginToOverlayTransform ) = 0; + + /** Gets the transform if it is absolute. Returns an error if the transform is some other type. */ + virtual EVROverlayError GetOverlayTransformAbsolute( VROverlayHandle_t ulOverlayHandle, ETrackingUniverseOrigin *peTrackingOrigin, HmdMatrix34_t *pmatTrackingOriginToOverlayTransform ) = 0; + + /** Sets the transform to relative to the transform of the specified tracked device. */ + virtual EVROverlayError SetOverlayTransformTrackedDeviceRelative( VROverlayHandle_t ulOverlayHandle, TrackedDeviceIndex_t unTrackedDevice, const HmdMatrix34_t *pmatTrackedDeviceToOverlayTransform ) = 0; + + /** Gets the transform if it is relative to a tracked device. Returns an error if the transform is some other type. */ + virtual EVROverlayError GetOverlayTransformTrackedDeviceRelative( VROverlayHandle_t ulOverlayHandle, TrackedDeviceIndex_t *punTrackedDevice, HmdMatrix34_t *pmatTrackedDeviceToOverlayTransform ) = 0; + + /** Sets the transform to draw the overlay on a rendermodel component mesh instead of a quad. This will only draw when the system is + * drawing the device. Overlays with this transform type cannot receive mouse events. */ + virtual EVROverlayError SetOverlayTransformTrackedDeviceComponent( VROverlayHandle_t ulOverlayHandle, TrackedDeviceIndex_t unDeviceIndex, const char *pchComponentName ) = 0; + + /** Gets the transform information when the overlay is rendering on a component. */ + virtual EVROverlayError GetOverlayTransformTrackedDeviceComponent( VROverlayHandle_t ulOverlayHandle, TrackedDeviceIndex_t *punDeviceIndex, VR_OUT_STRING() char *pchComponentName, uint32_t unComponentNameSize ) = 0; + + /** Gets the transform if it is relative to another overlay. Returns an error if the transform is some other type. */ + virtual vr::EVROverlayError GetOverlayTransformOverlayRelative( VROverlayHandle_t ulOverlayHandle, VROverlayHandle_t *ulOverlayHandleParent, HmdMatrix34_t *pmatParentOverlayToOverlayTransform ) = 0; + + /** Sets the transform to relative to the transform of the specified overlay. This overlays visibility will also track the parents visibility */ + virtual vr::EVROverlayError SetOverlayTransformOverlayRelative( VROverlayHandle_t ulOverlayHandle, VROverlayHandle_t ulOverlayHandleParent, const HmdMatrix34_t *pmatParentOverlayToOverlayTransform ) = 0; + + /** Shows the VR overlay. For dashboard overlays, only the Dashboard Manager is allowed to call this. */ + virtual EVROverlayError ShowOverlay( VROverlayHandle_t ulOverlayHandle ) = 0; + + /** Hides the VR overlay. For dashboard overlays, only the Dashboard Manager is allowed to call this. */ + virtual EVROverlayError HideOverlay( VROverlayHandle_t ulOverlayHandle ) = 0; + + /** Returns true if the overlay is visible. */ + virtual bool IsOverlayVisible( VROverlayHandle_t ulOverlayHandle ) = 0; + + /** Get the transform in 3d space associated with a specific 2d point in the overlay's coordinate space (where 0,0 is the lower left). -Z points out of the overlay */ + virtual EVROverlayError GetTransformForOverlayCoordinates( VROverlayHandle_t ulOverlayHandle, ETrackingUniverseOrigin eTrackingOrigin, HmdVector2_t coordinatesInOverlay, HmdMatrix34_t *pmatTransform ) = 0; + + // --------------------------------------------- + // Overlay input methods + // --------------------------------------------- + + /** Returns true and fills the event with the next event on the overlay's event queue, if there is one. + * If there are no events this method returns false. uncbVREvent should be the size in bytes of the VREvent_t struct */ + virtual bool PollNextOverlayEvent( VROverlayHandle_t ulOverlayHandle, VREvent_t *pEvent, uint32_t uncbVREvent ) = 0; + + /** Returns the current input settings for the specified overlay. */ + virtual EVROverlayError GetOverlayInputMethod( VROverlayHandle_t ulOverlayHandle, VROverlayInputMethod *peInputMethod ) = 0; + + /** Sets the input settings for the specified overlay. */ + virtual EVROverlayError SetOverlayInputMethod( VROverlayHandle_t ulOverlayHandle, VROverlayInputMethod eInputMethod ) = 0; + + /** Gets the mouse scaling factor that is used for mouse events. The actual texture may be a different size, but this is + * typically the size of the underlying UI in pixels. */ + virtual EVROverlayError GetOverlayMouseScale( VROverlayHandle_t ulOverlayHandle, HmdVector2_t *pvecMouseScale ) = 0; + + /** Sets the mouse scaling factor that is used for mouse events. The actual texture may be a different size, but this is + * typically the size of the underlying UI in pixels (not in world space). */ + virtual EVROverlayError SetOverlayMouseScale( VROverlayHandle_t ulOverlayHandle, const HmdVector2_t *pvecMouseScale ) = 0; + + /** Computes the overlay-space pixel coordinates of where the ray intersects the overlay with the + * specified settings. Returns false if there is no intersection. */ + virtual bool ComputeOverlayIntersection( VROverlayHandle_t ulOverlayHandle, const VROverlayIntersectionParams_t *pParams, VROverlayIntersectionResults_t *pResults ) = 0; + + /** Returns true if the specified overlay is the hover target. An overlay is the hover target when it is the last overlay "moused over" + * by the virtual mouse pointer */ + virtual bool IsHoverTargetOverlay( VROverlayHandle_t ulOverlayHandle ) = 0; + + /** Returns the current Gamepad focus overlay */ + virtual vr::VROverlayHandle_t GetGamepadFocusOverlay() = 0; + + /** Sets the current Gamepad focus overlay */ + virtual EVROverlayError SetGamepadFocusOverlay( VROverlayHandle_t ulNewFocusOverlay ) = 0; + + /** Sets an overlay's neighbor. This will also set the neighbor of the "to" overlay + * to point back to the "from" overlay. If an overlay's neighbor is set to invalid both + * ends will be cleared */ + virtual EVROverlayError SetOverlayNeighbor( EOverlayDirection eDirection, VROverlayHandle_t ulFrom, VROverlayHandle_t ulTo ) = 0; + + /** Changes the Gamepad focus from one overlay to one of its neighbors. Returns VROverlayError_NoNeighbor if there is no + * neighbor in that direction */ + virtual EVROverlayError MoveGamepadFocusToNeighbor( EOverlayDirection eDirection, VROverlayHandle_t ulFrom ) = 0; + + /** Sets the analog input to Dual Analog coordinate scale for the specified overlay. */ + virtual EVROverlayError SetOverlayDualAnalogTransform( VROverlayHandle_t ulOverlay, EDualAnalogWhich eWhich, const HmdVector2_t & vCenter, float fRadius ) = 0; + + /** Gets the analog input to Dual Analog coordinate scale for the specified overlay. */ + virtual EVROverlayError GetOverlayDualAnalogTransform( VROverlayHandle_t ulOverlay, EDualAnalogWhich eWhich, HmdVector2_t *pvCenter, float *pfRadius ) = 0; + + // --------------------------------------------- + // Overlay texture methods + // --------------------------------------------- + + /** Texture to draw for the overlay. This function can only be called by the overlay's creator or renderer process (see SetOverlayRenderingPid) . + * + * OpenGL dirty state: + * glBindTexture + */ + virtual EVROverlayError SetOverlayTexture( VROverlayHandle_t ulOverlayHandle, const Texture_t *pTexture ) = 0; + + /** Use this to tell the overlay system to release the texture set for this overlay. */ + virtual EVROverlayError ClearOverlayTexture( VROverlayHandle_t ulOverlayHandle ) = 0; + + /** Separate interface for providing the data as a stream of bytes, but there is an upper bound on data + * that can be sent. This function can only be called by the overlay's renderer process. */ + virtual EVROverlayError SetOverlayRaw( VROverlayHandle_t ulOverlayHandle, void *pvBuffer, uint32_t unWidth, uint32_t unHeight, uint32_t unDepth ) = 0; + + /** Separate interface for providing the image through a filename: can be png or jpg, and should not be bigger than 1920x1080. + * This function can only be called by the overlay's renderer process */ + virtual EVROverlayError SetOverlayFromFile( VROverlayHandle_t ulOverlayHandle, const char *pchFilePath ) = 0; + + /** Get the native texture handle/device for an overlay you have created. + * On windows this handle will be a ID3D11ShaderResourceView with a ID3D11Texture2D bound. + * + * The texture will always be sized to match the backing texture you supplied in SetOverlayTexture above. + * + * You MUST call ReleaseNativeOverlayHandle() with pNativeTextureHandle once you are done with this texture. + * + * pNativeTextureHandle is an OUTPUT, it will be a pointer to a ID3D11ShaderResourceView *. + * pNativeTextureRef is an INPUT and should be a ID3D11Resource *. The device used by pNativeTextureRef will be used to bind pNativeTextureHandle. + */ + virtual EVROverlayError GetOverlayTexture( VROverlayHandle_t ulOverlayHandle, void **pNativeTextureHandle, void *pNativeTextureRef, uint32_t *pWidth, uint32_t *pHeight, uint32_t *pNativeFormat, ETextureType *pAPIType, EColorSpace *pColorSpace, VRTextureBounds_t *pTextureBounds ) = 0; + + /** Release the pNativeTextureHandle provided from the GetOverlayTexture call, this allows the system to free the underlying GPU resources for this object, + * so only do it once you stop rendering this texture. + */ + virtual EVROverlayError ReleaseNativeOverlayHandle( VROverlayHandle_t ulOverlayHandle, void *pNativeTextureHandle ) = 0; + + /** Get the size of the overlay texture */ + virtual EVROverlayError GetOverlayTextureSize( VROverlayHandle_t ulOverlayHandle, uint32_t *pWidth, uint32_t *pHeight ) = 0; + + // ---------------------------------------------- + // Dashboard Overlay Methods + // ---------------------------------------------- + + /** Creates a dashboard overlay and returns its handle */ + virtual EVROverlayError CreateDashboardOverlay( const char *pchOverlayKey, const char *pchOverlayFriendlyName, VROverlayHandle_t * pMainHandle, VROverlayHandle_t *pThumbnailHandle ) = 0; + + /** Returns true if the dashboard is visible */ + virtual bool IsDashboardVisible() = 0; + + /** returns true if the dashboard is visible and the specified overlay is the active system Overlay */ + virtual bool IsActiveDashboardOverlay( VROverlayHandle_t ulOverlayHandle ) = 0; + + /** Sets the dashboard overlay to only appear when the specified process ID has scene focus */ + virtual EVROverlayError SetDashboardOverlaySceneProcess( VROverlayHandle_t ulOverlayHandle, uint32_t unProcessId ) = 0; + + /** Gets the process ID that this dashboard overlay requires to have scene focus */ + virtual EVROverlayError GetDashboardOverlaySceneProcess( VROverlayHandle_t ulOverlayHandle, uint32_t *punProcessId ) = 0; + + /** Shows the dashboard. */ + virtual void ShowDashboard( const char *pchOverlayToShow ) = 0; + + /** Returns the tracked device that has the laser pointer in the dashboard */ + virtual vr::TrackedDeviceIndex_t GetPrimaryDashboardDevice() = 0; + + // --------------------------------------------- + // Keyboard methods + // --------------------------------------------- + + /** Show the virtual keyboard to accept input **/ + virtual EVROverlayError ShowKeyboard( EGamepadTextInputMode eInputMode, EGamepadTextInputLineMode eLineInputMode, const char *pchDescription, uint32_t unCharMax, const char *pchExistingText, bool bUseMinimalMode, uint64_t uUserValue ) = 0; + + virtual EVROverlayError ShowKeyboardForOverlay( VROverlayHandle_t ulOverlayHandle, EGamepadTextInputMode eInputMode, EGamepadTextInputLineMode eLineInputMode, const char *pchDescription, uint32_t unCharMax, const char *pchExistingText, bool bUseMinimalMode, uint64_t uUserValue ) = 0; + + /** Get the text that was entered into the text input **/ + virtual uint32_t GetKeyboardText( VR_OUT_STRING() char *pchText, uint32_t cchText ) = 0; + + /** Hide the virtual keyboard **/ + virtual void HideKeyboard() = 0; + + /** Set the position of the keyboard in world space **/ + virtual void SetKeyboardTransformAbsolute( ETrackingUniverseOrigin eTrackingOrigin, const HmdMatrix34_t *pmatTrackingOriginToKeyboardTransform ) = 0; + + /** Set the position of the keyboard in overlay space by telling it to avoid a rectangle in the overlay. Rectangle coords have (0,0) in the bottom left **/ + virtual void SetKeyboardPositionForOverlay( VROverlayHandle_t ulOverlayHandle, HmdRect2_t avoidRect ) = 0; + + // --------------------------------------------- + // Overlay input methods + // --------------------------------------------- + + /** Sets a list of primitives to be used for controller ray intersection + * typically the size of the underlying UI in pixels (not in world space). */ + virtual EVROverlayError SetOverlayIntersectionMask( VROverlayHandle_t ulOverlayHandle, VROverlayIntersectionMaskPrimitive_t *pMaskPrimitives, uint32_t unNumMaskPrimitives, uint32_t unPrimitiveSize = sizeof( VROverlayIntersectionMaskPrimitive_t ) ) = 0; + + virtual EVROverlayError GetOverlayFlags( VROverlayHandle_t ulOverlayHandle, uint32_t *pFlags ) = 0; + + // --------------------------------------------- + // Message box methods + // --------------------------------------------- + + /** Show the message overlay. This will block and return you a result. **/ + virtual VRMessageOverlayResponse ShowMessageOverlay( const char* pchText, const char* pchCaption, const char* pchButton0Text, const char* pchButton1Text = nullptr, const char* pchButton2Text = nullptr, const char* pchButton3Text = nullptr ) = 0; + + /** If the calling process owns the overlay and it's open, this will close it. **/ + virtual void CloseMessageOverlay() = 0; + }; + + static const char * const IVROverlay_Version = "IVROverlay_018"; + +} // namespace vr + +// ivrrendermodels.h +namespace vr +{ + +static const char * const k_pch_Controller_Component_GDC2015 = "gdc2015"; // Canonical coordinate system of the gdc 2015 wired controller, provided for backwards compatibility +static const char * const k_pch_Controller_Component_Base = "base"; // For controllers with an unambiguous 'base'. +static const char * const k_pch_Controller_Component_Tip = "tip"; // For controllers with an unambiguous 'tip' (used for 'laser-pointing') +static const char * const k_pch_Controller_Component_HandGrip = "handgrip"; // Neutral, ambidextrous hand-pose when holding controller. On plane between neutrally posed index finger and thumb +static const char * const k_pch_Controller_Component_Status = "status"; // 1:1 aspect ratio status area, with canonical [0,1] uv mapping + +#pragma pack( push, 8 ) + +/** Errors that can occur with the VR compositor */ +enum EVRRenderModelError +{ + VRRenderModelError_None = 0, + VRRenderModelError_Loading = 100, + VRRenderModelError_NotSupported = 200, + VRRenderModelError_InvalidArg = 300, + VRRenderModelError_InvalidModel = 301, + VRRenderModelError_NoShapes = 302, + VRRenderModelError_MultipleShapes = 303, + VRRenderModelError_TooManyVertices = 304, + VRRenderModelError_MultipleTextures = 305, + VRRenderModelError_BufferTooSmall = 306, + VRRenderModelError_NotEnoughNormals = 307, + VRRenderModelError_NotEnoughTexCoords = 308, + + VRRenderModelError_InvalidTexture = 400, +}; + +typedef uint32_t VRComponentProperties; + +enum EVRComponentProperty +{ + VRComponentProperty_IsStatic = (1 << 0), + VRComponentProperty_IsVisible = (1 << 1), + VRComponentProperty_IsTouched = (1 << 2), + VRComponentProperty_IsPressed = (1 << 3), + VRComponentProperty_IsScrolled = (1 << 4), +}; + +/** Describes state information about a render-model component, including transforms and other dynamic properties */ +struct RenderModel_ComponentState_t +{ + HmdMatrix34_t mTrackingToComponentRenderModel; // Transform required when drawing the component render model + HmdMatrix34_t mTrackingToComponentLocal; // Transform available for attaching to a local component coordinate system (-Z out from surface ) + VRComponentProperties uProperties; +}; + +/** A single vertex in a render model */ +struct RenderModel_Vertex_t +{ + HmdVector3_t vPosition; // position in meters in device space + HmdVector3_t vNormal; + float rfTextureCoord[2]; +}; + +/** A texture map for use on a render model */ +#if defined(__linux__) || defined(__APPLE__) +// This structure was originally defined mis-packed on Linux, preserved for +// compatibility. +#pragma pack( push, 4 ) +#endif + +struct RenderModel_TextureMap_t +{ + uint16_t unWidth, unHeight; // width and height of the texture map in pixels + const uint8_t *rubTextureMapData; // Map texture data. All textures are RGBA with 8 bits per channel per pixel. Data size is width * height * 4ub +}; +#if defined(__linux__) || defined(__APPLE__) +#pragma pack( pop ) +#endif + +/** Session unique texture identifier. Rendermodels which share the same texture will have the same id. +IDs <0 denote the texture is not present */ + +typedef int32_t TextureID_t; + +const TextureID_t INVALID_TEXTURE_ID = -1; + +#if defined(__linux__) || defined(__APPLE__) +// This structure was originally defined mis-packed on Linux, preserved for +// compatibility. +#pragma pack( push, 4 ) +#endif + +struct RenderModel_t +{ + const RenderModel_Vertex_t *rVertexData; // Vertex data for the mesh + uint32_t unVertexCount; // Number of vertices in the vertex data + const uint16_t *rIndexData; // Indices into the vertex data for each triangle + uint32_t unTriangleCount; // Number of triangles in the mesh. Index count is 3 * TriangleCount + TextureID_t diffuseTextureId; // Session unique texture identifier. Rendermodels which share the same texture will have the same id. <0 == texture not present +}; +#if defined(__linux__) || defined(__APPLE__) +#pragma pack( pop ) +#endif + + +struct RenderModel_ControllerMode_State_t +{ + bool bScrollWheelVisible; // is this controller currently set to be in a scroll wheel mode +}; + +#pragma pack( pop ) + +class IVRRenderModels +{ +public: + + /** Loads and returns a render model for use in the application. pchRenderModelName should be a render model name + * from the Prop_RenderModelName_String property or an absolute path name to a render model on disk. + * + * The resulting render model is valid until VR_Shutdown() is called or until FreeRenderModel() is called. When the + * application is finished with the render model it should call FreeRenderModel() to free the memory associated + * with the model. + * + * The method returns VRRenderModelError_Loading while the render model is still being loaded. + * The method returns VRRenderModelError_None once loaded successfully, otherwise will return an error. */ + virtual EVRRenderModelError LoadRenderModel_Async( const char *pchRenderModelName, RenderModel_t **ppRenderModel ) = 0; + + /** Frees a previously returned render model + * It is safe to call this on a null ptr. */ + virtual void FreeRenderModel( RenderModel_t *pRenderModel ) = 0; + + /** Loads and returns a texture for use in the application. */ + virtual EVRRenderModelError LoadTexture_Async( TextureID_t textureId, RenderModel_TextureMap_t **ppTexture ) = 0; + + /** Frees a previously returned texture + * It is safe to call this on a null ptr. */ + virtual void FreeTexture( RenderModel_TextureMap_t *pTexture ) = 0; + + /** Creates a D3D11 texture and loads data into it. */ + virtual EVRRenderModelError LoadTextureD3D11_Async( TextureID_t textureId, void *pD3D11Device, void **ppD3D11Texture2D ) = 0; + + /** Helper function to copy the bits into an existing texture. */ + virtual EVRRenderModelError LoadIntoTextureD3D11_Async( TextureID_t textureId, void *pDstTexture ) = 0; + + /** Use this to free textures created with LoadTextureD3D11_Async instead of calling Release on them. */ + virtual void FreeTextureD3D11( void *pD3D11Texture2D ) = 0; + + /** Use this to get the names of available render models. Index does not correlate to a tracked device index, but + * is only used for iterating over all available render models. If the index is out of range, this function will return 0. + * Otherwise, it will return the size of the buffer required for the name. */ + virtual uint32_t GetRenderModelName( uint32_t unRenderModelIndex, VR_OUT_STRING() char *pchRenderModelName, uint32_t unRenderModelNameLen ) = 0; + + /** Returns the number of available render models. */ + virtual uint32_t GetRenderModelCount() = 0; + + + /** Returns the number of components of the specified render model. + * Components are useful when client application wish to draw, label, or otherwise interact with components of tracked objects. + * Examples controller components: + * renderable things such as triggers, buttons + * non-renderable things which include coordinate systems such as 'tip', 'base', a neutral controller agnostic hand-pose + * If all controller components are enumerated and rendered, it will be equivalent to drawing the traditional render model + * Returns 0 if components not supported, >0 otherwise */ + virtual uint32_t GetComponentCount( const char *pchRenderModelName ) = 0; + + /** Use this to get the names of available components. Index does not correlate to a tracked device index, but + * is only used for iterating over all available components. If the index is out of range, this function will return 0. + * Otherwise, it will return the size of the buffer required for the name. */ + virtual uint32_t GetComponentName( const char *pchRenderModelName, uint32_t unComponentIndex, VR_OUT_STRING( ) char *pchComponentName, uint32_t unComponentNameLen ) = 0; + + /** Get the button mask for all buttons associated with this component + * If no buttons (or axes) are associated with this component, return 0 + * Note: multiple components may be associated with the same button. Ex: two grip buttons on a single controller. + * Note: A single component may be associated with multiple buttons. Ex: A trackpad which also provides "D-pad" functionality */ + virtual uint64_t GetComponentButtonMask( const char *pchRenderModelName, const char *pchComponentName ) = 0; + + /** Use this to get the render model name for the specified rendermode/component combination, to be passed to LoadRenderModel. + * If the component name is out of range, this function will return 0. + * Otherwise, it will return the size of the buffer required for the name. */ + virtual uint32_t GetComponentRenderModelName( const char *pchRenderModelName, const char *pchComponentName, VR_OUT_STRING( ) char *pchComponentRenderModelName, uint32_t unComponentRenderModelNameLen ) = 0; + + /** Use this to query information about the component, as a function of the controller state. + * + * For dynamic controller components (ex: trigger) values will reflect component motions + * For static components this will return a consistent value independent of the VRControllerState_t + * + * If the pchRenderModelName or pchComponentName is invalid, this will return false (and transforms will be set to identity). + * Otherwise, return true + * Note: For dynamic objects, visibility may be dynamic. (I.e., true/false will be returned based on controller state and controller mode state ) */ + virtual bool GetComponentState( const char *pchRenderModelName, const char *pchComponentName, const vr::VRControllerState_t *pControllerState, const RenderModel_ControllerMode_State_t *pState, RenderModel_ComponentState_t *pComponentState ) = 0; + + /** Returns true if the render model has a component with the specified name */ + virtual bool RenderModelHasComponent( const char *pchRenderModelName, const char *pchComponentName ) = 0; + + /** Returns the URL of the thumbnail image for this rendermodel */ + virtual uint32_t GetRenderModelThumbnailURL( const char *pchRenderModelName, VR_OUT_STRING() char *pchThumbnailURL, uint32_t unThumbnailURLLen, vr::EVRRenderModelError *peError ) = 0; + + /** Provides a render model path that will load the unskinned model if the model name provided has been replace by the user. If the model + * hasn't been replaced the path value will still be a valid path to load the model. Pass this to LoadRenderModel_Async, etc. to load the + * model. */ + virtual uint32_t GetRenderModelOriginalPath( const char *pchRenderModelName, VR_OUT_STRING() char *pchOriginalPath, uint32_t unOriginalPathLen, vr::EVRRenderModelError *peError ) = 0; + + /** Returns a string for a render model error */ + virtual const char *GetRenderModelErrorNameFromEnum( vr::EVRRenderModelError error ) = 0; +}; + +static const char * const IVRRenderModels_Version = "IVRRenderModels_005"; + +} + + +// ivrextendeddisplay.h +namespace vr +{ + + /** NOTE: Use of this interface is not recommended in production applications. It will not work for displays which use + * direct-to-display mode. Creating our own window is also incompatible with the VR compositor and is not available when the compositor is running. */ + class IVRExtendedDisplay + { + public: + + /** Size and position that the window needs to be on the VR display. */ + virtual void GetWindowBounds( int32_t *pnX, int32_t *pnY, uint32_t *pnWidth, uint32_t *pnHeight ) = 0; + + /** Gets the viewport in the frame buffer to draw the output of the distortion into */ + virtual void GetEyeOutputViewport( EVREye eEye, uint32_t *pnX, uint32_t *pnY, uint32_t *pnWidth, uint32_t *pnHeight ) = 0; + + /** [D3D10/11 Only] + * Returns the adapter index and output index that the user should pass into EnumAdapters and EnumOutputs + * to create the device and swap chain in DX10 and DX11. If an error occurs both indices will be set to -1. + */ + virtual void GetDXGIOutputInfo( int32_t *pnAdapterIndex, int32_t *pnAdapterOutputIndex ) = 0; + + }; + + static const char * const IVRExtendedDisplay_Version = "IVRExtendedDisplay_001"; + +} + + +// ivrtrackedcamera.h +namespace vr +{ + +class IVRTrackedCamera +{ +public: + /** Returns a string for an error */ + virtual const char *GetCameraErrorNameFromEnum( vr::EVRTrackedCameraError eCameraError ) = 0; + + /** For convenience, same as tracked property request Prop_HasCamera_Bool */ + virtual vr::EVRTrackedCameraError HasCamera( vr::TrackedDeviceIndex_t nDeviceIndex, bool *pHasCamera ) = 0; + + /** Gets size of the image frame. */ + virtual vr::EVRTrackedCameraError GetCameraFrameSize( vr::TrackedDeviceIndex_t nDeviceIndex, vr::EVRTrackedCameraFrameType eFrameType, uint32_t *pnWidth, uint32_t *pnHeight, uint32_t *pnFrameBufferSize ) = 0; + + virtual vr::EVRTrackedCameraError GetCameraIntrinsics( vr::TrackedDeviceIndex_t nDeviceIndex, vr::EVRTrackedCameraFrameType eFrameType, vr::HmdVector2_t *pFocalLength, vr::HmdVector2_t *pCenter ) = 0; + + virtual vr::EVRTrackedCameraError GetCameraProjection( vr::TrackedDeviceIndex_t nDeviceIndex, vr::EVRTrackedCameraFrameType eFrameType, float flZNear, float flZFar, vr::HmdMatrix44_t *pProjection ) = 0; + + /** Acquiring streaming service permits video streaming for the caller. Releasing hints the system that video services do not need to be maintained for this client. + * If the camera has not already been activated, a one time spin up may incur some auto exposure as well as initial streaming frame delays. + * The camera should be considered a global resource accessible for shared consumption but not exclusive to any caller. + * The camera may go inactive due to lack of active consumers or headset idleness. */ + virtual vr::EVRTrackedCameraError AcquireVideoStreamingService( vr::TrackedDeviceIndex_t nDeviceIndex, vr::TrackedCameraHandle_t *pHandle ) = 0; + virtual vr::EVRTrackedCameraError ReleaseVideoStreamingService( vr::TrackedCameraHandle_t hTrackedCamera ) = 0; + + /** Copies the image frame into a caller's provided buffer. The image data is currently provided as RGBA data, 4 bytes per pixel. + * A caller can provide null for the framebuffer or frameheader if not desired. Requesting the frame header first, followed by the frame buffer allows + * the caller to determine if the frame as advanced per the frame header sequence. + * If there is no frame available yet, due to initial camera spinup or re-activation, the error will be VRTrackedCameraError_NoFrameAvailable. + * Ideally a caller should be polling at ~16ms intervals */ + virtual vr::EVRTrackedCameraError GetVideoStreamFrameBuffer( vr::TrackedCameraHandle_t hTrackedCamera, vr::EVRTrackedCameraFrameType eFrameType, void *pFrameBuffer, uint32_t nFrameBufferSize, vr::CameraVideoStreamFrameHeader_t *pFrameHeader, uint32_t nFrameHeaderSize ) = 0; + + /** Gets size of the image frame. */ + virtual vr::EVRTrackedCameraError GetVideoStreamTextureSize( vr::TrackedDeviceIndex_t nDeviceIndex, vr::EVRTrackedCameraFrameType eFrameType, vr::VRTextureBounds_t *pTextureBounds, uint32_t *pnWidth, uint32_t *pnHeight ) = 0; + + /** Access a shared D3D11 texture for the specified tracked camera stream. + * The camera frame type VRTrackedCameraFrameType_Undistorted is not supported directly as a shared texture. It is an interior subregion of the shared texture VRTrackedCameraFrameType_MaximumUndistorted. + * Instead, use GetVideoStreamTextureSize() with VRTrackedCameraFrameType_Undistorted to determine the proper interior subregion bounds along with GetVideoStreamTextureD3D11() with + * VRTrackedCameraFrameType_MaximumUndistorted to provide the texture. The VRTrackedCameraFrameType_MaximumUndistorted will yield an image where the invalid regions are decoded + * by the alpha channel having a zero component. The valid regions all have a non-zero alpha component. The subregion as described by VRTrackedCameraFrameType_Undistorted + * guarantees a rectangle where all pixels are valid. */ + virtual vr::EVRTrackedCameraError GetVideoStreamTextureD3D11( vr::TrackedCameraHandle_t hTrackedCamera, vr::EVRTrackedCameraFrameType eFrameType, void *pD3D11DeviceOrResource, void **ppD3D11ShaderResourceView, vr::CameraVideoStreamFrameHeader_t *pFrameHeader, uint32_t nFrameHeaderSize ) = 0; + + /** Access a shared GL texture for the specified tracked camera stream */ + virtual vr::EVRTrackedCameraError GetVideoStreamTextureGL( vr::TrackedCameraHandle_t hTrackedCamera, vr::EVRTrackedCameraFrameType eFrameType, vr::glUInt_t *pglTextureId, vr::CameraVideoStreamFrameHeader_t *pFrameHeader, uint32_t nFrameHeaderSize ) = 0; + virtual vr::EVRTrackedCameraError ReleaseVideoStreamTextureGL( vr::TrackedCameraHandle_t hTrackedCamera, vr::glUInt_t glTextureId ) = 0; +}; + +static const char * const IVRTrackedCamera_Version = "IVRTrackedCamera_003"; + +} // namespace vr + + +// ivrscreenshots.h +namespace vr +{ + +/** Errors that can occur with the VR compositor */ +enum EVRScreenshotError +{ + VRScreenshotError_None = 0, + VRScreenshotError_RequestFailed = 1, + VRScreenshotError_IncompatibleVersion = 100, + VRScreenshotError_NotFound = 101, + VRScreenshotError_BufferTooSmall = 102, + VRScreenshotError_ScreenshotAlreadyInProgress = 108, +}; + +/** Allows the application to generate screenshots */ +class IVRScreenshots +{ +public: + /** Request a screenshot of the requested type. + * A request of the VRScreenshotType_Stereo type will always + * work. Other types will depend on the underlying application + * support. + * The first file name is for the preview image and should be a + * regular screenshot (ideally from the left eye). The second + * is the VR screenshot in the correct format. They should be + * in the same aspect ratio. Formats per type: + * VRScreenshotType_Mono: the VR filename is ignored (can be + * nullptr), this is a normal flat single shot. + * VRScreenshotType_Stereo: The VR image should be a + * side-by-side with the left eye image on the left. + * VRScreenshotType_Cubemap: The VR image should be six square + * images composited horizontally. + * VRScreenshotType_StereoPanorama: above/below with left eye + * panorama being the above image. Image is typically square + * with the panorama being 2x horizontal. + * + * Note that the VR dashboard will call this function when + * the user presses the screenshot binding (currently System + * Button + Trigger). If Steam is running, the destination + * file names will be in %TEMP% and will be copied into + * Steam's screenshot library for the running application + * once SubmitScreenshot() is called. + * If Steam is not running, the paths will be in the user's + * documents folder under Documents\SteamVR\Screenshots. + * Other VR applications can call this to initiate a + * screenshot outside of user control. + * The destination file names do not need an extension, + * will be replaced with the correct one for the format + * which is currently .png. */ + virtual vr::EVRScreenshotError RequestScreenshot( vr::ScreenshotHandle_t *pOutScreenshotHandle, vr::EVRScreenshotType type, const char *pchPreviewFilename, const char *pchVRFilename ) = 0; + + /** Called by the running VR application to indicate that it + * wishes to be in charge of screenshots. If the + * application does not call this, the Compositor will only + * support VRScreenshotType_Stereo screenshots that will be + * captured without notification to the running app. + * Once hooked your application will receive a + * VREvent_RequestScreenshot event when the user presses the + * buttons to take a screenshot. */ + virtual vr::EVRScreenshotError HookScreenshot( VR_ARRAY_COUNT( numTypes ) const vr::EVRScreenshotType *pSupportedTypes, int numTypes ) = 0; + + /** When your application receives a + * VREvent_RequestScreenshot event, call these functions to get + * the details of the screenshot request. */ + virtual vr::EVRScreenshotType GetScreenshotPropertyType( vr::ScreenshotHandle_t screenshotHandle, vr::EVRScreenshotError *pError ) = 0; + + /** Get the filename for the preview or vr image (see + * vr::EScreenshotPropertyFilenames). The return value is + * the size of the string. */ + virtual uint32_t GetScreenshotPropertyFilename( vr::ScreenshotHandle_t screenshotHandle, vr::EVRScreenshotPropertyFilenames filenameType, VR_OUT_STRING() char *pchFilename, uint32_t cchFilename, vr::EVRScreenshotError *pError ) = 0; + + /** Call this if the application is taking the screen shot + * will take more than a few ms processing. This will result + * in an overlay being presented that shows a completion + * bar. */ + virtual vr::EVRScreenshotError UpdateScreenshotProgress( vr::ScreenshotHandle_t screenshotHandle, float flProgress ) = 0; + + /** Tells the compositor to take an internal screenshot of + * type VRScreenshotType_Stereo. It will take the current + * submitted scene textures of the running application and + * write them into the preview image and a side-by-side file + * for the VR image. + * This is similar to request screenshot, but doesn't ever + * talk to the application, just takes the shot and submits. */ + virtual vr::EVRScreenshotError TakeStereoScreenshot( vr::ScreenshotHandle_t *pOutScreenshotHandle, const char *pchPreviewFilename, const char *pchVRFilename ) = 0; + + /** Submit the completed screenshot. If Steam is running + * this will call into the Steam client and upload the + * screenshot to the screenshots section of the library for + * the running application. If Steam is not running, this + * function will display a notification to the user that the + * screenshot was taken. The paths should be full paths with + * extensions. + * File paths should be absolute including extensions. + * screenshotHandle can be k_unScreenshotHandleInvalid if this + * was a new shot taking by the app to be saved and not + * initiated by a user (achievement earned or something) */ + virtual vr::EVRScreenshotError SubmitScreenshot( vr::ScreenshotHandle_t screenshotHandle, vr::EVRScreenshotType type, const char *pchSourcePreviewFilename, const char *pchSourceVRFilename ) = 0; +}; + +static const char * const IVRScreenshots_Version = "IVRScreenshots_001"; + +} // namespace vr + + + +// ivrresources.h +namespace vr +{ + +class IVRResources +{ +public: + + // ------------------------------------ + // Shared Resource Methods + // ------------------------------------ + + /** Loads the specified resource into the provided buffer if large enough. + * Returns the size in bytes of the buffer required to hold the specified resource. */ + virtual uint32_t LoadSharedResource( const char *pchResourceName, char *pchBuffer, uint32_t unBufferLen ) = 0; + + /** Provides the full path to the specified resource. Resource names can include named directories for + * drivers and other things, and this resolves all of those and returns the actual physical path. + * pchResourceTypeDirectory is the subdirectory of resources to look in. */ + virtual uint32_t GetResourceFullPath( const char *pchResourceName, const char *pchResourceTypeDirectory, VR_OUT_STRING() char *pchPathBuffer, uint32_t unBufferLen ) = 0; +}; + +static const char * const IVRResources_Version = "IVRResources_001"; + + +} +// ivrdrivermanager.h +namespace vr +{ + +class IVRDriverManager +{ +public: + virtual uint32_t GetDriverCount() const = 0; + + /** Returns the length of the number of bytes necessary to hold this string including the trailing null. */ + virtual uint32_t GetDriverName( vr::DriverId_t nDriver, VR_OUT_STRING() char *pchValue, uint32_t unBufferSize ) = 0; + + virtual DriverHandle_t GetDriverHandle( const char *pchDriverName ) = 0; +}; + +static const char * const IVRDriverManager_Version = "IVRDriverManager_001"; + +} // namespace vr + + + +// ivrinput.h +namespace vr +{ + + typedef uint64_t VRActionHandle_t; + typedef uint64_t VRActionSetHandle_t; + typedef uint64_t VRInputValueHandle_t; + + static const VRActionHandle_t k_ulInvalidActionHandle = 0; + static const VRActionSetHandle_t k_ulInvalidActionSetHandle = 0; + static const VRInputValueHandle_t k_ulInvalidInputValueHandle = 0; + + static const uint32_t k_unMaxActionNameLength = 64; + static const uint32_t k_unMaxActionSetNameLength = 64; + static const uint32_t k_unMaxActionOriginCount = 16; + + struct InputAnalogActionData_t + { + // Whether or not this action is currently available to be bound in the active action set + bool bActive; + + // The origin that caused this action's current state + VRInputValueHandle_t activeOrigin; + + // The current state of this action; will be delta updates for mouse actions + float x, y, z; + + // Deltas since the previous call to UpdateActionState() + float deltaX, deltaY, deltaZ; + + // Time relative to now when this event happened. Will be negative to indicate a past time. + float fUpdateTime; + }; + + struct InputDigitalActionData_t + { + // Whether or not this action is currently available to be bound in the active action set + bool bActive; + + // The origin that caused this action's current state + VRInputValueHandle_t activeOrigin; + + // The current state of this action; will be true if currently pressed + bool bState; + + // This is true if the state has changed since the last frame + bool bChanged; + + // Time relative to now when this event happened. Will be negative to indicate a past time. + float fUpdateTime; + }; + + struct InputPoseActionData_t + { + // Whether or not this action is currently available to be bound in the active action set + bool bActive; + + // The origin that caused this action's current state + VRInputValueHandle_t activeOrigin; + + // The current state of this action + TrackedDevicePose_t pose; + }; + + enum EVRSkeletalTransformSpace + { + VRSkeletalTransformSpace_Action = 0, + VRSkeletalTransformSpace_Parent = 1, + VRSkeletalTransformSpace_Additive = 2, + }; + + + struct InputSkeletonActionData_t + { + // Whether or not this action is currently available to be bound in the active action set + bool bActive; + + // The origin that caused this action's current state + VRInputValueHandle_t activeOrigin; + }; + + enum EVRInputFilterCancelType + { + VRInputFilterCancel_Timers = 0, + VRInputFilterCancel_Momentum = 1, + }; + + struct InputOriginInfo_t + { + VRInputValueHandle_t devicePath; + TrackedDeviceIndex_t trackedDeviceIndex; + char rchRenderModelComponentName[128]; + }; + + struct VRActiveActionSet_t + { + /** This is the handle of the action set to activate for this frame. */ + VRActionSetHandle_t ulActionSet; + + /** This is the handle of a device path that this action set should be active for. To + * activate for all devices, set this to k_ulInvalidInputValueHandle. */ + VRInputValueHandle_t ulRestrictedToDevice; + + /** The action set to activate for all devices other than ulRestrictedDevice. If + * ulRestrictedToDevice is set to k_ulInvalidInputValueHandle, this parameter is + * ignored. */ + VRActionSetHandle_t ulSecondaryActionSet; + }; + + + class IVRInput + { + public: + + // --------------- Handle management --------------- // + + /** Sets the path to the action manifest JSON file that is used by this application. If this information + * was set on the Steam partner site, calls to this function are ignored. If the Steam partner site + * setting and the path provided by this call are different, VRInputError_MismatchedActionManifest is returned. + * This call must be made before the first call to UpdateActionState or IVRSystem::PollNextEvent. */ + virtual EVRInputError SetActionManifestPath( const char *pchActionManifestPath ) = 0; + + /** Returns a handle for an action set. This handle is used for all performance-sensitive calls. */ + virtual EVRInputError GetActionSetHandle( const char *pchActionSetName, VRActionSetHandle_t *pHandle ) = 0; + + /** Returns a handle for an action. This handle is used for all performance-sensitive calls. */ + virtual EVRInputError GetActionHandle( const char *pchActionName, VRActionHandle_t *pHandle ) = 0; + + /** Returns a handle for any path in the input system. E.g. /user/hand/right */ + virtual EVRInputError GetInputSourceHandle( const char *pchInputSourcePath, VRInputValueHandle_t *pHandle ) = 0; + + // --------------- Reading action state ------------------- // + + /** Reads the current state into all actions. After this call, the results of Get*Action calls + * will be the same until the next call to UpdateActionState. */ + virtual EVRInputError UpdateActionState( VR_ARRAY_COUNT( unSetCount ) VRActiveActionSet_t *pSets, uint32_t unSizeOfVRSelectedActionSet_t, uint32_t unSetCount ) = 0; + + /** Reads the state of a digital action given its handle. This will return VRInputError_WrongType if the type of + * action is something other than digital */ + virtual EVRInputError GetDigitalActionData( VRActionHandle_t action, InputDigitalActionData_t *pActionData, uint32_t unActionDataSize ) = 0; + + /** Reads the state of an analog action given its handle. This will return VRInputError_WrongType if the type of + * action is something other than analog */ + virtual EVRInputError GetAnalogActionData( VRActionHandle_t action, InputAnalogActionData_t *pActionData, uint32_t unActionDataSize ) = 0; + + /** Reads the state of a pose action given its handle. */ + virtual EVRInputError GetPoseActionData( VRActionHandle_t action, ETrackingUniverseOrigin eOrigin, float fPredictedSecondsFromNow, InputPoseActionData_t *pActionData, uint32_t unActionDataSize ) = 0; + + /** Reads the state of a skeletal action given its handle. */ + virtual EVRInputError GetSkeletalActionData( VRActionHandle_t action, EVRSkeletalTransformSpace eBoneParent, float fPredictedSecondsFromNow, InputSkeletonActionData_t *pActionData, uint32_t unActionDataSize, VR_ARRAY_COUNT( unTransformArrayCount ) VRBoneTransform_t *pTransformArray, uint32_t unTransformArrayCount ) = 0; + + /** Reads the state of a skeletal action given its handle in a compressed form that is suitable for + * sending over the network. The required buffer size will never exceed ( sizeof(VR_BoneTransform_t)*boneCount + 2). + * Usually the size will be much smaller. */ + virtual EVRInputError GetSkeletalActionDataCompressed( VRActionHandle_t action, EVRSkeletalTransformSpace eBoneParent, float fPredictedSecondsFromNow, VR_OUT_BUFFER_COUNT( unCompressedSize ) void *pvCompressedData, uint32_t unCompressedSize, uint32_t *punRequiredCompressedSize ) = 0; + + /** Turns a compressed buffer from GetSkeletalActionDataCompressed and turns it back into a bone transform array. */ + virtual EVRInputError UncompressSkeletalActionData( void *pvCompressedBuffer, uint32_t unCompressedBufferSize, EVRSkeletalTransformSpace *peBoneParent, VR_ARRAY_COUNT( unTransformArrayCount ) VRBoneTransform_t *pTransformArray, uint32_t unTransformArrayCount ) = 0; + + // --------------- Haptics ------------------- // + + /** Triggers a haptic event as described by the specified action */ + virtual EVRInputError TriggerHapticVibrationAction( VRActionHandle_t action, float fStartSecondsFromNow, float fDurationSeconds, float fFrequency, float fAmplitude ) = 0; + + // --------------- Action Origins ---------------- // + + /** Retrieve origin handles for an action */ + virtual EVRInputError GetActionOrigins( VRActionSetHandle_t actionSetHandle, VRActionHandle_t digitalActionHandle, VR_ARRAY_COUNT( originOutCount ) VRInputValueHandle_t *originsOut, uint32_t originOutCount ) = 0; + + /** Retrieves the name of the origin in the current language */ + virtual EVRInputError GetOriginLocalizedName( VRInputValueHandle_t origin, VR_OUT_STRING() char *pchNameArray, uint32_t unNameArraySize ) = 0; + + /** Retrieves useful information for the origin of this action */ + virtual EVRInputError GetOriginTrackedDeviceInfo( VRInputValueHandle_t origin, InputOriginInfo_t *pOriginInfo, uint32_t unOriginInfoSize ) = 0; + + /** Shows the current binding for the action in-headset */ + virtual EVRInputError ShowActionOrigins( VRActionSetHandle_t actionSetHandle, VRActionHandle_t ulActionHandle ) = 0; + + /** Shows the current binding all the actions in the specified action sets */ + virtual EVRInputError ShowBindingsForActionSet( VR_ARRAY_COUNT( unSetCount ) VRActiveActionSet_t *pSets, uint32_t unSizeOfVRSelectedActionSet_t, uint32_t unSetCount, VRInputValueHandle_t originToHighlight ) = 0; + }; + + static const char * const IVRInput_Version = "IVRInput_003"; + +} // namespace vr + +// ivriobuffer.h +namespace vr +{ + +typedef uint64_t IOBufferHandle_t; +static const uint64_t k_ulInvalidIOBufferHandle = 0; + + enum EIOBufferError + { + IOBuffer_Success = 0, + IOBuffer_OperationFailed = 100, + IOBuffer_InvalidHandle = 101, + IOBuffer_InvalidArgument = 102, + IOBuffer_PathExists = 103, + IOBuffer_PathDoesNotExist = 104, + IOBuffer_Permission = 105, + }; + + enum EIOBufferMode + { + IOBufferMode_Read = 0x0001, + IOBufferMode_Write = 0x0002, + IOBufferMode_Create = 0x0200, + }; + + // ---------------------------------------------------------------------------------------------- + // Purpose: + // ---------------------------------------------------------------------------------------------- + class IVRIOBuffer + { + public: + /** opens an existing or creates a new IOBuffer of unSize bytes */ + virtual vr::EIOBufferError Open( const char *pchPath, vr::EIOBufferMode mode, uint32_t unElementSize, uint32_t unElements, vr::IOBufferHandle_t *pulBuffer ) = 0; + + /** closes a previously opened or created buffer */ + virtual vr::EIOBufferError Close( vr::IOBufferHandle_t ulBuffer ) = 0; + + /** reads up to unBytes from buffer into *pDst, returning number of bytes read in *punRead */ + virtual vr::EIOBufferError Read( vr::IOBufferHandle_t ulBuffer, void *pDst, uint32_t unBytes, uint32_t *punRead ) = 0; + + /** writes unBytes of data from *pSrc into a buffer. */ + virtual vr::EIOBufferError Write( vr::IOBufferHandle_t ulBuffer, void *pSrc, uint32_t unBytes ) = 0; + + /** retrieves the property container of an buffer. */ + virtual vr::PropertyContainerHandle_t PropertyContainer( vr::IOBufferHandle_t ulBuffer ) = 0; + }; + + static const char *IVRIOBuffer_Version = "IVRIOBuffer_001"; +} +// End + +#endif // _OPENVR_API + + +namespace vr +{ + /** Finds the active installation of the VR API and initializes it. The provided path must be absolute + * or relative to the current working directory. These are the local install versions of the equivalent + * functions in steamvr.h and will work without a local Steam install. + * + * This path is to the "root" of the VR API install. That's the directory with + * the "drivers" directory and a platform (i.e. "win32") directory in it, not the directory with the DLL itself. + * + * pStartupInfo is reserved for future use. + */ + inline IVRSystem *VR_Init( EVRInitError *peError, EVRApplicationType eApplicationType, const char *pStartupInfo = nullptr ); + + /** unloads vrclient.dll. Any interface pointers from the interface are + * invalid after this point */ + inline void VR_Shutdown(); + + /** Returns true if there is an HMD attached. This check is as lightweight as possible and + * can be called outside of VR_Init/VR_Shutdown. It should be used when an application wants + * to know if initializing VR is a possibility but isn't ready to take that step yet. + */ + VR_INTERFACE bool VR_CALLTYPE VR_IsHmdPresent(); + + /** Returns true if the OpenVR runtime is installed. */ + VR_INTERFACE bool VR_CALLTYPE VR_IsRuntimeInstalled(); + + /** Returns where the OpenVR runtime is installed. */ + VR_INTERFACE const char *VR_CALLTYPE VR_RuntimePath(); + + /** Returns the name of the enum value for an EVRInitError. This function may be called outside of VR_Init()/VR_Shutdown(). */ + VR_INTERFACE const char *VR_CALLTYPE VR_GetVRInitErrorAsSymbol( EVRInitError error ); + + /** Returns an English string for an EVRInitError. Applications should call VR_GetVRInitErrorAsSymbol instead and + * use that as a key to look up their own localized error message. This function may be called outside of VR_Init()/VR_Shutdown(). */ + VR_INTERFACE const char *VR_CALLTYPE VR_GetVRInitErrorAsEnglishDescription( EVRInitError error ); + + /** Returns the interface of the specified version. This method must be called after VR_Init. The + * pointer returned is valid until VR_Shutdown is called. + */ + VR_INTERFACE void *VR_CALLTYPE VR_GetGenericInterface( const char *pchInterfaceVersion, EVRInitError *peError ); + + /** Returns whether the interface of the specified version exists. + */ + VR_INTERFACE bool VR_CALLTYPE VR_IsInterfaceVersionValid( const char *pchInterfaceVersion ); + + /** Returns a token that represents whether the VR interface handles need to be reloaded */ + VR_INTERFACE uint32_t VR_CALLTYPE VR_GetInitToken(); + + // These typedefs allow old enum names from SDK 0.9.11 to be used in applications. + // They will go away in the future. + typedef EVRInitError HmdError; + typedef EVREye Hmd_Eye; + typedef EColorSpace ColorSpace; + typedef ETrackingResult HmdTrackingResult; + typedef ETrackedDeviceClass TrackedDeviceClass; + typedef ETrackingUniverseOrigin TrackingUniverseOrigin; + typedef ETrackedDeviceProperty TrackedDeviceProperty; + typedef ETrackedPropertyError TrackedPropertyError; + typedef EVRSubmitFlags VRSubmitFlags_t; + typedef EVRState VRState_t; + typedef ECollisionBoundsStyle CollisionBoundsStyle_t; + typedef EVROverlayError VROverlayError; + typedef EVRFirmwareError VRFirmwareError; + typedef EVRCompositorError VRCompositorError; + typedef EVRScreenshotError VRScreenshotsError; + + inline uint32_t &VRToken() + { + static uint32_t token; + return token; + } + + class COpenVRContext + { + public: + COpenVRContext() { Clear(); } + void Clear(); + + inline void CheckClear() + { + if ( VRToken() != VR_GetInitToken() ) + { + Clear(); + VRToken() = VR_GetInitToken(); + } + } + + IVRSystem *VRSystem() + { + CheckClear(); + if ( m_pVRSystem == nullptr ) + { + EVRInitError eError; + m_pVRSystem = ( IVRSystem * )VR_GetGenericInterface( IVRSystem_Version, &eError ); + } + return m_pVRSystem; + } + IVRChaperone *VRChaperone() + { + CheckClear(); + if ( m_pVRChaperone == nullptr ) + { + EVRInitError eError; + m_pVRChaperone = ( IVRChaperone * )VR_GetGenericInterface( IVRChaperone_Version, &eError ); + } + return m_pVRChaperone; + } + + IVRChaperoneSetup *VRChaperoneSetup() + { + CheckClear(); + if ( m_pVRChaperoneSetup == nullptr ) + { + EVRInitError eError; + m_pVRChaperoneSetup = ( IVRChaperoneSetup * )VR_GetGenericInterface( IVRChaperoneSetup_Version, &eError ); + } + return m_pVRChaperoneSetup; + } + + IVRCompositor *VRCompositor() + { + CheckClear(); + if ( m_pVRCompositor == nullptr ) + { + EVRInitError eError; + m_pVRCompositor = ( IVRCompositor * )VR_GetGenericInterface( IVRCompositor_Version, &eError ); + } + return m_pVRCompositor; + } + + IVROverlay *VROverlay() + { + CheckClear(); + if ( m_pVROverlay == nullptr ) + { + EVRInitError eError; + m_pVROverlay = ( IVROverlay * )VR_GetGenericInterface( IVROverlay_Version, &eError ); + } + return m_pVROverlay; + } + + IVRResources *VRResources() + { + CheckClear(); + if ( m_pVRResources == nullptr ) + { + EVRInitError eError; + m_pVRResources = (IVRResources *)VR_GetGenericInterface( IVRResources_Version, &eError ); + } + return m_pVRResources; + } + + IVRScreenshots *VRScreenshots() + { + CheckClear(); + if ( m_pVRScreenshots == nullptr ) + { + EVRInitError eError; + m_pVRScreenshots = ( IVRScreenshots * )VR_GetGenericInterface( IVRScreenshots_Version, &eError ); + } + return m_pVRScreenshots; + } + + IVRRenderModels *VRRenderModels() + { + CheckClear(); + if ( m_pVRRenderModels == nullptr ) + { + EVRInitError eError; + m_pVRRenderModels = ( IVRRenderModels * )VR_GetGenericInterface( IVRRenderModels_Version, &eError ); + } + return m_pVRRenderModels; + } + + IVRExtendedDisplay *VRExtendedDisplay() + { + CheckClear(); + if ( m_pVRExtendedDisplay == nullptr ) + { + EVRInitError eError; + m_pVRExtendedDisplay = ( IVRExtendedDisplay * )VR_GetGenericInterface( IVRExtendedDisplay_Version, &eError ); + } + return m_pVRExtendedDisplay; + } + + IVRSettings *VRSettings() + { + CheckClear(); + if ( m_pVRSettings == nullptr ) + { + EVRInitError eError; + m_pVRSettings = ( IVRSettings * )VR_GetGenericInterface( IVRSettings_Version, &eError ); + } + return m_pVRSettings; + } + + IVRApplications *VRApplications() + { + CheckClear(); + if ( m_pVRApplications == nullptr ) + { + EVRInitError eError; + m_pVRApplications = ( IVRApplications * )VR_GetGenericInterface( IVRApplications_Version, &eError ); + } + return m_pVRApplications; + } + + IVRTrackedCamera *VRTrackedCamera() + { + CheckClear(); + if ( m_pVRTrackedCamera == nullptr ) + { + EVRInitError eError; + m_pVRTrackedCamera = ( IVRTrackedCamera * )VR_GetGenericInterface( IVRTrackedCamera_Version, &eError ); + } + return m_pVRTrackedCamera; + } + + IVRDriverManager *VRDriverManager() + { + CheckClear(); + if ( !m_pVRDriverManager ) + { + EVRInitError eError; + m_pVRDriverManager = ( IVRDriverManager * )VR_GetGenericInterface( IVRDriverManager_Version, &eError ); + } + return m_pVRDriverManager; + } + + IVRInput *VRInput() + { + CheckClear(); + if ( !m_pVRInput ) + { + EVRInitError eError; + m_pVRInput = (IVRInput *)VR_GetGenericInterface( IVRInput_Version, &eError ); + } + return m_pVRInput; + } + + IVRIOBuffer *VRIOBuffer() + { + if ( !m_pVRIOBuffer ) + { + EVRInitError eError; + m_pVRIOBuffer = ( IVRIOBuffer * )VR_GetGenericInterface( IVRIOBuffer_Version, &eError ); + } + return m_pVRIOBuffer; + } + + private: + IVRSystem *m_pVRSystem; + IVRChaperone *m_pVRChaperone; + IVRChaperoneSetup *m_pVRChaperoneSetup; + IVRCompositor *m_pVRCompositor; + IVROverlay *m_pVROverlay; + IVRResources *m_pVRResources; + IVRRenderModels *m_pVRRenderModels; + IVRExtendedDisplay *m_pVRExtendedDisplay; + IVRSettings *m_pVRSettings; + IVRApplications *m_pVRApplications; + IVRTrackedCamera *m_pVRTrackedCamera; + IVRScreenshots *m_pVRScreenshots; + IVRDriverManager *m_pVRDriverManager; + IVRInput *m_pVRInput; + IVRIOBuffer *m_pVRIOBuffer; + }; + + inline COpenVRContext &OpenVRInternal_ModuleContext() + { + static void *ctx[ sizeof( COpenVRContext ) / sizeof( void * ) ]; + return *( COpenVRContext * )ctx; // bypass zero-init constructor + } + + inline IVRSystem *VR_CALLTYPE VRSystem() { return OpenVRInternal_ModuleContext().VRSystem(); } + inline IVRChaperone *VR_CALLTYPE VRChaperone() { return OpenVRInternal_ModuleContext().VRChaperone(); } + inline IVRChaperoneSetup *VR_CALLTYPE VRChaperoneSetup() { return OpenVRInternal_ModuleContext().VRChaperoneSetup(); } + inline IVRCompositor *VR_CALLTYPE VRCompositor() { return OpenVRInternal_ModuleContext().VRCompositor(); } + inline IVROverlay *VR_CALLTYPE VROverlay() { return OpenVRInternal_ModuleContext().VROverlay(); } + inline IVRScreenshots *VR_CALLTYPE VRScreenshots() { return OpenVRInternal_ModuleContext().VRScreenshots(); } + inline IVRRenderModels *VR_CALLTYPE VRRenderModels() { return OpenVRInternal_ModuleContext().VRRenderModels(); } + inline IVRApplications *VR_CALLTYPE VRApplications() { return OpenVRInternal_ModuleContext().VRApplications(); } + inline IVRSettings *VR_CALLTYPE VRSettings() { return OpenVRInternal_ModuleContext().VRSettings(); } + inline IVRResources *VR_CALLTYPE VRResources() { return OpenVRInternal_ModuleContext().VRResources(); } + inline IVRExtendedDisplay *VR_CALLTYPE VRExtendedDisplay() { return OpenVRInternal_ModuleContext().VRExtendedDisplay(); } + inline IVRTrackedCamera *VR_CALLTYPE VRTrackedCamera() { return OpenVRInternal_ModuleContext().VRTrackedCamera(); } + inline IVRDriverManager *VR_CALLTYPE VRDriverManager() { return OpenVRInternal_ModuleContext().VRDriverManager(); } + inline IVRInput *VR_CALLTYPE VRInput() { return OpenVRInternal_ModuleContext().VRInput(); } + inline IVRIOBuffer *VR_CALLTYPE VRIOBuffer() { return OpenVRInternal_ModuleContext().VRIOBuffer(); } + + inline void COpenVRContext::Clear() + { + m_pVRSystem = nullptr; + m_pVRChaperone = nullptr; + m_pVRChaperoneSetup = nullptr; + m_pVRCompositor = nullptr; + m_pVROverlay = nullptr; + m_pVRRenderModels = nullptr; + m_pVRExtendedDisplay = nullptr; + m_pVRSettings = nullptr; + m_pVRApplications = nullptr; + m_pVRTrackedCamera = nullptr; + m_pVRResources = nullptr; + m_pVRScreenshots = nullptr; + m_pVRDriverManager = nullptr; + m_pVRInput = nullptr; + m_pVRIOBuffer = nullptr; + } + + VR_INTERFACE uint32_t VR_CALLTYPE VR_InitInternal2( EVRInitError *peError, EVRApplicationType eApplicationType, const char *pStartupInfo ); + VR_INTERFACE void VR_CALLTYPE VR_ShutdownInternal(); + + /** Finds the active installation of vrclient.dll and initializes it */ + inline IVRSystem *VR_Init( EVRInitError *peError, EVRApplicationType eApplicationType, const char *pStartupInfo ) + { + IVRSystem *pVRSystem = nullptr; + + EVRInitError eError; + VRToken() = VR_InitInternal2( &eError, eApplicationType, pStartupInfo ); + COpenVRContext &ctx = OpenVRInternal_ModuleContext(); + ctx.Clear(); + + if ( eError == VRInitError_None ) + { + if ( VR_IsInterfaceVersionValid( IVRSystem_Version ) ) + { + pVRSystem = VRSystem(); + } + else + { + VR_ShutdownInternal(); + eError = VRInitError_Init_InterfaceNotFound; + } + } + + if ( peError ) + *peError = eError; + return pVRSystem; + } + + /** unloads vrclient.dll. Any interface pointers from the interface are + * invalid after this point */ + inline void VR_Shutdown() + { + VR_ShutdownInternal(); + } +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/include/spirv/GLSL.std.450.h b/utils/dxvk-1.10.3/include/spirv/GLSL.std.450.h new file mode 100644 index 00000000000..54cc00e9a88 --- /dev/null +++ b/utils/dxvk-1.10.3/include/spirv/GLSL.std.450.h @@ -0,0 +1,131 @@ +/* +** Copyright (c) 2014-2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLstd450_H +#define GLSLstd450_H + +static const int GLSLstd450Version = 100; +static const int GLSLstd450Revision = 3; + +enum GLSLstd450 { + GLSLstd450Bad = 0, // Don't use + + GLSLstd450Round = 1, + GLSLstd450RoundEven = 2, + GLSLstd450Trunc = 3, + GLSLstd450FAbs = 4, + GLSLstd450SAbs = 5, + GLSLstd450FSign = 6, + GLSLstd450SSign = 7, + GLSLstd450Floor = 8, + GLSLstd450Ceil = 9, + GLSLstd450Fract = 10, + + GLSLstd450Radians = 11, + GLSLstd450Degrees = 12, + GLSLstd450Sin = 13, + GLSLstd450Cos = 14, + GLSLstd450Tan = 15, + GLSLstd450Asin = 16, + GLSLstd450Acos = 17, + GLSLstd450Atan = 18, + GLSLstd450Sinh = 19, + GLSLstd450Cosh = 20, + GLSLstd450Tanh = 21, + GLSLstd450Asinh = 22, + GLSLstd450Acosh = 23, + GLSLstd450Atanh = 24, + GLSLstd450Atan2 = 25, + + GLSLstd450Pow = 26, + GLSLstd450Exp = 27, + GLSLstd450Log = 28, + GLSLstd450Exp2 = 29, + GLSLstd450Log2 = 30, + GLSLstd450Sqrt = 31, + GLSLstd450InverseSqrt = 32, + + GLSLstd450Determinant = 33, + GLSLstd450MatrixInverse = 34, + + GLSLstd450Modf = 35, // second operand needs an OpVariable to write to + GLSLstd450ModfStruct = 36, // no OpVariable operand + GLSLstd450FMin = 37, + GLSLstd450UMin = 38, + GLSLstd450SMin = 39, + GLSLstd450FMax = 40, + GLSLstd450UMax = 41, + GLSLstd450SMax = 42, + GLSLstd450FClamp = 43, + GLSLstd450UClamp = 44, + GLSLstd450SClamp = 45, + GLSLstd450FMix = 46, + GLSLstd450IMix = 47, // Reserved + GLSLstd450Step = 48, + GLSLstd450SmoothStep = 49, + + GLSLstd450Fma = 50, + GLSLstd450Frexp = 51, // second operand needs an OpVariable to write to + GLSLstd450FrexpStruct = 52, // no OpVariable operand + GLSLstd450Ldexp = 53, + + GLSLstd450PackSnorm4x8 = 54, + GLSLstd450PackUnorm4x8 = 55, + GLSLstd450PackSnorm2x16 = 56, + GLSLstd450PackUnorm2x16 = 57, + GLSLstd450PackHalf2x16 = 58, + GLSLstd450PackDouble2x32 = 59, + GLSLstd450UnpackSnorm2x16 = 60, + GLSLstd450UnpackUnorm2x16 = 61, + GLSLstd450UnpackHalf2x16 = 62, + GLSLstd450UnpackSnorm4x8 = 63, + GLSLstd450UnpackUnorm4x8 = 64, + GLSLstd450UnpackDouble2x32 = 65, + + GLSLstd450Length = 66, + GLSLstd450Distance = 67, + GLSLstd450Cross = 68, + GLSLstd450Normalize = 69, + GLSLstd450FaceForward = 70, + GLSLstd450Reflect = 71, + GLSLstd450Refract = 72, + + GLSLstd450FindILsb = 73, + GLSLstd450FindSMsb = 74, + GLSLstd450FindUMsb = 75, + + GLSLstd450InterpolateAtCentroid = 76, + GLSLstd450InterpolateAtSample = 77, + GLSLstd450InterpolateAtOffset = 78, + + GLSLstd450NMin = 79, + GLSLstd450NMax = 80, + GLSLstd450NClamp = 81, + + GLSLstd450Count +}; + +#endif // #ifndef GLSLstd450_H diff --git a/utils/dxvk-1.10.3/include/spirv/GLSL.std.450.hpp b/utils/dxvk-1.10.3/include/spirv/GLSL.std.450.hpp new file mode 100644 index 00000000000..186436680a9 --- /dev/null +++ b/utils/dxvk-1.10.3/include/spirv/GLSL.std.450.hpp @@ -0,0 +1,135 @@ +/* +** Copyright (c) 2014-2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLstd450_HPP +#define GLSLstd450_HPP + +namespace spv { + +static const int GLSLstd450Version = 100; +static const int GLSLstd450Revision = 3; + +enum GLSLstd450 { + GLSLstd450Bad = 0, // Don't use + + GLSLstd450Round = 1, + GLSLstd450RoundEven = 2, + GLSLstd450Trunc = 3, + GLSLstd450FAbs = 4, + GLSLstd450SAbs = 5, + GLSLstd450FSign = 6, + GLSLstd450SSign = 7, + GLSLstd450Floor = 8, + GLSLstd450Ceil = 9, + GLSLstd450Fract = 10, + + GLSLstd450Radians = 11, + GLSLstd450Degrees = 12, + GLSLstd450Sin = 13, + GLSLstd450Cos = 14, + GLSLstd450Tan = 15, + GLSLstd450Asin = 16, + GLSLstd450Acos = 17, + GLSLstd450Atan = 18, + GLSLstd450Sinh = 19, + GLSLstd450Cosh = 20, + GLSLstd450Tanh = 21, + GLSLstd450Asinh = 22, + GLSLstd450Acosh = 23, + GLSLstd450Atanh = 24, + GLSLstd450Atan2 = 25, + + GLSLstd450Pow = 26, + GLSLstd450Exp = 27, + GLSLstd450Log = 28, + GLSLstd450Exp2 = 29, + GLSLstd450Log2 = 30, + GLSLstd450Sqrt = 31, + GLSLstd450InverseSqrt = 32, + + GLSLstd450Determinant = 33, + GLSLstd450MatrixInverse = 34, + + GLSLstd450Modf = 35, // second operand needs an OpVariable to write to + GLSLstd450ModfStruct = 36, // no OpVariable operand + GLSLstd450FMin = 37, + GLSLstd450UMin = 38, + GLSLstd450SMin = 39, + GLSLstd450FMax = 40, + GLSLstd450UMax = 41, + GLSLstd450SMax = 42, + GLSLstd450FClamp = 43, + GLSLstd450UClamp = 44, + GLSLstd450SClamp = 45, + GLSLstd450FMix = 46, + GLSLstd450IMix = 47, // Reserved + GLSLstd450Step = 48, + GLSLstd450SmoothStep = 49, + + GLSLstd450Fma = 50, + GLSLstd450Frexp = 51, // second operand needs an OpVariable to write to + GLSLstd450FrexpStruct = 52, // no OpVariable operand + GLSLstd450Ldexp = 53, + + GLSLstd450PackSnorm4x8 = 54, + GLSLstd450PackUnorm4x8 = 55, + GLSLstd450PackSnorm2x16 = 56, + GLSLstd450PackUnorm2x16 = 57, + GLSLstd450PackHalf2x16 = 58, + GLSLstd450PackDouble2x32 = 59, + GLSLstd450UnpackSnorm2x16 = 60, + GLSLstd450UnpackUnorm2x16 = 61, + GLSLstd450UnpackHalf2x16 = 62, + GLSLstd450UnpackSnorm4x8 = 63, + GLSLstd450UnpackUnorm4x8 = 64, + GLSLstd450UnpackDouble2x32 = 65, + + GLSLstd450Length = 66, + GLSLstd450Distance = 67, + GLSLstd450Cross = 68, + GLSLstd450Normalize = 69, + GLSLstd450FaceForward = 70, + GLSLstd450Reflect = 71, + GLSLstd450Refract = 72, + + GLSLstd450FindILsb = 73, + GLSLstd450FindSMsb = 74, + GLSLstd450FindUMsb = 75, + + GLSLstd450InterpolateAtCentroid = 76, + GLSLstd450InterpolateAtSample = 77, + GLSLstd450InterpolateAtOffset = 78, + + GLSLstd450NMin = 79, + GLSLstd450NMax = 80, + GLSLstd450NClamp = 81, + + GLSLstd450Count +}; + +} + +#endif // #ifndef GLSLstd450_HPP \ No newline at end of file diff --git a/utils/dxvk-1.10.3/include/spirv/spirv.hpp b/utils/dxvk-1.10.3/include/spirv/spirv.hpp new file mode 100644 index 00000000000..50cc20da324 --- /dev/null +++ b/utils/dxvk-1.10.3/include/spirv/spirv.hpp @@ -0,0 +1,1934 @@ +// Copyright (c) 2014-2019 The Khronos Group Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and/or associated documentation files (the "Materials"), +// to deal in the Materials without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Materials, and to permit persons to whom the +// Materials are furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Materials. +// +// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +// STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +// +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +// IN THE MATERIALS. + +// This header is automatically generated by the same tool that creates +// the Binary Section of the SPIR-V specification. + +// Enumeration tokens for SPIR-V, in various styles: +// C, C++, C++11, JSON, Lua, Python, C#, D +// +// - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL +// - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL +// - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL +// - Lua will use tables, e.g.: spv.SourceLanguage.GLSL +// - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL'] +// - C# will use enum classes in the Specification class located in the "Spv" namespace, +// e.g.: Spv.Specification.SourceLanguage.GLSL +// - D will have tokens under the "spv" module, e.g: spv.SourceLanguage.GLSL +// +// Some tokens act like mask values, which can be OR'd together, +// while others are mutually exclusive. The mask-like ones have +// "Mask" in their name, and a parallel enum that has the shift +// amount (1 << x) for each corresponding enumerant. + +#ifndef spirv_HPP +#define spirv_HPP + +namespace spv { + +typedef unsigned int Id; + +#define SPV_VERSION 0x10400 +#define SPV_REVISION 1 + +static const unsigned int MagicNumber = 0x07230203; +static const unsigned int Version = 0x00010400; +static const unsigned int Revision = 1; +static const unsigned int OpCodeMask = 0xffff; +static const unsigned int WordCountShift = 16; + +enum SourceLanguage { + SourceLanguageUnknown = 0, + SourceLanguageESSL = 1, + SourceLanguageGLSL = 2, + SourceLanguageOpenCL_C = 3, + SourceLanguageOpenCL_CPP = 4, + SourceLanguageHLSL = 5, + SourceLanguageMax = 0x7fffffff, +}; + +enum ExecutionModel { + ExecutionModelVertex = 0, + ExecutionModelTessellationControl = 1, + ExecutionModelTessellationEvaluation = 2, + ExecutionModelGeometry = 3, + ExecutionModelFragment = 4, + ExecutionModelGLCompute = 5, + ExecutionModelKernel = 6, + ExecutionModelTaskNV = 5267, + ExecutionModelMeshNV = 5268, + ExecutionModelRayGenerationNV = 5313, + ExecutionModelIntersectionNV = 5314, + ExecutionModelAnyHitNV = 5315, + ExecutionModelClosestHitNV = 5316, + ExecutionModelMissNV = 5317, + ExecutionModelCallableNV = 5318, + ExecutionModelMax = 0x7fffffff, +}; + +enum AddressingModel { + AddressingModelLogical = 0, + AddressingModelPhysical32 = 1, + AddressingModelPhysical64 = 2, + AddressingModelPhysicalStorageBuffer64EXT = 5348, + AddressingModelMax = 0x7fffffff, +}; + +enum MemoryModel { + MemoryModelSimple = 0, + MemoryModelGLSL450 = 1, + MemoryModelOpenCL = 2, + MemoryModelVulkanKHR = 3, + MemoryModelMax = 0x7fffffff, +}; + +enum ExecutionMode { + ExecutionModeInvocations = 0, + ExecutionModeSpacingEqual = 1, + ExecutionModeSpacingFractionalEven = 2, + ExecutionModeSpacingFractionalOdd = 3, + ExecutionModeVertexOrderCw = 4, + ExecutionModeVertexOrderCcw = 5, + ExecutionModePixelCenterInteger = 6, + ExecutionModeOriginUpperLeft = 7, + ExecutionModeOriginLowerLeft = 8, + ExecutionModeEarlyFragmentTests = 9, + ExecutionModePointMode = 10, + ExecutionModeXfb = 11, + ExecutionModeDepthReplacing = 12, + ExecutionModeDepthGreater = 14, + ExecutionModeDepthLess = 15, + ExecutionModeDepthUnchanged = 16, + ExecutionModeLocalSize = 17, + ExecutionModeLocalSizeHint = 18, + ExecutionModeInputPoints = 19, + ExecutionModeInputLines = 20, + ExecutionModeInputLinesAdjacency = 21, + ExecutionModeTriangles = 22, + ExecutionModeInputTrianglesAdjacency = 23, + ExecutionModeQuads = 24, + ExecutionModeIsolines = 25, + ExecutionModeOutputVertices = 26, + ExecutionModeOutputPoints = 27, + ExecutionModeOutputLineStrip = 28, + ExecutionModeOutputTriangleStrip = 29, + ExecutionModeVecTypeHint = 30, + ExecutionModeContractionOff = 31, + ExecutionModeInitializer = 33, + ExecutionModeFinalizer = 34, + ExecutionModeSubgroupSize = 35, + ExecutionModeSubgroupsPerWorkgroup = 36, + ExecutionModeSubgroupsPerWorkgroupId = 37, + ExecutionModeLocalSizeId = 38, + ExecutionModeLocalSizeHintId = 39, + ExecutionModePostDepthCoverage = 4446, + ExecutionModeDenormPreserve = 4459, + ExecutionModeDenormFlushToZero = 4460, + ExecutionModeSignedZeroInfNanPreserve = 4461, + ExecutionModeRoundingModeRTE = 4462, + ExecutionModeRoundingModeRTZ = 4463, + ExecutionModeStencilRefReplacingEXT = 5027, + ExecutionModeOutputLinesNV = 5269, + ExecutionModeOutputPrimitivesNV = 5270, + ExecutionModeDerivativeGroupQuadsNV = 5289, + ExecutionModeDerivativeGroupLinearNV = 5290, + ExecutionModeOutputTrianglesNV = 5298, + ExecutionModePixelInterlockOrderedEXT = 5366, + ExecutionModePixelInterlockUnorderedEXT = 5367, + ExecutionModeSampleInterlockOrderedEXT = 5368, + ExecutionModeSampleInterlockUnorderedEXT = 5369, + ExecutionModeShadingRateInterlockOrderedEXT = 5370, + ExecutionModeShadingRateInterlockUnorderedEXT = 5371, + ExecutionModeMax = 0x7fffffff, +}; + +enum StorageClass { + StorageClassUniformConstant = 0, + StorageClassInput = 1, + StorageClassUniform = 2, + StorageClassOutput = 3, + StorageClassWorkgroup = 4, + StorageClassCrossWorkgroup = 5, + StorageClassPrivate = 6, + StorageClassFunction = 7, + StorageClassGeneric = 8, + StorageClassPushConstant = 9, + StorageClassAtomicCounter = 10, + StorageClassImage = 11, + StorageClassStorageBuffer = 12, + StorageClassCallableDataNV = 5328, + StorageClassIncomingCallableDataNV = 5329, + StorageClassRayPayloadNV = 5338, + StorageClassHitAttributeNV = 5339, + StorageClassIncomingRayPayloadNV = 5342, + StorageClassShaderRecordBufferNV = 5343, + StorageClassPhysicalStorageBufferEXT = 5349, + StorageClassMax = 0x7fffffff, +}; + +enum Dim { + Dim1D = 0, + Dim2D = 1, + Dim3D = 2, + DimCube = 3, + DimRect = 4, + DimBuffer = 5, + DimSubpassData = 6, + DimMax = 0x7fffffff, +}; + +enum SamplerAddressingMode { + SamplerAddressingModeNone = 0, + SamplerAddressingModeClampToEdge = 1, + SamplerAddressingModeClamp = 2, + SamplerAddressingModeRepeat = 3, + SamplerAddressingModeRepeatMirrored = 4, + SamplerAddressingModeMax = 0x7fffffff, +}; + +enum SamplerFilterMode { + SamplerFilterModeNearest = 0, + SamplerFilterModeLinear = 1, + SamplerFilterModeMax = 0x7fffffff, +}; + +enum ImageFormat { + ImageFormatUnknown = 0, + ImageFormatRgba32f = 1, + ImageFormatRgba16f = 2, + ImageFormatR32f = 3, + ImageFormatRgba8 = 4, + ImageFormatRgba8Snorm = 5, + ImageFormatRg32f = 6, + ImageFormatRg16f = 7, + ImageFormatR11fG11fB10f = 8, + ImageFormatR16f = 9, + ImageFormatRgba16 = 10, + ImageFormatRgb10A2 = 11, + ImageFormatRg16 = 12, + ImageFormatRg8 = 13, + ImageFormatR16 = 14, + ImageFormatR8 = 15, + ImageFormatRgba16Snorm = 16, + ImageFormatRg16Snorm = 17, + ImageFormatRg8Snorm = 18, + ImageFormatR16Snorm = 19, + ImageFormatR8Snorm = 20, + ImageFormatRgba32i = 21, + ImageFormatRgba16i = 22, + ImageFormatRgba8i = 23, + ImageFormatR32i = 24, + ImageFormatRg32i = 25, + ImageFormatRg16i = 26, + ImageFormatRg8i = 27, + ImageFormatR16i = 28, + ImageFormatR8i = 29, + ImageFormatRgba32ui = 30, + ImageFormatRgba16ui = 31, + ImageFormatRgba8ui = 32, + ImageFormatR32ui = 33, + ImageFormatRgb10a2ui = 34, + ImageFormatRg32ui = 35, + ImageFormatRg16ui = 36, + ImageFormatRg8ui = 37, + ImageFormatR16ui = 38, + ImageFormatR8ui = 39, + ImageFormatMax = 0x7fffffff, +}; + +enum ImageChannelOrder { + ImageChannelOrderR = 0, + ImageChannelOrderA = 1, + ImageChannelOrderRG = 2, + ImageChannelOrderRA = 3, + ImageChannelOrderRGB = 4, + ImageChannelOrderRGBA = 5, + ImageChannelOrderBGRA = 6, + ImageChannelOrderARGB = 7, + ImageChannelOrderIntensity = 8, + ImageChannelOrderLuminance = 9, + ImageChannelOrderRx = 10, + ImageChannelOrderRGx = 11, + ImageChannelOrderRGBx = 12, + ImageChannelOrderDepth = 13, + ImageChannelOrderDepthStencil = 14, + ImageChannelOrdersRGB = 15, + ImageChannelOrdersRGBx = 16, + ImageChannelOrdersRGBA = 17, + ImageChannelOrdersBGRA = 18, + ImageChannelOrderABGR = 19, + ImageChannelOrderMax = 0x7fffffff, +}; + +enum ImageChannelDataType { + ImageChannelDataTypeSnormInt8 = 0, + ImageChannelDataTypeSnormInt16 = 1, + ImageChannelDataTypeUnormInt8 = 2, + ImageChannelDataTypeUnormInt16 = 3, + ImageChannelDataTypeUnormShort565 = 4, + ImageChannelDataTypeUnormShort555 = 5, + ImageChannelDataTypeUnormInt101010 = 6, + ImageChannelDataTypeSignedInt8 = 7, + ImageChannelDataTypeSignedInt16 = 8, + ImageChannelDataTypeSignedInt32 = 9, + ImageChannelDataTypeUnsignedInt8 = 10, + ImageChannelDataTypeUnsignedInt16 = 11, + ImageChannelDataTypeUnsignedInt32 = 12, + ImageChannelDataTypeHalfFloat = 13, + ImageChannelDataTypeFloat = 14, + ImageChannelDataTypeUnormInt24 = 15, + ImageChannelDataTypeUnormInt101010_2 = 16, + ImageChannelDataTypeMax = 0x7fffffff, +}; + +enum ImageOperandsShift { + ImageOperandsBiasShift = 0, + ImageOperandsLodShift = 1, + ImageOperandsGradShift = 2, + ImageOperandsConstOffsetShift = 3, + ImageOperandsOffsetShift = 4, + ImageOperandsConstOffsetsShift = 5, + ImageOperandsSampleShift = 6, + ImageOperandsMinLodShift = 7, + ImageOperandsMakeTexelAvailableKHRShift = 8, + ImageOperandsMakeTexelVisibleKHRShift = 9, + ImageOperandsNonPrivateTexelKHRShift = 10, + ImageOperandsVolatileTexelKHRShift = 11, + ImageOperandsSignExtendShift = 12, + ImageOperandsZeroExtendShift = 13, + ImageOperandsMax = 0x7fffffff, +}; + +enum ImageOperandsMask { + ImageOperandsMaskNone = 0, + ImageOperandsBiasMask = 0x00000001, + ImageOperandsLodMask = 0x00000002, + ImageOperandsGradMask = 0x00000004, + ImageOperandsConstOffsetMask = 0x00000008, + ImageOperandsOffsetMask = 0x00000010, + ImageOperandsConstOffsetsMask = 0x00000020, + ImageOperandsSampleMask = 0x00000040, + ImageOperandsMinLodMask = 0x00000080, + ImageOperandsMakeTexelAvailableKHRMask = 0x00000100, + ImageOperandsMakeTexelVisibleKHRMask = 0x00000200, + ImageOperandsNonPrivateTexelKHRMask = 0x00000400, + ImageOperandsVolatileTexelKHRMask = 0x00000800, + ImageOperandsSignExtendMask = 0x00001000, + ImageOperandsZeroExtendMask = 0x00002000, +}; + +enum FPFastMathModeShift { + FPFastMathModeNotNaNShift = 0, + FPFastMathModeNotInfShift = 1, + FPFastMathModeNSZShift = 2, + FPFastMathModeAllowRecipShift = 3, + FPFastMathModeFastShift = 4, + FPFastMathModeMax = 0x7fffffff, +}; + +enum FPFastMathModeMask { + FPFastMathModeMaskNone = 0, + FPFastMathModeNotNaNMask = 0x00000001, + FPFastMathModeNotInfMask = 0x00000002, + FPFastMathModeNSZMask = 0x00000004, + FPFastMathModeAllowRecipMask = 0x00000008, + FPFastMathModeFastMask = 0x00000010, +}; + +enum FPRoundingMode { + FPRoundingModeRTE = 0, + FPRoundingModeRTZ = 1, + FPRoundingModeRTP = 2, + FPRoundingModeRTN = 3, + FPRoundingModeMax = 0x7fffffff, +}; + +enum LinkageType { + LinkageTypeExport = 0, + LinkageTypeImport = 1, + LinkageTypeMax = 0x7fffffff, +}; + +enum AccessQualifier { + AccessQualifierReadOnly = 0, + AccessQualifierWriteOnly = 1, + AccessQualifierReadWrite = 2, + AccessQualifierMax = 0x7fffffff, +}; + +enum FunctionParameterAttribute { + FunctionParameterAttributeZext = 0, + FunctionParameterAttributeSext = 1, + FunctionParameterAttributeByVal = 2, + FunctionParameterAttributeSret = 3, + FunctionParameterAttributeNoAlias = 4, + FunctionParameterAttributeNoCapture = 5, + FunctionParameterAttributeNoWrite = 6, + FunctionParameterAttributeNoReadWrite = 7, + FunctionParameterAttributeMax = 0x7fffffff, +}; + +enum Decoration { + DecorationRelaxedPrecision = 0, + DecorationSpecId = 1, + DecorationBlock = 2, + DecorationBufferBlock = 3, + DecorationRowMajor = 4, + DecorationColMajor = 5, + DecorationArrayStride = 6, + DecorationMatrixStride = 7, + DecorationGLSLShared = 8, + DecorationGLSLPacked = 9, + DecorationCPacked = 10, + DecorationBuiltIn = 11, + DecorationNoPerspective = 13, + DecorationFlat = 14, + DecorationPatch = 15, + DecorationCentroid = 16, + DecorationSample = 17, + DecorationInvariant = 18, + DecorationRestrict = 19, + DecorationAliased = 20, + DecorationVolatile = 21, + DecorationConstant = 22, + DecorationCoherent = 23, + DecorationNonWritable = 24, + DecorationNonReadable = 25, + DecorationUniform = 26, + DecorationUniformId = 27, + DecorationSaturatedConversion = 28, + DecorationStream = 29, + DecorationLocation = 30, + DecorationComponent = 31, + DecorationIndex = 32, + DecorationBinding = 33, + DecorationDescriptorSet = 34, + DecorationOffset = 35, + DecorationXfbBuffer = 36, + DecorationXfbStride = 37, + DecorationFuncParamAttr = 38, + DecorationFPRoundingMode = 39, + DecorationFPFastMathMode = 40, + DecorationLinkageAttributes = 41, + DecorationNoContraction = 42, + DecorationInputAttachmentIndex = 43, + DecorationAlignment = 44, + DecorationMaxByteOffset = 45, + DecorationAlignmentId = 46, + DecorationMaxByteOffsetId = 47, + DecorationNoSignedWrap = 4469, + DecorationNoUnsignedWrap = 4470, + DecorationExplicitInterpAMD = 4999, + DecorationOverrideCoverageNV = 5248, + DecorationPassthroughNV = 5250, + DecorationViewportRelativeNV = 5252, + DecorationSecondaryViewportRelativeNV = 5256, + DecorationPerPrimitiveNV = 5271, + DecorationPerViewNV = 5272, + DecorationPerTaskNV = 5273, + DecorationPerVertexNV = 5285, + DecorationNonUniformEXT = 5300, + DecorationRestrictPointerEXT = 5355, + DecorationAliasedPointerEXT = 5356, + DecorationCounterBuffer = 5634, + DecorationHlslCounterBufferGOOGLE = 5634, + DecorationHlslSemanticGOOGLE = 5635, + DecorationUserSemantic = 5635, + DecorationUserTypeGOOGLE = 5636, + DecorationMax = 0x7fffffff, +}; + +enum BuiltIn { + BuiltInPosition = 0, + BuiltInPointSize = 1, + BuiltInClipDistance = 3, + BuiltInCullDistance = 4, + BuiltInVertexId = 5, + BuiltInInstanceId = 6, + BuiltInPrimitiveId = 7, + BuiltInInvocationId = 8, + BuiltInLayer = 9, + BuiltInViewportIndex = 10, + BuiltInTessLevelOuter = 11, + BuiltInTessLevelInner = 12, + BuiltInTessCoord = 13, + BuiltInPatchVertices = 14, + BuiltInFragCoord = 15, + BuiltInPointCoord = 16, + BuiltInFrontFacing = 17, + BuiltInSampleId = 18, + BuiltInSamplePosition = 19, + BuiltInSampleMask = 20, + BuiltInFragDepth = 22, + BuiltInHelperInvocation = 23, + BuiltInNumWorkgroups = 24, + BuiltInWorkgroupSize = 25, + BuiltInWorkgroupId = 26, + BuiltInLocalInvocationId = 27, + BuiltInGlobalInvocationId = 28, + BuiltInLocalInvocationIndex = 29, + BuiltInWorkDim = 30, + BuiltInGlobalSize = 31, + BuiltInEnqueuedWorkgroupSize = 32, + BuiltInGlobalOffset = 33, + BuiltInGlobalLinearId = 34, + BuiltInSubgroupSize = 36, + BuiltInSubgroupMaxSize = 37, + BuiltInNumSubgroups = 38, + BuiltInNumEnqueuedSubgroups = 39, + BuiltInSubgroupId = 40, + BuiltInSubgroupLocalInvocationId = 41, + BuiltInVertexIndex = 42, + BuiltInInstanceIndex = 43, + BuiltInSubgroupEqMask = 4416, + BuiltInSubgroupEqMaskKHR = 4416, + BuiltInSubgroupGeMask = 4417, + BuiltInSubgroupGeMaskKHR = 4417, + BuiltInSubgroupGtMask = 4418, + BuiltInSubgroupGtMaskKHR = 4418, + BuiltInSubgroupLeMask = 4419, + BuiltInSubgroupLeMaskKHR = 4419, + BuiltInSubgroupLtMask = 4420, + BuiltInSubgroupLtMaskKHR = 4420, + BuiltInBaseVertex = 4424, + BuiltInBaseInstance = 4425, + BuiltInDrawIndex = 4426, + BuiltInDeviceIndex = 4438, + BuiltInViewIndex = 4440, + BuiltInBaryCoordNoPerspAMD = 4992, + BuiltInBaryCoordNoPerspCentroidAMD = 4993, + BuiltInBaryCoordNoPerspSampleAMD = 4994, + BuiltInBaryCoordSmoothAMD = 4995, + BuiltInBaryCoordSmoothCentroidAMD = 4996, + BuiltInBaryCoordSmoothSampleAMD = 4997, + BuiltInBaryCoordPullModelAMD = 4998, + BuiltInFragStencilRefEXT = 5014, + BuiltInViewportMaskNV = 5253, + BuiltInSecondaryPositionNV = 5257, + BuiltInSecondaryViewportMaskNV = 5258, + BuiltInPositionPerViewNV = 5261, + BuiltInViewportMaskPerViewNV = 5262, + BuiltInFullyCoveredEXT = 5264, + BuiltInTaskCountNV = 5274, + BuiltInPrimitiveCountNV = 5275, + BuiltInPrimitiveIndicesNV = 5276, + BuiltInClipDistancePerViewNV = 5277, + BuiltInCullDistancePerViewNV = 5278, + BuiltInLayerPerViewNV = 5279, + BuiltInMeshViewCountNV = 5280, + BuiltInMeshViewIndicesNV = 5281, + BuiltInBaryCoordNV = 5286, + BuiltInBaryCoordNoPerspNV = 5287, + BuiltInFragSizeEXT = 5292, + BuiltInFragmentSizeNV = 5292, + BuiltInFragInvocationCountEXT = 5293, + BuiltInInvocationsPerPixelNV = 5293, + BuiltInLaunchIdNV = 5319, + BuiltInLaunchSizeNV = 5320, + BuiltInWorldRayOriginNV = 5321, + BuiltInWorldRayDirectionNV = 5322, + BuiltInObjectRayOriginNV = 5323, + BuiltInObjectRayDirectionNV = 5324, + BuiltInRayTminNV = 5325, + BuiltInRayTmaxNV = 5326, + BuiltInInstanceCustomIndexNV = 5327, + BuiltInObjectToWorldNV = 5330, + BuiltInWorldToObjectNV = 5331, + BuiltInHitTNV = 5332, + BuiltInHitKindNV = 5333, + BuiltInIncomingRayFlagsNV = 5351, + BuiltInWarpsPerSMNV = 5374, + BuiltInSMCountNV = 5375, + BuiltInWarpIDNV = 5376, + BuiltInSMIDNV = 5377, + BuiltInMax = 0x7fffffff, +}; + +enum SelectionControlShift { + SelectionControlFlattenShift = 0, + SelectionControlDontFlattenShift = 1, + SelectionControlMax = 0x7fffffff, +}; + +enum SelectionControlMask { + SelectionControlMaskNone = 0, + SelectionControlFlattenMask = 0x00000001, + SelectionControlDontFlattenMask = 0x00000002, +}; + +enum LoopControlShift { + LoopControlUnrollShift = 0, + LoopControlDontUnrollShift = 1, + LoopControlDependencyInfiniteShift = 2, + LoopControlDependencyLengthShift = 3, + LoopControlMinIterationsShift = 4, + LoopControlMaxIterationsShift = 5, + LoopControlIterationMultipleShift = 6, + LoopControlPeelCountShift = 7, + LoopControlPartialCountShift = 8, + LoopControlMax = 0x7fffffff, +}; + +enum LoopControlMask { + LoopControlMaskNone = 0, + LoopControlUnrollMask = 0x00000001, + LoopControlDontUnrollMask = 0x00000002, + LoopControlDependencyInfiniteMask = 0x00000004, + LoopControlDependencyLengthMask = 0x00000008, + LoopControlMinIterationsMask = 0x00000010, + LoopControlMaxIterationsMask = 0x00000020, + LoopControlIterationMultipleMask = 0x00000040, + LoopControlPeelCountMask = 0x00000080, + LoopControlPartialCountMask = 0x00000100, +}; + +enum FunctionControlShift { + FunctionControlInlineShift = 0, + FunctionControlDontInlineShift = 1, + FunctionControlPureShift = 2, + FunctionControlConstShift = 3, + FunctionControlMax = 0x7fffffff, +}; + +enum FunctionControlMask { + FunctionControlMaskNone = 0, + FunctionControlInlineMask = 0x00000001, + FunctionControlDontInlineMask = 0x00000002, + FunctionControlPureMask = 0x00000004, + FunctionControlConstMask = 0x00000008, +}; + +enum MemorySemanticsShift { + MemorySemanticsAcquireShift = 1, + MemorySemanticsReleaseShift = 2, + MemorySemanticsAcquireReleaseShift = 3, + MemorySemanticsSequentiallyConsistentShift = 4, + MemorySemanticsUniformMemoryShift = 6, + MemorySemanticsSubgroupMemoryShift = 7, + MemorySemanticsWorkgroupMemoryShift = 8, + MemorySemanticsCrossWorkgroupMemoryShift = 9, + MemorySemanticsAtomicCounterMemoryShift = 10, + MemorySemanticsImageMemoryShift = 11, + MemorySemanticsOutputMemoryKHRShift = 12, + MemorySemanticsMakeAvailableKHRShift = 13, + MemorySemanticsMakeVisibleKHRShift = 14, + MemorySemanticsVolatileShift = 15, + MemorySemanticsMax = 0x7fffffff, +}; + +enum MemorySemanticsMask { + MemorySemanticsMaskNone = 0, + MemorySemanticsAcquireMask = 0x00000002, + MemorySemanticsReleaseMask = 0x00000004, + MemorySemanticsAcquireReleaseMask = 0x00000008, + MemorySemanticsSequentiallyConsistentMask = 0x00000010, + MemorySemanticsUniformMemoryMask = 0x00000040, + MemorySemanticsSubgroupMemoryMask = 0x00000080, + MemorySemanticsWorkgroupMemoryMask = 0x00000100, + MemorySemanticsCrossWorkgroupMemoryMask = 0x00000200, + MemorySemanticsAtomicCounterMemoryMask = 0x00000400, + MemorySemanticsImageMemoryMask = 0x00000800, + MemorySemanticsOutputMemoryKHRMask = 0x00001000, + MemorySemanticsMakeAvailableKHRMask = 0x00002000, + MemorySemanticsMakeVisibleKHRMask = 0x00004000, + MemorySemanticsVolatileMask = 0x00008000, +}; + +enum MemoryAccessShift { + MemoryAccessVolatileShift = 0, + MemoryAccessAlignedShift = 1, + MemoryAccessNontemporalShift = 2, + MemoryAccessMakePointerAvailableKHRShift = 3, + MemoryAccessMakePointerVisibleKHRShift = 4, + MemoryAccessNonPrivatePointerKHRShift = 5, + MemoryAccessMax = 0x7fffffff, +}; + +enum MemoryAccessMask { + MemoryAccessMaskNone = 0, + MemoryAccessVolatileMask = 0x00000001, + MemoryAccessAlignedMask = 0x00000002, + MemoryAccessNontemporalMask = 0x00000004, + MemoryAccessMakePointerAvailableKHRMask = 0x00000008, + MemoryAccessMakePointerVisibleKHRMask = 0x00000010, + MemoryAccessNonPrivatePointerKHRMask = 0x00000020, +}; + +enum Scope { + ScopeCrossDevice = 0, + ScopeDevice = 1, + ScopeWorkgroup = 2, + ScopeSubgroup = 3, + ScopeInvocation = 4, + ScopeQueueFamilyKHR = 5, + ScopeMax = 0x7fffffff, +}; + +enum GroupOperation { + GroupOperationReduce = 0, + GroupOperationInclusiveScan = 1, + GroupOperationExclusiveScan = 2, + GroupOperationClusteredReduce = 3, + GroupOperationPartitionedReduceNV = 6, + GroupOperationPartitionedInclusiveScanNV = 7, + GroupOperationPartitionedExclusiveScanNV = 8, + GroupOperationMax = 0x7fffffff, +}; + +enum KernelEnqueueFlags { + KernelEnqueueFlagsNoWait = 0, + KernelEnqueueFlagsWaitKernel = 1, + KernelEnqueueFlagsWaitWorkGroup = 2, + KernelEnqueueFlagsMax = 0x7fffffff, +}; + +enum KernelProfilingInfoShift { + KernelProfilingInfoCmdExecTimeShift = 0, + KernelProfilingInfoMax = 0x7fffffff, +}; + +enum KernelProfilingInfoMask { + KernelProfilingInfoMaskNone = 0, + KernelProfilingInfoCmdExecTimeMask = 0x00000001, +}; + +enum Capability { + CapabilityMatrix = 0, + CapabilityShader = 1, + CapabilityGeometry = 2, + CapabilityTessellation = 3, + CapabilityAddresses = 4, + CapabilityLinkage = 5, + CapabilityKernel = 6, + CapabilityVector16 = 7, + CapabilityFloat16Buffer = 8, + CapabilityFloat16 = 9, + CapabilityFloat64 = 10, + CapabilityInt64 = 11, + CapabilityInt64Atomics = 12, + CapabilityImageBasic = 13, + CapabilityImageReadWrite = 14, + CapabilityImageMipmap = 15, + CapabilityPipes = 17, + CapabilityGroups = 18, + CapabilityDeviceEnqueue = 19, + CapabilityLiteralSampler = 20, + CapabilityAtomicStorage = 21, + CapabilityInt16 = 22, + CapabilityTessellationPointSize = 23, + CapabilityGeometryPointSize = 24, + CapabilityImageGatherExtended = 25, + CapabilityStorageImageMultisample = 27, + CapabilityUniformBufferArrayDynamicIndexing = 28, + CapabilitySampledImageArrayDynamicIndexing = 29, + CapabilityStorageBufferArrayDynamicIndexing = 30, + CapabilityStorageImageArrayDynamicIndexing = 31, + CapabilityClipDistance = 32, + CapabilityCullDistance = 33, + CapabilityImageCubeArray = 34, + CapabilitySampleRateShading = 35, + CapabilityImageRect = 36, + CapabilitySampledRect = 37, + CapabilityGenericPointer = 38, + CapabilityInt8 = 39, + CapabilityInputAttachment = 40, + CapabilitySparseResidency = 41, + CapabilityMinLod = 42, + CapabilitySampled1D = 43, + CapabilityImage1D = 44, + CapabilitySampledCubeArray = 45, + CapabilitySampledBuffer = 46, + CapabilityImageBuffer = 47, + CapabilityImageMSArray = 48, + CapabilityStorageImageExtendedFormats = 49, + CapabilityImageQuery = 50, + CapabilityDerivativeControl = 51, + CapabilityInterpolationFunction = 52, + CapabilityTransformFeedback = 53, + CapabilityGeometryStreams = 54, + CapabilityStorageImageReadWithoutFormat = 55, + CapabilityStorageImageWriteWithoutFormat = 56, + CapabilityMultiViewport = 57, + CapabilitySubgroupDispatch = 58, + CapabilityNamedBarrier = 59, + CapabilityPipeStorage = 60, + CapabilityGroupNonUniform = 61, + CapabilityGroupNonUniformVote = 62, + CapabilityGroupNonUniformArithmetic = 63, + CapabilityGroupNonUniformBallot = 64, + CapabilityGroupNonUniformShuffle = 65, + CapabilityGroupNonUniformShuffleRelative = 66, + CapabilityGroupNonUniformClustered = 67, + CapabilityGroupNonUniformQuad = 68, + CapabilitySubgroupBallotKHR = 4423, + CapabilityDrawParameters = 4427, + CapabilitySubgroupVoteKHR = 4431, + CapabilityStorageBuffer16BitAccess = 4433, + CapabilityStorageUniformBufferBlock16 = 4433, + CapabilityStorageUniform16 = 4434, + CapabilityUniformAndStorageBuffer16BitAccess = 4434, + CapabilityStoragePushConstant16 = 4435, + CapabilityStorageInputOutput16 = 4436, + CapabilityDeviceGroup = 4437, + CapabilityMultiView = 4439, + CapabilityVariablePointersStorageBuffer = 4441, + CapabilityVariablePointers = 4442, + CapabilityAtomicStorageOps = 4445, + CapabilitySampleMaskPostDepthCoverage = 4447, + CapabilityStorageBuffer8BitAccess = 4448, + CapabilityUniformAndStorageBuffer8BitAccess = 4449, + CapabilityStoragePushConstant8 = 4450, + CapabilityDenormPreserve = 4464, + CapabilityDenormFlushToZero = 4465, + CapabilitySignedZeroInfNanPreserve = 4466, + CapabilityRoundingModeRTE = 4467, + CapabilityRoundingModeRTZ = 4468, + CapabilityFloat16ImageAMD = 5008, + CapabilityImageGatherBiasLodAMD = 5009, + CapabilityFragmentMaskAMD = 5010, + CapabilityStencilExportEXT = 5013, + CapabilityImageReadWriteLodAMD = 5015, + CapabilitySampleMaskOverrideCoverageNV = 5249, + CapabilityGeometryShaderPassthroughNV = 5251, + CapabilityShaderViewportIndexLayerEXT = 5254, + CapabilityShaderViewportIndexLayerNV = 5254, + CapabilityShaderViewportMaskNV = 5255, + CapabilityShaderStereoViewNV = 5259, + CapabilityPerViewAttributesNV = 5260, + CapabilityFragmentFullyCoveredEXT = 5265, + CapabilityMeshShadingNV = 5266, + CapabilityImageFootprintNV = 5282, + CapabilityFragmentBarycentricNV = 5284, + CapabilityComputeDerivativeGroupQuadsNV = 5288, + CapabilityFragmentDensityEXT = 5291, + CapabilityShadingRateNV = 5291, + CapabilityGroupNonUniformPartitionedNV = 5297, + CapabilityShaderNonUniformEXT = 5301, + CapabilityRuntimeDescriptorArrayEXT = 5302, + CapabilityInputAttachmentArrayDynamicIndexingEXT = 5303, + CapabilityUniformTexelBufferArrayDynamicIndexingEXT = 5304, + CapabilityStorageTexelBufferArrayDynamicIndexingEXT = 5305, + CapabilityUniformBufferArrayNonUniformIndexingEXT = 5306, + CapabilitySampledImageArrayNonUniformIndexingEXT = 5307, + CapabilityStorageBufferArrayNonUniformIndexingEXT = 5308, + CapabilityStorageImageArrayNonUniformIndexingEXT = 5309, + CapabilityInputAttachmentArrayNonUniformIndexingEXT = 5310, + CapabilityUniformTexelBufferArrayNonUniformIndexingEXT = 5311, + CapabilityStorageTexelBufferArrayNonUniformIndexingEXT = 5312, + CapabilityRayTracingNV = 5340, + CapabilityVulkanMemoryModelKHR = 5345, + CapabilityVulkanMemoryModelDeviceScopeKHR = 5346, + CapabilityPhysicalStorageBufferAddressesEXT = 5347, + CapabilityComputeDerivativeGroupLinearNV = 5350, + CapabilityCooperativeMatrixNV = 5357, + CapabilityFragmentShaderSampleInterlockEXT = 5363, + CapabilityFragmentShaderShadingRateInterlockEXT = 5372, + CapabilityShaderSMBuiltinsNV = 5373, + CapabilityFragmentShaderPixelInterlockEXT = 5378, + CapabilityDemoteToHelperInvocationEXT = 5379, + CapabilitySubgroupShuffleINTEL = 5568, + CapabilitySubgroupBufferBlockIOINTEL = 5569, + CapabilitySubgroupImageBlockIOINTEL = 5570, + CapabilitySubgroupImageMediaBlockIOINTEL = 5579, + CapabilityIntegerFunctions2INTEL = 5584, + CapabilitySubgroupAvcMotionEstimationINTEL = 5696, + CapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697, + CapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698, + CapabilityMax = 0x7fffffff, +}; + +enum Op { + OpNop = 0, + OpUndef = 1, + OpSourceContinued = 2, + OpSource = 3, + OpSourceExtension = 4, + OpName = 5, + OpMemberName = 6, + OpString = 7, + OpLine = 8, + OpExtension = 10, + OpExtInstImport = 11, + OpExtInst = 12, + OpMemoryModel = 14, + OpEntryPoint = 15, + OpExecutionMode = 16, + OpCapability = 17, + OpTypeVoid = 19, + OpTypeBool = 20, + OpTypeInt = 21, + OpTypeFloat = 22, + OpTypeVector = 23, + OpTypeMatrix = 24, + OpTypeImage = 25, + OpTypeSampler = 26, + OpTypeSampledImage = 27, + OpTypeArray = 28, + OpTypeRuntimeArray = 29, + OpTypeStruct = 30, + OpTypeOpaque = 31, + OpTypePointer = 32, + OpTypeFunction = 33, + OpTypeEvent = 34, + OpTypeDeviceEvent = 35, + OpTypeReserveId = 36, + OpTypeQueue = 37, + OpTypePipe = 38, + OpTypeForwardPointer = 39, + OpConstantTrue = 41, + OpConstantFalse = 42, + OpConstant = 43, + OpConstantComposite = 44, + OpConstantSampler = 45, + OpConstantNull = 46, + OpSpecConstantTrue = 48, + OpSpecConstantFalse = 49, + OpSpecConstant = 50, + OpSpecConstantComposite = 51, + OpSpecConstantOp = 52, + OpFunction = 54, + OpFunctionParameter = 55, + OpFunctionEnd = 56, + OpFunctionCall = 57, + OpVariable = 59, + OpImageTexelPointer = 60, + OpLoad = 61, + OpStore = 62, + OpCopyMemory = 63, + OpCopyMemorySized = 64, + OpAccessChain = 65, + OpInBoundsAccessChain = 66, + OpPtrAccessChain = 67, + OpArrayLength = 68, + OpGenericPtrMemSemantics = 69, + OpInBoundsPtrAccessChain = 70, + OpDecorate = 71, + OpMemberDecorate = 72, + OpDecorationGroup = 73, + OpGroupDecorate = 74, + OpGroupMemberDecorate = 75, + OpVectorExtractDynamic = 77, + OpVectorInsertDynamic = 78, + OpVectorShuffle = 79, + OpCompositeConstruct = 80, + OpCompositeExtract = 81, + OpCompositeInsert = 82, + OpCopyObject = 83, + OpTranspose = 84, + OpSampledImage = 86, + OpImageSampleImplicitLod = 87, + OpImageSampleExplicitLod = 88, + OpImageSampleDrefImplicitLod = 89, + OpImageSampleDrefExplicitLod = 90, + OpImageSampleProjImplicitLod = 91, + OpImageSampleProjExplicitLod = 92, + OpImageSampleProjDrefImplicitLod = 93, + OpImageSampleProjDrefExplicitLod = 94, + OpImageFetch = 95, + OpImageGather = 96, + OpImageDrefGather = 97, + OpImageRead = 98, + OpImageWrite = 99, + OpImage = 100, + OpImageQueryFormat = 101, + OpImageQueryOrder = 102, + OpImageQuerySizeLod = 103, + OpImageQuerySize = 104, + OpImageQueryLod = 105, + OpImageQueryLevels = 106, + OpImageQuerySamples = 107, + OpConvertFToU = 109, + OpConvertFToS = 110, + OpConvertSToF = 111, + OpConvertUToF = 112, + OpUConvert = 113, + OpSConvert = 114, + OpFConvert = 115, + OpQuantizeToF16 = 116, + OpConvertPtrToU = 117, + OpSatConvertSToU = 118, + OpSatConvertUToS = 119, + OpConvertUToPtr = 120, + OpPtrCastToGeneric = 121, + OpGenericCastToPtr = 122, + OpGenericCastToPtrExplicit = 123, + OpBitcast = 124, + OpSNegate = 126, + OpFNegate = 127, + OpIAdd = 128, + OpFAdd = 129, + OpISub = 130, + OpFSub = 131, + OpIMul = 132, + OpFMul = 133, + OpUDiv = 134, + OpSDiv = 135, + OpFDiv = 136, + OpUMod = 137, + OpSRem = 138, + OpSMod = 139, + OpFRem = 140, + OpFMod = 141, + OpVectorTimesScalar = 142, + OpMatrixTimesScalar = 143, + OpVectorTimesMatrix = 144, + OpMatrixTimesVector = 145, + OpMatrixTimesMatrix = 146, + OpOuterProduct = 147, + OpDot = 148, + OpIAddCarry = 149, + OpISubBorrow = 150, + OpUMulExtended = 151, + OpSMulExtended = 152, + OpAny = 154, + OpAll = 155, + OpIsNan = 156, + OpIsInf = 157, + OpIsFinite = 158, + OpIsNormal = 159, + OpSignBitSet = 160, + OpLessOrGreater = 161, + OpOrdered = 162, + OpUnordered = 163, + OpLogicalEqual = 164, + OpLogicalNotEqual = 165, + OpLogicalOr = 166, + OpLogicalAnd = 167, + OpLogicalNot = 168, + OpSelect = 169, + OpIEqual = 170, + OpINotEqual = 171, + OpUGreaterThan = 172, + OpSGreaterThan = 173, + OpUGreaterThanEqual = 174, + OpSGreaterThanEqual = 175, + OpULessThan = 176, + OpSLessThan = 177, + OpULessThanEqual = 178, + OpSLessThanEqual = 179, + OpFOrdEqual = 180, + OpFUnordEqual = 181, + OpFOrdNotEqual = 182, + OpFUnordNotEqual = 183, + OpFOrdLessThan = 184, + OpFUnordLessThan = 185, + OpFOrdGreaterThan = 186, + OpFUnordGreaterThan = 187, + OpFOrdLessThanEqual = 188, + OpFUnordLessThanEqual = 189, + OpFOrdGreaterThanEqual = 190, + OpFUnordGreaterThanEqual = 191, + OpShiftRightLogical = 194, + OpShiftRightArithmetic = 195, + OpShiftLeftLogical = 196, + OpBitwiseOr = 197, + OpBitwiseXor = 198, + OpBitwiseAnd = 199, + OpNot = 200, + OpBitFieldInsert = 201, + OpBitFieldSExtract = 202, + OpBitFieldUExtract = 203, + OpBitReverse = 204, + OpBitCount = 205, + OpDPdx = 207, + OpDPdy = 208, + OpFwidth = 209, + OpDPdxFine = 210, + OpDPdyFine = 211, + OpFwidthFine = 212, + OpDPdxCoarse = 213, + OpDPdyCoarse = 214, + OpFwidthCoarse = 215, + OpEmitVertex = 218, + OpEndPrimitive = 219, + OpEmitStreamVertex = 220, + OpEndStreamPrimitive = 221, + OpControlBarrier = 224, + OpMemoryBarrier = 225, + OpAtomicLoad = 227, + OpAtomicStore = 228, + OpAtomicExchange = 229, + OpAtomicCompareExchange = 230, + OpAtomicCompareExchangeWeak = 231, + OpAtomicIIncrement = 232, + OpAtomicIDecrement = 233, + OpAtomicIAdd = 234, + OpAtomicISub = 235, + OpAtomicSMin = 236, + OpAtomicUMin = 237, + OpAtomicSMax = 238, + OpAtomicUMax = 239, + OpAtomicAnd = 240, + OpAtomicOr = 241, + OpAtomicXor = 242, + OpPhi = 245, + OpLoopMerge = 246, + OpSelectionMerge = 247, + OpLabel = 248, + OpBranch = 249, + OpBranchConditional = 250, + OpSwitch = 251, + OpKill = 252, + OpReturn = 253, + OpReturnValue = 254, + OpUnreachable = 255, + OpLifetimeStart = 256, + OpLifetimeStop = 257, + OpGroupAsyncCopy = 259, + OpGroupWaitEvents = 260, + OpGroupAll = 261, + OpGroupAny = 262, + OpGroupBroadcast = 263, + OpGroupIAdd = 264, + OpGroupFAdd = 265, + OpGroupFMin = 266, + OpGroupUMin = 267, + OpGroupSMin = 268, + OpGroupFMax = 269, + OpGroupUMax = 270, + OpGroupSMax = 271, + OpReadPipe = 274, + OpWritePipe = 275, + OpReservedReadPipe = 276, + OpReservedWritePipe = 277, + OpReserveReadPipePackets = 278, + OpReserveWritePipePackets = 279, + OpCommitReadPipe = 280, + OpCommitWritePipe = 281, + OpIsValidReserveId = 282, + OpGetNumPipePackets = 283, + OpGetMaxPipePackets = 284, + OpGroupReserveReadPipePackets = 285, + OpGroupReserveWritePipePackets = 286, + OpGroupCommitReadPipe = 287, + OpGroupCommitWritePipe = 288, + OpEnqueueMarker = 291, + OpEnqueueKernel = 292, + OpGetKernelNDrangeSubGroupCount = 293, + OpGetKernelNDrangeMaxSubGroupSize = 294, + OpGetKernelWorkGroupSize = 295, + OpGetKernelPreferredWorkGroupSizeMultiple = 296, + OpRetainEvent = 297, + OpReleaseEvent = 298, + OpCreateUserEvent = 299, + OpIsValidEvent = 300, + OpSetUserEventStatus = 301, + OpCaptureEventProfilingInfo = 302, + OpGetDefaultQueue = 303, + OpBuildNDRange = 304, + OpImageSparseSampleImplicitLod = 305, + OpImageSparseSampleExplicitLod = 306, + OpImageSparseSampleDrefImplicitLod = 307, + OpImageSparseSampleDrefExplicitLod = 308, + OpImageSparseSampleProjImplicitLod = 309, + OpImageSparseSampleProjExplicitLod = 310, + OpImageSparseSampleProjDrefImplicitLod = 311, + OpImageSparseSampleProjDrefExplicitLod = 312, + OpImageSparseFetch = 313, + OpImageSparseGather = 314, + OpImageSparseDrefGather = 315, + OpImageSparseTexelsResident = 316, + OpNoLine = 317, + OpAtomicFlagTestAndSet = 318, + OpAtomicFlagClear = 319, + OpImageSparseRead = 320, + OpSizeOf = 321, + OpTypePipeStorage = 322, + OpConstantPipeStorage = 323, + OpCreatePipeFromPipeStorage = 324, + OpGetKernelLocalSizeForSubgroupCount = 325, + OpGetKernelMaxNumSubgroups = 326, + OpTypeNamedBarrier = 327, + OpNamedBarrierInitialize = 328, + OpMemoryNamedBarrier = 329, + OpModuleProcessed = 330, + OpExecutionModeId = 331, + OpDecorateId = 332, + OpGroupNonUniformElect = 333, + OpGroupNonUniformAll = 334, + OpGroupNonUniformAny = 335, + OpGroupNonUniformAllEqual = 336, + OpGroupNonUniformBroadcast = 337, + OpGroupNonUniformBroadcastFirst = 338, + OpGroupNonUniformBallot = 339, + OpGroupNonUniformInverseBallot = 340, + OpGroupNonUniformBallotBitExtract = 341, + OpGroupNonUniformBallotBitCount = 342, + OpGroupNonUniformBallotFindLSB = 343, + OpGroupNonUniformBallotFindMSB = 344, + OpGroupNonUniformShuffle = 345, + OpGroupNonUniformShuffleXor = 346, + OpGroupNonUniformShuffleUp = 347, + OpGroupNonUniformShuffleDown = 348, + OpGroupNonUniformIAdd = 349, + OpGroupNonUniformFAdd = 350, + OpGroupNonUniformIMul = 351, + OpGroupNonUniformFMul = 352, + OpGroupNonUniformSMin = 353, + OpGroupNonUniformUMin = 354, + OpGroupNonUniformFMin = 355, + OpGroupNonUniformSMax = 356, + OpGroupNonUniformUMax = 357, + OpGroupNonUniformFMax = 358, + OpGroupNonUniformBitwiseAnd = 359, + OpGroupNonUniformBitwiseOr = 360, + OpGroupNonUniformBitwiseXor = 361, + OpGroupNonUniformLogicalAnd = 362, + OpGroupNonUniformLogicalOr = 363, + OpGroupNonUniformLogicalXor = 364, + OpGroupNonUniformQuadBroadcast = 365, + OpGroupNonUniformQuadSwap = 366, + OpCopyLogical = 400, + OpPtrEqual = 401, + OpPtrNotEqual = 402, + OpPtrDiff = 403, + OpSubgroupBallotKHR = 4421, + OpSubgroupFirstInvocationKHR = 4422, + OpSubgroupAllKHR = 4428, + OpSubgroupAnyKHR = 4429, + OpSubgroupAllEqualKHR = 4430, + OpSubgroupReadInvocationKHR = 4432, + OpGroupIAddNonUniformAMD = 5000, + OpGroupFAddNonUniformAMD = 5001, + OpGroupFMinNonUniformAMD = 5002, + OpGroupUMinNonUniformAMD = 5003, + OpGroupSMinNonUniformAMD = 5004, + OpGroupFMaxNonUniformAMD = 5005, + OpGroupUMaxNonUniformAMD = 5006, + OpGroupSMaxNonUniformAMD = 5007, + OpFragmentMaskFetchAMD = 5011, + OpFragmentFetchAMD = 5012, + OpImageSampleFootprintNV = 5283, + OpGroupNonUniformPartitionNV = 5296, + OpWritePackedPrimitiveIndices4x8NV = 5299, + OpReportIntersectionNV = 5334, + OpIgnoreIntersectionNV = 5335, + OpTerminateRayNV = 5336, + OpTraceNV = 5337, + OpTypeAccelerationStructureNV = 5341, + OpExecuteCallableNV = 5344, + OpTypeCooperativeMatrixNV = 5358, + OpCooperativeMatrixLoadNV = 5359, + OpCooperativeMatrixStoreNV = 5360, + OpCooperativeMatrixMulAddNV = 5361, + OpCooperativeMatrixLengthNV = 5362, + OpBeginInvocationInterlockEXT = 5364, + OpEndInvocationInterlockEXT = 5365, + OpDemoteToHelperInvocationEXT = 5380, + OpIsHelperInvocationEXT = 5381, + OpSubgroupShuffleINTEL = 5571, + OpSubgroupShuffleDownINTEL = 5572, + OpSubgroupShuffleUpINTEL = 5573, + OpSubgroupShuffleXorINTEL = 5574, + OpSubgroupBlockReadINTEL = 5575, + OpSubgroupBlockWriteINTEL = 5576, + OpSubgroupImageBlockReadINTEL = 5577, + OpSubgroupImageBlockWriteINTEL = 5578, + OpSubgroupImageMediaBlockReadINTEL = 5580, + OpSubgroupImageMediaBlockWriteINTEL = 5581, + OpUCountLeadingZerosINTEL = 5585, + OpUCountTrailingZerosINTEL = 5586, + OpAbsISubINTEL = 5587, + OpAbsUSubINTEL = 5588, + OpIAddSatINTEL = 5589, + OpUAddSatINTEL = 5590, + OpIAverageINTEL = 5591, + OpUAverageINTEL = 5592, + OpIAverageRoundedINTEL = 5593, + OpUAverageRoundedINTEL = 5594, + OpISubSatINTEL = 5595, + OpUSubSatINTEL = 5596, + OpIMul32x16INTEL = 5597, + OpUMul32x16INTEL = 5598, + OpDecorateString = 5632, + OpDecorateStringGOOGLE = 5632, + OpMemberDecorateString = 5633, + OpMemberDecorateStringGOOGLE = 5633, + OpVmeImageINTEL = 5699, + OpTypeVmeImageINTEL = 5700, + OpTypeAvcImePayloadINTEL = 5701, + OpTypeAvcRefPayloadINTEL = 5702, + OpTypeAvcSicPayloadINTEL = 5703, + OpTypeAvcMcePayloadINTEL = 5704, + OpTypeAvcMceResultINTEL = 5705, + OpTypeAvcImeResultINTEL = 5706, + OpTypeAvcImeResultSingleReferenceStreamoutINTEL = 5707, + OpTypeAvcImeResultDualReferenceStreamoutINTEL = 5708, + OpTypeAvcImeSingleReferenceStreaminINTEL = 5709, + OpTypeAvcImeDualReferenceStreaminINTEL = 5710, + OpTypeAvcRefResultINTEL = 5711, + OpTypeAvcSicResultINTEL = 5712, + OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL = 5713, + OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL = 5714, + OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL = 5715, + OpSubgroupAvcMceSetInterShapePenaltyINTEL = 5716, + OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL = 5717, + OpSubgroupAvcMceSetInterDirectionPenaltyINTEL = 5718, + OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL = 5719, + OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL = 5720, + OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL = 5721, + OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL = 5722, + OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL = 5723, + OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL = 5724, + OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL = 5725, + OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL = 5726, + OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL = 5727, + OpSubgroupAvcMceSetAcOnlyHaarINTEL = 5728, + OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL = 5729, + OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL = 5730, + OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL = 5731, + OpSubgroupAvcMceConvertToImePayloadINTEL = 5732, + OpSubgroupAvcMceConvertToImeResultINTEL = 5733, + OpSubgroupAvcMceConvertToRefPayloadINTEL = 5734, + OpSubgroupAvcMceConvertToRefResultINTEL = 5735, + OpSubgroupAvcMceConvertToSicPayloadINTEL = 5736, + OpSubgroupAvcMceConvertToSicResultINTEL = 5737, + OpSubgroupAvcMceGetMotionVectorsINTEL = 5738, + OpSubgroupAvcMceGetInterDistortionsINTEL = 5739, + OpSubgroupAvcMceGetBestInterDistortionsINTEL = 5740, + OpSubgroupAvcMceGetInterMajorShapeINTEL = 5741, + OpSubgroupAvcMceGetInterMinorShapeINTEL = 5742, + OpSubgroupAvcMceGetInterDirectionsINTEL = 5743, + OpSubgroupAvcMceGetInterMotionVectorCountINTEL = 5744, + OpSubgroupAvcMceGetInterReferenceIdsINTEL = 5745, + OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL = 5746, + OpSubgroupAvcImeInitializeINTEL = 5747, + OpSubgroupAvcImeSetSingleReferenceINTEL = 5748, + OpSubgroupAvcImeSetDualReferenceINTEL = 5749, + OpSubgroupAvcImeRefWindowSizeINTEL = 5750, + OpSubgroupAvcImeAdjustRefOffsetINTEL = 5751, + OpSubgroupAvcImeConvertToMcePayloadINTEL = 5752, + OpSubgroupAvcImeSetMaxMotionVectorCountINTEL = 5753, + OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL = 5754, + OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL = 5755, + OpSubgroupAvcImeSetWeightedSadINTEL = 5756, + OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL = 5757, + OpSubgroupAvcImeEvaluateWithDualReferenceINTEL = 5758, + OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL = 5759, + OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL = 5760, + OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL = 5761, + OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL = 5762, + OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL = 5763, + OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL = 5764, + OpSubgroupAvcImeConvertToMceResultINTEL = 5765, + OpSubgroupAvcImeGetSingleReferenceStreaminINTEL = 5766, + OpSubgroupAvcImeGetDualReferenceStreaminINTEL = 5767, + OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL = 5768, + OpSubgroupAvcImeStripDualReferenceStreamoutINTEL = 5769, + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL = 5770, + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL = 5771, + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL = 5772, + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL = 5773, + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL = 5774, + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL = 5775, + OpSubgroupAvcImeGetBorderReachedINTEL = 5776, + OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL = 5777, + OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL = 5778, + OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL = 5779, + OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL = 5780, + OpSubgroupAvcFmeInitializeINTEL = 5781, + OpSubgroupAvcBmeInitializeINTEL = 5782, + OpSubgroupAvcRefConvertToMcePayloadINTEL = 5783, + OpSubgroupAvcRefSetBidirectionalMixDisableINTEL = 5784, + OpSubgroupAvcRefSetBilinearFilterEnableINTEL = 5785, + OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL = 5786, + OpSubgroupAvcRefEvaluateWithDualReferenceINTEL = 5787, + OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL = 5788, + OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL = 5789, + OpSubgroupAvcRefConvertToMceResultINTEL = 5790, + OpSubgroupAvcSicInitializeINTEL = 5791, + OpSubgroupAvcSicConfigureSkcINTEL = 5792, + OpSubgroupAvcSicConfigureIpeLumaINTEL = 5793, + OpSubgroupAvcSicConfigureIpeLumaChromaINTEL = 5794, + OpSubgroupAvcSicGetMotionVectorMaskINTEL = 5795, + OpSubgroupAvcSicConvertToMcePayloadINTEL = 5796, + OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL = 5797, + OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL = 5798, + OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL = 5799, + OpSubgroupAvcSicSetBilinearFilterEnableINTEL = 5800, + OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL = 5801, + OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL = 5802, + OpSubgroupAvcSicEvaluateIpeINTEL = 5803, + OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL = 5804, + OpSubgroupAvcSicEvaluateWithDualReferenceINTEL = 5805, + OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL = 5806, + OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL = 5807, + OpSubgroupAvcSicConvertToMceResultINTEL = 5808, + OpSubgroupAvcSicGetIpeLumaShapeINTEL = 5809, + OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL = 5810, + OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL = 5811, + OpSubgroupAvcSicGetPackedIpeLumaModesINTEL = 5812, + OpSubgroupAvcSicGetIpeChromaModeINTEL = 5813, + OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814, + OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815, + OpSubgroupAvcSicGetInterRawSadsINTEL = 5816, + OpMax = 0x7fffffff, +}; + +#ifdef SPV_ENABLE_UTILITY_CODE +inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) { + *hasResult = *hasResultType = false; + switch (opcode) { + default: /* unknown opcode */ break; + case OpNop: *hasResult = false; *hasResultType = false; break; + case OpUndef: *hasResult = true; *hasResultType = true; break; + case OpSourceContinued: *hasResult = false; *hasResultType = false; break; + case OpSource: *hasResult = false; *hasResultType = false; break; + case OpSourceExtension: *hasResult = false; *hasResultType = false; break; + case OpName: *hasResult = false; *hasResultType = false; break; + case OpMemberName: *hasResult = false; *hasResultType = false; break; + case OpString: *hasResult = true; *hasResultType = false; break; + case OpLine: *hasResult = false; *hasResultType = false; break; + case OpExtension: *hasResult = false; *hasResultType = false; break; + case OpExtInstImport: *hasResult = true; *hasResultType = false; break; + case OpExtInst: *hasResult = true; *hasResultType = true; break; + case OpMemoryModel: *hasResult = false; *hasResultType = false; break; + case OpEntryPoint: *hasResult = false; *hasResultType = false; break; + case OpExecutionMode: *hasResult = false; *hasResultType = false; break; + case OpCapability: *hasResult = false; *hasResultType = false; break; + case OpTypeVoid: *hasResult = true; *hasResultType = false; break; + case OpTypeBool: *hasResult = true; *hasResultType = false; break; + case OpTypeInt: *hasResult = true; *hasResultType = false; break; + case OpTypeFloat: *hasResult = true; *hasResultType = false; break; + case OpTypeVector: *hasResult = true; *hasResultType = false; break; + case OpTypeMatrix: *hasResult = true; *hasResultType = false; break; + case OpTypeImage: *hasResult = true; *hasResultType = false; break; + case OpTypeSampler: *hasResult = true; *hasResultType = false; break; + case OpTypeSampledImage: *hasResult = true; *hasResultType = false; break; + case OpTypeArray: *hasResult = true; *hasResultType = false; break; + case OpTypeRuntimeArray: *hasResult = true; *hasResultType = false; break; + case OpTypeStruct: *hasResult = true; *hasResultType = false; break; + case OpTypeOpaque: *hasResult = true; *hasResultType = false; break; + case OpTypePointer: *hasResult = true; *hasResultType = false; break; + case OpTypeFunction: *hasResult = true; *hasResultType = false; break; + case OpTypeEvent: *hasResult = true; *hasResultType = false; break; + case OpTypeDeviceEvent: *hasResult = true; *hasResultType = false; break; + case OpTypeReserveId: *hasResult = true; *hasResultType = false; break; + case OpTypeQueue: *hasResult = true; *hasResultType = false; break; + case OpTypePipe: *hasResult = true; *hasResultType = false; break; + case OpTypeForwardPointer: *hasResult = false; *hasResultType = false; break; + case OpConstantTrue: *hasResult = true; *hasResultType = true; break; + case OpConstantFalse: *hasResult = true; *hasResultType = true; break; + case OpConstant: *hasResult = true; *hasResultType = true; break; + case OpConstantComposite: *hasResult = true; *hasResultType = true; break; + case OpConstantSampler: *hasResult = true; *hasResultType = true; break; + case OpConstantNull: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantTrue: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantFalse: *hasResult = true; *hasResultType = true; break; + case OpSpecConstant: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantComposite: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantOp: *hasResult = true; *hasResultType = true; break; + case OpFunction: *hasResult = true; *hasResultType = true; break; + case OpFunctionParameter: *hasResult = true; *hasResultType = true; break; + case OpFunctionEnd: *hasResult = false; *hasResultType = false; break; + case OpFunctionCall: *hasResult = true; *hasResultType = true; break; + case OpVariable: *hasResult = true; *hasResultType = true; break; + case OpImageTexelPointer: *hasResult = true; *hasResultType = true; break; + case OpLoad: *hasResult = true; *hasResultType = true; break; + case OpStore: *hasResult = false; *hasResultType = false; break; + case OpCopyMemory: *hasResult = false; *hasResultType = false; break; + case OpCopyMemorySized: *hasResult = false; *hasResultType = false; break; + case OpAccessChain: *hasResult = true; *hasResultType = true; break; + case OpInBoundsAccessChain: *hasResult = true; *hasResultType = true; break; + case OpPtrAccessChain: *hasResult = true; *hasResultType = true; break; + case OpArrayLength: *hasResult = true; *hasResultType = true; break; + case OpGenericPtrMemSemantics: *hasResult = true; *hasResultType = true; break; + case OpInBoundsPtrAccessChain: *hasResult = true; *hasResultType = true; break; + case OpDecorate: *hasResult = false; *hasResultType = false; break; + case OpMemberDecorate: *hasResult = false; *hasResultType = false; break; + case OpDecorationGroup: *hasResult = true; *hasResultType = false; break; + case OpGroupDecorate: *hasResult = false; *hasResultType = false; break; + case OpGroupMemberDecorate: *hasResult = false; *hasResultType = false; break; + case OpVectorExtractDynamic: *hasResult = true; *hasResultType = true; break; + case OpVectorInsertDynamic: *hasResult = true; *hasResultType = true; break; + case OpVectorShuffle: *hasResult = true; *hasResultType = true; break; + case OpCompositeConstruct: *hasResult = true; *hasResultType = true; break; + case OpCompositeExtract: *hasResult = true; *hasResultType = true; break; + case OpCompositeInsert: *hasResult = true; *hasResultType = true; break; + case OpCopyObject: *hasResult = true; *hasResultType = true; break; + case OpTranspose: *hasResult = true; *hasResultType = true; break; + case OpSampledImage: *hasResult = true; *hasResultType = true; break; + case OpImageSampleImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageFetch: *hasResult = true; *hasResultType = true; break; + case OpImageGather: *hasResult = true; *hasResultType = true; break; + case OpImageDrefGather: *hasResult = true; *hasResultType = true; break; + case OpImageRead: *hasResult = true; *hasResultType = true; break; + case OpImageWrite: *hasResult = false; *hasResultType = false; break; + case OpImage: *hasResult = true; *hasResultType = true; break; + case OpImageQueryFormat: *hasResult = true; *hasResultType = true; break; + case OpImageQueryOrder: *hasResult = true; *hasResultType = true; break; + case OpImageQuerySizeLod: *hasResult = true; *hasResultType = true; break; + case OpImageQuerySize: *hasResult = true; *hasResultType = true; break; + case OpImageQueryLod: *hasResult = true; *hasResultType = true; break; + case OpImageQueryLevels: *hasResult = true; *hasResultType = true; break; + case OpImageQuerySamples: *hasResult = true; *hasResultType = true; break; + case OpConvertFToU: *hasResult = true; *hasResultType = true; break; + case OpConvertFToS: *hasResult = true; *hasResultType = true; break; + case OpConvertSToF: *hasResult = true; *hasResultType = true; break; + case OpConvertUToF: *hasResult = true; *hasResultType = true; break; + case OpUConvert: *hasResult = true; *hasResultType = true; break; + case OpSConvert: *hasResult = true; *hasResultType = true; break; + case OpFConvert: *hasResult = true; *hasResultType = true; break; + case OpQuantizeToF16: *hasResult = true; *hasResultType = true; break; + case OpConvertPtrToU: *hasResult = true; *hasResultType = true; break; + case OpSatConvertSToU: *hasResult = true; *hasResultType = true; break; + case OpSatConvertUToS: *hasResult = true; *hasResultType = true; break; + case OpConvertUToPtr: *hasResult = true; *hasResultType = true; break; + case OpPtrCastToGeneric: *hasResult = true; *hasResultType = true; break; + case OpGenericCastToPtr: *hasResult = true; *hasResultType = true; break; + case OpGenericCastToPtrExplicit: *hasResult = true; *hasResultType = true; break; + case OpBitcast: *hasResult = true; *hasResultType = true; break; + case OpSNegate: *hasResult = true; *hasResultType = true; break; + case OpFNegate: *hasResult = true; *hasResultType = true; break; + case OpIAdd: *hasResult = true; *hasResultType = true; break; + case OpFAdd: *hasResult = true; *hasResultType = true; break; + case OpISub: *hasResult = true; *hasResultType = true; break; + case OpFSub: *hasResult = true; *hasResultType = true; break; + case OpIMul: *hasResult = true; *hasResultType = true; break; + case OpFMul: *hasResult = true; *hasResultType = true; break; + case OpUDiv: *hasResult = true; *hasResultType = true; break; + case OpSDiv: *hasResult = true; *hasResultType = true; break; + case OpFDiv: *hasResult = true; *hasResultType = true; break; + case OpUMod: *hasResult = true; *hasResultType = true; break; + case OpSRem: *hasResult = true; *hasResultType = true; break; + case OpSMod: *hasResult = true; *hasResultType = true; break; + case OpFRem: *hasResult = true; *hasResultType = true; break; + case OpFMod: *hasResult = true; *hasResultType = true; break; + case OpVectorTimesScalar: *hasResult = true; *hasResultType = true; break; + case OpMatrixTimesScalar: *hasResult = true; *hasResultType = true; break; + case OpVectorTimesMatrix: *hasResult = true; *hasResultType = true; break; + case OpMatrixTimesVector: *hasResult = true; *hasResultType = true; break; + case OpMatrixTimesMatrix: *hasResult = true; *hasResultType = true; break; + case OpOuterProduct: *hasResult = true; *hasResultType = true; break; + case OpDot: *hasResult = true; *hasResultType = true; break; + case OpIAddCarry: *hasResult = true; *hasResultType = true; break; + case OpISubBorrow: *hasResult = true; *hasResultType = true; break; + case OpUMulExtended: *hasResult = true; *hasResultType = true; break; + case OpSMulExtended: *hasResult = true; *hasResultType = true; break; + case OpAny: *hasResult = true; *hasResultType = true; break; + case OpAll: *hasResult = true; *hasResultType = true; break; + case OpIsNan: *hasResult = true; *hasResultType = true; break; + case OpIsInf: *hasResult = true; *hasResultType = true; break; + case OpIsFinite: *hasResult = true; *hasResultType = true; break; + case OpIsNormal: *hasResult = true; *hasResultType = true; break; + case OpSignBitSet: *hasResult = true; *hasResultType = true; break; + case OpLessOrGreater: *hasResult = true; *hasResultType = true; break; + case OpOrdered: *hasResult = true; *hasResultType = true; break; + case OpUnordered: *hasResult = true; *hasResultType = true; break; + case OpLogicalEqual: *hasResult = true; *hasResultType = true; break; + case OpLogicalNotEqual: *hasResult = true; *hasResultType = true; break; + case OpLogicalOr: *hasResult = true; *hasResultType = true; break; + case OpLogicalAnd: *hasResult = true; *hasResultType = true; break; + case OpLogicalNot: *hasResult = true; *hasResultType = true; break; + case OpSelect: *hasResult = true; *hasResultType = true; break; + case OpIEqual: *hasResult = true; *hasResultType = true; break; + case OpINotEqual: *hasResult = true; *hasResultType = true; break; + case OpUGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpSGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpUGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpSGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpULessThan: *hasResult = true; *hasResultType = true; break; + case OpSLessThan: *hasResult = true; *hasResultType = true; break; + case OpULessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpSLessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdNotEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordNotEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdLessThan: *hasResult = true; *hasResultType = true; break; + case OpFUnordLessThan: *hasResult = true; *hasResultType = true; break; + case OpFOrdGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpFUnordGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpFOrdLessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordLessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpShiftRightLogical: *hasResult = true; *hasResultType = true; break; + case OpShiftRightArithmetic: *hasResult = true; *hasResultType = true; break; + case OpShiftLeftLogical: *hasResult = true; *hasResultType = true; break; + case OpBitwiseOr: *hasResult = true; *hasResultType = true; break; + case OpBitwiseXor: *hasResult = true; *hasResultType = true; break; + case OpBitwiseAnd: *hasResult = true; *hasResultType = true; break; + case OpNot: *hasResult = true; *hasResultType = true; break; + case OpBitFieldInsert: *hasResult = true; *hasResultType = true; break; + case OpBitFieldSExtract: *hasResult = true; *hasResultType = true; break; + case OpBitFieldUExtract: *hasResult = true; *hasResultType = true; break; + case OpBitReverse: *hasResult = true; *hasResultType = true; break; + case OpBitCount: *hasResult = true; *hasResultType = true; break; + case OpDPdx: *hasResult = true; *hasResultType = true; break; + case OpDPdy: *hasResult = true; *hasResultType = true; break; + case OpFwidth: *hasResult = true; *hasResultType = true; break; + case OpDPdxFine: *hasResult = true; *hasResultType = true; break; + case OpDPdyFine: *hasResult = true; *hasResultType = true; break; + case OpFwidthFine: *hasResult = true; *hasResultType = true; break; + case OpDPdxCoarse: *hasResult = true; *hasResultType = true; break; + case OpDPdyCoarse: *hasResult = true; *hasResultType = true; break; + case OpFwidthCoarse: *hasResult = true; *hasResultType = true; break; + case OpEmitVertex: *hasResult = false; *hasResultType = false; break; + case OpEndPrimitive: *hasResult = false; *hasResultType = false; break; + case OpEmitStreamVertex: *hasResult = false; *hasResultType = false; break; + case OpEndStreamPrimitive: *hasResult = false; *hasResultType = false; break; + case OpControlBarrier: *hasResult = false; *hasResultType = false; break; + case OpMemoryBarrier: *hasResult = false; *hasResultType = false; break; + case OpAtomicLoad: *hasResult = true; *hasResultType = true; break; + case OpAtomicStore: *hasResult = false; *hasResultType = false; break; + case OpAtomicExchange: *hasResult = true; *hasResultType = true; break; + case OpAtomicCompareExchange: *hasResult = true; *hasResultType = true; break; + case OpAtomicCompareExchangeWeak: *hasResult = true; *hasResultType = true; break; + case OpAtomicIIncrement: *hasResult = true; *hasResultType = true; break; + case OpAtomicIDecrement: *hasResult = true; *hasResultType = true; break; + case OpAtomicIAdd: *hasResult = true; *hasResultType = true; break; + case OpAtomicISub: *hasResult = true; *hasResultType = true; break; + case OpAtomicSMin: *hasResult = true; *hasResultType = true; break; + case OpAtomicUMin: *hasResult = true; *hasResultType = true; break; + case OpAtomicSMax: *hasResult = true; *hasResultType = true; break; + case OpAtomicUMax: *hasResult = true; *hasResultType = true; break; + case OpAtomicAnd: *hasResult = true; *hasResultType = true; break; + case OpAtomicOr: *hasResult = true; *hasResultType = true; break; + case OpAtomicXor: *hasResult = true; *hasResultType = true; break; + case OpPhi: *hasResult = true; *hasResultType = true; break; + case OpLoopMerge: *hasResult = false; *hasResultType = false; break; + case OpSelectionMerge: *hasResult = false; *hasResultType = false; break; + case OpLabel: *hasResult = true; *hasResultType = false; break; + case OpBranch: *hasResult = false; *hasResultType = false; break; + case OpBranchConditional: *hasResult = false; *hasResultType = false; break; + case OpSwitch: *hasResult = false; *hasResultType = false; break; + case OpKill: *hasResult = false; *hasResultType = false; break; + case OpReturn: *hasResult = false; *hasResultType = false; break; + case OpReturnValue: *hasResult = false; *hasResultType = false; break; + case OpUnreachable: *hasResult = false; *hasResultType = false; break; + case OpLifetimeStart: *hasResult = false; *hasResultType = false; break; + case OpLifetimeStop: *hasResult = false; *hasResultType = false; break; + case OpGroupAsyncCopy: *hasResult = true; *hasResultType = true; break; + case OpGroupWaitEvents: *hasResult = false; *hasResultType = false; break; + case OpGroupAll: *hasResult = true; *hasResultType = true; break; + case OpGroupAny: *hasResult = true; *hasResultType = true; break; + case OpGroupBroadcast: *hasResult = true; *hasResultType = true; break; + case OpGroupIAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupFAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupFMin: *hasResult = true; *hasResultType = true; break; + case OpGroupUMin: *hasResult = true; *hasResultType = true; break; + case OpGroupSMin: *hasResult = true; *hasResultType = true; break; + case OpGroupFMax: *hasResult = true; *hasResultType = true; break; + case OpGroupUMax: *hasResult = true; *hasResultType = true; break; + case OpGroupSMax: *hasResult = true; *hasResultType = true; break; + case OpReadPipe: *hasResult = true; *hasResultType = true; break; + case OpWritePipe: *hasResult = true; *hasResultType = true; break; + case OpReservedReadPipe: *hasResult = true; *hasResultType = true; break; + case OpReservedWritePipe: *hasResult = true; *hasResultType = true; break; + case OpReserveReadPipePackets: *hasResult = true; *hasResultType = true; break; + case OpReserveWritePipePackets: *hasResult = true; *hasResultType = true; break; + case OpCommitReadPipe: *hasResult = false; *hasResultType = false; break; + case OpCommitWritePipe: *hasResult = false; *hasResultType = false; break; + case OpIsValidReserveId: *hasResult = true; *hasResultType = true; break; + case OpGetNumPipePackets: *hasResult = true; *hasResultType = true; break; + case OpGetMaxPipePackets: *hasResult = true; *hasResultType = true; break; + case OpGroupReserveReadPipePackets: *hasResult = true; *hasResultType = true; break; + case OpGroupReserveWritePipePackets: *hasResult = true; *hasResultType = true; break; + case OpGroupCommitReadPipe: *hasResult = false; *hasResultType = false; break; + case OpGroupCommitWritePipe: *hasResult = false; *hasResultType = false; break; + case OpEnqueueMarker: *hasResult = true; *hasResultType = true; break; + case OpEnqueueKernel: *hasResult = true; *hasResultType = true; break; + case OpGetKernelNDrangeSubGroupCount: *hasResult = true; *hasResultType = true; break; + case OpGetKernelNDrangeMaxSubGroupSize: *hasResult = true; *hasResultType = true; break; + case OpGetKernelWorkGroupSize: *hasResult = true; *hasResultType = true; break; + case OpGetKernelPreferredWorkGroupSizeMultiple: *hasResult = true; *hasResultType = true; break; + case OpRetainEvent: *hasResult = false; *hasResultType = false; break; + case OpReleaseEvent: *hasResult = false; *hasResultType = false; break; + case OpCreateUserEvent: *hasResult = true; *hasResultType = true; break; + case OpIsValidEvent: *hasResult = true; *hasResultType = true; break; + case OpSetUserEventStatus: *hasResult = false; *hasResultType = false; break; + case OpCaptureEventProfilingInfo: *hasResult = false; *hasResultType = false; break; + case OpGetDefaultQueue: *hasResult = true; *hasResultType = true; break; + case OpBuildNDRange: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseFetch: *hasResult = true; *hasResultType = true; break; + case OpImageSparseGather: *hasResult = true; *hasResultType = true; break; + case OpImageSparseDrefGather: *hasResult = true; *hasResultType = true; break; + case OpImageSparseTexelsResident: *hasResult = true; *hasResultType = true; break; + case OpNoLine: *hasResult = false; *hasResultType = false; break; + case OpAtomicFlagTestAndSet: *hasResult = true; *hasResultType = true; break; + case OpAtomicFlagClear: *hasResult = false; *hasResultType = false; break; + case OpImageSparseRead: *hasResult = true; *hasResultType = true; break; + case OpSizeOf: *hasResult = true; *hasResultType = true; break; + case OpTypePipeStorage: *hasResult = true; *hasResultType = false; break; + case OpConstantPipeStorage: *hasResult = true; *hasResultType = true; break; + case OpCreatePipeFromPipeStorage: *hasResult = true; *hasResultType = true; break; + case OpGetKernelLocalSizeForSubgroupCount: *hasResult = true; *hasResultType = true; break; + case OpGetKernelMaxNumSubgroups: *hasResult = true; *hasResultType = true; break; + case OpTypeNamedBarrier: *hasResult = true; *hasResultType = false; break; + case OpNamedBarrierInitialize: *hasResult = true; *hasResultType = true; break; + case OpMemoryNamedBarrier: *hasResult = false; *hasResultType = false; break; + case OpModuleProcessed: *hasResult = false; *hasResultType = false; break; + case OpExecutionModeId: *hasResult = false; *hasResultType = false; break; + case OpDecorateId: *hasResult = false; *hasResultType = false; break; + case OpGroupNonUniformElect: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformAll: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformAny: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformAllEqual: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBroadcast: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBroadcastFirst: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallot: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformInverseBallot: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotBitExtract: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotBitCount: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotFindLSB: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotFindMSB: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffle: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffleXor: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffleUp: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffleDown: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformIAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformIMul: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFMul: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformSMin: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformUMin: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFMin: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformSMax: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformUMax: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFMax: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBitwiseAnd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBitwiseOr: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBitwiseXor: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformLogicalAnd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformLogicalOr: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformLogicalXor: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformQuadBroadcast: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformQuadSwap: *hasResult = true; *hasResultType = true; break; + case OpCopyLogical: *hasResult = true; *hasResultType = true; break; + case OpPtrEqual: *hasResult = true; *hasResultType = true; break; + case OpPtrNotEqual: *hasResult = true; *hasResultType = true; break; + case OpPtrDiff: *hasResult = true; *hasResultType = true; break; + case OpSubgroupBallotKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupFirstInvocationKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAllKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break; + case OpGroupIAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupFAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupFMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupUMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupSMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupFMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupUMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupSMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpFragmentMaskFetchAMD: *hasResult = true; *hasResultType = true; break; + case OpFragmentFetchAMD: *hasResult = true; *hasResultType = true; break; + case OpImageSampleFootprintNV: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformPartitionNV: *hasResult = true; *hasResultType = true; break; + case OpWritePackedPrimitiveIndices4x8NV: *hasResult = false; *hasResultType = false; break; + case OpReportIntersectionNV: *hasResult = true; *hasResultType = true; break; + case OpIgnoreIntersectionNV: *hasResult = false; *hasResultType = false; break; + case OpTerminateRayNV: *hasResult = false; *hasResultType = false; break; + case OpTraceNV: *hasResult = false; *hasResultType = false; break; + case OpTypeAccelerationStructureNV: *hasResult = true; *hasResultType = false; break; + case OpExecuteCallableNV: *hasResult = false; *hasResultType = false; break; + case OpTypeCooperativeMatrixNV: *hasResult = true; *hasResultType = false; break; + case OpCooperativeMatrixLoadNV: *hasResult = true; *hasResultType = true; break; + case OpCooperativeMatrixStoreNV: *hasResult = false; *hasResultType = false; break; + case OpCooperativeMatrixMulAddNV: *hasResult = true; *hasResultType = true; break; + case OpCooperativeMatrixLengthNV: *hasResult = true; *hasResultType = true; break; + case OpBeginInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break; + case OpEndInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break; + case OpDemoteToHelperInvocationEXT: *hasResult = false; *hasResultType = false; break; + case OpIsHelperInvocationEXT: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleDownINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleUpINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleXorINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case OpSubgroupImageBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupImageBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case OpSubgroupImageMediaBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupImageMediaBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case OpUCountLeadingZerosINTEL: *hasResult = true; *hasResultType = true; break; + case OpUCountTrailingZerosINTEL: *hasResult = true; *hasResultType = true; break; + case OpAbsISubINTEL: *hasResult = true; *hasResultType = true; break; + case OpAbsUSubINTEL: *hasResult = true; *hasResultType = true; break; + case OpIAddSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpUAddSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpIAverageINTEL: *hasResult = true; *hasResultType = true; break; + case OpUAverageINTEL: *hasResult = true; *hasResultType = true; break; + case OpIAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break; + case OpUAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break; + case OpISubSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpUSubSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpIMul32x16INTEL: *hasResult = true; *hasResultType = true; break; + case OpUMul32x16INTEL: *hasResult = true; *hasResultType = true; break; + case OpDecorateString: *hasResult = false; *hasResultType = false; break; + case OpMemberDecorateString: *hasResult = false; *hasResultType = false; break; + case OpVmeImageINTEL: *hasResult = true; *hasResultType = true; break; + case OpTypeVmeImageINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImePayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcRefPayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcSicPayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcMcePayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcMceResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeResultSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeResultDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcRefResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcSicResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetAcOnlyHaarINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToImePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToImeResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToRefPayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToRefResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToSicPayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToSicResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetBestInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterMajorShapeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterMinorShapeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterDirectionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeRefWindowSizeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeAdjustRefOffsetINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetMaxMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetWeightedSadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeStripDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetBorderReachedINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcFmeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcBmeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefSetBidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConfigureSkcINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConfigureIpeLumaINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConfigureIpeLumaChromaINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetMotionVectorMaskINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateIpeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetIpeLumaShapeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetPackedIpeLumaModesINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetIpeChromaModeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetInterRawSadsINTEL: *hasResult = true; *hasResultType = true; break; + } +} +#endif /* SPV_ENABLE_UTILITY_CODE */ + +// Overload operator| for mask bit combining + +inline ImageOperandsMask operator|(ImageOperandsMask a, ImageOperandsMask b) { return ImageOperandsMask(unsigned(a) | unsigned(b)); } +inline FPFastMathModeMask operator|(FPFastMathModeMask a, FPFastMathModeMask b) { return FPFastMathModeMask(unsigned(a) | unsigned(b)); } +inline SelectionControlMask operator|(SelectionControlMask a, SelectionControlMask b) { return SelectionControlMask(unsigned(a) | unsigned(b)); } +inline LoopControlMask operator|(LoopControlMask a, LoopControlMask b) { return LoopControlMask(unsigned(a) | unsigned(b)); } +inline FunctionControlMask operator|(FunctionControlMask a, FunctionControlMask b) { return FunctionControlMask(unsigned(a) | unsigned(b)); } +inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) | unsigned(b)); } +inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); } +inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); } + +} // end namespace spv + +#endif // #ifndef spirv_HPP + diff --git a/utils/dxvk-1.10.3/include/vulkan/vk_platform.h b/utils/dxvk-1.10.3/include/vulkan/vk_platform.h new file mode 100644 index 00000000000..18b913abc6a --- /dev/null +++ b/utils/dxvk-1.10.3/include/vulkan/vk_platform.h @@ -0,0 +1,84 @@ +// +// File: vk_platform.h +// +/* +** Copyright 2014-2021 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + + +#ifndef VK_PLATFORM_H_ +#define VK_PLATFORM_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +/* +*************************************************************************************************** +* Platform-specific directives and type declarations +*************************************************************************************************** +*/ + +/* Platform-specific calling convention macros. + * + * Platforms should define these so that Vulkan clients call Vulkan commands + * with the same calling conventions that the Vulkan implementation expects. + * + * VKAPI_ATTR - Placed before the return type in function declarations. + * Useful for C++11 and GCC/Clang-style function attribute syntax. + * VKAPI_CALL - Placed after the return type in function declarations. + * Useful for MSVC-style calling convention syntax. + * VKAPI_PTR - Placed between the '(' and '*' in function pointer types. + * + * Function declaration: VKAPI_ATTR void VKAPI_CALL vkCommand(void); + * Function pointer type: typedef void (VKAPI_PTR *PFN_vkCommand)(void); + */ +#if defined(_WIN32) + // On Windows, Vulkan commands use the stdcall convention + #define VKAPI_ATTR + #define VKAPI_CALL __stdcall + #define VKAPI_PTR VKAPI_CALL +#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH < 7 + #error "Vulkan isn't supported for the 'armeabi' NDK ABI" +#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7 && defined(__ARM_32BIT_STATE) + // On Android 32-bit ARM targets, Vulkan functions use the "hardfloat" + // calling convention, i.e. float parameters are passed in registers. This + // is true even if the rest of the application passes floats on the stack, + // as it does by default when compiling for the armeabi-v7a NDK ABI. + #define VKAPI_ATTR __attribute__((pcs("aapcs-vfp"))) + #define VKAPI_CALL + #define VKAPI_PTR VKAPI_ATTR +#else + // On other platforms, use the default calling convention + #define VKAPI_ATTR + #define VKAPI_CALL + #define VKAPI_PTR +#endif + +#if !defined(VK_NO_STDDEF_H) + #include +#endif // !defined(VK_NO_STDDEF_H) + +#if !defined(VK_NO_STDINT_H) + #if defined(_MSC_VER) && (_MSC_VER < 1600) + typedef signed __int8 int8_t; + typedef unsigned __int8 uint8_t; + typedef signed __int16 int16_t; + typedef unsigned __int16 uint16_t; + typedef signed __int32 int32_t; + typedef unsigned __int32 uint32_t; + typedef signed __int64 int64_t; + typedef unsigned __int64 uint64_t; + #else + #include + #endif +#endif // !defined(VK_NO_STDINT_H) + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif diff --git a/utils/dxvk-1.10.3/include/vulkan/vulkan.h b/utils/dxvk-1.10.3/include/vulkan/vulkan.h new file mode 100644 index 00000000000..3f7cdba5845 --- /dev/null +++ b/utils/dxvk-1.10.3/include/vulkan/vulkan.h @@ -0,0 +1,92 @@ +#ifndef VULKAN_H_ +#define VULKAN_H_ 1 + +/* +** Copyright 2015-2021 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +#include "vk_platform.h" +#include "vulkan_core.h" + +#ifdef VK_USE_PLATFORM_ANDROID_KHR +#include "vulkan_android.h" +#endif + +#ifdef VK_USE_PLATFORM_FUCHSIA +#include +#include "vulkan_fuchsia.h" +#endif + +#ifdef VK_USE_PLATFORM_IOS_MVK +#include "vulkan_ios.h" +#endif + + +#ifdef VK_USE_PLATFORM_MACOS_MVK +#include "vulkan_macos.h" +#endif + +#ifdef VK_USE_PLATFORM_METAL_EXT +#include "vulkan_metal.h" +#endif + +#ifdef VK_USE_PLATFORM_VI_NN +#include "vulkan_vi.h" +#endif + + +#ifdef VK_USE_PLATFORM_WAYLAND_KHR +#include +#include "vulkan_wayland.h" +#endif + + +#ifdef VK_USE_PLATFORM_WIN32_KHR +#include +#include "vulkan_win32.h" +#endif + + +#ifdef VK_USE_PLATFORM_XCB_KHR +#include +#include "vulkan_xcb.h" +#endif + + +#ifdef VK_USE_PLATFORM_XLIB_KHR +#include +#include "vulkan_xlib.h" +#endif + + +#ifdef VK_USE_PLATFORM_DIRECTFB_EXT +#include +#include "vulkan_directfb.h" +#endif + + +#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT +#include +#include +#include "vulkan_xlib_xrandr.h" +#endif + + +#ifdef VK_USE_PLATFORM_GGP +#include +#include "vulkan_ggp.h" +#endif + + +#ifdef VK_USE_PLATFORM_SCREEN_QNX +#include +#include "vulkan_screen.h" +#endif + +#ifdef VK_ENABLE_BETA_EXTENSIONS +#include "vulkan_beta.h" +#endif + +#endif // VULKAN_H_ diff --git a/utils/dxvk-1.10.3/include/vulkan/vulkan_core.h b/utils/dxvk-1.10.3/include/vulkan/vulkan_core.h new file mode 100644 index 00000000000..07b4acfe211 --- /dev/null +++ b/utils/dxvk-1.10.3/include/vulkan/vulkan_core.h @@ -0,0 +1,14720 @@ +#ifndef VULKAN_CORE_H_ +#define VULKAN_CORE_H_ 1 + +/* +** Copyright 2015-2022 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +#define VK_VERSION_1_0 1 +#include "vk_platform.h" + +#define VK_DEFINE_HANDLE(object) typedef struct object##_T* object; + + +#ifndef VK_USE_64_BIT_PTR_DEFINES + #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) + #define VK_USE_64_BIT_PTR_DEFINES 1 + #else + #define VK_USE_64_BIT_PTR_DEFINES 0 + #endif +#endif + + +#ifndef VK_DEFINE_NON_DISPATCHABLE_HANDLE + #if (VK_USE_64_BIT_PTR_DEFINES==1) + #if (defined(__cplusplus) && (__cplusplus >= 201103L)) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201103L)) + #define VK_NULL_HANDLE nullptr + #else + #define VK_NULL_HANDLE ((void*)0) + #endif + #else + #define VK_NULL_HANDLE 0ULL + #endif +#endif +#ifndef VK_NULL_HANDLE + #define VK_NULL_HANDLE 0 +#endif + + +#ifndef VK_DEFINE_NON_DISPATCHABLE_HANDLE + #if (VK_USE_64_BIT_PTR_DEFINES==1) + #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef struct object##_T *object; + #else + #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object; + #endif +#endif + +// DEPRECATED: This define is deprecated. VK_MAKE_API_VERSION should be used instead. +#define VK_MAKE_VERSION(major, minor, patch) \ + ((((uint32_t)(major)) << 22) | (((uint32_t)(minor)) << 12) | ((uint32_t)(patch))) + +// DEPRECATED: This define has been removed. Specific version defines (e.g. VK_API_VERSION_1_0), or the VK_MAKE_VERSION macro, should be used instead. +//#define VK_API_VERSION VK_MAKE_VERSION(1, 0, 0) // Patch version should always be set to 0 + +#define VK_MAKE_API_VERSION(variant, major, minor, patch) \ + ((((uint32_t)(variant)) << 29) | (((uint32_t)(major)) << 22) | (((uint32_t)(minor)) << 12) | ((uint32_t)(patch))) + +// Vulkan 1.0 version number +#define VK_API_VERSION_1_0 VK_MAKE_API_VERSION(0, 1, 0, 0)// Patch version should always be set to 0 + +// Version of this file +#define VK_HEADER_VERSION 217 + +// Complete version of this file +#define VK_HEADER_VERSION_COMPLETE VK_MAKE_API_VERSION(0, 1, 3, VK_HEADER_VERSION) + +// DEPRECATED: This define is deprecated. VK_API_VERSION_MAJOR should be used instead. +#define VK_VERSION_MAJOR(version) ((uint32_t)(version) >> 22) + +// DEPRECATED: This define is deprecated. VK_API_VERSION_MINOR should be used instead. +#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3FFU) + +// DEPRECATED: This define is deprecated. VK_API_VERSION_PATCH should be used instead. +#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xFFFU) + +#define VK_API_VERSION_VARIANT(version) ((uint32_t)(version) >> 29) +#define VK_API_VERSION_MAJOR(version) (((uint32_t)(version) >> 22) & 0x7FU) +#define VK_API_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3FFU) +#define VK_API_VERSION_PATCH(version) ((uint32_t)(version) & 0xFFFU) +typedef uint32_t VkBool32; +typedef uint64_t VkDeviceAddress; +typedef uint64_t VkDeviceSize; +typedef uint32_t VkFlags; +typedef uint32_t VkSampleMask; +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBuffer) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkImage) +VK_DEFINE_HANDLE(VkInstance) +VK_DEFINE_HANDLE(VkPhysicalDevice) +VK_DEFINE_HANDLE(VkDevice) +VK_DEFINE_HANDLE(VkQueue) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSemaphore) +VK_DEFINE_HANDLE(VkCommandBuffer) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkFence) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDeviceMemory) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkEvent) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkQueryPool) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBufferView) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkImageView) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkShaderModule) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipelineCache) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipelineLayout) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipeline) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkRenderPass) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorSetLayout) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSampler) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorSet) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorPool) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkFramebuffer) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCommandPool) +#define VK_ATTACHMENT_UNUSED (~0U) +#define VK_FALSE 0U +#define VK_LOD_CLAMP_NONE 1000.0F +#define VK_QUEUE_FAMILY_IGNORED (~0U) +#define VK_REMAINING_ARRAY_LAYERS (~0U) +#define VK_REMAINING_MIP_LEVELS (~0U) +#define VK_SUBPASS_EXTERNAL (~0U) +#define VK_TRUE 1U +#define VK_WHOLE_SIZE (~0ULL) +#define VK_MAX_MEMORY_TYPES 32U +#define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE 256U +#define VK_UUID_SIZE 16U +#define VK_MAX_EXTENSION_NAME_SIZE 256U +#define VK_MAX_DESCRIPTION_SIZE 256U +#define VK_MAX_MEMORY_HEAPS 16U + +typedef enum VkResult { + VK_SUCCESS = 0, + VK_NOT_READY = 1, + VK_TIMEOUT = 2, + VK_EVENT_SET = 3, + VK_EVENT_RESET = 4, + VK_INCOMPLETE = 5, + VK_ERROR_OUT_OF_HOST_MEMORY = -1, + VK_ERROR_OUT_OF_DEVICE_MEMORY = -2, + VK_ERROR_INITIALIZATION_FAILED = -3, + VK_ERROR_DEVICE_LOST = -4, + VK_ERROR_MEMORY_MAP_FAILED = -5, + VK_ERROR_LAYER_NOT_PRESENT = -6, + VK_ERROR_EXTENSION_NOT_PRESENT = -7, + VK_ERROR_FEATURE_NOT_PRESENT = -8, + VK_ERROR_INCOMPATIBLE_DRIVER = -9, + VK_ERROR_TOO_MANY_OBJECTS = -10, + VK_ERROR_FORMAT_NOT_SUPPORTED = -11, + VK_ERROR_FRAGMENTED_POOL = -12, + VK_ERROR_UNKNOWN = -13, + VK_ERROR_OUT_OF_POOL_MEMORY = -1000069000, + VK_ERROR_INVALID_EXTERNAL_HANDLE = -1000072003, + VK_ERROR_FRAGMENTATION = -1000161000, + VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS = -1000257000, + VK_PIPELINE_COMPILE_REQUIRED = 1000297000, + VK_ERROR_SURFACE_LOST_KHR = -1000000000, + VK_ERROR_NATIVE_WINDOW_IN_USE_KHR = -1000000001, + VK_SUBOPTIMAL_KHR = 1000001003, + VK_ERROR_OUT_OF_DATE_KHR = -1000001004, + VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001, + VK_ERROR_VALIDATION_FAILED_EXT = -1000011001, + VK_ERROR_INVALID_SHADER_NV = -1000012000, + VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT = -1000158000, + VK_ERROR_NOT_PERMITTED_KHR = -1000174001, + VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT = -1000255000, + VK_THREAD_IDLE_KHR = 1000268000, + VK_THREAD_DONE_KHR = 1000268001, + VK_OPERATION_DEFERRED_KHR = 1000268002, + VK_OPERATION_NOT_DEFERRED_KHR = 1000268003, + VK_ERROR_COMPRESSION_EXHAUSTED_EXT = -1000338000, + VK_ERROR_OUT_OF_POOL_MEMORY_KHR = VK_ERROR_OUT_OF_POOL_MEMORY, + VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR = VK_ERROR_INVALID_EXTERNAL_HANDLE, + VK_ERROR_FRAGMENTATION_EXT = VK_ERROR_FRAGMENTATION, + VK_ERROR_NOT_PERMITTED_EXT = VK_ERROR_NOT_PERMITTED_KHR, + VK_ERROR_INVALID_DEVICE_ADDRESS_EXT = VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS, + VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS_KHR = VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS, + VK_PIPELINE_COMPILE_REQUIRED_EXT = VK_PIPELINE_COMPILE_REQUIRED, + VK_ERROR_PIPELINE_COMPILE_REQUIRED_EXT = VK_PIPELINE_COMPILE_REQUIRED, + VK_RESULT_MAX_ENUM = 0x7FFFFFFF +} VkResult; + +typedef enum VkStructureType { + VK_STRUCTURE_TYPE_APPLICATION_INFO = 0, + VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO = 1, + VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO = 2, + VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO = 3, + VK_STRUCTURE_TYPE_SUBMIT_INFO = 4, + VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO = 5, + VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE = 6, + VK_STRUCTURE_TYPE_BIND_SPARSE_INFO = 7, + VK_STRUCTURE_TYPE_FENCE_CREATE_INFO = 8, + VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO = 9, + VK_STRUCTURE_TYPE_EVENT_CREATE_INFO = 10, + VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO = 11, + VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO = 12, + VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO = 13, + VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO = 14, + VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO = 15, + VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO = 16, + VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO = 17, + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO = 18, + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO = 19, + VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO = 20, + VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO = 21, + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO = 22, + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO = 23, + VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO = 24, + VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO = 25, + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO = 26, + VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO = 27, + VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO = 28, + VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO = 29, + VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO = 30, + VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO = 31, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO = 32, + VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO = 33, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO = 34, + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET = 35, + VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET = 36, + VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO = 37, + VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO = 38, + VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO = 39, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO = 40, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO = 41, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO = 42, + VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO = 43, + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER = 44, + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER = 45, + VK_STRUCTURE_TYPE_MEMORY_BARRIER = 46, + VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO = 47, + VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO = 48, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES = 1000094000, + VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO = 1000157000, + VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO = 1000157001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES = 1000083000, + VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS = 1000127000, + VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO = 1000127001, + VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO = 1000060000, + VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO = 1000060003, + VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO = 1000060004, + VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO = 1000060005, + VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO = 1000060006, + VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO = 1000060013, + VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO = 1000060014, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES = 1000070000, + VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO = 1000070001, + VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2 = 1000146000, + VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2 = 1000146001, + VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2 = 1000146002, + VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2 = 1000146003, + VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2 = 1000146004, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 = 1000059000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2 = 1000059001, + VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2 = 1000059002, + VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2 = 1000059003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2 = 1000059004, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2 = 1000059005, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2 = 1000059006, + VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2 = 1000059007, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2 = 1000059008, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES = 1000117000, + VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO = 1000117001, + VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO = 1000117002, + VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO = 1000117003, + VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO = 1000053000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES = 1000053001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES = 1000053002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES = 1000120000, + VK_STRUCTURE_TYPE_PROTECTED_SUBMIT_INFO = 1000145000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES = 1000145001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES = 1000145002, + VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2 = 1000145003, + VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO = 1000156000, + VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO = 1000156001, + VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO = 1000156002, + VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO = 1000156003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES = 1000156004, + VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES = 1000156005, + VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO = 1000085000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO = 1000071000, + VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES = 1000071001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO = 1000071002, + VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES = 1000071003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES = 1000071004, + VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO = 1000072000, + VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO = 1000072001, + VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO = 1000072002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO = 1000112000, + VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES = 1000112001, + VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO = 1000113000, + VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO = 1000077000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO = 1000076000, + VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES = 1000076001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES = 1000168000, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT = 1000168001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES = 1000063000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES = 49, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES = 50, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES = 51, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES = 52, + VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO = 1000147000, + VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2 = 1000109000, + VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2 = 1000109001, + VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2 = 1000109002, + VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2 = 1000109003, + VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2 = 1000109004, + VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO = 1000109005, + VK_STRUCTURE_TYPE_SUBPASS_END_INFO = 1000109006, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES = 1000177000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES = 1000196000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES = 1000180000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES = 1000082000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES = 1000197000, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO = 1000161000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES = 1000161001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES = 1000161002, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO = 1000161003, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT = 1000161004, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES = 1000199000, + VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE = 1000199001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES = 1000221000, + VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO = 1000246000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES = 1000130000, + VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO = 1000130001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES = 1000211000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES = 1000108000, + VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO = 1000108001, + VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO = 1000108002, + VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO = 1000108003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES = 1000253000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES = 1000175000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES = 1000241000, + VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_STENCIL_LAYOUT = 1000241001, + VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT = 1000241002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES = 1000261000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES = 1000207000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES = 1000207001, + VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO = 1000207002, + VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO = 1000207003, + VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO = 1000207004, + VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO = 1000207005, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES = 1000257000, + VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO = 1000244001, + VK_STRUCTURE_TYPE_BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO = 1000257002, + VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO = 1000257003, + VK_STRUCTURE_TYPE_DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO = 1000257004, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES = 53, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_PROPERTIES = 54, + VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO = 1000192000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES = 1000215000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TOOL_PROPERTIES = 1000245000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES = 1000276000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES = 1000295000, + VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO = 1000295001, + VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO = 1000295002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES = 1000297000, + VK_STRUCTURE_TYPE_MEMORY_BARRIER_2 = 1000314000, + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2 = 1000314001, + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2 = 1000314002, + VK_STRUCTURE_TYPE_DEPENDENCY_INFO = 1000314003, + VK_STRUCTURE_TYPE_SUBMIT_INFO_2 = 1000314004, + VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO = 1000314005, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO = 1000314006, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES = 1000314007, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ZERO_INITIALIZE_WORKGROUP_MEMORY_FEATURES = 1000325000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES = 1000335000, + VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2 = 1000337000, + VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2 = 1000337001, + VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2 = 1000337002, + VK_STRUCTURE_TYPE_COPY_IMAGE_TO_BUFFER_INFO_2 = 1000337003, + VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2 = 1000337004, + VK_STRUCTURE_TYPE_RESOLVE_IMAGE_INFO_2 = 1000337005, + VK_STRUCTURE_TYPE_BUFFER_COPY_2 = 1000337006, + VK_STRUCTURE_TYPE_IMAGE_COPY_2 = 1000337007, + VK_STRUCTURE_TYPE_IMAGE_BLIT_2 = 1000337008, + VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2 = 1000337009, + VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2 = 1000337010, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES = 1000225000, + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO = 1000225001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES = 1000225002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES = 1000138000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES = 1000138001, + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK = 1000138002, + VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO = 1000138003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES = 1000066000, + VK_STRUCTURE_TYPE_RENDERING_INFO = 1000044000, + VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO = 1000044001, + VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO = 1000044002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES = 1000044003, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO = 1000044004, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES = 1000280000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_PROPERTIES = 1000280001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES = 1000281001, + VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3 = 1000360000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES = 1000413000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES = 1000413001, + VK_STRUCTURE_TYPE_DEVICE_BUFFER_MEMORY_REQUIREMENTS = 1000413002, + VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS = 1000413003, + VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR = 1000001000, + VK_STRUCTURE_TYPE_PRESENT_INFO_KHR = 1000001001, + VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR = 1000060007, + VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHR = 1000060008, + VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR = 1000060009, + VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR = 1000060010, + VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_INFO_KHR = 1000060011, + VK_STRUCTURE_TYPE_DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHR = 1000060012, + VK_STRUCTURE_TYPE_DISPLAY_MODE_CREATE_INFO_KHR = 1000002000, + VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR = 1000002001, + VK_STRUCTURE_TYPE_DISPLAY_PRESENT_INFO_KHR = 1000003000, + VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR = 1000004000, + VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR = 1000005000, + VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR = 1000006000, + VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR = 1000008000, + VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000, + VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT = 1000011000, + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_RASTERIZATION_ORDER_AMD = 1000018000, + VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT = 1000022000, + VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_TAG_INFO_EXT = 1000022001, + VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT = 1000022002, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_PROFILE_KHR = 1000023000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR = 1000023001, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_KHR = 1000023002, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_GET_MEMORY_PROPERTIES_KHR = 1000023003, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_BIND_MEMORY_KHR = 1000023004, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_SESSION_CREATE_INFO_KHR = 1000023005, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR = 1000023006, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_UPDATE_INFO_KHR = 1000023007, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR = 1000023008, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_END_CODING_INFO_KHR = 1000023009, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_CODING_CONTROL_INFO_KHR = 1000023010, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_KHR = 1000023011, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_QUEUE_FAMILY_PROPERTIES_2_KHR = 1000023012, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_PROFILES_KHR = 1000023013, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_FORMAT_INFO_KHR = 1000023014, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_FORMAT_PROPERTIES_KHR = 1000023015, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_QUEUE_FAMILY_QUERY_RESULT_STATUS_PROPERTIES_2_KHR = 1000023016, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_INFO_KHR = 1000024000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_CAPABILITIES_KHR = 1000024001, +#endif + VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV = 1000026000, + VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV = 1000026001, + VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV = 1000026002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT = 1000028000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT = 1000028001, + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT = 1000028002, + VK_STRUCTURE_TYPE_CU_MODULE_CREATE_INFO_NVX = 1000029000, + VK_STRUCTURE_TYPE_CU_FUNCTION_CREATE_INFO_NVX = 1000029001, + VK_STRUCTURE_TYPE_CU_LAUNCH_INFO_NVX = 1000029002, + VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX = 1000030000, + VK_STRUCTURE_TYPE_IMAGE_VIEW_ADDRESS_PROPERTIES_NVX = 1000030001, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_CAPABILITIES_EXT = 1000038000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_CREATE_INFO_EXT = 1000038001, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_ADD_INFO_EXT = 1000038002, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_VCL_FRAME_INFO_EXT = 1000038003, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_DPB_SLOT_INFO_EXT = 1000038004, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_NALU_SLICE_EXT = 1000038005, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_EMIT_PICTURE_PARAMETERS_EXT = 1000038006, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PROFILE_EXT = 1000038007, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_RATE_CONTROL_INFO_EXT = 1000038008, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_RATE_CONTROL_LAYER_INFO_EXT = 1000038009, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_REFERENCE_LISTS_EXT = 1000038010, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_CAPABILITIES_EXT = 1000039000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_CREATE_INFO_EXT = 1000039001, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_ADD_INFO_EXT = 1000039002, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_VCL_FRAME_INFO_EXT = 1000039003, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_DPB_SLOT_INFO_EXT = 1000039004, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_NALU_SLICE_SEGMENT_EXT = 1000039005, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_EMIT_PICTURE_PARAMETERS_EXT = 1000039006, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PROFILE_EXT = 1000039007, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_REFERENCE_LISTS_EXT = 1000039008, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_RATE_CONTROL_INFO_EXT = 1000039009, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_RATE_CONTROL_LAYER_INFO_EXT = 1000039010, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_CAPABILITIES_EXT = 1000040000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PICTURE_INFO_EXT = 1000040001, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_MVC_EXT = 1000040002, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_EXT = 1000040003, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_EXT = 1000040004, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_ADD_INFO_EXT = 1000040005, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_DPB_SLOT_INFO_EXT = 1000040006, +#endif + VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD = 1000041000, + VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR = 1000044006, + VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_INFO_EXT = 1000044007, + VK_STRUCTURE_TYPE_ATTACHMENT_SAMPLE_COUNT_INFO_AMD = 1000044008, + VK_STRUCTURE_TYPE_MULTIVIEW_PER_VIEW_ATTRIBUTES_INFO_NVX = 1000044009, + VK_STRUCTURE_TYPE_STREAM_DESCRIPTOR_SURFACE_CREATE_INFO_GGP = 1000049000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV = 1000050000, + VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV = 1000056000, + VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV = 1000056001, + VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057000, + VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057001, + VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV = 1000058000, + VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT = 1000061000, + VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN = 1000062000, + VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT = 1000067000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT = 1000067001, + VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR = 1000073000, + VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR = 1000073001, + VK_STRUCTURE_TYPE_MEMORY_WIN32_HANDLE_PROPERTIES_KHR = 1000073002, + VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR = 1000073003, + VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR = 1000074000, + VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR = 1000074001, + VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR = 1000074002, + VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR = 1000075000, + VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR = 1000078000, + VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR = 1000078001, + VK_STRUCTURE_TYPE_D3D12_FENCE_SUBMIT_INFO_KHR = 1000078002, + VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR = 1000078003, + VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR = 1000079000, + VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR = 1000079001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR = 1000080000, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT = 1000081000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT = 1000081001, + VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT = 1000081002, + VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR = 1000084000, + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_W_SCALING_STATE_CREATE_INFO_NV = 1000087000, + VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT = 1000090000, + VK_STRUCTURE_TYPE_DISPLAY_POWER_INFO_EXT = 1000091000, + VK_STRUCTURE_TYPE_DEVICE_EVENT_INFO_EXT = 1000091001, + VK_STRUCTURE_TYPE_DISPLAY_EVENT_INFO_EXT = 1000091002, + VK_STRUCTURE_TYPE_SWAPCHAIN_COUNTER_CREATE_INFO_EXT = 1000091003, + VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE = 1000092000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_ATTRIBUTES_PROPERTIES_NVX = 1000097000, + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SWIZZLE_STATE_CREATE_INFO_NV = 1000098000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISCARD_RECTANGLE_PROPERTIES_EXT = 1000099000, + VK_STRUCTURE_TYPE_PIPELINE_DISCARD_RECTANGLE_STATE_CREATE_INFO_EXT = 1000099001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONSERVATIVE_RASTERIZATION_PROPERTIES_EXT = 1000101000, + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT = 1000101001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT = 1000102000, + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT = 1000102001, + VK_STRUCTURE_TYPE_HDR_METADATA_EXT = 1000105000, + VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR = 1000111000, + VK_STRUCTURE_TYPE_IMPORT_FENCE_WIN32_HANDLE_INFO_KHR = 1000114000, + VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR = 1000114001, + VK_STRUCTURE_TYPE_FENCE_GET_WIN32_HANDLE_INFO_KHR = 1000114002, + VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR = 1000115000, + VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR = 1000115001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR = 1000116000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_PROPERTIES_KHR = 1000116001, + VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_CREATE_INFO_KHR = 1000116002, + VK_STRUCTURE_TYPE_PERFORMANCE_QUERY_SUBMIT_INFO_KHR = 1000116003, + VK_STRUCTURE_TYPE_ACQUIRE_PROFILING_LOCK_INFO_KHR = 1000116004, + VK_STRUCTURE_TYPE_PERFORMANCE_COUNTER_KHR = 1000116005, + VK_STRUCTURE_TYPE_PERFORMANCE_COUNTER_DESCRIPTION_KHR = 1000116006, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR = 1000119000, + VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR = 1000119001, + VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR = 1000119002, + VK_STRUCTURE_TYPE_DISPLAY_PROPERTIES_2_KHR = 1000121000, + VK_STRUCTURE_TYPE_DISPLAY_PLANE_PROPERTIES_2_KHR = 1000121001, + VK_STRUCTURE_TYPE_DISPLAY_MODE_PROPERTIES_2_KHR = 1000121002, + VK_STRUCTURE_TYPE_DISPLAY_PLANE_INFO_2_KHR = 1000121003, + VK_STRUCTURE_TYPE_DISPLAY_PLANE_CAPABILITIES_2_KHR = 1000121004, + VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK = 1000122000, + VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000123000, + VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT = 1000128000, + VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_TAG_INFO_EXT = 1000128001, + VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT = 1000128002, + VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT = 1000128003, + VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT = 1000128004, + VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID = 1000129000, + VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID = 1000129001, + VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID = 1000129002, + VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID = 1000129003, + VK_STRUCTURE_TYPE_MEMORY_GET_ANDROID_HARDWARE_BUFFER_INFO_ANDROID = 1000129004, + VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID = 1000129005, + VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_2_ANDROID = 1000129006, + VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT = 1000143000, + VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT = 1000143001, + VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT = 1000143002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT = 1000143003, + VK_STRUCTURE_TYPE_MULTISAMPLE_PROPERTIES_EXT = 1000143004, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT = 1000148000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT = 1000148001, + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT = 1000148002, + VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_TO_COLOR_STATE_CREATE_INFO_NV = 1000149000, + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR = 1000150007, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR = 1000150000, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR = 1000150002, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR = 1000150003, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR = 1000150004, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR = 1000150005, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR = 1000150006, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_VERSION_INFO_KHR = 1000150009, + VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR = 1000150010, + VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_TO_MEMORY_INFO_KHR = 1000150011, + VK_STRUCTURE_TYPE_COPY_MEMORY_TO_ACCELERATION_STRUCTURE_INFO_KHR = 1000150012, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR = 1000150013, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR = 1000150014, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR = 1000150017, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR = 1000150020, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR = 1000347000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR = 1000347001, + VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR = 1000150015, + VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR = 1000150016, + VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_INTERFACE_CREATE_INFO_KHR = 1000150018, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_QUERY_FEATURES_KHR = 1000348013, + VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_MODULATION_STATE_CREATE_INFO_NV = 1000152000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_FEATURES_NV = 1000154000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_PROPERTIES_NV = 1000154001, + VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT = 1000158000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT = 1000158002, + VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT = 1000158003, + VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT = 1000158004, + VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT = 1000158005, + VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_2_EXT = 1000158006, + VK_STRUCTURE_TYPE_VALIDATION_CACHE_CREATE_INFO_EXT = 1000160000, + VK_STRUCTURE_TYPE_SHADER_MODULE_VALIDATION_CACHE_CREATE_INFO_EXT = 1000160001, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR = 1000163000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_PROPERTIES_KHR = 1000163001, +#endif + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SHADING_RATE_IMAGE_STATE_CREATE_INFO_NV = 1000164000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV = 1000164001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_PROPERTIES_NV = 1000164002, + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_COARSE_SAMPLE_ORDER_STATE_CREATE_INFO_NV = 1000164005, + VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_NV = 1000165000, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV = 1000165001, + VK_STRUCTURE_TYPE_GEOMETRY_NV = 1000165003, + VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV = 1000165004, + VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV = 1000165005, + VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV = 1000165006, + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV = 1000165007, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV = 1000165008, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV = 1000165009, + VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV = 1000165011, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV = 1000165012, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_REPRESENTATIVE_FRAGMENT_TEST_FEATURES_NV = 1000166000, + VK_STRUCTURE_TYPE_PIPELINE_REPRESENTATIVE_FRAGMENT_TEST_STATE_CREATE_INFO_NV = 1000166001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_IMAGE_FORMAT_INFO_EXT = 1000170000, + VK_STRUCTURE_TYPE_FILTER_CUBIC_IMAGE_VIEW_IMAGE_FORMAT_PROPERTIES_EXT = 1000170001, + VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT = 1000178000, + VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT = 1000178001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT = 1000178002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CLOCK_FEATURES_KHR = 1000181000, + VK_STRUCTURE_TYPE_PIPELINE_COMPILER_CONTROL_CREATE_INFO_AMD = 1000183000, + VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_EXT = 1000184000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_AMD = 1000185000, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_CAPABILITIES_EXT = 1000187000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_CREATE_INFO_EXT = 1000187001, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_ADD_INFO_EXT = 1000187002, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_EXT = 1000187003, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PICTURE_INFO_EXT = 1000187004, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_DPB_SLOT_INFO_EXT = 1000187005, +#endif + VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_KHR = 1000174000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_KHR = 1000388000, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_KHR = 1000388001, + VK_STRUCTURE_TYPE_DEVICE_MEMORY_OVERALLOCATION_CREATE_INFO_AMD = 1000189000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT = 1000190000, + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT = 1000190001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT = 1000190002, + VK_STRUCTURE_TYPE_PRESENT_FRAME_TOKEN_GGP = 1000191000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_NV = 1000201000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_NV = 1000202000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_NV = 1000202001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_FOOTPRINT_FEATURES_NV = 1000204000, + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_EXCLUSIVE_SCISSOR_STATE_CREATE_INFO_NV = 1000205000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXCLUSIVE_SCISSOR_FEATURES_NV = 1000205002, + VK_STRUCTURE_TYPE_CHECKPOINT_DATA_NV = 1000206000, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_NV = 1000206001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_FUNCTIONS_2_FEATURES_INTEL = 1000209000, + VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_QUERY_CREATE_INFO_INTEL = 1000210000, + VK_STRUCTURE_TYPE_INITIALIZE_PERFORMANCE_API_INFO_INTEL = 1000210001, + VK_STRUCTURE_TYPE_PERFORMANCE_MARKER_INFO_INTEL = 1000210002, + VK_STRUCTURE_TYPE_PERFORMANCE_STREAM_MARKER_INFO_INTEL = 1000210003, + VK_STRUCTURE_TYPE_PERFORMANCE_OVERRIDE_INFO_INTEL = 1000210004, + VK_STRUCTURE_TYPE_PERFORMANCE_CONFIGURATION_ACQUIRE_INFO_INTEL = 1000210005, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT = 1000212000, + VK_STRUCTURE_TYPE_DISPLAY_NATIVE_HDR_SURFACE_CAPABILITIES_AMD = 1000213000, + VK_STRUCTURE_TYPE_SWAPCHAIN_DISPLAY_NATIVE_HDR_CREATE_INFO_AMD = 1000213001, + VK_STRUCTURE_TYPE_IMAGEPIPE_SURFACE_CREATE_INFO_FUCHSIA = 1000214000, + VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT = 1000217000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT = 1000218000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_PROPERTIES_EXT = 1000218001, + VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT = 1000218002, + VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR = 1000226000, + VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR = 1000226001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR = 1000226002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR = 1000226003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR = 1000226004, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_2_AMD = 1000227000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COHERENT_MEMORY_FEATURES_AMD = 1000229000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_ATOMIC_INT64_FEATURES_EXT = 1000234000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT = 1000237000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PRIORITY_FEATURES_EXT = 1000238000, + VK_STRUCTURE_TYPE_MEMORY_PRIORITY_ALLOCATE_INFO_EXT = 1000238001, + VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR = 1000239000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEDICATED_ALLOCATION_IMAGE_ALIASING_FEATURES_NV = 1000240000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT = 1000244000, + VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_CREATE_INFO_EXT = 1000244002, + VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT = 1000247000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_WAIT_FEATURES_KHR = 1000248000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_NV = 1000249000, + VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_PROPERTIES_NV = 1000249001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_NV = 1000249002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COVERAGE_REDUCTION_MODE_FEATURES_NV = 1000250000, + VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_REDUCTION_STATE_CREATE_INFO_NV = 1000250001, + VK_STRUCTURE_TYPE_FRAMEBUFFER_MIXED_SAMPLES_COMBINATION_NV = 1000250002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT = 1000251000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_IMAGE_ARRAYS_FEATURES_EXT = 1000252000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT = 1000254000, + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT = 1000254001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_PROPERTIES_EXT = 1000254002, + VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT = 1000255000, + VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_FULL_SCREEN_EXCLUSIVE_EXT = 1000255002, + VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_WIN32_INFO_EXT = 1000255001, + VK_STRUCTURE_TYPE_HEADLESS_SURFACE_CREATE_INFO_EXT = 1000256000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT = 1000259000, + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT = 1000259001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_EXT = 1000259002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT = 1000260000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT = 1000265000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT = 1000267000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR = 1000269000, + VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR = 1000269001, + VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_PROPERTIES_KHR = 1000269002, + VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR = 1000269003, + VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR = 1000269004, + VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR = 1000269005, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_2_FEATURES_EXT = 1000273000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_PROPERTIES_NV = 1000277000, + VK_STRUCTURE_TYPE_GRAPHICS_SHADER_GROUP_CREATE_INFO_NV = 1000277001, + VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_SHADER_GROUPS_CREATE_INFO_NV = 1000277002, + VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_TOKEN_NV = 1000277003, + VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NV = 1000277004, + VK_STRUCTURE_TYPE_GENERATED_COMMANDS_INFO_NV = 1000277005, + VK_STRUCTURE_TYPE_GENERATED_COMMANDS_MEMORY_REQUIREMENTS_INFO_NV = 1000277006, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_FEATURES_NV = 1000277007, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INHERITED_VIEWPORT_SCISSOR_FEATURES_NV = 1000278000, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_VIEWPORT_SCISSOR_INFO_NV = 1000278001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT = 1000281000, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDER_PASS_TRANSFORM_INFO_QCOM = 1000282000, + VK_STRUCTURE_TYPE_RENDER_PASS_TRANSFORM_BEGIN_INFO_QCOM = 1000282001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_MEMORY_REPORT_FEATURES_EXT = 1000284000, + VK_STRUCTURE_TYPE_DEVICE_DEVICE_MEMORY_REPORT_CREATE_INFO_EXT = 1000284001, + VK_STRUCTURE_TYPE_DEVICE_MEMORY_REPORT_CALLBACK_DATA_EXT = 1000284002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT = 1000286000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_EXT = 1000286001, + VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT = 1000287000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_PROPERTIES_EXT = 1000287001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT = 1000287002, + VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR = 1000290000, + VK_STRUCTURE_TYPE_PRESENT_ID_KHR = 1000294000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_ID_FEATURES_KHR = 1000294001, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_INFO_KHR = 1000299000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_RATE_CONTROL_INFO_KHR = 1000299001, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_RATE_CONTROL_LAYER_INFO_KHR = 1000299002, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_CAPABILITIES_KHR = 1000299003, +#endif + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV = 1000300000, + VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV = 1000300001, + VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECT_CREATE_INFO_EXT = 1000311000, + VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECTS_INFO_EXT = 1000311001, + VK_STRUCTURE_TYPE_EXPORT_METAL_DEVICE_INFO_EXT = 1000311002, + VK_STRUCTURE_TYPE_EXPORT_METAL_COMMAND_QUEUE_INFO_EXT = 1000311003, + VK_STRUCTURE_TYPE_EXPORT_METAL_BUFFER_INFO_EXT = 1000311004, + VK_STRUCTURE_TYPE_IMPORT_METAL_BUFFER_INFO_EXT = 1000311005, + VK_STRUCTURE_TYPE_EXPORT_METAL_TEXTURE_INFO_EXT = 1000311006, + VK_STRUCTURE_TYPE_IMPORT_METAL_TEXTURE_INFO_EXT = 1000311007, + VK_STRUCTURE_TYPE_EXPORT_METAL_IO_SURFACE_INFO_EXT = 1000311008, + VK_STRUCTURE_TYPE_IMPORT_METAL_IO_SURFACE_INFO_EXT = 1000311009, + VK_STRUCTURE_TYPE_EXPORT_METAL_SHARED_EVENT_INFO_EXT = 1000311010, + VK_STRUCTURE_TYPE_IMPORT_METAL_SHARED_EVENT_INFO_EXT = 1000311011, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_2_NV = 1000314008, + VK_STRUCTURE_TYPE_CHECKPOINT_DATA_2_NV = 1000314009, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_FEATURES_EXT = 1000320000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_PROPERTIES_EXT = 1000320001, + VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT = 1000320002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_EARLY_AND_LATE_FRAGMENT_TESTS_FEATURES_AMD = 1000321000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_KHR = 1000203000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_PROPERTIES_KHR = 1000322000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_FEATURES_KHR = 1000323000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_ENUMS_PROPERTIES_NV = 1000326000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_ENUMS_FEATURES_NV = 1000326001, + VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_ENUM_STATE_CREATE_INFO_NV = 1000326002, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_MOTION_TRIANGLES_DATA_NV = 1000327000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_MOTION_BLUR_FEATURES_NV = 1000327001, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MOTION_INFO_NV = 1000327002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_2_PLANE_444_FORMATS_FEATURES_EXT = 1000330000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_FEATURES_EXT = 1000332000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_PROPERTIES_EXT = 1000332001, + VK_STRUCTURE_TYPE_COPY_COMMAND_TRANSFORM_INFO_QCOM = 1000333000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_FEATURES_KHR = 1000336000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_FEATURES_EXT = 1000338000, + VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT = 1000338001, + VK_STRUCTURE_TYPE_SUBRESOURCE_LAYOUT_2_EXT = 1000338002, + VK_STRUCTURE_TYPE_IMAGE_SUBRESOURCE_2_EXT = 1000338003, + VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_PROPERTIES_EXT = 1000338004, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT = 1000340000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_ARM = 1000342000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RGBA10X6_FORMATS_FEATURES_EXT = 1000344000, + VK_STRUCTURE_TYPE_DIRECTFB_SURFACE_CREATE_INFO_EXT = 1000346000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_VALVE = 1000351000, + VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_VALVE = 1000351002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT = 1000352000, + VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT = 1000352001, + VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT = 1000352002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRM_PROPERTIES_EXT = 1000353000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_CONTROL_FEATURES_EXT = 1000355000, + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT = 1000355001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVE_TOPOLOGY_LIST_RESTART_FEATURES_EXT = 1000356000, + VK_STRUCTURE_TYPE_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA = 1000364000, + VK_STRUCTURE_TYPE_MEMORY_ZIRCON_HANDLE_PROPERTIES_FUCHSIA = 1000364001, + VK_STRUCTURE_TYPE_MEMORY_GET_ZIRCON_HANDLE_INFO_FUCHSIA = 1000364002, + VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_ZIRCON_HANDLE_INFO_FUCHSIA = 1000365000, + VK_STRUCTURE_TYPE_SEMAPHORE_GET_ZIRCON_HANDLE_INFO_FUCHSIA = 1000365001, + VK_STRUCTURE_TYPE_BUFFER_COLLECTION_CREATE_INFO_FUCHSIA = 1000366000, + VK_STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA = 1000366001, + VK_STRUCTURE_TYPE_BUFFER_COLLECTION_IMAGE_CREATE_INFO_FUCHSIA = 1000366002, + VK_STRUCTURE_TYPE_BUFFER_COLLECTION_PROPERTIES_FUCHSIA = 1000366003, + VK_STRUCTURE_TYPE_BUFFER_CONSTRAINTS_INFO_FUCHSIA = 1000366004, + VK_STRUCTURE_TYPE_BUFFER_COLLECTION_BUFFER_CREATE_INFO_FUCHSIA = 1000366005, + VK_STRUCTURE_TYPE_IMAGE_CONSTRAINTS_INFO_FUCHSIA = 1000366006, + VK_STRUCTURE_TYPE_IMAGE_FORMAT_CONSTRAINTS_INFO_FUCHSIA = 1000366007, + VK_STRUCTURE_TYPE_SYSMEM_COLOR_SPACE_FUCHSIA = 1000366008, + VK_STRUCTURE_TYPE_BUFFER_COLLECTION_CONSTRAINTS_INFO_FUCHSIA = 1000366009, + VK_STRUCTURE_TYPE_SUBPASS_SHADING_PIPELINE_CREATE_INFO_HUAWEI = 1000369000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_SHADING_FEATURES_HUAWEI = 1000369001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_SHADING_PROPERTIES_HUAWEI = 1000369002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INVOCATION_MASK_FEATURES_HUAWEI = 1000370000, + VK_STRUCTURE_TYPE_MEMORY_GET_REMOTE_ADDRESS_INFO_NV = 1000371000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_RDMA_FEATURES_NV = 1000371001, + VK_STRUCTURE_TYPE_PIPELINE_PROPERTIES_IDENTIFIER_EXT = 1000372000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROPERTIES_FEATURES_EXT = 1000372001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT = 1000377000, + VK_STRUCTURE_TYPE_SCREEN_SURFACE_CREATE_INFO_QNX = 1000378000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT = 1000381000, + VK_STRUCTURE_TYPE_PIPELINE_COLOR_WRITE_CREATE_INFO_EXT = 1000381001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVES_GENERATED_QUERY_FEATURES_EXT = 1000382000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_MAINTENANCE_1_FEATURES_KHR = 1000386000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT = 1000391000, + VK_STRUCTURE_TYPE_IMAGE_VIEW_MIN_LOD_CREATE_INFO_EXT = 1000391001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_FEATURES_EXT = 1000392000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_PROPERTIES_EXT = 1000392001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_2D_VIEW_OF_3D_FEATURES_EXT = 1000393000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BORDER_COLOR_SWIZZLE_FEATURES_EXT = 1000411000, + VK_STRUCTURE_TYPE_SAMPLER_BORDER_COLOR_COMPONENT_MAPPING_CREATE_INFO_EXT = 1000411001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PAGEABLE_DEVICE_LOCAL_MEMORY_FEATURES_EXT = 1000412000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_SET_HOST_MAPPING_FEATURES_VALVE = 1000420000, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_BINDING_REFERENCE_VALVE = 1000420001, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_HOST_MAPPING_INFO_VALVE = 1000420002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NON_SEAMLESS_CUBE_MAP_FEATURES_EXT = 1000422000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_FEATURES_QCOM = 1000425000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_PROPERTIES_QCOM = 1000425001, + VK_STRUCTURE_TYPE_SUBPASS_FRAGMENT_DENSITY_MAP_OFFSET_END_INFO_QCOM = 1000425002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINEAR_COLOR_ATTACHMENT_FEATURES_NV = 1000430000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_FEATURES_EXT = 1000437000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_MERGE_FEEDBACK_FEATURES_EXT = 1000458000, + VK_STRUCTURE_TYPE_RENDER_PASS_CREATION_CONTROL_EXT = 1000458001, + VK_STRUCTURE_TYPE_RENDER_PASS_CREATION_FEEDBACK_CREATE_INFO_EXT = 1000458002, + VK_STRUCTURE_TYPE_RENDER_PASS_SUBPASS_FEEDBACK_CREATE_INFO_EXT = 1000458003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES, + VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT, + VK_STRUCTURE_TYPE_RENDERING_INFO_KHR = VK_STRUCTURE_TYPE_RENDERING_INFO, + VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, + VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO, + VK_STRUCTURE_TYPE_ATTACHMENT_SAMPLE_COUNT_INFO_NV = VK_STRUCTURE_TYPE_ATTACHMENT_SAMPLE_COUNT_INFO_AMD, + VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, + VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2, + VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2, + VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2, + VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHR = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO, + VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO_KHR = VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO, + VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO_KHR = VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO, + VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO_KHR = VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO, + VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO_KHR = VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO, + VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO_KHR = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO, + VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO_KHR = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES, + VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO, + VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO, + VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHR = VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES, + VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO, + VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, + VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO, + VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES, + VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES, + VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO, + VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES2_EXT = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES, + VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO, + VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO_KHR = VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO, + VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO_KHR = VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO, + VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2_KHR = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, + VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, + VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2, + VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2_KHR = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2, + VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2, + VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO_KHR = VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO, + VK_STRUCTURE_TYPE_SUBPASS_END_INFO_KHR = VK_STRUCTURE_TYPE_SUBPASS_END_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO, + VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES_KHR = VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES, + VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES, + VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO, + VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO, + VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES_KHR, + VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, + VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES, + VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES, + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK, + VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO, + VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2, + VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2, + VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2_KHR = VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2, + VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, + VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2_KHR = VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2, + VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO, + VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO, + VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO_KHR = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO, + VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO_KHR = VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO, + VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO_KHR = VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES, + VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES_KHR = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES, + VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO, + VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT_EXT = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT_KHR = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT, + VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_KHR, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES, + VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES, + VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE_KHR = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_NV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_KHR, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES, + VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO, + VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO_KHR = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO, + VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO_KHR = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO, + VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO_KHR = VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO, + VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO_INTEL = VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_QUERY_CREATE_INFO_INTEL, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES, + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES, + VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_STENCIL_LAYOUT_KHR = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_STENCIL_LAYOUT, + VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT_KHR = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_ADDRESS_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT, + VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_EXT = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TOOL_PROPERTIES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TOOL_PROPERTIES, + VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES, + VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_KHR = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, + VK_STRUCTURE_TYPE_BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO, + VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO_KHR = VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO, + VK_STRUCTURE_TYPE_DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO_KHR = VK_STRUCTURE_TYPE_DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_PROPERTIES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES, + VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO, + VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES, + VK_STRUCTURE_TYPE_MEMORY_BARRIER_2_KHR = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2, + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2_KHR = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2, + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2_KHR = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, + VK_STRUCTURE_TYPE_DEPENDENCY_INFO_KHR = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, + VK_STRUCTURE_TYPE_SUBMIT_INFO_2_KHR = VK_STRUCTURE_TYPE_SUBMIT_INFO_2, + VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO_KHR = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO_KHR = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ZERO_INITIALIZE_WORKGROUP_MEMORY_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ZERO_INITIALIZE_WORKGROUP_MEMORY_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES, + VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2_KHR = VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2, + VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2_KHR = VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2, + VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2_KHR = VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2, + VK_STRUCTURE_TYPE_COPY_IMAGE_TO_BUFFER_INFO_2_KHR = VK_STRUCTURE_TYPE_COPY_IMAGE_TO_BUFFER_INFO_2, + VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2_KHR = VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2, + VK_STRUCTURE_TYPE_RESOLVE_IMAGE_INFO_2_KHR = VK_STRUCTURE_TYPE_RESOLVE_IMAGE_INFO_2, + VK_STRUCTURE_TYPE_BUFFER_COPY_2_KHR = VK_STRUCTURE_TYPE_BUFFER_COPY_2, + VK_STRUCTURE_TYPE_IMAGE_COPY_2_KHR = VK_STRUCTURE_TYPE_IMAGE_COPY_2, + VK_STRUCTURE_TYPE_IMAGE_BLIT_2_KHR = VK_STRUCTURE_TYPE_IMAGE_BLIT_2, + VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2_KHR = VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2, + VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2_KHR = VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2, + VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3_KHR = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3, + VK_STRUCTURE_TYPE_PIPELINE_INFO_EXT = VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_KHR, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_EXT = VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_KHR, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES, + VK_STRUCTURE_TYPE_DEVICE_BUFFER_MEMORY_REQUIREMENTS_KHR = VK_STRUCTURE_TYPE_DEVICE_BUFFER_MEMORY_REQUIREMENTS, + VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS_KHR = VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS, + VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkStructureType; + +typedef enum VkPipelineCacheHeaderVersion { + VK_PIPELINE_CACHE_HEADER_VERSION_ONE = 1, + VK_PIPELINE_CACHE_HEADER_VERSION_MAX_ENUM = 0x7FFFFFFF +} VkPipelineCacheHeaderVersion; + +typedef enum VkImageLayout { + VK_IMAGE_LAYOUT_UNDEFINED = 0, + VK_IMAGE_LAYOUT_GENERAL = 1, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL = 2, + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL = 3, + VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL = 4, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL = 5, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL = 6, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL = 7, + VK_IMAGE_LAYOUT_PREINITIALIZED = 8, + VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL = 1000117000, + VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL = 1000117001, + VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL = 1000241000, + VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL = 1000241001, + VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL = 1000241002, + VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL = 1000241003, + VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL = 1000314000, + VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL = 1000314001, + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR = 1000001002, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR = 1000024000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_LAYOUT_VIDEO_DECODE_SRC_KHR = 1000024001, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR = 1000024002, +#endif + VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR = 1000111000, + VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT = 1000218000, + VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR = 1000164003, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_LAYOUT_VIDEO_ENCODE_DST_KHR = 1000299000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_LAYOUT_VIDEO_ENCODE_SRC_KHR = 1000299001, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR = 1000299002, +#endif + VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR, + VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_MAX_ENUM = 0x7FFFFFFF +} VkImageLayout; + +typedef enum VkObjectType { + VK_OBJECT_TYPE_UNKNOWN = 0, + VK_OBJECT_TYPE_INSTANCE = 1, + VK_OBJECT_TYPE_PHYSICAL_DEVICE = 2, + VK_OBJECT_TYPE_DEVICE = 3, + VK_OBJECT_TYPE_QUEUE = 4, + VK_OBJECT_TYPE_SEMAPHORE = 5, + VK_OBJECT_TYPE_COMMAND_BUFFER = 6, + VK_OBJECT_TYPE_FENCE = 7, + VK_OBJECT_TYPE_DEVICE_MEMORY = 8, + VK_OBJECT_TYPE_BUFFER = 9, + VK_OBJECT_TYPE_IMAGE = 10, + VK_OBJECT_TYPE_EVENT = 11, + VK_OBJECT_TYPE_QUERY_POOL = 12, + VK_OBJECT_TYPE_BUFFER_VIEW = 13, + VK_OBJECT_TYPE_IMAGE_VIEW = 14, + VK_OBJECT_TYPE_SHADER_MODULE = 15, + VK_OBJECT_TYPE_PIPELINE_CACHE = 16, + VK_OBJECT_TYPE_PIPELINE_LAYOUT = 17, + VK_OBJECT_TYPE_RENDER_PASS = 18, + VK_OBJECT_TYPE_PIPELINE = 19, + VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT = 20, + VK_OBJECT_TYPE_SAMPLER = 21, + VK_OBJECT_TYPE_DESCRIPTOR_POOL = 22, + VK_OBJECT_TYPE_DESCRIPTOR_SET = 23, + VK_OBJECT_TYPE_FRAMEBUFFER = 24, + VK_OBJECT_TYPE_COMMAND_POOL = 25, + VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION = 1000156000, + VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE = 1000085000, + VK_OBJECT_TYPE_PRIVATE_DATA_SLOT = 1000295000, + VK_OBJECT_TYPE_SURFACE_KHR = 1000000000, + VK_OBJECT_TYPE_SWAPCHAIN_KHR = 1000001000, + VK_OBJECT_TYPE_DISPLAY_KHR = 1000002000, + VK_OBJECT_TYPE_DISPLAY_MODE_KHR = 1000002001, + VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT = 1000011000, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_OBJECT_TYPE_VIDEO_SESSION_KHR = 1000023000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_OBJECT_TYPE_VIDEO_SESSION_PARAMETERS_KHR = 1000023001, +#endif + VK_OBJECT_TYPE_CU_MODULE_NVX = 1000029000, + VK_OBJECT_TYPE_CU_FUNCTION_NVX = 1000029001, + VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT = 1000128000, + VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR = 1000150000, + VK_OBJECT_TYPE_VALIDATION_CACHE_EXT = 1000160000, + VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000, + VK_OBJECT_TYPE_PERFORMANCE_CONFIGURATION_INTEL = 1000210000, + VK_OBJECT_TYPE_DEFERRED_OPERATION_KHR = 1000268000, + VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NV = 1000277000, + VK_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA = 1000366000, + VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR = VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE, + VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR = VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION, + VK_OBJECT_TYPE_PRIVATE_DATA_SLOT_EXT = VK_OBJECT_TYPE_PRIVATE_DATA_SLOT, + VK_OBJECT_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkObjectType; + +typedef enum VkVendorId { + VK_VENDOR_ID_VIV = 0x10001, + VK_VENDOR_ID_VSI = 0x10002, + VK_VENDOR_ID_KAZAN = 0x10003, + VK_VENDOR_ID_CODEPLAY = 0x10004, + VK_VENDOR_ID_MESA = 0x10005, + VK_VENDOR_ID_POCL = 0x10006, + VK_VENDOR_ID_MAX_ENUM = 0x7FFFFFFF +} VkVendorId; + +typedef enum VkSystemAllocationScope { + VK_SYSTEM_ALLOCATION_SCOPE_COMMAND = 0, + VK_SYSTEM_ALLOCATION_SCOPE_OBJECT = 1, + VK_SYSTEM_ALLOCATION_SCOPE_CACHE = 2, + VK_SYSTEM_ALLOCATION_SCOPE_DEVICE = 3, + VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE = 4, + VK_SYSTEM_ALLOCATION_SCOPE_MAX_ENUM = 0x7FFFFFFF +} VkSystemAllocationScope; + +typedef enum VkInternalAllocationType { + VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE = 0, + VK_INTERNAL_ALLOCATION_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkInternalAllocationType; + +typedef enum VkFormat { + VK_FORMAT_UNDEFINED = 0, + VK_FORMAT_R4G4_UNORM_PACK8 = 1, + VK_FORMAT_R4G4B4A4_UNORM_PACK16 = 2, + VK_FORMAT_B4G4R4A4_UNORM_PACK16 = 3, + VK_FORMAT_R5G6B5_UNORM_PACK16 = 4, + VK_FORMAT_B5G6R5_UNORM_PACK16 = 5, + VK_FORMAT_R5G5B5A1_UNORM_PACK16 = 6, + VK_FORMAT_B5G5R5A1_UNORM_PACK16 = 7, + VK_FORMAT_A1R5G5B5_UNORM_PACK16 = 8, + VK_FORMAT_R8_UNORM = 9, + VK_FORMAT_R8_SNORM = 10, + VK_FORMAT_R8_USCALED = 11, + VK_FORMAT_R8_SSCALED = 12, + VK_FORMAT_R8_UINT = 13, + VK_FORMAT_R8_SINT = 14, + VK_FORMAT_R8_SRGB = 15, + VK_FORMAT_R8G8_UNORM = 16, + VK_FORMAT_R8G8_SNORM = 17, + VK_FORMAT_R8G8_USCALED = 18, + VK_FORMAT_R8G8_SSCALED = 19, + VK_FORMAT_R8G8_UINT = 20, + VK_FORMAT_R8G8_SINT = 21, + VK_FORMAT_R8G8_SRGB = 22, + VK_FORMAT_R8G8B8_UNORM = 23, + VK_FORMAT_R8G8B8_SNORM = 24, + VK_FORMAT_R8G8B8_USCALED = 25, + VK_FORMAT_R8G8B8_SSCALED = 26, + VK_FORMAT_R8G8B8_UINT = 27, + VK_FORMAT_R8G8B8_SINT = 28, + VK_FORMAT_R8G8B8_SRGB = 29, + VK_FORMAT_B8G8R8_UNORM = 30, + VK_FORMAT_B8G8R8_SNORM = 31, + VK_FORMAT_B8G8R8_USCALED = 32, + VK_FORMAT_B8G8R8_SSCALED = 33, + VK_FORMAT_B8G8R8_UINT = 34, + VK_FORMAT_B8G8R8_SINT = 35, + VK_FORMAT_B8G8R8_SRGB = 36, + VK_FORMAT_R8G8B8A8_UNORM = 37, + VK_FORMAT_R8G8B8A8_SNORM = 38, + VK_FORMAT_R8G8B8A8_USCALED = 39, + VK_FORMAT_R8G8B8A8_SSCALED = 40, + VK_FORMAT_R8G8B8A8_UINT = 41, + VK_FORMAT_R8G8B8A8_SINT = 42, + VK_FORMAT_R8G8B8A8_SRGB = 43, + VK_FORMAT_B8G8R8A8_UNORM = 44, + VK_FORMAT_B8G8R8A8_SNORM = 45, + VK_FORMAT_B8G8R8A8_USCALED = 46, + VK_FORMAT_B8G8R8A8_SSCALED = 47, + VK_FORMAT_B8G8R8A8_UINT = 48, + VK_FORMAT_B8G8R8A8_SINT = 49, + VK_FORMAT_B8G8R8A8_SRGB = 50, + VK_FORMAT_A8B8G8R8_UNORM_PACK32 = 51, + VK_FORMAT_A8B8G8R8_SNORM_PACK32 = 52, + VK_FORMAT_A8B8G8R8_USCALED_PACK32 = 53, + VK_FORMAT_A8B8G8R8_SSCALED_PACK32 = 54, + VK_FORMAT_A8B8G8R8_UINT_PACK32 = 55, + VK_FORMAT_A8B8G8R8_SINT_PACK32 = 56, + VK_FORMAT_A8B8G8R8_SRGB_PACK32 = 57, + VK_FORMAT_A2R10G10B10_UNORM_PACK32 = 58, + VK_FORMAT_A2R10G10B10_SNORM_PACK32 = 59, + VK_FORMAT_A2R10G10B10_USCALED_PACK32 = 60, + VK_FORMAT_A2R10G10B10_SSCALED_PACK32 = 61, + VK_FORMAT_A2R10G10B10_UINT_PACK32 = 62, + VK_FORMAT_A2R10G10B10_SINT_PACK32 = 63, + VK_FORMAT_A2B10G10R10_UNORM_PACK32 = 64, + VK_FORMAT_A2B10G10R10_SNORM_PACK32 = 65, + VK_FORMAT_A2B10G10R10_USCALED_PACK32 = 66, + VK_FORMAT_A2B10G10R10_SSCALED_PACK32 = 67, + VK_FORMAT_A2B10G10R10_UINT_PACK32 = 68, + VK_FORMAT_A2B10G10R10_SINT_PACK32 = 69, + VK_FORMAT_R16_UNORM = 70, + VK_FORMAT_R16_SNORM = 71, + VK_FORMAT_R16_USCALED = 72, + VK_FORMAT_R16_SSCALED = 73, + VK_FORMAT_R16_UINT = 74, + VK_FORMAT_R16_SINT = 75, + VK_FORMAT_R16_SFLOAT = 76, + VK_FORMAT_R16G16_UNORM = 77, + VK_FORMAT_R16G16_SNORM = 78, + VK_FORMAT_R16G16_USCALED = 79, + VK_FORMAT_R16G16_SSCALED = 80, + VK_FORMAT_R16G16_UINT = 81, + VK_FORMAT_R16G16_SINT = 82, + VK_FORMAT_R16G16_SFLOAT = 83, + VK_FORMAT_R16G16B16_UNORM = 84, + VK_FORMAT_R16G16B16_SNORM = 85, + VK_FORMAT_R16G16B16_USCALED = 86, + VK_FORMAT_R16G16B16_SSCALED = 87, + VK_FORMAT_R16G16B16_UINT = 88, + VK_FORMAT_R16G16B16_SINT = 89, + VK_FORMAT_R16G16B16_SFLOAT = 90, + VK_FORMAT_R16G16B16A16_UNORM = 91, + VK_FORMAT_R16G16B16A16_SNORM = 92, + VK_FORMAT_R16G16B16A16_USCALED = 93, + VK_FORMAT_R16G16B16A16_SSCALED = 94, + VK_FORMAT_R16G16B16A16_UINT = 95, + VK_FORMAT_R16G16B16A16_SINT = 96, + VK_FORMAT_R16G16B16A16_SFLOAT = 97, + VK_FORMAT_R32_UINT = 98, + VK_FORMAT_R32_SINT = 99, + VK_FORMAT_R32_SFLOAT = 100, + VK_FORMAT_R32G32_UINT = 101, + VK_FORMAT_R32G32_SINT = 102, + VK_FORMAT_R32G32_SFLOAT = 103, + VK_FORMAT_R32G32B32_UINT = 104, + VK_FORMAT_R32G32B32_SINT = 105, + VK_FORMAT_R32G32B32_SFLOAT = 106, + VK_FORMAT_R32G32B32A32_UINT = 107, + VK_FORMAT_R32G32B32A32_SINT = 108, + VK_FORMAT_R32G32B32A32_SFLOAT = 109, + VK_FORMAT_R64_UINT = 110, + VK_FORMAT_R64_SINT = 111, + VK_FORMAT_R64_SFLOAT = 112, + VK_FORMAT_R64G64_UINT = 113, + VK_FORMAT_R64G64_SINT = 114, + VK_FORMAT_R64G64_SFLOAT = 115, + VK_FORMAT_R64G64B64_UINT = 116, + VK_FORMAT_R64G64B64_SINT = 117, + VK_FORMAT_R64G64B64_SFLOAT = 118, + VK_FORMAT_R64G64B64A64_UINT = 119, + VK_FORMAT_R64G64B64A64_SINT = 120, + VK_FORMAT_R64G64B64A64_SFLOAT = 121, + VK_FORMAT_B10G11R11_UFLOAT_PACK32 = 122, + VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 = 123, + VK_FORMAT_D16_UNORM = 124, + VK_FORMAT_X8_D24_UNORM_PACK32 = 125, + VK_FORMAT_D32_SFLOAT = 126, + VK_FORMAT_S8_UINT = 127, + VK_FORMAT_D16_UNORM_S8_UINT = 128, + VK_FORMAT_D24_UNORM_S8_UINT = 129, + VK_FORMAT_D32_SFLOAT_S8_UINT = 130, + VK_FORMAT_BC1_RGB_UNORM_BLOCK = 131, + VK_FORMAT_BC1_RGB_SRGB_BLOCK = 132, + VK_FORMAT_BC1_RGBA_UNORM_BLOCK = 133, + VK_FORMAT_BC1_RGBA_SRGB_BLOCK = 134, + VK_FORMAT_BC2_UNORM_BLOCK = 135, + VK_FORMAT_BC2_SRGB_BLOCK = 136, + VK_FORMAT_BC3_UNORM_BLOCK = 137, + VK_FORMAT_BC3_SRGB_BLOCK = 138, + VK_FORMAT_BC4_UNORM_BLOCK = 139, + VK_FORMAT_BC4_SNORM_BLOCK = 140, + VK_FORMAT_BC5_UNORM_BLOCK = 141, + VK_FORMAT_BC5_SNORM_BLOCK = 142, + VK_FORMAT_BC6H_UFLOAT_BLOCK = 143, + VK_FORMAT_BC6H_SFLOAT_BLOCK = 144, + VK_FORMAT_BC7_UNORM_BLOCK = 145, + VK_FORMAT_BC7_SRGB_BLOCK = 146, + VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK = 147, + VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK = 148, + VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK = 149, + VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK = 150, + VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK = 151, + VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK = 152, + VK_FORMAT_EAC_R11_UNORM_BLOCK = 153, + VK_FORMAT_EAC_R11_SNORM_BLOCK = 154, + VK_FORMAT_EAC_R11G11_UNORM_BLOCK = 155, + VK_FORMAT_EAC_R11G11_SNORM_BLOCK = 156, + VK_FORMAT_ASTC_4x4_UNORM_BLOCK = 157, + VK_FORMAT_ASTC_4x4_SRGB_BLOCK = 158, + VK_FORMAT_ASTC_5x4_UNORM_BLOCK = 159, + VK_FORMAT_ASTC_5x4_SRGB_BLOCK = 160, + VK_FORMAT_ASTC_5x5_UNORM_BLOCK = 161, + VK_FORMAT_ASTC_5x5_SRGB_BLOCK = 162, + VK_FORMAT_ASTC_6x5_UNORM_BLOCK = 163, + VK_FORMAT_ASTC_6x5_SRGB_BLOCK = 164, + VK_FORMAT_ASTC_6x6_UNORM_BLOCK = 165, + VK_FORMAT_ASTC_6x6_SRGB_BLOCK = 166, + VK_FORMAT_ASTC_8x5_UNORM_BLOCK = 167, + VK_FORMAT_ASTC_8x5_SRGB_BLOCK = 168, + VK_FORMAT_ASTC_8x6_UNORM_BLOCK = 169, + VK_FORMAT_ASTC_8x6_SRGB_BLOCK = 170, + VK_FORMAT_ASTC_8x8_UNORM_BLOCK = 171, + VK_FORMAT_ASTC_8x8_SRGB_BLOCK = 172, + VK_FORMAT_ASTC_10x5_UNORM_BLOCK = 173, + VK_FORMAT_ASTC_10x5_SRGB_BLOCK = 174, + VK_FORMAT_ASTC_10x6_UNORM_BLOCK = 175, + VK_FORMAT_ASTC_10x6_SRGB_BLOCK = 176, + VK_FORMAT_ASTC_10x8_UNORM_BLOCK = 177, + VK_FORMAT_ASTC_10x8_SRGB_BLOCK = 178, + VK_FORMAT_ASTC_10x10_UNORM_BLOCK = 179, + VK_FORMAT_ASTC_10x10_SRGB_BLOCK = 180, + VK_FORMAT_ASTC_12x10_UNORM_BLOCK = 181, + VK_FORMAT_ASTC_12x10_SRGB_BLOCK = 182, + VK_FORMAT_ASTC_12x12_UNORM_BLOCK = 183, + VK_FORMAT_ASTC_12x12_SRGB_BLOCK = 184, + VK_FORMAT_G8B8G8R8_422_UNORM = 1000156000, + VK_FORMAT_B8G8R8G8_422_UNORM = 1000156001, + VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM = 1000156002, + VK_FORMAT_G8_B8R8_2PLANE_420_UNORM = 1000156003, + VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM = 1000156004, + VK_FORMAT_G8_B8R8_2PLANE_422_UNORM = 1000156005, + VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM = 1000156006, + VK_FORMAT_R10X6_UNORM_PACK16 = 1000156007, + VK_FORMAT_R10X6G10X6_UNORM_2PACK16 = 1000156008, + VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16 = 1000156009, + VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16 = 1000156010, + VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16 = 1000156011, + VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16 = 1000156012, + VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16 = 1000156013, + VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16 = 1000156014, + VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16 = 1000156015, + VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16 = 1000156016, + VK_FORMAT_R12X4_UNORM_PACK16 = 1000156017, + VK_FORMAT_R12X4G12X4_UNORM_2PACK16 = 1000156018, + VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16 = 1000156019, + VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16 = 1000156020, + VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16 = 1000156021, + VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16 = 1000156022, + VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16 = 1000156023, + VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16 = 1000156024, + VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16 = 1000156025, + VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16 = 1000156026, + VK_FORMAT_G16B16G16R16_422_UNORM = 1000156027, + VK_FORMAT_B16G16R16G16_422_UNORM = 1000156028, + VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM = 1000156029, + VK_FORMAT_G16_B16R16_2PLANE_420_UNORM = 1000156030, + VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM = 1000156031, + VK_FORMAT_G16_B16R16_2PLANE_422_UNORM = 1000156032, + VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM = 1000156033, + VK_FORMAT_G8_B8R8_2PLANE_444_UNORM = 1000330000, + VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16 = 1000330001, + VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16 = 1000330002, + VK_FORMAT_G16_B16R16_2PLANE_444_UNORM = 1000330003, + VK_FORMAT_A4R4G4B4_UNORM_PACK16 = 1000340000, + VK_FORMAT_A4B4G4R4_UNORM_PACK16 = 1000340001, + VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK = 1000066000, + VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK = 1000066001, + VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK = 1000066002, + VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK = 1000066003, + VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK = 1000066004, + VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK = 1000066005, + VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK = 1000066006, + VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK = 1000066007, + VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK = 1000066008, + VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK = 1000066009, + VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK = 1000066010, + VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK = 1000066011, + VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK = 1000066012, + VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK = 1000066013, + VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG = 1000054000, + VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG = 1000054001, + VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG = 1000054002, + VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG = 1000054003, + VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG = 1000054004, + VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG = 1000054005, + VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG = 1000054006, + VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG = 1000054007, + VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK, + VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK, + VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK, + VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK, + VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK, + VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK, + VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK, + VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK, + VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK, + VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK, + VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK, + VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK, + VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK, + VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK, + VK_FORMAT_G8B8G8R8_422_UNORM_KHR = VK_FORMAT_G8B8G8R8_422_UNORM, + VK_FORMAT_B8G8R8G8_422_UNORM_KHR = VK_FORMAT_B8G8R8G8_422_UNORM, + VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM_KHR = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM, + VK_FORMAT_G8_B8R8_2PLANE_420_UNORM_KHR = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, + VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM_KHR = VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM, + VK_FORMAT_G8_B8R8_2PLANE_422_UNORM_KHR = VK_FORMAT_G8_B8R8_2PLANE_422_UNORM, + VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM_KHR = VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM, + VK_FORMAT_R10X6_UNORM_PACK16_KHR = VK_FORMAT_R10X6_UNORM_PACK16, + VK_FORMAT_R10X6G10X6_UNORM_2PACK16_KHR = VK_FORMAT_R10X6G10X6_UNORM_2PACK16, + VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16_KHR = VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16, + VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16_KHR = VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16, + VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16_KHR = VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16, + VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_KHR = VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16, + VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_KHR = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16, + VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16_KHR = VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16, + VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16_KHR = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16, + VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16_KHR = VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16, + VK_FORMAT_R12X4_UNORM_PACK16_KHR = VK_FORMAT_R12X4_UNORM_PACK16, + VK_FORMAT_R12X4G12X4_UNORM_2PACK16_KHR = VK_FORMAT_R12X4G12X4_UNORM_2PACK16, + VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16_KHR = VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16, + VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16_KHR = VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16, + VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16_KHR = VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16, + VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_KHR = VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16, + VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_KHR = VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16, + VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16_KHR = VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16, + VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16_KHR = VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16, + VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16_KHR = VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16, + VK_FORMAT_G16B16G16R16_422_UNORM_KHR = VK_FORMAT_G16B16G16R16_422_UNORM, + VK_FORMAT_B16G16R16G16_422_UNORM_KHR = VK_FORMAT_B16G16R16G16_422_UNORM, + VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM_KHR = VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, + VK_FORMAT_G16_B16R16_2PLANE_420_UNORM_KHR = VK_FORMAT_G16_B16R16_2PLANE_420_UNORM, + VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM_KHR = VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, + VK_FORMAT_G16_B16R16_2PLANE_422_UNORM_KHR = VK_FORMAT_G16_B16R16_2PLANE_422_UNORM, + VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM_KHR = VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, + VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT = VK_FORMAT_G8_B8R8_2PLANE_444_UNORM, + VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16_EXT = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16, + VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16_EXT = VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16, + VK_FORMAT_G16_B16R16_2PLANE_444_UNORM_EXT = VK_FORMAT_G16_B16R16_2PLANE_444_UNORM, + VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT = VK_FORMAT_A4R4G4B4_UNORM_PACK16, + VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT = VK_FORMAT_A4B4G4R4_UNORM_PACK16, + VK_FORMAT_MAX_ENUM = 0x7FFFFFFF +} VkFormat; + +typedef enum VkImageTiling { + VK_IMAGE_TILING_OPTIMAL = 0, + VK_IMAGE_TILING_LINEAR = 1, + VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT = 1000158000, + VK_IMAGE_TILING_MAX_ENUM = 0x7FFFFFFF +} VkImageTiling; + +typedef enum VkImageType { + VK_IMAGE_TYPE_1D = 0, + VK_IMAGE_TYPE_2D = 1, + VK_IMAGE_TYPE_3D = 2, + VK_IMAGE_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkImageType; + +typedef enum VkPhysicalDeviceType { + VK_PHYSICAL_DEVICE_TYPE_OTHER = 0, + VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU = 1, + VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU = 2, + VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU = 3, + VK_PHYSICAL_DEVICE_TYPE_CPU = 4, + VK_PHYSICAL_DEVICE_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkPhysicalDeviceType; + +typedef enum VkQueryType { + VK_QUERY_TYPE_OCCLUSION = 0, + VK_QUERY_TYPE_PIPELINE_STATISTICS = 1, + VK_QUERY_TYPE_TIMESTAMP = 2, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR = 1000023000, +#endif + VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT = 1000028004, + VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR = 1000116000, + VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR = 1000150000, + VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR = 1000150001, + VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV = 1000165000, + VK_QUERY_TYPE_PERFORMANCE_QUERY_INTEL = 1000210000, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_QUERY_TYPE_VIDEO_ENCODE_BITSTREAM_BUFFER_RANGE_KHR = 1000299000, +#endif + VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT = 1000382000, + VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_BOTTOM_LEVEL_POINTERS_KHR = 1000386000, + VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SIZE_KHR = 1000386001, + VK_QUERY_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkQueryType; + +typedef enum VkSharingMode { + VK_SHARING_MODE_EXCLUSIVE = 0, + VK_SHARING_MODE_CONCURRENT = 1, + VK_SHARING_MODE_MAX_ENUM = 0x7FFFFFFF +} VkSharingMode; + +typedef enum VkComponentSwizzle { + VK_COMPONENT_SWIZZLE_IDENTITY = 0, + VK_COMPONENT_SWIZZLE_ZERO = 1, + VK_COMPONENT_SWIZZLE_ONE = 2, + VK_COMPONENT_SWIZZLE_R = 3, + VK_COMPONENT_SWIZZLE_G = 4, + VK_COMPONENT_SWIZZLE_B = 5, + VK_COMPONENT_SWIZZLE_A = 6, + VK_COMPONENT_SWIZZLE_MAX_ENUM = 0x7FFFFFFF +} VkComponentSwizzle; + +typedef enum VkImageViewType { + VK_IMAGE_VIEW_TYPE_1D = 0, + VK_IMAGE_VIEW_TYPE_2D = 1, + VK_IMAGE_VIEW_TYPE_3D = 2, + VK_IMAGE_VIEW_TYPE_CUBE = 3, + VK_IMAGE_VIEW_TYPE_1D_ARRAY = 4, + VK_IMAGE_VIEW_TYPE_2D_ARRAY = 5, + VK_IMAGE_VIEW_TYPE_CUBE_ARRAY = 6, + VK_IMAGE_VIEW_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkImageViewType; + +typedef enum VkBlendFactor { + VK_BLEND_FACTOR_ZERO = 0, + VK_BLEND_FACTOR_ONE = 1, + VK_BLEND_FACTOR_SRC_COLOR = 2, + VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR = 3, + VK_BLEND_FACTOR_DST_COLOR = 4, + VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR = 5, + VK_BLEND_FACTOR_SRC_ALPHA = 6, + VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA = 7, + VK_BLEND_FACTOR_DST_ALPHA = 8, + VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA = 9, + VK_BLEND_FACTOR_CONSTANT_COLOR = 10, + VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR = 11, + VK_BLEND_FACTOR_CONSTANT_ALPHA = 12, + VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA = 13, + VK_BLEND_FACTOR_SRC_ALPHA_SATURATE = 14, + VK_BLEND_FACTOR_SRC1_COLOR = 15, + VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR = 16, + VK_BLEND_FACTOR_SRC1_ALPHA = 17, + VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA = 18, + VK_BLEND_FACTOR_MAX_ENUM = 0x7FFFFFFF +} VkBlendFactor; + +typedef enum VkBlendOp { + VK_BLEND_OP_ADD = 0, + VK_BLEND_OP_SUBTRACT = 1, + VK_BLEND_OP_REVERSE_SUBTRACT = 2, + VK_BLEND_OP_MIN = 3, + VK_BLEND_OP_MAX = 4, + VK_BLEND_OP_ZERO_EXT = 1000148000, + VK_BLEND_OP_SRC_EXT = 1000148001, + VK_BLEND_OP_DST_EXT = 1000148002, + VK_BLEND_OP_SRC_OVER_EXT = 1000148003, + VK_BLEND_OP_DST_OVER_EXT = 1000148004, + VK_BLEND_OP_SRC_IN_EXT = 1000148005, + VK_BLEND_OP_DST_IN_EXT = 1000148006, + VK_BLEND_OP_SRC_OUT_EXT = 1000148007, + VK_BLEND_OP_DST_OUT_EXT = 1000148008, + VK_BLEND_OP_SRC_ATOP_EXT = 1000148009, + VK_BLEND_OP_DST_ATOP_EXT = 1000148010, + VK_BLEND_OP_XOR_EXT = 1000148011, + VK_BLEND_OP_MULTIPLY_EXT = 1000148012, + VK_BLEND_OP_SCREEN_EXT = 1000148013, + VK_BLEND_OP_OVERLAY_EXT = 1000148014, + VK_BLEND_OP_DARKEN_EXT = 1000148015, + VK_BLEND_OP_LIGHTEN_EXT = 1000148016, + VK_BLEND_OP_COLORDODGE_EXT = 1000148017, + VK_BLEND_OP_COLORBURN_EXT = 1000148018, + VK_BLEND_OP_HARDLIGHT_EXT = 1000148019, + VK_BLEND_OP_SOFTLIGHT_EXT = 1000148020, + VK_BLEND_OP_DIFFERENCE_EXT = 1000148021, + VK_BLEND_OP_EXCLUSION_EXT = 1000148022, + VK_BLEND_OP_INVERT_EXT = 1000148023, + VK_BLEND_OP_INVERT_RGB_EXT = 1000148024, + VK_BLEND_OP_LINEARDODGE_EXT = 1000148025, + VK_BLEND_OP_LINEARBURN_EXT = 1000148026, + VK_BLEND_OP_VIVIDLIGHT_EXT = 1000148027, + VK_BLEND_OP_LINEARLIGHT_EXT = 1000148028, + VK_BLEND_OP_PINLIGHT_EXT = 1000148029, + VK_BLEND_OP_HARDMIX_EXT = 1000148030, + VK_BLEND_OP_HSL_HUE_EXT = 1000148031, + VK_BLEND_OP_HSL_SATURATION_EXT = 1000148032, + VK_BLEND_OP_HSL_COLOR_EXT = 1000148033, + VK_BLEND_OP_HSL_LUMINOSITY_EXT = 1000148034, + VK_BLEND_OP_PLUS_EXT = 1000148035, + VK_BLEND_OP_PLUS_CLAMPED_EXT = 1000148036, + VK_BLEND_OP_PLUS_CLAMPED_ALPHA_EXT = 1000148037, + VK_BLEND_OP_PLUS_DARKER_EXT = 1000148038, + VK_BLEND_OP_MINUS_EXT = 1000148039, + VK_BLEND_OP_MINUS_CLAMPED_EXT = 1000148040, + VK_BLEND_OP_CONTRAST_EXT = 1000148041, + VK_BLEND_OP_INVERT_OVG_EXT = 1000148042, + VK_BLEND_OP_RED_EXT = 1000148043, + VK_BLEND_OP_GREEN_EXT = 1000148044, + VK_BLEND_OP_BLUE_EXT = 1000148045, + VK_BLEND_OP_MAX_ENUM = 0x7FFFFFFF +} VkBlendOp; + +typedef enum VkCompareOp { + VK_COMPARE_OP_NEVER = 0, + VK_COMPARE_OP_LESS = 1, + VK_COMPARE_OP_EQUAL = 2, + VK_COMPARE_OP_LESS_OR_EQUAL = 3, + VK_COMPARE_OP_GREATER = 4, + VK_COMPARE_OP_NOT_EQUAL = 5, + VK_COMPARE_OP_GREATER_OR_EQUAL = 6, + VK_COMPARE_OP_ALWAYS = 7, + VK_COMPARE_OP_MAX_ENUM = 0x7FFFFFFF +} VkCompareOp; + +typedef enum VkDynamicState { + VK_DYNAMIC_STATE_VIEWPORT = 0, + VK_DYNAMIC_STATE_SCISSOR = 1, + VK_DYNAMIC_STATE_LINE_WIDTH = 2, + VK_DYNAMIC_STATE_DEPTH_BIAS = 3, + VK_DYNAMIC_STATE_BLEND_CONSTANTS = 4, + VK_DYNAMIC_STATE_DEPTH_BOUNDS = 5, + VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK = 6, + VK_DYNAMIC_STATE_STENCIL_WRITE_MASK = 7, + VK_DYNAMIC_STATE_STENCIL_REFERENCE = 8, + VK_DYNAMIC_STATE_CULL_MODE = 1000267000, + VK_DYNAMIC_STATE_FRONT_FACE = 1000267001, + VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY = 1000267002, + VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT = 1000267003, + VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT = 1000267004, + VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE = 1000267005, + VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE = 1000267006, + VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE = 1000267007, + VK_DYNAMIC_STATE_DEPTH_COMPARE_OP = 1000267008, + VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE = 1000267009, + VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE = 1000267010, + VK_DYNAMIC_STATE_STENCIL_OP = 1000267011, + VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE = 1000377001, + VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE = 1000377002, + VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE = 1000377004, + VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV = 1000087000, + VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT = 1000099000, + VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT = 1000143000, + VK_DYNAMIC_STATE_RAY_TRACING_PIPELINE_STACK_SIZE_KHR = 1000347000, + VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV = 1000164004, + VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV = 1000164006, + VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV = 1000205001, + VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR = 1000226000, + VK_DYNAMIC_STATE_LINE_STIPPLE_EXT = 1000259000, + VK_DYNAMIC_STATE_VERTEX_INPUT_EXT = 1000352000, + VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT = 1000377000, + VK_DYNAMIC_STATE_LOGIC_OP_EXT = 1000377003, + VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT = 1000381000, + VK_DYNAMIC_STATE_CULL_MODE_EXT = VK_DYNAMIC_STATE_CULL_MODE, + VK_DYNAMIC_STATE_FRONT_FACE_EXT = VK_DYNAMIC_STATE_FRONT_FACE, + VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT = VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY, + VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT = VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT, + VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT = VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT, + VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT = VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE, + VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT = VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE, + VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT = VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE, + VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT = VK_DYNAMIC_STATE_DEPTH_COMPARE_OP, + VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT = VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE, + VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT = VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE, + VK_DYNAMIC_STATE_STENCIL_OP_EXT = VK_DYNAMIC_STATE_STENCIL_OP, + VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE_EXT = VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE, + VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE_EXT = VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE, + VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT = VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE, + VK_DYNAMIC_STATE_MAX_ENUM = 0x7FFFFFFF +} VkDynamicState; + +typedef enum VkFrontFace { + VK_FRONT_FACE_COUNTER_CLOCKWISE = 0, + VK_FRONT_FACE_CLOCKWISE = 1, + VK_FRONT_FACE_MAX_ENUM = 0x7FFFFFFF +} VkFrontFace; + +typedef enum VkVertexInputRate { + VK_VERTEX_INPUT_RATE_VERTEX = 0, + VK_VERTEX_INPUT_RATE_INSTANCE = 1, + VK_VERTEX_INPUT_RATE_MAX_ENUM = 0x7FFFFFFF +} VkVertexInputRate; + +typedef enum VkPrimitiveTopology { + VK_PRIMITIVE_TOPOLOGY_POINT_LIST = 0, + VK_PRIMITIVE_TOPOLOGY_LINE_LIST = 1, + VK_PRIMITIVE_TOPOLOGY_LINE_STRIP = 2, + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST = 3, + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP = 4, + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN = 5, + VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY = 6, + VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY = 7, + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY = 8, + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY = 9, + VK_PRIMITIVE_TOPOLOGY_PATCH_LIST = 10, + VK_PRIMITIVE_TOPOLOGY_MAX_ENUM = 0x7FFFFFFF +} VkPrimitiveTopology; + +typedef enum VkPolygonMode { + VK_POLYGON_MODE_FILL = 0, + VK_POLYGON_MODE_LINE = 1, + VK_POLYGON_MODE_POINT = 2, + VK_POLYGON_MODE_FILL_RECTANGLE_NV = 1000153000, + VK_POLYGON_MODE_MAX_ENUM = 0x7FFFFFFF +} VkPolygonMode; + +typedef enum VkStencilOp { + VK_STENCIL_OP_KEEP = 0, + VK_STENCIL_OP_ZERO = 1, + VK_STENCIL_OP_REPLACE = 2, + VK_STENCIL_OP_INCREMENT_AND_CLAMP = 3, + VK_STENCIL_OP_DECREMENT_AND_CLAMP = 4, + VK_STENCIL_OP_INVERT = 5, + VK_STENCIL_OP_INCREMENT_AND_WRAP = 6, + VK_STENCIL_OP_DECREMENT_AND_WRAP = 7, + VK_STENCIL_OP_MAX_ENUM = 0x7FFFFFFF +} VkStencilOp; + +typedef enum VkLogicOp { + VK_LOGIC_OP_CLEAR = 0, + VK_LOGIC_OP_AND = 1, + VK_LOGIC_OP_AND_REVERSE = 2, + VK_LOGIC_OP_COPY = 3, + VK_LOGIC_OP_AND_INVERTED = 4, + VK_LOGIC_OP_NO_OP = 5, + VK_LOGIC_OP_XOR = 6, + VK_LOGIC_OP_OR = 7, + VK_LOGIC_OP_NOR = 8, + VK_LOGIC_OP_EQUIVALENT = 9, + VK_LOGIC_OP_INVERT = 10, + VK_LOGIC_OP_OR_REVERSE = 11, + VK_LOGIC_OP_COPY_INVERTED = 12, + VK_LOGIC_OP_OR_INVERTED = 13, + VK_LOGIC_OP_NAND = 14, + VK_LOGIC_OP_SET = 15, + VK_LOGIC_OP_MAX_ENUM = 0x7FFFFFFF +} VkLogicOp; + +typedef enum VkBorderColor { + VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK = 0, + VK_BORDER_COLOR_INT_TRANSPARENT_BLACK = 1, + VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK = 2, + VK_BORDER_COLOR_INT_OPAQUE_BLACK = 3, + VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE = 4, + VK_BORDER_COLOR_INT_OPAQUE_WHITE = 5, + VK_BORDER_COLOR_FLOAT_CUSTOM_EXT = 1000287003, + VK_BORDER_COLOR_INT_CUSTOM_EXT = 1000287004, + VK_BORDER_COLOR_MAX_ENUM = 0x7FFFFFFF +} VkBorderColor; + +typedef enum VkFilter { + VK_FILTER_NEAREST = 0, + VK_FILTER_LINEAR = 1, + VK_FILTER_CUBIC_IMG = 1000015000, + VK_FILTER_CUBIC_EXT = VK_FILTER_CUBIC_IMG, + VK_FILTER_MAX_ENUM = 0x7FFFFFFF +} VkFilter; + +typedef enum VkSamplerAddressMode { + VK_SAMPLER_ADDRESS_MODE_REPEAT = 0, + VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT = 1, + VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE = 2, + VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER = 3, + VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE = 4, + VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE_KHR = VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, + VK_SAMPLER_ADDRESS_MODE_MAX_ENUM = 0x7FFFFFFF +} VkSamplerAddressMode; + +typedef enum VkSamplerMipmapMode { + VK_SAMPLER_MIPMAP_MODE_NEAREST = 0, + VK_SAMPLER_MIPMAP_MODE_LINEAR = 1, + VK_SAMPLER_MIPMAP_MODE_MAX_ENUM = 0x7FFFFFFF +} VkSamplerMipmapMode; + +typedef enum VkDescriptorType { + VK_DESCRIPTOR_TYPE_SAMPLER = 0, + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER = 1, + VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE = 2, + VK_DESCRIPTOR_TYPE_STORAGE_IMAGE = 3, + VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER = 4, + VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER = 5, + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER = 6, + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER = 7, + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC = 8, + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 9, + VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10, + VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK = 1000138000, + VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR = 1000150000, + VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000, + VK_DESCRIPTOR_TYPE_MUTABLE_VALVE = 1000351000, + VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK, + VK_DESCRIPTOR_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkDescriptorType; + +typedef enum VkAttachmentLoadOp { + VK_ATTACHMENT_LOAD_OP_LOAD = 0, + VK_ATTACHMENT_LOAD_OP_CLEAR = 1, + VK_ATTACHMENT_LOAD_OP_DONT_CARE = 2, + VK_ATTACHMENT_LOAD_OP_NONE_EXT = 1000400000, + VK_ATTACHMENT_LOAD_OP_MAX_ENUM = 0x7FFFFFFF +} VkAttachmentLoadOp; + +typedef enum VkAttachmentStoreOp { + VK_ATTACHMENT_STORE_OP_STORE = 0, + VK_ATTACHMENT_STORE_OP_DONT_CARE = 1, + VK_ATTACHMENT_STORE_OP_NONE = 1000301000, + VK_ATTACHMENT_STORE_OP_NONE_KHR = VK_ATTACHMENT_STORE_OP_NONE, + VK_ATTACHMENT_STORE_OP_NONE_QCOM = VK_ATTACHMENT_STORE_OP_NONE, + VK_ATTACHMENT_STORE_OP_NONE_EXT = VK_ATTACHMENT_STORE_OP_NONE, + VK_ATTACHMENT_STORE_OP_MAX_ENUM = 0x7FFFFFFF +} VkAttachmentStoreOp; + +typedef enum VkPipelineBindPoint { + VK_PIPELINE_BIND_POINT_GRAPHICS = 0, + VK_PIPELINE_BIND_POINT_COMPUTE = 1, + VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR = 1000165000, + VK_PIPELINE_BIND_POINT_SUBPASS_SHADING_HUAWEI = 1000369003, + VK_PIPELINE_BIND_POINT_RAY_TRACING_NV = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, + VK_PIPELINE_BIND_POINT_MAX_ENUM = 0x7FFFFFFF +} VkPipelineBindPoint; + +typedef enum VkCommandBufferLevel { + VK_COMMAND_BUFFER_LEVEL_PRIMARY = 0, + VK_COMMAND_BUFFER_LEVEL_SECONDARY = 1, + VK_COMMAND_BUFFER_LEVEL_MAX_ENUM = 0x7FFFFFFF +} VkCommandBufferLevel; + +typedef enum VkIndexType { + VK_INDEX_TYPE_UINT16 = 0, + VK_INDEX_TYPE_UINT32 = 1, + VK_INDEX_TYPE_NONE_KHR = 1000165000, + VK_INDEX_TYPE_UINT8_EXT = 1000265000, + VK_INDEX_TYPE_NONE_NV = VK_INDEX_TYPE_NONE_KHR, + VK_INDEX_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkIndexType; + +typedef enum VkSubpassContents { + VK_SUBPASS_CONTENTS_INLINE = 0, + VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS = 1, + VK_SUBPASS_CONTENTS_MAX_ENUM = 0x7FFFFFFF +} VkSubpassContents; + +typedef enum VkAccessFlagBits { + VK_ACCESS_INDIRECT_COMMAND_READ_BIT = 0x00000001, + VK_ACCESS_INDEX_READ_BIT = 0x00000002, + VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT = 0x00000004, + VK_ACCESS_UNIFORM_READ_BIT = 0x00000008, + VK_ACCESS_INPUT_ATTACHMENT_READ_BIT = 0x00000010, + VK_ACCESS_SHADER_READ_BIT = 0x00000020, + VK_ACCESS_SHADER_WRITE_BIT = 0x00000040, + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT = 0x00000080, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT = 0x00000100, + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT = 0x00000200, + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT = 0x00000400, + VK_ACCESS_TRANSFER_READ_BIT = 0x00000800, + VK_ACCESS_TRANSFER_WRITE_BIT = 0x00001000, + VK_ACCESS_HOST_READ_BIT = 0x00002000, + VK_ACCESS_HOST_WRITE_BIT = 0x00004000, + VK_ACCESS_MEMORY_READ_BIT = 0x00008000, + VK_ACCESS_MEMORY_WRITE_BIT = 0x00010000, + VK_ACCESS_NONE = 0, + VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT = 0x02000000, + VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT = 0x04000000, + VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT = 0x08000000, + VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT = 0x00100000, + VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT = 0x00080000, + VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR = 0x00200000, + VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR = 0x00400000, + VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT = 0x01000000, + VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR = 0x00800000, + VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_NV = 0x00020000, + VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_NV = 0x00040000, + VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV = VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR, + VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, + VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, + VK_ACCESS_NONE_KHR = VK_ACCESS_NONE, + VK_ACCESS_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkAccessFlagBits; +typedef VkFlags VkAccessFlags; + +typedef enum VkImageAspectFlagBits { + VK_IMAGE_ASPECT_COLOR_BIT = 0x00000001, + VK_IMAGE_ASPECT_DEPTH_BIT = 0x00000002, + VK_IMAGE_ASPECT_STENCIL_BIT = 0x00000004, + VK_IMAGE_ASPECT_METADATA_BIT = 0x00000008, + VK_IMAGE_ASPECT_PLANE_0_BIT = 0x00000010, + VK_IMAGE_ASPECT_PLANE_1_BIT = 0x00000020, + VK_IMAGE_ASPECT_PLANE_2_BIT = 0x00000040, + VK_IMAGE_ASPECT_NONE = 0, + VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT = 0x00000080, + VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT = 0x00000100, + VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT = 0x00000200, + VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT = 0x00000400, + VK_IMAGE_ASPECT_PLANE_0_BIT_KHR = VK_IMAGE_ASPECT_PLANE_0_BIT, + VK_IMAGE_ASPECT_PLANE_1_BIT_KHR = VK_IMAGE_ASPECT_PLANE_1_BIT, + VK_IMAGE_ASPECT_PLANE_2_BIT_KHR = VK_IMAGE_ASPECT_PLANE_2_BIT, + VK_IMAGE_ASPECT_NONE_KHR = VK_IMAGE_ASPECT_NONE, + VK_IMAGE_ASPECT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkImageAspectFlagBits; +typedef VkFlags VkImageAspectFlags; + +typedef enum VkFormatFeatureFlagBits { + VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT = 0x00000001, + VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT = 0x00000002, + VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT = 0x00000004, + VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT = 0x00000008, + VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT = 0x00000010, + VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT = 0x00000020, + VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT = 0x00000040, + VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT = 0x00000080, + VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT = 0x00000100, + VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000200, + VK_FORMAT_FEATURE_BLIT_SRC_BIT = 0x00000400, + VK_FORMAT_FEATURE_BLIT_DST_BIT = 0x00000800, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT = 0x00001000, + VK_FORMAT_FEATURE_TRANSFER_SRC_BIT = 0x00004000, + VK_FORMAT_FEATURE_TRANSFER_DST_BIT = 0x00008000, + VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT = 0x00020000, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT = 0x00040000, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT = 0x00080000, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT = 0x00100000, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT = 0x00200000, + VK_FORMAT_FEATURE_DISJOINT_BIT = 0x00400000, + VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT = 0x00800000, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT = 0x00010000, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG = 0x00002000, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_FORMAT_FEATURE_VIDEO_DECODE_OUTPUT_BIT_KHR = 0x02000000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_FORMAT_FEATURE_VIDEO_DECODE_DPB_BIT_KHR = 0x04000000, +#endif + VK_FORMAT_FEATURE_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR = 0x20000000, + VK_FORMAT_FEATURE_FRAGMENT_DENSITY_MAP_BIT_EXT = 0x01000000, + VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x40000000, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_FORMAT_FEATURE_VIDEO_ENCODE_INPUT_BIT_KHR = 0x08000000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_FORMAT_FEATURE_VIDEO_ENCODE_DPB_BIT_KHR = 0x10000000, +#endif + VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT, + VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR = VK_FORMAT_FEATURE_TRANSFER_DST_BIT, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT_EXT = VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT, + VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT_KHR = VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT_KHR = VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT_KHR = VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT_KHR = VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT_KHR = VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT, + VK_FORMAT_FEATURE_DISJOINT_BIT_KHR = VK_FORMAT_FEATURE_DISJOINT_BIT, + VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT_KHR = VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT = VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG, + VK_FORMAT_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkFormatFeatureFlagBits; +typedef VkFlags VkFormatFeatureFlags; + +typedef enum VkImageCreateFlagBits { + VK_IMAGE_CREATE_SPARSE_BINDING_BIT = 0x00000001, + VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT = 0x00000002, + VK_IMAGE_CREATE_SPARSE_ALIASED_BIT = 0x00000004, + VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT = 0x00000008, + VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT = 0x00000010, + VK_IMAGE_CREATE_ALIAS_BIT = 0x00000400, + VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT = 0x00000040, + VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT = 0x00000020, + VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT = 0x00000080, + VK_IMAGE_CREATE_EXTENDED_USAGE_BIT = 0x00000100, + VK_IMAGE_CREATE_PROTECTED_BIT = 0x00000800, + VK_IMAGE_CREATE_DISJOINT_BIT = 0x00000200, + VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV = 0x00002000, + VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT = 0x00001000, + VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT = 0x00004000, + VK_IMAGE_CREATE_2D_VIEW_COMPATIBLE_BIT_EXT = 0x00020000, + VK_IMAGE_CREATE_FRAGMENT_DENSITY_MAP_OFFSET_BIT_QCOM = 0x00008000, + VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR = VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT, + VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR = VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT, + VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT_KHR = VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT, + VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR = VK_IMAGE_CREATE_EXTENDED_USAGE_BIT, + VK_IMAGE_CREATE_DISJOINT_BIT_KHR = VK_IMAGE_CREATE_DISJOINT_BIT, + VK_IMAGE_CREATE_ALIAS_BIT_KHR = VK_IMAGE_CREATE_ALIAS_BIT, + VK_IMAGE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkImageCreateFlagBits; +typedef VkFlags VkImageCreateFlags; + +typedef enum VkSampleCountFlagBits { + VK_SAMPLE_COUNT_1_BIT = 0x00000001, + VK_SAMPLE_COUNT_2_BIT = 0x00000002, + VK_SAMPLE_COUNT_4_BIT = 0x00000004, + VK_SAMPLE_COUNT_8_BIT = 0x00000008, + VK_SAMPLE_COUNT_16_BIT = 0x00000010, + VK_SAMPLE_COUNT_32_BIT = 0x00000020, + VK_SAMPLE_COUNT_64_BIT = 0x00000040, + VK_SAMPLE_COUNT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkSampleCountFlagBits; +typedef VkFlags VkSampleCountFlags; + +typedef enum VkImageUsageFlagBits { + VK_IMAGE_USAGE_TRANSFER_SRC_BIT = 0x00000001, + VK_IMAGE_USAGE_TRANSFER_DST_BIT = 0x00000002, + VK_IMAGE_USAGE_SAMPLED_BIT = 0x00000004, + VK_IMAGE_USAGE_STORAGE_BIT = 0x00000008, + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT = 0x00000010, + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000020, + VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT = 0x00000040, + VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT = 0x00000080, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR = 0x00000400, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_USAGE_VIDEO_DECODE_SRC_BIT_KHR = 0x00000800, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR = 0x00001000, +#endif + VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT = 0x00000200, + VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x00000100, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_USAGE_VIDEO_ENCODE_DST_BIT_KHR = 0x00002000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR = 0x00004000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR = 0x00008000, +#endif + VK_IMAGE_USAGE_INVOCATION_MASK_BIT_HUAWEI = 0x00040000, + VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV = VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR, + VK_IMAGE_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkImageUsageFlagBits; +typedef VkFlags VkImageUsageFlags; + +typedef enum VkInstanceCreateFlagBits { + VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR = 0x00000001, + VK_INSTANCE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkInstanceCreateFlagBits; +typedef VkFlags VkInstanceCreateFlags; + +typedef enum VkMemoryHeapFlagBits { + VK_MEMORY_HEAP_DEVICE_LOCAL_BIT = 0x00000001, + VK_MEMORY_HEAP_MULTI_INSTANCE_BIT = 0x00000002, + VK_MEMORY_HEAP_MULTI_INSTANCE_BIT_KHR = VK_MEMORY_HEAP_MULTI_INSTANCE_BIT, + VK_MEMORY_HEAP_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkMemoryHeapFlagBits; +typedef VkFlags VkMemoryHeapFlags; + +typedef enum VkMemoryPropertyFlagBits { + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT = 0x00000001, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT = 0x00000002, + VK_MEMORY_PROPERTY_HOST_COHERENT_BIT = 0x00000004, + VK_MEMORY_PROPERTY_HOST_CACHED_BIT = 0x00000008, + VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT = 0x00000010, + VK_MEMORY_PROPERTY_PROTECTED_BIT = 0x00000020, + VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD = 0x00000040, + VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD = 0x00000080, + VK_MEMORY_PROPERTY_RDMA_CAPABLE_BIT_NV = 0x00000100, + VK_MEMORY_PROPERTY_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkMemoryPropertyFlagBits; +typedef VkFlags VkMemoryPropertyFlags; + +typedef enum VkQueueFlagBits { + VK_QUEUE_GRAPHICS_BIT = 0x00000001, + VK_QUEUE_COMPUTE_BIT = 0x00000002, + VK_QUEUE_TRANSFER_BIT = 0x00000004, + VK_QUEUE_SPARSE_BINDING_BIT = 0x00000008, + VK_QUEUE_PROTECTED_BIT = 0x00000010, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_QUEUE_VIDEO_DECODE_BIT_KHR = 0x00000020, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_QUEUE_VIDEO_ENCODE_BIT_KHR = 0x00000040, +#endif + VK_QUEUE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkQueueFlagBits; +typedef VkFlags VkQueueFlags; +typedef VkFlags VkDeviceCreateFlags; + +typedef enum VkDeviceQueueCreateFlagBits { + VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT = 0x00000001, + VK_DEVICE_QUEUE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkDeviceQueueCreateFlagBits; +typedef VkFlags VkDeviceQueueCreateFlags; + +typedef enum VkPipelineStageFlagBits { + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT = 0x00000001, + VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT = 0x00000002, + VK_PIPELINE_STAGE_VERTEX_INPUT_BIT = 0x00000004, + VK_PIPELINE_STAGE_VERTEX_SHADER_BIT = 0x00000008, + VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT = 0x00000010, + VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT = 0x00000020, + VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT = 0x00000040, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT = 0x00000080, + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT = 0x00000100, + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT = 0x00000200, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT = 0x00000400, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT = 0x00000800, + VK_PIPELINE_STAGE_TRANSFER_BIT = 0x00001000, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT = 0x00002000, + VK_PIPELINE_STAGE_HOST_BIT = 0x00004000, + VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT = 0x00008000, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT = 0x00010000, + VK_PIPELINE_STAGE_NONE = 0, + VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT = 0x01000000, + VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT = 0x00040000, + VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR = 0x02000000, + VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR = 0x00200000, + VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV = 0x00080000, + VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV = 0x00100000, + VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT = 0x00800000, + VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x00400000, + VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV = 0x00020000, + VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV = VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR, + VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_NV = VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, + VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV = VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, + VK_PIPELINE_STAGE_NONE_KHR = VK_PIPELINE_STAGE_NONE, + VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPipelineStageFlagBits; +typedef VkFlags VkPipelineStageFlags; +typedef VkFlags VkMemoryMapFlags; + +typedef enum VkSparseMemoryBindFlagBits { + VK_SPARSE_MEMORY_BIND_METADATA_BIT = 0x00000001, + VK_SPARSE_MEMORY_BIND_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkSparseMemoryBindFlagBits; +typedef VkFlags VkSparseMemoryBindFlags; + +typedef enum VkSparseImageFormatFlagBits { + VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT = 0x00000001, + VK_SPARSE_IMAGE_FORMAT_ALIGNED_MIP_SIZE_BIT = 0x00000002, + VK_SPARSE_IMAGE_FORMAT_NONSTANDARD_BLOCK_SIZE_BIT = 0x00000004, + VK_SPARSE_IMAGE_FORMAT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkSparseImageFormatFlagBits; +typedef VkFlags VkSparseImageFormatFlags; + +typedef enum VkFenceCreateFlagBits { + VK_FENCE_CREATE_SIGNALED_BIT = 0x00000001, + VK_FENCE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkFenceCreateFlagBits; +typedef VkFlags VkFenceCreateFlags; +typedef VkFlags VkSemaphoreCreateFlags; + +typedef enum VkEventCreateFlagBits { + VK_EVENT_CREATE_DEVICE_ONLY_BIT = 0x00000001, + VK_EVENT_CREATE_DEVICE_ONLY_BIT_KHR = VK_EVENT_CREATE_DEVICE_ONLY_BIT, + VK_EVENT_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkEventCreateFlagBits; +typedef VkFlags VkEventCreateFlags; + +typedef enum VkQueryPipelineStatisticFlagBits { + VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT = 0x00000001, + VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT = 0x00000002, + VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT = 0x00000004, + VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT = 0x00000008, + VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT = 0x00000010, + VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT = 0x00000020, + VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT = 0x00000040, + VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT = 0x00000080, + VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT = 0x00000100, + VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT = 0x00000200, + VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT = 0x00000400, + VK_QUERY_PIPELINE_STATISTIC_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkQueryPipelineStatisticFlagBits; +typedef VkFlags VkQueryPipelineStatisticFlags; +typedef VkFlags VkQueryPoolCreateFlags; + +typedef enum VkQueryResultFlagBits { + VK_QUERY_RESULT_64_BIT = 0x00000001, + VK_QUERY_RESULT_WAIT_BIT = 0x00000002, + VK_QUERY_RESULT_WITH_AVAILABILITY_BIT = 0x00000004, + VK_QUERY_RESULT_PARTIAL_BIT = 0x00000008, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_QUERY_RESULT_WITH_STATUS_BIT_KHR = 0x00000010, +#endif + VK_QUERY_RESULT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkQueryResultFlagBits; +typedef VkFlags VkQueryResultFlags; + +typedef enum VkBufferCreateFlagBits { + VK_BUFFER_CREATE_SPARSE_BINDING_BIT = 0x00000001, + VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT = 0x00000002, + VK_BUFFER_CREATE_SPARSE_ALIASED_BIT = 0x00000004, + VK_BUFFER_CREATE_PROTECTED_BIT = 0x00000008, + VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT = 0x00000010, + VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_EXT = VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT, + VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR = VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT, + VK_BUFFER_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkBufferCreateFlagBits; +typedef VkFlags VkBufferCreateFlags; + +typedef enum VkBufferUsageFlagBits { + VK_BUFFER_USAGE_TRANSFER_SRC_BIT = 0x00000001, + VK_BUFFER_USAGE_TRANSFER_DST_BIT = 0x00000002, + VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT = 0x00000004, + VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT = 0x00000008, + VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT = 0x00000010, + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT = 0x00000020, + VK_BUFFER_USAGE_INDEX_BUFFER_BIT = 0x00000040, + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT = 0x00000080, + VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT = 0x00000100, + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT = 0x00020000, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR = 0x00002000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_BUFFER_USAGE_VIDEO_DECODE_DST_BIT_KHR = 0x00004000, +#endif + VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT = 0x00000800, + VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT = 0x00001000, + VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT = 0x00000200, + VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR = 0x00080000, + VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR = 0x00100000, + VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR = 0x00000400, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_BUFFER_USAGE_VIDEO_ENCODE_DST_BIT_KHR = 0x00008000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_BUFFER_USAGE_VIDEO_ENCODE_SRC_BIT_KHR = 0x00010000, +#endif + VK_BUFFER_USAGE_RAY_TRACING_BIT_NV = VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR, + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_EXT = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, + VK_BUFFER_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkBufferUsageFlagBits; +typedef VkFlags VkBufferUsageFlags; +typedef VkFlags VkBufferViewCreateFlags; + +typedef enum VkImageViewCreateFlagBits { + VK_IMAGE_VIEW_CREATE_FRAGMENT_DENSITY_MAP_DYNAMIC_BIT_EXT = 0x00000001, + VK_IMAGE_VIEW_CREATE_FRAGMENT_DENSITY_MAP_DEFERRED_BIT_EXT = 0x00000002, + VK_IMAGE_VIEW_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkImageViewCreateFlagBits; +typedef VkFlags VkImageViewCreateFlags; +typedef VkFlags VkShaderModuleCreateFlags; + +typedef enum VkPipelineCacheCreateFlagBits { + VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT = 0x00000001, + VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT_EXT = VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT, + VK_PIPELINE_CACHE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPipelineCacheCreateFlagBits; +typedef VkFlags VkPipelineCacheCreateFlags; + +typedef enum VkColorComponentFlagBits { + VK_COLOR_COMPONENT_R_BIT = 0x00000001, + VK_COLOR_COMPONENT_G_BIT = 0x00000002, + VK_COLOR_COMPONENT_B_BIT = 0x00000004, + VK_COLOR_COMPONENT_A_BIT = 0x00000008, + VK_COLOR_COMPONENT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkColorComponentFlagBits; +typedef VkFlags VkColorComponentFlags; + +typedef enum VkPipelineCreateFlagBits { + VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT = 0x00000001, + VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT = 0x00000002, + VK_PIPELINE_CREATE_DERIVATIVE_BIT = 0x00000004, + VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT = 0x00000008, + VK_PIPELINE_CREATE_DISPATCH_BASE_BIT = 0x00000010, + VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT = 0x00000100, + VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT = 0x00000200, + VK_PIPELINE_CREATE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x00200000, + VK_PIPELINE_CREATE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT = 0x00400000, + VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR = 0x00004000, + VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR = 0x00008000, + VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_MISS_SHADERS_BIT_KHR = 0x00010000, + VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_INTERSECTION_SHADERS_BIT_KHR = 0x00020000, + VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR = 0x00001000, + VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR = 0x00002000, + VK_PIPELINE_CREATE_RAY_TRACING_SHADER_GROUP_HANDLE_CAPTURE_REPLAY_BIT_KHR = 0x00080000, + VK_PIPELINE_CREATE_DEFER_COMPILE_BIT_NV = 0x00000020, + VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR = 0x00000040, + VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR = 0x00000080, + VK_PIPELINE_CREATE_INDIRECT_BINDABLE_BIT_NV = 0x00040000, + VK_PIPELINE_CREATE_LIBRARY_BIT_KHR = 0x00000800, + VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT = 0x00800000, + VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT = 0x00000400, + VK_PIPELINE_CREATE_RAY_TRACING_ALLOW_MOTION_BIT_NV = 0x00100000, + VK_PIPELINE_CREATE_DISPATCH_BASE = VK_PIPELINE_CREATE_DISPATCH_BASE_BIT, + VK_PIPELINE_RASTERIZATION_STATE_CREATE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = VK_PIPELINE_CREATE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR, + VK_PIPELINE_RASTERIZATION_STATE_CREATE_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT = VK_PIPELINE_CREATE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT, + VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHR = VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT, + VK_PIPELINE_CREATE_DISPATCH_BASE_KHR = VK_PIPELINE_CREATE_DISPATCH_BASE, + VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_EXT = VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT, + VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT_EXT = VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT, + VK_PIPELINE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPipelineCreateFlagBits; +typedef VkFlags VkPipelineCreateFlags; + +typedef enum VkPipelineShaderStageCreateFlagBits { + VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT = 0x00000001, + VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT = 0x00000002, + VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT = VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT, + VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT = VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT, + VK_PIPELINE_SHADER_STAGE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPipelineShaderStageCreateFlagBits; +typedef VkFlags VkPipelineShaderStageCreateFlags; + +typedef enum VkShaderStageFlagBits { + VK_SHADER_STAGE_VERTEX_BIT = 0x00000001, + VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT = 0x00000002, + VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT = 0x00000004, + VK_SHADER_STAGE_GEOMETRY_BIT = 0x00000008, + VK_SHADER_STAGE_FRAGMENT_BIT = 0x00000010, + VK_SHADER_STAGE_COMPUTE_BIT = 0x00000020, + VK_SHADER_STAGE_ALL_GRAPHICS = 0x0000001F, + VK_SHADER_STAGE_ALL = 0x7FFFFFFF, + VK_SHADER_STAGE_RAYGEN_BIT_KHR = 0x00000100, + VK_SHADER_STAGE_ANY_HIT_BIT_KHR = 0x00000200, + VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR = 0x00000400, + VK_SHADER_STAGE_MISS_BIT_KHR = 0x00000800, + VK_SHADER_STAGE_INTERSECTION_BIT_KHR = 0x00001000, + VK_SHADER_STAGE_CALLABLE_BIT_KHR = 0x00002000, + VK_SHADER_STAGE_TASK_BIT_NV = 0x00000040, + VK_SHADER_STAGE_MESH_BIT_NV = 0x00000080, + VK_SHADER_STAGE_SUBPASS_SHADING_BIT_HUAWEI = 0x00004000, + VK_SHADER_STAGE_RAYGEN_BIT_NV = VK_SHADER_STAGE_RAYGEN_BIT_KHR, + VK_SHADER_STAGE_ANY_HIT_BIT_NV = VK_SHADER_STAGE_ANY_HIT_BIT_KHR, + VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, + VK_SHADER_STAGE_MISS_BIT_NV = VK_SHADER_STAGE_MISS_BIT_KHR, + VK_SHADER_STAGE_INTERSECTION_BIT_NV = VK_SHADER_STAGE_INTERSECTION_BIT_KHR, + VK_SHADER_STAGE_CALLABLE_BIT_NV = VK_SHADER_STAGE_CALLABLE_BIT_KHR, + VK_SHADER_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkShaderStageFlagBits; + +typedef enum VkCullModeFlagBits { + VK_CULL_MODE_NONE = 0, + VK_CULL_MODE_FRONT_BIT = 0x00000001, + VK_CULL_MODE_BACK_BIT = 0x00000002, + VK_CULL_MODE_FRONT_AND_BACK = 0x00000003, + VK_CULL_MODE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkCullModeFlagBits; +typedef VkFlags VkCullModeFlags; +typedef VkFlags VkPipelineVertexInputStateCreateFlags; +typedef VkFlags VkPipelineInputAssemblyStateCreateFlags; +typedef VkFlags VkPipelineTessellationStateCreateFlags; +typedef VkFlags VkPipelineViewportStateCreateFlags; +typedef VkFlags VkPipelineRasterizationStateCreateFlags; +typedef VkFlags VkPipelineMultisampleStateCreateFlags; + +typedef enum VkPipelineDepthStencilStateCreateFlagBits { + VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_ARM = 0x00000001, + VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_ARM = 0x00000002, + VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPipelineDepthStencilStateCreateFlagBits; +typedef VkFlags VkPipelineDepthStencilStateCreateFlags; + +typedef enum VkPipelineColorBlendStateCreateFlagBits { + VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_ARM = 0x00000001, + VK_PIPELINE_COLOR_BLEND_STATE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPipelineColorBlendStateCreateFlagBits; +typedef VkFlags VkPipelineColorBlendStateCreateFlags; +typedef VkFlags VkPipelineDynamicStateCreateFlags; + +typedef enum VkPipelineLayoutCreateFlagBits { + VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT = 0x00000002, + VK_PIPELINE_LAYOUT_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPipelineLayoutCreateFlagBits; +typedef VkFlags VkPipelineLayoutCreateFlags; +typedef VkFlags VkShaderStageFlags; + +typedef enum VkSamplerCreateFlagBits { + VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT = 0x00000001, + VK_SAMPLER_CREATE_SUBSAMPLED_COARSE_RECONSTRUCTION_BIT_EXT = 0x00000002, + VK_SAMPLER_CREATE_NON_SEAMLESS_CUBE_MAP_BIT_EXT = 0x00000004, + VK_SAMPLER_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkSamplerCreateFlagBits; +typedef VkFlags VkSamplerCreateFlags; + +typedef enum VkDescriptorPoolCreateFlagBits { + VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT = 0x00000001, + VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT = 0x00000002, + VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_VALVE = 0x00000004, + VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT, + VK_DESCRIPTOR_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkDescriptorPoolCreateFlagBits; +typedef VkFlags VkDescriptorPoolCreateFlags; +typedef VkFlags VkDescriptorPoolResetFlags; + +typedef enum VkDescriptorSetLayoutCreateFlagBits { + VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT = 0x00000002, + VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR = 0x00000001, + VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_VALVE = 0x00000004, + VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT, + VK_DESCRIPTOR_SET_LAYOUT_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkDescriptorSetLayoutCreateFlagBits; +typedef VkFlags VkDescriptorSetLayoutCreateFlags; + +typedef enum VkAttachmentDescriptionFlagBits { + VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT = 0x00000001, + VK_ATTACHMENT_DESCRIPTION_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkAttachmentDescriptionFlagBits; +typedef VkFlags VkAttachmentDescriptionFlags; + +typedef enum VkDependencyFlagBits { + VK_DEPENDENCY_BY_REGION_BIT = 0x00000001, + VK_DEPENDENCY_DEVICE_GROUP_BIT = 0x00000004, + VK_DEPENDENCY_VIEW_LOCAL_BIT = 0x00000002, + VK_DEPENDENCY_VIEW_LOCAL_BIT_KHR = VK_DEPENDENCY_VIEW_LOCAL_BIT, + VK_DEPENDENCY_DEVICE_GROUP_BIT_KHR = VK_DEPENDENCY_DEVICE_GROUP_BIT, + VK_DEPENDENCY_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkDependencyFlagBits; +typedef VkFlags VkDependencyFlags; + +typedef enum VkFramebufferCreateFlagBits { + VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT = 0x00000001, + VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT_KHR = VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT, + VK_FRAMEBUFFER_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkFramebufferCreateFlagBits; +typedef VkFlags VkFramebufferCreateFlags; + +typedef enum VkRenderPassCreateFlagBits { + VK_RENDER_PASS_CREATE_TRANSFORM_BIT_QCOM = 0x00000002, + VK_RENDER_PASS_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkRenderPassCreateFlagBits; +typedef VkFlags VkRenderPassCreateFlags; + +typedef enum VkSubpassDescriptionFlagBits { + VK_SUBPASS_DESCRIPTION_PER_VIEW_ATTRIBUTES_BIT_NVX = 0x00000001, + VK_SUBPASS_DESCRIPTION_PER_VIEW_POSITION_X_ONLY_BIT_NVX = 0x00000002, + VK_SUBPASS_DESCRIPTION_FRAGMENT_REGION_BIT_QCOM = 0x00000004, + VK_SUBPASS_DESCRIPTION_SHADER_RESOLVE_BIT_QCOM = 0x00000008, + VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_COLOR_ACCESS_BIT_ARM = 0x00000010, + VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_ARM = 0x00000020, + VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_ARM = 0x00000040, + VK_SUBPASS_DESCRIPTION_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkSubpassDescriptionFlagBits; +typedef VkFlags VkSubpassDescriptionFlags; + +typedef enum VkCommandPoolCreateFlagBits { + VK_COMMAND_POOL_CREATE_TRANSIENT_BIT = 0x00000001, + VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT = 0x00000002, + VK_COMMAND_POOL_CREATE_PROTECTED_BIT = 0x00000004, + VK_COMMAND_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkCommandPoolCreateFlagBits; +typedef VkFlags VkCommandPoolCreateFlags; + +typedef enum VkCommandPoolResetFlagBits { + VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT = 0x00000001, + VK_COMMAND_POOL_RESET_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkCommandPoolResetFlagBits; +typedef VkFlags VkCommandPoolResetFlags; + +typedef enum VkCommandBufferUsageFlagBits { + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT = 0x00000001, + VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT = 0x00000002, + VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT = 0x00000004, + VK_COMMAND_BUFFER_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkCommandBufferUsageFlagBits; +typedef VkFlags VkCommandBufferUsageFlags; + +typedef enum VkQueryControlFlagBits { + VK_QUERY_CONTROL_PRECISE_BIT = 0x00000001, + VK_QUERY_CONTROL_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkQueryControlFlagBits; +typedef VkFlags VkQueryControlFlags; + +typedef enum VkCommandBufferResetFlagBits { + VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT = 0x00000001, + VK_COMMAND_BUFFER_RESET_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkCommandBufferResetFlagBits; +typedef VkFlags VkCommandBufferResetFlags; + +typedef enum VkStencilFaceFlagBits { + VK_STENCIL_FACE_FRONT_BIT = 0x00000001, + VK_STENCIL_FACE_BACK_BIT = 0x00000002, + VK_STENCIL_FACE_FRONT_AND_BACK = 0x00000003, + VK_STENCIL_FRONT_AND_BACK = VK_STENCIL_FACE_FRONT_AND_BACK, + VK_STENCIL_FACE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkStencilFaceFlagBits; +typedef VkFlags VkStencilFaceFlags; +typedef struct VkExtent2D { + uint32_t width; + uint32_t height; +} VkExtent2D; + +typedef struct VkExtent3D { + uint32_t width; + uint32_t height; + uint32_t depth; +} VkExtent3D; + +typedef struct VkOffset2D { + int32_t x; + int32_t y; +} VkOffset2D; + +typedef struct VkOffset3D { + int32_t x; + int32_t y; + int32_t z; +} VkOffset3D; + +typedef struct VkRect2D { + VkOffset2D offset; + VkExtent2D extent; +} VkRect2D; + +typedef struct VkBaseInStructure { + VkStructureType sType; + const struct VkBaseInStructure* pNext; +} VkBaseInStructure; + +typedef struct VkBaseOutStructure { + VkStructureType sType; + struct VkBaseOutStructure* pNext; +} VkBaseOutStructure; + +typedef struct VkBufferMemoryBarrier { + VkStructureType sType; + const void* pNext; + VkAccessFlags srcAccessMask; + VkAccessFlags dstAccessMask; + uint32_t srcQueueFamilyIndex; + uint32_t dstQueueFamilyIndex; + VkBuffer buffer; + VkDeviceSize offset; + VkDeviceSize size; +} VkBufferMemoryBarrier; + +typedef struct VkDispatchIndirectCommand { + uint32_t x; + uint32_t y; + uint32_t z; +} VkDispatchIndirectCommand; + +typedef struct VkDrawIndexedIndirectCommand { + uint32_t indexCount; + uint32_t instanceCount; + uint32_t firstIndex; + int32_t vertexOffset; + uint32_t firstInstance; +} VkDrawIndexedIndirectCommand; + +typedef struct VkDrawIndirectCommand { + uint32_t vertexCount; + uint32_t instanceCount; + uint32_t firstVertex; + uint32_t firstInstance; +} VkDrawIndirectCommand; + +typedef struct VkImageSubresourceRange { + VkImageAspectFlags aspectMask; + uint32_t baseMipLevel; + uint32_t levelCount; + uint32_t baseArrayLayer; + uint32_t layerCount; +} VkImageSubresourceRange; + +typedef struct VkImageMemoryBarrier { + VkStructureType sType; + const void* pNext; + VkAccessFlags srcAccessMask; + VkAccessFlags dstAccessMask; + VkImageLayout oldLayout; + VkImageLayout newLayout; + uint32_t srcQueueFamilyIndex; + uint32_t dstQueueFamilyIndex; + VkImage image; + VkImageSubresourceRange subresourceRange; +} VkImageMemoryBarrier; + +typedef struct VkMemoryBarrier { + VkStructureType sType; + const void* pNext; + VkAccessFlags srcAccessMask; + VkAccessFlags dstAccessMask; +} VkMemoryBarrier; + +typedef struct VkPipelineCacheHeaderVersionOne { + uint32_t headerSize; + VkPipelineCacheHeaderVersion headerVersion; + uint32_t vendorID; + uint32_t deviceID; + uint8_t pipelineCacheUUID[VK_UUID_SIZE]; +} VkPipelineCacheHeaderVersionOne; + +typedef void* (VKAPI_PTR *PFN_vkAllocationFunction)( + void* pUserData, + size_t size, + size_t alignment, + VkSystemAllocationScope allocationScope); + +typedef void (VKAPI_PTR *PFN_vkFreeFunction)( + void* pUserData, + void* pMemory); + +typedef void (VKAPI_PTR *PFN_vkInternalAllocationNotification)( + void* pUserData, + size_t size, + VkInternalAllocationType allocationType, + VkSystemAllocationScope allocationScope); + +typedef void (VKAPI_PTR *PFN_vkInternalFreeNotification)( + void* pUserData, + size_t size, + VkInternalAllocationType allocationType, + VkSystemAllocationScope allocationScope); + +typedef void* (VKAPI_PTR *PFN_vkReallocationFunction)( + void* pUserData, + void* pOriginal, + size_t size, + size_t alignment, + VkSystemAllocationScope allocationScope); + +typedef void (VKAPI_PTR *PFN_vkVoidFunction)(void); +typedef struct VkAllocationCallbacks { + void* pUserData; + PFN_vkAllocationFunction pfnAllocation; + PFN_vkReallocationFunction pfnReallocation; + PFN_vkFreeFunction pfnFree; + PFN_vkInternalAllocationNotification pfnInternalAllocation; + PFN_vkInternalFreeNotification pfnInternalFree; +} VkAllocationCallbacks; + +typedef struct VkApplicationInfo { + VkStructureType sType; + const void* pNext; + const char* pApplicationName; + uint32_t applicationVersion; + const char* pEngineName; + uint32_t engineVersion; + uint32_t apiVersion; +} VkApplicationInfo; + +typedef struct VkFormatProperties { + VkFormatFeatureFlags linearTilingFeatures; + VkFormatFeatureFlags optimalTilingFeatures; + VkFormatFeatureFlags bufferFeatures; +} VkFormatProperties; + +typedef struct VkImageFormatProperties { + VkExtent3D maxExtent; + uint32_t maxMipLevels; + uint32_t maxArrayLayers; + VkSampleCountFlags sampleCounts; + VkDeviceSize maxResourceSize; +} VkImageFormatProperties; + +typedef struct VkInstanceCreateInfo { + VkStructureType sType; + const void* pNext; + VkInstanceCreateFlags flags; + const VkApplicationInfo* pApplicationInfo; + uint32_t enabledLayerCount; + const char* const* ppEnabledLayerNames; + uint32_t enabledExtensionCount; + const char* const* ppEnabledExtensionNames; +} VkInstanceCreateInfo; + +typedef struct VkMemoryHeap { + VkDeviceSize size; + VkMemoryHeapFlags flags; +} VkMemoryHeap; + +typedef struct VkMemoryType { + VkMemoryPropertyFlags propertyFlags; + uint32_t heapIndex; +} VkMemoryType; + +typedef struct VkPhysicalDeviceFeatures { + VkBool32 robustBufferAccess; + VkBool32 fullDrawIndexUint32; + VkBool32 imageCubeArray; + VkBool32 independentBlend; + VkBool32 geometryShader; + VkBool32 tessellationShader; + VkBool32 sampleRateShading; + VkBool32 dualSrcBlend; + VkBool32 logicOp; + VkBool32 multiDrawIndirect; + VkBool32 drawIndirectFirstInstance; + VkBool32 depthClamp; + VkBool32 depthBiasClamp; + VkBool32 fillModeNonSolid; + VkBool32 depthBounds; + VkBool32 wideLines; + VkBool32 largePoints; + VkBool32 alphaToOne; + VkBool32 multiViewport; + VkBool32 samplerAnisotropy; + VkBool32 textureCompressionETC2; + VkBool32 textureCompressionASTC_LDR; + VkBool32 textureCompressionBC; + VkBool32 occlusionQueryPrecise; + VkBool32 pipelineStatisticsQuery; + VkBool32 vertexPipelineStoresAndAtomics; + VkBool32 fragmentStoresAndAtomics; + VkBool32 shaderTessellationAndGeometryPointSize; + VkBool32 shaderImageGatherExtended; + VkBool32 shaderStorageImageExtendedFormats; + VkBool32 shaderStorageImageMultisample; + VkBool32 shaderStorageImageReadWithoutFormat; + VkBool32 shaderStorageImageWriteWithoutFormat; + VkBool32 shaderUniformBufferArrayDynamicIndexing; + VkBool32 shaderSampledImageArrayDynamicIndexing; + VkBool32 shaderStorageBufferArrayDynamicIndexing; + VkBool32 shaderStorageImageArrayDynamicIndexing; + VkBool32 shaderClipDistance; + VkBool32 shaderCullDistance; + VkBool32 shaderFloat64; + VkBool32 shaderInt64; + VkBool32 shaderInt16; + VkBool32 shaderResourceResidency; + VkBool32 shaderResourceMinLod; + VkBool32 sparseBinding; + VkBool32 sparseResidencyBuffer; + VkBool32 sparseResidencyImage2D; + VkBool32 sparseResidencyImage3D; + VkBool32 sparseResidency2Samples; + VkBool32 sparseResidency4Samples; + VkBool32 sparseResidency8Samples; + VkBool32 sparseResidency16Samples; + VkBool32 sparseResidencyAliased; + VkBool32 variableMultisampleRate; + VkBool32 inheritedQueries; +} VkPhysicalDeviceFeatures; + +typedef struct VkPhysicalDeviceLimits { + uint32_t maxImageDimension1D; + uint32_t maxImageDimension2D; + uint32_t maxImageDimension3D; + uint32_t maxImageDimensionCube; + uint32_t maxImageArrayLayers; + uint32_t maxTexelBufferElements; + uint32_t maxUniformBufferRange; + uint32_t maxStorageBufferRange; + uint32_t maxPushConstantsSize; + uint32_t maxMemoryAllocationCount; + uint32_t maxSamplerAllocationCount; + VkDeviceSize bufferImageGranularity; + VkDeviceSize sparseAddressSpaceSize; + uint32_t maxBoundDescriptorSets; + uint32_t maxPerStageDescriptorSamplers; + uint32_t maxPerStageDescriptorUniformBuffers; + uint32_t maxPerStageDescriptorStorageBuffers; + uint32_t maxPerStageDescriptorSampledImages; + uint32_t maxPerStageDescriptorStorageImages; + uint32_t maxPerStageDescriptorInputAttachments; + uint32_t maxPerStageResources; + uint32_t maxDescriptorSetSamplers; + uint32_t maxDescriptorSetUniformBuffers; + uint32_t maxDescriptorSetUniformBuffersDynamic; + uint32_t maxDescriptorSetStorageBuffers; + uint32_t maxDescriptorSetStorageBuffersDynamic; + uint32_t maxDescriptorSetSampledImages; + uint32_t maxDescriptorSetStorageImages; + uint32_t maxDescriptorSetInputAttachments; + uint32_t maxVertexInputAttributes; + uint32_t maxVertexInputBindings; + uint32_t maxVertexInputAttributeOffset; + uint32_t maxVertexInputBindingStride; + uint32_t maxVertexOutputComponents; + uint32_t maxTessellationGenerationLevel; + uint32_t maxTessellationPatchSize; + uint32_t maxTessellationControlPerVertexInputComponents; + uint32_t maxTessellationControlPerVertexOutputComponents; + uint32_t maxTessellationControlPerPatchOutputComponents; + uint32_t maxTessellationControlTotalOutputComponents; + uint32_t maxTessellationEvaluationInputComponents; + uint32_t maxTessellationEvaluationOutputComponents; + uint32_t maxGeometryShaderInvocations; + uint32_t maxGeometryInputComponents; + uint32_t maxGeometryOutputComponents; + uint32_t maxGeometryOutputVertices; + uint32_t maxGeometryTotalOutputComponents; + uint32_t maxFragmentInputComponents; + uint32_t maxFragmentOutputAttachments; + uint32_t maxFragmentDualSrcAttachments; + uint32_t maxFragmentCombinedOutputResources; + uint32_t maxComputeSharedMemorySize; + uint32_t maxComputeWorkGroupCount[3]; + uint32_t maxComputeWorkGroupInvocations; + uint32_t maxComputeWorkGroupSize[3]; + uint32_t subPixelPrecisionBits; + uint32_t subTexelPrecisionBits; + uint32_t mipmapPrecisionBits; + uint32_t maxDrawIndexedIndexValue; + uint32_t maxDrawIndirectCount; + float maxSamplerLodBias; + float maxSamplerAnisotropy; + uint32_t maxViewports; + uint32_t maxViewportDimensions[2]; + float viewportBoundsRange[2]; + uint32_t viewportSubPixelBits; + size_t minMemoryMapAlignment; + VkDeviceSize minTexelBufferOffsetAlignment; + VkDeviceSize minUniformBufferOffsetAlignment; + VkDeviceSize minStorageBufferOffsetAlignment; + int32_t minTexelOffset; + uint32_t maxTexelOffset; + int32_t minTexelGatherOffset; + uint32_t maxTexelGatherOffset; + float minInterpolationOffset; + float maxInterpolationOffset; + uint32_t subPixelInterpolationOffsetBits; + uint32_t maxFramebufferWidth; + uint32_t maxFramebufferHeight; + uint32_t maxFramebufferLayers; + VkSampleCountFlags framebufferColorSampleCounts; + VkSampleCountFlags framebufferDepthSampleCounts; + VkSampleCountFlags framebufferStencilSampleCounts; + VkSampleCountFlags framebufferNoAttachmentsSampleCounts; + uint32_t maxColorAttachments; + VkSampleCountFlags sampledImageColorSampleCounts; + VkSampleCountFlags sampledImageIntegerSampleCounts; + VkSampleCountFlags sampledImageDepthSampleCounts; + VkSampleCountFlags sampledImageStencilSampleCounts; + VkSampleCountFlags storageImageSampleCounts; + uint32_t maxSampleMaskWords; + VkBool32 timestampComputeAndGraphics; + float timestampPeriod; + uint32_t maxClipDistances; + uint32_t maxCullDistances; + uint32_t maxCombinedClipAndCullDistances; + uint32_t discreteQueuePriorities; + float pointSizeRange[2]; + float lineWidthRange[2]; + float pointSizeGranularity; + float lineWidthGranularity; + VkBool32 strictLines; + VkBool32 standardSampleLocations; + VkDeviceSize optimalBufferCopyOffsetAlignment; + VkDeviceSize optimalBufferCopyRowPitchAlignment; + VkDeviceSize nonCoherentAtomSize; +} VkPhysicalDeviceLimits; + +typedef struct VkPhysicalDeviceMemoryProperties { + uint32_t memoryTypeCount; + VkMemoryType memoryTypes[VK_MAX_MEMORY_TYPES]; + uint32_t memoryHeapCount; + VkMemoryHeap memoryHeaps[VK_MAX_MEMORY_HEAPS]; +} VkPhysicalDeviceMemoryProperties; + +typedef struct VkPhysicalDeviceSparseProperties { + VkBool32 residencyStandard2DBlockShape; + VkBool32 residencyStandard2DMultisampleBlockShape; + VkBool32 residencyStandard3DBlockShape; + VkBool32 residencyAlignedMipSize; + VkBool32 residencyNonResidentStrict; +} VkPhysicalDeviceSparseProperties; + +typedef struct VkPhysicalDeviceProperties { + uint32_t apiVersion; + uint32_t driverVersion; + uint32_t vendorID; + uint32_t deviceID; + VkPhysicalDeviceType deviceType; + char deviceName[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE]; + uint8_t pipelineCacheUUID[VK_UUID_SIZE]; + VkPhysicalDeviceLimits limits; + VkPhysicalDeviceSparseProperties sparseProperties; +} VkPhysicalDeviceProperties; + +typedef struct VkQueueFamilyProperties { + VkQueueFlags queueFlags; + uint32_t queueCount; + uint32_t timestampValidBits; + VkExtent3D minImageTransferGranularity; +} VkQueueFamilyProperties; + +typedef struct VkDeviceQueueCreateInfo { + VkStructureType sType; + const void* pNext; + VkDeviceQueueCreateFlags flags; + uint32_t queueFamilyIndex; + uint32_t queueCount; + const float* pQueuePriorities; +} VkDeviceQueueCreateInfo; + +typedef struct VkDeviceCreateInfo { + VkStructureType sType; + const void* pNext; + VkDeviceCreateFlags flags; + uint32_t queueCreateInfoCount; + const VkDeviceQueueCreateInfo* pQueueCreateInfos; + uint32_t enabledLayerCount; + const char* const* ppEnabledLayerNames; + uint32_t enabledExtensionCount; + const char* const* ppEnabledExtensionNames; + const VkPhysicalDeviceFeatures* pEnabledFeatures; +} VkDeviceCreateInfo; + +typedef struct VkExtensionProperties { + char extensionName[VK_MAX_EXTENSION_NAME_SIZE]; + uint32_t specVersion; +} VkExtensionProperties; + +typedef struct VkLayerProperties { + char layerName[VK_MAX_EXTENSION_NAME_SIZE]; + uint32_t specVersion; + uint32_t implementationVersion; + char description[VK_MAX_DESCRIPTION_SIZE]; +} VkLayerProperties; + +typedef struct VkSubmitInfo { + VkStructureType sType; + const void* pNext; + uint32_t waitSemaphoreCount; + const VkSemaphore* pWaitSemaphores; + const VkPipelineStageFlags* pWaitDstStageMask; + uint32_t commandBufferCount; + const VkCommandBuffer* pCommandBuffers; + uint32_t signalSemaphoreCount; + const VkSemaphore* pSignalSemaphores; +} VkSubmitInfo; + +typedef struct VkMappedMemoryRange { + VkStructureType sType; + const void* pNext; + VkDeviceMemory memory; + VkDeviceSize offset; + VkDeviceSize size; +} VkMappedMemoryRange; + +typedef struct VkMemoryAllocateInfo { + VkStructureType sType; + const void* pNext; + VkDeviceSize allocationSize; + uint32_t memoryTypeIndex; +} VkMemoryAllocateInfo; + +typedef struct VkMemoryRequirements { + VkDeviceSize size; + VkDeviceSize alignment; + uint32_t memoryTypeBits; +} VkMemoryRequirements; + +typedef struct VkSparseMemoryBind { + VkDeviceSize resourceOffset; + VkDeviceSize size; + VkDeviceMemory memory; + VkDeviceSize memoryOffset; + VkSparseMemoryBindFlags flags; +} VkSparseMemoryBind; + +typedef struct VkSparseBufferMemoryBindInfo { + VkBuffer buffer; + uint32_t bindCount; + const VkSparseMemoryBind* pBinds; +} VkSparseBufferMemoryBindInfo; + +typedef struct VkSparseImageOpaqueMemoryBindInfo { + VkImage image; + uint32_t bindCount; + const VkSparseMemoryBind* pBinds; +} VkSparseImageOpaqueMemoryBindInfo; + +typedef struct VkImageSubresource { + VkImageAspectFlags aspectMask; + uint32_t mipLevel; + uint32_t arrayLayer; +} VkImageSubresource; + +typedef struct VkSparseImageMemoryBind { + VkImageSubresource subresource; + VkOffset3D offset; + VkExtent3D extent; + VkDeviceMemory memory; + VkDeviceSize memoryOffset; + VkSparseMemoryBindFlags flags; +} VkSparseImageMemoryBind; + +typedef struct VkSparseImageMemoryBindInfo { + VkImage image; + uint32_t bindCount; + const VkSparseImageMemoryBind* pBinds; +} VkSparseImageMemoryBindInfo; + +typedef struct VkBindSparseInfo { + VkStructureType sType; + const void* pNext; + uint32_t waitSemaphoreCount; + const VkSemaphore* pWaitSemaphores; + uint32_t bufferBindCount; + const VkSparseBufferMemoryBindInfo* pBufferBinds; + uint32_t imageOpaqueBindCount; + const VkSparseImageOpaqueMemoryBindInfo* pImageOpaqueBinds; + uint32_t imageBindCount; + const VkSparseImageMemoryBindInfo* pImageBinds; + uint32_t signalSemaphoreCount; + const VkSemaphore* pSignalSemaphores; +} VkBindSparseInfo; + +typedef struct VkSparseImageFormatProperties { + VkImageAspectFlags aspectMask; + VkExtent3D imageGranularity; + VkSparseImageFormatFlags flags; +} VkSparseImageFormatProperties; + +typedef struct VkSparseImageMemoryRequirements { + VkSparseImageFormatProperties formatProperties; + uint32_t imageMipTailFirstLod; + VkDeviceSize imageMipTailSize; + VkDeviceSize imageMipTailOffset; + VkDeviceSize imageMipTailStride; +} VkSparseImageMemoryRequirements; + +typedef struct VkFenceCreateInfo { + VkStructureType sType; + const void* pNext; + VkFenceCreateFlags flags; +} VkFenceCreateInfo; + +typedef struct VkSemaphoreCreateInfo { + VkStructureType sType; + const void* pNext; + VkSemaphoreCreateFlags flags; +} VkSemaphoreCreateInfo; + +typedef struct VkEventCreateInfo { + VkStructureType sType; + const void* pNext; + VkEventCreateFlags flags; +} VkEventCreateInfo; + +typedef struct VkQueryPoolCreateInfo { + VkStructureType sType; + const void* pNext; + VkQueryPoolCreateFlags flags; + VkQueryType queryType; + uint32_t queryCount; + VkQueryPipelineStatisticFlags pipelineStatistics; +} VkQueryPoolCreateInfo; + +typedef struct VkBufferCreateInfo { + VkStructureType sType; + const void* pNext; + VkBufferCreateFlags flags; + VkDeviceSize size; + VkBufferUsageFlags usage; + VkSharingMode sharingMode; + uint32_t queueFamilyIndexCount; + const uint32_t* pQueueFamilyIndices; +} VkBufferCreateInfo; + +typedef struct VkBufferViewCreateInfo { + VkStructureType sType; + const void* pNext; + VkBufferViewCreateFlags flags; + VkBuffer buffer; + VkFormat format; + VkDeviceSize offset; + VkDeviceSize range; +} VkBufferViewCreateInfo; + +typedef struct VkImageCreateInfo { + VkStructureType sType; + const void* pNext; + VkImageCreateFlags flags; + VkImageType imageType; + VkFormat format; + VkExtent3D extent; + uint32_t mipLevels; + uint32_t arrayLayers; + VkSampleCountFlagBits samples; + VkImageTiling tiling; + VkImageUsageFlags usage; + VkSharingMode sharingMode; + uint32_t queueFamilyIndexCount; + const uint32_t* pQueueFamilyIndices; + VkImageLayout initialLayout; +} VkImageCreateInfo; + +typedef struct VkSubresourceLayout { + VkDeviceSize offset; + VkDeviceSize size; + VkDeviceSize rowPitch; + VkDeviceSize arrayPitch; + VkDeviceSize depthPitch; +} VkSubresourceLayout; + +typedef struct VkComponentMapping { + VkComponentSwizzle r; + VkComponentSwizzle g; + VkComponentSwizzle b; + VkComponentSwizzle a; +} VkComponentMapping; + +typedef struct VkImageViewCreateInfo { + VkStructureType sType; + const void* pNext; + VkImageViewCreateFlags flags; + VkImage image; + VkImageViewType viewType; + VkFormat format; + VkComponentMapping components; + VkImageSubresourceRange subresourceRange; +} VkImageViewCreateInfo; + +typedef struct VkShaderModuleCreateInfo { + VkStructureType sType; + const void* pNext; + VkShaderModuleCreateFlags flags; + size_t codeSize; + const uint32_t* pCode; +} VkShaderModuleCreateInfo; + +typedef struct VkPipelineCacheCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineCacheCreateFlags flags; + size_t initialDataSize; + const void* pInitialData; +} VkPipelineCacheCreateInfo; + +typedef struct VkSpecializationMapEntry { + uint32_t constantID; + uint32_t offset; + size_t size; +} VkSpecializationMapEntry; + +typedef struct VkSpecializationInfo { + uint32_t mapEntryCount; + const VkSpecializationMapEntry* pMapEntries; + size_t dataSize; + const void* pData; +} VkSpecializationInfo; + +typedef struct VkPipelineShaderStageCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineShaderStageCreateFlags flags; + VkShaderStageFlagBits stage; + VkShaderModule module; + const char* pName; + const VkSpecializationInfo* pSpecializationInfo; +} VkPipelineShaderStageCreateInfo; + +typedef struct VkComputePipelineCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineCreateFlags flags; + VkPipelineShaderStageCreateInfo stage; + VkPipelineLayout layout; + VkPipeline basePipelineHandle; + int32_t basePipelineIndex; +} VkComputePipelineCreateInfo; + +typedef struct VkVertexInputBindingDescription { + uint32_t binding; + uint32_t stride; + VkVertexInputRate inputRate; +} VkVertexInputBindingDescription; + +typedef struct VkVertexInputAttributeDescription { + uint32_t location; + uint32_t binding; + VkFormat format; + uint32_t offset; +} VkVertexInputAttributeDescription; + +typedef struct VkPipelineVertexInputStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineVertexInputStateCreateFlags flags; + uint32_t vertexBindingDescriptionCount; + const VkVertexInputBindingDescription* pVertexBindingDescriptions; + uint32_t vertexAttributeDescriptionCount; + const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; +} VkPipelineVertexInputStateCreateInfo; + +typedef struct VkPipelineInputAssemblyStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineInputAssemblyStateCreateFlags flags; + VkPrimitiveTopology topology; + VkBool32 primitiveRestartEnable; +} VkPipelineInputAssemblyStateCreateInfo; + +typedef struct VkPipelineTessellationStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineTessellationStateCreateFlags flags; + uint32_t patchControlPoints; +} VkPipelineTessellationStateCreateInfo; + +typedef struct VkViewport { + float x; + float y; + float width; + float height; + float minDepth; + float maxDepth; +} VkViewport; + +typedef struct VkPipelineViewportStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineViewportStateCreateFlags flags; + uint32_t viewportCount; + const VkViewport* pViewports; + uint32_t scissorCount; + const VkRect2D* pScissors; +} VkPipelineViewportStateCreateInfo; + +typedef struct VkPipelineRasterizationStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineRasterizationStateCreateFlags flags; + VkBool32 depthClampEnable; + VkBool32 rasterizerDiscardEnable; + VkPolygonMode polygonMode; + VkCullModeFlags cullMode; + VkFrontFace frontFace; + VkBool32 depthBiasEnable; + float depthBiasConstantFactor; + float depthBiasClamp; + float depthBiasSlopeFactor; + float lineWidth; +} VkPipelineRasterizationStateCreateInfo; + +typedef struct VkPipelineMultisampleStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineMultisampleStateCreateFlags flags; + VkSampleCountFlagBits rasterizationSamples; + VkBool32 sampleShadingEnable; + float minSampleShading; + const VkSampleMask* pSampleMask; + VkBool32 alphaToCoverageEnable; + VkBool32 alphaToOneEnable; +} VkPipelineMultisampleStateCreateInfo; + +typedef struct VkStencilOpState { + VkStencilOp failOp; + VkStencilOp passOp; + VkStencilOp depthFailOp; + VkCompareOp compareOp; + uint32_t compareMask; + uint32_t writeMask; + uint32_t reference; +} VkStencilOpState; + +typedef struct VkPipelineDepthStencilStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineDepthStencilStateCreateFlags flags; + VkBool32 depthTestEnable; + VkBool32 depthWriteEnable; + VkCompareOp depthCompareOp; + VkBool32 depthBoundsTestEnable; + VkBool32 stencilTestEnable; + VkStencilOpState front; + VkStencilOpState back; + float minDepthBounds; + float maxDepthBounds; +} VkPipelineDepthStencilStateCreateInfo; + +typedef struct VkPipelineColorBlendAttachmentState { + VkBool32 blendEnable; + VkBlendFactor srcColorBlendFactor; + VkBlendFactor dstColorBlendFactor; + VkBlendOp colorBlendOp; + VkBlendFactor srcAlphaBlendFactor; + VkBlendFactor dstAlphaBlendFactor; + VkBlendOp alphaBlendOp; + VkColorComponentFlags colorWriteMask; +} VkPipelineColorBlendAttachmentState; + +typedef struct VkPipelineColorBlendStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineColorBlendStateCreateFlags flags; + VkBool32 logicOpEnable; + VkLogicOp logicOp; + uint32_t attachmentCount; + const VkPipelineColorBlendAttachmentState* pAttachments; + float blendConstants[4]; +} VkPipelineColorBlendStateCreateInfo; + +typedef struct VkPipelineDynamicStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineDynamicStateCreateFlags flags; + uint32_t dynamicStateCount; + const VkDynamicState* pDynamicStates; +} VkPipelineDynamicStateCreateInfo; + +typedef struct VkGraphicsPipelineCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineCreateFlags flags; + uint32_t stageCount; + const VkPipelineShaderStageCreateInfo* pStages; + const VkPipelineVertexInputStateCreateInfo* pVertexInputState; + const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; + const VkPipelineTessellationStateCreateInfo* pTessellationState; + const VkPipelineViewportStateCreateInfo* pViewportState; + const VkPipelineRasterizationStateCreateInfo* pRasterizationState; + const VkPipelineMultisampleStateCreateInfo* pMultisampleState; + const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; + const VkPipelineColorBlendStateCreateInfo* pColorBlendState; + const VkPipelineDynamicStateCreateInfo* pDynamicState; + VkPipelineLayout layout; + VkRenderPass renderPass; + uint32_t subpass; + VkPipeline basePipelineHandle; + int32_t basePipelineIndex; +} VkGraphicsPipelineCreateInfo; + +typedef struct VkPushConstantRange { + VkShaderStageFlags stageFlags; + uint32_t offset; + uint32_t size; +} VkPushConstantRange; + +typedef struct VkPipelineLayoutCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineLayoutCreateFlags flags; + uint32_t setLayoutCount; + const VkDescriptorSetLayout* pSetLayouts; + uint32_t pushConstantRangeCount; + const VkPushConstantRange* pPushConstantRanges; +} VkPipelineLayoutCreateInfo; + +typedef struct VkSamplerCreateInfo { + VkStructureType sType; + const void* pNext; + VkSamplerCreateFlags flags; + VkFilter magFilter; + VkFilter minFilter; + VkSamplerMipmapMode mipmapMode; + VkSamplerAddressMode addressModeU; + VkSamplerAddressMode addressModeV; + VkSamplerAddressMode addressModeW; + float mipLodBias; + VkBool32 anisotropyEnable; + float maxAnisotropy; + VkBool32 compareEnable; + VkCompareOp compareOp; + float minLod; + float maxLod; + VkBorderColor borderColor; + VkBool32 unnormalizedCoordinates; +} VkSamplerCreateInfo; + +typedef struct VkCopyDescriptorSet { + VkStructureType sType; + const void* pNext; + VkDescriptorSet srcSet; + uint32_t srcBinding; + uint32_t srcArrayElement; + VkDescriptorSet dstSet; + uint32_t dstBinding; + uint32_t dstArrayElement; + uint32_t descriptorCount; +} VkCopyDescriptorSet; + +typedef struct VkDescriptorBufferInfo { + VkBuffer buffer; + VkDeviceSize offset; + VkDeviceSize range; +} VkDescriptorBufferInfo; + +typedef struct VkDescriptorImageInfo { + VkSampler sampler; + VkImageView imageView; + VkImageLayout imageLayout; +} VkDescriptorImageInfo; + +typedef struct VkDescriptorPoolSize { + VkDescriptorType type; + uint32_t descriptorCount; +} VkDescriptorPoolSize; + +typedef struct VkDescriptorPoolCreateInfo { + VkStructureType sType; + const void* pNext; + VkDescriptorPoolCreateFlags flags; + uint32_t maxSets; + uint32_t poolSizeCount; + const VkDescriptorPoolSize* pPoolSizes; +} VkDescriptorPoolCreateInfo; + +typedef struct VkDescriptorSetAllocateInfo { + VkStructureType sType; + const void* pNext; + VkDescriptorPool descriptorPool; + uint32_t descriptorSetCount; + const VkDescriptorSetLayout* pSetLayouts; +} VkDescriptorSetAllocateInfo; + +typedef struct VkDescriptorSetLayoutBinding { + uint32_t binding; + VkDescriptorType descriptorType; + uint32_t descriptorCount; + VkShaderStageFlags stageFlags; + const VkSampler* pImmutableSamplers; +} VkDescriptorSetLayoutBinding; + +typedef struct VkDescriptorSetLayoutCreateInfo { + VkStructureType sType; + const void* pNext; + VkDescriptorSetLayoutCreateFlags flags; + uint32_t bindingCount; + const VkDescriptorSetLayoutBinding* pBindings; +} VkDescriptorSetLayoutCreateInfo; + +typedef struct VkWriteDescriptorSet { + VkStructureType sType; + const void* pNext; + VkDescriptorSet dstSet; + uint32_t dstBinding; + uint32_t dstArrayElement; + uint32_t descriptorCount; + VkDescriptorType descriptorType; + const VkDescriptorImageInfo* pImageInfo; + const VkDescriptorBufferInfo* pBufferInfo; + const VkBufferView* pTexelBufferView; +} VkWriteDescriptorSet; + +typedef struct VkAttachmentDescription { + VkAttachmentDescriptionFlags flags; + VkFormat format; + VkSampleCountFlagBits samples; + VkAttachmentLoadOp loadOp; + VkAttachmentStoreOp storeOp; + VkAttachmentLoadOp stencilLoadOp; + VkAttachmentStoreOp stencilStoreOp; + VkImageLayout initialLayout; + VkImageLayout finalLayout; +} VkAttachmentDescription; + +typedef struct VkAttachmentReference { + uint32_t attachment; + VkImageLayout layout; +} VkAttachmentReference; + +typedef struct VkFramebufferCreateInfo { + VkStructureType sType; + const void* pNext; + VkFramebufferCreateFlags flags; + VkRenderPass renderPass; + uint32_t attachmentCount; + const VkImageView* pAttachments; + uint32_t width; + uint32_t height; + uint32_t layers; +} VkFramebufferCreateInfo; + +typedef struct VkSubpassDescription { + VkSubpassDescriptionFlags flags; + VkPipelineBindPoint pipelineBindPoint; + uint32_t inputAttachmentCount; + const VkAttachmentReference* pInputAttachments; + uint32_t colorAttachmentCount; + const VkAttachmentReference* pColorAttachments; + const VkAttachmentReference* pResolveAttachments; + const VkAttachmentReference* pDepthStencilAttachment; + uint32_t preserveAttachmentCount; + const uint32_t* pPreserveAttachments; +} VkSubpassDescription; + +typedef struct VkSubpassDependency { + uint32_t srcSubpass; + uint32_t dstSubpass; + VkPipelineStageFlags srcStageMask; + VkPipelineStageFlags dstStageMask; + VkAccessFlags srcAccessMask; + VkAccessFlags dstAccessMask; + VkDependencyFlags dependencyFlags; +} VkSubpassDependency; + +typedef struct VkRenderPassCreateInfo { + VkStructureType sType; + const void* pNext; + VkRenderPassCreateFlags flags; + uint32_t attachmentCount; + const VkAttachmentDescription* pAttachments; + uint32_t subpassCount; + const VkSubpassDescription* pSubpasses; + uint32_t dependencyCount; + const VkSubpassDependency* pDependencies; +} VkRenderPassCreateInfo; + +typedef struct VkCommandPoolCreateInfo { + VkStructureType sType; + const void* pNext; + VkCommandPoolCreateFlags flags; + uint32_t queueFamilyIndex; +} VkCommandPoolCreateInfo; + +typedef struct VkCommandBufferAllocateInfo { + VkStructureType sType; + const void* pNext; + VkCommandPool commandPool; + VkCommandBufferLevel level; + uint32_t commandBufferCount; +} VkCommandBufferAllocateInfo; + +typedef struct VkCommandBufferInheritanceInfo { + VkStructureType sType; + const void* pNext; + VkRenderPass renderPass; + uint32_t subpass; + VkFramebuffer framebuffer; + VkBool32 occlusionQueryEnable; + VkQueryControlFlags queryFlags; + VkQueryPipelineStatisticFlags pipelineStatistics; +} VkCommandBufferInheritanceInfo; + +typedef struct VkCommandBufferBeginInfo { + VkStructureType sType; + const void* pNext; + VkCommandBufferUsageFlags flags; + const VkCommandBufferInheritanceInfo* pInheritanceInfo; +} VkCommandBufferBeginInfo; + +typedef struct VkBufferCopy { + VkDeviceSize srcOffset; + VkDeviceSize dstOffset; + VkDeviceSize size; +} VkBufferCopy; + +typedef struct VkImageSubresourceLayers { + VkImageAspectFlags aspectMask; + uint32_t mipLevel; + uint32_t baseArrayLayer; + uint32_t layerCount; +} VkImageSubresourceLayers; + +typedef struct VkBufferImageCopy { + VkDeviceSize bufferOffset; + uint32_t bufferRowLength; + uint32_t bufferImageHeight; + VkImageSubresourceLayers imageSubresource; + VkOffset3D imageOffset; + VkExtent3D imageExtent; +} VkBufferImageCopy; + +typedef union VkClearColorValue { + float float32[4]; + int32_t int32[4]; + uint32_t uint32[4]; +} VkClearColorValue; + +typedef struct VkClearDepthStencilValue { + float depth; + uint32_t stencil; +} VkClearDepthStencilValue; + +typedef union VkClearValue { + VkClearColorValue color; + VkClearDepthStencilValue depthStencil; +} VkClearValue; + +typedef struct VkClearAttachment { + VkImageAspectFlags aspectMask; + uint32_t colorAttachment; + VkClearValue clearValue; +} VkClearAttachment; + +typedef struct VkClearRect { + VkRect2D rect; + uint32_t baseArrayLayer; + uint32_t layerCount; +} VkClearRect; + +typedef struct VkImageBlit { + VkImageSubresourceLayers srcSubresource; + VkOffset3D srcOffsets[2]; + VkImageSubresourceLayers dstSubresource; + VkOffset3D dstOffsets[2]; +} VkImageBlit; + +typedef struct VkImageCopy { + VkImageSubresourceLayers srcSubresource; + VkOffset3D srcOffset; + VkImageSubresourceLayers dstSubresource; + VkOffset3D dstOffset; + VkExtent3D extent; +} VkImageCopy; + +typedef struct VkImageResolve { + VkImageSubresourceLayers srcSubresource; + VkOffset3D srcOffset; + VkImageSubresourceLayers dstSubresource; + VkOffset3D dstOffset; + VkExtent3D extent; +} VkImageResolve; + +typedef struct VkRenderPassBeginInfo { + VkStructureType sType; + const void* pNext; + VkRenderPass renderPass; + VkFramebuffer framebuffer; + VkRect2D renderArea; + uint32_t clearValueCount; + const VkClearValue* pClearValues; +} VkRenderPassBeginInfo; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateInstance)(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance); +typedef void (VKAPI_PTR *PFN_vkDestroyInstance)(VkInstance instance, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDevices)(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFeatures)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures* pFeatures); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFormatProperties)(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties* pFormatProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceImageFormatProperties)(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* pImageFormatProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceProperties)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties* pProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyProperties)(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties* pQueueFamilyProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMemoryProperties)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties* pMemoryProperties); +typedef PFN_vkVoidFunction (VKAPI_PTR *PFN_vkGetInstanceProcAddr)(VkInstance instance, const char* pName); +typedef PFN_vkVoidFunction (VKAPI_PTR *PFN_vkGetDeviceProcAddr)(VkDevice device, const char* pName); +typedef VkResult (VKAPI_PTR *PFN_vkCreateDevice)(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice); +typedef void (VKAPI_PTR *PFN_vkDestroyDevice)(VkDevice device, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkEnumerateInstanceExtensionProperties)(const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkEnumerateDeviceExtensionProperties)(VkPhysicalDevice physicalDevice, const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkEnumerateInstanceLayerProperties)(uint32_t* pPropertyCount, VkLayerProperties* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkEnumerateDeviceLayerProperties)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkLayerProperties* pProperties); +typedef void (VKAPI_PTR *PFN_vkGetDeviceQueue)(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue* pQueue); +typedef VkResult (VKAPI_PTR *PFN_vkQueueSubmit)(VkQueue queue, uint32_t submitCount, const VkSubmitInfo* pSubmits, VkFence fence); +typedef VkResult (VKAPI_PTR *PFN_vkQueueWaitIdle)(VkQueue queue); +typedef VkResult (VKAPI_PTR *PFN_vkDeviceWaitIdle)(VkDevice device); +typedef VkResult (VKAPI_PTR *PFN_vkAllocateMemory)(VkDevice device, const VkMemoryAllocateInfo* pAllocateInfo, const VkAllocationCallbacks* pAllocator, VkDeviceMemory* pMemory); +typedef void (VKAPI_PTR *PFN_vkFreeMemory)(VkDevice device, VkDeviceMemory memory, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkMapMemory)(VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData); +typedef void (VKAPI_PTR *PFN_vkUnmapMemory)(VkDevice device, VkDeviceMemory memory); +typedef VkResult (VKAPI_PTR *PFN_vkFlushMappedMemoryRanges)(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges); +typedef VkResult (VKAPI_PTR *PFN_vkInvalidateMappedMemoryRanges)(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges); +typedef void (VKAPI_PTR *PFN_vkGetDeviceMemoryCommitment)(VkDevice device, VkDeviceMemory memory, VkDeviceSize* pCommittedMemoryInBytes); +typedef VkResult (VKAPI_PTR *PFN_vkBindBufferMemory)(VkDevice device, VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset); +typedef VkResult (VKAPI_PTR *PFN_vkBindImageMemory)(VkDevice device, VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset); +typedef void (VKAPI_PTR *PFN_vkGetBufferMemoryRequirements)(VkDevice device, VkBuffer buffer, VkMemoryRequirements* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetImageMemoryRequirements)(VkDevice device, VkImage image, VkMemoryRequirements* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetImageSparseMemoryRequirements)(VkDevice device, VkImage image, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements* pSparseMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties)(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t* pPropertyCount, VkSparseImageFormatProperties* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkQueueBindSparse)(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo* pBindInfo, VkFence fence); +typedef VkResult (VKAPI_PTR *PFN_vkCreateFence)(VkDevice device, const VkFenceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence); +typedef void (VKAPI_PTR *PFN_vkDestroyFence)(VkDevice device, VkFence fence, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkResetFences)(VkDevice device, uint32_t fenceCount, const VkFence* pFences); +typedef VkResult (VKAPI_PTR *PFN_vkGetFenceStatus)(VkDevice device, VkFence fence); +typedef VkResult (VKAPI_PTR *PFN_vkWaitForFences)(VkDevice device, uint32_t fenceCount, const VkFence* pFences, VkBool32 waitAll, uint64_t timeout); +typedef VkResult (VKAPI_PTR *PFN_vkCreateSemaphore)(VkDevice device, const VkSemaphoreCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSemaphore* pSemaphore); +typedef void (VKAPI_PTR *PFN_vkDestroySemaphore)(VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreateEvent)(VkDevice device, const VkEventCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkEvent* pEvent); +typedef void (VKAPI_PTR *PFN_vkDestroyEvent)(VkDevice device, VkEvent event, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkGetEventStatus)(VkDevice device, VkEvent event); +typedef VkResult (VKAPI_PTR *PFN_vkSetEvent)(VkDevice device, VkEvent event); +typedef VkResult (VKAPI_PTR *PFN_vkResetEvent)(VkDevice device, VkEvent event); +typedef VkResult (VKAPI_PTR *PFN_vkCreateQueryPool)(VkDevice device, const VkQueryPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkQueryPool* pQueryPool); +typedef void (VKAPI_PTR *PFN_vkDestroyQueryPool)(VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkGetQueryPoolResults)(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, size_t dataSize, void* pData, VkDeviceSize stride, VkQueryResultFlags flags); +typedef VkResult (VKAPI_PTR *PFN_vkCreateBuffer)(VkDevice device, const VkBufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBuffer* pBuffer); +typedef void (VKAPI_PTR *PFN_vkDestroyBuffer)(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreateBufferView)(VkDevice device, const VkBufferViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBufferView* pView); +typedef void (VKAPI_PTR *PFN_vkDestroyBufferView)(VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreateImage)(VkDevice device, const VkImageCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImage* pImage); +typedef void (VKAPI_PTR *PFN_vkDestroyImage)(VkDevice device, VkImage image, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkGetImageSubresourceLayout)(VkDevice device, VkImage image, const VkImageSubresource* pSubresource, VkSubresourceLayout* pLayout); +typedef VkResult (VKAPI_PTR *PFN_vkCreateImageView)(VkDevice device, const VkImageViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImageView* pView); +typedef void (VKAPI_PTR *PFN_vkDestroyImageView)(VkDevice device, VkImageView imageView, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreateShaderModule)(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule); +typedef void (VKAPI_PTR *PFN_vkDestroyShaderModule)(VkDevice device, VkShaderModule shaderModule, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreatePipelineCache)(VkDevice device, const VkPipelineCacheCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineCache* pPipelineCache); +typedef void (VKAPI_PTR *PFN_vkDestroyPipelineCache)(VkDevice device, VkPipelineCache pipelineCache, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkGetPipelineCacheData)(VkDevice device, VkPipelineCache pipelineCache, size_t* pDataSize, void* pData); +typedef VkResult (VKAPI_PTR *PFN_vkMergePipelineCaches)(VkDevice device, VkPipelineCache dstCache, uint32_t srcCacheCount, const VkPipelineCache* pSrcCaches); +typedef VkResult (VKAPI_PTR *PFN_vkCreateGraphicsPipelines)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); +typedef VkResult (VKAPI_PTR *PFN_vkCreateComputePipelines)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); +typedef void (VKAPI_PTR *PFN_vkDestroyPipeline)(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreatePipelineLayout)(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout); +typedef void (VKAPI_PTR *PFN_vkDestroyPipelineLayout)(VkDevice device, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreateSampler)(VkDevice device, const VkSamplerCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSampler* pSampler); +typedef void (VKAPI_PTR *PFN_vkDestroySampler)(VkDevice device, VkSampler sampler, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreateDescriptorSetLayout)(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorSetLayout* pSetLayout); +typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorSetLayout)(VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreateDescriptorPool)(VkDevice device, const VkDescriptorPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorPool* pDescriptorPool); +typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorPool)(VkDevice device, VkDescriptorPool descriptorPool, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkResetDescriptorPool)(VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorPoolResetFlags flags); +typedef VkResult (VKAPI_PTR *PFN_vkAllocateDescriptorSets)(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets); +typedef VkResult (VKAPI_PTR *PFN_vkFreeDescriptorSets)(VkDevice device, VkDescriptorPool descriptorPool, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets); +typedef void (VKAPI_PTR *PFN_vkUpdateDescriptorSets)(VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites, uint32_t descriptorCopyCount, const VkCopyDescriptorSet* pDescriptorCopies); +typedef VkResult (VKAPI_PTR *PFN_vkCreateFramebuffer)(VkDevice device, const VkFramebufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFramebuffer* pFramebuffer); +typedef void (VKAPI_PTR *PFN_vkDestroyFramebuffer)(VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreateRenderPass)(VkDevice device, const VkRenderPassCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass); +typedef void (VKAPI_PTR *PFN_vkDestroyRenderPass)(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkGetRenderAreaGranularity)(VkDevice device, VkRenderPass renderPass, VkExtent2D* pGranularity); +typedef VkResult (VKAPI_PTR *PFN_vkCreateCommandPool)(VkDevice device, const VkCommandPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCommandPool* pCommandPool); +typedef void (VKAPI_PTR *PFN_vkDestroyCommandPool)(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkResetCommandPool)(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags); +typedef VkResult (VKAPI_PTR *PFN_vkAllocateCommandBuffers)(VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo, VkCommandBuffer* pCommandBuffers); +typedef void (VKAPI_PTR *PFN_vkFreeCommandBuffers)(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers); +typedef VkResult (VKAPI_PTR *PFN_vkBeginCommandBuffer)(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo* pBeginInfo); +typedef VkResult (VKAPI_PTR *PFN_vkEndCommandBuffer)(VkCommandBuffer commandBuffer); +typedef VkResult (VKAPI_PTR *PFN_vkResetCommandBuffer)(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags); +typedef void (VKAPI_PTR *PFN_vkCmdBindPipeline)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline); +typedef void (VKAPI_PTR *PFN_vkCmdSetViewport)(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewport* pViewports); +typedef void (VKAPI_PTR *PFN_vkCmdSetScissor)(VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_t scissorCount, const VkRect2D* pScissors); +typedef void (VKAPI_PTR *PFN_vkCmdSetLineWidth)(VkCommandBuffer commandBuffer, float lineWidth); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBias)(VkCommandBuffer commandBuffer, float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor); +typedef void (VKAPI_PTR *PFN_vkCmdSetBlendConstants)(VkCommandBuffer commandBuffer, const float blendConstants[4]); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBounds)(VkCommandBuffer commandBuffer, float minDepthBounds, float maxDepthBounds); +typedef void (VKAPI_PTR *PFN_vkCmdSetStencilCompareMask)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t compareMask); +typedef void (VKAPI_PTR *PFN_vkCmdSetStencilWriteMask)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t writeMask); +typedef void (VKAPI_PTR *PFN_vkCmdSetStencilReference)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t reference); +typedef void (VKAPI_PTR *PFN_vkCmdBindDescriptorSets)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets, uint32_t dynamicOffsetCount, const uint32_t* pDynamicOffsets); +typedef void (VKAPI_PTR *PFN_vkCmdBindIndexBuffer)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType); +typedef void (VKAPI_PTR *PFN_vkCmdBindVertexBuffers)(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets); +typedef void (VKAPI_PTR *PFN_vkCmdDraw)(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexed)(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirect)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirect)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdDispatch)(VkCommandBuffer commandBuffer, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ); +typedef void (VKAPI_PTR *PFN_vkCmdDispatchIndirect)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset); +typedef void (VKAPI_PTR *PFN_vkCmdCopyBuffer)(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferCopy* pRegions); +typedef void (VKAPI_PTR *PFN_vkCmdCopyImage)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageCopy* pRegions); +typedef void (VKAPI_PTR *PFN_vkCmdBlitImage)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageBlit* pRegions, VkFilter filter); +typedef void (VKAPI_PTR *PFN_vkCmdCopyBufferToImage)(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkBufferImageCopy* pRegions); +typedef void (VKAPI_PTR *PFN_vkCmdCopyImageToBuffer)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy* pRegions); +typedef void (VKAPI_PTR *PFN_vkCmdUpdateBuffer)(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const void* pData); +typedef void (VKAPI_PTR *PFN_vkCmdFillBuffer)(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data); +typedef void (VKAPI_PTR *PFN_vkCmdClearColorImage)(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearColorValue* pColor, uint32_t rangeCount, const VkImageSubresourceRange* pRanges); +typedef void (VKAPI_PTR *PFN_vkCmdClearDepthStencilImage)(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearDepthStencilValue* pDepthStencil, uint32_t rangeCount, const VkImageSubresourceRange* pRanges); +typedef void (VKAPI_PTR *PFN_vkCmdClearAttachments)(VkCommandBuffer commandBuffer, uint32_t attachmentCount, const VkClearAttachment* pAttachments, uint32_t rectCount, const VkClearRect* pRects); +typedef void (VKAPI_PTR *PFN_vkCmdResolveImage)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageResolve* pRegions); +typedef void (VKAPI_PTR *PFN_vkCmdSetEvent)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask); +typedef void (VKAPI_PTR *PFN_vkCmdResetEvent)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask); +typedef void (VKAPI_PTR *PFN_vkCmdWaitEvents)(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent* pEvents, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers); +typedef void (VKAPI_PTR *PFN_vkCmdPipelineBarrier)(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers); +typedef void (VKAPI_PTR *PFN_vkCmdBeginQuery)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags); +typedef void (VKAPI_PTR *PFN_vkCmdEndQuery)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query); +typedef void (VKAPI_PTR *PFN_vkCmdResetQueryPool)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount); +typedef void (VKAPI_PTR *PFN_vkCmdWriteTimestamp)(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkQueryPool queryPool, uint32_t query); +typedef void (VKAPI_PTR *PFN_vkCmdCopyQueryPoolResults)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags); +typedef void (VKAPI_PTR *PFN_vkCmdPushConstants)(VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size, const void* pValues); +typedef void (VKAPI_PTR *PFN_vkCmdBeginRenderPass)(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, VkSubpassContents contents); +typedef void (VKAPI_PTR *PFN_vkCmdNextSubpass)(VkCommandBuffer commandBuffer, VkSubpassContents contents); +typedef void (VKAPI_PTR *PFN_vkCmdEndRenderPass)(VkCommandBuffer commandBuffer); +typedef void (VKAPI_PTR *PFN_vkCmdExecuteCommands)(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance( + const VkInstanceCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkInstance* pInstance); + +VKAPI_ATTR void VKAPI_CALL vkDestroyInstance( + VkInstance instance, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDevices( + VkInstance instance, + uint32_t* pPhysicalDeviceCount, + VkPhysicalDevice* pPhysicalDevices); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures( + VkPhysicalDevice physicalDevice, + VkPhysicalDeviceFeatures* pFeatures); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFormatProperties( + VkPhysicalDevice physicalDevice, + VkFormat format, + VkFormatProperties* pFormatProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties( + VkPhysicalDevice physicalDevice, + VkFormat format, + VkImageType type, + VkImageTiling tiling, + VkImageUsageFlags usage, + VkImageCreateFlags flags, + VkImageFormatProperties* pImageFormatProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties( + VkPhysicalDevice physicalDevice, + VkPhysicalDeviceProperties* pProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties( + VkPhysicalDevice physicalDevice, + uint32_t* pQueueFamilyPropertyCount, + VkQueueFamilyProperties* pQueueFamilyProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties( + VkPhysicalDevice physicalDevice, + VkPhysicalDeviceMemoryProperties* pMemoryProperties); + +VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr( + VkInstance instance, + const char* pName); + +VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr( + VkDevice device, + const char* pName); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice( + VkPhysicalDevice physicalDevice, + const VkDeviceCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDevice* pDevice); + +VKAPI_ATTR void VKAPI_CALL vkDestroyDevice( + VkDevice device, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties( + const char* pLayerName, + uint32_t* pPropertyCount, + VkExtensionProperties* pProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties( + VkPhysicalDevice physicalDevice, + const char* pLayerName, + uint32_t* pPropertyCount, + VkExtensionProperties* pProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties( + uint32_t* pPropertyCount, + VkLayerProperties* pProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties( + VkPhysicalDevice physicalDevice, + uint32_t* pPropertyCount, + VkLayerProperties* pProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetDeviceQueue( + VkDevice device, + uint32_t queueFamilyIndex, + uint32_t queueIndex, + VkQueue* pQueue); + +VKAPI_ATTR VkResult VKAPI_CALL vkQueueSubmit( + VkQueue queue, + uint32_t submitCount, + const VkSubmitInfo* pSubmits, + VkFence fence); + +VKAPI_ATTR VkResult VKAPI_CALL vkQueueWaitIdle( + VkQueue queue); + +VKAPI_ATTR VkResult VKAPI_CALL vkDeviceWaitIdle( + VkDevice device); + +VKAPI_ATTR VkResult VKAPI_CALL vkAllocateMemory( + VkDevice device, + const VkMemoryAllocateInfo* pAllocateInfo, + const VkAllocationCallbacks* pAllocator, + VkDeviceMemory* pMemory); + +VKAPI_ATTR void VKAPI_CALL vkFreeMemory( + VkDevice device, + VkDeviceMemory memory, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkMapMemory( + VkDevice device, + VkDeviceMemory memory, + VkDeviceSize offset, + VkDeviceSize size, + VkMemoryMapFlags flags, + void** ppData); + +VKAPI_ATTR void VKAPI_CALL vkUnmapMemory( + VkDevice device, + VkDeviceMemory memory); + +VKAPI_ATTR VkResult VKAPI_CALL vkFlushMappedMemoryRanges( + VkDevice device, + uint32_t memoryRangeCount, + const VkMappedMemoryRange* pMemoryRanges); + +VKAPI_ATTR VkResult VKAPI_CALL vkInvalidateMappedMemoryRanges( + VkDevice device, + uint32_t memoryRangeCount, + const VkMappedMemoryRange* pMemoryRanges); + +VKAPI_ATTR void VKAPI_CALL vkGetDeviceMemoryCommitment( + VkDevice device, + VkDeviceMemory memory, + VkDeviceSize* pCommittedMemoryInBytes); + +VKAPI_ATTR VkResult VKAPI_CALL vkBindBufferMemory( + VkDevice device, + VkBuffer buffer, + VkDeviceMemory memory, + VkDeviceSize memoryOffset); + +VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory( + VkDevice device, + VkImage image, + VkDeviceMemory memory, + VkDeviceSize memoryOffset); + +VKAPI_ATTR void VKAPI_CALL vkGetBufferMemoryRequirements( + VkDevice device, + VkBuffer buffer, + VkMemoryRequirements* pMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkGetImageMemoryRequirements( + VkDevice device, + VkImage image, + VkMemoryRequirements* pMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkGetImageSparseMemoryRequirements( + VkDevice device, + VkImage image, + uint32_t* pSparseMemoryRequirementCount, + VkSparseImageMemoryRequirements* pSparseMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties( + VkPhysicalDevice physicalDevice, + VkFormat format, + VkImageType type, + VkSampleCountFlagBits samples, + VkImageUsageFlags usage, + VkImageTiling tiling, + uint32_t* pPropertyCount, + VkSparseImageFormatProperties* pProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkQueueBindSparse( + VkQueue queue, + uint32_t bindInfoCount, + const VkBindSparseInfo* pBindInfo, + VkFence fence); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateFence( + VkDevice device, + const VkFenceCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkFence* pFence); + +VKAPI_ATTR void VKAPI_CALL vkDestroyFence( + VkDevice device, + VkFence fence, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkResetFences( + VkDevice device, + uint32_t fenceCount, + const VkFence* pFences); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceStatus( + VkDevice device, + VkFence fence); + +VKAPI_ATTR VkResult VKAPI_CALL vkWaitForFences( + VkDevice device, + uint32_t fenceCount, + const VkFence* pFences, + VkBool32 waitAll, + uint64_t timeout); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateSemaphore( + VkDevice device, + const VkSemaphoreCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSemaphore* pSemaphore); + +VKAPI_ATTR void VKAPI_CALL vkDestroySemaphore( + VkDevice device, + VkSemaphore semaphore, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateEvent( + VkDevice device, + const VkEventCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkEvent* pEvent); + +VKAPI_ATTR void VKAPI_CALL vkDestroyEvent( + VkDevice device, + VkEvent event, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetEventStatus( + VkDevice device, + VkEvent event); + +VKAPI_ATTR VkResult VKAPI_CALL vkSetEvent( + VkDevice device, + VkEvent event); + +VKAPI_ATTR VkResult VKAPI_CALL vkResetEvent( + VkDevice device, + VkEvent event); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateQueryPool( + VkDevice device, + const VkQueryPoolCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkQueryPool* pQueryPool); + +VKAPI_ATTR void VKAPI_CALL vkDestroyQueryPool( + VkDevice device, + VkQueryPool queryPool, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetQueryPoolResults( + VkDevice device, + VkQueryPool queryPool, + uint32_t firstQuery, + uint32_t queryCount, + size_t dataSize, + void* pData, + VkDeviceSize stride, + VkQueryResultFlags flags); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateBuffer( + VkDevice device, + const VkBufferCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkBuffer* pBuffer); + +VKAPI_ATTR void VKAPI_CALL vkDestroyBuffer( + VkDevice device, + VkBuffer buffer, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateBufferView( + VkDevice device, + const VkBufferViewCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkBufferView* pView); + +VKAPI_ATTR void VKAPI_CALL vkDestroyBufferView( + VkDevice device, + VkBufferView bufferView, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateImage( + VkDevice device, + const VkImageCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkImage* pImage); + +VKAPI_ATTR void VKAPI_CALL vkDestroyImage( + VkDevice device, + VkImage image, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR void VKAPI_CALL vkGetImageSubresourceLayout( + VkDevice device, + VkImage image, + const VkImageSubresource* pSubresource, + VkSubresourceLayout* pLayout); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateImageView( + VkDevice device, + const VkImageViewCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkImageView* pView); + +VKAPI_ATTR void VKAPI_CALL vkDestroyImageView( + VkDevice device, + VkImageView imageView, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateShaderModule( + VkDevice device, + const VkShaderModuleCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkShaderModule* pShaderModule); + +VKAPI_ATTR void VKAPI_CALL vkDestroyShaderModule( + VkDevice device, + VkShaderModule shaderModule, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreatePipelineCache( + VkDevice device, + const VkPipelineCacheCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkPipelineCache* pPipelineCache); + +VKAPI_ATTR void VKAPI_CALL vkDestroyPipelineCache( + VkDevice device, + VkPipelineCache pipelineCache, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineCacheData( + VkDevice device, + VkPipelineCache pipelineCache, + size_t* pDataSize, + void* pData); + +VKAPI_ATTR VkResult VKAPI_CALL vkMergePipelineCaches( + VkDevice device, + VkPipelineCache dstCache, + uint32_t srcCacheCount, + const VkPipelineCache* pSrcCaches); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateGraphicsPipelines( + VkDevice device, + VkPipelineCache pipelineCache, + uint32_t createInfoCount, + const VkGraphicsPipelineCreateInfo* pCreateInfos, + const VkAllocationCallbacks* pAllocator, + VkPipeline* pPipelines); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateComputePipelines( + VkDevice device, + VkPipelineCache pipelineCache, + uint32_t createInfoCount, + const VkComputePipelineCreateInfo* pCreateInfos, + const VkAllocationCallbacks* pAllocator, + VkPipeline* pPipelines); + +VKAPI_ATTR void VKAPI_CALL vkDestroyPipeline( + VkDevice device, + VkPipeline pipeline, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreatePipelineLayout( + VkDevice device, + const VkPipelineLayoutCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkPipelineLayout* pPipelineLayout); + +VKAPI_ATTR void VKAPI_CALL vkDestroyPipelineLayout( + VkDevice device, + VkPipelineLayout pipelineLayout, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateSampler( + VkDevice device, + const VkSamplerCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSampler* pSampler); + +VKAPI_ATTR void VKAPI_CALL vkDestroySampler( + VkDevice device, + VkSampler sampler, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorSetLayout( + VkDevice device, + const VkDescriptorSetLayoutCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDescriptorSetLayout* pSetLayout); + +VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorSetLayout( + VkDevice device, + VkDescriptorSetLayout descriptorSetLayout, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorPool( + VkDevice device, + const VkDescriptorPoolCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDescriptorPool* pDescriptorPool); + +VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorPool( + VkDevice device, + VkDescriptorPool descriptorPool, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkResetDescriptorPool( + VkDevice device, + VkDescriptorPool descriptorPool, + VkDescriptorPoolResetFlags flags); + +VKAPI_ATTR VkResult VKAPI_CALL vkAllocateDescriptorSets( + VkDevice device, + const VkDescriptorSetAllocateInfo* pAllocateInfo, + VkDescriptorSet* pDescriptorSets); + +VKAPI_ATTR VkResult VKAPI_CALL vkFreeDescriptorSets( + VkDevice device, + VkDescriptorPool descriptorPool, + uint32_t descriptorSetCount, + const VkDescriptorSet* pDescriptorSets); + +VKAPI_ATTR void VKAPI_CALL vkUpdateDescriptorSets( + VkDevice device, + uint32_t descriptorWriteCount, + const VkWriteDescriptorSet* pDescriptorWrites, + uint32_t descriptorCopyCount, + const VkCopyDescriptorSet* pDescriptorCopies); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateFramebuffer( + VkDevice device, + const VkFramebufferCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkFramebuffer* pFramebuffer); + +VKAPI_ATTR void VKAPI_CALL vkDestroyFramebuffer( + VkDevice device, + VkFramebuffer framebuffer, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateRenderPass( + VkDevice device, + const VkRenderPassCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkRenderPass* pRenderPass); + +VKAPI_ATTR void VKAPI_CALL vkDestroyRenderPass( + VkDevice device, + VkRenderPass renderPass, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR void VKAPI_CALL vkGetRenderAreaGranularity( + VkDevice device, + VkRenderPass renderPass, + VkExtent2D* pGranularity); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateCommandPool( + VkDevice device, + const VkCommandPoolCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkCommandPool* pCommandPool); + +VKAPI_ATTR void VKAPI_CALL vkDestroyCommandPool( + VkDevice device, + VkCommandPool commandPool, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkResetCommandPool( + VkDevice device, + VkCommandPool commandPool, + VkCommandPoolResetFlags flags); + +VKAPI_ATTR VkResult VKAPI_CALL vkAllocateCommandBuffers( + VkDevice device, + const VkCommandBufferAllocateInfo* pAllocateInfo, + VkCommandBuffer* pCommandBuffers); + +VKAPI_ATTR void VKAPI_CALL vkFreeCommandBuffers( + VkDevice device, + VkCommandPool commandPool, + uint32_t commandBufferCount, + const VkCommandBuffer* pCommandBuffers); + +VKAPI_ATTR VkResult VKAPI_CALL vkBeginCommandBuffer( + VkCommandBuffer commandBuffer, + const VkCommandBufferBeginInfo* pBeginInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkEndCommandBuffer( + VkCommandBuffer commandBuffer); + +VKAPI_ATTR VkResult VKAPI_CALL vkResetCommandBuffer( + VkCommandBuffer commandBuffer, + VkCommandBufferResetFlags flags); + +VKAPI_ATTR void VKAPI_CALL vkCmdBindPipeline( + VkCommandBuffer commandBuffer, + VkPipelineBindPoint pipelineBindPoint, + VkPipeline pipeline); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetViewport( + VkCommandBuffer commandBuffer, + uint32_t firstViewport, + uint32_t viewportCount, + const VkViewport* pViewports); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetScissor( + VkCommandBuffer commandBuffer, + uint32_t firstScissor, + uint32_t scissorCount, + const VkRect2D* pScissors); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetLineWidth( + VkCommandBuffer commandBuffer, + float lineWidth); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBias( + VkCommandBuffer commandBuffer, + float depthBiasConstantFactor, + float depthBiasClamp, + float depthBiasSlopeFactor); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetBlendConstants( + VkCommandBuffer commandBuffer, + const float blendConstants[4]); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBounds( + VkCommandBuffer commandBuffer, + float minDepthBounds, + float maxDepthBounds); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilCompareMask( + VkCommandBuffer commandBuffer, + VkStencilFaceFlags faceMask, + uint32_t compareMask); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilWriteMask( + VkCommandBuffer commandBuffer, + VkStencilFaceFlags faceMask, + uint32_t writeMask); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilReference( + VkCommandBuffer commandBuffer, + VkStencilFaceFlags faceMask, + uint32_t reference); + +VKAPI_ATTR void VKAPI_CALL vkCmdBindDescriptorSets( + VkCommandBuffer commandBuffer, + VkPipelineBindPoint pipelineBindPoint, + VkPipelineLayout layout, + uint32_t firstSet, + uint32_t descriptorSetCount, + const VkDescriptorSet* pDescriptorSets, + uint32_t dynamicOffsetCount, + const uint32_t* pDynamicOffsets); + +VKAPI_ATTR void VKAPI_CALL vkCmdBindIndexBuffer( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkIndexType indexType); + +VKAPI_ATTR void VKAPI_CALL vkCmdBindVertexBuffers( + VkCommandBuffer commandBuffer, + uint32_t firstBinding, + uint32_t bindingCount, + const VkBuffer* pBuffers, + const VkDeviceSize* pOffsets); + +VKAPI_ATTR void VKAPI_CALL vkCmdDraw( + VkCommandBuffer commandBuffer, + uint32_t vertexCount, + uint32_t instanceCount, + uint32_t firstVertex, + uint32_t firstInstance); + +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexed( + VkCommandBuffer commandBuffer, + uint32_t indexCount, + uint32_t instanceCount, + uint32_t firstIndex, + int32_t vertexOffset, + uint32_t firstInstance); + +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirect( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + uint32_t drawCount, + uint32_t stride); + +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirect( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + uint32_t drawCount, + uint32_t stride); + +VKAPI_ATTR void VKAPI_CALL vkCmdDispatch( + VkCommandBuffer commandBuffer, + uint32_t groupCountX, + uint32_t groupCountY, + uint32_t groupCountZ); + +VKAPI_ATTR void VKAPI_CALL vkCmdDispatchIndirect( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyBuffer( + VkCommandBuffer commandBuffer, + VkBuffer srcBuffer, + VkBuffer dstBuffer, + uint32_t regionCount, + const VkBufferCopy* pRegions); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyImage( + VkCommandBuffer commandBuffer, + VkImage srcImage, + VkImageLayout srcImageLayout, + VkImage dstImage, + VkImageLayout dstImageLayout, + uint32_t regionCount, + const VkImageCopy* pRegions); + +VKAPI_ATTR void VKAPI_CALL vkCmdBlitImage( + VkCommandBuffer commandBuffer, + VkImage srcImage, + VkImageLayout srcImageLayout, + VkImage dstImage, + VkImageLayout dstImageLayout, + uint32_t regionCount, + const VkImageBlit* pRegions, + VkFilter filter); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyBufferToImage( + VkCommandBuffer commandBuffer, + VkBuffer srcBuffer, + VkImage dstImage, + VkImageLayout dstImageLayout, + uint32_t regionCount, + const VkBufferImageCopy* pRegions); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyImageToBuffer( + VkCommandBuffer commandBuffer, + VkImage srcImage, + VkImageLayout srcImageLayout, + VkBuffer dstBuffer, + uint32_t regionCount, + const VkBufferImageCopy* pRegions); + +VKAPI_ATTR void VKAPI_CALL vkCmdUpdateBuffer( + VkCommandBuffer commandBuffer, + VkBuffer dstBuffer, + VkDeviceSize dstOffset, + VkDeviceSize dataSize, + const void* pData); + +VKAPI_ATTR void VKAPI_CALL vkCmdFillBuffer( + VkCommandBuffer commandBuffer, + VkBuffer dstBuffer, + VkDeviceSize dstOffset, + VkDeviceSize size, + uint32_t data); + +VKAPI_ATTR void VKAPI_CALL vkCmdClearColorImage( + VkCommandBuffer commandBuffer, + VkImage image, + VkImageLayout imageLayout, + const VkClearColorValue* pColor, + uint32_t rangeCount, + const VkImageSubresourceRange* pRanges); + +VKAPI_ATTR void VKAPI_CALL vkCmdClearDepthStencilImage( + VkCommandBuffer commandBuffer, + VkImage image, + VkImageLayout imageLayout, + const VkClearDepthStencilValue* pDepthStencil, + uint32_t rangeCount, + const VkImageSubresourceRange* pRanges); + +VKAPI_ATTR void VKAPI_CALL vkCmdClearAttachments( + VkCommandBuffer commandBuffer, + uint32_t attachmentCount, + const VkClearAttachment* pAttachments, + uint32_t rectCount, + const VkClearRect* pRects); + +VKAPI_ATTR void VKAPI_CALL vkCmdResolveImage( + VkCommandBuffer commandBuffer, + VkImage srcImage, + VkImageLayout srcImageLayout, + VkImage dstImage, + VkImageLayout dstImageLayout, + uint32_t regionCount, + const VkImageResolve* pRegions); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetEvent( + VkCommandBuffer commandBuffer, + VkEvent event, + VkPipelineStageFlags stageMask); + +VKAPI_ATTR void VKAPI_CALL vkCmdResetEvent( + VkCommandBuffer commandBuffer, + VkEvent event, + VkPipelineStageFlags stageMask); + +VKAPI_ATTR void VKAPI_CALL vkCmdWaitEvents( + VkCommandBuffer commandBuffer, + uint32_t eventCount, + const VkEvent* pEvents, + VkPipelineStageFlags srcStageMask, + VkPipelineStageFlags dstStageMask, + uint32_t memoryBarrierCount, + const VkMemoryBarrier* pMemoryBarriers, + uint32_t bufferMemoryBarrierCount, + const VkBufferMemoryBarrier* pBufferMemoryBarriers, + uint32_t imageMemoryBarrierCount, + const VkImageMemoryBarrier* pImageMemoryBarriers); + +VKAPI_ATTR void VKAPI_CALL vkCmdPipelineBarrier( + VkCommandBuffer commandBuffer, + VkPipelineStageFlags srcStageMask, + VkPipelineStageFlags dstStageMask, + VkDependencyFlags dependencyFlags, + uint32_t memoryBarrierCount, + const VkMemoryBarrier* pMemoryBarriers, + uint32_t bufferMemoryBarrierCount, + const VkBufferMemoryBarrier* pBufferMemoryBarriers, + uint32_t imageMemoryBarrierCount, + const VkImageMemoryBarrier* pImageMemoryBarriers); + +VKAPI_ATTR void VKAPI_CALL vkCmdBeginQuery( + VkCommandBuffer commandBuffer, + VkQueryPool queryPool, + uint32_t query, + VkQueryControlFlags flags); + +VKAPI_ATTR void VKAPI_CALL vkCmdEndQuery( + VkCommandBuffer commandBuffer, + VkQueryPool queryPool, + uint32_t query); + +VKAPI_ATTR void VKAPI_CALL vkCmdResetQueryPool( + VkCommandBuffer commandBuffer, + VkQueryPool queryPool, + uint32_t firstQuery, + uint32_t queryCount); + +VKAPI_ATTR void VKAPI_CALL vkCmdWriteTimestamp( + VkCommandBuffer commandBuffer, + VkPipelineStageFlagBits pipelineStage, + VkQueryPool queryPool, + uint32_t query); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyQueryPoolResults( + VkCommandBuffer commandBuffer, + VkQueryPool queryPool, + uint32_t firstQuery, + uint32_t queryCount, + VkBuffer dstBuffer, + VkDeviceSize dstOffset, + VkDeviceSize stride, + VkQueryResultFlags flags); + +VKAPI_ATTR void VKAPI_CALL vkCmdPushConstants( + VkCommandBuffer commandBuffer, + VkPipelineLayout layout, + VkShaderStageFlags stageFlags, + uint32_t offset, + uint32_t size, + const void* pValues); + +VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderPass( + VkCommandBuffer commandBuffer, + const VkRenderPassBeginInfo* pRenderPassBegin, + VkSubpassContents contents); + +VKAPI_ATTR void VKAPI_CALL vkCmdNextSubpass( + VkCommandBuffer commandBuffer, + VkSubpassContents contents); + +VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderPass( + VkCommandBuffer commandBuffer); + +VKAPI_ATTR void VKAPI_CALL vkCmdExecuteCommands( + VkCommandBuffer commandBuffer, + uint32_t commandBufferCount, + const VkCommandBuffer* pCommandBuffers); +#endif + + +#define VK_VERSION_1_1 1 +// Vulkan 1.1 version number +#define VK_API_VERSION_1_1 VK_MAKE_API_VERSION(0, 1, 1, 0)// Patch version should always be set to 0 + +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSamplerYcbcrConversion) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorUpdateTemplate) +#define VK_MAX_DEVICE_GROUP_SIZE 32U +#define VK_LUID_SIZE 8U +#define VK_QUEUE_FAMILY_EXTERNAL (~1U) + +typedef enum VkPointClippingBehavior { + VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES = 0, + VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY = 1, + VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES_KHR = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES, + VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY_KHR = VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY, + VK_POINT_CLIPPING_BEHAVIOR_MAX_ENUM = 0x7FFFFFFF +} VkPointClippingBehavior; + +typedef enum VkTessellationDomainOrigin { + VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT = 0, + VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT = 1, + VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT_KHR = VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT, + VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT_KHR = VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT, + VK_TESSELLATION_DOMAIN_ORIGIN_MAX_ENUM = 0x7FFFFFFF +} VkTessellationDomainOrigin; + +typedef enum VkSamplerYcbcrModelConversion { + VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY = 0, + VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY = 1, + VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709 = 2, + VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601 = 3, + VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020 = 4, + VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY, + VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY, + VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709, + VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601, + VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020, + VK_SAMPLER_YCBCR_MODEL_CONVERSION_MAX_ENUM = 0x7FFFFFFF +} VkSamplerYcbcrModelConversion; + +typedef enum VkSamplerYcbcrRange { + VK_SAMPLER_YCBCR_RANGE_ITU_FULL = 0, + VK_SAMPLER_YCBCR_RANGE_ITU_NARROW = 1, + VK_SAMPLER_YCBCR_RANGE_ITU_FULL_KHR = VK_SAMPLER_YCBCR_RANGE_ITU_FULL, + VK_SAMPLER_YCBCR_RANGE_ITU_NARROW_KHR = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW, + VK_SAMPLER_YCBCR_RANGE_MAX_ENUM = 0x7FFFFFFF +} VkSamplerYcbcrRange; + +typedef enum VkChromaLocation { + VK_CHROMA_LOCATION_COSITED_EVEN = 0, + VK_CHROMA_LOCATION_MIDPOINT = 1, + VK_CHROMA_LOCATION_COSITED_EVEN_KHR = VK_CHROMA_LOCATION_COSITED_EVEN, + VK_CHROMA_LOCATION_MIDPOINT_KHR = VK_CHROMA_LOCATION_MIDPOINT, + VK_CHROMA_LOCATION_MAX_ENUM = 0x7FFFFFFF +} VkChromaLocation; + +typedef enum VkDescriptorUpdateTemplateType { + VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET = 0, + VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR = 1, + VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET, + VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkDescriptorUpdateTemplateType; + +typedef enum VkSubgroupFeatureFlagBits { + VK_SUBGROUP_FEATURE_BASIC_BIT = 0x00000001, + VK_SUBGROUP_FEATURE_VOTE_BIT = 0x00000002, + VK_SUBGROUP_FEATURE_ARITHMETIC_BIT = 0x00000004, + VK_SUBGROUP_FEATURE_BALLOT_BIT = 0x00000008, + VK_SUBGROUP_FEATURE_SHUFFLE_BIT = 0x00000010, + VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT = 0x00000020, + VK_SUBGROUP_FEATURE_CLUSTERED_BIT = 0x00000040, + VK_SUBGROUP_FEATURE_QUAD_BIT = 0x00000080, + VK_SUBGROUP_FEATURE_PARTITIONED_BIT_NV = 0x00000100, + VK_SUBGROUP_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkSubgroupFeatureFlagBits; +typedef VkFlags VkSubgroupFeatureFlags; + +typedef enum VkPeerMemoryFeatureFlagBits { + VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT = 0x00000001, + VK_PEER_MEMORY_FEATURE_COPY_DST_BIT = 0x00000002, + VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT = 0x00000004, + VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT = 0x00000008, + VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT_KHR = VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT, + VK_PEER_MEMORY_FEATURE_COPY_DST_BIT_KHR = VK_PEER_MEMORY_FEATURE_COPY_DST_BIT, + VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT_KHR = VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT, + VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT_KHR = VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT, + VK_PEER_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPeerMemoryFeatureFlagBits; +typedef VkFlags VkPeerMemoryFeatureFlags; + +typedef enum VkMemoryAllocateFlagBits { + VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT = 0x00000001, + VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT = 0x00000002, + VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT = 0x00000004, + VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT_KHR = VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT, + VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT, + VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT, + VK_MEMORY_ALLOCATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkMemoryAllocateFlagBits; +typedef VkFlags VkMemoryAllocateFlags; +typedef VkFlags VkCommandPoolTrimFlags; +typedef VkFlags VkDescriptorUpdateTemplateCreateFlags; + +typedef enum VkExternalMemoryHandleTypeFlagBits { + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT = 0x00000001, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT = 0x00000002, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 0x00000004, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT = 0x00000008, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT = 0x00000010, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT = 0x00000020, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT = 0x00000040, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT = 0x00000200, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID = 0x00000400, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT = 0x00000080, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT = 0x00000100, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA = 0x00000800, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_RDMA_ADDRESS_BIT_NV = 0x00001000, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkExternalMemoryHandleTypeFlagBits; +typedef VkFlags VkExternalMemoryHandleTypeFlags; + +typedef enum VkExternalMemoryFeatureFlagBits { + VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT = 0x00000001, + VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT = 0x00000002, + VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT = 0x00000004, + VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR = VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT, + VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT, + VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT, + VK_EXTERNAL_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkExternalMemoryFeatureFlagBits; +typedef VkFlags VkExternalMemoryFeatureFlags; + +typedef enum VkExternalFenceHandleTypeFlagBits { + VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT = 0x00000001, + VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT = 0x00000002, + VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 0x00000004, + VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT = 0x00000008, + VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT, + VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT, + VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, + VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT, + VK_EXTERNAL_FENCE_HANDLE_TYPE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkExternalFenceHandleTypeFlagBits; +typedef VkFlags VkExternalFenceHandleTypeFlags; + +typedef enum VkExternalFenceFeatureFlagBits { + VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT = 0x00000001, + VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT = 0x00000002, + VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT_KHR = VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT, + VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT_KHR = VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT, + VK_EXTERNAL_FENCE_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkExternalFenceFeatureFlagBits; +typedef VkFlags VkExternalFenceFeatureFlags; + +typedef enum VkFenceImportFlagBits { + VK_FENCE_IMPORT_TEMPORARY_BIT = 0x00000001, + VK_FENCE_IMPORT_TEMPORARY_BIT_KHR = VK_FENCE_IMPORT_TEMPORARY_BIT, + VK_FENCE_IMPORT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkFenceImportFlagBits; +typedef VkFlags VkFenceImportFlags; + +typedef enum VkSemaphoreImportFlagBits { + VK_SEMAPHORE_IMPORT_TEMPORARY_BIT = 0x00000001, + VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT, + VK_SEMAPHORE_IMPORT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkSemaphoreImportFlagBits; +typedef VkFlags VkSemaphoreImportFlags; + +typedef enum VkExternalSemaphoreHandleTypeFlagBits { + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT = 0x00000001, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT = 0x00000002, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 0x00000004, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT = 0x00000008, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT = 0x00000010, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA = 0x00000080, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D11_FENCE_BIT = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT_KHR = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkExternalSemaphoreHandleTypeFlagBits; +typedef VkFlags VkExternalSemaphoreHandleTypeFlags; + +typedef enum VkExternalSemaphoreFeatureFlagBits { + VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT = 0x00000001, + VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT = 0x00000002, + VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHR = VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT, + VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR = VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT, + VK_EXTERNAL_SEMAPHORE_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkExternalSemaphoreFeatureFlagBits; +typedef VkFlags VkExternalSemaphoreFeatureFlags; +typedef struct VkPhysicalDeviceSubgroupProperties { + VkStructureType sType; + void* pNext; + uint32_t subgroupSize; + VkShaderStageFlags supportedStages; + VkSubgroupFeatureFlags supportedOperations; + VkBool32 quadOperationsInAllStages; +} VkPhysicalDeviceSubgroupProperties; + +typedef struct VkBindBufferMemoryInfo { + VkStructureType sType; + const void* pNext; + VkBuffer buffer; + VkDeviceMemory memory; + VkDeviceSize memoryOffset; +} VkBindBufferMemoryInfo; + +typedef struct VkBindImageMemoryInfo { + VkStructureType sType; + const void* pNext; + VkImage image; + VkDeviceMemory memory; + VkDeviceSize memoryOffset; +} VkBindImageMemoryInfo; + +typedef struct VkPhysicalDevice16BitStorageFeatures { + VkStructureType sType; + void* pNext; + VkBool32 storageBuffer16BitAccess; + VkBool32 uniformAndStorageBuffer16BitAccess; + VkBool32 storagePushConstant16; + VkBool32 storageInputOutput16; +} VkPhysicalDevice16BitStorageFeatures; + +typedef struct VkMemoryDedicatedRequirements { + VkStructureType sType; + void* pNext; + VkBool32 prefersDedicatedAllocation; + VkBool32 requiresDedicatedAllocation; +} VkMemoryDedicatedRequirements; + +typedef struct VkMemoryDedicatedAllocateInfo { + VkStructureType sType; + const void* pNext; + VkImage image; + VkBuffer buffer; +} VkMemoryDedicatedAllocateInfo; + +typedef struct VkMemoryAllocateFlagsInfo { + VkStructureType sType; + const void* pNext; + VkMemoryAllocateFlags flags; + uint32_t deviceMask; +} VkMemoryAllocateFlagsInfo; + +typedef struct VkDeviceGroupRenderPassBeginInfo { + VkStructureType sType; + const void* pNext; + uint32_t deviceMask; + uint32_t deviceRenderAreaCount; + const VkRect2D* pDeviceRenderAreas; +} VkDeviceGroupRenderPassBeginInfo; + +typedef struct VkDeviceGroupCommandBufferBeginInfo { + VkStructureType sType; + const void* pNext; + uint32_t deviceMask; +} VkDeviceGroupCommandBufferBeginInfo; + +typedef struct VkDeviceGroupSubmitInfo { + VkStructureType sType; + const void* pNext; + uint32_t waitSemaphoreCount; + const uint32_t* pWaitSemaphoreDeviceIndices; + uint32_t commandBufferCount; + const uint32_t* pCommandBufferDeviceMasks; + uint32_t signalSemaphoreCount; + const uint32_t* pSignalSemaphoreDeviceIndices; +} VkDeviceGroupSubmitInfo; + +typedef struct VkDeviceGroupBindSparseInfo { + VkStructureType sType; + const void* pNext; + uint32_t resourceDeviceIndex; + uint32_t memoryDeviceIndex; +} VkDeviceGroupBindSparseInfo; + +typedef struct VkBindBufferMemoryDeviceGroupInfo { + VkStructureType sType; + const void* pNext; + uint32_t deviceIndexCount; + const uint32_t* pDeviceIndices; +} VkBindBufferMemoryDeviceGroupInfo; + +typedef struct VkBindImageMemoryDeviceGroupInfo { + VkStructureType sType; + const void* pNext; + uint32_t deviceIndexCount; + const uint32_t* pDeviceIndices; + uint32_t splitInstanceBindRegionCount; + const VkRect2D* pSplitInstanceBindRegions; +} VkBindImageMemoryDeviceGroupInfo; + +typedef struct VkPhysicalDeviceGroupProperties { + VkStructureType sType; + void* pNext; + uint32_t physicalDeviceCount; + VkPhysicalDevice physicalDevices[VK_MAX_DEVICE_GROUP_SIZE]; + VkBool32 subsetAllocation; +} VkPhysicalDeviceGroupProperties; + +typedef struct VkDeviceGroupDeviceCreateInfo { + VkStructureType sType; + const void* pNext; + uint32_t physicalDeviceCount; + const VkPhysicalDevice* pPhysicalDevices; +} VkDeviceGroupDeviceCreateInfo; + +typedef struct VkBufferMemoryRequirementsInfo2 { + VkStructureType sType; + const void* pNext; + VkBuffer buffer; +} VkBufferMemoryRequirementsInfo2; + +typedef struct VkImageMemoryRequirementsInfo2 { + VkStructureType sType; + const void* pNext; + VkImage image; +} VkImageMemoryRequirementsInfo2; + +typedef struct VkImageSparseMemoryRequirementsInfo2 { + VkStructureType sType; + const void* pNext; + VkImage image; +} VkImageSparseMemoryRequirementsInfo2; + +typedef struct VkMemoryRequirements2 { + VkStructureType sType; + void* pNext; + VkMemoryRequirements memoryRequirements; +} VkMemoryRequirements2; + +typedef struct VkSparseImageMemoryRequirements2 { + VkStructureType sType; + void* pNext; + VkSparseImageMemoryRequirements memoryRequirements; +} VkSparseImageMemoryRequirements2; + +typedef struct VkPhysicalDeviceFeatures2 { + VkStructureType sType; + void* pNext; + VkPhysicalDeviceFeatures features; +} VkPhysicalDeviceFeatures2; + +typedef struct VkPhysicalDeviceProperties2 { + VkStructureType sType; + void* pNext; + VkPhysicalDeviceProperties properties; +} VkPhysicalDeviceProperties2; + +typedef struct VkFormatProperties2 { + VkStructureType sType; + void* pNext; + VkFormatProperties formatProperties; +} VkFormatProperties2; + +typedef struct VkImageFormatProperties2 { + VkStructureType sType; + void* pNext; + VkImageFormatProperties imageFormatProperties; +} VkImageFormatProperties2; + +typedef struct VkPhysicalDeviceImageFormatInfo2 { + VkStructureType sType; + const void* pNext; + VkFormat format; + VkImageType type; + VkImageTiling tiling; + VkImageUsageFlags usage; + VkImageCreateFlags flags; +} VkPhysicalDeviceImageFormatInfo2; + +typedef struct VkQueueFamilyProperties2 { + VkStructureType sType; + void* pNext; + VkQueueFamilyProperties queueFamilyProperties; +} VkQueueFamilyProperties2; + +typedef struct VkPhysicalDeviceMemoryProperties2 { + VkStructureType sType; + void* pNext; + VkPhysicalDeviceMemoryProperties memoryProperties; +} VkPhysicalDeviceMemoryProperties2; + +typedef struct VkSparseImageFormatProperties2 { + VkStructureType sType; + void* pNext; + VkSparseImageFormatProperties properties; +} VkSparseImageFormatProperties2; + +typedef struct VkPhysicalDeviceSparseImageFormatInfo2 { + VkStructureType sType; + const void* pNext; + VkFormat format; + VkImageType type; + VkSampleCountFlagBits samples; + VkImageUsageFlags usage; + VkImageTiling tiling; +} VkPhysicalDeviceSparseImageFormatInfo2; + +typedef struct VkPhysicalDevicePointClippingProperties { + VkStructureType sType; + void* pNext; + VkPointClippingBehavior pointClippingBehavior; +} VkPhysicalDevicePointClippingProperties; + +typedef struct VkInputAttachmentAspectReference { + uint32_t subpass; + uint32_t inputAttachmentIndex; + VkImageAspectFlags aspectMask; +} VkInputAttachmentAspectReference; + +typedef struct VkRenderPassInputAttachmentAspectCreateInfo { + VkStructureType sType; + const void* pNext; + uint32_t aspectReferenceCount; + const VkInputAttachmentAspectReference* pAspectReferences; +} VkRenderPassInputAttachmentAspectCreateInfo; + +typedef struct VkImageViewUsageCreateInfo { + VkStructureType sType; + const void* pNext; + VkImageUsageFlags usage; +} VkImageViewUsageCreateInfo; + +typedef struct VkPipelineTessellationDomainOriginStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkTessellationDomainOrigin domainOrigin; +} VkPipelineTessellationDomainOriginStateCreateInfo; + +typedef struct VkRenderPassMultiviewCreateInfo { + VkStructureType sType; + const void* pNext; + uint32_t subpassCount; + const uint32_t* pViewMasks; + uint32_t dependencyCount; + const int32_t* pViewOffsets; + uint32_t correlationMaskCount; + const uint32_t* pCorrelationMasks; +} VkRenderPassMultiviewCreateInfo; + +typedef struct VkPhysicalDeviceMultiviewFeatures { + VkStructureType sType; + void* pNext; + VkBool32 multiview; + VkBool32 multiviewGeometryShader; + VkBool32 multiviewTessellationShader; +} VkPhysicalDeviceMultiviewFeatures; + +typedef struct VkPhysicalDeviceMultiviewProperties { + VkStructureType sType; + void* pNext; + uint32_t maxMultiviewViewCount; + uint32_t maxMultiviewInstanceIndex; +} VkPhysicalDeviceMultiviewProperties; + +typedef struct VkPhysicalDeviceVariablePointersFeatures { + VkStructureType sType; + void* pNext; + VkBool32 variablePointersStorageBuffer; + VkBool32 variablePointers; +} VkPhysicalDeviceVariablePointersFeatures; + +typedef VkPhysicalDeviceVariablePointersFeatures VkPhysicalDeviceVariablePointerFeatures; + +typedef struct VkPhysicalDeviceProtectedMemoryFeatures { + VkStructureType sType; + void* pNext; + VkBool32 protectedMemory; +} VkPhysicalDeviceProtectedMemoryFeatures; + +typedef struct VkPhysicalDeviceProtectedMemoryProperties { + VkStructureType sType; + void* pNext; + VkBool32 protectedNoFault; +} VkPhysicalDeviceProtectedMemoryProperties; + +typedef struct VkDeviceQueueInfo2 { + VkStructureType sType; + const void* pNext; + VkDeviceQueueCreateFlags flags; + uint32_t queueFamilyIndex; + uint32_t queueIndex; +} VkDeviceQueueInfo2; + +typedef struct VkProtectedSubmitInfo { + VkStructureType sType; + const void* pNext; + VkBool32 protectedSubmit; +} VkProtectedSubmitInfo; + +typedef struct VkSamplerYcbcrConversionCreateInfo { + VkStructureType sType; + const void* pNext; + VkFormat format; + VkSamplerYcbcrModelConversion ycbcrModel; + VkSamplerYcbcrRange ycbcrRange; + VkComponentMapping components; + VkChromaLocation xChromaOffset; + VkChromaLocation yChromaOffset; + VkFilter chromaFilter; + VkBool32 forceExplicitReconstruction; +} VkSamplerYcbcrConversionCreateInfo; + +typedef struct VkSamplerYcbcrConversionInfo { + VkStructureType sType; + const void* pNext; + VkSamplerYcbcrConversion conversion; +} VkSamplerYcbcrConversionInfo; + +typedef struct VkBindImagePlaneMemoryInfo { + VkStructureType sType; + const void* pNext; + VkImageAspectFlagBits planeAspect; +} VkBindImagePlaneMemoryInfo; + +typedef struct VkImagePlaneMemoryRequirementsInfo { + VkStructureType sType; + const void* pNext; + VkImageAspectFlagBits planeAspect; +} VkImagePlaneMemoryRequirementsInfo; + +typedef struct VkPhysicalDeviceSamplerYcbcrConversionFeatures { + VkStructureType sType; + void* pNext; + VkBool32 samplerYcbcrConversion; +} VkPhysicalDeviceSamplerYcbcrConversionFeatures; + +typedef struct VkSamplerYcbcrConversionImageFormatProperties { + VkStructureType sType; + void* pNext; + uint32_t combinedImageSamplerDescriptorCount; +} VkSamplerYcbcrConversionImageFormatProperties; + +typedef struct VkDescriptorUpdateTemplateEntry { + uint32_t dstBinding; + uint32_t dstArrayElement; + uint32_t descriptorCount; + VkDescriptorType descriptorType; + size_t offset; + size_t stride; +} VkDescriptorUpdateTemplateEntry; + +typedef struct VkDescriptorUpdateTemplateCreateInfo { + VkStructureType sType; + const void* pNext; + VkDescriptorUpdateTemplateCreateFlags flags; + uint32_t descriptorUpdateEntryCount; + const VkDescriptorUpdateTemplateEntry* pDescriptorUpdateEntries; + VkDescriptorUpdateTemplateType templateType; + VkDescriptorSetLayout descriptorSetLayout; + VkPipelineBindPoint pipelineBindPoint; + VkPipelineLayout pipelineLayout; + uint32_t set; +} VkDescriptorUpdateTemplateCreateInfo; + +typedef struct VkExternalMemoryProperties { + VkExternalMemoryFeatureFlags externalMemoryFeatures; + VkExternalMemoryHandleTypeFlags exportFromImportedHandleTypes; + VkExternalMemoryHandleTypeFlags compatibleHandleTypes; +} VkExternalMemoryProperties; + +typedef struct VkPhysicalDeviceExternalImageFormatInfo { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlagBits handleType; +} VkPhysicalDeviceExternalImageFormatInfo; + +typedef struct VkExternalImageFormatProperties { + VkStructureType sType; + void* pNext; + VkExternalMemoryProperties externalMemoryProperties; +} VkExternalImageFormatProperties; + +typedef struct VkPhysicalDeviceExternalBufferInfo { + VkStructureType sType; + const void* pNext; + VkBufferCreateFlags flags; + VkBufferUsageFlags usage; + VkExternalMemoryHandleTypeFlagBits handleType; +} VkPhysicalDeviceExternalBufferInfo; + +typedef struct VkExternalBufferProperties { + VkStructureType sType; + void* pNext; + VkExternalMemoryProperties externalMemoryProperties; +} VkExternalBufferProperties; + +typedef struct VkPhysicalDeviceIDProperties { + VkStructureType sType; + void* pNext; + uint8_t deviceUUID[VK_UUID_SIZE]; + uint8_t driverUUID[VK_UUID_SIZE]; + uint8_t deviceLUID[VK_LUID_SIZE]; + uint32_t deviceNodeMask; + VkBool32 deviceLUIDValid; +} VkPhysicalDeviceIDProperties; + +typedef struct VkExternalMemoryImageCreateInfo { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlags handleTypes; +} VkExternalMemoryImageCreateInfo; + +typedef struct VkExternalMemoryBufferCreateInfo { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlags handleTypes; +} VkExternalMemoryBufferCreateInfo; + +typedef struct VkExportMemoryAllocateInfo { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlags handleTypes; +} VkExportMemoryAllocateInfo; + +typedef struct VkPhysicalDeviceExternalFenceInfo { + VkStructureType sType; + const void* pNext; + VkExternalFenceHandleTypeFlagBits handleType; +} VkPhysicalDeviceExternalFenceInfo; + +typedef struct VkExternalFenceProperties { + VkStructureType sType; + void* pNext; + VkExternalFenceHandleTypeFlags exportFromImportedHandleTypes; + VkExternalFenceHandleTypeFlags compatibleHandleTypes; + VkExternalFenceFeatureFlags externalFenceFeatures; +} VkExternalFenceProperties; + +typedef struct VkExportFenceCreateInfo { + VkStructureType sType; + const void* pNext; + VkExternalFenceHandleTypeFlags handleTypes; +} VkExportFenceCreateInfo; + +typedef struct VkExportSemaphoreCreateInfo { + VkStructureType sType; + const void* pNext; + VkExternalSemaphoreHandleTypeFlags handleTypes; +} VkExportSemaphoreCreateInfo; + +typedef struct VkPhysicalDeviceExternalSemaphoreInfo { + VkStructureType sType; + const void* pNext; + VkExternalSemaphoreHandleTypeFlagBits handleType; +} VkPhysicalDeviceExternalSemaphoreInfo; + +typedef struct VkExternalSemaphoreProperties { + VkStructureType sType; + void* pNext; + VkExternalSemaphoreHandleTypeFlags exportFromImportedHandleTypes; + VkExternalSemaphoreHandleTypeFlags compatibleHandleTypes; + VkExternalSemaphoreFeatureFlags externalSemaphoreFeatures; +} VkExternalSemaphoreProperties; + +typedef struct VkPhysicalDeviceMaintenance3Properties { + VkStructureType sType; + void* pNext; + uint32_t maxPerSetDescriptors; + VkDeviceSize maxMemoryAllocationSize; +} VkPhysicalDeviceMaintenance3Properties; + +typedef struct VkDescriptorSetLayoutSupport { + VkStructureType sType; + void* pNext; + VkBool32 supported; +} VkDescriptorSetLayoutSupport; + +typedef struct VkPhysicalDeviceShaderDrawParametersFeatures { + VkStructureType sType; + void* pNext; + VkBool32 shaderDrawParameters; +} VkPhysicalDeviceShaderDrawParametersFeatures; + +typedef VkPhysicalDeviceShaderDrawParametersFeatures VkPhysicalDeviceShaderDrawParameterFeatures; + +typedef VkResult (VKAPI_PTR *PFN_vkEnumerateInstanceVersion)(uint32_t* pApiVersion); +typedef VkResult (VKAPI_PTR *PFN_vkBindBufferMemory2)(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos); +typedef VkResult (VKAPI_PTR *PFN_vkBindImageMemory2)(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos); +typedef void (VKAPI_PTR *PFN_vkGetDeviceGroupPeerMemoryFeatures)(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures); +typedef void (VKAPI_PTR *PFN_vkCmdSetDeviceMask)(VkCommandBuffer commandBuffer, uint32_t deviceMask); +typedef void (VKAPI_PTR *PFN_vkCmdDispatchBase)(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ); +typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDeviceGroups)(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties); +typedef void (VKAPI_PTR *PFN_vkGetImageMemoryRequirements2)(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetBufferMemoryRequirements2)(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetImageSparseMemoryRequirements2)(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFeatures2)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceProperties2)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFormatProperties2)(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceImageFormatProperties2)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyProperties2)(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMemoryProperties2)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties2)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties); +typedef void (VKAPI_PTR *PFN_vkTrimCommandPool)(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags); +typedef void (VKAPI_PTR *PFN_vkGetDeviceQueue2)(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue); +typedef VkResult (VKAPI_PTR *PFN_vkCreateSamplerYcbcrConversion)(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion); +typedef void (VKAPI_PTR *PFN_vkDestroySamplerYcbcrConversion)(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreateDescriptorUpdateTemplate)(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate); +typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorUpdateTemplate)(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkUpdateDescriptorSetWithTemplate)(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalBufferProperties)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalFenceProperties)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalSemaphoreProperties)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties); +typedef void (VKAPI_PTR *PFN_vkGetDescriptorSetLayoutSupport)(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceVersion( + uint32_t* pApiVersion); + +VKAPI_ATTR VkResult VKAPI_CALL vkBindBufferMemory2( + VkDevice device, + uint32_t bindInfoCount, + const VkBindBufferMemoryInfo* pBindInfos); + +VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory2( + VkDevice device, + uint32_t bindInfoCount, + const VkBindImageMemoryInfo* pBindInfos); + +VKAPI_ATTR void VKAPI_CALL vkGetDeviceGroupPeerMemoryFeatures( + VkDevice device, + uint32_t heapIndex, + uint32_t localDeviceIndex, + uint32_t remoteDeviceIndex, + VkPeerMemoryFeatureFlags* pPeerMemoryFeatures); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDeviceMask( + VkCommandBuffer commandBuffer, + uint32_t deviceMask); + +VKAPI_ATTR void VKAPI_CALL vkCmdDispatchBase( + VkCommandBuffer commandBuffer, + uint32_t baseGroupX, + uint32_t baseGroupY, + uint32_t baseGroupZ, + uint32_t groupCountX, + uint32_t groupCountY, + uint32_t groupCountZ); + +VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceGroups( + VkInstance instance, + uint32_t* pPhysicalDeviceGroupCount, + VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetImageMemoryRequirements2( + VkDevice device, + const VkImageMemoryRequirementsInfo2* pInfo, + VkMemoryRequirements2* pMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkGetBufferMemoryRequirements2( + VkDevice device, + const VkBufferMemoryRequirementsInfo2* pInfo, + VkMemoryRequirements2* pMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkGetImageSparseMemoryRequirements2( + VkDevice device, + const VkImageSparseMemoryRequirementsInfo2* pInfo, + uint32_t* pSparseMemoryRequirementCount, + VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures2( + VkPhysicalDevice physicalDevice, + VkPhysicalDeviceFeatures2* pFeatures); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties2( + VkPhysicalDevice physicalDevice, + VkPhysicalDeviceProperties2* pProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFormatProperties2( + VkPhysicalDevice physicalDevice, + VkFormat format, + VkFormatProperties2* pFormatProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties2( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, + VkImageFormatProperties2* pImageFormatProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties2( + VkPhysicalDevice physicalDevice, + uint32_t* pQueueFamilyPropertyCount, + VkQueueFamilyProperties2* pQueueFamilyProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties2( + VkPhysicalDevice physicalDevice, + VkPhysicalDeviceMemoryProperties2* pMemoryProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties2( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, + uint32_t* pPropertyCount, + VkSparseImageFormatProperties2* pProperties); + +VKAPI_ATTR void VKAPI_CALL vkTrimCommandPool( + VkDevice device, + VkCommandPool commandPool, + VkCommandPoolTrimFlags flags); + +VKAPI_ATTR void VKAPI_CALL vkGetDeviceQueue2( + VkDevice device, + const VkDeviceQueueInfo2* pQueueInfo, + VkQueue* pQueue); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateSamplerYcbcrConversion( + VkDevice device, + const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSamplerYcbcrConversion* pYcbcrConversion); + +VKAPI_ATTR void VKAPI_CALL vkDestroySamplerYcbcrConversion( + VkDevice device, + VkSamplerYcbcrConversion ycbcrConversion, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorUpdateTemplate( + VkDevice device, + const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate); + +VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorUpdateTemplate( + VkDevice device, + VkDescriptorUpdateTemplate descriptorUpdateTemplate, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR void VKAPI_CALL vkUpdateDescriptorSetWithTemplate( + VkDevice device, + VkDescriptorSet descriptorSet, + VkDescriptorUpdateTemplate descriptorUpdateTemplate, + const void* pData); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalBufferProperties( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, + VkExternalBufferProperties* pExternalBufferProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalFenceProperties( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, + VkExternalFenceProperties* pExternalFenceProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalSemaphoreProperties( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, + VkExternalSemaphoreProperties* pExternalSemaphoreProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutSupport( + VkDevice device, + const VkDescriptorSetLayoutCreateInfo* pCreateInfo, + VkDescriptorSetLayoutSupport* pSupport); +#endif + + +#define VK_VERSION_1_2 1 +// Vulkan 1.2 version number +#define VK_API_VERSION_1_2 VK_MAKE_API_VERSION(0, 1, 2, 0)// Patch version should always be set to 0 + +#define VK_MAX_DRIVER_NAME_SIZE 256U +#define VK_MAX_DRIVER_INFO_SIZE 256U + +typedef enum VkDriverId { + VK_DRIVER_ID_AMD_PROPRIETARY = 1, + VK_DRIVER_ID_AMD_OPEN_SOURCE = 2, + VK_DRIVER_ID_MESA_RADV = 3, + VK_DRIVER_ID_NVIDIA_PROPRIETARY = 4, + VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS = 5, + VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA = 6, + VK_DRIVER_ID_IMAGINATION_PROPRIETARY = 7, + VK_DRIVER_ID_QUALCOMM_PROPRIETARY = 8, + VK_DRIVER_ID_ARM_PROPRIETARY = 9, + VK_DRIVER_ID_GOOGLE_SWIFTSHADER = 10, + VK_DRIVER_ID_GGP_PROPRIETARY = 11, + VK_DRIVER_ID_BROADCOM_PROPRIETARY = 12, + VK_DRIVER_ID_MESA_LLVMPIPE = 13, + VK_DRIVER_ID_MOLTENVK = 14, + VK_DRIVER_ID_COREAVI_PROPRIETARY = 15, + VK_DRIVER_ID_JUICE_PROPRIETARY = 16, + VK_DRIVER_ID_VERISILICON_PROPRIETARY = 17, + VK_DRIVER_ID_MESA_TURNIP = 18, + VK_DRIVER_ID_MESA_V3DV = 19, + VK_DRIVER_ID_MESA_PANVK = 20, + VK_DRIVER_ID_SAMSUNG_PROPRIETARY = 21, + VK_DRIVER_ID_MESA_VENUS = 22, + VK_DRIVER_ID_AMD_PROPRIETARY_KHR = VK_DRIVER_ID_AMD_PROPRIETARY, + VK_DRIVER_ID_AMD_OPEN_SOURCE_KHR = VK_DRIVER_ID_AMD_OPEN_SOURCE, + VK_DRIVER_ID_MESA_RADV_KHR = VK_DRIVER_ID_MESA_RADV, + VK_DRIVER_ID_NVIDIA_PROPRIETARY_KHR = VK_DRIVER_ID_NVIDIA_PROPRIETARY, + VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS_KHR = VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS, + VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA_KHR = VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA, + VK_DRIVER_ID_IMAGINATION_PROPRIETARY_KHR = VK_DRIVER_ID_IMAGINATION_PROPRIETARY, + VK_DRIVER_ID_QUALCOMM_PROPRIETARY_KHR = VK_DRIVER_ID_QUALCOMM_PROPRIETARY, + VK_DRIVER_ID_ARM_PROPRIETARY_KHR = VK_DRIVER_ID_ARM_PROPRIETARY, + VK_DRIVER_ID_GOOGLE_SWIFTSHADER_KHR = VK_DRIVER_ID_GOOGLE_SWIFTSHADER, + VK_DRIVER_ID_GGP_PROPRIETARY_KHR = VK_DRIVER_ID_GGP_PROPRIETARY, + VK_DRIVER_ID_BROADCOM_PROPRIETARY_KHR = VK_DRIVER_ID_BROADCOM_PROPRIETARY, + VK_DRIVER_ID_MAX_ENUM = 0x7FFFFFFF +} VkDriverId; + +typedef enum VkShaderFloatControlsIndependence { + VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY = 0, + VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL = 1, + VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE = 2, + VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY_KHR = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY, + VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL_KHR = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL, + VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE_KHR = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE, + VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_MAX_ENUM = 0x7FFFFFFF +} VkShaderFloatControlsIndependence; + +typedef enum VkSamplerReductionMode { + VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE = 0, + VK_SAMPLER_REDUCTION_MODE_MIN = 1, + VK_SAMPLER_REDUCTION_MODE_MAX = 2, + VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT = VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE, + VK_SAMPLER_REDUCTION_MODE_MIN_EXT = VK_SAMPLER_REDUCTION_MODE_MIN, + VK_SAMPLER_REDUCTION_MODE_MAX_EXT = VK_SAMPLER_REDUCTION_MODE_MAX, + VK_SAMPLER_REDUCTION_MODE_MAX_ENUM = 0x7FFFFFFF +} VkSamplerReductionMode; + +typedef enum VkSemaphoreType { + VK_SEMAPHORE_TYPE_BINARY = 0, + VK_SEMAPHORE_TYPE_TIMELINE = 1, + VK_SEMAPHORE_TYPE_BINARY_KHR = VK_SEMAPHORE_TYPE_BINARY, + VK_SEMAPHORE_TYPE_TIMELINE_KHR = VK_SEMAPHORE_TYPE_TIMELINE, + VK_SEMAPHORE_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkSemaphoreType; + +typedef enum VkResolveModeFlagBits { + VK_RESOLVE_MODE_NONE = 0, + VK_RESOLVE_MODE_SAMPLE_ZERO_BIT = 0x00000001, + VK_RESOLVE_MODE_AVERAGE_BIT = 0x00000002, + VK_RESOLVE_MODE_MIN_BIT = 0x00000004, + VK_RESOLVE_MODE_MAX_BIT = 0x00000008, + VK_RESOLVE_MODE_NONE_KHR = VK_RESOLVE_MODE_NONE, + VK_RESOLVE_MODE_SAMPLE_ZERO_BIT_KHR = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT, + VK_RESOLVE_MODE_AVERAGE_BIT_KHR = VK_RESOLVE_MODE_AVERAGE_BIT, + VK_RESOLVE_MODE_MIN_BIT_KHR = VK_RESOLVE_MODE_MIN_BIT, + VK_RESOLVE_MODE_MAX_BIT_KHR = VK_RESOLVE_MODE_MAX_BIT, + VK_RESOLVE_MODE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkResolveModeFlagBits; +typedef VkFlags VkResolveModeFlags; + +typedef enum VkDescriptorBindingFlagBits { + VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT = 0x00000001, + VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT = 0x00000002, + VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT = 0x00000004, + VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT = 0x00000008, + VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT = VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT, + VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT = VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT, + VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT = VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT, + VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT = VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT, + VK_DESCRIPTOR_BINDING_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkDescriptorBindingFlagBits; +typedef VkFlags VkDescriptorBindingFlags; + +typedef enum VkSemaphoreWaitFlagBits { + VK_SEMAPHORE_WAIT_ANY_BIT = 0x00000001, + VK_SEMAPHORE_WAIT_ANY_BIT_KHR = VK_SEMAPHORE_WAIT_ANY_BIT, + VK_SEMAPHORE_WAIT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkSemaphoreWaitFlagBits; +typedef VkFlags VkSemaphoreWaitFlags; +typedef struct VkPhysicalDeviceVulkan11Features { + VkStructureType sType; + void* pNext; + VkBool32 storageBuffer16BitAccess; + VkBool32 uniformAndStorageBuffer16BitAccess; + VkBool32 storagePushConstant16; + VkBool32 storageInputOutput16; + VkBool32 multiview; + VkBool32 multiviewGeometryShader; + VkBool32 multiviewTessellationShader; + VkBool32 variablePointersStorageBuffer; + VkBool32 variablePointers; + VkBool32 protectedMemory; + VkBool32 samplerYcbcrConversion; + VkBool32 shaderDrawParameters; +} VkPhysicalDeviceVulkan11Features; + +typedef struct VkPhysicalDeviceVulkan11Properties { + VkStructureType sType; + void* pNext; + uint8_t deviceUUID[VK_UUID_SIZE]; + uint8_t driverUUID[VK_UUID_SIZE]; + uint8_t deviceLUID[VK_LUID_SIZE]; + uint32_t deviceNodeMask; + VkBool32 deviceLUIDValid; + uint32_t subgroupSize; + VkShaderStageFlags subgroupSupportedStages; + VkSubgroupFeatureFlags subgroupSupportedOperations; + VkBool32 subgroupQuadOperationsInAllStages; + VkPointClippingBehavior pointClippingBehavior; + uint32_t maxMultiviewViewCount; + uint32_t maxMultiviewInstanceIndex; + VkBool32 protectedNoFault; + uint32_t maxPerSetDescriptors; + VkDeviceSize maxMemoryAllocationSize; +} VkPhysicalDeviceVulkan11Properties; + +typedef struct VkPhysicalDeviceVulkan12Features { + VkStructureType sType; + void* pNext; + VkBool32 samplerMirrorClampToEdge; + VkBool32 drawIndirectCount; + VkBool32 storageBuffer8BitAccess; + VkBool32 uniformAndStorageBuffer8BitAccess; + VkBool32 storagePushConstant8; + VkBool32 shaderBufferInt64Atomics; + VkBool32 shaderSharedInt64Atomics; + VkBool32 shaderFloat16; + VkBool32 shaderInt8; + VkBool32 descriptorIndexing; + VkBool32 shaderInputAttachmentArrayDynamicIndexing; + VkBool32 shaderUniformTexelBufferArrayDynamicIndexing; + VkBool32 shaderStorageTexelBufferArrayDynamicIndexing; + VkBool32 shaderUniformBufferArrayNonUniformIndexing; + VkBool32 shaderSampledImageArrayNonUniformIndexing; + VkBool32 shaderStorageBufferArrayNonUniformIndexing; + VkBool32 shaderStorageImageArrayNonUniformIndexing; + VkBool32 shaderInputAttachmentArrayNonUniformIndexing; + VkBool32 shaderUniformTexelBufferArrayNonUniformIndexing; + VkBool32 shaderStorageTexelBufferArrayNonUniformIndexing; + VkBool32 descriptorBindingUniformBufferUpdateAfterBind; + VkBool32 descriptorBindingSampledImageUpdateAfterBind; + VkBool32 descriptorBindingStorageImageUpdateAfterBind; + VkBool32 descriptorBindingStorageBufferUpdateAfterBind; + VkBool32 descriptorBindingUniformTexelBufferUpdateAfterBind; + VkBool32 descriptorBindingStorageTexelBufferUpdateAfterBind; + VkBool32 descriptorBindingUpdateUnusedWhilePending; + VkBool32 descriptorBindingPartiallyBound; + VkBool32 descriptorBindingVariableDescriptorCount; + VkBool32 runtimeDescriptorArray; + VkBool32 samplerFilterMinmax; + VkBool32 scalarBlockLayout; + VkBool32 imagelessFramebuffer; + VkBool32 uniformBufferStandardLayout; + VkBool32 shaderSubgroupExtendedTypes; + VkBool32 separateDepthStencilLayouts; + VkBool32 hostQueryReset; + VkBool32 timelineSemaphore; + VkBool32 bufferDeviceAddress; + VkBool32 bufferDeviceAddressCaptureReplay; + VkBool32 bufferDeviceAddressMultiDevice; + VkBool32 vulkanMemoryModel; + VkBool32 vulkanMemoryModelDeviceScope; + VkBool32 vulkanMemoryModelAvailabilityVisibilityChains; + VkBool32 shaderOutputViewportIndex; + VkBool32 shaderOutputLayer; + VkBool32 subgroupBroadcastDynamicId; +} VkPhysicalDeviceVulkan12Features; + +typedef struct VkConformanceVersion { + uint8_t major; + uint8_t minor; + uint8_t subminor; + uint8_t patch; +} VkConformanceVersion; + +typedef struct VkPhysicalDeviceVulkan12Properties { + VkStructureType sType; + void* pNext; + VkDriverId driverID; + char driverName[VK_MAX_DRIVER_NAME_SIZE]; + char driverInfo[VK_MAX_DRIVER_INFO_SIZE]; + VkConformanceVersion conformanceVersion; + VkShaderFloatControlsIndependence denormBehaviorIndependence; + VkShaderFloatControlsIndependence roundingModeIndependence; + VkBool32 shaderSignedZeroInfNanPreserveFloat16; + VkBool32 shaderSignedZeroInfNanPreserveFloat32; + VkBool32 shaderSignedZeroInfNanPreserveFloat64; + VkBool32 shaderDenormPreserveFloat16; + VkBool32 shaderDenormPreserveFloat32; + VkBool32 shaderDenormPreserveFloat64; + VkBool32 shaderDenormFlushToZeroFloat16; + VkBool32 shaderDenormFlushToZeroFloat32; + VkBool32 shaderDenormFlushToZeroFloat64; + VkBool32 shaderRoundingModeRTEFloat16; + VkBool32 shaderRoundingModeRTEFloat32; + VkBool32 shaderRoundingModeRTEFloat64; + VkBool32 shaderRoundingModeRTZFloat16; + VkBool32 shaderRoundingModeRTZFloat32; + VkBool32 shaderRoundingModeRTZFloat64; + uint32_t maxUpdateAfterBindDescriptorsInAllPools; + VkBool32 shaderUniformBufferArrayNonUniformIndexingNative; + VkBool32 shaderSampledImageArrayNonUniformIndexingNative; + VkBool32 shaderStorageBufferArrayNonUniformIndexingNative; + VkBool32 shaderStorageImageArrayNonUniformIndexingNative; + VkBool32 shaderInputAttachmentArrayNonUniformIndexingNative; + VkBool32 robustBufferAccessUpdateAfterBind; + VkBool32 quadDivergentImplicitLod; + uint32_t maxPerStageDescriptorUpdateAfterBindSamplers; + uint32_t maxPerStageDescriptorUpdateAfterBindUniformBuffers; + uint32_t maxPerStageDescriptorUpdateAfterBindStorageBuffers; + uint32_t maxPerStageDescriptorUpdateAfterBindSampledImages; + uint32_t maxPerStageDescriptorUpdateAfterBindStorageImages; + uint32_t maxPerStageDescriptorUpdateAfterBindInputAttachments; + uint32_t maxPerStageUpdateAfterBindResources; + uint32_t maxDescriptorSetUpdateAfterBindSamplers; + uint32_t maxDescriptorSetUpdateAfterBindUniformBuffers; + uint32_t maxDescriptorSetUpdateAfterBindUniformBuffersDynamic; + uint32_t maxDescriptorSetUpdateAfterBindStorageBuffers; + uint32_t maxDescriptorSetUpdateAfterBindStorageBuffersDynamic; + uint32_t maxDescriptorSetUpdateAfterBindSampledImages; + uint32_t maxDescriptorSetUpdateAfterBindStorageImages; + uint32_t maxDescriptorSetUpdateAfterBindInputAttachments; + VkResolveModeFlags supportedDepthResolveModes; + VkResolveModeFlags supportedStencilResolveModes; + VkBool32 independentResolveNone; + VkBool32 independentResolve; + VkBool32 filterMinmaxSingleComponentFormats; + VkBool32 filterMinmaxImageComponentMapping; + uint64_t maxTimelineSemaphoreValueDifference; + VkSampleCountFlags framebufferIntegerColorSampleCounts; +} VkPhysicalDeviceVulkan12Properties; + +typedef struct VkImageFormatListCreateInfo { + VkStructureType sType; + const void* pNext; + uint32_t viewFormatCount; + const VkFormat* pViewFormats; +} VkImageFormatListCreateInfo; + +typedef struct VkAttachmentDescription2 { + VkStructureType sType; + const void* pNext; + VkAttachmentDescriptionFlags flags; + VkFormat format; + VkSampleCountFlagBits samples; + VkAttachmentLoadOp loadOp; + VkAttachmentStoreOp storeOp; + VkAttachmentLoadOp stencilLoadOp; + VkAttachmentStoreOp stencilStoreOp; + VkImageLayout initialLayout; + VkImageLayout finalLayout; +} VkAttachmentDescription2; + +typedef struct VkAttachmentReference2 { + VkStructureType sType; + const void* pNext; + uint32_t attachment; + VkImageLayout layout; + VkImageAspectFlags aspectMask; +} VkAttachmentReference2; + +typedef struct VkSubpassDescription2 { + VkStructureType sType; + const void* pNext; + VkSubpassDescriptionFlags flags; + VkPipelineBindPoint pipelineBindPoint; + uint32_t viewMask; + uint32_t inputAttachmentCount; + const VkAttachmentReference2* pInputAttachments; + uint32_t colorAttachmentCount; + const VkAttachmentReference2* pColorAttachments; + const VkAttachmentReference2* pResolveAttachments; + const VkAttachmentReference2* pDepthStencilAttachment; + uint32_t preserveAttachmentCount; + const uint32_t* pPreserveAttachments; +} VkSubpassDescription2; + +typedef struct VkSubpassDependency2 { + VkStructureType sType; + const void* pNext; + uint32_t srcSubpass; + uint32_t dstSubpass; + VkPipelineStageFlags srcStageMask; + VkPipelineStageFlags dstStageMask; + VkAccessFlags srcAccessMask; + VkAccessFlags dstAccessMask; + VkDependencyFlags dependencyFlags; + int32_t viewOffset; +} VkSubpassDependency2; + +typedef struct VkRenderPassCreateInfo2 { + VkStructureType sType; + const void* pNext; + VkRenderPassCreateFlags flags; + uint32_t attachmentCount; + const VkAttachmentDescription2* pAttachments; + uint32_t subpassCount; + const VkSubpassDescription2* pSubpasses; + uint32_t dependencyCount; + const VkSubpassDependency2* pDependencies; + uint32_t correlatedViewMaskCount; + const uint32_t* pCorrelatedViewMasks; +} VkRenderPassCreateInfo2; + +typedef struct VkSubpassBeginInfo { + VkStructureType sType; + const void* pNext; + VkSubpassContents contents; +} VkSubpassBeginInfo; + +typedef struct VkSubpassEndInfo { + VkStructureType sType; + const void* pNext; +} VkSubpassEndInfo; + +typedef struct VkPhysicalDevice8BitStorageFeatures { + VkStructureType sType; + void* pNext; + VkBool32 storageBuffer8BitAccess; + VkBool32 uniformAndStorageBuffer8BitAccess; + VkBool32 storagePushConstant8; +} VkPhysicalDevice8BitStorageFeatures; + +typedef struct VkPhysicalDeviceDriverProperties { + VkStructureType sType; + void* pNext; + VkDriverId driverID; + char driverName[VK_MAX_DRIVER_NAME_SIZE]; + char driverInfo[VK_MAX_DRIVER_INFO_SIZE]; + VkConformanceVersion conformanceVersion; +} VkPhysicalDeviceDriverProperties; + +typedef struct VkPhysicalDeviceShaderAtomicInt64Features { + VkStructureType sType; + void* pNext; + VkBool32 shaderBufferInt64Atomics; + VkBool32 shaderSharedInt64Atomics; +} VkPhysicalDeviceShaderAtomicInt64Features; + +typedef struct VkPhysicalDeviceShaderFloat16Int8Features { + VkStructureType sType; + void* pNext; + VkBool32 shaderFloat16; + VkBool32 shaderInt8; +} VkPhysicalDeviceShaderFloat16Int8Features; + +typedef struct VkPhysicalDeviceFloatControlsProperties { + VkStructureType sType; + void* pNext; + VkShaderFloatControlsIndependence denormBehaviorIndependence; + VkShaderFloatControlsIndependence roundingModeIndependence; + VkBool32 shaderSignedZeroInfNanPreserveFloat16; + VkBool32 shaderSignedZeroInfNanPreserveFloat32; + VkBool32 shaderSignedZeroInfNanPreserveFloat64; + VkBool32 shaderDenormPreserveFloat16; + VkBool32 shaderDenormPreserveFloat32; + VkBool32 shaderDenormPreserveFloat64; + VkBool32 shaderDenormFlushToZeroFloat16; + VkBool32 shaderDenormFlushToZeroFloat32; + VkBool32 shaderDenormFlushToZeroFloat64; + VkBool32 shaderRoundingModeRTEFloat16; + VkBool32 shaderRoundingModeRTEFloat32; + VkBool32 shaderRoundingModeRTEFloat64; + VkBool32 shaderRoundingModeRTZFloat16; + VkBool32 shaderRoundingModeRTZFloat32; + VkBool32 shaderRoundingModeRTZFloat64; +} VkPhysicalDeviceFloatControlsProperties; + +typedef struct VkDescriptorSetLayoutBindingFlagsCreateInfo { + VkStructureType sType; + const void* pNext; + uint32_t bindingCount; + const VkDescriptorBindingFlags* pBindingFlags; +} VkDescriptorSetLayoutBindingFlagsCreateInfo; + +typedef struct VkPhysicalDeviceDescriptorIndexingFeatures { + VkStructureType sType; + void* pNext; + VkBool32 shaderInputAttachmentArrayDynamicIndexing; + VkBool32 shaderUniformTexelBufferArrayDynamicIndexing; + VkBool32 shaderStorageTexelBufferArrayDynamicIndexing; + VkBool32 shaderUniformBufferArrayNonUniformIndexing; + VkBool32 shaderSampledImageArrayNonUniformIndexing; + VkBool32 shaderStorageBufferArrayNonUniformIndexing; + VkBool32 shaderStorageImageArrayNonUniformIndexing; + VkBool32 shaderInputAttachmentArrayNonUniformIndexing; + VkBool32 shaderUniformTexelBufferArrayNonUniformIndexing; + VkBool32 shaderStorageTexelBufferArrayNonUniformIndexing; + VkBool32 descriptorBindingUniformBufferUpdateAfterBind; + VkBool32 descriptorBindingSampledImageUpdateAfterBind; + VkBool32 descriptorBindingStorageImageUpdateAfterBind; + VkBool32 descriptorBindingStorageBufferUpdateAfterBind; + VkBool32 descriptorBindingUniformTexelBufferUpdateAfterBind; + VkBool32 descriptorBindingStorageTexelBufferUpdateAfterBind; + VkBool32 descriptorBindingUpdateUnusedWhilePending; + VkBool32 descriptorBindingPartiallyBound; + VkBool32 descriptorBindingVariableDescriptorCount; + VkBool32 runtimeDescriptorArray; +} VkPhysicalDeviceDescriptorIndexingFeatures; + +typedef struct VkPhysicalDeviceDescriptorIndexingProperties { + VkStructureType sType; + void* pNext; + uint32_t maxUpdateAfterBindDescriptorsInAllPools; + VkBool32 shaderUniformBufferArrayNonUniformIndexingNative; + VkBool32 shaderSampledImageArrayNonUniformIndexingNative; + VkBool32 shaderStorageBufferArrayNonUniformIndexingNative; + VkBool32 shaderStorageImageArrayNonUniformIndexingNative; + VkBool32 shaderInputAttachmentArrayNonUniformIndexingNative; + VkBool32 robustBufferAccessUpdateAfterBind; + VkBool32 quadDivergentImplicitLod; + uint32_t maxPerStageDescriptorUpdateAfterBindSamplers; + uint32_t maxPerStageDescriptorUpdateAfterBindUniformBuffers; + uint32_t maxPerStageDescriptorUpdateAfterBindStorageBuffers; + uint32_t maxPerStageDescriptorUpdateAfterBindSampledImages; + uint32_t maxPerStageDescriptorUpdateAfterBindStorageImages; + uint32_t maxPerStageDescriptorUpdateAfterBindInputAttachments; + uint32_t maxPerStageUpdateAfterBindResources; + uint32_t maxDescriptorSetUpdateAfterBindSamplers; + uint32_t maxDescriptorSetUpdateAfterBindUniformBuffers; + uint32_t maxDescriptorSetUpdateAfterBindUniformBuffersDynamic; + uint32_t maxDescriptorSetUpdateAfterBindStorageBuffers; + uint32_t maxDescriptorSetUpdateAfterBindStorageBuffersDynamic; + uint32_t maxDescriptorSetUpdateAfterBindSampledImages; + uint32_t maxDescriptorSetUpdateAfterBindStorageImages; + uint32_t maxDescriptorSetUpdateAfterBindInputAttachments; +} VkPhysicalDeviceDescriptorIndexingProperties; + +typedef struct VkDescriptorSetVariableDescriptorCountAllocateInfo { + VkStructureType sType; + const void* pNext; + uint32_t descriptorSetCount; + const uint32_t* pDescriptorCounts; +} VkDescriptorSetVariableDescriptorCountAllocateInfo; + +typedef struct VkDescriptorSetVariableDescriptorCountLayoutSupport { + VkStructureType sType; + void* pNext; + uint32_t maxVariableDescriptorCount; +} VkDescriptorSetVariableDescriptorCountLayoutSupport; + +typedef struct VkSubpassDescriptionDepthStencilResolve { + VkStructureType sType; + const void* pNext; + VkResolveModeFlagBits depthResolveMode; + VkResolveModeFlagBits stencilResolveMode; + const VkAttachmentReference2* pDepthStencilResolveAttachment; +} VkSubpassDescriptionDepthStencilResolve; + +typedef struct VkPhysicalDeviceDepthStencilResolveProperties { + VkStructureType sType; + void* pNext; + VkResolveModeFlags supportedDepthResolveModes; + VkResolveModeFlags supportedStencilResolveModes; + VkBool32 independentResolveNone; + VkBool32 independentResolve; +} VkPhysicalDeviceDepthStencilResolveProperties; + +typedef struct VkPhysicalDeviceScalarBlockLayoutFeatures { + VkStructureType sType; + void* pNext; + VkBool32 scalarBlockLayout; +} VkPhysicalDeviceScalarBlockLayoutFeatures; + +typedef struct VkImageStencilUsageCreateInfo { + VkStructureType sType; + const void* pNext; + VkImageUsageFlags stencilUsage; +} VkImageStencilUsageCreateInfo; + +typedef struct VkSamplerReductionModeCreateInfo { + VkStructureType sType; + const void* pNext; + VkSamplerReductionMode reductionMode; +} VkSamplerReductionModeCreateInfo; + +typedef struct VkPhysicalDeviceSamplerFilterMinmaxProperties { + VkStructureType sType; + void* pNext; + VkBool32 filterMinmaxSingleComponentFormats; + VkBool32 filterMinmaxImageComponentMapping; +} VkPhysicalDeviceSamplerFilterMinmaxProperties; + +typedef struct VkPhysicalDeviceVulkanMemoryModelFeatures { + VkStructureType sType; + void* pNext; + VkBool32 vulkanMemoryModel; + VkBool32 vulkanMemoryModelDeviceScope; + VkBool32 vulkanMemoryModelAvailabilityVisibilityChains; +} VkPhysicalDeviceVulkanMemoryModelFeatures; + +typedef struct VkPhysicalDeviceImagelessFramebufferFeatures { + VkStructureType sType; + void* pNext; + VkBool32 imagelessFramebuffer; +} VkPhysicalDeviceImagelessFramebufferFeatures; + +typedef struct VkFramebufferAttachmentImageInfo { + VkStructureType sType; + const void* pNext; + VkImageCreateFlags flags; + VkImageUsageFlags usage; + uint32_t width; + uint32_t height; + uint32_t layerCount; + uint32_t viewFormatCount; + const VkFormat* pViewFormats; +} VkFramebufferAttachmentImageInfo; + +typedef struct VkFramebufferAttachmentsCreateInfo { + VkStructureType sType; + const void* pNext; + uint32_t attachmentImageInfoCount; + const VkFramebufferAttachmentImageInfo* pAttachmentImageInfos; +} VkFramebufferAttachmentsCreateInfo; + +typedef struct VkRenderPassAttachmentBeginInfo { + VkStructureType sType; + const void* pNext; + uint32_t attachmentCount; + const VkImageView* pAttachments; +} VkRenderPassAttachmentBeginInfo; + +typedef struct VkPhysicalDeviceUniformBufferStandardLayoutFeatures { + VkStructureType sType; + void* pNext; + VkBool32 uniformBufferStandardLayout; +} VkPhysicalDeviceUniformBufferStandardLayoutFeatures; + +typedef struct VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures { + VkStructureType sType; + void* pNext; + VkBool32 shaderSubgroupExtendedTypes; +} VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures; + +typedef struct VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures { + VkStructureType sType; + void* pNext; + VkBool32 separateDepthStencilLayouts; +} VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures; + +typedef struct VkAttachmentReferenceStencilLayout { + VkStructureType sType; + void* pNext; + VkImageLayout stencilLayout; +} VkAttachmentReferenceStencilLayout; + +typedef struct VkAttachmentDescriptionStencilLayout { + VkStructureType sType; + void* pNext; + VkImageLayout stencilInitialLayout; + VkImageLayout stencilFinalLayout; +} VkAttachmentDescriptionStencilLayout; + +typedef struct VkPhysicalDeviceHostQueryResetFeatures { + VkStructureType sType; + void* pNext; + VkBool32 hostQueryReset; +} VkPhysicalDeviceHostQueryResetFeatures; + +typedef struct VkPhysicalDeviceTimelineSemaphoreFeatures { + VkStructureType sType; + void* pNext; + VkBool32 timelineSemaphore; +} VkPhysicalDeviceTimelineSemaphoreFeatures; + +typedef struct VkPhysicalDeviceTimelineSemaphoreProperties { + VkStructureType sType; + void* pNext; + uint64_t maxTimelineSemaphoreValueDifference; +} VkPhysicalDeviceTimelineSemaphoreProperties; + +typedef struct VkSemaphoreTypeCreateInfo { + VkStructureType sType; + const void* pNext; + VkSemaphoreType semaphoreType; + uint64_t initialValue; +} VkSemaphoreTypeCreateInfo; + +typedef struct VkTimelineSemaphoreSubmitInfo { + VkStructureType sType; + const void* pNext; + uint32_t waitSemaphoreValueCount; + const uint64_t* pWaitSemaphoreValues; + uint32_t signalSemaphoreValueCount; + const uint64_t* pSignalSemaphoreValues; +} VkTimelineSemaphoreSubmitInfo; + +typedef struct VkSemaphoreWaitInfo { + VkStructureType sType; + const void* pNext; + VkSemaphoreWaitFlags flags; + uint32_t semaphoreCount; + const VkSemaphore* pSemaphores; + const uint64_t* pValues; +} VkSemaphoreWaitInfo; + +typedef struct VkSemaphoreSignalInfo { + VkStructureType sType; + const void* pNext; + VkSemaphore semaphore; + uint64_t value; +} VkSemaphoreSignalInfo; + +typedef struct VkPhysicalDeviceBufferDeviceAddressFeatures { + VkStructureType sType; + void* pNext; + VkBool32 bufferDeviceAddress; + VkBool32 bufferDeviceAddressCaptureReplay; + VkBool32 bufferDeviceAddressMultiDevice; +} VkPhysicalDeviceBufferDeviceAddressFeatures; + +typedef struct VkBufferDeviceAddressInfo { + VkStructureType sType; + const void* pNext; + VkBuffer buffer; +} VkBufferDeviceAddressInfo; + +typedef struct VkBufferOpaqueCaptureAddressCreateInfo { + VkStructureType sType; + const void* pNext; + uint64_t opaqueCaptureAddress; +} VkBufferOpaqueCaptureAddressCreateInfo; + +typedef struct VkMemoryOpaqueCaptureAddressAllocateInfo { + VkStructureType sType; + const void* pNext; + uint64_t opaqueCaptureAddress; +} VkMemoryOpaqueCaptureAddressAllocateInfo; + +typedef struct VkDeviceMemoryOpaqueCaptureAddressInfo { + VkStructureType sType; + const void* pNext; + VkDeviceMemory memory; +} VkDeviceMemoryOpaqueCaptureAddressInfo; + +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectCount)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirectCount)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); +typedef VkResult (VKAPI_PTR *PFN_vkCreateRenderPass2)(VkDevice device, const VkRenderPassCreateInfo2* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass); +typedef void (VKAPI_PTR *PFN_vkCmdBeginRenderPass2)(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, const VkSubpassBeginInfo* pSubpassBeginInfo); +typedef void (VKAPI_PTR *PFN_vkCmdNextSubpass2)(VkCommandBuffer commandBuffer, const VkSubpassBeginInfo* pSubpassBeginInfo, const VkSubpassEndInfo* pSubpassEndInfo); +typedef void (VKAPI_PTR *PFN_vkCmdEndRenderPass2)(VkCommandBuffer commandBuffer, const VkSubpassEndInfo* pSubpassEndInfo); +typedef void (VKAPI_PTR *PFN_vkResetQueryPool)(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount); +typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreCounterValue)(VkDevice device, VkSemaphore semaphore, uint64_t* pValue); +typedef VkResult (VKAPI_PTR *PFN_vkWaitSemaphores)(VkDevice device, const VkSemaphoreWaitInfo* pWaitInfo, uint64_t timeout); +typedef VkResult (VKAPI_PTR *PFN_vkSignalSemaphore)(VkDevice device, const VkSemaphoreSignalInfo* pSignalInfo); +typedef VkDeviceAddress (VKAPI_PTR *PFN_vkGetBufferDeviceAddress)(VkDevice device, const VkBufferDeviceAddressInfo* pInfo); +typedef uint64_t (VKAPI_PTR *PFN_vkGetBufferOpaqueCaptureAddress)(VkDevice device, const VkBufferDeviceAddressInfo* pInfo); +typedef uint64_t (VKAPI_PTR *PFN_vkGetDeviceMemoryOpaqueCaptureAddress)(VkDevice device, const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectCount( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkBuffer countBuffer, + VkDeviceSize countBufferOffset, + uint32_t maxDrawCount, + uint32_t stride); + +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCount( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkBuffer countBuffer, + VkDeviceSize countBufferOffset, + uint32_t maxDrawCount, + uint32_t stride); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateRenderPass2( + VkDevice device, + const VkRenderPassCreateInfo2* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkRenderPass* pRenderPass); + +VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderPass2( + VkCommandBuffer commandBuffer, + const VkRenderPassBeginInfo* pRenderPassBegin, + const VkSubpassBeginInfo* pSubpassBeginInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdNextSubpass2( + VkCommandBuffer commandBuffer, + const VkSubpassBeginInfo* pSubpassBeginInfo, + const VkSubpassEndInfo* pSubpassEndInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderPass2( + VkCommandBuffer commandBuffer, + const VkSubpassEndInfo* pSubpassEndInfo); + +VKAPI_ATTR void VKAPI_CALL vkResetQueryPool( + VkDevice device, + VkQueryPool queryPool, + uint32_t firstQuery, + uint32_t queryCount); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreCounterValue( + VkDevice device, + VkSemaphore semaphore, + uint64_t* pValue); + +VKAPI_ATTR VkResult VKAPI_CALL vkWaitSemaphores( + VkDevice device, + const VkSemaphoreWaitInfo* pWaitInfo, + uint64_t timeout); + +VKAPI_ATTR VkResult VKAPI_CALL vkSignalSemaphore( + VkDevice device, + const VkSemaphoreSignalInfo* pSignalInfo); + +VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetBufferDeviceAddress( + VkDevice device, + const VkBufferDeviceAddressInfo* pInfo); + +VKAPI_ATTR uint64_t VKAPI_CALL vkGetBufferOpaqueCaptureAddress( + VkDevice device, + const VkBufferDeviceAddressInfo* pInfo); + +VKAPI_ATTR uint64_t VKAPI_CALL vkGetDeviceMemoryOpaqueCaptureAddress( + VkDevice device, + const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo); +#endif + + +#define VK_VERSION_1_3 1 +// Vulkan 1.3 version number +#define VK_API_VERSION_1_3 VK_MAKE_API_VERSION(0, 1, 3, 0)// Patch version should always be set to 0 + +typedef uint64_t VkFlags64; +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPrivateDataSlot) + +typedef enum VkPipelineCreationFeedbackFlagBits { + VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT = 0x00000001, + VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT = 0x00000002, + VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT = 0x00000004, + VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT = VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT, + VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT = VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT, + VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT = VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT, + VK_PIPELINE_CREATION_FEEDBACK_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPipelineCreationFeedbackFlagBits; +typedef VkFlags VkPipelineCreationFeedbackFlags; + +typedef enum VkToolPurposeFlagBits { + VK_TOOL_PURPOSE_VALIDATION_BIT = 0x00000001, + VK_TOOL_PURPOSE_PROFILING_BIT = 0x00000002, + VK_TOOL_PURPOSE_TRACING_BIT = 0x00000004, + VK_TOOL_PURPOSE_ADDITIONAL_FEATURES_BIT = 0x00000008, + VK_TOOL_PURPOSE_MODIFYING_FEATURES_BIT = 0x00000010, + VK_TOOL_PURPOSE_DEBUG_REPORTING_BIT_EXT = 0x00000020, + VK_TOOL_PURPOSE_DEBUG_MARKERS_BIT_EXT = 0x00000040, + VK_TOOL_PURPOSE_VALIDATION_BIT_EXT = VK_TOOL_PURPOSE_VALIDATION_BIT, + VK_TOOL_PURPOSE_PROFILING_BIT_EXT = VK_TOOL_PURPOSE_PROFILING_BIT, + VK_TOOL_PURPOSE_TRACING_BIT_EXT = VK_TOOL_PURPOSE_TRACING_BIT, + VK_TOOL_PURPOSE_ADDITIONAL_FEATURES_BIT_EXT = VK_TOOL_PURPOSE_ADDITIONAL_FEATURES_BIT, + VK_TOOL_PURPOSE_MODIFYING_FEATURES_BIT_EXT = VK_TOOL_PURPOSE_MODIFYING_FEATURES_BIT, + VK_TOOL_PURPOSE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkToolPurposeFlagBits; +typedef VkFlags VkToolPurposeFlags; +typedef VkFlags VkPrivateDataSlotCreateFlags; +typedef VkFlags64 VkPipelineStageFlags2; + +// Flag bits for VkPipelineStageFlagBits2 +typedef VkFlags64 VkPipelineStageFlagBits2; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_NONE = 0ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_NONE_KHR = 0ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT = 0x00000001ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR = 0x00000001ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT = 0x00000002ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT_KHR = 0x00000002ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT = 0x00000004ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT_KHR = 0x00000004ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT = 0x00000008ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT_KHR = 0x00000008ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT = 0x00000010ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT_KHR = 0x00000010ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT = 0x00000020ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT_KHR = 0x00000020ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT = 0x00000040ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT_KHR = 0x00000040ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT = 0x00000080ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT_KHR = 0x00000080ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT = 0x00000100ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT_KHR = 0x00000100ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT = 0x00000200ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT_KHR = 0x00000200ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT = 0x00000400ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR = 0x00000400ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT = 0x00000800ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT_KHR = 0x00000800ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT = 0x00001000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT_KHR = 0x00001000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TRANSFER_BIT = 0x00001000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR = 0x00001000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT = 0x00002000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR = 0x00002000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_HOST_BIT = 0x00004000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_HOST_BIT_KHR = 0x00004000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT = 0x00008000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT_KHR = 0x00008000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT = 0x00010000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT_KHR = 0x00010000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COPY_BIT = 0x100000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COPY_BIT_KHR = 0x100000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_RESOLVE_BIT = 0x200000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_RESOLVE_BIT_KHR = 0x200000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_BLIT_BIT = 0x400000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_BLIT_BIT_KHR = 0x400000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_CLEAR_BIT = 0x800000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_CLEAR_BIT_KHR = 0x800000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT = 0x1000000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT_KHR = 0x1000000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT = 0x2000000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT_KHR = 0x2000000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT = 0x4000000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT_KHR = 0x4000000000ULL; +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR = 0x04000000ULL; +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR = 0x08000000ULL; +#endif +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT = 0x01000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_CONDITIONAL_RENDERING_BIT_EXT = 0x00040000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_NV = 0x00020000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x00400000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_SHADING_RATE_IMAGE_BIT_NV = 0x00400000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR = 0x02000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR = 0x00200000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_NV = 0x00200000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_NV = 0x02000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_FRAGMENT_DENSITY_PROCESS_BIT_EXT = 0x00800000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_NV = 0x00080000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_NV = 0x00100000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_SUBPASS_SHADING_BIT_HUAWEI = 0x8000000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_INVOCATION_MASK_BIT_HUAWEI = 0x10000000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHR = 0x10000000ULL; + +typedef VkFlags64 VkAccessFlags2; + +// Flag bits for VkAccessFlagBits2 +typedef VkFlags64 VkAccessFlagBits2; +static const VkAccessFlagBits2 VK_ACCESS_2_NONE = 0ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_NONE_KHR = 0ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT = 0x00000001ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT_KHR = 0x00000001ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_INDEX_READ_BIT = 0x00000002ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_INDEX_READ_BIT_KHR = 0x00000002ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT = 0x00000004ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT_KHR = 0x00000004ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_UNIFORM_READ_BIT = 0x00000008ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_UNIFORM_READ_BIT_KHR = 0x00000008ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT = 0x00000010ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT_KHR = 0x00000010ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_READ_BIT = 0x00000020ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_READ_BIT_KHR = 0x00000020ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_WRITE_BIT = 0x00000040ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_WRITE_BIT_KHR = 0x00000040ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT = 0x00000080ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT_KHR = 0x00000080ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT = 0x00000100ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR = 0x00000100ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT = 0x00000200ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT_KHR = 0x00000200ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT = 0x00000400ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT_KHR = 0x00000400ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFER_READ_BIT = 0x00000800ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFER_READ_BIT_KHR = 0x00000800ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFER_WRITE_BIT = 0x00001000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR = 0x00001000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_HOST_READ_BIT = 0x00002000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_HOST_READ_BIT_KHR = 0x00002000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_HOST_WRITE_BIT = 0x00004000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_HOST_WRITE_BIT_KHR = 0x00004000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_MEMORY_READ_BIT = 0x00008000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_MEMORY_READ_BIT_KHR = 0x00008000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_MEMORY_WRITE_BIT = 0x00010000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_MEMORY_WRITE_BIT_KHR = 0x00010000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_SAMPLED_READ_BIT = 0x100000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_SAMPLED_READ_BIT_KHR = 0x100000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_STORAGE_READ_BIT = 0x200000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_STORAGE_READ_BIT_KHR = 0x200000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT = 0x400000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT_KHR = 0x400000000ULL; +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkAccessFlagBits2 VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR = 0x800000000ULL; +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkAccessFlagBits2 VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR = 0x1000000000ULL; +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkAccessFlagBits2 VK_ACCESS_2_VIDEO_ENCODE_READ_BIT_KHR = 0x2000000000ULL; +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkAccessFlagBits2 VK_ACCESS_2_VIDEO_ENCODE_WRITE_BIT_KHR = 0x4000000000ULL; +#endif +static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFORM_FEEDBACK_WRITE_BIT_EXT = 0x02000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT = 0x04000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT = 0x08000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_CONDITIONAL_RENDERING_READ_BIT_EXT = 0x00100000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_COMMAND_PREPROCESS_READ_BIT_NV = 0x00020000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_COMMAND_PREPROCESS_WRITE_BIT_NV = 0x00040000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR = 0x00800000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADING_RATE_IMAGE_READ_BIT_NV = 0x00800000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR = 0x00200000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR = 0x00400000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_NV = 0x00200000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_NV = 0x00400000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_FRAGMENT_DENSITY_MAP_READ_BIT_EXT = 0x01000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT = 0x00080000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_INVOCATION_MASK_READ_BIT_HUAWEI = 0x8000000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_BINDING_TABLE_READ_BIT_KHR = 0x10000000000ULL; + + +typedef enum VkSubmitFlagBits { + VK_SUBMIT_PROTECTED_BIT = 0x00000001, + VK_SUBMIT_PROTECTED_BIT_KHR = VK_SUBMIT_PROTECTED_BIT, + VK_SUBMIT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkSubmitFlagBits; +typedef VkFlags VkSubmitFlags; + +typedef enum VkRenderingFlagBits { + VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT = 0x00000001, + VK_RENDERING_SUSPENDING_BIT = 0x00000002, + VK_RENDERING_RESUMING_BIT = 0x00000004, + VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR = VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT, + VK_RENDERING_SUSPENDING_BIT_KHR = VK_RENDERING_SUSPENDING_BIT, + VK_RENDERING_RESUMING_BIT_KHR = VK_RENDERING_RESUMING_BIT, + VK_RENDERING_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkRenderingFlagBits; +typedef VkFlags VkRenderingFlags; +typedef VkFlags64 VkFormatFeatureFlags2; + +// Flag bits for VkFormatFeatureFlagBits2 +typedef VkFlags64 VkFormatFeatureFlagBits2; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT = 0x00000001ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT_KHR = 0x00000001ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT = 0x00000002ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT_KHR = 0x00000002ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT = 0x00000004ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT_KHR = 0x00000004ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT = 0x00000008ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT_KHR = 0x00000008ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT = 0x00000010ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT_KHR = 0x00000010ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_ATOMIC_BIT = 0x00000020ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_ATOMIC_BIT_KHR = 0x00000020ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT = 0x00000040ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT_KHR = 0x00000040ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT = 0x00000080ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT_KHR = 0x00000080ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT = 0x00000100ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT_KHR = 0x00000100ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000200ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT_KHR = 0x00000200ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_BLIT_SRC_BIT = 0x00000400ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_BLIT_SRC_BIT_KHR = 0x00000400ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_BLIT_DST_BIT = 0x00000800ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_BLIT_DST_BIT_KHR = 0x00000800ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT = 0x00001000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT_KHR = 0x00001000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_CUBIC_BIT = 0x00002000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT = 0x00002000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT = 0x00004000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT_KHR = 0x00004000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT = 0x00008000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT_KHR = 0x00008000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT = 0x00010000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT_KHR = 0x00010000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT = 0x00020000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT_KHR = 0x00020000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT = 0x00040000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT_KHR = 0x00040000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT = 0x00080000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT_KHR = 0x00080000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT = 0x00100000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT_KHR = 0x00100000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT = 0x00200000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT_KHR = 0x00200000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_DISJOINT_BIT = 0x00400000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_DISJOINT_BIT_KHR = 0x00400000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_COSITED_CHROMA_SAMPLES_BIT = 0x00800000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_COSITED_CHROMA_SAMPLES_BIT_KHR = 0x00800000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT = 0x80000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT_KHR = 0x80000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT = 0x100000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT_KHR = 0x100000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT = 0x200000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT_KHR = 0x200000000ULL; +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_VIDEO_DECODE_OUTPUT_BIT_KHR = 0x02000000ULL; +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_VIDEO_DECODE_DPB_BIT_KHR = 0x04000000ULL; +#endif +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR = 0x20000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_FRAGMENT_DENSITY_MAP_BIT_EXT = 0x01000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x40000000ULL; +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_VIDEO_ENCODE_INPUT_BIT_KHR = 0x08000000ULL; +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_VIDEO_ENCODE_DPB_BIT_KHR = 0x10000000ULL; +#endif +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_LINEAR_COLOR_ATTACHMENT_BIT_NV = 0x4000000000ULL; + +typedef struct VkPhysicalDeviceVulkan13Features { + VkStructureType sType; + void* pNext; + VkBool32 robustImageAccess; + VkBool32 inlineUniformBlock; + VkBool32 descriptorBindingInlineUniformBlockUpdateAfterBind; + VkBool32 pipelineCreationCacheControl; + VkBool32 privateData; + VkBool32 shaderDemoteToHelperInvocation; + VkBool32 shaderTerminateInvocation; + VkBool32 subgroupSizeControl; + VkBool32 computeFullSubgroups; + VkBool32 synchronization2; + VkBool32 textureCompressionASTC_HDR; + VkBool32 shaderZeroInitializeWorkgroupMemory; + VkBool32 dynamicRendering; + VkBool32 shaderIntegerDotProduct; + VkBool32 maintenance4; +} VkPhysicalDeviceVulkan13Features; + +typedef struct VkPhysicalDeviceVulkan13Properties { + VkStructureType sType; + void* pNext; + uint32_t minSubgroupSize; + uint32_t maxSubgroupSize; + uint32_t maxComputeWorkgroupSubgroups; + VkShaderStageFlags requiredSubgroupSizeStages; + uint32_t maxInlineUniformBlockSize; + uint32_t maxPerStageDescriptorInlineUniformBlocks; + uint32_t maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks; + uint32_t maxDescriptorSetInlineUniformBlocks; + uint32_t maxDescriptorSetUpdateAfterBindInlineUniformBlocks; + uint32_t maxInlineUniformTotalSize; + VkBool32 integerDotProduct8BitUnsignedAccelerated; + VkBool32 integerDotProduct8BitSignedAccelerated; + VkBool32 integerDotProduct8BitMixedSignednessAccelerated; + VkBool32 integerDotProduct4x8BitPackedUnsignedAccelerated; + VkBool32 integerDotProduct4x8BitPackedSignedAccelerated; + VkBool32 integerDotProduct4x8BitPackedMixedSignednessAccelerated; + VkBool32 integerDotProduct16BitUnsignedAccelerated; + VkBool32 integerDotProduct16BitSignedAccelerated; + VkBool32 integerDotProduct16BitMixedSignednessAccelerated; + VkBool32 integerDotProduct32BitUnsignedAccelerated; + VkBool32 integerDotProduct32BitSignedAccelerated; + VkBool32 integerDotProduct32BitMixedSignednessAccelerated; + VkBool32 integerDotProduct64BitUnsignedAccelerated; + VkBool32 integerDotProduct64BitSignedAccelerated; + VkBool32 integerDotProduct64BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating8BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating8BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating8BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating4x8BitPackedUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating4x8BitPackedSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating4x8BitPackedMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating16BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating16BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating16BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating32BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating32BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating32BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating64BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating64BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating64BitMixedSignednessAccelerated; + VkDeviceSize storageTexelBufferOffsetAlignmentBytes; + VkBool32 storageTexelBufferOffsetSingleTexelAlignment; + VkDeviceSize uniformTexelBufferOffsetAlignmentBytes; + VkBool32 uniformTexelBufferOffsetSingleTexelAlignment; + VkDeviceSize maxBufferSize; +} VkPhysicalDeviceVulkan13Properties; + +typedef struct VkPipelineCreationFeedback { + VkPipelineCreationFeedbackFlags flags; + uint64_t duration; +} VkPipelineCreationFeedback; + +typedef struct VkPipelineCreationFeedbackCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineCreationFeedback* pPipelineCreationFeedback; + uint32_t pipelineStageCreationFeedbackCount; + VkPipelineCreationFeedback* pPipelineStageCreationFeedbacks; +} VkPipelineCreationFeedbackCreateInfo; + +typedef struct VkPhysicalDeviceShaderTerminateInvocationFeatures { + VkStructureType sType; + void* pNext; + VkBool32 shaderTerminateInvocation; +} VkPhysicalDeviceShaderTerminateInvocationFeatures; + +typedef struct VkPhysicalDeviceToolProperties { + VkStructureType sType; + void* pNext; + char name[VK_MAX_EXTENSION_NAME_SIZE]; + char version[VK_MAX_EXTENSION_NAME_SIZE]; + VkToolPurposeFlags purposes; + char description[VK_MAX_DESCRIPTION_SIZE]; + char layer[VK_MAX_EXTENSION_NAME_SIZE]; +} VkPhysicalDeviceToolProperties; + +typedef struct VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures { + VkStructureType sType; + void* pNext; + VkBool32 shaderDemoteToHelperInvocation; +} VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures; + +typedef struct VkPhysicalDevicePrivateDataFeatures { + VkStructureType sType; + void* pNext; + VkBool32 privateData; +} VkPhysicalDevicePrivateDataFeatures; + +typedef struct VkDevicePrivateDataCreateInfo { + VkStructureType sType; + const void* pNext; + uint32_t privateDataSlotRequestCount; +} VkDevicePrivateDataCreateInfo; + +typedef struct VkPrivateDataSlotCreateInfo { + VkStructureType sType; + const void* pNext; + VkPrivateDataSlotCreateFlags flags; +} VkPrivateDataSlotCreateInfo; + +typedef struct VkPhysicalDevicePipelineCreationCacheControlFeatures { + VkStructureType sType; + void* pNext; + VkBool32 pipelineCreationCacheControl; +} VkPhysicalDevicePipelineCreationCacheControlFeatures; + +typedef struct VkMemoryBarrier2 { + VkStructureType sType; + const void* pNext; + VkPipelineStageFlags2 srcStageMask; + VkAccessFlags2 srcAccessMask; + VkPipelineStageFlags2 dstStageMask; + VkAccessFlags2 dstAccessMask; +} VkMemoryBarrier2; + +typedef struct VkBufferMemoryBarrier2 { + VkStructureType sType; + const void* pNext; + VkPipelineStageFlags2 srcStageMask; + VkAccessFlags2 srcAccessMask; + VkPipelineStageFlags2 dstStageMask; + VkAccessFlags2 dstAccessMask; + uint32_t srcQueueFamilyIndex; + uint32_t dstQueueFamilyIndex; + VkBuffer buffer; + VkDeviceSize offset; + VkDeviceSize size; +} VkBufferMemoryBarrier2; + +typedef struct VkImageMemoryBarrier2 { + VkStructureType sType; + const void* pNext; + VkPipelineStageFlags2 srcStageMask; + VkAccessFlags2 srcAccessMask; + VkPipelineStageFlags2 dstStageMask; + VkAccessFlags2 dstAccessMask; + VkImageLayout oldLayout; + VkImageLayout newLayout; + uint32_t srcQueueFamilyIndex; + uint32_t dstQueueFamilyIndex; + VkImage image; + VkImageSubresourceRange subresourceRange; +} VkImageMemoryBarrier2; + +typedef struct VkDependencyInfo { + VkStructureType sType; + const void* pNext; + VkDependencyFlags dependencyFlags; + uint32_t memoryBarrierCount; + const VkMemoryBarrier2* pMemoryBarriers; + uint32_t bufferMemoryBarrierCount; + const VkBufferMemoryBarrier2* pBufferMemoryBarriers; + uint32_t imageMemoryBarrierCount; + const VkImageMemoryBarrier2* pImageMemoryBarriers; +} VkDependencyInfo; + +typedef struct VkSemaphoreSubmitInfo { + VkStructureType sType; + const void* pNext; + VkSemaphore semaphore; + uint64_t value; + VkPipelineStageFlags2 stageMask; + uint32_t deviceIndex; +} VkSemaphoreSubmitInfo; + +typedef struct VkCommandBufferSubmitInfo { + VkStructureType sType; + const void* pNext; + VkCommandBuffer commandBuffer; + uint32_t deviceMask; +} VkCommandBufferSubmitInfo; + +typedef struct VkSubmitInfo2 { + VkStructureType sType; + const void* pNext; + VkSubmitFlags flags; + uint32_t waitSemaphoreInfoCount; + const VkSemaphoreSubmitInfo* pWaitSemaphoreInfos; + uint32_t commandBufferInfoCount; + const VkCommandBufferSubmitInfo* pCommandBufferInfos; + uint32_t signalSemaphoreInfoCount; + const VkSemaphoreSubmitInfo* pSignalSemaphoreInfos; +} VkSubmitInfo2; + +typedef struct VkPhysicalDeviceSynchronization2Features { + VkStructureType sType; + void* pNext; + VkBool32 synchronization2; +} VkPhysicalDeviceSynchronization2Features; + +typedef struct VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeatures { + VkStructureType sType; + void* pNext; + VkBool32 shaderZeroInitializeWorkgroupMemory; +} VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeatures; + +typedef struct VkPhysicalDeviceImageRobustnessFeatures { + VkStructureType sType; + void* pNext; + VkBool32 robustImageAccess; +} VkPhysicalDeviceImageRobustnessFeatures; + +typedef struct VkBufferCopy2 { + VkStructureType sType; + const void* pNext; + VkDeviceSize srcOffset; + VkDeviceSize dstOffset; + VkDeviceSize size; +} VkBufferCopy2; + +typedef struct VkCopyBufferInfo2 { + VkStructureType sType; + const void* pNext; + VkBuffer srcBuffer; + VkBuffer dstBuffer; + uint32_t regionCount; + const VkBufferCopy2* pRegions; +} VkCopyBufferInfo2; + +typedef struct VkImageCopy2 { + VkStructureType sType; + const void* pNext; + VkImageSubresourceLayers srcSubresource; + VkOffset3D srcOffset; + VkImageSubresourceLayers dstSubresource; + VkOffset3D dstOffset; + VkExtent3D extent; +} VkImageCopy2; + +typedef struct VkCopyImageInfo2 { + VkStructureType sType; + const void* pNext; + VkImage srcImage; + VkImageLayout srcImageLayout; + VkImage dstImage; + VkImageLayout dstImageLayout; + uint32_t regionCount; + const VkImageCopy2* pRegions; +} VkCopyImageInfo2; + +typedef struct VkBufferImageCopy2 { + VkStructureType sType; + const void* pNext; + VkDeviceSize bufferOffset; + uint32_t bufferRowLength; + uint32_t bufferImageHeight; + VkImageSubresourceLayers imageSubresource; + VkOffset3D imageOffset; + VkExtent3D imageExtent; +} VkBufferImageCopy2; + +typedef struct VkCopyBufferToImageInfo2 { + VkStructureType sType; + const void* pNext; + VkBuffer srcBuffer; + VkImage dstImage; + VkImageLayout dstImageLayout; + uint32_t regionCount; + const VkBufferImageCopy2* pRegions; +} VkCopyBufferToImageInfo2; + +typedef struct VkCopyImageToBufferInfo2 { + VkStructureType sType; + const void* pNext; + VkImage srcImage; + VkImageLayout srcImageLayout; + VkBuffer dstBuffer; + uint32_t regionCount; + const VkBufferImageCopy2* pRegions; +} VkCopyImageToBufferInfo2; + +typedef struct VkImageBlit2 { + VkStructureType sType; + const void* pNext; + VkImageSubresourceLayers srcSubresource; + VkOffset3D srcOffsets[2]; + VkImageSubresourceLayers dstSubresource; + VkOffset3D dstOffsets[2]; +} VkImageBlit2; + +typedef struct VkBlitImageInfo2 { + VkStructureType sType; + const void* pNext; + VkImage srcImage; + VkImageLayout srcImageLayout; + VkImage dstImage; + VkImageLayout dstImageLayout; + uint32_t regionCount; + const VkImageBlit2* pRegions; + VkFilter filter; +} VkBlitImageInfo2; + +typedef struct VkImageResolve2 { + VkStructureType sType; + const void* pNext; + VkImageSubresourceLayers srcSubresource; + VkOffset3D srcOffset; + VkImageSubresourceLayers dstSubresource; + VkOffset3D dstOffset; + VkExtent3D extent; +} VkImageResolve2; + +typedef struct VkResolveImageInfo2 { + VkStructureType sType; + const void* pNext; + VkImage srcImage; + VkImageLayout srcImageLayout; + VkImage dstImage; + VkImageLayout dstImageLayout; + uint32_t regionCount; + const VkImageResolve2* pRegions; +} VkResolveImageInfo2; + +typedef struct VkPhysicalDeviceSubgroupSizeControlFeatures { + VkStructureType sType; + void* pNext; + VkBool32 subgroupSizeControl; + VkBool32 computeFullSubgroups; +} VkPhysicalDeviceSubgroupSizeControlFeatures; + +typedef struct VkPhysicalDeviceSubgroupSizeControlProperties { + VkStructureType sType; + void* pNext; + uint32_t minSubgroupSize; + uint32_t maxSubgroupSize; + uint32_t maxComputeWorkgroupSubgroups; + VkShaderStageFlags requiredSubgroupSizeStages; +} VkPhysicalDeviceSubgroupSizeControlProperties; + +typedef struct VkPipelineShaderStageRequiredSubgroupSizeCreateInfo { + VkStructureType sType; + void* pNext; + uint32_t requiredSubgroupSize; +} VkPipelineShaderStageRequiredSubgroupSizeCreateInfo; + +typedef struct VkPhysicalDeviceInlineUniformBlockFeatures { + VkStructureType sType; + void* pNext; + VkBool32 inlineUniformBlock; + VkBool32 descriptorBindingInlineUniformBlockUpdateAfterBind; +} VkPhysicalDeviceInlineUniformBlockFeatures; + +typedef struct VkPhysicalDeviceInlineUniformBlockProperties { + VkStructureType sType; + void* pNext; + uint32_t maxInlineUniformBlockSize; + uint32_t maxPerStageDescriptorInlineUniformBlocks; + uint32_t maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks; + uint32_t maxDescriptorSetInlineUniformBlocks; + uint32_t maxDescriptorSetUpdateAfterBindInlineUniformBlocks; +} VkPhysicalDeviceInlineUniformBlockProperties; + +typedef struct VkWriteDescriptorSetInlineUniformBlock { + VkStructureType sType; + const void* pNext; + uint32_t dataSize; + const void* pData; +} VkWriteDescriptorSetInlineUniformBlock; + +typedef struct VkDescriptorPoolInlineUniformBlockCreateInfo { + VkStructureType sType; + const void* pNext; + uint32_t maxInlineUniformBlockBindings; +} VkDescriptorPoolInlineUniformBlockCreateInfo; + +typedef struct VkPhysicalDeviceTextureCompressionASTCHDRFeatures { + VkStructureType sType; + void* pNext; + VkBool32 textureCompressionASTC_HDR; +} VkPhysicalDeviceTextureCompressionASTCHDRFeatures; + +typedef struct VkRenderingAttachmentInfo { + VkStructureType sType; + const void* pNext; + VkImageView imageView; + VkImageLayout imageLayout; + VkResolveModeFlagBits resolveMode; + VkImageView resolveImageView; + VkImageLayout resolveImageLayout; + VkAttachmentLoadOp loadOp; + VkAttachmentStoreOp storeOp; + VkClearValue clearValue; +} VkRenderingAttachmentInfo; + +typedef struct VkRenderingInfo { + VkStructureType sType; + const void* pNext; + VkRenderingFlags flags; + VkRect2D renderArea; + uint32_t layerCount; + uint32_t viewMask; + uint32_t colorAttachmentCount; + const VkRenderingAttachmentInfo* pColorAttachments; + const VkRenderingAttachmentInfo* pDepthAttachment; + const VkRenderingAttachmentInfo* pStencilAttachment; +} VkRenderingInfo; + +typedef struct VkPipelineRenderingCreateInfo { + VkStructureType sType; + const void* pNext; + uint32_t viewMask; + uint32_t colorAttachmentCount; + const VkFormat* pColorAttachmentFormats; + VkFormat depthAttachmentFormat; + VkFormat stencilAttachmentFormat; +} VkPipelineRenderingCreateInfo; + +typedef struct VkPhysicalDeviceDynamicRenderingFeatures { + VkStructureType sType; + void* pNext; + VkBool32 dynamicRendering; +} VkPhysicalDeviceDynamicRenderingFeatures; + +typedef struct VkCommandBufferInheritanceRenderingInfo { + VkStructureType sType; + const void* pNext; + VkRenderingFlags flags; + uint32_t viewMask; + uint32_t colorAttachmentCount; + const VkFormat* pColorAttachmentFormats; + VkFormat depthAttachmentFormat; + VkFormat stencilAttachmentFormat; + VkSampleCountFlagBits rasterizationSamples; +} VkCommandBufferInheritanceRenderingInfo; + +typedef struct VkPhysicalDeviceShaderIntegerDotProductFeatures { + VkStructureType sType; + void* pNext; + VkBool32 shaderIntegerDotProduct; +} VkPhysicalDeviceShaderIntegerDotProductFeatures; + +typedef struct VkPhysicalDeviceShaderIntegerDotProductProperties { + VkStructureType sType; + void* pNext; + VkBool32 integerDotProduct8BitUnsignedAccelerated; + VkBool32 integerDotProduct8BitSignedAccelerated; + VkBool32 integerDotProduct8BitMixedSignednessAccelerated; + VkBool32 integerDotProduct4x8BitPackedUnsignedAccelerated; + VkBool32 integerDotProduct4x8BitPackedSignedAccelerated; + VkBool32 integerDotProduct4x8BitPackedMixedSignednessAccelerated; + VkBool32 integerDotProduct16BitUnsignedAccelerated; + VkBool32 integerDotProduct16BitSignedAccelerated; + VkBool32 integerDotProduct16BitMixedSignednessAccelerated; + VkBool32 integerDotProduct32BitUnsignedAccelerated; + VkBool32 integerDotProduct32BitSignedAccelerated; + VkBool32 integerDotProduct32BitMixedSignednessAccelerated; + VkBool32 integerDotProduct64BitUnsignedAccelerated; + VkBool32 integerDotProduct64BitSignedAccelerated; + VkBool32 integerDotProduct64BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating8BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating8BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating8BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating4x8BitPackedUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating4x8BitPackedSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating4x8BitPackedMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating16BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating16BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating16BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating32BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating32BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating32BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating64BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating64BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating64BitMixedSignednessAccelerated; +} VkPhysicalDeviceShaderIntegerDotProductProperties; + +typedef struct VkPhysicalDeviceTexelBufferAlignmentProperties { + VkStructureType sType; + void* pNext; + VkDeviceSize storageTexelBufferOffsetAlignmentBytes; + VkBool32 storageTexelBufferOffsetSingleTexelAlignment; + VkDeviceSize uniformTexelBufferOffsetAlignmentBytes; + VkBool32 uniformTexelBufferOffsetSingleTexelAlignment; +} VkPhysicalDeviceTexelBufferAlignmentProperties; + +typedef struct VkFormatProperties3 { + VkStructureType sType; + void* pNext; + VkFormatFeatureFlags2 linearTilingFeatures; + VkFormatFeatureFlags2 optimalTilingFeatures; + VkFormatFeatureFlags2 bufferFeatures; +} VkFormatProperties3; + +typedef struct VkPhysicalDeviceMaintenance4Features { + VkStructureType sType; + void* pNext; + VkBool32 maintenance4; +} VkPhysicalDeviceMaintenance4Features; + +typedef struct VkPhysicalDeviceMaintenance4Properties { + VkStructureType sType; + void* pNext; + VkDeviceSize maxBufferSize; +} VkPhysicalDeviceMaintenance4Properties; + +typedef struct VkDeviceBufferMemoryRequirements { + VkStructureType sType; + const void* pNext; + const VkBufferCreateInfo* pCreateInfo; +} VkDeviceBufferMemoryRequirements; + +typedef struct VkDeviceImageMemoryRequirements { + VkStructureType sType; + const void* pNext; + const VkImageCreateInfo* pCreateInfo; + VkImageAspectFlagBits planeAspect; +} VkDeviceImageMemoryRequirements; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceToolProperties)(VkPhysicalDevice physicalDevice, uint32_t* pToolCount, VkPhysicalDeviceToolProperties* pToolProperties); +typedef VkResult (VKAPI_PTR *PFN_vkCreatePrivateDataSlot)(VkDevice device, const VkPrivateDataSlotCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPrivateDataSlot* pPrivateDataSlot); +typedef void (VKAPI_PTR *PFN_vkDestroyPrivateDataSlot)(VkDevice device, VkPrivateDataSlot privateDataSlot, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkSetPrivateData)(VkDevice device, VkObjectType objectType, uint64_t objectHandle, VkPrivateDataSlot privateDataSlot, uint64_t data); +typedef void (VKAPI_PTR *PFN_vkGetPrivateData)(VkDevice device, VkObjectType objectType, uint64_t objectHandle, VkPrivateDataSlot privateDataSlot, uint64_t* pData); +typedef void (VKAPI_PTR *PFN_vkCmdSetEvent2)(VkCommandBuffer commandBuffer, VkEvent event, const VkDependencyInfo* pDependencyInfo); +typedef void (VKAPI_PTR *PFN_vkCmdResetEvent2)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags2 stageMask); +typedef void (VKAPI_PTR *PFN_vkCmdWaitEvents2)(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent* pEvents, const VkDependencyInfo* pDependencyInfos); +typedef void (VKAPI_PTR *PFN_vkCmdPipelineBarrier2)(VkCommandBuffer commandBuffer, const VkDependencyInfo* pDependencyInfo); +typedef void (VKAPI_PTR *PFN_vkCmdWriteTimestamp2)(VkCommandBuffer commandBuffer, VkPipelineStageFlags2 stage, VkQueryPool queryPool, uint32_t query); +typedef VkResult (VKAPI_PTR *PFN_vkQueueSubmit2)(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2* pSubmits, VkFence fence); +typedef void (VKAPI_PTR *PFN_vkCmdCopyBuffer2)(VkCommandBuffer commandBuffer, const VkCopyBufferInfo2* pCopyBufferInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyImage2)(VkCommandBuffer commandBuffer, const VkCopyImageInfo2* pCopyImageInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyBufferToImage2)(VkCommandBuffer commandBuffer, const VkCopyBufferToImageInfo2* pCopyBufferToImageInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyImageToBuffer2)(VkCommandBuffer commandBuffer, const VkCopyImageToBufferInfo2* pCopyImageToBufferInfo); +typedef void (VKAPI_PTR *PFN_vkCmdBlitImage2)(VkCommandBuffer commandBuffer, const VkBlitImageInfo2* pBlitImageInfo); +typedef void (VKAPI_PTR *PFN_vkCmdResolveImage2)(VkCommandBuffer commandBuffer, const VkResolveImageInfo2* pResolveImageInfo); +typedef void (VKAPI_PTR *PFN_vkCmdBeginRendering)(VkCommandBuffer commandBuffer, const VkRenderingInfo* pRenderingInfo); +typedef void (VKAPI_PTR *PFN_vkCmdEndRendering)(VkCommandBuffer commandBuffer); +typedef void (VKAPI_PTR *PFN_vkCmdSetCullMode)(VkCommandBuffer commandBuffer, VkCullModeFlags cullMode); +typedef void (VKAPI_PTR *PFN_vkCmdSetFrontFace)(VkCommandBuffer commandBuffer, VkFrontFace frontFace); +typedef void (VKAPI_PTR *PFN_vkCmdSetPrimitiveTopology)(VkCommandBuffer commandBuffer, VkPrimitiveTopology primitiveTopology); +typedef void (VKAPI_PTR *PFN_vkCmdSetViewportWithCount)(VkCommandBuffer commandBuffer, uint32_t viewportCount, const VkViewport* pViewports); +typedef void (VKAPI_PTR *PFN_vkCmdSetScissorWithCount)(VkCommandBuffer commandBuffer, uint32_t scissorCount, const VkRect2D* pScissors); +typedef void (VKAPI_PTR *PFN_vkCmdBindVertexBuffers2)(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets, const VkDeviceSize* pSizes, const VkDeviceSize* pStrides); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthTestEnable)(VkCommandBuffer commandBuffer, VkBool32 depthTestEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthWriteEnable)(VkCommandBuffer commandBuffer, VkBool32 depthWriteEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthCompareOp)(VkCommandBuffer commandBuffer, VkCompareOp depthCompareOp); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBoundsTestEnable)(VkCommandBuffer commandBuffer, VkBool32 depthBoundsTestEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetStencilTestEnable)(VkCommandBuffer commandBuffer, VkBool32 stencilTestEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetStencilOp)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, VkStencilOp failOp, VkStencilOp passOp, VkStencilOp depthFailOp, VkCompareOp compareOp); +typedef void (VKAPI_PTR *PFN_vkCmdSetRasterizerDiscardEnable)(VkCommandBuffer commandBuffer, VkBool32 rasterizerDiscardEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBiasEnable)(VkCommandBuffer commandBuffer, VkBool32 depthBiasEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetPrimitiveRestartEnable)(VkCommandBuffer commandBuffer, VkBool32 primitiveRestartEnable); +typedef void (VKAPI_PTR *PFN_vkGetDeviceBufferMemoryRequirements)(VkDevice device, const VkDeviceBufferMemoryRequirements* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetDeviceImageMemoryRequirements)(VkDevice device, const VkDeviceImageMemoryRequirements* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetDeviceImageSparseMemoryRequirements)(VkDevice device, const VkDeviceImageMemoryRequirements* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceToolProperties( + VkPhysicalDevice physicalDevice, + uint32_t* pToolCount, + VkPhysicalDeviceToolProperties* pToolProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreatePrivateDataSlot( + VkDevice device, + const VkPrivateDataSlotCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkPrivateDataSlot* pPrivateDataSlot); + +VKAPI_ATTR void VKAPI_CALL vkDestroyPrivateDataSlot( + VkDevice device, + VkPrivateDataSlot privateDataSlot, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkSetPrivateData( + VkDevice device, + VkObjectType objectType, + uint64_t objectHandle, + VkPrivateDataSlot privateDataSlot, + uint64_t data); + +VKAPI_ATTR void VKAPI_CALL vkGetPrivateData( + VkDevice device, + VkObjectType objectType, + uint64_t objectHandle, + VkPrivateDataSlot privateDataSlot, + uint64_t* pData); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetEvent2( + VkCommandBuffer commandBuffer, + VkEvent event, + const VkDependencyInfo* pDependencyInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdResetEvent2( + VkCommandBuffer commandBuffer, + VkEvent event, + VkPipelineStageFlags2 stageMask); + +VKAPI_ATTR void VKAPI_CALL vkCmdWaitEvents2( + VkCommandBuffer commandBuffer, + uint32_t eventCount, + const VkEvent* pEvents, + const VkDependencyInfo* pDependencyInfos); + +VKAPI_ATTR void VKAPI_CALL vkCmdPipelineBarrier2( + VkCommandBuffer commandBuffer, + const VkDependencyInfo* pDependencyInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdWriteTimestamp2( + VkCommandBuffer commandBuffer, + VkPipelineStageFlags2 stage, + VkQueryPool queryPool, + uint32_t query); + +VKAPI_ATTR VkResult VKAPI_CALL vkQueueSubmit2( + VkQueue queue, + uint32_t submitCount, + const VkSubmitInfo2* pSubmits, + VkFence fence); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyBuffer2( + VkCommandBuffer commandBuffer, + const VkCopyBufferInfo2* pCopyBufferInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyImage2( + VkCommandBuffer commandBuffer, + const VkCopyImageInfo2* pCopyImageInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyBufferToImage2( + VkCommandBuffer commandBuffer, + const VkCopyBufferToImageInfo2* pCopyBufferToImageInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyImageToBuffer2( + VkCommandBuffer commandBuffer, + const VkCopyImageToBufferInfo2* pCopyImageToBufferInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdBlitImage2( + VkCommandBuffer commandBuffer, + const VkBlitImageInfo2* pBlitImageInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdResolveImage2( + VkCommandBuffer commandBuffer, + const VkResolveImageInfo2* pResolveImageInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdBeginRendering( + VkCommandBuffer commandBuffer, + const VkRenderingInfo* pRenderingInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdEndRendering( + VkCommandBuffer commandBuffer); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetCullMode( + VkCommandBuffer commandBuffer, + VkCullModeFlags cullMode); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetFrontFace( + VkCommandBuffer commandBuffer, + VkFrontFace frontFace); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetPrimitiveTopology( + VkCommandBuffer commandBuffer, + VkPrimitiveTopology primitiveTopology); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportWithCount( + VkCommandBuffer commandBuffer, + uint32_t viewportCount, + const VkViewport* pViewports); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetScissorWithCount( + VkCommandBuffer commandBuffer, + uint32_t scissorCount, + const VkRect2D* pScissors); + +VKAPI_ATTR void VKAPI_CALL vkCmdBindVertexBuffers2( + VkCommandBuffer commandBuffer, + uint32_t firstBinding, + uint32_t bindingCount, + const VkBuffer* pBuffers, + const VkDeviceSize* pOffsets, + const VkDeviceSize* pSizes, + const VkDeviceSize* pStrides); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthTestEnable( + VkCommandBuffer commandBuffer, + VkBool32 depthTestEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthWriteEnable( + VkCommandBuffer commandBuffer, + VkBool32 depthWriteEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthCompareOp( + VkCommandBuffer commandBuffer, + VkCompareOp depthCompareOp); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBoundsTestEnable( + VkCommandBuffer commandBuffer, + VkBool32 depthBoundsTestEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilTestEnable( + VkCommandBuffer commandBuffer, + VkBool32 stencilTestEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilOp( + VkCommandBuffer commandBuffer, + VkStencilFaceFlags faceMask, + VkStencilOp failOp, + VkStencilOp passOp, + VkStencilOp depthFailOp, + VkCompareOp compareOp); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetRasterizerDiscardEnable( + VkCommandBuffer commandBuffer, + VkBool32 rasterizerDiscardEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBiasEnable( + VkCommandBuffer commandBuffer, + VkBool32 depthBiasEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetPrimitiveRestartEnable( + VkCommandBuffer commandBuffer, + VkBool32 primitiveRestartEnable); + +VKAPI_ATTR void VKAPI_CALL vkGetDeviceBufferMemoryRequirements( + VkDevice device, + const VkDeviceBufferMemoryRequirements* pInfo, + VkMemoryRequirements2* pMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkGetDeviceImageMemoryRequirements( + VkDevice device, + const VkDeviceImageMemoryRequirements* pInfo, + VkMemoryRequirements2* pMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkGetDeviceImageSparseMemoryRequirements( + VkDevice device, + const VkDeviceImageMemoryRequirements* pInfo, + uint32_t* pSparseMemoryRequirementCount, + VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); +#endif + + +#define VK_KHR_surface 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSurfaceKHR) +#define VK_KHR_SURFACE_SPEC_VERSION 25 +#define VK_KHR_SURFACE_EXTENSION_NAME "VK_KHR_surface" + +typedef enum VkPresentModeKHR { + VK_PRESENT_MODE_IMMEDIATE_KHR = 0, + VK_PRESENT_MODE_MAILBOX_KHR = 1, + VK_PRESENT_MODE_FIFO_KHR = 2, + VK_PRESENT_MODE_FIFO_RELAXED_KHR = 3, + VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR = 1000111000, + VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR = 1000111001, + VK_PRESENT_MODE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkPresentModeKHR; + +typedef enum VkColorSpaceKHR { + VK_COLOR_SPACE_SRGB_NONLINEAR_KHR = 0, + VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT = 1000104001, + VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT = 1000104002, + VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT = 1000104003, + VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT = 1000104004, + VK_COLOR_SPACE_BT709_LINEAR_EXT = 1000104005, + VK_COLOR_SPACE_BT709_NONLINEAR_EXT = 1000104006, + VK_COLOR_SPACE_BT2020_LINEAR_EXT = 1000104007, + VK_COLOR_SPACE_HDR10_ST2084_EXT = 1000104008, + VK_COLOR_SPACE_DOLBYVISION_EXT = 1000104009, + VK_COLOR_SPACE_HDR10_HLG_EXT = 1000104010, + VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT = 1000104011, + VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT = 1000104012, + VK_COLOR_SPACE_PASS_THROUGH_EXT = 1000104013, + VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT = 1000104014, + VK_COLOR_SPACE_DISPLAY_NATIVE_AMD = 1000213000, + VK_COLORSPACE_SRGB_NONLINEAR_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, + VK_COLOR_SPACE_DCI_P3_LINEAR_EXT = VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT, + VK_COLOR_SPACE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkColorSpaceKHR; + +typedef enum VkSurfaceTransformFlagBitsKHR { + VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR = 0x00000001, + VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR = 0x00000002, + VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR = 0x00000004, + VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR = 0x00000008, + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR = 0x00000010, + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR = 0x00000020, + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR = 0x00000040, + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR = 0x00000080, + VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR = 0x00000100, + VK_SURFACE_TRANSFORM_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkSurfaceTransformFlagBitsKHR; + +typedef enum VkCompositeAlphaFlagBitsKHR { + VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR = 0x00000001, + VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR = 0x00000002, + VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR = 0x00000004, + VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR = 0x00000008, + VK_COMPOSITE_ALPHA_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkCompositeAlphaFlagBitsKHR; +typedef VkFlags VkCompositeAlphaFlagsKHR; +typedef VkFlags VkSurfaceTransformFlagsKHR; +typedef struct VkSurfaceCapabilitiesKHR { + uint32_t minImageCount; + uint32_t maxImageCount; + VkExtent2D currentExtent; + VkExtent2D minImageExtent; + VkExtent2D maxImageExtent; + uint32_t maxImageArrayLayers; + VkSurfaceTransformFlagsKHR supportedTransforms; + VkSurfaceTransformFlagBitsKHR currentTransform; + VkCompositeAlphaFlagsKHR supportedCompositeAlpha; + VkImageUsageFlags supportedUsageFlags; +} VkSurfaceCapabilitiesKHR; + +typedef struct VkSurfaceFormatKHR { + VkFormat format; + VkColorSpaceKHR colorSpace; +} VkSurfaceFormatKHR; + +typedef void (VKAPI_PTR *PFN_vkDestroySurfaceKHR)(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, VkSurfaceKHR surface, VkBool32* pSupported); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR* pSurfaceCapabilities); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceFormatsKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pSurfaceFormatCount, VkSurfaceFormatKHR* pSurfaceFormats); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfacePresentModesKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pPresentModeCount, VkPresentModeKHR* pPresentModes); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroySurfaceKHR( + VkInstance instance, + VkSurfaceKHR surface, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceSupportKHR( + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + VkSurfaceKHR surface, + VkBool32* pSupported); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilitiesKHR( + VkPhysicalDevice physicalDevice, + VkSurfaceKHR surface, + VkSurfaceCapabilitiesKHR* pSurfaceCapabilities); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormatsKHR( + VkPhysicalDevice physicalDevice, + VkSurfaceKHR surface, + uint32_t* pSurfaceFormatCount, + VkSurfaceFormatKHR* pSurfaceFormats); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfacePresentModesKHR( + VkPhysicalDevice physicalDevice, + VkSurfaceKHR surface, + uint32_t* pPresentModeCount, + VkPresentModeKHR* pPresentModes); +#endif + + +#define VK_KHR_swapchain 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSwapchainKHR) +#define VK_KHR_SWAPCHAIN_SPEC_VERSION 70 +#define VK_KHR_SWAPCHAIN_EXTENSION_NAME "VK_KHR_swapchain" + +typedef enum VkSwapchainCreateFlagBitsKHR { + VK_SWAPCHAIN_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR = 0x00000001, + VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR = 0x00000002, + VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR = 0x00000004, + VK_SWAPCHAIN_CREATE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkSwapchainCreateFlagBitsKHR; +typedef VkFlags VkSwapchainCreateFlagsKHR; + +typedef enum VkDeviceGroupPresentModeFlagBitsKHR { + VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR = 0x00000001, + VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR = 0x00000002, + VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR = 0x00000004, + VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR = 0x00000008, + VK_DEVICE_GROUP_PRESENT_MODE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkDeviceGroupPresentModeFlagBitsKHR; +typedef VkFlags VkDeviceGroupPresentModeFlagsKHR; +typedef struct VkSwapchainCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkSwapchainCreateFlagsKHR flags; + VkSurfaceKHR surface; + uint32_t minImageCount; + VkFormat imageFormat; + VkColorSpaceKHR imageColorSpace; + VkExtent2D imageExtent; + uint32_t imageArrayLayers; + VkImageUsageFlags imageUsage; + VkSharingMode imageSharingMode; + uint32_t queueFamilyIndexCount; + const uint32_t* pQueueFamilyIndices; + VkSurfaceTransformFlagBitsKHR preTransform; + VkCompositeAlphaFlagBitsKHR compositeAlpha; + VkPresentModeKHR presentMode; + VkBool32 clipped; + VkSwapchainKHR oldSwapchain; +} VkSwapchainCreateInfoKHR; + +typedef struct VkPresentInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t waitSemaphoreCount; + const VkSemaphore* pWaitSemaphores; + uint32_t swapchainCount; + const VkSwapchainKHR* pSwapchains; + const uint32_t* pImageIndices; + VkResult* pResults; +} VkPresentInfoKHR; + +typedef struct VkImageSwapchainCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkSwapchainKHR swapchain; +} VkImageSwapchainCreateInfoKHR; + +typedef struct VkBindImageMemorySwapchainInfoKHR { + VkStructureType sType; + const void* pNext; + VkSwapchainKHR swapchain; + uint32_t imageIndex; +} VkBindImageMemorySwapchainInfoKHR; + +typedef struct VkAcquireNextImageInfoKHR { + VkStructureType sType; + const void* pNext; + VkSwapchainKHR swapchain; + uint64_t timeout; + VkSemaphore semaphore; + VkFence fence; + uint32_t deviceMask; +} VkAcquireNextImageInfoKHR; + +typedef struct VkDeviceGroupPresentCapabilitiesKHR { + VkStructureType sType; + void* pNext; + uint32_t presentMask[VK_MAX_DEVICE_GROUP_SIZE]; + VkDeviceGroupPresentModeFlagsKHR modes; +} VkDeviceGroupPresentCapabilitiesKHR; + +typedef struct VkDeviceGroupPresentInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t swapchainCount; + const uint32_t* pDeviceMasks; + VkDeviceGroupPresentModeFlagBitsKHR mode; +} VkDeviceGroupPresentInfoKHR; + +typedef struct VkDeviceGroupSwapchainCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkDeviceGroupPresentModeFlagsKHR modes; +} VkDeviceGroupSwapchainCreateInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateSwapchainKHR)(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchain); +typedef void (VKAPI_PTR *PFN_vkDestroySwapchainKHR)(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainImagesKHR)(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pSwapchainImageCount, VkImage* pSwapchainImages); +typedef VkResult (VKAPI_PTR *PFN_vkAcquireNextImageKHR)(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* pImageIndex); +typedef VkResult (VKAPI_PTR *PFN_vkQueuePresentKHR)(VkQueue queue, const VkPresentInfoKHR* pPresentInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceGroupPresentCapabilitiesKHR)(VkDevice device, VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities); +typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceGroupSurfacePresentModesKHR)(VkDevice device, VkSurfaceKHR surface, VkDeviceGroupPresentModeFlagsKHR* pModes); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDevicePresentRectanglesKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pRectCount, VkRect2D* pRects); +typedef VkResult (VKAPI_PTR *PFN_vkAcquireNextImage2KHR)(VkDevice device, const VkAcquireNextImageInfoKHR* pAcquireInfo, uint32_t* pImageIndex); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateSwapchainKHR( + VkDevice device, + const VkSwapchainCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSwapchainKHR* pSwapchain); + +VKAPI_ATTR void VKAPI_CALL vkDestroySwapchainKHR( + VkDevice device, + VkSwapchainKHR swapchain, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainImagesKHR( + VkDevice device, + VkSwapchainKHR swapchain, + uint32_t* pSwapchainImageCount, + VkImage* pSwapchainImages); + +VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImageKHR( + VkDevice device, + VkSwapchainKHR swapchain, + uint64_t timeout, + VkSemaphore semaphore, + VkFence fence, + uint32_t* pImageIndex); + +VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR( + VkQueue queue, + const VkPresentInfoKHR* pPresentInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupPresentCapabilitiesKHR( + VkDevice device, + VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupSurfacePresentModesKHR( + VkDevice device, + VkSurfaceKHR surface, + VkDeviceGroupPresentModeFlagsKHR* pModes); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDevicePresentRectanglesKHR( + VkPhysicalDevice physicalDevice, + VkSurfaceKHR surface, + uint32_t* pRectCount, + VkRect2D* pRects); + +VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImage2KHR( + VkDevice device, + const VkAcquireNextImageInfoKHR* pAcquireInfo, + uint32_t* pImageIndex); +#endif + + +#define VK_KHR_display 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDisplayKHR) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDisplayModeKHR) +#define VK_KHR_DISPLAY_SPEC_VERSION 23 +#define VK_KHR_DISPLAY_EXTENSION_NAME "VK_KHR_display" +typedef VkFlags VkDisplayModeCreateFlagsKHR; + +typedef enum VkDisplayPlaneAlphaFlagBitsKHR { + VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR = 0x00000001, + VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR = 0x00000002, + VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR = 0x00000004, + VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR = 0x00000008, + VK_DISPLAY_PLANE_ALPHA_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkDisplayPlaneAlphaFlagBitsKHR; +typedef VkFlags VkDisplayPlaneAlphaFlagsKHR; +typedef VkFlags VkDisplaySurfaceCreateFlagsKHR; +typedef struct VkDisplayModeParametersKHR { + VkExtent2D visibleRegion; + uint32_t refreshRate; +} VkDisplayModeParametersKHR; + +typedef struct VkDisplayModeCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkDisplayModeCreateFlagsKHR flags; + VkDisplayModeParametersKHR parameters; +} VkDisplayModeCreateInfoKHR; + +typedef struct VkDisplayModePropertiesKHR { + VkDisplayModeKHR displayMode; + VkDisplayModeParametersKHR parameters; +} VkDisplayModePropertiesKHR; + +typedef struct VkDisplayPlaneCapabilitiesKHR { + VkDisplayPlaneAlphaFlagsKHR supportedAlpha; + VkOffset2D minSrcPosition; + VkOffset2D maxSrcPosition; + VkExtent2D minSrcExtent; + VkExtent2D maxSrcExtent; + VkOffset2D minDstPosition; + VkOffset2D maxDstPosition; + VkExtent2D minDstExtent; + VkExtent2D maxDstExtent; +} VkDisplayPlaneCapabilitiesKHR; + +typedef struct VkDisplayPlanePropertiesKHR { + VkDisplayKHR currentDisplay; + uint32_t currentStackIndex; +} VkDisplayPlanePropertiesKHR; + +typedef struct VkDisplayPropertiesKHR { + VkDisplayKHR display; + const char* displayName; + VkExtent2D physicalDimensions; + VkExtent2D physicalResolution; + VkSurfaceTransformFlagsKHR supportedTransforms; + VkBool32 planeReorderPossible; + VkBool32 persistentContent; +} VkDisplayPropertiesKHR; + +typedef struct VkDisplaySurfaceCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkDisplaySurfaceCreateFlagsKHR flags; + VkDisplayModeKHR displayMode; + uint32_t planeIndex; + uint32_t planeStackIndex; + VkSurfaceTransformFlagBitsKHR transform; + float globalAlpha; + VkDisplayPlaneAlphaFlagBitsKHR alphaMode; + VkExtent2D imageExtent; +} VkDisplaySurfaceCreateInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayPropertiesKHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPropertiesKHR* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPlanePropertiesKHR* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayPlaneSupportedDisplaysKHR)(VkPhysicalDevice physicalDevice, uint32_t planeIndex, uint32_t* pDisplayCount, VkDisplayKHR* pDisplays); +typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayModePropertiesKHR)(VkPhysicalDevice physicalDevice, VkDisplayKHR display, uint32_t* pPropertyCount, VkDisplayModePropertiesKHR* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkCreateDisplayModeKHR)(VkPhysicalDevice physicalDevice, VkDisplayKHR display, const VkDisplayModeCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDisplayModeKHR* pMode); +typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayPlaneCapabilitiesKHR)(VkPhysicalDevice physicalDevice, VkDisplayModeKHR mode, uint32_t planeIndex, VkDisplayPlaneCapabilitiesKHR* pCapabilities); +typedef VkResult (VKAPI_PTR *PFN_vkCreateDisplayPlaneSurfaceKHR)(VkInstance instance, const VkDisplaySurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPropertiesKHR( + VkPhysicalDevice physicalDevice, + uint32_t* pPropertyCount, + VkDisplayPropertiesKHR* pProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPlanePropertiesKHR( + VkPhysicalDevice physicalDevice, + uint32_t* pPropertyCount, + VkDisplayPlanePropertiesKHR* pProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneSupportedDisplaysKHR( + VkPhysicalDevice physicalDevice, + uint32_t planeIndex, + uint32_t* pDisplayCount, + VkDisplayKHR* pDisplays); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayModePropertiesKHR( + VkPhysicalDevice physicalDevice, + VkDisplayKHR display, + uint32_t* pPropertyCount, + VkDisplayModePropertiesKHR* pProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDisplayModeKHR( + VkPhysicalDevice physicalDevice, + VkDisplayKHR display, + const VkDisplayModeCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDisplayModeKHR* pMode); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneCapabilitiesKHR( + VkPhysicalDevice physicalDevice, + VkDisplayModeKHR mode, + uint32_t planeIndex, + VkDisplayPlaneCapabilitiesKHR* pCapabilities); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDisplayPlaneSurfaceKHR( + VkInstance instance, + const VkDisplaySurfaceCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); +#endif + + +#define VK_KHR_display_swapchain 1 +#define VK_KHR_DISPLAY_SWAPCHAIN_SPEC_VERSION 10 +#define VK_KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME "VK_KHR_display_swapchain" +typedef struct VkDisplayPresentInfoKHR { + VkStructureType sType; + const void* pNext; + VkRect2D srcRect; + VkRect2D dstRect; + VkBool32 persistent; +} VkDisplayPresentInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateSharedSwapchainsKHR)(VkDevice device, uint32_t swapchainCount, const VkSwapchainCreateInfoKHR* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchains); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateSharedSwapchainsKHR( + VkDevice device, + uint32_t swapchainCount, + const VkSwapchainCreateInfoKHR* pCreateInfos, + const VkAllocationCallbacks* pAllocator, + VkSwapchainKHR* pSwapchains); +#endif + + +#define VK_KHR_sampler_mirror_clamp_to_edge 1 +#define VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_SPEC_VERSION 3 +#define VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME "VK_KHR_sampler_mirror_clamp_to_edge" + + +#define VK_KHR_dynamic_rendering 1 +#define VK_KHR_DYNAMIC_RENDERING_SPEC_VERSION 1 +#define VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME "VK_KHR_dynamic_rendering" +typedef VkRenderingFlags VkRenderingFlagsKHR; + +typedef VkRenderingFlagBits VkRenderingFlagBitsKHR; + +typedef VkRenderingInfo VkRenderingInfoKHR; + +typedef VkRenderingAttachmentInfo VkRenderingAttachmentInfoKHR; + +typedef VkPipelineRenderingCreateInfo VkPipelineRenderingCreateInfoKHR; + +typedef VkPhysicalDeviceDynamicRenderingFeatures VkPhysicalDeviceDynamicRenderingFeaturesKHR; + +typedef VkCommandBufferInheritanceRenderingInfo VkCommandBufferInheritanceRenderingInfoKHR; + +typedef struct VkRenderingFragmentShadingRateAttachmentInfoKHR { + VkStructureType sType; + const void* pNext; + VkImageView imageView; + VkImageLayout imageLayout; + VkExtent2D shadingRateAttachmentTexelSize; +} VkRenderingFragmentShadingRateAttachmentInfoKHR; + +typedef struct VkRenderingFragmentDensityMapAttachmentInfoEXT { + VkStructureType sType; + const void* pNext; + VkImageView imageView; + VkImageLayout imageLayout; +} VkRenderingFragmentDensityMapAttachmentInfoEXT; + +typedef struct VkAttachmentSampleCountInfoAMD { + VkStructureType sType; + const void* pNext; + uint32_t colorAttachmentCount; + const VkSampleCountFlagBits* pColorAttachmentSamples; + VkSampleCountFlagBits depthStencilAttachmentSamples; +} VkAttachmentSampleCountInfoAMD; + +typedef VkAttachmentSampleCountInfoAMD VkAttachmentSampleCountInfoNV; + +typedef struct VkMultiviewPerViewAttributesInfoNVX { + VkStructureType sType; + const void* pNext; + VkBool32 perViewAttributes; + VkBool32 perViewAttributesPositionXOnly; +} VkMultiviewPerViewAttributesInfoNVX; + +typedef void (VKAPI_PTR *PFN_vkCmdBeginRenderingKHR)(VkCommandBuffer commandBuffer, const VkRenderingInfo* pRenderingInfo); +typedef void (VKAPI_PTR *PFN_vkCmdEndRenderingKHR)(VkCommandBuffer commandBuffer); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderingKHR( + VkCommandBuffer commandBuffer, + const VkRenderingInfo* pRenderingInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderingKHR( + VkCommandBuffer commandBuffer); +#endif + + +#define VK_KHR_multiview 1 +#define VK_KHR_MULTIVIEW_SPEC_VERSION 1 +#define VK_KHR_MULTIVIEW_EXTENSION_NAME "VK_KHR_multiview" +typedef VkRenderPassMultiviewCreateInfo VkRenderPassMultiviewCreateInfoKHR; + +typedef VkPhysicalDeviceMultiviewFeatures VkPhysicalDeviceMultiviewFeaturesKHR; + +typedef VkPhysicalDeviceMultiviewProperties VkPhysicalDeviceMultiviewPropertiesKHR; + + + +#define VK_KHR_get_physical_device_properties2 1 +#define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION 2 +#define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME "VK_KHR_get_physical_device_properties2" +typedef VkPhysicalDeviceFeatures2 VkPhysicalDeviceFeatures2KHR; + +typedef VkPhysicalDeviceProperties2 VkPhysicalDeviceProperties2KHR; + +typedef VkFormatProperties2 VkFormatProperties2KHR; + +typedef VkImageFormatProperties2 VkImageFormatProperties2KHR; + +typedef VkPhysicalDeviceImageFormatInfo2 VkPhysicalDeviceImageFormatInfo2KHR; + +typedef VkQueueFamilyProperties2 VkQueueFamilyProperties2KHR; + +typedef VkPhysicalDeviceMemoryProperties2 VkPhysicalDeviceMemoryProperties2KHR; + +typedef VkSparseImageFormatProperties2 VkSparseImageFormatProperties2KHR; + +typedef VkPhysicalDeviceSparseImageFormatInfo2 VkPhysicalDeviceSparseImageFormatInfo2KHR; + +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFeatures2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceProperties2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFormatProperties2KHR)(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceImageFormatProperties2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR)(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMemoryProperties2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures2KHR( + VkPhysicalDevice physicalDevice, + VkPhysicalDeviceFeatures2* pFeatures); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties2KHR( + VkPhysicalDevice physicalDevice, + VkPhysicalDeviceProperties2* pProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFormatProperties2KHR( + VkPhysicalDevice physicalDevice, + VkFormat format, + VkFormatProperties2* pFormatProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties2KHR( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, + VkImageFormatProperties2* pImageFormatProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties2KHR( + VkPhysicalDevice physicalDevice, + uint32_t* pQueueFamilyPropertyCount, + VkQueueFamilyProperties2* pQueueFamilyProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties2KHR( + VkPhysicalDevice physicalDevice, + VkPhysicalDeviceMemoryProperties2* pMemoryProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties2KHR( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, + uint32_t* pPropertyCount, + VkSparseImageFormatProperties2* pProperties); +#endif + + +#define VK_KHR_device_group 1 +#define VK_KHR_DEVICE_GROUP_SPEC_VERSION 4 +#define VK_KHR_DEVICE_GROUP_EXTENSION_NAME "VK_KHR_device_group" +typedef VkPeerMemoryFeatureFlags VkPeerMemoryFeatureFlagsKHR; + +typedef VkPeerMemoryFeatureFlagBits VkPeerMemoryFeatureFlagBitsKHR; + +typedef VkMemoryAllocateFlags VkMemoryAllocateFlagsKHR; + +typedef VkMemoryAllocateFlagBits VkMemoryAllocateFlagBitsKHR; + +typedef VkMemoryAllocateFlagsInfo VkMemoryAllocateFlagsInfoKHR; + +typedef VkDeviceGroupRenderPassBeginInfo VkDeviceGroupRenderPassBeginInfoKHR; + +typedef VkDeviceGroupCommandBufferBeginInfo VkDeviceGroupCommandBufferBeginInfoKHR; + +typedef VkDeviceGroupSubmitInfo VkDeviceGroupSubmitInfoKHR; + +typedef VkDeviceGroupBindSparseInfo VkDeviceGroupBindSparseInfoKHR; + +typedef VkBindBufferMemoryDeviceGroupInfo VkBindBufferMemoryDeviceGroupInfoKHR; + +typedef VkBindImageMemoryDeviceGroupInfo VkBindImageMemoryDeviceGroupInfoKHR; + +typedef void (VKAPI_PTR *PFN_vkGetDeviceGroupPeerMemoryFeaturesKHR)(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures); +typedef void (VKAPI_PTR *PFN_vkCmdSetDeviceMaskKHR)(VkCommandBuffer commandBuffer, uint32_t deviceMask); +typedef void (VKAPI_PTR *PFN_vkCmdDispatchBaseKHR)(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetDeviceGroupPeerMemoryFeaturesKHR( + VkDevice device, + uint32_t heapIndex, + uint32_t localDeviceIndex, + uint32_t remoteDeviceIndex, + VkPeerMemoryFeatureFlags* pPeerMemoryFeatures); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDeviceMaskKHR( + VkCommandBuffer commandBuffer, + uint32_t deviceMask); + +VKAPI_ATTR void VKAPI_CALL vkCmdDispatchBaseKHR( + VkCommandBuffer commandBuffer, + uint32_t baseGroupX, + uint32_t baseGroupY, + uint32_t baseGroupZ, + uint32_t groupCountX, + uint32_t groupCountY, + uint32_t groupCountZ); +#endif + + +#define VK_KHR_shader_draw_parameters 1 +#define VK_KHR_SHADER_DRAW_PARAMETERS_SPEC_VERSION 1 +#define VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME "VK_KHR_shader_draw_parameters" + + +#define VK_KHR_maintenance1 1 +#define VK_KHR_MAINTENANCE_1_SPEC_VERSION 2 +#define VK_KHR_MAINTENANCE_1_EXTENSION_NAME "VK_KHR_maintenance1" +#define VK_KHR_MAINTENANCE1_SPEC_VERSION VK_KHR_MAINTENANCE_1_SPEC_VERSION +#define VK_KHR_MAINTENANCE1_EXTENSION_NAME VK_KHR_MAINTENANCE_1_EXTENSION_NAME +typedef VkCommandPoolTrimFlags VkCommandPoolTrimFlagsKHR; + +typedef void (VKAPI_PTR *PFN_vkTrimCommandPoolKHR)(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkTrimCommandPoolKHR( + VkDevice device, + VkCommandPool commandPool, + VkCommandPoolTrimFlags flags); +#endif + + +#define VK_KHR_device_group_creation 1 +#define VK_KHR_DEVICE_GROUP_CREATION_SPEC_VERSION 1 +#define VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME "VK_KHR_device_group_creation" +#define VK_MAX_DEVICE_GROUP_SIZE_KHR VK_MAX_DEVICE_GROUP_SIZE +typedef VkPhysicalDeviceGroupProperties VkPhysicalDeviceGroupPropertiesKHR; + +typedef VkDeviceGroupDeviceCreateInfo VkDeviceGroupDeviceCreateInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDeviceGroupsKHR)(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceGroupsKHR( + VkInstance instance, + uint32_t* pPhysicalDeviceGroupCount, + VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties); +#endif + + +#define VK_KHR_external_memory_capabilities 1 +#define VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_memory_capabilities" +#define VK_LUID_SIZE_KHR VK_LUID_SIZE +typedef VkExternalMemoryHandleTypeFlags VkExternalMemoryHandleTypeFlagsKHR; + +typedef VkExternalMemoryHandleTypeFlagBits VkExternalMemoryHandleTypeFlagBitsKHR; + +typedef VkExternalMemoryFeatureFlags VkExternalMemoryFeatureFlagsKHR; + +typedef VkExternalMemoryFeatureFlagBits VkExternalMemoryFeatureFlagBitsKHR; + +typedef VkExternalMemoryProperties VkExternalMemoryPropertiesKHR; + +typedef VkPhysicalDeviceExternalImageFormatInfo VkPhysicalDeviceExternalImageFormatInfoKHR; + +typedef VkExternalImageFormatProperties VkExternalImageFormatPropertiesKHR; + +typedef VkPhysicalDeviceExternalBufferInfo VkPhysicalDeviceExternalBufferInfoKHR; + +typedef VkExternalBufferProperties VkExternalBufferPropertiesKHR; + +typedef VkPhysicalDeviceIDProperties VkPhysicalDeviceIDPropertiesKHR; + +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalBufferPropertiesKHR( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, + VkExternalBufferProperties* pExternalBufferProperties); +#endif + + +#define VK_KHR_external_memory 1 +#define VK_KHR_EXTERNAL_MEMORY_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME "VK_KHR_external_memory" +#define VK_QUEUE_FAMILY_EXTERNAL_KHR VK_QUEUE_FAMILY_EXTERNAL +typedef VkExternalMemoryImageCreateInfo VkExternalMemoryImageCreateInfoKHR; + +typedef VkExternalMemoryBufferCreateInfo VkExternalMemoryBufferCreateInfoKHR; + +typedef VkExportMemoryAllocateInfo VkExportMemoryAllocateInfoKHR; + + + +#define VK_KHR_external_memory_fd 1 +#define VK_KHR_EXTERNAL_MEMORY_FD_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME "VK_KHR_external_memory_fd" +typedef struct VkImportMemoryFdInfoKHR { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlagBits handleType; + int fd; +} VkImportMemoryFdInfoKHR; + +typedef struct VkMemoryFdPropertiesKHR { + VkStructureType sType; + void* pNext; + uint32_t memoryTypeBits; +} VkMemoryFdPropertiesKHR; + +typedef struct VkMemoryGetFdInfoKHR { + VkStructureType sType; + const void* pNext; + VkDeviceMemory memory; + VkExternalMemoryHandleTypeFlagBits handleType; +} VkMemoryGetFdInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryFdKHR)(VkDevice device, const VkMemoryGetFdInfoKHR* pGetFdInfo, int* pFd); +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryFdPropertiesKHR)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, int fd, VkMemoryFdPropertiesKHR* pMemoryFdProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFdKHR( + VkDevice device, + const VkMemoryGetFdInfoKHR* pGetFdInfo, + int* pFd); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFdPropertiesKHR( + VkDevice device, + VkExternalMemoryHandleTypeFlagBits handleType, + int fd, + VkMemoryFdPropertiesKHR* pMemoryFdProperties); +#endif + + +#define VK_KHR_external_semaphore_capabilities 1 +#define VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_semaphore_capabilities" +typedef VkExternalSemaphoreHandleTypeFlags VkExternalSemaphoreHandleTypeFlagsKHR; + +typedef VkExternalSemaphoreHandleTypeFlagBits VkExternalSemaphoreHandleTypeFlagBitsKHR; + +typedef VkExternalSemaphoreFeatureFlags VkExternalSemaphoreFeatureFlagsKHR; + +typedef VkExternalSemaphoreFeatureFlagBits VkExternalSemaphoreFeatureFlagBitsKHR; + +typedef VkPhysicalDeviceExternalSemaphoreInfo VkPhysicalDeviceExternalSemaphoreInfoKHR; + +typedef VkExternalSemaphoreProperties VkExternalSemaphorePropertiesKHR; + +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalSemaphorePropertiesKHR( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, + VkExternalSemaphoreProperties* pExternalSemaphoreProperties); +#endif + + +#define VK_KHR_external_semaphore 1 +#define VK_KHR_EXTERNAL_SEMAPHORE_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME "VK_KHR_external_semaphore" +typedef VkSemaphoreImportFlags VkSemaphoreImportFlagsKHR; + +typedef VkSemaphoreImportFlagBits VkSemaphoreImportFlagBitsKHR; + +typedef VkExportSemaphoreCreateInfo VkExportSemaphoreCreateInfoKHR; + + + +#define VK_KHR_external_semaphore_fd 1 +#define VK_KHR_EXTERNAL_SEMAPHORE_FD_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME "VK_KHR_external_semaphore_fd" +typedef struct VkImportSemaphoreFdInfoKHR { + VkStructureType sType; + const void* pNext; + VkSemaphore semaphore; + VkSemaphoreImportFlags flags; + VkExternalSemaphoreHandleTypeFlagBits handleType; + int fd; +} VkImportSemaphoreFdInfoKHR; + +typedef struct VkSemaphoreGetFdInfoKHR { + VkStructureType sType; + const void* pNext; + VkSemaphore semaphore; + VkExternalSemaphoreHandleTypeFlagBits handleType; +} VkSemaphoreGetFdInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkImportSemaphoreFdKHR)(VkDevice device, const VkImportSemaphoreFdInfoKHR* pImportSemaphoreFdInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreFdKHR)(VkDevice device, const VkSemaphoreGetFdInfoKHR* pGetFdInfo, int* pFd); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkImportSemaphoreFdKHR( + VkDevice device, + const VkImportSemaphoreFdInfoKHR* pImportSemaphoreFdInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreFdKHR( + VkDevice device, + const VkSemaphoreGetFdInfoKHR* pGetFdInfo, + int* pFd); +#endif + + +#define VK_KHR_push_descriptor 1 +#define VK_KHR_PUSH_DESCRIPTOR_SPEC_VERSION 2 +#define VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME "VK_KHR_push_descriptor" +typedef struct VkPhysicalDevicePushDescriptorPropertiesKHR { + VkStructureType sType; + void* pNext; + uint32_t maxPushDescriptors; +} VkPhysicalDevicePushDescriptorPropertiesKHR; + +typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSetKHR)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t set, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites); +typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSetWithTemplateKHR)(VkCommandBuffer commandBuffer, VkDescriptorUpdateTemplate descriptorUpdateTemplate, VkPipelineLayout layout, uint32_t set, const void* pData); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetKHR( + VkCommandBuffer commandBuffer, + VkPipelineBindPoint pipelineBindPoint, + VkPipelineLayout layout, + uint32_t set, + uint32_t descriptorWriteCount, + const VkWriteDescriptorSet* pDescriptorWrites); + +VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetWithTemplateKHR( + VkCommandBuffer commandBuffer, + VkDescriptorUpdateTemplate descriptorUpdateTemplate, + VkPipelineLayout layout, + uint32_t set, + const void* pData); +#endif + + +#define VK_KHR_shader_float16_int8 1 +#define VK_KHR_SHADER_FLOAT16_INT8_SPEC_VERSION 1 +#define VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME "VK_KHR_shader_float16_int8" +typedef VkPhysicalDeviceShaderFloat16Int8Features VkPhysicalDeviceShaderFloat16Int8FeaturesKHR; + +typedef VkPhysicalDeviceShaderFloat16Int8Features VkPhysicalDeviceFloat16Int8FeaturesKHR; + + + +#define VK_KHR_16bit_storage 1 +#define VK_KHR_16BIT_STORAGE_SPEC_VERSION 1 +#define VK_KHR_16BIT_STORAGE_EXTENSION_NAME "VK_KHR_16bit_storage" +typedef VkPhysicalDevice16BitStorageFeatures VkPhysicalDevice16BitStorageFeaturesKHR; + + + +#define VK_KHR_incremental_present 1 +#define VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION 2 +#define VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME "VK_KHR_incremental_present" +typedef struct VkRectLayerKHR { + VkOffset2D offset; + VkExtent2D extent; + uint32_t layer; +} VkRectLayerKHR; + +typedef struct VkPresentRegionKHR { + uint32_t rectangleCount; + const VkRectLayerKHR* pRectangles; +} VkPresentRegionKHR; + +typedef struct VkPresentRegionsKHR { + VkStructureType sType; + const void* pNext; + uint32_t swapchainCount; + const VkPresentRegionKHR* pRegions; +} VkPresentRegionsKHR; + + + +#define VK_KHR_descriptor_update_template 1 +typedef VkDescriptorUpdateTemplate VkDescriptorUpdateTemplateKHR; + +#define VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_SPEC_VERSION 1 +#define VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME "VK_KHR_descriptor_update_template" +typedef VkDescriptorUpdateTemplateType VkDescriptorUpdateTemplateTypeKHR; + +typedef VkDescriptorUpdateTemplateCreateFlags VkDescriptorUpdateTemplateCreateFlagsKHR; + +typedef VkDescriptorUpdateTemplateEntry VkDescriptorUpdateTemplateEntryKHR; + +typedef VkDescriptorUpdateTemplateCreateInfo VkDescriptorUpdateTemplateCreateInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateDescriptorUpdateTemplateKHR)(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate); +typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorUpdateTemplateKHR)(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkUpdateDescriptorSetWithTemplateKHR)(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorUpdateTemplateKHR( + VkDevice device, + const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate); + +VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorUpdateTemplateKHR( + VkDevice device, + VkDescriptorUpdateTemplate descriptorUpdateTemplate, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR void VKAPI_CALL vkUpdateDescriptorSetWithTemplateKHR( + VkDevice device, + VkDescriptorSet descriptorSet, + VkDescriptorUpdateTemplate descriptorUpdateTemplate, + const void* pData); +#endif + + +#define VK_KHR_imageless_framebuffer 1 +#define VK_KHR_IMAGELESS_FRAMEBUFFER_SPEC_VERSION 1 +#define VK_KHR_IMAGELESS_FRAMEBUFFER_EXTENSION_NAME "VK_KHR_imageless_framebuffer" +typedef VkPhysicalDeviceImagelessFramebufferFeatures VkPhysicalDeviceImagelessFramebufferFeaturesKHR; + +typedef VkFramebufferAttachmentsCreateInfo VkFramebufferAttachmentsCreateInfoKHR; + +typedef VkFramebufferAttachmentImageInfo VkFramebufferAttachmentImageInfoKHR; + +typedef VkRenderPassAttachmentBeginInfo VkRenderPassAttachmentBeginInfoKHR; + + + +#define VK_KHR_create_renderpass2 1 +#define VK_KHR_CREATE_RENDERPASS_2_SPEC_VERSION 1 +#define VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME "VK_KHR_create_renderpass2" +typedef VkRenderPassCreateInfo2 VkRenderPassCreateInfo2KHR; + +typedef VkAttachmentDescription2 VkAttachmentDescription2KHR; + +typedef VkAttachmentReference2 VkAttachmentReference2KHR; + +typedef VkSubpassDescription2 VkSubpassDescription2KHR; + +typedef VkSubpassDependency2 VkSubpassDependency2KHR; + +typedef VkSubpassBeginInfo VkSubpassBeginInfoKHR; + +typedef VkSubpassEndInfo VkSubpassEndInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateRenderPass2KHR)(VkDevice device, const VkRenderPassCreateInfo2* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass); +typedef void (VKAPI_PTR *PFN_vkCmdBeginRenderPass2KHR)(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, const VkSubpassBeginInfo* pSubpassBeginInfo); +typedef void (VKAPI_PTR *PFN_vkCmdNextSubpass2KHR)(VkCommandBuffer commandBuffer, const VkSubpassBeginInfo* pSubpassBeginInfo, const VkSubpassEndInfo* pSubpassEndInfo); +typedef void (VKAPI_PTR *PFN_vkCmdEndRenderPass2KHR)(VkCommandBuffer commandBuffer, const VkSubpassEndInfo* pSubpassEndInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateRenderPass2KHR( + VkDevice device, + const VkRenderPassCreateInfo2* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkRenderPass* pRenderPass); + +VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderPass2KHR( + VkCommandBuffer commandBuffer, + const VkRenderPassBeginInfo* pRenderPassBegin, + const VkSubpassBeginInfo* pSubpassBeginInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdNextSubpass2KHR( + VkCommandBuffer commandBuffer, + const VkSubpassBeginInfo* pSubpassBeginInfo, + const VkSubpassEndInfo* pSubpassEndInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderPass2KHR( + VkCommandBuffer commandBuffer, + const VkSubpassEndInfo* pSubpassEndInfo); +#endif + + +#define VK_KHR_shared_presentable_image 1 +#define VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION 1 +#define VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME "VK_KHR_shared_presentable_image" +typedef struct VkSharedPresentSurfaceCapabilitiesKHR { + VkStructureType sType; + void* pNext; + VkImageUsageFlags sharedPresentSupportedUsageFlags; +} VkSharedPresentSurfaceCapabilitiesKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainStatusKHR)(VkDevice device, VkSwapchainKHR swapchain); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainStatusKHR( + VkDevice device, + VkSwapchainKHR swapchain); +#endif + + +#define VK_KHR_external_fence_capabilities 1 +#define VK_KHR_EXTERNAL_FENCE_CAPABILITIES_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_fence_capabilities" +typedef VkExternalFenceHandleTypeFlags VkExternalFenceHandleTypeFlagsKHR; + +typedef VkExternalFenceHandleTypeFlagBits VkExternalFenceHandleTypeFlagBitsKHR; + +typedef VkExternalFenceFeatureFlags VkExternalFenceFeatureFlagsKHR; + +typedef VkExternalFenceFeatureFlagBits VkExternalFenceFeatureFlagBitsKHR; + +typedef VkPhysicalDeviceExternalFenceInfo VkPhysicalDeviceExternalFenceInfoKHR; + +typedef VkExternalFenceProperties VkExternalFencePropertiesKHR; + +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalFencePropertiesKHR( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, + VkExternalFenceProperties* pExternalFenceProperties); +#endif + + +#define VK_KHR_external_fence 1 +#define VK_KHR_EXTERNAL_FENCE_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_FENCE_EXTENSION_NAME "VK_KHR_external_fence" +typedef VkFenceImportFlags VkFenceImportFlagsKHR; + +typedef VkFenceImportFlagBits VkFenceImportFlagBitsKHR; + +typedef VkExportFenceCreateInfo VkExportFenceCreateInfoKHR; + + + +#define VK_KHR_external_fence_fd 1 +#define VK_KHR_EXTERNAL_FENCE_FD_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME "VK_KHR_external_fence_fd" +typedef struct VkImportFenceFdInfoKHR { + VkStructureType sType; + const void* pNext; + VkFence fence; + VkFenceImportFlags flags; + VkExternalFenceHandleTypeFlagBits handleType; + int fd; +} VkImportFenceFdInfoKHR; + +typedef struct VkFenceGetFdInfoKHR { + VkStructureType sType; + const void* pNext; + VkFence fence; + VkExternalFenceHandleTypeFlagBits handleType; +} VkFenceGetFdInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkImportFenceFdKHR)(VkDevice device, const VkImportFenceFdInfoKHR* pImportFenceFdInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetFenceFdKHR)(VkDevice device, const VkFenceGetFdInfoKHR* pGetFdInfo, int* pFd); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkImportFenceFdKHR( + VkDevice device, + const VkImportFenceFdInfoKHR* pImportFenceFdInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceFdKHR( + VkDevice device, + const VkFenceGetFdInfoKHR* pGetFdInfo, + int* pFd); +#endif + + +#define VK_KHR_performance_query 1 +#define VK_KHR_PERFORMANCE_QUERY_SPEC_VERSION 1 +#define VK_KHR_PERFORMANCE_QUERY_EXTENSION_NAME "VK_KHR_performance_query" + +typedef enum VkPerformanceCounterUnitKHR { + VK_PERFORMANCE_COUNTER_UNIT_GENERIC_KHR = 0, + VK_PERFORMANCE_COUNTER_UNIT_PERCENTAGE_KHR = 1, + VK_PERFORMANCE_COUNTER_UNIT_NANOSECONDS_KHR = 2, + VK_PERFORMANCE_COUNTER_UNIT_BYTES_KHR = 3, + VK_PERFORMANCE_COUNTER_UNIT_BYTES_PER_SECOND_KHR = 4, + VK_PERFORMANCE_COUNTER_UNIT_KELVIN_KHR = 5, + VK_PERFORMANCE_COUNTER_UNIT_WATTS_KHR = 6, + VK_PERFORMANCE_COUNTER_UNIT_VOLTS_KHR = 7, + VK_PERFORMANCE_COUNTER_UNIT_AMPS_KHR = 8, + VK_PERFORMANCE_COUNTER_UNIT_HERTZ_KHR = 9, + VK_PERFORMANCE_COUNTER_UNIT_CYCLES_KHR = 10, + VK_PERFORMANCE_COUNTER_UNIT_MAX_ENUM_KHR = 0x7FFFFFFF +} VkPerformanceCounterUnitKHR; + +typedef enum VkPerformanceCounterScopeKHR { + VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_BUFFER_KHR = 0, + VK_PERFORMANCE_COUNTER_SCOPE_RENDER_PASS_KHR = 1, + VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_KHR = 2, + VK_QUERY_SCOPE_COMMAND_BUFFER_KHR = VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_BUFFER_KHR, + VK_QUERY_SCOPE_RENDER_PASS_KHR = VK_PERFORMANCE_COUNTER_SCOPE_RENDER_PASS_KHR, + VK_QUERY_SCOPE_COMMAND_KHR = VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_KHR, + VK_PERFORMANCE_COUNTER_SCOPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkPerformanceCounterScopeKHR; + +typedef enum VkPerformanceCounterStorageKHR { + VK_PERFORMANCE_COUNTER_STORAGE_INT32_KHR = 0, + VK_PERFORMANCE_COUNTER_STORAGE_INT64_KHR = 1, + VK_PERFORMANCE_COUNTER_STORAGE_UINT32_KHR = 2, + VK_PERFORMANCE_COUNTER_STORAGE_UINT64_KHR = 3, + VK_PERFORMANCE_COUNTER_STORAGE_FLOAT32_KHR = 4, + VK_PERFORMANCE_COUNTER_STORAGE_FLOAT64_KHR = 5, + VK_PERFORMANCE_COUNTER_STORAGE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkPerformanceCounterStorageKHR; + +typedef enum VkPerformanceCounterDescriptionFlagBitsKHR { + VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_BIT_KHR = 0x00000001, + VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_BIT_KHR = 0x00000002, + VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_KHR = VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_BIT_KHR, + VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_KHR = VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_BIT_KHR, + VK_PERFORMANCE_COUNTER_DESCRIPTION_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkPerformanceCounterDescriptionFlagBitsKHR; +typedef VkFlags VkPerformanceCounterDescriptionFlagsKHR; + +typedef enum VkAcquireProfilingLockFlagBitsKHR { + VK_ACQUIRE_PROFILING_LOCK_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAcquireProfilingLockFlagBitsKHR; +typedef VkFlags VkAcquireProfilingLockFlagsKHR; +typedef struct VkPhysicalDevicePerformanceQueryFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 performanceCounterQueryPools; + VkBool32 performanceCounterMultipleQueryPools; +} VkPhysicalDevicePerformanceQueryFeaturesKHR; + +typedef struct VkPhysicalDevicePerformanceQueryPropertiesKHR { + VkStructureType sType; + void* pNext; + VkBool32 allowCommandBufferQueryCopies; +} VkPhysicalDevicePerformanceQueryPropertiesKHR; + +typedef struct VkPerformanceCounterKHR { + VkStructureType sType; + void* pNext; + VkPerformanceCounterUnitKHR unit; + VkPerformanceCounterScopeKHR scope; + VkPerformanceCounterStorageKHR storage; + uint8_t uuid[VK_UUID_SIZE]; +} VkPerformanceCounterKHR; + +typedef struct VkPerformanceCounterDescriptionKHR { + VkStructureType sType; + void* pNext; + VkPerformanceCounterDescriptionFlagsKHR flags; + char name[VK_MAX_DESCRIPTION_SIZE]; + char category[VK_MAX_DESCRIPTION_SIZE]; + char description[VK_MAX_DESCRIPTION_SIZE]; +} VkPerformanceCounterDescriptionKHR; + +typedef struct VkQueryPoolPerformanceCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t queueFamilyIndex; + uint32_t counterIndexCount; + const uint32_t* pCounterIndices; +} VkQueryPoolPerformanceCreateInfoKHR; + +typedef union VkPerformanceCounterResultKHR { + int32_t int32; + int64_t int64; + uint32_t uint32; + uint64_t uint64; + float float32; + double float64; +} VkPerformanceCounterResultKHR; + +typedef struct VkAcquireProfilingLockInfoKHR { + VkStructureType sType; + const void* pNext; + VkAcquireProfilingLockFlagsKHR flags; + uint64_t timeout; +} VkAcquireProfilingLockInfoKHR; + +typedef struct VkPerformanceQuerySubmitInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t counterPassIndex; +} VkPerformanceQuerySubmitInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, uint32_t* pCounterCount, VkPerformanceCounterKHR* pCounters, VkPerformanceCounterDescriptionKHR* pCounterDescriptions); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR)(VkPhysicalDevice physicalDevice, const VkQueryPoolPerformanceCreateInfoKHR* pPerformanceQueryCreateInfo, uint32_t* pNumPasses); +typedef VkResult (VKAPI_PTR *PFN_vkAcquireProfilingLockKHR)(VkDevice device, const VkAcquireProfilingLockInfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkReleaseProfilingLockKHR)(VkDevice device); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR( + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + uint32_t* pCounterCount, + VkPerformanceCounterKHR* pCounters, + VkPerformanceCounterDescriptionKHR* pCounterDescriptions); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR( + VkPhysicalDevice physicalDevice, + const VkQueryPoolPerformanceCreateInfoKHR* pPerformanceQueryCreateInfo, + uint32_t* pNumPasses); + +VKAPI_ATTR VkResult VKAPI_CALL vkAcquireProfilingLockKHR( + VkDevice device, + const VkAcquireProfilingLockInfoKHR* pInfo); + +VKAPI_ATTR void VKAPI_CALL vkReleaseProfilingLockKHR( + VkDevice device); +#endif + + +#define VK_KHR_maintenance2 1 +#define VK_KHR_MAINTENANCE_2_SPEC_VERSION 1 +#define VK_KHR_MAINTENANCE_2_EXTENSION_NAME "VK_KHR_maintenance2" +#define VK_KHR_MAINTENANCE2_SPEC_VERSION VK_KHR_MAINTENANCE_2_SPEC_VERSION +#define VK_KHR_MAINTENANCE2_EXTENSION_NAME VK_KHR_MAINTENANCE_2_EXTENSION_NAME +typedef VkPointClippingBehavior VkPointClippingBehaviorKHR; + +typedef VkTessellationDomainOrigin VkTessellationDomainOriginKHR; + +typedef VkPhysicalDevicePointClippingProperties VkPhysicalDevicePointClippingPropertiesKHR; + +typedef VkRenderPassInputAttachmentAspectCreateInfo VkRenderPassInputAttachmentAspectCreateInfoKHR; + +typedef VkInputAttachmentAspectReference VkInputAttachmentAspectReferenceKHR; + +typedef VkImageViewUsageCreateInfo VkImageViewUsageCreateInfoKHR; + +typedef VkPipelineTessellationDomainOriginStateCreateInfo VkPipelineTessellationDomainOriginStateCreateInfoKHR; + + + +#define VK_KHR_get_surface_capabilities2 1 +#define VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION 1 +#define VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME "VK_KHR_get_surface_capabilities2" +typedef struct VkPhysicalDeviceSurfaceInfo2KHR { + VkStructureType sType; + const void* pNext; + VkSurfaceKHR surface; +} VkPhysicalDeviceSurfaceInfo2KHR; + +typedef struct VkSurfaceCapabilities2KHR { + VkStructureType sType; + void* pNext; + VkSurfaceCapabilitiesKHR surfaceCapabilities; +} VkSurfaceCapabilities2KHR; + +typedef struct VkSurfaceFormat2KHR { + VkStructureType sType; + void* pNext; + VkSurfaceFormatKHR surfaceFormat; +} VkSurfaceFormat2KHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkSurfaceCapabilities2KHR* pSurfaceCapabilities); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceFormats2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, uint32_t* pSurfaceFormatCount, VkSurfaceFormat2KHR* pSurfaceFormats); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilities2KHR( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, + VkSurfaceCapabilities2KHR* pSurfaceCapabilities); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormats2KHR( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, + uint32_t* pSurfaceFormatCount, + VkSurfaceFormat2KHR* pSurfaceFormats); +#endif + + +#define VK_KHR_variable_pointers 1 +#define VK_KHR_VARIABLE_POINTERS_SPEC_VERSION 1 +#define VK_KHR_VARIABLE_POINTERS_EXTENSION_NAME "VK_KHR_variable_pointers" +typedef VkPhysicalDeviceVariablePointersFeatures VkPhysicalDeviceVariablePointerFeaturesKHR; + +typedef VkPhysicalDeviceVariablePointersFeatures VkPhysicalDeviceVariablePointersFeaturesKHR; + + + +#define VK_KHR_get_display_properties2 1 +#define VK_KHR_GET_DISPLAY_PROPERTIES_2_SPEC_VERSION 1 +#define VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME "VK_KHR_get_display_properties2" +typedef struct VkDisplayProperties2KHR { + VkStructureType sType; + void* pNext; + VkDisplayPropertiesKHR displayProperties; +} VkDisplayProperties2KHR; + +typedef struct VkDisplayPlaneProperties2KHR { + VkStructureType sType; + void* pNext; + VkDisplayPlanePropertiesKHR displayPlaneProperties; +} VkDisplayPlaneProperties2KHR; + +typedef struct VkDisplayModeProperties2KHR { + VkStructureType sType; + void* pNext; + VkDisplayModePropertiesKHR displayModeProperties; +} VkDisplayModeProperties2KHR; + +typedef struct VkDisplayPlaneInfo2KHR { + VkStructureType sType; + const void* pNext; + VkDisplayModeKHR mode; + uint32_t planeIndex; +} VkDisplayPlaneInfo2KHR; + +typedef struct VkDisplayPlaneCapabilities2KHR { + VkStructureType sType; + void* pNext; + VkDisplayPlaneCapabilitiesKHR capabilities; +} VkDisplayPlaneCapabilities2KHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayProperties2KHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayProperties2KHR* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayPlaneProperties2KHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPlaneProperties2KHR* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayModeProperties2KHR)(VkPhysicalDevice physicalDevice, VkDisplayKHR display, uint32_t* pPropertyCount, VkDisplayModeProperties2KHR* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayPlaneCapabilities2KHR)(VkPhysicalDevice physicalDevice, const VkDisplayPlaneInfo2KHR* pDisplayPlaneInfo, VkDisplayPlaneCapabilities2KHR* pCapabilities); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayProperties2KHR( + VkPhysicalDevice physicalDevice, + uint32_t* pPropertyCount, + VkDisplayProperties2KHR* pProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPlaneProperties2KHR( + VkPhysicalDevice physicalDevice, + uint32_t* pPropertyCount, + VkDisplayPlaneProperties2KHR* pProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayModeProperties2KHR( + VkPhysicalDevice physicalDevice, + VkDisplayKHR display, + uint32_t* pPropertyCount, + VkDisplayModeProperties2KHR* pProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneCapabilities2KHR( + VkPhysicalDevice physicalDevice, + const VkDisplayPlaneInfo2KHR* pDisplayPlaneInfo, + VkDisplayPlaneCapabilities2KHR* pCapabilities); +#endif + + +#define VK_KHR_dedicated_allocation 1 +#define VK_KHR_DEDICATED_ALLOCATION_SPEC_VERSION 3 +#define VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME "VK_KHR_dedicated_allocation" +typedef VkMemoryDedicatedRequirements VkMemoryDedicatedRequirementsKHR; + +typedef VkMemoryDedicatedAllocateInfo VkMemoryDedicatedAllocateInfoKHR; + + + +#define VK_KHR_storage_buffer_storage_class 1 +#define VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_SPEC_VERSION 1 +#define VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME "VK_KHR_storage_buffer_storage_class" + + +#define VK_KHR_relaxed_block_layout 1 +#define VK_KHR_RELAXED_BLOCK_LAYOUT_SPEC_VERSION 1 +#define VK_KHR_RELAXED_BLOCK_LAYOUT_EXTENSION_NAME "VK_KHR_relaxed_block_layout" + + +#define VK_KHR_get_memory_requirements2 1 +#define VK_KHR_GET_MEMORY_REQUIREMENTS_2_SPEC_VERSION 1 +#define VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME "VK_KHR_get_memory_requirements2" +typedef VkBufferMemoryRequirementsInfo2 VkBufferMemoryRequirementsInfo2KHR; + +typedef VkImageMemoryRequirementsInfo2 VkImageMemoryRequirementsInfo2KHR; + +typedef VkImageSparseMemoryRequirementsInfo2 VkImageSparseMemoryRequirementsInfo2KHR; + +typedef VkMemoryRequirements2 VkMemoryRequirements2KHR; + +typedef VkSparseImageMemoryRequirements2 VkSparseImageMemoryRequirements2KHR; + +typedef void (VKAPI_PTR *PFN_vkGetImageMemoryRequirements2KHR)(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetBufferMemoryRequirements2KHR)(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetImageSparseMemoryRequirements2KHR)(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetImageMemoryRequirements2KHR( + VkDevice device, + const VkImageMemoryRequirementsInfo2* pInfo, + VkMemoryRequirements2* pMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkGetBufferMemoryRequirements2KHR( + VkDevice device, + const VkBufferMemoryRequirementsInfo2* pInfo, + VkMemoryRequirements2* pMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkGetImageSparseMemoryRequirements2KHR( + VkDevice device, + const VkImageSparseMemoryRequirementsInfo2* pInfo, + uint32_t* pSparseMemoryRequirementCount, + VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); +#endif + + +#define VK_KHR_image_format_list 1 +#define VK_KHR_IMAGE_FORMAT_LIST_SPEC_VERSION 1 +#define VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME "VK_KHR_image_format_list" +typedef VkImageFormatListCreateInfo VkImageFormatListCreateInfoKHR; + + + +#define VK_KHR_sampler_ycbcr_conversion 1 +typedef VkSamplerYcbcrConversion VkSamplerYcbcrConversionKHR; + +#define VK_KHR_SAMPLER_YCBCR_CONVERSION_SPEC_VERSION 14 +#define VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME "VK_KHR_sampler_ycbcr_conversion" +typedef VkSamplerYcbcrModelConversion VkSamplerYcbcrModelConversionKHR; + +typedef VkSamplerYcbcrRange VkSamplerYcbcrRangeKHR; + +typedef VkChromaLocation VkChromaLocationKHR; + +typedef VkSamplerYcbcrConversionCreateInfo VkSamplerYcbcrConversionCreateInfoKHR; + +typedef VkSamplerYcbcrConversionInfo VkSamplerYcbcrConversionInfoKHR; + +typedef VkBindImagePlaneMemoryInfo VkBindImagePlaneMemoryInfoKHR; + +typedef VkImagePlaneMemoryRequirementsInfo VkImagePlaneMemoryRequirementsInfoKHR; + +typedef VkPhysicalDeviceSamplerYcbcrConversionFeatures VkPhysicalDeviceSamplerYcbcrConversionFeaturesKHR; + +typedef VkSamplerYcbcrConversionImageFormatProperties VkSamplerYcbcrConversionImageFormatPropertiesKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateSamplerYcbcrConversionKHR)(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion); +typedef void (VKAPI_PTR *PFN_vkDestroySamplerYcbcrConversionKHR)(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateSamplerYcbcrConversionKHR( + VkDevice device, + const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSamplerYcbcrConversion* pYcbcrConversion); + +VKAPI_ATTR void VKAPI_CALL vkDestroySamplerYcbcrConversionKHR( + VkDevice device, + VkSamplerYcbcrConversion ycbcrConversion, + const VkAllocationCallbacks* pAllocator); +#endif + + +#define VK_KHR_bind_memory2 1 +#define VK_KHR_BIND_MEMORY_2_SPEC_VERSION 1 +#define VK_KHR_BIND_MEMORY_2_EXTENSION_NAME "VK_KHR_bind_memory2" +typedef VkBindBufferMemoryInfo VkBindBufferMemoryInfoKHR; + +typedef VkBindImageMemoryInfo VkBindImageMemoryInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkBindBufferMemory2KHR)(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos); +typedef VkResult (VKAPI_PTR *PFN_vkBindImageMemory2KHR)(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkBindBufferMemory2KHR( + VkDevice device, + uint32_t bindInfoCount, + const VkBindBufferMemoryInfo* pBindInfos); + +VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory2KHR( + VkDevice device, + uint32_t bindInfoCount, + const VkBindImageMemoryInfo* pBindInfos); +#endif + + +#define VK_KHR_maintenance3 1 +#define VK_KHR_MAINTENANCE_3_SPEC_VERSION 1 +#define VK_KHR_MAINTENANCE_3_EXTENSION_NAME "VK_KHR_maintenance3" +#define VK_KHR_MAINTENANCE3_SPEC_VERSION VK_KHR_MAINTENANCE_3_SPEC_VERSION +#define VK_KHR_MAINTENANCE3_EXTENSION_NAME VK_KHR_MAINTENANCE_3_EXTENSION_NAME +typedef VkPhysicalDeviceMaintenance3Properties VkPhysicalDeviceMaintenance3PropertiesKHR; + +typedef VkDescriptorSetLayoutSupport VkDescriptorSetLayoutSupportKHR; + +typedef void (VKAPI_PTR *PFN_vkGetDescriptorSetLayoutSupportKHR)(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutSupportKHR( + VkDevice device, + const VkDescriptorSetLayoutCreateInfo* pCreateInfo, + VkDescriptorSetLayoutSupport* pSupport); +#endif + + +#define VK_KHR_draw_indirect_count 1 +#define VK_KHR_DRAW_INDIRECT_COUNT_SPEC_VERSION 1 +#define VK_KHR_DRAW_INDIRECT_COUNT_EXTENSION_NAME "VK_KHR_draw_indirect_count" +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectCountKHR)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirectCountKHR)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectCountKHR( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkBuffer countBuffer, + VkDeviceSize countBufferOffset, + uint32_t maxDrawCount, + uint32_t stride); + +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCountKHR( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkBuffer countBuffer, + VkDeviceSize countBufferOffset, + uint32_t maxDrawCount, + uint32_t stride); +#endif + + +#define VK_KHR_shader_subgroup_extended_types 1 +#define VK_KHR_SHADER_SUBGROUP_EXTENDED_TYPES_SPEC_VERSION 1 +#define VK_KHR_SHADER_SUBGROUP_EXTENDED_TYPES_EXTENSION_NAME "VK_KHR_shader_subgroup_extended_types" +typedef VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures VkPhysicalDeviceShaderSubgroupExtendedTypesFeaturesKHR; + + + +#define VK_KHR_8bit_storage 1 +#define VK_KHR_8BIT_STORAGE_SPEC_VERSION 1 +#define VK_KHR_8BIT_STORAGE_EXTENSION_NAME "VK_KHR_8bit_storage" +typedef VkPhysicalDevice8BitStorageFeatures VkPhysicalDevice8BitStorageFeaturesKHR; + + + +#define VK_KHR_shader_atomic_int64 1 +#define VK_KHR_SHADER_ATOMIC_INT64_SPEC_VERSION 1 +#define VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME "VK_KHR_shader_atomic_int64" +typedef VkPhysicalDeviceShaderAtomicInt64Features VkPhysicalDeviceShaderAtomicInt64FeaturesKHR; + + + +#define VK_KHR_shader_clock 1 +#define VK_KHR_SHADER_CLOCK_SPEC_VERSION 1 +#define VK_KHR_SHADER_CLOCK_EXTENSION_NAME "VK_KHR_shader_clock" +typedef struct VkPhysicalDeviceShaderClockFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 shaderSubgroupClock; + VkBool32 shaderDeviceClock; +} VkPhysicalDeviceShaderClockFeaturesKHR; + + + +#define VK_KHR_global_priority 1 +#define VK_MAX_GLOBAL_PRIORITY_SIZE_KHR 16U +#define VK_KHR_GLOBAL_PRIORITY_SPEC_VERSION 1 +#define VK_KHR_GLOBAL_PRIORITY_EXTENSION_NAME "VK_KHR_global_priority" + +typedef enum VkQueueGlobalPriorityKHR { + VK_QUEUE_GLOBAL_PRIORITY_LOW_KHR = 128, + VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_KHR = 256, + VK_QUEUE_GLOBAL_PRIORITY_HIGH_KHR = 512, + VK_QUEUE_GLOBAL_PRIORITY_REALTIME_KHR = 1024, + VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT = VK_QUEUE_GLOBAL_PRIORITY_LOW_KHR, + VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT = VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_KHR, + VK_QUEUE_GLOBAL_PRIORITY_HIGH_EXT = VK_QUEUE_GLOBAL_PRIORITY_HIGH_KHR, + VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT = VK_QUEUE_GLOBAL_PRIORITY_REALTIME_KHR, + VK_QUEUE_GLOBAL_PRIORITY_MAX_ENUM_KHR = 0x7FFFFFFF +} VkQueueGlobalPriorityKHR; +typedef struct VkDeviceQueueGlobalPriorityCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkQueueGlobalPriorityKHR globalPriority; +} VkDeviceQueueGlobalPriorityCreateInfoKHR; + +typedef struct VkPhysicalDeviceGlobalPriorityQueryFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 globalPriorityQuery; +} VkPhysicalDeviceGlobalPriorityQueryFeaturesKHR; + +typedef struct VkQueueFamilyGlobalPriorityPropertiesKHR { + VkStructureType sType; + void* pNext; + uint32_t priorityCount; + VkQueueGlobalPriorityKHR priorities[VK_MAX_GLOBAL_PRIORITY_SIZE_KHR]; +} VkQueueFamilyGlobalPriorityPropertiesKHR; + + + +#define VK_KHR_driver_properties 1 +#define VK_KHR_DRIVER_PROPERTIES_SPEC_VERSION 1 +#define VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME "VK_KHR_driver_properties" +#define VK_MAX_DRIVER_NAME_SIZE_KHR VK_MAX_DRIVER_NAME_SIZE +#define VK_MAX_DRIVER_INFO_SIZE_KHR VK_MAX_DRIVER_INFO_SIZE +typedef VkDriverId VkDriverIdKHR; + +typedef VkConformanceVersion VkConformanceVersionKHR; + +typedef VkPhysicalDeviceDriverProperties VkPhysicalDeviceDriverPropertiesKHR; + + + +#define VK_KHR_shader_float_controls 1 +#define VK_KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION 4 +#define VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME "VK_KHR_shader_float_controls" +typedef VkShaderFloatControlsIndependence VkShaderFloatControlsIndependenceKHR; + +typedef VkPhysicalDeviceFloatControlsProperties VkPhysicalDeviceFloatControlsPropertiesKHR; + + + +#define VK_KHR_depth_stencil_resolve 1 +#define VK_KHR_DEPTH_STENCIL_RESOLVE_SPEC_VERSION 1 +#define VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME "VK_KHR_depth_stencil_resolve" +typedef VkResolveModeFlagBits VkResolveModeFlagBitsKHR; + +typedef VkResolveModeFlags VkResolveModeFlagsKHR; + +typedef VkSubpassDescriptionDepthStencilResolve VkSubpassDescriptionDepthStencilResolveKHR; + +typedef VkPhysicalDeviceDepthStencilResolveProperties VkPhysicalDeviceDepthStencilResolvePropertiesKHR; + + + +#define VK_KHR_swapchain_mutable_format 1 +#define VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_SPEC_VERSION 1 +#define VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_EXTENSION_NAME "VK_KHR_swapchain_mutable_format" + + +#define VK_KHR_timeline_semaphore 1 +#define VK_KHR_TIMELINE_SEMAPHORE_SPEC_VERSION 2 +#define VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME "VK_KHR_timeline_semaphore" +typedef VkSemaphoreType VkSemaphoreTypeKHR; + +typedef VkSemaphoreWaitFlagBits VkSemaphoreWaitFlagBitsKHR; + +typedef VkSemaphoreWaitFlags VkSemaphoreWaitFlagsKHR; + +typedef VkPhysicalDeviceTimelineSemaphoreFeatures VkPhysicalDeviceTimelineSemaphoreFeaturesKHR; + +typedef VkPhysicalDeviceTimelineSemaphoreProperties VkPhysicalDeviceTimelineSemaphorePropertiesKHR; + +typedef VkSemaphoreTypeCreateInfo VkSemaphoreTypeCreateInfoKHR; + +typedef VkTimelineSemaphoreSubmitInfo VkTimelineSemaphoreSubmitInfoKHR; + +typedef VkSemaphoreWaitInfo VkSemaphoreWaitInfoKHR; + +typedef VkSemaphoreSignalInfo VkSemaphoreSignalInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreCounterValueKHR)(VkDevice device, VkSemaphore semaphore, uint64_t* pValue); +typedef VkResult (VKAPI_PTR *PFN_vkWaitSemaphoresKHR)(VkDevice device, const VkSemaphoreWaitInfo* pWaitInfo, uint64_t timeout); +typedef VkResult (VKAPI_PTR *PFN_vkSignalSemaphoreKHR)(VkDevice device, const VkSemaphoreSignalInfo* pSignalInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreCounterValueKHR( + VkDevice device, + VkSemaphore semaphore, + uint64_t* pValue); + +VKAPI_ATTR VkResult VKAPI_CALL vkWaitSemaphoresKHR( + VkDevice device, + const VkSemaphoreWaitInfo* pWaitInfo, + uint64_t timeout); + +VKAPI_ATTR VkResult VKAPI_CALL vkSignalSemaphoreKHR( + VkDevice device, + const VkSemaphoreSignalInfo* pSignalInfo); +#endif + + +#define VK_KHR_vulkan_memory_model 1 +#define VK_KHR_VULKAN_MEMORY_MODEL_SPEC_VERSION 3 +#define VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME "VK_KHR_vulkan_memory_model" +typedef VkPhysicalDeviceVulkanMemoryModelFeatures VkPhysicalDeviceVulkanMemoryModelFeaturesKHR; + + + +#define VK_KHR_shader_terminate_invocation 1 +#define VK_KHR_SHADER_TERMINATE_INVOCATION_SPEC_VERSION 1 +#define VK_KHR_SHADER_TERMINATE_INVOCATION_EXTENSION_NAME "VK_KHR_shader_terminate_invocation" +typedef VkPhysicalDeviceShaderTerminateInvocationFeatures VkPhysicalDeviceShaderTerminateInvocationFeaturesKHR; + + + +#define VK_KHR_fragment_shading_rate 1 +#define VK_KHR_FRAGMENT_SHADING_RATE_SPEC_VERSION 2 +#define VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME "VK_KHR_fragment_shading_rate" + +typedef enum VkFragmentShadingRateCombinerOpKHR { + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR = 0, + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR = 1, + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_KHR = 2, + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_KHR = 3, + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_KHR = 4, + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_ENUM_KHR = 0x7FFFFFFF +} VkFragmentShadingRateCombinerOpKHR; +typedef struct VkFragmentShadingRateAttachmentInfoKHR { + VkStructureType sType; + const void* pNext; + const VkAttachmentReference2* pFragmentShadingRateAttachment; + VkExtent2D shadingRateAttachmentTexelSize; +} VkFragmentShadingRateAttachmentInfoKHR; + +typedef struct VkPipelineFragmentShadingRateStateCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkExtent2D fragmentSize; + VkFragmentShadingRateCombinerOpKHR combinerOps[2]; +} VkPipelineFragmentShadingRateStateCreateInfoKHR; + +typedef struct VkPhysicalDeviceFragmentShadingRateFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 pipelineFragmentShadingRate; + VkBool32 primitiveFragmentShadingRate; + VkBool32 attachmentFragmentShadingRate; +} VkPhysicalDeviceFragmentShadingRateFeaturesKHR; + +typedef struct VkPhysicalDeviceFragmentShadingRatePropertiesKHR { + VkStructureType sType; + void* pNext; + VkExtent2D minFragmentShadingRateAttachmentTexelSize; + VkExtent2D maxFragmentShadingRateAttachmentTexelSize; + uint32_t maxFragmentShadingRateAttachmentTexelSizeAspectRatio; + VkBool32 primitiveFragmentShadingRateWithMultipleViewports; + VkBool32 layeredShadingRateAttachments; + VkBool32 fragmentShadingRateNonTrivialCombinerOps; + VkExtent2D maxFragmentSize; + uint32_t maxFragmentSizeAspectRatio; + uint32_t maxFragmentShadingRateCoverageSamples; + VkSampleCountFlagBits maxFragmentShadingRateRasterizationSamples; + VkBool32 fragmentShadingRateWithShaderDepthStencilWrites; + VkBool32 fragmentShadingRateWithSampleMask; + VkBool32 fragmentShadingRateWithShaderSampleMask; + VkBool32 fragmentShadingRateWithConservativeRasterization; + VkBool32 fragmentShadingRateWithFragmentShaderInterlock; + VkBool32 fragmentShadingRateWithCustomSampleLocations; + VkBool32 fragmentShadingRateStrictMultiplyCombiner; +} VkPhysicalDeviceFragmentShadingRatePropertiesKHR; + +typedef struct VkPhysicalDeviceFragmentShadingRateKHR { + VkStructureType sType; + void* pNext; + VkSampleCountFlags sampleCounts; + VkExtent2D fragmentSize; +} VkPhysicalDeviceFragmentShadingRateKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceFragmentShadingRatesKHR)(VkPhysicalDevice physicalDevice, uint32_t* pFragmentShadingRateCount, VkPhysicalDeviceFragmentShadingRateKHR* pFragmentShadingRates); +typedef void (VKAPI_PTR *PFN_vkCmdSetFragmentShadingRateKHR)(VkCommandBuffer commandBuffer, const VkExtent2D* pFragmentSize, const VkFragmentShadingRateCombinerOpKHR combinerOps[2]); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceFragmentShadingRatesKHR( + VkPhysicalDevice physicalDevice, + uint32_t* pFragmentShadingRateCount, + VkPhysicalDeviceFragmentShadingRateKHR* pFragmentShadingRates); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetFragmentShadingRateKHR( + VkCommandBuffer commandBuffer, + const VkExtent2D* pFragmentSize, + const VkFragmentShadingRateCombinerOpKHR combinerOps[2]); +#endif + + +#define VK_KHR_spirv_1_4 1 +#define VK_KHR_SPIRV_1_4_SPEC_VERSION 1 +#define VK_KHR_SPIRV_1_4_EXTENSION_NAME "VK_KHR_spirv_1_4" + + +#define VK_KHR_surface_protected_capabilities 1 +#define VK_KHR_SURFACE_PROTECTED_CAPABILITIES_SPEC_VERSION 1 +#define VK_KHR_SURFACE_PROTECTED_CAPABILITIES_EXTENSION_NAME "VK_KHR_surface_protected_capabilities" +typedef struct VkSurfaceProtectedCapabilitiesKHR { + VkStructureType sType; + const void* pNext; + VkBool32 supportsProtected; +} VkSurfaceProtectedCapabilitiesKHR; + + + +#define VK_KHR_separate_depth_stencil_layouts 1 +#define VK_KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_SPEC_VERSION 1 +#define VK_KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_EXTENSION_NAME "VK_KHR_separate_depth_stencil_layouts" +typedef VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures VkPhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR; + +typedef VkAttachmentReferenceStencilLayout VkAttachmentReferenceStencilLayoutKHR; + +typedef VkAttachmentDescriptionStencilLayout VkAttachmentDescriptionStencilLayoutKHR; + + + +#define VK_KHR_present_wait 1 +#define VK_KHR_PRESENT_WAIT_SPEC_VERSION 1 +#define VK_KHR_PRESENT_WAIT_EXTENSION_NAME "VK_KHR_present_wait" +typedef struct VkPhysicalDevicePresentWaitFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 presentWait; +} VkPhysicalDevicePresentWaitFeaturesKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkWaitForPresentKHR)(VkDevice device, VkSwapchainKHR swapchain, uint64_t presentId, uint64_t timeout); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkWaitForPresentKHR( + VkDevice device, + VkSwapchainKHR swapchain, + uint64_t presentId, + uint64_t timeout); +#endif + + +#define VK_KHR_uniform_buffer_standard_layout 1 +#define VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_SPEC_VERSION 1 +#define VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_EXTENSION_NAME "VK_KHR_uniform_buffer_standard_layout" +typedef VkPhysicalDeviceUniformBufferStandardLayoutFeatures VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR; + + + +#define VK_KHR_buffer_device_address 1 +#define VK_KHR_BUFFER_DEVICE_ADDRESS_SPEC_VERSION 1 +#define VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME "VK_KHR_buffer_device_address" +typedef VkPhysicalDeviceBufferDeviceAddressFeatures VkPhysicalDeviceBufferDeviceAddressFeaturesKHR; + +typedef VkBufferDeviceAddressInfo VkBufferDeviceAddressInfoKHR; + +typedef VkBufferOpaqueCaptureAddressCreateInfo VkBufferOpaqueCaptureAddressCreateInfoKHR; + +typedef VkMemoryOpaqueCaptureAddressAllocateInfo VkMemoryOpaqueCaptureAddressAllocateInfoKHR; + +typedef VkDeviceMemoryOpaqueCaptureAddressInfo VkDeviceMemoryOpaqueCaptureAddressInfoKHR; + +typedef VkDeviceAddress (VKAPI_PTR *PFN_vkGetBufferDeviceAddressKHR)(VkDevice device, const VkBufferDeviceAddressInfo* pInfo); +typedef uint64_t (VKAPI_PTR *PFN_vkGetBufferOpaqueCaptureAddressKHR)(VkDevice device, const VkBufferDeviceAddressInfo* pInfo); +typedef uint64_t (VKAPI_PTR *PFN_vkGetDeviceMemoryOpaqueCaptureAddressKHR)(VkDevice device, const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetBufferDeviceAddressKHR( + VkDevice device, + const VkBufferDeviceAddressInfo* pInfo); + +VKAPI_ATTR uint64_t VKAPI_CALL vkGetBufferOpaqueCaptureAddressKHR( + VkDevice device, + const VkBufferDeviceAddressInfo* pInfo); + +VKAPI_ATTR uint64_t VKAPI_CALL vkGetDeviceMemoryOpaqueCaptureAddressKHR( + VkDevice device, + const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo); +#endif + + +#define VK_KHR_deferred_host_operations 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDeferredOperationKHR) +#define VK_KHR_DEFERRED_HOST_OPERATIONS_SPEC_VERSION 4 +#define VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME "VK_KHR_deferred_host_operations" +typedef VkResult (VKAPI_PTR *PFN_vkCreateDeferredOperationKHR)(VkDevice device, const VkAllocationCallbacks* pAllocator, VkDeferredOperationKHR* pDeferredOperation); +typedef void (VKAPI_PTR *PFN_vkDestroyDeferredOperationKHR)(VkDevice device, VkDeferredOperationKHR operation, const VkAllocationCallbacks* pAllocator); +typedef uint32_t (VKAPI_PTR *PFN_vkGetDeferredOperationMaxConcurrencyKHR)(VkDevice device, VkDeferredOperationKHR operation); +typedef VkResult (VKAPI_PTR *PFN_vkGetDeferredOperationResultKHR)(VkDevice device, VkDeferredOperationKHR operation); +typedef VkResult (VKAPI_PTR *PFN_vkDeferredOperationJoinKHR)(VkDevice device, VkDeferredOperationKHR operation); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDeferredOperationKHR( + VkDevice device, + const VkAllocationCallbacks* pAllocator, + VkDeferredOperationKHR* pDeferredOperation); + +VKAPI_ATTR void VKAPI_CALL vkDestroyDeferredOperationKHR( + VkDevice device, + VkDeferredOperationKHR operation, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR uint32_t VKAPI_CALL vkGetDeferredOperationMaxConcurrencyKHR( + VkDevice device, + VkDeferredOperationKHR operation); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetDeferredOperationResultKHR( + VkDevice device, + VkDeferredOperationKHR operation); + +VKAPI_ATTR VkResult VKAPI_CALL vkDeferredOperationJoinKHR( + VkDevice device, + VkDeferredOperationKHR operation); +#endif + + +#define VK_KHR_pipeline_executable_properties 1 +#define VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_SPEC_VERSION 1 +#define VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME "VK_KHR_pipeline_executable_properties" + +typedef enum VkPipelineExecutableStatisticFormatKHR { + VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_BOOL32_KHR = 0, + VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_INT64_KHR = 1, + VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR = 2, + VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_FLOAT64_KHR = 3, + VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_MAX_ENUM_KHR = 0x7FFFFFFF +} VkPipelineExecutableStatisticFormatKHR; +typedef struct VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 pipelineExecutableInfo; +} VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR; + +typedef struct VkPipelineInfoKHR { + VkStructureType sType; + const void* pNext; + VkPipeline pipeline; +} VkPipelineInfoKHR; + +typedef struct VkPipelineExecutablePropertiesKHR { + VkStructureType sType; + void* pNext; + VkShaderStageFlags stages; + char name[VK_MAX_DESCRIPTION_SIZE]; + char description[VK_MAX_DESCRIPTION_SIZE]; + uint32_t subgroupSize; +} VkPipelineExecutablePropertiesKHR; + +typedef struct VkPipelineExecutableInfoKHR { + VkStructureType sType; + const void* pNext; + VkPipeline pipeline; + uint32_t executableIndex; +} VkPipelineExecutableInfoKHR; + +typedef union VkPipelineExecutableStatisticValueKHR { + VkBool32 b32; + int64_t i64; + uint64_t u64; + double f64; +} VkPipelineExecutableStatisticValueKHR; + +typedef struct VkPipelineExecutableStatisticKHR { + VkStructureType sType; + void* pNext; + char name[VK_MAX_DESCRIPTION_SIZE]; + char description[VK_MAX_DESCRIPTION_SIZE]; + VkPipelineExecutableStatisticFormatKHR format; + VkPipelineExecutableStatisticValueKHR value; +} VkPipelineExecutableStatisticKHR; + +typedef struct VkPipelineExecutableInternalRepresentationKHR { + VkStructureType sType; + void* pNext; + char name[VK_MAX_DESCRIPTION_SIZE]; + char description[VK_MAX_DESCRIPTION_SIZE]; + VkBool32 isText; + size_t dataSize; + void* pData; +} VkPipelineExecutableInternalRepresentationKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPipelineExecutablePropertiesKHR)(VkDevice device, const VkPipelineInfoKHR* pPipelineInfo, uint32_t* pExecutableCount, VkPipelineExecutablePropertiesKHR* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetPipelineExecutableStatisticsKHR)(VkDevice device, const VkPipelineExecutableInfoKHR* pExecutableInfo, uint32_t* pStatisticCount, VkPipelineExecutableStatisticKHR* pStatistics); +typedef VkResult (VKAPI_PTR *PFN_vkGetPipelineExecutableInternalRepresentationsKHR)(VkDevice device, const VkPipelineExecutableInfoKHR* pExecutableInfo, uint32_t* pInternalRepresentationCount, VkPipelineExecutableInternalRepresentationKHR* pInternalRepresentations); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineExecutablePropertiesKHR( + VkDevice device, + const VkPipelineInfoKHR* pPipelineInfo, + uint32_t* pExecutableCount, + VkPipelineExecutablePropertiesKHR* pProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineExecutableStatisticsKHR( + VkDevice device, + const VkPipelineExecutableInfoKHR* pExecutableInfo, + uint32_t* pStatisticCount, + VkPipelineExecutableStatisticKHR* pStatistics); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineExecutableInternalRepresentationsKHR( + VkDevice device, + const VkPipelineExecutableInfoKHR* pExecutableInfo, + uint32_t* pInternalRepresentationCount, + VkPipelineExecutableInternalRepresentationKHR* pInternalRepresentations); +#endif + + +#define VK_KHR_shader_integer_dot_product 1 +#define VK_KHR_SHADER_INTEGER_DOT_PRODUCT_SPEC_VERSION 1 +#define VK_KHR_SHADER_INTEGER_DOT_PRODUCT_EXTENSION_NAME "VK_KHR_shader_integer_dot_product" +typedef VkPhysicalDeviceShaderIntegerDotProductFeatures VkPhysicalDeviceShaderIntegerDotProductFeaturesKHR; + +typedef VkPhysicalDeviceShaderIntegerDotProductProperties VkPhysicalDeviceShaderIntegerDotProductPropertiesKHR; + + + +#define VK_KHR_pipeline_library 1 +#define VK_KHR_PIPELINE_LIBRARY_SPEC_VERSION 1 +#define VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME "VK_KHR_pipeline_library" +typedef struct VkPipelineLibraryCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t libraryCount; + const VkPipeline* pLibraries; +} VkPipelineLibraryCreateInfoKHR; + + + +#define VK_KHR_shader_non_semantic_info 1 +#define VK_KHR_SHADER_NON_SEMANTIC_INFO_SPEC_VERSION 1 +#define VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME "VK_KHR_shader_non_semantic_info" + + +#define VK_KHR_present_id 1 +#define VK_KHR_PRESENT_ID_SPEC_VERSION 1 +#define VK_KHR_PRESENT_ID_EXTENSION_NAME "VK_KHR_present_id" +typedef struct VkPresentIdKHR { + VkStructureType sType; + const void* pNext; + uint32_t swapchainCount; + const uint64_t* pPresentIds; +} VkPresentIdKHR; + +typedef struct VkPhysicalDevicePresentIdFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 presentId; +} VkPhysicalDevicePresentIdFeaturesKHR; + + + +#define VK_KHR_synchronization2 1 +#define VK_KHR_SYNCHRONIZATION_2_SPEC_VERSION 1 +#define VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME "VK_KHR_synchronization2" +typedef VkPipelineStageFlags2 VkPipelineStageFlags2KHR; + +typedef VkPipelineStageFlagBits2 VkPipelineStageFlagBits2KHR; + +typedef VkAccessFlags2 VkAccessFlags2KHR; + +typedef VkAccessFlagBits2 VkAccessFlagBits2KHR; + +typedef VkSubmitFlagBits VkSubmitFlagBitsKHR; + +typedef VkSubmitFlags VkSubmitFlagsKHR; + +typedef VkMemoryBarrier2 VkMemoryBarrier2KHR; + +typedef VkBufferMemoryBarrier2 VkBufferMemoryBarrier2KHR; + +typedef VkImageMemoryBarrier2 VkImageMemoryBarrier2KHR; + +typedef VkDependencyInfo VkDependencyInfoKHR; + +typedef VkSubmitInfo2 VkSubmitInfo2KHR; + +typedef VkSemaphoreSubmitInfo VkSemaphoreSubmitInfoKHR; + +typedef VkCommandBufferSubmitInfo VkCommandBufferSubmitInfoKHR; + +typedef VkPhysicalDeviceSynchronization2Features VkPhysicalDeviceSynchronization2FeaturesKHR; + +typedef struct VkQueueFamilyCheckpointProperties2NV { + VkStructureType sType; + void* pNext; + VkPipelineStageFlags2 checkpointExecutionStageMask; +} VkQueueFamilyCheckpointProperties2NV; + +typedef struct VkCheckpointData2NV { + VkStructureType sType; + void* pNext; + VkPipelineStageFlags2 stage; + void* pCheckpointMarker; +} VkCheckpointData2NV; + +typedef void (VKAPI_PTR *PFN_vkCmdSetEvent2KHR)(VkCommandBuffer commandBuffer, VkEvent event, const VkDependencyInfo* pDependencyInfo); +typedef void (VKAPI_PTR *PFN_vkCmdResetEvent2KHR)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags2 stageMask); +typedef void (VKAPI_PTR *PFN_vkCmdWaitEvents2KHR)(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent* pEvents, const VkDependencyInfo* pDependencyInfos); +typedef void (VKAPI_PTR *PFN_vkCmdPipelineBarrier2KHR)(VkCommandBuffer commandBuffer, const VkDependencyInfo* pDependencyInfo); +typedef void (VKAPI_PTR *PFN_vkCmdWriteTimestamp2KHR)(VkCommandBuffer commandBuffer, VkPipelineStageFlags2 stage, VkQueryPool queryPool, uint32_t query); +typedef VkResult (VKAPI_PTR *PFN_vkQueueSubmit2KHR)(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2* pSubmits, VkFence fence); +typedef void (VKAPI_PTR *PFN_vkCmdWriteBufferMarker2AMD)(VkCommandBuffer commandBuffer, VkPipelineStageFlags2 stage, VkBuffer dstBuffer, VkDeviceSize dstOffset, uint32_t marker); +typedef void (VKAPI_PTR *PFN_vkGetQueueCheckpointData2NV)(VkQueue queue, uint32_t* pCheckpointDataCount, VkCheckpointData2NV* pCheckpointData); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetEvent2KHR( + VkCommandBuffer commandBuffer, + VkEvent event, + const VkDependencyInfo* pDependencyInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdResetEvent2KHR( + VkCommandBuffer commandBuffer, + VkEvent event, + VkPipelineStageFlags2 stageMask); + +VKAPI_ATTR void VKAPI_CALL vkCmdWaitEvents2KHR( + VkCommandBuffer commandBuffer, + uint32_t eventCount, + const VkEvent* pEvents, + const VkDependencyInfo* pDependencyInfos); + +VKAPI_ATTR void VKAPI_CALL vkCmdPipelineBarrier2KHR( + VkCommandBuffer commandBuffer, + const VkDependencyInfo* pDependencyInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdWriteTimestamp2KHR( + VkCommandBuffer commandBuffer, + VkPipelineStageFlags2 stage, + VkQueryPool queryPool, + uint32_t query); + +VKAPI_ATTR VkResult VKAPI_CALL vkQueueSubmit2KHR( + VkQueue queue, + uint32_t submitCount, + const VkSubmitInfo2* pSubmits, + VkFence fence); + +VKAPI_ATTR void VKAPI_CALL vkCmdWriteBufferMarker2AMD( + VkCommandBuffer commandBuffer, + VkPipelineStageFlags2 stage, + VkBuffer dstBuffer, + VkDeviceSize dstOffset, + uint32_t marker); + +VKAPI_ATTR void VKAPI_CALL vkGetQueueCheckpointData2NV( + VkQueue queue, + uint32_t* pCheckpointDataCount, + VkCheckpointData2NV* pCheckpointData); +#endif + + +#define VK_KHR_fragment_shader_barycentric 1 +#define VK_KHR_FRAGMENT_SHADER_BARYCENTRIC_SPEC_VERSION 1 +#define VK_KHR_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME "VK_KHR_fragment_shader_barycentric" +typedef struct VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 fragmentShaderBarycentric; +} VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR; + +typedef struct VkPhysicalDeviceFragmentShaderBarycentricPropertiesKHR { + VkStructureType sType; + void* pNext; + VkBool32 triStripVertexOrderIndependentOfProvokingVertex; +} VkPhysicalDeviceFragmentShaderBarycentricPropertiesKHR; + + + +#define VK_KHR_shader_subgroup_uniform_control_flow 1 +#define VK_KHR_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_SPEC_VERSION 1 +#define VK_KHR_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_EXTENSION_NAME "VK_KHR_shader_subgroup_uniform_control_flow" +typedef struct VkPhysicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 shaderSubgroupUniformControlFlow; +} VkPhysicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR; + + + +#define VK_KHR_zero_initialize_workgroup_memory 1 +#define VK_KHR_ZERO_INITIALIZE_WORKGROUP_MEMORY_SPEC_VERSION 1 +#define VK_KHR_ZERO_INITIALIZE_WORKGROUP_MEMORY_EXTENSION_NAME "VK_KHR_zero_initialize_workgroup_memory" +typedef VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeatures VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeaturesKHR; + + + +#define VK_KHR_workgroup_memory_explicit_layout 1 +#define VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_SPEC_VERSION 1 +#define VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME "VK_KHR_workgroup_memory_explicit_layout" +typedef struct VkPhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 workgroupMemoryExplicitLayout; + VkBool32 workgroupMemoryExplicitLayoutScalarBlockLayout; + VkBool32 workgroupMemoryExplicitLayout8BitAccess; + VkBool32 workgroupMemoryExplicitLayout16BitAccess; +} VkPhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR; + + + +#define VK_KHR_copy_commands2 1 +#define VK_KHR_COPY_COMMANDS_2_SPEC_VERSION 1 +#define VK_KHR_COPY_COMMANDS_2_EXTENSION_NAME "VK_KHR_copy_commands2" +typedef VkCopyBufferInfo2 VkCopyBufferInfo2KHR; + +typedef VkCopyImageInfo2 VkCopyImageInfo2KHR; + +typedef VkCopyBufferToImageInfo2 VkCopyBufferToImageInfo2KHR; + +typedef VkCopyImageToBufferInfo2 VkCopyImageToBufferInfo2KHR; + +typedef VkBlitImageInfo2 VkBlitImageInfo2KHR; + +typedef VkResolveImageInfo2 VkResolveImageInfo2KHR; + +typedef VkBufferCopy2 VkBufferCopy2KHR; + +typedef VkImageCopy2 VkImageCopy2KHR; + +typedef VkImageBlit2 VkImageBlit2KHR; + +typedef VkBufferImageCopy2 VkBufferImageCopy2KHR; + +typedef VkImageResolve2 VkImageResolve2KHR; + +typedef void (VKAPI_PTR *PFN_vkCmdCopyBuffer2KHR)(VkCommandBuffer commandBuffer, const VkCopyBufferInfo2* pCopyBufferInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyImage2KHR)(VkCommandBuffer commandBuffer, const VkCopyImageInfo2* pCopyImageInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyBufferToImage2KHR)(VkCommandBuffer commandBuffer, const VkCopyBufferToImageInfo2* pCopyBufferToImageInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyImageToBuffer2KHR)(VkCommandBuffer commandBuffer, const VkCopyImageToBufferInfo2* pCopyImageToBufferInfo); +typedef void (VKAPI_PTR *PFN_vkCmdBlitImage2KHR)(VkCommandBuffer commandBuffer, const VkBlitImageInfo2* pBlitImageInfo); +typedef void (VKAPI_PTR *PFN_vkCmdResolveImage2KHR)(VkCommandBuffer commandBuffer, const VkResolveImageInfo2* pResolveImageInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCopyBuffer2KHR( + VkCommandBuffer commandBuffer, + const VkCopyBufferInfo2* pCopyBufferInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyImage2KHR( + VkCommandBuffer commandBuffer, + const VkCopyImageInfo2* pCopyImageInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyBufferToImage2KHR( + VkCommandBuffer commandBuffer, + const VkCopyBufferToImageInfo2* pCopyBufferToImageInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyImageToBuffer2KHR( + VkCommandBuffer commandBuffer, + const VkCopyImageToBufferInfo2* pCopyImageToBufferInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdBlitImage2KHR( + VkCommandBuffer commandBuffer, + const VkBlitImageInfo2* pBlitImageInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdResolveImage2KHR( + VkCommandBuffer commandBuffer, + const VkResolveImageInfo2* pResolveImageInfo); +#endif + + +#define VK_KHR_format_feature_flags2 1 +#define VK_KHR_FORMAT_FEATURE_FLAGS_2_SPEC_VERSION 1 +#define VK_KHR_FORMAT_FEATURE_FLAGS_2_EXTENSION_NAME "VK_KHR_format_feature_flags2" +typedef VkFormatFeatureFlags2 VkFormatFeatureFlags2KHR; + +typedef VkFormatFeatureFlagBits2 VkFormatFeatureFlagBits2KHR; + +typedef VkFormatProperties3 VkFormatProperties3KHR; + + + +#define VK_KHR_ray_tracing_maintenance1 1 +#define VK_KHR_RAY_TRACING_MAINTENANCE_1_SPEC_VERSION 1 +#define VK_KHR_RAY_TRACING_MAINTENANCE_1_EXTENSION_NAME "VK_KHR_ray_tracing_maintenance1" +typedef struct VkPhysicalDeviceRayTracingMaintenance1FeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 rayTracingMaintenance1; + VkBool32 rayTracingPipelineTraceRaysIndirect2; +} VkPhysicalDeviceRayTracingMaintenance1FeaturesKHR; + +typedef struct VkTraceRaysIndirectCommand2KHR { + VkDeviceAddress raygenShaderRecordAddress; + VkDeviceSize raygenShaderRecordSize; + VkDeviceAddress missShaderBindingTableAddress; + VkDeviceSize missShaderBindingTableSize; + VkDeviceSize missShaderBindingTableStride; + VkDeviceAddress hitShaderBindingTableAddress; + VkDeviceSize hitShaderBindingTableSize; + VkDeviceSize hitShaderBindingTableStride; + VkDeviceAddress callableShaderBindingTableAddress; + VkDeviceSize callableShaderBindingTableSize; + VkDeviceSize callableShaderBindingTableStride; + uint32_t width; + uint32_t height; + uint32_t depth; +} VkTraceRaysIndirectCommand2KHR; + +typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysIndirect2KHR)(VkCommandBuffer commandBuffer, VkDeviceAddress indirectDeviceAddress); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysIndirect2KHR( + VkCommandBuffer commandBuffer, + VkDeviceAddress indirectDeviceAddress); +#endif + + +#define VK_KHR_portability_enumeration 1 +#define VK_KHR_PORTABILITY_ENUMERATION_SPEC_VERSION 1 +#define VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME "VK_KHR_portability_enumeration" + + +#define VK_KHR_maintenance4 1 +#define VK_KHR_MAINTENANCE_4_SPEC_VERSION 2 +#define VK_KHR_MAINTENANCE_4_EXTENSION_NAME "VK_KHR_maintenance4" +typedef VkPhysicalDeviceMaintenance4Features VkPhysicalDeviceMaintenance4FeaturesKHR; + +typedef VkPhysicalDeviceMaintenance4Properties VkPhysicalDeviceMaintenance4PropertiesKHR; + +typedef VkDeviceBufferMemoryRequirements VkDeviceBufferMemoryRequirementsKHR; + +typedef VkDeviceImageMemoryRequirements VkDeviceImageMemoryRequirementsKHR; + +typedef void (VKAPI_PTR *PFN_vkGetDeviceBufferMemoryRequirementsKHR)(VkDevice device, const VkDeviceBufferMemoryRequirements* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetDeviceImageMemoryRequirementsKHR)(VkDevice device, const VkDeviceImageMemoryRequirements* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetDeviceImageSparseMemoryRequirementsKHR)(VkDevice device, const VkDeviceImageMemoryRequirements* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetDeviceBufferMemoryRequirementsKHR( + VkDevice device, + const VkDeviceBufferMemoryRequirements* pInfo, + VkMemoryRequirements2* pMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkGetDeviceImageMemoryRequirementsKHR( + VkDevice device, + const VkDeviceImageMemoryRequirements* pInfo, + VkMemoryRequirements2* pMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkGetDeviceImageSparseMemoryRequirementsKHR( + VkDevice device, + const VkDeviceImageMemoryRequirements* pInfo, + uint32_t* pSparseMemoryRequirementCount, + VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); +#endif + + +#define VK_EXT_debug_report 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT) +#define VK_EXT_DEBUG_REPORT_SPEC_VERSION 10 +#define VK_EXT_DEBUG_REPORT_EXTENSION_NAME "VK_EXT_debug_report" + +typedef enum VkDebugReportObjectTypeEXT { + VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT = 0, + VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT = 1, + VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT = 2, + VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT = 3, + VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT = 4, + VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT = 5, + VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT = 6, + VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT = 7, + VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT = 8, + VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT = 9, + VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT = 10, + VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT = 11, + VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT = 12, + VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT = 13, + VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT = 14, + VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT = 15, + VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT = 16, + VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT = 17, + VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT = 18, + VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT = 19, + VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT = 20, + VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT = 21, + VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT = 22, + VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT = 23, + VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT = 24, + VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT = 25, + VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT = 26, + VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT = 27, + VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT = 28, + VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT = 29, + VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT = 30, + VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT = 33, + VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT = 1000156000, + VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT = 1000085000, + VK_DEBUG_REPORT_OBJECT_TYPE_CU_MODULE_NVX_EXT = 1000029000, + VK_DEBUG_REPORT_OBJECT_TYPE_CU_FUNCTION_NVX_EXT = 1000029001, + VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR_EXT = 1000150000, + VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT = 1000165000, + VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA_EXT = 1000366000, + VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT, + VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT, + VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT, + VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT, + VK_DEBUG_REPORT_OBJECT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDebugReportObjectTypeEXT; + +typedef enum VkDebugReportFlagBitsEXT { + VK_DEBUG_REPORT_INFORMATION_BIT_EXT = 0x00000001, + VK_DEBUG_REPORT_WARNING_BIT_EXT = 0x00000002, + VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT = 0x00000004, + VK_DEBUG_REPORT_ERROR_BIT_EXT = 0x00000008, + VK_DEBUG_REPORT_DEBUG_BIT_EXT = 0x00000010, + VK_DEBUG_REPORT_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDebugReportFlagBitsEXT; +typedef VkFlags VkDebugReportFlagsEXT; +typedef VkBool32 (VKAPI_PTR *PFN_vkDebugReportCallbackEXT)( + VkDebugReportFlagsEXT flags, + VkDebugReportObjectTypeEXT objectType, + uint64_t object, + size_t location, + int32_t messageCode, + const char* pLayerPrefix, + const char* pMessage, + void* pUserData); + +typedef struct VkDebugReportCallbackCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkDebugReportFlagsEXT flags; + PFN_vkDebugReportCallbackEXT pfnCallback; + void* pUserData; +} VkDebugReportCallbackCreateInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateDebugReportCallbackEXT)(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback); +typedef void (VKAPI_PTR *PFN_vkDestroyDebugReportCallbackEXT)(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkDebugReportMessageEXT)(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugReportCallbackEXT( + VkInstance instance, + const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDebugReportCallbackEXT* pCallback); + +VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT( + VkInstance instance, + VkDebugReportCallbackEXT callback, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR void VKAPI_CALL vkDebugReportMessageEXT( + VkInstance instance, + VkDebugReportFlagsEXT flags, + VkDebugReportObjectTypeEXT objectType, + uint64_t object, + size_t location, + int32_t messageCode, + const char* pLayerPrefix, + const char* pMessage); +#endif + + +#define VK_NV_glsl_shader 1 +#define VK_NV_GLSL_SHADER_SPEC_VERSION 1 +#define VK_NV_GLSL_SHADER_EXTENSION_NAME "VK_NV_glsl_shader" + + +#define VK_EXT_depth_range_unrestricted 1 +#define VK_EXT_DEPTH_RANGE_UNRESTRICTED_SPEC_VERSION 1 +#define VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME "VK_EXT_depth_range_unrestricted" + + +#define VK_IMG_filter_cubic 1 +#define VK_IMG_FILTER_CUBIC_SPEC_VERSION 1 +#define VK_IMG_FILTER_CUBIC_EXTENSION_NAME "VK_IMG_filter_cubic" + + +#define VK_AMD_rasterization_order 1 +#define VK_AMD_RASTERIZATION_ORDER_SPEC_VERSION 1 +#define VK_AMD_RASTERIZATION_ORDER_EXTENSION_NAME "VK_AMD_rasterization_order" + +typedef enum VkRasterizationOrderAMD { + VK_RASTERIZATION_ORDER_STRICT_AMD = 0, + VK_RASTERIZATION_ORDER_RELAXED_AMD = 1, + VK_RASTERIZATION_ORDER_MAX_ENUM_AMD = 0x7FFFFFFF +} VkRasterizationOrderAMD; +typedef struct VkPipelineRasterizationStateRasterizationOrderAMD { + VkStructureType sType; + const void* pNext; + VkRasterizationOrderAMD rasterizationOrder; +} VkPipelineRasterizationStateRasterizationOrderAMD; + + + +#define VK_AMD_shader_trinary_minmax 1 +#define VK_AMD_SHADER_TRINARY_MINMAX_SPEC_VERSION 1 +#define VK_AMD_SHADER_TRINARY_MINMAX_EXTENSION_NAME "VK_AMD_shader_trinary_minmax" + + +#define VK_AMD_shader_explicit_vertex_parameter 1 +#define VK_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_SPEC_VERSION 1 +#define VK_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_EXTENSION_NAME "VK_AMD_shader_explicit_vertex_parameter" + + +#define VK_EXT_debug_marker 1 +#define VK_EXT_DEBUG_MARKER_SPEC_VERSION 4 +#define VK_EXT_DEBUG_MARKER_EXTENSION_NAME "VK_EXT_debug_marker" +typedef struct VkDebugMarkerObjectNameInfoEXT { + VkStructureType sType; + const void* pNext; + VkDebugReportObjectTypeEXT objectType; + uint64_t object; + const char* pObjectName; +} VkDebugMarkerObjectNameInfoEXT; + +typedef struct VkDebugMarkerObjectTagInfoEXT { + VkStructureType sType; + const void* pNext; + VkDebugReportObjectTypeEXT objectType; + uint64_t object; + uint64_t tagName; + size_t tagSize; + const void* pTag; +} VkDebugMarkerObjectTagInfoEXT; + +typedef struct VkDebugMarkerMarkerInfoEXT { + VkStructureType sType; + const void* pNext; + const char* pMarkerName; + float color[4]; +} VkDebugMarkerMarkerInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkDebugMarkerSetObjectTagEXT)(VkDevice device, const VkDebugMarkerObjectTagInfoEXT* pTagInfo); +typedef VkResult (VKAPI_PTR *PFN_vkDebugMarkerSetObjectNameEXT)(VkDevice device, const VkDebugMarkerObjectNameInfoEXT* pNameInfo); +typedef void (VKAPI_PTR *PFN_vkCmdDebugMarkerBeginEXT)(VkCommandBuffer commandBuffer, const VkDebugMarkerMarkerInfoEXT* pMarkerInfo); +typedef void (VKAPI_PTR *PFN_vkCmdDebugMarkerEndEXT)(VkCommandBuffer commandBuffer); +typedef void (VKAPI_PTR *PFN_vkCmdDebugMarkerInsertEXT)(VkCommandBuffer commandBuffer, const VkDebugMarkerMarkerInfoEXT* pMarkerInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkDebugMarkerSetObjectTagEXT( + VkDevice device, + const VkDebugMarkerObjectTagInfoEXT* pTagInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkDebugMarkerSetObjectNameEXT( + VkDevice device, + const VkDebugMarkerObjectNameInfoEXT* pNameInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdDebugMarkerBeginEXT( + VkCommandBuffer commandBuffer, + const VkDebugMarkerMarkerInfoEXT* pMarkerInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdDebugMarkerEndEXT( + VkCommandBuffer commandBuffer); + +VKAPI_ATTR void VKAPI_CALL vkCmdDebugMarkerInsertEXT( + VkCommandBuffer commandBuffer, + const VkDebugMarkerMarkerInfoEXT* pMarkerInfo); +#endif + + +#define VK_AMD_gcn_shader 1 +#define VK_AMD_GCN_SHADER_SPEC_VERSION 1 +#define VK_AMD_GCN_SHADER_EXTENSION_NAME "VK_AMD_gcn_shader" + + +#define VK_NV_dedicated_allocation 1 +#define VK_NV_DEDICATED_ALLOCATION_SPEC_VERSION 1 +#define VK_NV_DEDICATED_ALLOCATION_EXTENSION_NAME "VK_NV_dedicated_allocation" +typedef struct VkDedicatedAllocationImageCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkBool32 dedicatedAllocation; +} VkDedicatedAllocationImageCreateInfoNV; + +typedef struct VkDedicatedAllocationBufferCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkBool32 dedicatedAllocation; +} VkDedicatedAllocationBufferCreateInfoNV; + +typedef struct VkDedicatedAllocationMemoryAllocateInfoNV { + VkStructureType sType; + const void* pNext; + VkImage image; + VkBuffer buffer; +} VkDedicatedAllocationMemoryAllocateInfoNV; + + + +#define VK_EXT_transform_feedback 1 +#define VK_EXT_TRANSFORM_FEEDBACK_SPEC_VERSION 1 +#define VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME "VK_EXT_transform_feedback" +typedef VkFlags VkPipelineRasterizationStateStreamCreateFlagsEXT; +typedef struct VkPhysicalDeviceTransformFeedbackFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 transformFeedback; + VkBool32 geometryStreams; +} VkPhysicalDeviceTransformFeedbackFeaturesEXT; + +typedef struct VkPhysicalDeviceTransformFeedbackPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t maxTransformFeedbackStreams; + uint32_t maxTransformFeedbackBuffers; + VkDeviceSize maxTransformFeedbackBufferSize; + uint32_t maxTransformFeedbackStreamDataSize; + uint32_t maxTransformFeedbackBufferDataSize; + uint32_t maxTransformFeedbackBufferDataStride; + VkBool32 transformFeedbackQueries; + VkBool32 transformFeedbackStreamsLinesTriangles; + VkBool32 transformFeedbackRasterizationStreamSelect; + VkBool32 transformFeedbackDraw; +} VkPhysicalDeviceTransformFeedbackPropertiesEXT; + +typedef struct VkPipelineRasterizationStateStreamCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkPipelineRasterizationStateStreamCreateFlagsEXT flags; + uint32_t rasterizationStream; +} VkPipelineRasterizationStateStreamCreateInfoEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdBindTransformFeedbackBuffersEXT)(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets, const VkDeviceSize* pSizes); +typedef void (VKAPI_PTR *PFN_vkCmdBeginTransformFeedbackEXT)(VkCommandBuffer commandBuffer, uint32_t firstCounterBuffer, uint32_t counterBufferCount, const VkBuffer* pCounterBuffers, const VkDeviceSize* pCounterBufferOffsets); +typedef void (VKAPI_PTR *PFN_vkCmdEndTransformFeedbackEXT)(VkCommandBuffer commandBuffer, uint32_t firstCounterBuffer, uint32_t counterBufferCount, const VkBuffer* pCounterBuffers, const VkDeviceSize* pCounterBufferOffsets); +typedef void (VKAPI_PTR *PFN_vkCmdBeginQueryIndexedEXT)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags, uint32_t index); +typedef void (VKAPI_PTR *PFN_vkCmdEndQueryIndexedEXT)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, uint32_t index); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectByteCountEXT)(VkCommandBuffer commandBuffer, uint32_t instanceCount, uint32_t firstInstance, VkBuffer counterBuffer, VkDeviceSize counterBufferOffset, uint32_t counterOffset, uint32_t vertexStride); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBindTransformFeedbackBuffersEXT( + VkCommandBuffer commandBuffer, + uint32_t firstBinding, + uint32_t bindingCount, + const VkBuffer* pBuffers, + const VkDeviceSize* pOffsets, + const VkDeviceSize* pSizes); + +VKAPI_ATTR void VKAPI_CALL vkCmdBeginTransformFeedbackEXT( + VkCommandBuffer commandBuffer, + uint32_t firstCounterBuffer, + uint32_t counterBufferCount, + const VkBuffer* pCounterBuffers, + const VkDeviceSize* pCounterBufferOffsets); + +VKAPI_ATTR void VKAPI_CALL vkCmdEndTransformFeedbackEXT( + VkCommandBuffer commandBuffer, + uint32_t firstCounterBuffer, + uint32_t counterBufferCount, + const VkBuffer* pCounterBuffers, + const VkDeviceSize* pCounterBufferOffsets); + +VKAPI_ATTR void VKAPI_CALL vkCmdBeginQueryIndexedEXT( + VkCommandBuffer commandBuffer, + VkQueryPool queryPool, + uint32_t query, + VkQueryControlFlags flags, + uint32_t index); + +VKAPI_ATTR void VKAPI_CALL vkCmdEndQueryIndexedEXT( + VkCommandBuffer commandBuffer, + VkQueryPool queryPool, + uint32_t query, + uint32_t index); + +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectByteCountEXT( + VkCommandBuffer commandBuffer, + uint32_t instanceCount, + uint32_t firstInstance, + VkBuffer counterBuffer, + VkDeviceSize counterBufferOffset, + uint32_t counterOffset, + uint32_t vertexStride); +#endif + + +#define VK_NVX_binary_import 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCuModuleNVX) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCuFunctionNVX) +#define VK_NVX_BINARY_IMPORT_SPEC_VERSION 1 +#define VK_NVX_BINARY_IMPORT_EXTENSION_NAME "VK_NVX_binary_import" +typedef struct VkCuModuleCreateInfoNVX { + VkStructureType sType; + const void* pNext; + size_t dataSize; + const void* pData; +} VkCuModuleCreateInfoNVX; + +typedef struct VkCuFunctionCreateInfoNVX { + VkStructureType sType; + const void* pNext; + VkCuModuleNVX module; + const char* pName; +} VkCuFunctionCreateInfoNVX; + +typedef struct VkCuLaunchInfoNVX { + VkStructureType sType; + const void* pNext; + VkCuFunctionNVX function; + uint32_t gridDimX; + uint32_t gridDimY; + uint32_t gridDimZ; + uint32_t blockDimX; + uint32_t blockDimY; + uint32_t blockDimZ; + uint32_t sharedMemBytes; + size_t paramCount; + const void* const * pParams; + size_t extraCount; + const void* const * pExtras; +} VkCuLaunchInfoNVX; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateCuModuleNVX)(VkDevice device, const VkCuModuleCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCuModuleNVX* pModule); +typedef VkResult (VKAPI_PTR *PFN_vkCreateCuFunctionNVX)(VkDevice device, const VkCuFunctionCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCuFunctionNVX* pFunction); +typedef void (VKAPI_PTR *PFN_vkDestroyCuModuleNVX)(VkDevice device, VkCuModuleNVX module, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkDestroyCuFunctionNVX)(VkDevice device, VkCuFunctionNVX function, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkCmdCuLaunchKernelNVX)(VkCommandBuffer commandBuffer, const VkCuLaunchInfoNVX* pLaunchInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateCuModuleNVX( + VkDevice device, + const VkCuModuleCreateInfoNVX* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkCuModuleNVX* pModule); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateCuFunctionNVX( + VkDevice device, + const VkCuFunctionCreateInfoNVX* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkCuFunctionNVX* pFunction); + +VKAPI_ATTR void VKAPI_CALL vkDestroyCuModuleNVX( + VkDevice device, + VkCuModuleNVX module, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR void VKAPI_CALL vkDestroyCuFunctionNVX( + VkDevice device, + VkCuFunctionNVX function, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR void VKAPI_CALL vkCmdCuLaunchKernelNVX( + VkCommandBuffer commandBuffer, + const VkCuLaunchInfoNVX* pLaunchInfo); +#endif + + +#define VK_NVX_image_view_handle 1 +#define VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION 2 +#define VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME "VK_NVX_image_view_handle" +typedef struct VkImageViewHandleInfoNVX { + VkStructureType sType; + const void* pNext; + VkImageView imageView; + VkDescriptorType descriptorType; + VkSampler sampler; +} VkImageViewHandleInfoNVX; + +typedef struct VkImageViewAddressPropertiesNVX { + VkStructureType sType; + void* pNext; + VkDeviceAddress deviceAddress; + VkDeviceSize size; +} VkImageViewAddressPropertiesNVX; + +typedef uint32_t (VKAPI_PTR *PFN_vkGetImageViewHandleNVX)(VkDevice device, const VkImageViewHandleInfoNVX* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetImageViewAddressNVX)(VkDevice device, VkImageView imageView, VkImageViewAddressPropertiesNVX* pProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR uint32_t VKAPI_CALL vkGetImageViewHandleNVX( + VkDevice device, + const VkImageViewHandleInfoNVX* pInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetImageViewAddressNVX( + VkDevice device, + VkImageView imageView, + VkImageViewAddressPropertiesNVX* pProperties); +#endif + + +#define VK_AMD_draw_indirect_count 1 +#define VK_AMD_DRAW_INDIRECT_COUNT_SPEC_VERSION 2 +#define VK_AMD_DRAW_INDIRECT_COUNT_EXTENSION_NAME "VK_AMD_draw_indirect_count" +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectCountAMD)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirectCountAMD)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectCountAMD( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkBuffer countBuffer, + VkDeviceSize countBufferOffset, + uint32_t maxDrawCount, + uint32_t stride); + +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCountAMD( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkBuffer countBuffer, + VkDeviceSize countBufferOffset, + uint32_t maxDrawCount, + uint32_t stride); +#endif + + +#define VK_AMD_negative_viewport_height 1 +#define VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_SPEC_VERSION 1 +#define VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_EXTENSION_NAME "VK_AMD_negative_viewport_height" + + +#define VK_AMD_gpu_shader_half_float 1 +#define VK_AMD_GPU_SHADER_HALF_FLOAT_SPEC_VERSION 2 +#define VK_AMD_GPU_SHADER_HALF_FLOAT_EXTENSION_NAME "VK_AMD_gpu_shader_half_float" + + +#define VK_AMD_shader_ballot 1 +#define VK_AMD_SHADER_BALLOT_SPEC_VERSION 1 +#define VK_AMD_SHADER_BALLOT_EXTENSION_NAME "VK_AMD_shader_ballot" + + +#define VK_AMD_texture_gather_bias_lod 1 +#define VK_AMD_TEXTURE_GATHER_BIAS_LOD_SPEC_VERSION 1 +#define VK_AMD_TEXTURE_GATHER_BIAS_LOD_EXTENSION_NAME "VK_AMD_texture_gather_bias_lod" +typedef struct VkTextureLODGatherFormatPropertiesAMD { + VkStructureType sType; + void* pNext; + VkBool32 supportsTextureGatherLODBiasAMD; +} VkTextureLODGatherFormatPropertiesAMD; + + + +#define VK_AMD_shader_info 1 +#define VK_AMD_SHADER_INFO_SPEC_VERSION 1 +#define VK_AMD_SHADER_INFO_EXTENSION_NAME "VK_AMD_shader_info" + +typedef enum VkShaderInfoTypeAMD { + VK_SHADER_INFO_TYPE_STATISTICS_AMD = 0, + VK_SHADER_INFO_TYPE_BINARY_AMD = 1, + VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD = 2, + VK_SHADER_INFO_TYPE_MAX_ENUM_AMD = 0x7FFFFFFF +} VkShaderInfoTypeAMD; +typedef struct VkShaderResourceUsageAMD { + uint32_t numUsedVgprs; + uint32_t numUsedSgprs; + uint32_t ldsSizePerLocalWorkGroup; + size_t ldsUsageSizeInBytes; + size_t scratchMemUsageInBytes; +} VkShaderResourceUsageAMD; + +typedef struct VkShaderStatisticsInfoAMD { + VkShaderStageFlags shaderStageMask; + VkShaderResourceUsageAMD resourceUsage; + uint32_t numPhysicalVgprs; + uint32_t numPhysicalSgprs; + uint32_t numAvailableVgprs; + uint32_t numAvailableSgprs; + uint32_t computeWorkGroupSize[3]; +} VkShaderStatisticsInfoAMD; + +typedef VkResult (VKAPI_PTR *PFN_vkGetShaderInfoAMD)(VkDevice device, VkPipeline pipeline, VkShaderStageFlagBits shaderStage, VkShaderInfoTypeAMD infoType, size_t* pInfoSize, void* pInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetShaderInfoAMD( + VkDevice device, + VkPipeline pipeline, + VkShaderStageFlagBits shaderStage, + VkShaderInfoTypeAMD infoType, + size_t* pInfoSize, + void* pInfo); +#endif + + +#define VK_AMD_shader_image_load_store_lod 1 +#define VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_SPEC_VERSION 1 +#define VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME "VK_AMD_shader_image_load_store_lod" + + +#define VK_NV_corner_sampled_image 1 +#define VK_NV_CORNER_SAMPLED_IMAGE_SPEC_VERSION 2 +#define VK_NV_CORNER_SAMPLED_IMAGE_EXTENSION_NAME "VK_NV_corner_sampled_image" +typedef struct VkPhysicalDeviceCornerSampledImageFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 cornerSampledImage; +} VkPhysicalDeviceCornerSampledImageFeaturesNV; + + + +#define VK_IMG_format_pvrtc 1 +#define VK_IMG_FORMAT_PVRTC_SPEC_VERSION 1 +#define VK_IMG_FORMAT_PVRTC_EXTENSION_NAME "VK_IMG_format_pvrtc" + + +#define VK_NV_external_memory_capabilities 1 +#define VK_NV_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1 +#define VK_NV_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME "VK_NV_external_memory_capabilities" + +typedef enum VkExternalMemoryHandleTypeFlagBitsNV { + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_NV = 0x00000001, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_NV = 0x00000002, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_BIT_NV = 0x00000004, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_KMT_BIT_NV = 0x00000008, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkExternalMemoryHandleTypeFlagBitsNV; +typedef VkFlags VkExternalMemoryHandleTypeFlagsNV; + +typedef enum VkExternalMemoryFeatureFlagBitsNV { + VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_NV = 0x00000001, + VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_NV = 0x00000002, + VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_NV = 0x00000004, + VK_EXTERNAL_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkExternalMemoryFeatureFlagBitsNV; +typedef VkFlags VkExternalMemoryFeatureFlagsNV; +typedef struct VkExternalImageFormatPropertiesNV { + VkImageFormatProperties imageFormatProperties; + VkExternalMemoryFeatureFlagsNV externalMemoryFeatures; + VkExternalMemoryHandleTypeFlagsNV exportFromImportedHandleTypes; + VkExternalMemoryHandleTypeFlagsNV compatibleHandleTypes; +} VkExternalImageFormatPropertiesNV; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV)(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkExternalMemoryHandleTypeFlagsNV externalHandleType, VkExternalImageFormatPropertiesNV* pExternalImageFormatProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceExternalImageFormatPropertiesNV( + VkPhysicalDevice physicalDevice, + VkFormat format, + VkImageType type, + VkImageTiling tiling, + VkImageUsageFlags usage, + VkImageCreateFlags flags, + VkExternalMemoryHandleTypeFlagsNV externalHandleType, + VkExternalImageFormatPropertiesNV* pExternalImageFormatProperties); +#endif + + +#define VK_NV_external_memory 1 +#define VK_NV_EXTERNAL_MEMORY_SPEC_VERSION 1 +#define VK_NV_EXTERNAL_MEMORY_EXTENSION_NAME "VK_NV_external_memory" +typedef struct VkExternalMemoryImageCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlagsNV handleTypes; +} VkExternalMemoryImageCreateInfoNV; + +typedef struct VkExportMemoryAllocateInfoNV { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlagsNV handleTypes; +} VkExportMemoryAllocateInfoNV; + + + +#define VK_EXT_validation_flags 1 +#define VK_EXT_VALIDATION_FLAGS_SPEC_VERSION 2 +#define VK_EXT_VALIDATION_FLAGS_EXTENSION_NAME "VK_EXT_validation_flags" + +typedef enum VkValidationCheckEXT { + VK_VALIDATION_CHECK_ALL_EXT = 0, + VK_VALIDATION_CHECK_SHADERS_EXT = 1, + VK_VALIDATION_CHECK_MAX_ENUM_EXT = 0x7FFFFFFF +} VkValidationCheckEXT; +typedef struct VkValidationFlagsEXT { + VkStructureType sType; + const void* pNext; + uint32_t disabledValidationCheckCount; + const VkValidationCheckEXT* pDisabledValidationChecks; +} VkValidationFlagsEXT; + + + +#define VK_EXT_shader_subgroup_ballot 1 +#define VK_EXT_SHADER_SUBGROUP_BALLOT_SPEC_VERSION 1 +#define VK_EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME "VK_EXT_shader_subgroup_ballot" + + +#define VK_EXT_shader_subgroup_vote 1 +#define VK_EXT_SHADER_SUBGROUP_VOTE_SPEC_VERSION 1 +#define VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME "VK_EXT_shader_subgroup_vote" + + +#define VK_EXT_texture_compression_astc_hdr 1 +#define VK_EXT_TEXTURE_COMPRESSION_ASTC_HDR_SPEC_VERSION 1 +#define VK_EXT_TEXTURE_COMPRESSION_ASTC_HDR_EXTENSION_NAME "VK_EXT_texture_compression_astc_hdr" +typedef VkPhysicalDeviceTextureCompressionASTCHDRFeatures VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT; + + + +#define VK_EXT_astc_decode_mode 1 +#define VK_EXT_ASTC_DECODE_MODE_SPEC_VERSION 1 +#define VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME "VK_EXT_astc_decode_mode" +typedef struct VkImageViewASTCDecodeModeEXT { + VkStructureType sType; + const void* pNext; + VkFormat decodeMode; +} VkImageViewASTCDecodeModeEXT; + +typedef struct VkPhysicalDeviceASTCDecodeFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 decodeModeSharedExponent; +} VkPhysicalDeviceASTCDecodeFeaturesEXT; + + + +#define VK_EXT_conditional_rendering 1 +#define VK_EXT_CONDITIONAL_RENDERING_SPEC_VERSION 2 +#define VK_EXT_CONDITIONAL_RENDERING_EXTENSION_NAME "VK_EXT_conditional_rendering" + +typedef enum VkConditionalRenderingFlagBitsEXT { + VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT = 0x00000001, + VK_CONDITIONAL_RENDERING_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkConditionalRenderingFlagBitsEXT; +typedef VkFlags VkConditionalRenderingFlagsEXT; +typedef struct VkConditionalRenderingBeginInfoEXT { + VkStructureType sType; + const void* pNext; + VkBuffer buffer; + VkDeviceSize offset; + VkConditionalRenderingFlagsEXT flags; +} VkConditionalRenderingBeginInfoEXT; + +typedef struct VkPhysicalDeviceConditionalRenderingFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 conditionalRendering; + VkBool32 inheritedConditionalRendering; +} VkPhysicalDeviceConditionalRenderingFeaturesEXT; + +typedef struct VkCommandBufferInheritanceConditionalRenderingInfoEXT { + VkStructureType sType; + const void* pNext; + VkBool32 conditionalRenderingEnable; +} VkCommandBufferInheritanceConditionalRenderingInfoEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdBeginConditionalRenderingEXT)(VkCommandBuffer commandBuffer, const VkConditionalRenderingBeginInfoEXT* pConditionalRenderingBegin); +typedef void (VKAPI_PTR *PFN_vkCmdEndConditionalRenderingEXT)(VkCommandBuffer commandBuffer); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBeginConditionalRenderingEXT( + VkCommandBuffer commandBuffer, + const VkConditionalRenderingBeginInfoEXT* pConditionalRenderingBegin); + +VKAPI_ATTR void VKAPI_CALL vkCmdEndConditionalRenderingEXT( + VkCommandBuffer commandBuffer); +#endif + + +#define VK_NV_clip_space_w_scaling 1 +#define VK_NV_CLIP_SPACE_W_SCALING_SPEC_VERSION 1 +#define VK_NV_CLIP_SPACE_W_SCALING_EXTENSION_NAME "VK_NV_clip_space_w_scaling" +typedef struct VkViewportWScalingNV { + float xcoeff; + float ycoeff; +} VkViewportWScalingNV; + +typedef struct VkPipelineViewportWScalingStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkBool32 viewportWScalingEnable; + uint32_t viewportCount; + const VkViewportWScalingNV* pViewportWScalings; +} VkPipelineViewportWScalingStateCreateInfoNV; + +typedef void (VKAPI_PTR *PFN_vkCmdSetViewportWScalingNV)(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewportWScalingNV* pViewportWScalings); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportWScalingNV( + VkCommandBuffer commandBuffer, + uint32_t firstViewport, + uint32_t viewportCount, + const VkViewportWScalingNV* pViewportWScalings); +#endif + + +#define VK_EXT_direct_mode_display 1 +#define VK_EXT_DIRECT_MODE_DISPLAY_SPEC_VERSION 1 +#define VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME "VK_EXT_direct_mode_display" +typedef VkResult (VKAPI_PTR *PFN_vkReleaseDisplayEXT)(VkPhysicalDevice physicalDevice, VkDisplayKHR display); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkReleaseDisplayEXT( + VkPhysicalDevice physicalDevice, + VkDisplayKHR display); +#endif + + +#define VK_EXT_display_surface_counter 1 +#define VK_EXT_DISPLAY_SURFACE_COUNTER_SPEC_VERSION 1 +#define VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME "VK_EXT_display_surface_counter" + +typedef enum VkSurfaceCounterFlagBitsEXT { + VK_SURFACE_COUNTER_VBLANK_BIT_EXT = 0x00000001, + VK_SURFACE_COUNTER_VBLANK_EXT = VK_SURFACE_COUNTER_VBLANK_BIT_EXT, + VK_SURFACE_COUNTER_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkSurfaceCounterFlagBitsEXT; +typedef VkFlags VkSurfaceCounterFlagsEXT; +typedef struct VkSurfaceCapabilities2EXT { + VkStructureType sType; + void* pNext; + uint32_t minImageCount; + uint32_t maxImageCount; + VkExtent2D currentExtent; + VkExtent2D minImageExtent; + VkExtent2D maxImageExtent; + uint32_t maxImageArrayLayers; + VkSurfaceTransformFlagsKHR supportedTransforms; + VkSurfaceTransformFlagBitsKHR currentTransform; + VkCompositeAlphaFlagsKHR supportedCompositeAlpha; + VkImageUsageFlags supportedUsageFlags; + VkSurfaceCounterFlagsEXT supportedSurfaceCounters; +} VkSurfaceCapabilities2EXT; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilities2EXT* pSurfaceCapabilities); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilities2EXT( + VkPhysicalDevice physicalDevice, + VkSurfaceKHR surface, + VkSurfaceCapabilities2EXT* pSurfaceCapabilities); +#endif + + +#define VK_EXT_display_control 1 +#define VK_EXT_DISPLAY_CONTROL_SPEC_VERSION 1 +#define VK_EXT_DISPLAY_CONTROL_EXTENSION_NAME "VK_EXT_display_control" + +typedef enum VkDisplayPowerStateEXT { + VK_DISPLAY_POWER_STATE_OFF_EXT = 0, + VK_DISPLAY_POWER_STATE_SUSPEND_EXT = 1, + VK_DISPLAY_POWER_STATE_ON_EXT = 2, + VK_DISPLAY_POWER_STATE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDisplayPowerStateEXT; + +typedef enum VkDeviceEventTypeEXT { + VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT = 0, + VK_DEVICE_EVENT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDeviceEventTypeEXT; + +typedef enum VkDisplayEventTypeEXT { + VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT = 0, + VK_DISPLAY_EVENT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDisplayEventTypeEXT; +typedef struct VkDisplayPowerInfoEXT { + VkStructureType sType; + const void* pNext; + VkDisplayPowerStateEXT powerState; +} VkDisplayPowerInfoEXT; + +typedef struct VkDeviceEventInfoEXT { + VkStructureType sType; + const void* pNext; + VkDeviceEventTypeEXT deviceEvent; +} VkDeviceEventInfoEXT; + +typedef struct VkDisplayEventInfoEXT { + VkStructureType sType; + const void* pNext; + VkDisplayEventTypeEXT displayEvent; +} VkDisplayEventInfoEXT; + +typedef struct VkSwapchainCounterCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkSurfaceCounterFlagsEXT surfaceCounters; +} VkSwapchainCounterCreateInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkDisplayPowerControlEXT)(VkDevice device, VkDisplayKHR display, const VkDisplayPowerInfoEXT* pDisplayPowerInfo); +typedef VkResult (VKAPI_PTR *PFN_vkRegisterDeviceEventEXT)(VkDevice device, const VkDeviceEventInfoEXT* pDeviceEventInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence); +typedef VkResult (VKAPI_PTR *PFN_vkRegisterDisplayEventEXT)(VkDevice device, VkDisplayKHR display, const VkDisplayEventInfoEXT* pDisplayEventInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence); +typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainCounterEXT)(VkDevice device, VkSwapchainKHR swapchain, VkSurfaceCounterFlagBitsEXT counter, uint64_t* pCounterValue); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkDisplayPowerControlEXT( + VkDevice device, + VkDisplayKHR display, + const VkDisplayPowerInfoEXT* pDisplayPowerInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkRegisterDeviceEventEXT( + VkDevice device, + const VkDeviceEventInfoEXT* pDeviceEventInfo, + const VkAllocationCallbacks* pAllocator, + VkFence* pFence); + +VKAPI_ATTR VkResult VKAPI_CALL vkRegisterDisplayEventEXT( + VkDevice device, + VkDisplayKHR display, + const VkDisplayEventInfoEXT* pDisplayEventInfo, + const VkAllocationCallbacks* pAllocator, + VkFence* pFence); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainCounterEXT( + VkDevice device, + VkSwapchainKHR swapchain, + VkSurfaceCounterFlagBitsEXT counter, + uint64_t* pCounterValue); +#endif + + +#define VK_GOOGLE_display_timing 1 +#define VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION 1 +#define VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME "VK_GOOGLE_display_timing" +typedef struct VkRefreshCycleDurationGOOGLE { + uint64_t refreshDuration; +} VkRefreshCycleDurationGOOGLE; + +typedef struct VkPastPresentationTimingGOOGLE { + uint32_t presentID; + uint64_t desiredPresentTime; + uint64_t actualPresentTime; + uint64_t earliestPresentTime; + uint64_t presentMargin; +} VkPastPresentationTimingGOOGLE; + +typedef struct VkPresentTimeGOOGLE { + uint32_t presentID; + uint64_t desiredPresentTime; +} VkPresentTimeGOOGLE; + +typedef struct VkPresentTimesInfoGOOGLE { + VkStructureType sType; + const void* pNext; + uint32_t swapchainCount; + const VkPresentTimeGOOGLE* pTimes; +} VkPresentTimesInfoGOOGLE; + +typedef VkResult (VKAPI_PTR *PFN_vkGetRefreshCycleDurationGOOGLE)(VkDevice device, VkSwapchainKHR swapchain, VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetPastPresentationTimingGOOGLE)(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pPresentationTimingCount, VkPastPresentationTimingGOOGLE* pPresentationTimings); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetRefreshCycleDurationGOOGLE( + VkDevice device, + VkSwapchainKHR swapchain, + VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPastPresentationTimingGOOGLE( + VkDevice device, + VkSwapchainKHR swapchain, + uint32_t* pPresentationTimingCount, + VkPastPresentationTimingGOOGLE* pPresentationTimings); +#endif + + +#define VK_NV_sample_mask_override_coverage 1 +#define VK_NV_SAMPLE_MASK_OVERRIDE_COVERAGE_SPEC_VERSION 1 +#define VK_NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME "VK_NV_sample_mask_override_coverage" + + +#define VK_NV_geometry_shader_passthrough 1 +#define VK_NV_GEOMETRY_SHADER_PASSTHROUGH_SPEC_VERSION 1 +#define VK_NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME "VK_NV_geometry_shader_passthrough" + + +#define VK_NV_viewport_array2 1 +#define VK_NV_VIEWPORT_ARRAY_2_SPEC_VERSION 1 +#define VK_NV_VIEWPORT_ARRAY_2_EXTENSION_NAME "VK_NV_viewport_array2" +#define VK_NV_VIEWPORT_ARRAY2_SPEC_VERSION VK_NV_VIEWPORT_ARRAY_2_SPEC_VERSION +#define VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME VK_NV_VIEWPORT_ARRAY_2_EXTENSION_NAME + + +#define VK_NVX_multiview_per_view_attributes 1 +#define VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_SPEC_VERSION 1 +#define VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME "VK_NVX_multiview_per_view_attributes" +typedef struct VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX { + VkStructureType sType; + void* pNext; + VkBool32 perViewPositionAllComponents; +} VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX; + + + +#define VK_NV_viewport_swizzle 1 +#define VK_NV_VIEWPORT_SWIZZLE_SPEC_VERSION 1 +#define VK_NV_VIEWPORT_SWIZZLE_EXTENSION_NAME "VK_NV_viewport_swizzle" + +typedef enum VkViewportCoordinateSwizzleNV { + VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV = 0, + VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_X_NV = 1, + VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV = 2, + VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Y_NV = 3, + VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV = 4, + VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Z_NV = 5, + VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV = 6, + VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV = 7, + VK_VIEWPORT_COORDINATE_SWIZZLE_MAX_ENUM_NV = 0x7FFFFFFF +} VkViewportCoordinateSwizzleNV; +typedef VkFlags VkPipelineViewportSwizzleStateCreateFlagsNV; +typedef struct VkViewportSwizzleNV { + VkViewportCoordinateSwizzleNV x; + VkViewportCoordinateSwizzleNV y; + VkViewportCoordinateSwizzleNV z; + VkViewportCoordinateSwizzleNV w; +} VkViewportSwizzleNV; + +typedef struct VkPipelineViewportSwizzleStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkPipelineViewportSwizzleStateCreateFlagsNV flags; + uint32_t viewportCount; + const VkViewportSwizzleNV* pViewportSwizzles; +} VkPipelineViewportSwizzleStateCreateInfoNV; + + + +#define VK_EXT_discard_rectangles 1 +#define VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION 1 +#define VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME "VK_EXT_discard_rectangles" + +typedef enum VkDiscardRectangleModeEXT { + VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT = 0, + VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT = 1, + VK_DISCARD_RECTANGLE_MODE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDiscardRectangleModeEXT; +typedef VkFlags VkPipelineDiscardRectangleStateCreateFlagsEXT; +typedef struct VkPhysicalDeviceDiscardRectanglePropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t maxDiscardRectangles; +} VkPhysicalDeviceDiscardRectanglePropertiesEXT; + +typedef struct VkPipelineDiscardRectangleStateCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkPipelineDiscardRectangleStateCreateFlagsEXT flags; + VkDiscardRectangleModeEXT discardRectangleMode; + uint32_t discardRectangleCount; + const VkRect2D* pDiscardRectangles; +} VkPipelineDiscardRectangleStateCreateInfoEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdSetDiscardRectangleEXT)(VkCommandBuffer commandBuffer, uint32_t firstDiscardRectangle, uint32_t discardRectangleCount, const VkRect2D* pDiscardRectangles); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetDiscardRectangleEXT( + VkCommandBuffer commandBuffer, + uint32_t firstDiscardRectangle, + uint32_t discardRectangleCount, + const VkRect2D* pDiscardRectangles); +#endif + + +#define VK_EXT_conservative_rasterization 1 +#define VK_EXT_CONSERVATIVE_RASTERIZATION_SPEC_VERSION 1 +#define VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME "VK_EXT_conservative_rasterization" + +typedef enum VkConservativeRasterizationModeEXT { + VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT = 0, + VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT = 1, + VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT = 2, + VK_CONSERVATIVE_RASTERIZATION_MODE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkConservativeRasterizationModeEXT; +typedef VkFlags VkPipelineRasterizationConservativeStateCreateFlagsEXT; +typedef struct VkPhysicalDeviceConservativeRasterizationPropertiesEXT { + VkStructureType sType; + void* pNext; + float primitiveOverestimationSize; + float maxExtraPrimitiveOverestimationSize; + float extraPrimitiveOverestimationSizeGranularity; + VkBool32 primitiveUnderestimation; + VkBool32 conservativePointAndLineRasterization; + VkBool32 degenerateTrianglesRasterized; + VkBool32 degenerateLinesRasterized; + VkBool32 fullyCoveredFragmentShaderInputVariable; + VkBool32 conservativeRasterizationPostDepthCoverage; +} VkPhysicalDeviceConservativeRasterizationPropertiesEXT; + +typedef struct VkPipelineRasterizationConservativeStateCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkPipelineRasterizationConservativeStateCreateFlagsEXT flags; + VkConservativeRasterizationModeEXT conservativeRasterizationMode; + float extraPrimitiveOverestimationSize; +} VkPipelineRasterizationConservativeStateCreateInfoEXT; + + + +#define VK_EXT_depth_clip_enable 1 +#define VK_EXT_DEPTH_CLIP_ENABLE_SPEC_VERSION 1 +#define VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME "VK_EXT_depth_clip_enable" +typedef VkFlags VkPipelineRasterizationDepthClipStateCreateFlagsEXT; +typedef struct VkPhysicalDeviceDepthClipEnableFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 depthClipEnable; +} VkPhysicalDeviceDepthClipEnableFeaturesEXT; + +typedef struct VkPipelineRasterizationDepthClipStateCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkPipelineRasterizationDepthClipStateCreateFlagsEXT flags; + VkBool32 depthClipEnable; +} VkPipelineRasterizationDepthClipStateCreateInfoEXT; + + + +#define VK_EXT_swapchain_colorspace 1 +#define VK_EXT_SWAPCHAIN_COLOR_SPACE_SPEC_VERSION 4 +#define VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME "VK_EXT_swapchain_colorspace" + + +#define VK_EXT_hdr_metadata 1 +#define VK_EXT_HDR_METADATA_SPEC_VERSION 2 +#define VK_EXT_HDR_METADATA_EXTENSION_NAME "VK_EXT_hdr_metadata" +typedef struct VkXYColorEXT { + float x; + float y; +} VkXYColorEXT; + +typedef struct VkHdrMetadataEXT { + VkStructureType sType; + const void* pNext; + VkXYColorEXT displayPrimaryRed; + VkXYColorEXT displayPrimaryGreen; + VkXYColorEXT displayPrimaryBlue; + VkXYColorEXT whitePoint; + float maxLuminance; + float minLuminance; + float maxContentLightLevel; + float maxFrameAverageLightLevel; +} VkHdrMetadataEXT; + +typedef void (VKAPI_PTR *PFN_vkSetHdrMetadataEXT)(VkDevice device, uint32_t swapchainCount, const VkSwapchainKHR* pSwapchains, const VkHdrMetadataEXT* pMetadata); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkSetHdrMetadataEXT( + VkDevice device, + uint32_t swapchainCount, + const VkSwapchainKHR* pSwapchains, + const VkHdrMetadataEXT* pMetadata); +#endif + + +#define VK_EXT_external_memory_dma_buf 1 +#define VK_EXT_EXTERNAL_MEMORY_DMA_BUF_SPEC_VERSION 1 +#define VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME "VK_EXT_external_memory_dma_buf" + + +#define VK_EXT_queue_family_foreign 1 +#define VK_EXT_QUEUE_FAMILY_FOREIGN_SPEC_VERSION 1 +#define VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME "VK_EXT_queue_family_foreign" +#define VK_QUEUE_FAMILY_FOREIGN_EXT (~2U) + + +#define VK_EXT_debug_utils 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugUtilsMessengerEXT) +#define VK_EXT_DEBUG_UTILS_SPEC_VERSION 2 +#define VK_EXT_DEBUG_UTILS_EXTENSION_NAME "VK_EXT_debug_utils" +typedef VkFlags VkDebugUtilsMessengerCallbackDataFlagsEXT; + +typedef enum VkDebugUtilsMessageSeverityFlagBitsEXT { + VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT = 0x00000001, + VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT = 0x00000010, + VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT = 0x00000100, + VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT = 0x00001000, + VK_DEBUG_UTILS_MESSAGE_SEVERITY_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDebugUtilsMessageSeverityFlagBitsEXT; + +typedef enum VkDebugUtilsMessageTypeFlagBitsEXT { + VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT = 0x00000001, + VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT = 0x00000002, + VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT = 0x00000004, + VK_DEBUG_UTILS_MESSAGE_TYPE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDebugUtilsMessageTypeFlagBitsEXT; +typedef VkFlags VkDebugUtilsMessageTypeFlagsEXT; +typedef VkFlags VkDebugUtilsMessageSeverityFlagsEXT; +typedef VkFlags VkDebugUtilsMessengerCreateFlagsEXT; +typedef struct VkDebugUtilsLabelEXT { + VkStructureType sType; + const void* pNext; + const char* pLabelName; + float color[4]; +} VkDebugUtilsLabelEXT; + +typedef struct VkDebugUtilsObjectNameInfoEXT { + VkStructureType sType; + const void* pNext; + VkObjectType objectType; + uint64_t objectHandle; + const char* pObjectName; +} VkDebugUtilsObjectNameInfoEXT; + +typedef struct VkDebugUtilsMessengerCallbackDataEXT { + VkStructureType sType; + const void* pNext; + VkDebugUtilsMessengerCallbackDataFlagsEXT flags; + const char* pMessageIdName; + int32_t messageIdNumber; + const char* pMessage; + uint32_t queueLabelCount; + const VkDebugUtilsLabelEXT* pQueueLabels; + uint32_t cmdBufLabelCount; + const VkDebugUtilsLabelEXT* pCmdBufLabels; + uint32_t objectCount; + const VkDebugUtilsObjectNameInfoEXT* pObjects; +} VkDebugUtilsMessengerCallbackDataEXT; + +typedef VkBool32 (VKAPI_PTR *PFN_vkDebugUtilsMessengerCallbackEXT)( + VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageTypes, + const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, + void* pUserData); + +typedef struct VkDebugUtilsMessengerCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkDebugUtilsMessengerCreateFlagsEXT flags; + VkDebugUtilsMessageSeverityFlagsEXT messageSeverity; + VkDebugUtilsMessageTypeFlagsEXT messageType; + PFN_vkDebugUtilsMessengerCallbackEXT pfnUserCallback; + void* pUserData; +} VkDebugUtilsMessengerCreateInfoEXT; + +typedef struct VkDebugUtilsObjectTagInfoEXT { + VkStructureType sType; + const void* pNext; + VkObjectType objectType; + uint64_t objectHandle; + uint64_t tagName; + size_t tagSize; + const void* pTag; +} VkDebugUtilsObjectTagInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkSetDebugUtilsObjectNameEXT)(VkDevice device, const VkDebugUtilsObjectNameInfoEXT* pNameInfo); +typedef VkResult (VKAPI_PTR *PFN_vkSetDebugUtilsObjectTagEXT)(VkDevice device, const VkDebugUtilsObjectTagInfoEXT* pTagInfo); +typedef void (VKAPI_PTR *PFN_vkQueueBeginDebugUtilsLabelEXT)(VkQueue queue, const VkDebugUtilsLabelEXT* pLabelInfo); +typedef void (VKAPI_PTR *PFN_vkQueueEndDebugUtilsLabelEXT)(VkQueue queue); +typedef void (VKAPI_PTR *PFN_vkQueueInsertDebugUtilsLabelEXT)(VkQueue queue, const VkDebugUtilsLabelEXT* pLabelInfo); +typedef void (VKAPI_PTR *PFN_vkCmdBeginDebugUtilsLabelEXT)(VkCommandBuffer commandBuffer, const VkDebugUtilsLabelEXT* pLabelInfo); +typedef void (VKAPI_PTR *PFN_vkCmdEndDebugUtilsLabelEXT)(VkCommandBuffer commandBuffer); +typedef void (VKAPI_PTR *PFN_vkCmdInsertDebugUtilsLabelEXT)(VkCommandBuffer commandBuffer, const VkDebugUtilsLabelEXT* pLabelInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCreateDebugUtilsMessengerEXT)(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pMessenger); +typedef void (VKAPI_PTR *PFN_vkDestroyDebugUtilsMessengerEXT)(VkInstance instance, VkDebugUtilsMessengerEXT messenger, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkSubmitDebugUtilsMessageEXT)(VkInstance instance, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageTypes, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkSetDebugUtilsObjectNameEXT( + VkDevice device, + const VkDebugUtilsObjectNameInfoEXT* pNameInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkSetDebugUtilsObjectTagEXT( + VkDevice device, + const VkDebugUtilsObjectTagInfoEXT* pTagInfo); + +VKAPI_ATTR void VKAPI_CALL vkQueueBeginDebugUtilsLabelEXT( + VkQueue queue, + const VkDebugUtilsLabelEXT* pLabelInfo); + +VKAPI_ATTR void VKAPI_CALL vkQueueEndDebugUtilsLabelEXT( + VkQueue queue); + +VKAPI_ATTR void VKAPI_CALL vkQueueInsertDebugUtilsLabelEXT( + VkQueue queue, + const VkDebugUtilsLabelEXT* pLabelInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdBeginDebugUtilsLabelEXT( + VkCommandBuffer commandBuffer, + const VkDebugUtilsLabelEXT* pLabelInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdEndDebugUtilsLabelEXT( + VkCommandBuffer commandBuffer); + +VKAPI_ATTR void VKAPI_CALL vkCmdInsertDebugUtilsLabelEXT( + VkCommandBuffer commandBuffer, + const VkDebugUtilsLabelEXT* pLabelInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugUtilsMessengerEXT( + VkInstance instance, + const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDebugUtilsMessengerEXT* pMessenger); + +VKAPI_ATTR void VKAPI_CALL vkDestroyDebugUtilsMessengerEXT( + VkInstance instance, + VkDebugUtilsMessengerEXT messenger, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR void VKAPI_CALL vkSubmitDebugUtilsMessageEXT( + VkInstance instance, + VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageTypes, + const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData); +#endif + + +#define VK_EXT_sampler_filter_minmax 1 +#define VK_EXT_SAMPLER_FILTER_MINMAX_SPEC_VERSION 2 +#define VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME "VK_EXT_sampler_filter_minmax" +typedef VkSamplerReductionMode VkSamplerReductionModeEXT; + +typedef VkSamplerReductionModeCreateInfo VkSamplerReductionModeCreateInfoEXT; + +typedef VkPhysicalDeviceSamplerFilterMinmaxProperties VkPhysicalDeviceSamplerFilterMinmaxPropertiesEXT; + + + +#define VK_AMD_gpu_shader_int16 1 +#define VK_AMD_GPU_SHADER_INT16_SPEC_VERSION 2 +#define VK_AMD_GPU_SHADER_INT16_EXTENSION_NAME "VK_AMD_gpu_shader_int16" + + +#define VK_AMD_mixed_attachment_samples 1 +#define VK_AMD_MIXED_ATTACHMENT_SAMPLES_SPEC_VERSION 1 +#define VK_AMD_MIXED_ATTACHMENT_SAMPLES_EXTENSION_NAME "VK_AMD_mixed_attachment_samples" + + +#define VK_AMD_shader_fragment_mask 1 +#define VK_AMD_SHADER_FRAGMENT_MASK_SPEC_VERSION 1 +#define VK_AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME "VK_AMD_shader_fragment_mask" + + +#define VK_EXT_inline_uniform_block 1 +#define VK_EXT_INLINE_UNIFORM_BLOCK_SPEC_VERSION 1 +#define VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME "VK_EXT_inline_uniform_block" +typedef VkPhysicalDeviceInlineUniformBlockFeatures VkPhysicalDeviceInlineUniformBlockFeaturesEXT; + +typedef VkPhysicalDeviceInlineUniformBlockProperties VkPhysicalDeviceInlineUniformBlockPropertiesEXT; + +typedef VkWriteDescriptorSetInlineUniformBlock VkWriteDescriptorSetInlineUniformBlockEXT; + +typedef VkDescriptorPoolInlineUniformBlockCreateInfo VkDescriptorPoolInlineUniformBlockCreateInfoEXT; + + + +#define VK_EXT_shader_stencil_export 1 +#define VK_EXT_SHADER_STENCIL_EXPORT_SPEC_VERSION 1 +#define VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME "VK_EXT_shader_stencil_export" + + +#define VK_EXT_sample_locations 1 +#define VK_EXT_SAMPLE_LOCATIONS_SPEC_VERSION 1 +#define VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME "VK_EXT_sample_locations" +typedef struct VkSampleLocationEXT { + float x; + float y; +} VkSampleLocationEXT; + +typedef struct VkSampleLocationsInfoEXT { + VkStructureType sType; + const void* pNext; + VkSampleCountFlagBits sampleLocationsPerPixel; + VkExtent2D sampleLocationGridSize; + uint32_t sampleLocationsCount; + const VkSampleLocationEXT* pSampleLocations; +} VkSampleLocationsInfoEXT; + +typedef struct VkAttachmentSampleLocationsEXT { + uint32_t attachmentIndex; + VkSampleLocationsInfoEXT sampleLocationsInfo; +} VkAttachmentSampleLocationsEXT; + +typedef struct VkSubpassSampleLocationsEXT { + uint32_t subpassIndex; + VkSampleLocationsInfoEXT sampleLocationsInfo; +} VkSubpassSampleLocationsEXT; + +typedef struct VkRenderPassSampleLocationsBeginInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t attachmentInitialSampleLocationsCount; + const VkAttachmentSampleLocationsEXT* pAttachmentInitialSampleLocations; + uint32_t postSubpassSampleLocationsCount; + const VkSubpassSampleLocationsEXT* pPostSubpassSampleLocations; +} VkRenderPassSampleLocationsBeginInfoEXT; + +typedef struct VkPipelineSampleLocationsStateCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkBool32 sampleLocationsEnable; + VkSampleLocationsInfoEXT sampleLocationsInfo; +} VkPipelineSampleLocationsStateCreateInfoEXT; + +typedef struct VkPhysicalDeviceSampleLocationsPropertiesEXT { + VkStructureType sType; + void* pNext; + VkSampleCountFlags sampleLocationSampleCounts; + VkExtent2D maxSampleLocationGridSize; + float sampleLocationCoordinateRange[2]; + uint32_t sampleLocationSubPixelBits; + VkBool32 variableSampleLocations; +} VkPhysicalDeviceSampleLocationsPropertiesEXT; + +typedef struct VkMultisamplePropertiesEXT { + VkStructureType sType; + void* pNext; + VkExtent2D maxSampleLocationGridSize; +} VkMultisamplePropertiesEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdSetSampleLocationsEXT)(VkCommandBuffer commandBuffer, const VkSampleLocationsInfoEXT* pSampleLocationsInfo); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT)(VkPhysicalDevice physicalDevice, VkSampleCountFlagBits samples, VkMultisamplePropertiesEXT* pMultisampleProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetSampleLocationsEXT( + VkCommandBuffer commandBuffer, + const VkSampleLocationsInfoEXT* pSampleLocationsInfo); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMultisamplePropertiesEXT( + VkPhysicalDevice physicalDevice, + VkSampleCountFlagBits samples, + VkMultisamplePropertiesEXT* pMultisampleProperties); +#endif + + +#define VK_EXT_blend_operation_advanced 1 +#define VK_EXT_BLEND_OPERATION_ADVANCED_SPEC_VERSION 2 +#define VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME "VK_EXT_blend_operation_advanced" + +typedef enum VkBlendOverlapEXT { + VK_BLEND_OVERLAP_UNCORRELATED_EXT = 0, + VK_BLEND_OVERLAP_DISJOINT_EXT = 1, + VK_BLEND_OVERLAP_CONJOINT_EXT = 2, + VK_BLEND_OVERLAP_MAX_ENUM_EXT = 0x7FFFFFFF +} VkBlendOverlapEXT; +typedef struct VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 advancedBlendCoherentOperations; +} VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT; + +typedef struct VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t advancedBlendMaxColorAttachments; + VkBool32 advancedBlendIndependentBlend; + VkBool32 advancedBlendNonPremultipliedSrcColor; + VkBool32 advancedBlendNonPremultipliedDstColor; + VkBool32 advancedBlendCorrelatedOverlap; + VkBool32 advancedBlendAllOperations; +} VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT; + +typedef struct VkPipelineColorBlendAdvancedStateCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkBool32 srcPremultiplied; + VkBool32 dstPremultiplied; + VkBlendOverlapEXT blendOverlap; +} VkPipelineColorBlendAdvancedStateCreateInfoEXT; + + + +#define VK_NV_fragment_coverage_to_color 1 +#define VK_NV_FRAGMENT_COVERAGE_TO_COLOR_SPEC_VERSION 1 +#define VK_NV_FRAGMENT_COVERAGE_TO_COLOR_EXTENSION_NAME "VK_NV_fragment_coverage_to_color" +typedef VkFlags VkPipelineCoverageToColorStateCreateFlagsNV; +typedef struct VkPipelineCoverageToColorStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkPipelineCoverageToColorStateCreateFlagsNV flags; + VkBool32 coverageToColorEnable; + uint32_t coverageToColorLocation; +} VkPipelineCoverageToColorStateCreateInfoNV; + + + +#define VK_NV_framebuffer_mixed_samples 1 +#define VK_NV_FRAMEBUFFER_MIXED_SAMPLES_SPEC_VERSION 1 +#define VK_NV_FRAMEBUFFER_MIXED_SAMPLES_EXTENSION_NAME "VK_NV_framebuffer_mixed_samples" + +typedef enum VkCoverageModulationModeNV { + VK_COVERAGE_MODULATION_MODE_NONE_NV = 0, + VK_COVERAGE_MODULATION_MODE_RGB_NV = 1, + VK_COVERAGE_MODULATION_MODE_ALPHA_NV = 2, + VK_COVERAGE_MODULATION_MODE_RGBA_NV = 3, + VK_COVERAGE_MODULATION_MODE_MAX_ENUM_NV = 0x7FFFFFFF +} VkCoverageModulationModeNV; +typedef VkFlags VkPipelineCoverageModulationStateCreateFlagsNV; +typedef struct VkPipelineCoverageModulationStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkPipelineCoverageModulationStateCreateFlagsNV flags; + VkCoverageModulationModeNV coverageModulationMode; + VkBool32 coverageModulationTableEnable; + uint32_t coverageModulationTableCount; + const float* pCoverageModulationTable; +} VkPipelineCoverageModulationStateCreateInfoNV; + + + +#define VK_NV_fill_rectangle 1 +#define VK_NV_FILL_RECTANGLE_SPEC_VERSION 1 +#define VK_NV_FILL_RECTANGLE_EXTENSION_NAME "VK_NV_fill_rectangle" + + +#define VK_NV_shader_sm_builtins 1 +#define VK_NV_SHADER_SM_BUILTINS_SPEC_VERSION 1 +#define VK_NV_SHADER_SM_BUILTINS_EXTENSION_NAME "VK_NV_shader_sm_builtins" +typedef struct VkPhysicalDeviceShaderSMBuiltinsPropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t shaderSMCount; + uint32_t shaderWarpsPerSM; +} VkPhysicalDeviceShaderSMBuiltinsPropertiesNV; + +typedef struct VkPhysicalDeviceShaderSMBuiltinsFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 shaderSMBuiltins; +} VkPhysicalDeviceShaderSMBuiltinsFeaturesNV; + + + +#define VK_EXT_post_depth_coverage 1 +#define VK_EXT_POST_DEPTH_COVERAGE_SPEC_VERSION 1 +#define VK_EXT_POST_DEPTH_COVERAGE_EXTENSION_NAME "VK_EXT_post_depth_coverage" + + +#define VK_EXT_image_drm_format_modifier 1 +#define VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_SPEC_VERSION 2 +#define VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME "VK_EXT_image_drm_format_modifier" +typedef struct VkDrmFormatModifierPropertiesEXT { + uint64_t drmFormatModifier; + uint32_t drmFormatModifierPlaneCount; + VkFormatFeatureFlags drmFormatModifierTilingFeatures; +} VkDrmFormatModifierPropertiesEXT; + +typedef struct VkDrmFormatModifierPropertiesListEXT { + VkStructureType sType; + void* pNext; + uint32_t drmFormatModifierCount; + VkDrmFormatModifierPropertiesEXT* pDrmFormatModifierProperties; +} VkDrmFormatModifierPropertiesListEXT; + +typedef struct VkPhysicalDeviceImageDrmFormatModifierInfoEXT { + VkStructureType sType; + const void* pNext; + uint64_t drmFormatModifier; + VkSharingMode sharingMode; + uint32_t queueFamilyIndexCount; + const uint32_t* pQueueFamilyIndices; +} VkPhysicalDeviceImageDrmFormatModifierInfoEXT; + +typedef struct VkImageDrmFormatModifierListCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t drmFormatModifierCount; + const uint64_t* pDrmFormatModifiers; +} VkImageDrmFormatModifierListCreateInfoEXT; + +typedef struct VkImageDrmFormatModifierExplicitCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint64_t drmFormatModifier; + uint32_t drmFormatModifierPlaneCount; + const VkSubresourceLayout* pPlaneLayouts; +} VkImageDrmFormatModifierExplicitCreateInfoEXT; + +typedef struct VkImageDrmFormatModifierPropertiesEXT { + VkStructureType sType; + void* pNext; + uint64_t drmFormatModifier; +} VkImageDrmFormatModifierPropertiesEXT; + +typedef struct VkDrmFormatModifierProperties2EXT { + uint64_t drmFormatModifier; + uint32_t drmFormatModifierPlaneCount; + VkFormatFeatureFlags2 drmFormatModifierTilingFeatures; +} VkDrmFormatModifierProperties2EXT; + +typedef struct VkDrmFormatModifierPropertiesList2EXT { + VkStructureType sType; + void* pNext; + uint32_t drmFormatModifierCount; + VkDrmFormatModifierProperties2EXT* pDrmFormatModifierProperties; +} VkDrmFormatModifierPropertiesList2EXT; + +typedef VkResult (VKAPI_PTR *PFN_vkGetImageDrmFormatModifierPropertiesEXT)(VkDevice device, VkImage image, VkImageDrmFormatModifierPropertiesEXT* pProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetImageDrmFormatModifierPropertiesEXT( + VkDevice device, + VkImage image, + VkImageDrmFormatModifierPropertiesEXT* pProperties); +#endif + + +#define VK_EXT_validation_cache 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkValidationCacheEXT) +#define VK_EXT_VALIDATION_CACHE_SPEC_VERSION 1 +#define VK_EXT_VALIDATION_CACHE_EXTENSION_NAME "VK_EXT_validation_cache" + +typedef enum VkValidationCacheHeaderVersionEXT { + VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT = 1, + VK_VALIDATION_CACHE_HEADER_VERSION_MAX_ENUM_EXT = 0x7FFFFFFF +} VkValidationCacheHeaderVersionEXT; +typedef VkFlags VkValidationCacheCreateFlagsEXT; +typedef struct VkValidationCacheCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkValidationCacheCreateFlagsEXT flags; + size_t initialDataSize; + const void* pInitialData; +} VkValidationCacheCreateInfoEXT; + +typedef struct VkShaderModuleValidationCacheCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkValidationCacheEXT validationCache; +} VkShaderModuleValidationCacheCreateInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateValidationCacheEXT)(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache); +typedef void (VKAPI_PTR *PFN_vkDestroyValidationCacheEXT)(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkMergeValidationCachesEXT)(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches); +typedef VkResult (VKAPI_PTR *PFN_vkGetValidationCacheDataEXT)(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateValidationCacheEXT( + VkDevice device, + const VkValidationCacheCreateInfoEXT* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkValidationCacheEXT* pValidationCache); + +VKAPI_ATTR void VKAPI_CALL vkDestroyValidationCacheEXT( + VkDevice device, + VkValidationCacheEXT validationCache, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkMergeValidationCachesEXT( + VkDevice device, + VkValidationCacheEXT dstCache, + uint32_t srcCacheCount, + const VkValidationCacheEXT* pSrcCaches); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetValidationCacheDataEXT( + VkDevice device, + VkValidationCacheEXT validationCache, + size_t* pDataSize, + void* pData); +#endif + + +#define VK_EXT_descriptor_indexing 1 +#define VK_EXT_DESCRIPTOR_INDEXING_SPEC_VERSION 2 +#define VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME "VK_EXT_descriptor_indexing" +typedef VkDescriptorBindingFlagBits VkDescriptorBindingFlagBitsEXT; + +typedef VkDescriptorBindingFlags VkDescriptorBindingFlagsEXT; + +typedef VkDescriptorSetLayoutBindingFlagsCreateInfo VkDescriptorSetLayoutBindingFlagsCreateInfoEXT; + +typedef VkPhysicalDeviceDescriptorIndexingFeatures VkPhysicalDeviceDescriptorIndexingFeaturesEXT; + +typedef VkPhysicalDeviceDescriptorIndexingProperties VkPhysicalDeviceDescriptorIndexingPropertiesEXT; + +typedef VkDescriptorSetVariableDescriptorCountAllocateInfo VkDescriptorSetVariableDescriptorCountAllocateInfoEXT; + +typedef VkDescriptorSetVariableDescriptorCountLayoutSupport VkDescriptorSetVariableDescriptorCountLayoutSupportEXT; + + + +#define VK_EXT_shader_viewport_index_layer 1 +#define VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_SPEC_VERSION 1 +#define VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME "VK_EXT_shader_viewport_index_layer" + + +#define VK_NV_shading_rate_image 1 +#define VK_NV_SHADING_RATE_IMAGE_SPEC_VERSION 3 +#define VK_NV_SHADING_RATE_IMAGE_EXTENSION_NAME "VK_NV_shading_rate_image" + +typedef enum VkShadingRatePaletteEntryNV { + VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV = 0, + VK_SHADING_RATE_PALETTE_ENTRY_16_INVOCATIONS_PER_PIXEL_NV = 1, + VK_SHADING_RATE_PALETTE_ENTRY_8_INVOCATIONS_PER_PIXEL_NV = 2, + VK_SHADING_RATE_PALETTE_ENTRY_4_INVOCATIONS_PER_PIXEL_NV = 3, + VK_SHADING_RATE_PALETTE_ENTRY_2_INVOCATIONS_PER_PIXEL_NV = 4, + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_PIXEL_NV = 5, + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X1_PIXELS_NV = 6, + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_1X2_PIXELS_NV = 7, + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X2_PIXELS_NV = 8, + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X2_PIXELS_NV = 9, + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X4_PIXELS_NV = 10, + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV = 11, + VK_SHADING_RATE_PALETTE_ENTRY_MAX_ENUM_NV = 0x7FFFFFFF +} VkShadingRatePaletteEntryNV; + +typedef enum VkCoarseSampleOrderTypeNV { + VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV = 0, + VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV = 1, + VK_COARSE_SAMPLE_ORDER_TYPE_PIXEL_MAJOR_NV = 2, + VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV = 3, + VK_COARSE_SAMPLE_ORDER_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkCoarseSampleOrderTypeNV; +typedef struct VkShadingRatePaletteNV { + uint32_t shadingRatePaletteEntryCount; + const VkShadingRatePaletteEntryNV* pShadingRatePaletteEntries; +} VkShadingRatePaletteNV; + +typedef struct VkPipelineViewportShadingRateImageStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkBool32 shadingRateImageEnable; + uint32_t viewportCount; + const VkShadingRatePaletteNV* pShadingRatePalettes; +} VkPipelineViewportShadingRateImageStateCreateInfoNV; + +typedef struct VkPhysicalDeviceShadingRateImageFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 shadingRateImage; + VkBool32 shadingRateCoarseSampleOrder; +} VkPhysicalDeviceShadingRateImageFeaturesNV; + +typedef struct VkPhysicalDeviceShadingRateImagePropertiesNV { + VkStructureType sType; + void* pNext; + VkExtent2D shadingRateTexelSize; + uint32_t shadingRatePaletteSize; + uint32_t shadingRateMaxCoarseSamples; +} VkPhysicalDeviceShadingRateImagePropertiesNV; + +typedef struct VkCoarseSampleLocationNV { + uint32_t pixelX; + uint32_t pixelY; + uint32_t sample; +} VkCoarseSampleLocationNV; + +typedef struct VkCoarseSampleOrderCustomNV { + VkShadingRatePaletteEntryNV shadingRate; + uint32_t sampleCount; + uint32_t sampleLocationCount; + const VkCoarseSampleLocationNV* pSampleLocations; +} VkCoarseSampleOrderCustomNV; + +typedef struct VkPipelineViewportCoarseSampleOrderStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkCoarseSampleOrderTypeNV sampleOrderType; + uint32_t customSampleOrderCount; + const VkCoarseSampleOrderCustomNV* pCustomSampleOrders; +} VkPipelineViewportCoarseSampleOrderStateCreateInfoNV; + +typedef void (VKAPI_PTR *PFN_vkCmdBindShadingRateImageNV)(VkCommandBuffer commandBuffer, VkImageView imageView, VkImageLayout imageLayout); +typedef void (VKAPI_PTR *PFN_vkCmdSetViewportShadingRatePaletteNV)(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkShadingRatePaletteNV* pShadingRatePalettes); +typedef void (VKAPI_PTR *PFN_vkCmdSetCoarseSampleOrderNV)(VkCommandBuffer commandBuffer, VkCoarseSampleOrderTypeNV sampleOrderType, uint32_t customSampleOrderCount, const VkCoarseSampleOrderCustomNV* pCustomSampleOrders); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBindShadingRateImageNV( + VkCommandBuffer commandBuffer, + VkImageView imageView, + VkImageLayout imageLayout); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportShadingRatePaletteNV( + VkCommandBuffer commandBuffer, + uint32_t firstViewport, + uint32_t viewportCount, + const VkShadingRatePaletteNV* pShadingRatePalettes); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetCoarseSampleOrderNV( + VkCommandBuffer commandBuffer, + VkCoarseSampleOrderTypeNV sampleOrderType, + uint32_t customSampleOrderCount, + const VkCoarseSampleOrderCustomNV* pCustomSampleOrders); +#endif + + +#define VK_NV_ray_tracing 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkAccelerationStructureNV) +#define VK_NV_RAY_TRACING_SPEC_VERSION 3 +#define VK_NV_RAY_TRACING_EXTENSION_NAME "VK_NV_ray_tracing" +#define VK_SHADER_UNUSED_KHR (~0U) +#define VK_SHADER_UNUSED_NV VK_SHADER_UNUSED_KHR + +typedef enum VkRayTracingShaderGroupTypeKHR { + VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR = 0, + VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR = 1, + VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR = 2, + VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR, + VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR, + VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR, + VK_RAY_TRACING_SHADER_GROUP_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkRayTracingShaderGroupTypeKHR; +typedef VkRayTracingShaderGroupTypeKHR VkRayTracingShaderGroupTypeNV; + + +typedef enum VkGeometryTypeKHR { + VK_GEOMETRY_TYPE_TRIANGLES_KHR = 0, + VK_GEOMETRY_TYPE_AABBS_KHR = 1, + VK_GEOMETRY_TYPE_INSTANCES_KHR = 2, + VK_GEOMETRY_TYPE_TRIANGLES_NV = VK_GEOMETRY_TYPE_TRIANGLES_KHR, + VK_GEOMETRY_TYPE_AABBS_NV = VK_GEOMETRY_TYPE_AABBS_KHR, + VK_GEOMETRY_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkGeometryTypeKHR; +typedef VkGeometryTypeKHR VkGeometryTypeNV; + + +typedef enum VkAccelerationStructureTypeKHR { + VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR = 0, + VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR = 1, + VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR = 2, + VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR, + VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR, + VK_ACCELERATION_STRUCTURE_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAccelerationStructureTypeKHR; +typedef VkAccelerationStructureTypeKHR VkAccelerationStructureTypeNV; + + +typedef enum VkCopyAccelerationStructureModeKHR { + VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR = 0, + VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR = 1, + VK_COPY_ACCELERATION_STRUCTURE_MODE_SERIALIZE_KHR = 2, + VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR = 3, + VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV = VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR, + VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV = VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR, + VK_COPY_ACCELERATION_STRUCTURE_MODE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkCopyAccelerationStructureModeKHR; +typedef VkCopyAccelerationStructureModeKHR VkCopyAccelerationStructureModeNV; + + +typedef enum VkAccelerationStructureMemoryRequirementsTypeNV { + VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV = 0, + VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV = 1, + VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV = 2, + VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkAccelerationStructureMemoryRequirementsTypeNV; + +typedef enum VkGeometryFlagBitsKHR { + VK_GEOMETRY_OPAQUE_BIT_KHR = 0x00000001, + VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR = 0x00000002, + VK_GEOMETRY_OPAQUE_BIT_NV = VK_GEOMETRY_OPAQUE_BIT_KHR, + VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_NV = VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR, + VK_GEOMETRY_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkGeometryFlagBitsKHR; +typedef VkFlags VkGeometryFlagsKHR; +typedef VkGeometryFlagsKHR VkGeometryFlagsNV; + +typedef VkGeometryFlagBitsKHR VkGeometryFlagBitsNV; + + +typedef enum VkGeometryInstanceFlagBitsKHR { + VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR = 0x00000001, + VK_GEOMETRY_INSTANCE_TRIANGLE_FLIP_FACING_BIT_KHR = 0x00000002, + VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR = 0x00000004, + VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR = 0x00000008, + VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR = VK_GEOMETRY_INSTANCE_TRIANGLE_FLIP_FACING_BIT_KHR, + VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR, + VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_NV = VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR, + VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_NV = VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR, + VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_NV = VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR, + VK_GEOMETRY_INSTANCE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkGeometryInstanceFlagBitsKHR; +typedef VkFlags VkGeometryInstanceFlagsKHR; +typedef VkGeometryInstanceFlagsKHR VkGeometryInstanceFlagsNV; + +typedef VkGeometryInstanceFlagBitsKHR VkGeometryInstanceFlagBitsNV; + + +typedef enum VkBuildAccelerationStructureFlagBitsKHR { + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR = 0x00000001, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR = 0x00000002, + VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR = 0x00000004, + VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR = 0x00000008, + VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR = 0x00000010, + VK_BUILD_ACCELERATION_STRUCTURE_MOTION_BIT_NV = 0x00000020, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR, + VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR, + VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR, + VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR, + VK_BUILD_ACCELERATION_STRUCTURE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkBuildAccelerationStructureFlagBitsKHR; +typedef VkFlags VkBuildAccelerationStructureFlagsKHR; +typedef VkBuildAccelerationStructureFlagsKHR VkBuildAccelerationStructureFlagsNV; + +typedef VkBuildAccelerationStructureFlagBitsKHR VkBuildAccelerationStructureFlagBitsNV; + +typedef struct VkRayTracingShaderGroupCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkRayTracingShaderGroupTypeKHR type; + uint32_t generalShader; + uint32_t closestHitShader; + uint32_t anyHitShader; + uint32_t intersectionShader; +} VkRayTracingShaderGroupCreateInfoNV; + +typedef struct VkRayTracingPipelineCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkPipelineCreateFlags flags; + uint32_t stageCount; + const VkPipelineShaderStageCreateInfo* pStages; + uint32_t groupCount; + const VkRayTracingShaderGroupCreateInfoNV* pGroups; + uint32_t maxRecursionDepth; + VkPipelineLayout layout; + VkPipeline basePipelineHandle; + int32_t basePipelineIndex; +} VkRayTracingPipelineCreateInfoNV; + +typedef struct VkGeometryTrianglesNV { + VkStructureType sType; + const void* pNext; + VkBuffer vertexData; + VkDeviceSize vertexOffset; + uint32_t vertexCount; + VkDeviceSize vertexStride; + VkFormat vertexFormat; + VkBuffer indexData; + VkDeviceSize indexOffset; + uint32_t indexCount; + VkIndexType indexType; + VkBuffer transformData; + VkDeviceSize transformOffset; +} VkGeometryTrianglesNV; + +typedef struct VkGeometryAABBNV { + VkStructureType sType; + const void* pNext; + VkBuffer aabbData; + uint32_t numAABBs; + uint32_t stride; + VkDeviceSize offset; +} VkGeometryAABBNV; + +typedef struct VkGeometryDataNV { + VkGeometryTrianglesNV triangles; + VkGeometryAABBNV aabbs; +} VkGeometryDataNV; + +typedef struct VkGeometryNV { + VkStructureType sType; + const void* pNext; + VkGeometryTypeKHR geometryType; + VkGeometryDataNV geometry; + VkGeometryFlagsKHR flags; +} VkGeometryNV; + +typedef struct VkAccelerationStructureInfoNV { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureTypeNV type; + VkBuildAccelerationStructureFlagsNV flags; + uint32_t instanceCount; + uint32_t geometryCount; + const VkGeometryNV* pGeometries; +} VkAccelerationStructureInfoNV; + +typedef struct VkAccelerationStructureCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkDeviceSize compactedSize; + VkAccelerationStructureInfoNV info; +} VkAccelerationStructureCreateInfoNV; + +typedef struct VkBindAccelerationStructureMemoryInfoNV { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureNV accelerationStructure; + VkDeviceMemory memory; + VkDeviceSize memoryOffset; + uint32_t deviceIndexCount; + const uint32_t* pDeviceIndices; +} VkBindAccelerationStructureMemoryInfoNV; + +typedef struct VkWriteDescriptorSetAccelerationStructureNV { + VkStructureType sType; + const void* pNext; + uint32_t accelerationStructureCount; + const VkAccelerationStructureNV* pAccelerationStructures; +} VkWriteDescriptorSetAccelerationStructureNV; + +typedef struct VkAccelerationStructureMemoryRequirementsInfoNV { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureMemoryRequirementsTypeNV type; + VkAccelerationStructureNV accelerationStructure; +} VkAccelerationStructureMemoryRequirementsInfoNV; + +typedef struct VkPhysicalDeviceRayTracingPropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t shaderGroupHandleSize; + uint32_t maxRecursionDepth; + uint32_t maxShaderGroupStride; + uint32_t shaderGroupBaseAlignment; + uint64_t maxGeometryCount; + uint64_t maxInstanceCount; + uint64_t maxTriangleCount; + uint32_t maxDescriptorSetAccelerationStructures; +} VkPhysicalDeviceRayTracingPropertiesNV; + +typedef struct VkTransformMatrixKHR { + float matrix[3][4]; +} VkTransformMatrixKHR; + +typedef VkTransformMatrixKHR VkTransformMatrixNV; + +typedef struct VkAabbPositionsKHR { + float minX; + float minY; + float minZ; + float maxX; + float maxY; + float maxZ; +} VkAabbPositionsKHR; + +typedef VkAabbPositionsKHR VkAabbPositionsNV; + +typedef struct VkAccelerationStructureInstanceKHR { + VkTransformMatrixKHR transform; + uint32_t instanceCustomIndex:24; + uint32_t mask:8; + uint32_t instanceShaderBindingTableRecordOffset:24; + VkGeometryInstanceFlagsKHR flags:8; + uint64_t accelerationStructureReference; +} VkAccelerationStructureInstanceKHR; + +typedef VkAccelerationStructureInstanceKHR VkAccelerationStructureInstanceNV; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateAccelerationStructureNV)(VkDevice device, const VkAccelerationStructureCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkAccelerationStructureNV* pAccelerationStructure); +typedef void (VKAPI_PTR *PFN_vkDestroyAccelerationStructureNV)(VkDevice device, VkAccelerationStructureNV accelerationStructure, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkGetAccelerationStructureMemoryRequirementsNV)(VkDevice device, const VkAccelerationStructureMemoryRequirementsInfoNV* pInfo, VkMemoryRequirements2KHR* pMemoryRequirements); +typedef VkResult (VKAPI_PTR *PFN_vkBindAccelerationStructureMemoryNV)(VkDevice device, uint32_t bindInfoCount, const VkBindAccelerationStructureMemoryInfoNV* pBindInfos); +typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructureNV)(VkCommandBuffer commandBuffer, const VkAccelerationStructureInfoNV* pInfo, VkBuffer instanceData, VkDeviceSize instanceOffset, VkBool32 update, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, VkBuffer scratch, VkDeviceSize scratchOffset); +typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureNV)(VkCommandBuffer commandBuffer, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, VkCopyAccelerationStructureModeKHR mode); +typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysNV)(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer, VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer, VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride, VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset, VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer, VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride, uint32_t width, uint32_t height, uint32_t depth); +typedef VkResult (VKAPI_PTR *PFN_vkCreateRayTracingPipelinesNV)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); +typedef VkResult (VKAPI_PTR *PFN_vkGetRayTracingShaderGroupHandlesKHR)(VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData); +typedef VkResult (VKAPI_PTR *PFN_vkGetRayTracingShaderGroupHandlesNV)(VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData); +typedef VkResult (VKAPI_PTR *PFN_vkGetAccelerationStructureHandleNV)(VkDevice device, VkAccelerationStructureNV accelerationStructure, size_t dataSize, void* pData); +typedef void (VKAPI_PTR *PFN_vkCmdWriteAccelerationStructuresPropertiesNV)(VkCommandBuffer commandBuffer, uint32_t accelerationStructureCount, const VkAccelerationStructureNV* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery); +typedef VkResult (VKAPI_PTR *PFN_vkCompileDeferredNV)(VkDevice device, VkPipeline pipeline, uint32_t shader); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateAccelerationStructureNV( + VkDevice device, + const VkAccelerationStructureCreateInfoNV* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkAccelerationStructureNV* pAccelerationStructure); + +VKAPI_ATTR void VKAPI_CALL vkDestroyAccelerationStructureNV( + VkDevice device, + VkAccelerationStructureNV accelerationStructure, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR void VKAPI_CALL vkGetAccelerationStructureMemoryRequirementsNV( + VkDevice device, + const VkAccelerationStructureMemoryRequirementsInfoNV* pInfo, + VkMemoryRequirements2KHR* pMemoryRequirements); + +VKAPI_ATTR VkResult VKAPI_CALL vkBindAccelerationStructureMemoryNV( + VkDevice device, + uint32_t bindInfoCount, + const VkBindAccelerationStructureMemoryInfoNV* pBindInfos); + +VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructureNV( + VkCommandBuffer commandBuffer, + const VkAccelerationStructureInfoNV* pInfo, + VkBuffer instanceData, + VkDeviceSize instanceOffset, + VkBool32 update, + VkAccelerationStructureNV dst, + VkAccelerationStructureNV src, + VkBuffer scratch, + VkDeviceSize scratchOffset); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureNV( + VkCommandBuffer commandBuffer, + VkAccelerationStructureNV dst, + VkAccelerationStructureNV src, + VkCopyAccelerationStructureModeKHR mode); + +VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysNV( + VkCommandBuffer commandBuffer, + VkBuffer raygenShaderBindingTableBuffer, + VkDeviceSize raygenShaderBindingOffset, + VkBuffer missShaderBindingTableBuffer, + VkDeviceSize missShaderBindingOffset, + VkDeviceSize missShaderBindingStride, + VkBuffer hitShaderBindingTableBuffer, + VkDeviceSize hitShaderBindingOffset, + VkDeviceSize hitShaderBindingStride, + VkBuffer callableShaderBindingTableBuffer, + VkDeviceSize callableShaderBindingOffset, + VkDeviceSize callableShaderBindingStride, + uint32_t width, + uint32_t height, + uint32_t depth); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateRayTracingPipelinesNV( + VkDevice device, + VkPipelineCache pipelineCache, + uint32_t createInfoCount, + const VkRayTracingPipelineCreateInfoNV* pCreateInfos, + const VkAllocationCallbacks* pAllocator, + VkPipeline* pPipelines); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetRayTracingShaderGroupHandlesKHR( + VkDevice device, + VkPipeline pipeline, + uint32_t firstGroup, + uint32_t groupCount, + size_t dataSize, + void* pData); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetRayTracingShaderGroupHandlesNV( + VkDevice device, + VkPipeline pipeline, + uint32_t firstGroup, + uint32_t groupCount, + size_t dataSize, + void* pData); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetAccelerationStructureHandleNV( + VkDevice device, + VkAccelerationStructureNV accelerationStructure, + size_t dataSize, + void* pData); + +VKAPI_ATTR void VKAPI_CALL vkCmdWriteAccelerationStructuresPropertiesNV( + VkCommandBuffer commandBuffer, + uint32_t accelerationStructureCount, + const VkAccelerationStructureNV* pAccelerationStructures, + VkQueryType queryType, + VkQueryPool queryPool, + uint32_t firstQuery); + +VKAPI_ATTR VkResult VKAPI_CALL vkCompileDeferredNV( + VkDevice device, + VkPipeline pipeline, + uint32_t shader); +#endif + + +#define VK_NV_representative_fragment_test 1 +#define VK_NV_REPRESENTATIVE_FRAGMENT_TEST_SPEC_VERSION 2 +#define VK_NV_REPRESENTATIVE_FRAGMENT_TEST_EXTENSION_NAME "VK_NV_representative_fragment_test" +typedef struct VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 representativeFragmentTest; +} VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV; + +typedef struct VkPipelineRepresentativeFragmentTestStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkBool32 representativeFragmentTestEnable; +} VkPipelineRepresentativeFragmentTestStateCreateInfoNV; + + + +#define VK_EXT_filter_cubic 1 +#define VK_EXT_FILTER_CUBIC_SPEC_VERSION 3 +#define VK_EXT_FILTER_CUBIC_EXTENSION_NAME "VK_EXT_filter_cubic" +typedef struct VkPhysicalDeviceImageViewImageFormatInfoEXT { + VkStructureType sType; + void* pNext; + VkImageViewType imageViewType; +} VkPhysicalDeviceImageViewImageFormatInfoEXT; + +typedef struct VkFilterCubicImageViewImageFormatPropertiesEXT { + VkStructureType sType; + void* pNext; + VkBool32 filterCubic; + VkBool32 filterCubicMinmax; +} VkFilterCubicImageViewImageFormatPropertiesEXT; + + + +#define VK_QCOM_render_pass_shader_resolve 1 +#define VK_QCOM_RENDER_PASS_SHADER_RESOLVE_SPEC_VERSION 4 +#define VK_QCOM_RENDER_PASS_SHADER_RESOLVE_EXTENSION_NAME "VK_QCOM_render_pass_shader_resolve" + + +#define VK_EXT_global_priority 1 +#define VK_EXT_GLOBAL_PRIORITY_SPEC_VERSION 2 +#define VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME "VK_EXT_global_priority" +typedef VkQueueGlobalPriorityKHR VkQueueGlobalPriorityEXT; + +typedef VkDeviceQueueGlobalPriorityCreateInfoKHR VkDeviceQueueGlobalPriorityCreateInfoEXT; + + + +#define VK_EXT_external_memory_host 1 +#define VK_EXT_EXTERNAL_MEMORY_HOST_SPEC_VERSION 1 +#define VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME "VK_EXT_external_memory_host" +typedef struct VkImportMemoryHostPointerInfoEXT { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlagBits handleType; + void* pHostPointer; +} VkImportMemoryHostPointerInfoEXT; + +typedef struct VkMemoryHostPointerPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t memoryTypeBits; +} VkMemoryHostPointerPropertiesEXT; + +typedef struct VkPhysicalDeviceExternalMemoryHostPropertiesEXT { + VkStructureType sType; + void* pNext; + VkDeviceSize minImportedHostPointerAlignment; +} VkPhysicalDeviceExternalMemoryHostPropertiesEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryHostPointerPropertiesEXT)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, const void* pHostPointer, VkMemoryHostPointerPropertiesEXT* pMemoryHostPointerProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryHostPointerPropertiesEXT( + VkDevice device, + VkExternalMemoryHandleTypeFlagBits handleType, + const void* pHostPointer, + VkMemoryHostPointerPropertiesEXT* pMemoryHostPointerProperties); +#endif + + +#define VK_AMD_buffer_marker 1 +#define VK_AMD_BUFFER_MARKER_SPEC_VERSION 1 +#define VK_AMD_BUFFER_MARKER_EXTENSION_NAME "VK_AMD_buffer_marker" +typedef void (VKAPI_PTR *PFN_vkCmdWriteBufferMarkerAMD)(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkBuffer dstBuffer, VkDeviceSize dstOffset, uint32_t marker); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdWriteBufferMarkerAMD( + VkCommandBuffer commandBuffer, + VkPipelineStageFlagBits pipelineStage, + VkBuffer dstBuffer, + VkDeviceSize dstOffset, + uint32_t marker); +#endif + + +#define VK_AMD_pipeline_compiler_control 1 +#define VK_AMD_PIPELINE_COMPILER_CONTROL_SPEC_VERSION 1 +#define VK_AMD_PIPELINE_COMPILER_CONTROL_EXTENSION_NAME "VK_AMD_pipeline_compiler_control" + +typedef enum VkPipelineCompilerControlFlagBitsAMD { + VK_PIPELINE_COMPILER_CONTROL_FLAG_BITS_MAX_ENUM_AMD = 0x7FFFFFFF +} VkPipelineCompilerControlFlagBitsAMD; +typedef VkFlags VkPipelineCompilerControlFlagsAMD; +typedef struct VkPipelineCompilerControlCreateInfoAMD { + VkStructureType sType; + const void* pNext; + VkPipelineCompilerControlFlagsAMD compilerControlFlags; +} VkPipelineCompilerControlCreateInfoAMD; + + + +#define VK_EXT_calibrated_timestamps 1 +#define VK_EXT_CALIBRATED_TIMESTAMPS_SPEC_VERSION 2 +#define VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME "VK_EXT_calibrated_timestamps" + +typedef enum VkTimeDomainEXT { + VK_TIME_DOMAIN_DEVICE_EXT = 0, + VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT = 1, + VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT = 2, + VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT = 3, + VK_TIME_DOMAIN_MAX_ENUM_EXT = 0x7FFFFFFF +} VkTimeDomainEXT; +typedef struct VkCalibratedTimestampInfoEXT { + VkStructureType sType; + const void* pNext; + VkTimeDomainEXT timeDomain; +} VkCalibratedTimestampInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT)(VkPhysicalDevice physicalDevice, uint32_t* pTimeDomainCount, VkTimeDomainEXT* pTimeDomains); +typedef VkResult (VKAPI_PTR *PFN_vkGetCalibratedTimestampsEXT)(VkDevice device, uint32_t timestampCount, const VkCalibratedTimestampInfoEXT* pTimestampInfos, uint64_t* pTimestamps, uint64_t* pMaxDeviation); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceCalibrateableTimeDomainsEXT( + VkPhysicalDevice physicalDevice, + uint32_t* pTimeDomainCount, + VkTimeDomainEXT* pTimeDomains); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetCalibratedTimestampsEXT( + VkDevice device, + uint32_t timestampCount, + const VkCalibratedTimestampInfoEXT* pTimestampInfos, + uint64_t* pTimestamps, + uint64_t* pMaxDeviation); +#endif + + +#define VK_AMD_shader_core_properties 1 +#define VK_AMD_SHADER_CORE_PROPERTIES_SPEC_VERSION 2 +#define VK_AMD_SHADER_CORE_PROPERTIES_EXTENSION_NAME "VK_AMD_shader_core_properties" +typedef struct VkPhysicalDeviceShaderCorePropertiesAMD { + VkStructureType sType; + void* pNext; + uint32_t shaderEngineCount; + uint32_t shaderArraysPerEngineCount; + uint32_t computeUnitsPerShaderArray; + uint32_t simdPerComputeUnit; + uint32_t wavefrontsPerSimd; + uint32_t wavefrontSize; + uint32_t sgprsPerSimd; + uint32_t minSgprAllocation; + uint32_t maxSgprAllocation; + uint32_t sgprAllocationGranularity; + uint32_t vgprsPerSimd; + uint32_t minVgprAllocation; + uint32_t maxVgprAllocation; + uint32_t vgprAllocationGranularity; +} VkPhysicalDeviceShaderCorePropertiesAMD; + + + +#define VK_AMD_memory_overallocation_behavior 1 +#define VK_AMD_MEMORY_OVERALLOCATION_BEHAVIOR_SPEC_VERSION 1 +#define VK_AMD_MEMORY_OVERALLOCATION_BEHAVIOR_EXTENSION_NAME "VK_AMD_memory_overallocation_behavior" + +typedef enum VkMemoryOverallocationBehaviorAMD { + VK_MEMORY_OVERALLOCATION_BEHAVIOR_DEFAULT_AMD = 0, + VK_MEMORY_OVERALLOCATION_BEHAVIOR_ALLOWED_AMD = 1, + VK_MEMORY_OVERALLOCATION_BEHAVIOR_DISALLOWED_AMD = 2, + VK_MEMORY_OVERALLOCATION_BEHAVIOR_MAX_ENUM_AMD = 0x7FFFFFFF +} VkMemoryOverallocationBehaviorAMD; +typedef struct VkDeviceMemoryOverallocationCreateInfoAMD { + VkStructureType sType; + const void* pNext; + VkMemoryOverallocationBehaviorAMD overallocationBehavior; +} VkDeviceMemoryOverallocationCreateInfoAMD; + + + +#define VK_EXT_vertex_attribute_divisor 1 +#define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_SPEC_VERSION 3 +#define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME "VK_EXT_vertex_attribute_divisor" +typedef struct VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t maxVertexAttribDivisor; +} VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT; + +typedef struct VkVertexInputBindingDivisorDescriptionEXT { + uint32_t binding; + uint32_t divisor; +} VkVertexInputBindingDivisorDescriptionEXT; + +typedef struct VkPipelineVertexInputDivisorStateCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t vertexBindingDivisorCount; + const VkVertexInputBindingDivisorDescriptionEXT* pVertexBindingDivisors; +} VkPipelineVertexInputDivisorStateCreateInfoEXT; + +typedef struct VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 vertexAttributeInstanceRateDivisor; + VkBool32 vertexAttributeInstanceRateZeroDivisor; +} VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT; + + + +#define VK_EXT_pipeline_creation_feedback 1 +#define VK_EXT_PIPELINE_CREATION_FEEDBACK_SPEC_VERSION 1 +#define VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME "VK_EXT_pipeline_creation_feedback" +typedef VkPipelineCreationFeedbackFlagBits VkPipelineCreationFeedbackFlagBitsEXT; + +typedef VkPipelineCreationFeedbackFlags VkPipelineCreationFeedbackFlagsEXT; + +typedef VkPipelineCreationFeedbackCreateInfo VkPipelineCreationFeedbackCreateInfoEXT; + +typedef VkPipelineCreationFeedback VkPipelineCreationFeedbackEXT; + + + +#define VK_NV_shader_subgroup_partitioned 1 +#define VK_NV_SHADER_SUBGROUP_PARTITIONED_SPEC_VERSION 1 +#define VK_NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME "VK_NV_shader_subgroup_partitioned" + + +#define VK_NV_compute_shader_derivatives 1 +#define VK_NV_COMPUTE_SHADER_DERIVATIVES_SPEC_VERSION 1 +#define VK_NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME "VK_NV_compute_shader_derivatives" +typedef struct VkPhysicalDeviceComputeShaderDerivativesFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 computeDerivativeGroupQuads; + VkBool32 computeDerivativeGroupLinear; +} VkPhysicalDeviceComputeShaderDerivativesFeaturesNV; + + + +#define VK_NV_mesh_shader 1 +#define VK_NV_MESH_SHADER_SPEC_VERSION 1 +#define VK_NV_MESH_SHADER_EXTENSION_NAME "VK_NV_mesh_shader" +typedef struct VkPhysicalDeviceMeshShaderFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 taskShader; + VkBool32 meshShader; +} VkPhysicalDeviceMeshShaderFeaturesNV; + +typedef struct VkPhysicalDeviceMeshShaderPropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t maxDrawMeshTasksCount; + uint32_t maxTaskWorkGroupInvocations; + uint32_t maxTaskWorkGroupSize[3]; + uint32_t maxTaskTotalMemorySize; + uint32_t maxTaskOutputCount; + uint32_t maxMeshWorkGroupInvocations; + uint32_t maxMeshWorkGroupSize[3]; + uint32_t maxMeshTotalMemorySize; + uint32_t maxMeshOutputVertices; + uint32_t maxMeshOutputPrimitives; + uint32_t maxMeshMultiviewViewCount; + uint32_t meshOutputPerVertexGranularity; + uint32_t meshOutputPerPrimitiveGranularity; +} VkPhysicalDeviceMeshShaderPropertiesNV; + +typedef struct VkDrawMeshTasksIndirectCommandNV { + uint32_t taskCount; + uint32_t firstTask; +} VkDrawMeshTasksIndirectCommandNV; + +typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksNV)(VkCommandBuffer commandBuffer, uint32_t taskCount, uint32_t firstTask); +typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksIndirectNV)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksIndirectCountNV)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksNV( + VkCommandBuffer commandBuffer, + uint32_t taskCount, + uint32_t firstTask); + +VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksIndirectNV( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + uint32_t drawCount, + uint32_t stride); + +VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksIndirectCountNV( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkBuffer countBuffer, + VkDeviceSize countBufferOffset, + uint32_t maxDrawCount, + uint32_t stride); +#endif + + +#define VK_NV_fragment_shader_barycentric 1 +#define VK_NV_FRAGMENT_SHADER_BARYCENTRIC_SPEC_VERSION 1 +#define VK_NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME "VK_NV_fragment_shader_barycentric" +typedef VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV; + + + +#define VK_NV_shader_image_footprint 1 +#define VK_NV_SHADER_IMAGE_FOOTPRINT_SPEC_VERSION 2 +#define VK_NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME "VK_NV_shader_image_footprint" +typedef struct VkPhysicalDeviceShaderImageFootprintFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 imageFootprint; +} VkPhysicalDeviceShaderImageFootprintFeaturesNV; + + + +#define VK_NV_scissor_exclusive 1 +#define VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION 1 +#define VK_NV_SCISSOR_EXCLUSIVE_EXTENSION_NAME "VK_NV_scissor_exclusive" +typedef struct VkPipelineViewportExclusiveScissorStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + uint32_t exclusiveScissorCount; + const VkRect2D* pExclusiveScissors; +} VkPipelineViewportExclusiveScissorStateCreateInfoNV; + +typedef struct VkPhysicalDeviceExclusiveScissorFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 exclusiveScissor; +} VkPhysicalDeviceExclusiveScissorFeaturesNV; + +typedef void (VKAPI_PTR *PFN_vkCmdSetExclusiveScissorNV)(VkCommandBuffer commandBuffer, uint32_t firstExclusiveScissor, uint32_t exclusiveScissorCount, const VkRect2D* pExclusiveScissors); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetExclusiveScissorNV( + VkCommandBuffer commandBuffer, + uint32_t firstExclusiveScissor, + uint32_t exclusiveScissorCount, + const VkRect2D* pExclusiveScissors); +#endif + + +#define VK_NV_device_diagnostic_checkpoints 1 +#define VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_SPEC_VERSION 2 +#define VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME "VK_NV_device_diagnostic_checkpoints" +typedef struct VkQueueFamilyCheckpointPropertiesNV { + VkStructureType sType; + void* pNext; + VkPipelineStageFlags checkpointExecutionStageMask; +} VkQueueFamilyCheckpointPropertiesNV; + +typedef struct VkCheckpointDataNV { + VkStructureType sType; + void* pNext; + VkPipelineStageFlagBits stage; + void* pCheckpointMarker; +} VkCheckpointDataNV; + +typedef void (VKAPI_PTR *PFN_vkCmdSetCheckpointNV)(VkCommandBuffer commandBuffer, const void* pCheckpointMarker); +typedef void (VKAPI_PTR *PFN_vkGetQueueCheckpointDataNV)(VkQueue queue, uint32_t* pCheckpointDataCount, VkCheckpointDataNV* pCheckpointData); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetCheckpointNV( + VkCommandBuffer commandBuffer, + const void* pCheckpointMarker); + +VKAPI_ATTR void VKAPI_CALL vkGetQueueCheckpointDataNV( + VkQueue queue, + uint32_t* pCheckpointDataCount, + VkCheckpointDataNV* pCheckpointData); +#endif + + +#define VK_INTEL_shader_integer_functions2 1 +#define VK_INTEL_SHADER_INTEGER_FUNCTIONS_2_SPEC_VERSION 1 +#define VK_INTEL_SHADER_INTEGER_FUNCTIONS_2_EXTENSION_NAME "VK_INTEL_shader_integer_functions2" +typedef struct VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL { + VkStructureType sType; + void* pNext; + VkBool32 shaderIntegerFunctions2; +} VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL; + + + +#define VK_INTEL_performance_query 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPerformanceConfigurationINTEL) +#define VK_INTEL_PERFORMANCE_QUERY_SPEC_VERSION 2 +#define VK_INTEL_PERFORMANCE_QUERY_EXTENSION_NAME "VK_INTEL_performance_query" + +typedef enum VkPerformanceConfigurationTypeINTEL { + VK_PERFORMANCE_CONFIGURATION_TYPE_COMMAND_QUEUE_METRICS_DISCOVERY_ACTIVATED_INTEL = 0, + VK_PERFORMANCE_CONFIGURATION_TYPE_MAX_ENUM_INTEL = 0x7FFFFFFF +} VkPerformanceConfigurationTypeINTEL; + +typedef enum VkQueryPoolSamplingModeINTEL { + VK_QUERY_POOL_SAMPLING_MODE_MANUAL_INTEL = 0, + VK_QUERY_POOL_SAMPLING_MODE_MAX_ENUM_INTEL = 0x7FFFFFFF +} VkQueryPoolSamplingModeINTEL; + +typedef enum VkPerformanceOverrideTypeINTEL { + VK_PERFORMANCE_OVERRIDE_TYPE_NULL_HARDWARE_INTEL = 0, + VK_PERFORMANCE_OVERRIDE_TYPE_FLUSH_GPU_CACHES_INTEL = 1, + VK_PERFORMANCE_OVERRIDE_TYPE_MAX_ENUM_INTEL = 0x7FFFFFFF +} VkPerformanceOverrideTypeINTEL; + +typedef enum VkPerformanceParameterTypeINTEL { + VK_PERFORMANCE_PARAMETER_TYPE_HW_COUNTERS_SUPPORTED_INTEL = 0, + VK_PERFORMANCE_PARAMETER_TYPE_STREAM_MARKER_VALID_BITS_INTEL = 1, + VK_PERFORMANCE_PARAMETER_TYPE_MAX_ENUM_INTEL = 0x7FFFFFFF +} VkPerformanceParameterTypeINTEL; + +typedef enum VkPerformanceValueTypeINTEL { + VK_PERFORMANCE_VALUE_TYPE_UINT32_INTEL = 0, + VK_PERFORMANCE_VALUE_TYPE_UINT64_INTEL = 1, + VK_PERFORMANCE_VALUE_TYPE_FLOAT_INTEL = 2, + VK_PERFORMANCE_VALUE_TYPE_BOOL_INTEL = 3, + VK_PERFORMANCE_VALUE_TYPE_STRING_INTEL = 4, + VK_PERFORMANCE_VALUE_TYPE_MAX_ENUM_INTEL = 0x7FFFFFFF +} VkPerformanceValueTypeINTEL; +typedef union VkPerformanceValueDataINTEL { + uint32_t value32; + uint64_t value64; + float valueFloat; + VkBool32 valueBool; + const char* valueString; +} VkPerformanceValueDataINTEL; + +typedef struct VkPerformanceValueINTEL { + VkPerformanceValueTypeINTEL type; + VkPerformanceValueDataINTEL data; +} VkPerformanceValueINTEL; + +typedef struct VkInitializePerformanceApiInfoINTEL { + VkStructureType sType; + const void* pNext; + void* pUserData; +} VkInitializePerformanceApiInfoINTEL; + +typedef struct VkQueryPoolPerformanceQueryCreateInfoINTEL { + VkStructureType sType; + const void* pNext; + VkQueryPoolSamplingModeINTEL performanceCountersSampling; +} VkQueryPoolPerformanceQueryCreateInfoINTEL; + +typedef VkQueryPoolPerformanceQueryCreateInfoINTEL VkQueryPoolCreateInfoINTEL; + +typedef struct VkPerformanceMarkerInfoINTEL { + VkStructureType sType; + const void* pNext; + uint64_t marker; +} VkPerformanceMarkerInfoINTEL; + +typedef struct VkPerformanceStreamMarkerInfoINTEL { + VkStructureType sType; + const void* pNext; + uint32_t marker; +} VkPerformanceStreamMarkerInfoINTEL; + +typedef struct VkPerformanceOverrideInfoINTEL { + VkStructureType sType; + const void* pNext; + VkPerformanceOverrideTypeINTEL type; + VkBool32 enable; + uint64_t parameter; +} VkPerformanceOverrideInfoINTEL; + +typedef struct VkPerformanceConfigurationAcquireInfoINTEL { + VkStructureType sType; + const void* pNext; + VkPerformanceConfigurationTypeINTEL type; +} VkPerformanceConfigurationAcquireInfoINTEL; + +typedef VkResult (VKAPI_PTR *PFN_vkInitializePerformanceApiINTEL)(VkDevice device, const VkInitializePerformanceApiInfoINTEL* pInitializeInfo); +typedef void (VKAPI_PTR *PFN_vkUninitializePerformanceApiINTEL)(VkDevice device); +typedef VkResult (VKAPI_PTR *PFN_vkCmdSetPerformanceMarkerINTEL)(VkCommandBuffer commandBuffer, const VkPerformanceMarkerInfoINTEL* pMarkerInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCmdSetPerformanceStreamMarkerINTEL)(VkCommandBuffer commandBuffer, const VkPerformanceStreamMarkerInfoINTEL* pMarkerInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCmdSetPerformanceOverrideINTEL)(VkCommandBuffer commandBuffer, const VkPerformanceOverrideInfoINTEL* pOverrideInfo); +typedef VkResult (VKAPI_PTR *PFN_vkAcquirePerformanceConfigurationINTEL)(VkDevice device, const VkPerformanceConfigurationAcquireInfoINTEL* pAcquireInfo, VkPerformanceConfigurationINTEL* pConfiguration); +typedef VkResult (VKAPI_PTR *PFN_vkReleasePerformanceConfigurationINTEL)(VkDevice device, VkPerformanceConfigurationINTEL configuration); +typedef VkResult (VKAPI_PTR *PFN_vkQueueSetPerformanceConfigurationINTEL)(VkQueue queue, VkPerformanceConfigurationINTEL configuration); +typedef VkResult (VKAPI_PTR *PFN_vkGetPerformanceParameterINTEL)(VkDevice device, VkPerformanceParameterTypeINTEL parameter, VkPerformanceValueINTEL* pValue); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkInitializePerformanceApiINTEL( + VkDevice device, + const VkInitializePerformanceApiInfoINTEL* pInitializeInfo); + +VKAPI_ATTR void VKAPI_CALL vkUninitializePerformanceApiINTEL( + VkDevice device); + +VKAPI_ATTR VkResult VKAPI_CALL vkCmdSetPerformanceMarkerINTEL( + VkCommandBuffer commandBuffer, + const VkPerformanceMarkerInfoINTEL* pMarkerInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkCmdSetPerformanceStreamMarkerINTEL( + VkCommandBuffer commandBuffer, + const VkPerformanceStreamMarkerInfoINTEL* pMarkerInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkCmdSetPerformanceOverrideINTEL( + VkCommandBuffer commandBuffer, + const VkPerformanceOverrideInfoINTEL* pOverrideInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkAcquirePerformanceConfigurationINTEL( + VkDevice device, + const VkPerformanceConfigurationAcquireInfoINTEL* pAcquireInfo, + VkPerformanceConfigurationINTEL* pConfiguration); + +VKAPI_ATTR VkResult VKAPI_CALL vkReleasePerformanceConfigurationINTEL( + VkDevice device, + VkPerformanceConfigurationINTEL configuration); + +VKAPI_ATTR VkResult VKAPI_CALL vkQueueSetPerformanceConfigurationINTEL( + VkQueue queue, + VkPerformanceConfigurationINTEL configuration); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPerformanceParameterINTEL( + VkDevice device, + VkPerformanceParameterTypeINTEL parameter, + VkPerformanceValueINTEL* pValue); +#endif + + +#define VK_EXT_pci_bus_info 1 +#define VK_EXT_PCI_BUS_INFO_SPEC_VERSION 2 +#define VK_EXT_PCI_BUS_INFO_EXTENSION_NAME "VK_EXT_pci_bus_info" +typedef struct VkPhysicalDevicePCIBusInfoPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t pciDomain; + uint32_t pciBus; + uint32_t pciDevice; + uint32_t pciFunction; +} VkPhysicalDevicePCIBusInfoPropertiesEXT; + + + +#define VK_AMD_display_native_hdr 1 +#define VK_AMD_DISPLAY_NATIVE_HDR_SPEC_VERSION 1 +#define VK_AMD_DISPLAY_NATIVE_HDR_EXTENSION_NAME "VK_AMD_display_native_hdr" +typedef struct VkDisplayNativeHdrSurfaceCapabilitiesAMD { + VkStructureType sType; + void* pNext; + VkBool32 localDimmingSupport; +} VkDisplayNativeHdrSurfaceCapabilitiesAMD; + +typedef struct VkSwapchainDisplayNativeHdrCreateInfoAMD { + VkStructureType sType; + const void* pNext; + VkBool32 localDimmingEnable; +} VkSwapchainDisplayNativeHdrCreateInfoAMD; + +typedef void (VKAPI_PTR *PFN_vkSetLocalDimmingAMD)(VkDevice device, VkSwapchainKHR swapChain, VkBool32 localDimmingEnable); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkSetLocalDimmingAMD( + VkDevice device, + VkSwapchainKHR swapChain, + VkBool32 localDimmingEnable); +#endif + + +#define VK_EXT_fragment_density_map 1 +#define VK_EXT_FRAGMENT_DENSITY_MAP_SPEC_VERSION 2 +#define VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME "VK_EXT_fragment_density_map" +typedef struct VkPhysicalDeviceFragmentDensityMapFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 fragmentDensityMap; + VkBool32 fragmentDensityMapDynamic; + VkBool32 fragmentDensityMapNonSubsampledImages; +} VkPhysicalDeviceFragmentDensityMapFeaturesEXT; + +typedef struct VkPhysicalDeviceFragmentDensityMapPropertiesEXT { + VkStructureType sType; + void* pNext; + VkExtent2D minFragmentDensityTexelSize; + VkExtent2D maxFragmentDensityTexelSize; + VkBool32 fragmentDensityInvocations; +} VkPhysicalDeviceFragmentDensityMapPropertiesEXT; + +typedef struct VkRenderPassFragmentDensityMapCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkAttachmentReference fragmentDensityMapAttachment; +} VkRenderPassFragmentDensityMapCreateInfoEXT; + + + +#define VK_EXT_scalar_block_layout 1 +#define VK_EXT_SCALAR_BLOCK_LAYOUT_SPEC_VERSION 1 +#define VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME "VK_EXT_scalar_block_layout" +typedef VkPhysicalDeviceScalarBlockLayoutFeatures VkPhysicalDeviceScalarBlockLayoutFeaturesEXT; + + + +#define VK_GOOGLE_hlsl_functionality1 1 +#define VK_GOOGLE_HLSL_FUNCTIONALITY_1_SPEC_VERSION 1 +#define VK_GOOGLE_HLSL_FUNCTIONALITY_1_EXTENSION_NAME "VK_GOOGLE_hlsl_functionality1" +#define VK_GOOGLE_HLSL_FUNCTIONALITY1_SPEC_VERSION VK_GOOGLE_HLSL_FUNCTIONALITY_1_SPEC_VERSION +#define VK_GOOGLE_HLSL_FUNCTIONALITY1_EXTENSION_NAME VK_GOOGLE_HLSL_FUNCTIONALITY_1_EXTENSION_NAME + + +#define VK_GOOGLE_decorate_string 1 +#define VK_GOOGLE_DECORATE_STRING_SPEC_VERSION 1 +#define VK_GOOGLE_DECORATE_STRING_EXTENSION_NAME "VK_GOOGLE_decorate_string" + + +#define VK_EXT_subgroup_size_control 1 +#define VK_EXT_SUBGROUP_SIZE_CONTROL_SPEC_VERSION 2 +#define VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME "VK_EXT_subgroup_size_control" +typedef VkPhysicalDeviceSubgroupSizeControlFeatures VkPhysicalDeviceSubgroupSizeControlFeaturesEXT; + +typedef VkPhysicalDeviceSubgroupSizeControlProperties VkPhysicalDeviceSubgroupSizeControlPropertiesEXT; + +typedef VkPipelineShaderStageRequiredSubgroupSizeCreateInfo VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT; + + + +#define VK_AMD_shader_core_properties2 1 +#define VK_AMD_SHADER_CORE_PROPERTIES_2_SPEC_VERSION 1 +#define VK_AMD_SHADER_CORE_PROPERTIES_2_EXTENSION_NAME "VK_AMD_shader_core_properties2" + +typedef enum VkShaderCorePropertiesFlagBitsAMD { + VK_SHADER_CORE_PROPERTIES_FLAG_BITS_MAX_ENUM_AMD = 0x7FFFFFFF +} VkShaderCorePropertiesFlagBitsAMD; +typedef VkFlags VkShaderCorePropertiesFlagsAMD; +typedef struct VkPhysicalDeviceShaderCoreProperties2AMD { + VkStructureType sType; + void* pNext; + VkShaderCorePropertiesFlagsAMD shaderCoreFeatures; + uint32_t activeComputeUnitCount; +} VkPhysicalDeviceShaderCoreProperties2AMD; + + + +#define VK_AMD_device_coherent_memory 1 +#define VK_AMD_DEVICE_COHERENT_MEMORY_SPEC_VERSION 1 +#define VK_AMD_DEVICE_COHERENT_MEMORY_EXTENSION_NAME "VK_AMD_device_coherent_memory" +typedef struct VkPhysicalDeviceCoherentMemoryFeaturesAMD { + VkStructureType sType; + void* pNext; + VkBool32 deviceCoherentMemory; +} VkPhysicalDeviceCoherentMemoryFeaturesAMD; + + + +#define VK_EXT_shader_image_atomic_int64 1 +#define VK_EXT_SHADER_IMAGE_ATOMIC_INT64_SPEC_VERSION 1 +#define VK_EXT_SHADER_IMAGE_ATOMIC_INT64_EXTENSION_NAME "VK_EXT_shader_image_atomic_int64" +typedef struct VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shaderImageInt64Atomics; + VkBool32 sparseImageInt64Atomics; +} VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT; + + + +#define VK_EXT_memory_budget 1 +#define VK_EXT_MEMORY_BUDGET_SPEC_VERSION 1 +#define VK_EXT_MEMORY_BUDGET_EXTENSION_NAME "VK_EXT_memory_budget" +typedef struct VkPhysicalDeviceMemoryBudgetPropertiesEXT { + VkStructureType sType; + void* pNext; + VkDeviceSize heapBudget[VK_MAX_MEMORY_HEAPS]; + VkDeviceSize heapUsage[VK_MAX_MEMORY_HEAPS]; +} VkPhysicalDeviceMemoryBudgetPropertiesEXT; + + + +#define VK_EXT_memory_priority 1 +#define VK_EXT_MEMORY_PRIORITY_SPEC_VERSION 1 +#define VK_EXT_MEMORY_PRIORITY_EXTENSION_NAME "VK_EXT_memory_priority" +typedef struct VkPhysicalDeviceMemoryPriorityFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 memoryPriority; +} VkPhysicalDeviceMemoryPriorityFeaturesEXT; + +typedef struct VkMemoryPriorityAllocateInfoEXT { + VkStructureType sType; + const void* pNext; + float priority; +} VkMemoryPriorityAllocateInfoEXT; + + + +#define VK_NV_dedicated_allocation_image_aliasing 1 +#define VK_NV_DEDICATED_ALLOCATION_IMAGE_ALIASING_SPEC_VERSION 1 +#define VK_NV_DEDICATED_ALLOCATION_IMAGE_ALIASING_EXTENSION_NAME "VK_NV_dedicated_allocation_image_aliasing" +typedef struct VkPhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 dedicatedAllocationImageAliasing; +} VkPhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV; + + + +#define VK_EXT_buffer_device_address 1 +#define VK_EXT_BUFFER_DEVICE_ADDRESS_SPEC_VERSION 2 +#define VK_EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME "VK_EXT_buffer_device_address" +typedef struct VkPhysicalDeviceBufferDeviceAddressFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 bufferDeviceAddress; + VkBool32 bufferDeviceAddressCaptureReplay; + VkBool32 bufferDeviceAddressMultiDevice; +} VkPhysicalDeviceBufferDeviceAddressFeaturesEXT; + +typedef VkPhysicalDeviceBufferDeviceAddressFeaturesEXT VkPhysicalDeviceBufferAddressFeaturesEXT; + +typedef VkBufferDeviceAddressInfo VkBufferDeviceAddressInfoEXT; + +typedef struct VkBufferDeviceAddressCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkDeviceAddress deviceAddress; +} VkBufferDeviceAddressCreateInfoEXT; + +typedef VkDeviceAddress (VKAPI_PTR *PFN_vkGetBufferDeviceAddressEXT)(VkDevice device, const VkBufferDeviceAddressInfo* pInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetBufferDeviceAddressEXT( + VkDevice device, + const VkBufferDeviceAddressInfo* pInfo); +#endif + + +#define VK_EXT_tooling_info 1 +#define VK_EXT_TOOLING_INFO_SPEC_VERSION 1 +#define VK_EXT_TOOLING_INFO_EXTENSION_NAME "VK_EXT_tooling_info" +typedef VkToolPurposeFlagBits VkToolPurposeFlagBitsEXT; + +typedef VkToolPurposeFlags VkToolPurposeFlagsEXT; + +typedef VkPhysicalDeviceToolProperties VkPhysicalDeviceToolPropertiesEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceToolPropertiesEXT)(VkPhysicalDevice physicalDevice, uint32_t* pToolCount, VkPhysicalDeviceToolProperties* pToolProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceToolPropertiesEXT( + VkPhysicalDevice physicalDevice, + uint32_t* pToolCount, + VkPhysicalDeviceToolProperties* pToolProperties); +#endif + + +#define VK_EXT_separate_stencil_usage 1 +#define VK_EXT_SEPARATE_STENCIL_USAGE_SPEC_VERSION 1 +#define VK_EXT_SEPARATE_STENCIL_USAGE_EXTENSION_NAME "VK_EXT_separate_stencil_usage" +typedef VkImageStencilUsageCreateInfo VkImageStencilUsageCreateInfoEXT; + + + +#define VK_EXT_validation_features 1 +#define VK_EXT_VALIDATION_FEATURES_SPEC_VERSION 5 +#define VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME "VK_EXT_validation_features" + +typedef enum VkValidationFeatureEnableEXT { + VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT = 0, + VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT = 1, + VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT = 2, + VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT = 3, + VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT = 4, + VK_VALIDATION_FEATURE_ENABLE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkValidationFeatureEnableEXT; + +typedef enum VkValidationFeatureDisableEXT { + VK_VALIDATION_FEATURE_DISABLE_ALL_EXT = 0, + VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT = 1, + VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT = 2, + VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT = 3, + VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT = 4, + VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT = 5, + VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT = 6, + VK_VALIDATION_FEATURE_DISABLE_SHADER_VALIDATION_CACHE_EXT = 7, + VK_VALIDATION_FEATURE_DISABLE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkValidationFeatureDisableEXT; +typedef struct VkValidationFeaturesEXT { + VkStructureType sType; + const void* pNext; + uint32_t enabledValidationFeatureCount; + const VkValidationFeatureEnableEXT* pEnabledValidationFeatures; + uint32_t disabledValidationFeatureCount; + const VkValidationFeatureDisableEXT* pDisabledValidationFeatures; +} VkValidationFeaturesEXT; + + + +#define VK_NV_cooperative_matrix 1 +#define VK_NV_COOPERATIVE_MATRIX_SPEC_VERSION 1 +#define VK_NV_COOPERATIVE_MATRIX_EXTENSION_NAME "VK_NV_cooperative_matrix" + +typedef enum VkComponentTypeNV { + VK_COMPONENT_TYPE_FLOAT16_NV = 0, + VK_COMPONENT_TYPE_FLOAT32_NV = 1, + VK_COMPONENT_TYPE_FLOAT64_NV = 2, + VK_COMPONENT_TYPE_SINT8_NV = 3, + VK_COMPONENT_TYPE_SINT16_NV = 4, + VK_COMPONENT_TYPE_SINT32_NV = 5, + VK_COMPONENT_TYPE_SINT64_NV = 6, + VK_COMPONENT_TYPE_UINT8_NV = 7, + VK_COMPONENT_TYPE_UINT16_NV = 8, + VK_COMPONENT_TYPE_UINT32_NV = 9, + VK_COMPONENT_TYPE_UINT64_NV = 10, + VK_COMPONENT_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkComponentTypeNV; + +typedef enum VkScopeNV { + VK_SCOPE_DEVICE_NV = 1, + VK_SCOPE_WORKGROUP_NV = 2, + VK_SCOPE_SUBGROUP_NV = 3, + VK_SCOPE_QUEUE_FAMILY_NV = 5, + VK_SCOPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkScopeNV; +typedef struct VkCooperativeMatrixPropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t MSize; + uint32_t NSize; + uint32_t KSize; + VkComponentTypeNV AType; + VkComponentTypeNV BType; + VkComponentTypeNV CType; + VkComponentTypeNV DType; + VkScopeNV scope; +} VkCooperativeMatrixPropertiesNV; + +typedef struct VkPhysicalDeviceCooperativeMatrixFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 cooperativeMatrix; + VkBool32 cooperativeMatrixRobustBufferAccess; +} VkPhysicalDeviceCooperativeMatrixFeaturesNV; + +typedef struct VkPhysicalDeviceCooperativeMatrixPropertiesNV { + VkStructureType sType; + void* pNext; + VkShaderStageFlags cooperativeMatrixSupportedStages; +} VkPhysicalDeviceCooperativeMatrixPropertiesNV; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesNV)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkCooperativeMatrixPropertiesNV* pProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceCooperativeMatrixPropertiesNV( + VkPhysicalDevice physicalDevice, + uint32_t* pPropertyCount, + VkCooperativeMatrixPropertiesNV* pProperties); +#endif + + +#define VK_NV_coverage_reduction_mode 1 +#define VK_NV_COVERAGE_REDUCTION_MODE_SPEC_VERSION 1 +#define VK_NV_COVERAGE_REDUCTION_MODE_EXTENSION_NAME "VK_NV_coverage_reduction_mode" + +typedef enum VkCoverageReductionModeNV { + VK_COVERAGE_REDUCTION_MODE_MERGE_NV = 0, + VK_COVERAGE_REDUCTION_MODE_TRUNCATE_NV = 1, + VK_COVERAGE_REDUCTION_MODE_MAX_ENUM_NV = 0x7FFFFFFF +} VkCoverageReductionModeNV; +typedef VkFlags VkPipelineCoverageReductionStateCreateFlagsNV; +typedef struct VkPhysicalDeviceCoverageReductionModeFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 coverageReductionMode; +} VkPhysicalDeviceCoverageReductionModeFeaturesNV; + +typedef struct VkPipelineCoverageReductionStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkPipelineCoverageReductionStateCreateFlagsNV flags; + VkCoverageReductionModeNV coverageReductionMode; +} VkPipelineCoverageReductionStateCreateInfoNV; + +typedef struct VkFramebufferMixedSamplesCombinationNV { + VkStructureType sType; + void* pNext; + VkCoverageReductionModeNV coverageReductionMode; + VkSampleCountFlagBits rasterizationSamples; + VkSampleCountFlags depthStencilSamples; + VkSampleCountFlags colorSamples; +} VkFramebufferMixedSamplesCombinationNV; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV)(VkPhysicalDevice physicalDevice, uint32_t* pCombinationCount, VkFramebufferMixedSamplesCombinationNV* pCombinations); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV( + VkPhysicalDevice physicalDevice, + uint32_t* pCombinationCount, + VkFramebufferMixedSamplesCombinationNV* pCombinations); +#endif + + +#define VK_EXT_fragment_shader_interlock 1 +#define VK_EXT_FRAGMENT_SHADER_INTERLOCK_SPEC_VERSION 1 +#define VK_EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME "VK_EXT_fragment_shader_interlock" +typedef struct VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 fragmentShaderSampleInterlock; + VkBool32 fragmentShaderPixelInterlock; + VkBool32 fragmentShaderShadingRateInterlock; +} VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT; + + + +#define VK_EXT_ycbcr_image_arrays 1 +#define VK_EXT_YCBCR_IMAGE_ARRAYS_SPEC_VERSION 1 +#define VK_EXT_YCBCR_IMAGE_ARRAYS_EXTENSION_NAME "VK_EXT_ycbcr_image_arrays" +typedef struct VkPhysicalDeviceYcbcrImageArraysFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 ycbcrImageArrays; +} VkPhysicalDeviceYcbcrImageArraysFeaturesEXT; + + + +#define VK_EXT_provoking_vertex 1 +#define VK_EXT_PROVOKING_VERTEX_SPEC_VERSION 1 +#define VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME "VK_EXT_provoking_vertex" + +typedef enum VkProvokingVertexModeEXT { + VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT = 0, + VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT = 1, + VK_PROVOKING_VERTEX_MODE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkProvokingVertexModeEXT; +typedef struct VkPhysicalDeviceProvokingVertexFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 provokingVertexLast; + VkBool32 transformFeedbackPreservesProvokingVertex; +} VkPhysicalDeviceProvokingVertexFeaturesEXT; + +typedef struct VkPhysicalDeviceProvokingVertexPropertiesEXT { + VkStructureType sType; + void* pNext; + VkBool32 provokingVertexModePerPipeline; + VkBool32 transformFeedbackPreservesTriangleFanProvokingVertex; +} VkPhysicalDeviceProvokingVertexPropertiesEXT; + +typedef struct VkPipelineRasterizationProvokingVertexStateCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkProvokingVertexModeEXT provokingVertexMode; +} VkPipelineRasterizationProvokingVertexStateCreateInfoEXT; + + + +#define VK_EXT_headless_surface 1 +#define VK_EXT_HEADLESS_SURFACE_SPEC_VERSION 1 +#define VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME "VK_EXT_headless_surface" +typedef VkFlags VkHeadlessSurfaceCreateFlagsEXT; +typedef struct VkHeadlessSurfaceCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkHeadlessSurfaceCreateFlagsEXT flags; +} VkHeadlessSurfaceCreateInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateHeadlessSurfaceEXT)(VkInstance instance, const VkHeadlessSurfaceCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateHeadlessSurfaceEXT( + VkInstance instance, + const VkHeadlessSurfaceCreateInfoEXT* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); +#endif + + +#define VK_EXT_line_rasterization 1 +#define VK_EXT_LINE_RASTERIZATION_SPEC_VERSION 1 +#define VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME "VK_EXT_line_rasterization" + +typedef enum VkLineRasterizationModeEXT { + VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT = 0, + VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT = 1, + VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT = 2, + VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT = 3, + VK_LINE_RASTERIZATION_MODE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkLineRasterizationModeEXT; +typedef struct VkPhysicalDeviceLineRasterizationFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 rectangularLines; + VkBool32 bresenhamLines; + VkBool32 smoothLines; + VkBool32 stippledRectangularLines; + VkBool32 stippledBresenhamLines; + VkBool32 stippledSmoothLines; +} VkPhysicalDeviceLineRasterizationFeaturesEXT; + +typedef struct VkPhysicalDeviceLineRasterizationPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t lineSubPixelPrecisionBits; +} VkPhysicalDeviceLineRasterizationPropertiesEXT; + +typedef struct VkPipelineRasterizationLineStateCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkLineRasterizationModeEXT lineRasterizationMode; + VkBool32 stippledLineEnable; + uint32_t lineStippleFactor; + uint16_t lineStipplePattern; +} VkPipelineRasterizationLineStateCreateInfoEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdSetLineStippleEXT)(VkCommandBuffer commandBuffer, uint32_t lineStippleFactor, uint16_t lineStipplePattern); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetLineStippleEXT( + VkCommandBuffer commandBuffer, + uint32_t lineStippleFactor, + uint16_t lineStipplePattern); +#endif + + +#define VK_EXT_shader_atomic_float 1 +#define VK_EXT_SHADER_ATOMIC_FLOAT_SPEC_VERSION 1 +#define VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME "VK_EXT_shader_atomic_float" +typedef struct VkPhysicalDeviceShaderAtomicFloatFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shaderBufferFloat32Atomics; + VkBool32 shaderBufferFloat32AtomicAdd; + VkBool32 shaderBufferFloat64Atomics; + VkBool32 shaderBufferFloat64AtomicAdd; + VkBool32 shaderSharedFloat32Atomics; + VkBool32 shaderSharedFloat32AtomicAdd; + VkBool32 shaderSharedFloat64Atomics; + VkBool32 shaderSharedFloat64AtomicAdd; + VkBool32 shaderImageFloat32Atomics; + VkBool32 shaderImageFloat32AtomicAdd; + VkBool32 sparseImageFloat32Atomics; + VkBool32 sparseImageFloat32AtomicAdd; +} VkPhysicalDeviceShaderAtomicFloatFeaturesEXT; + + + +#define VK_EXT_host_query_reset 1 +#define VK_EXT_HOST_QUERY_RESET_SPEC_VERSION 1 +#define VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME "VK_EXT_host_query_reset" +typedef VkPhysicalDeviceHostQueryResetFeatures VkPhysicalDeviceHostQueryResetFeaturesEXT; + +typedef void (VKAPI_PTR *PFN_vkResetQueryPoolEXT)(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkResetQueryPoolEXT( + VkDevice device, + VkQueryPool queryPool, + uint32_t firstQuery, + uint32_t queryCount); +#endif + + +#define VK_EXT_index_type_uint8 1 +#define VK_EXT_INDEX_TYPE_UINT8_SPEC_VERSION 1 +#define VK_EXT_INDEX_TYPE_UINT8_EXTENSION_NAME "VK_EXT_index_type_uint8" +typedef struct VkPhysicalDeviceIndexTypeUint8FeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 indexTypeUint8; +} VkPhysicalDeviceIndexTypeUint8FeaturesEXT; + + + +#define VK_EXT_extended_dynamic_state 1 +#define VK_EXT_EXTENDED_DYNAMIC_STATE_SPEC_VERSION 1 +#define VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME "VK_EXT_extended_dynamic_state" +typedef struct VkPhysicalDeviceExtendedDynamicStateFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 extendedDynamicState; +} VkPhysicalDeviceExtendedDynamicStateFeaturesEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdSetCullModeEXT)(VkCommandBuffer commandBuffer, VkCullModeFlags cullMode); +typedef void (VKAPI_PTR *PFN_vkCmdSetFrontFaceEXT)(VkCommandBuffer commandBuffer, VkFrontFace frontFace); +typedef void (VKAPI_PTR *PFN_vkCmdSetPrimitiveTopologyEXT)(VkCommandBuffer commandBuffer, VkPrimitiveTopology primitiveTopology); +typedef void (VKAPI_PTR *PFN_vkCmdSetViewportWithCountEXT)(VkCommandBuffer commandBuffer, uint32_t viewportCount, const VkViewport* pViewports); +typedef void (VKAPI_PTR *PFN_vkCmdSetScissorWithCountEXT)(VkCommandBuffer commandBuffer, uint32_t scissorCount, const VkRect2D* pScissors); +typedef void (VKAPI_PTR *PFN_vkCmdBindVertexBuffers2EXT)(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets, const VkDeviceSize* pSizes, const VkDeviceSize* pStrides); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthTestEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 depthTestEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthWriteEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 depthWriteEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthCompareOpEXT)(VkCommandBuffer commandBuffer, VkCompareOp depthCompareOp); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBoundsTestEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 depthBoundsTestEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetStencilTestEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 stencilTestEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetStencilOpEXT)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, VkStencilOp failOp, VkStencilOp passOp, VkStencilOp depthFailOp, VkCompareOp compareOp); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetCullModeEXT( + VkCommandBuffer commandBuffer, + VkCullModeFlags cullMode); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetFrontFaceEXT( + VkCommandBuffer commandBuffer, + VkFrontFace frontFace); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetPrimitiveTopologyEXT( + VkCommandBuffer commandBuffer, + VkPrimitiveTopology primitiveTopology); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportWithCountEXT( + VkCommandBuffer commandBuffer, + uint32_t viewportCount, + const VkViewport* pViewports); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetScissorWithCountEXT( + VkCommandBuffer commandBuffer, + uint32_t scissorCount, + const VkRect2D* pScissors); + +VKAPI_ATTR void VKAPI_CALL vkCmdBindVertexBuffers2EXT( + VkCommandBuffer commandBuffer, + uint32_t firstBinding, + uint32_t bindingCount, + const VkBuffer* pBuffers, + const VkDeviceSize* pOffsets, + const VkDeviceSize* pSizes, + const VkDeviceSize* pStrides); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthTestEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 depthTestEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthWriteEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 depthWriteEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthCompareOpEXT( + VkCommandBuffer commandBuffer, + VkCompareOp depthCompareOp); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBoundsTestEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 depthBoundsTestEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilTestEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 stencilTestEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilOpEXT( + VkCommandBuffer commandBuffer, + VkStencilFaceFlags faceMask, + VkStencilOp failOp, + VkStencilOp passOp, + VkStencilOp depthFailOp, + VkCompareOp compareOp); +#endif + + +#define VK_EXT_shader_atomic_float2 1 +#define VK_EXT_SHADER_ATOMIC_FLOAT_2_SPEC_VERSION 1 +#define VK_EXT_SHADER_ATOMIC_FLOAT_2_EXTENSION_NAME "VK_EXT_shader_atomic_float2" +typedef struct VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shaderBufferFloat16Atomics; + VkBool32 shaderBufferFloat16AtomicAdd; + VkBool32 shaderBufferFloat16AtomicMinMax; + VkBool32 shaderBufferFloat32AtomicMinMax; + VkBool32 shaderBufferFloat64AtomicMinMax; + VkBool32 shaderSharedFloat16Atomics; + VkBool32 shaderSharedFloat16AtomicAdd; + VkBool32 shaderSharedFloat16AtomicMinMax; + VkBool32 shaderSharedFloat32AtomicMinMax; + VkBool32 shaderSharedFloat64AtomicMinMax; + VkBool32 shaderImageFloat32AtomicMinMax; + VkBool32 sparseImageFloat32AtomicMinMax; +} VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT; + + + +#define VK_EXT_shader_demote_to_helper_invocation 1 +#define VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_SPEC_VERSION 1 +#define VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME "VK_EXT_shader_demote_to_helper_invocation" +typedef VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT; + + + +#define VK_NV_device_generated_commands 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkIndirectCommandsLayoutNV) +#define VK_NV_DEVICE_GENERATED_COMMANDS_SPEC_VERSION 3 +#define VK_NV_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME "VK_NV_device_generated_commands" + +typedef enum VkIndirectCommandsTokenTypeNV { + VK_INDIRECT_COMMANDS_TOKEN_TYPE_SHADER_GROUP_NV = 0, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_STATE_FLAGS_NV = 1, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NV = 2, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NV = 3, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV = 4, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NV = 5, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NV = 6, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_TASKS_NV = 7, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkIndirectCommandsTokenTypeNV; + +typedef enum VkIndirectStateFlagBitsNV { + VK_INDIRECT_STATE_FLAG_FRONTFACE_BIT_NV = 0x00000001, + VK_INDIRECT_STATE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkIndirectStateFlagBitsNV; +typedef VkFlags VkIndirectStateFlagsNV; + +typedef enum VkIndirectCommandsLayoutUsageFlagBitsNV { + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EXPLICIT_PREPROCESS_BIT_NV = 0x00000001, + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NV = 0x00000002, + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NV = 0x00000004, + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkIndirectCommandsLayoutUsageFlagBitsNV; +typedef VkFlags VkIndirectCommandsLayoutUsageFlagsNV; +typedef struct VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t maxGraphicsShaderGroupCount; + uint32_t maxIndirectSequenceCount; + uint32_t maxIndirectCommandsTokenCount; + uint32_t maxIndirectCommandsStreamCount; + uint32_t maxIndirectCommandsTokenOffset; + uint32_t maxIndirectCommandsStreamStride; + uint32_t minSequencesCountBufferOffsetAlignment; + uint32_t minSequencesIndexBufferOffsetAlignment; + uint32_t minIndirectCommandsBufferOffsetAlignment; +} VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV; + +typedef struct VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 deviceGeneratedCommands; +} VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV; + +typedef struct VkGraphicsShaderGroupCreateInfoNV { + VkStructureType sType; + const void* pNext; + uint32_t stageCount; + const VkPipelineShaderStageCreateInfo* pStages; + const VkPipelineVertexInputStateCreateInfo* pVertexInputState; + const VkPipelineTessellationStateCreateInfo* pTessellationState; +} VkGraphicsShaderGroupCreateInfoNV; + +typedef struct VkGraphicsPipelineShaderGroupsCreateInfoNV { + VkStructureType sType; + const void* pNext; + uint32_t groupCount; + const VkGraphicsShaderGroupCreateInfoNV* pGroups; + uint32_t pipelineCount; + const VkPipeline* pPipelines; +} VkGraphicsPipelineShaderGroupsCreateInfoNV; + +typedef struct VkBindShaderGroupIndirectCommandNV { + uint32_t groupIndex; +} VkBindShaderGroupIndirectCommandNV; + +typedef struct VkBindIndexBufferIndirectCommandNV { + VkDeviceAddress bufferAddress; + uint32_t size; + VkIndexType indexType; +} VkBindIndexBufferIndirectCommandNV; + +typedef struct VkBindVertexBufferIndirectCommandNV { + VkDeviceAddress bufferAddress; + uint32_t size; + uint32_t stride; +} VkBindVertexBufferIndirectCommandNV; + +typedef struct VkSetStateFlagsIndirectCommandNV { + uint32_t data; +} VkSetStateFlagsIndirectCommandNV; + +typedef struct VkIndirectCommandsStreamNV { + VkBuffer buffer; + VkDeviceSize offset; +} VkIndirectCommandsStreamNV; + +typedef struct VkIndirectCommandsLayoutTokenNV { + VkStructureType sType; + const void* pNext; + VkIndirectCommandsTokenTypeNV tokenType; + uint32_t stream; + uint32_t offset; + uint32_t vertexBindingUnit; + VkBool32 vertexDynamicStride; + VkPipelineLayout pushconstantPipelineLayout; + VkShaderStageFlags pushconstantShaderStageFlags; + uint32_t pushconstantOffset; + uint32_t pushconstantSize; + VkIndirectStateFlagsNV indirectStateFlags; + uint32_t indexTypeCount; + const VkIndexType* pIndexTypes; + const uint32_t* pIndexTypeValues; +} VkIndirectCommandsLayoutTokenNV; + +typedef struct VkIndirectCommandsLayoutCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkIndirectCommandsLayoutUsageFlagsNV flags; + VkPipelineBindPoint pipelineBindPoint; + uint32_t tokenCount; + const VkIndirectCommandsLayoutTokenNV* pTokens; + uint32_t streamCount; + const uint32_t* pStreamStrides; +} VkIndirectCommandsLayoutCreateInfoNV; + +typedef struct VkGeneratedCommandsInfoNV { + VkStructureType sType; + const void* pNext; + VkPipelineBindPoint pipelineBindPoint; + VkPipeline pipeline; + VkIndirectCommandsLayoutNV indirectCommandsLayout; + uint32_t streamCount; + const VkIndirectCommandsStreamNV* pStreams; + uint32_t sequencesCount; + VkBuffer preprocessBuffer; + VkDeviceSize preprocessOffset; + VkDeviceSize preprocessSize; + VkBuffer sequencesCountBuffer; + VkDeviceSize sequencesCountOffset; + VkBuffer sequencesIndexBuffer; + VkDeviceSize sequencesIndexOffset; +} VkGeneratedCommandsInfoNV; + +typedef struct VkGeneratedCommandsMemoryRequirementsInfoNV { + VkStructureType sType; + const void* pNext; + VkPipelineBindPoint pipelineBindPoint; + VkPipeline pipeline; + VkIndirectCommandsLayoutNV indirectCommandsLayout; + uint32_t maxSequencesCount; +} VkGeneratedCommandsMemoryRequirementsInfoNV; + +typedef void (VKAPI_PTR *PFN_vkGetGeneratedCommandsMemoryRequirementsNV)(VkDevice device, const VkGeneratedCommandsMemoryRequirementsInfoNV* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkCmdPreprocessGeneratedCommandsNV)(VkCommandBuffer commandBuffer, const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo); +typedef void (VKAPI_PTR *PFN_vkCmdExecuteGeneratedCommandsNV)(VkCommandBuffer commandBuffer, VkBool32 isPreprocessed, const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo); +typedef void (VKAPI_PTR *PFN_vkCmdBindPipelineShaderGroupNV)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline, uint32_t groupIndex); +typedef VkResult (VKAPI_PTR *PFN_vkCreateIndirectCommandsLayoutNV)(VkDevice device, const VkIndirectCommandsLayoutCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkIndirectCommandsLayoutNV* pIndirectCommandsLayout); +typedef void (VKAPI_PTR *PFN_vkDestroyIndirectCommandsLayoutNV)(VkDevice device, VkIndirectCommandsLayoutNV indirectCommandsLayout, const VkAllocationCallbacks* pAllocator); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetGeneratedCommandsMemoryRequirementsNV( + VkDevice device, + const VkGeneratedCommandsMemoryRequirementsInfoNV* pInfo, + VkMemoryRequirements2* pMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkCmdPreprocessGeneratedCommandsNV( + VkCommandBuffer commandBuffer, + const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdExecuteGeneratedCommandsNV( + VkCommandBuffer commandBuffer, + VkBool32 isPreprocessed, + const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdBindPipelineShaderGroupNV( + VkCommandBuffer commandBuffer, + VkPipelineBindPoint pipelineBindPoint, + VkPipeline pipeline, + uint32_t groupIndex); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateIndirectCommandsLayoutNV( + VkDevice device, + const VkIndirectCommandsLayoutCreateInfoNV* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkIndirectCommandsLayoutNV* pIndirectCommandsLayout); + +VKAPI_ATTR void VKAPI_CALL vkDestroyIndirectCommandsLayoutNV( + VkDevice device, + VkIndirectCommandsLayoutNV indirectCommandsLayout, + const VkAllocationCallbacks* pAllocator); +#endif + + +#define VK_NV_inherited_viewport_scissor 1 +#define VK_NV_INHERITED_VIEWPORT_SCISSOR_SPEC_VERSION 1 +#define VK_NV_INHERITED_VIEWPORT_SCISSOR_EXTENSION_NAME "VK_NV_inherited_viewport_scissor" +typedef struct VkPhysicalDeviceInheritedViewportScissorFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 inheritedViewportScissor2D; +} VkPhysicalDeviceInheritedViewportScissorFeaturesNV; + +typedef struct VkCommandBufferInheritanceViewportScissorInfoNV { + VkStructureType sType; + const void* pNext; + VkBool32 viewportScissor2D; + uint32_t viewportDepthCount; + const VkViewport* pViewportDepths; +} VkCommandBufferInheritanceViewportScissorInfoNV; + + + +#define VK_EXT_texel_buffer_alignment 1 +#define VK_EXT_TEXEL_BUFFER_ALIGNMENT_SPEC_VERSION 1 +#define VK_EXT_TEXEL_BUFFER_ALIGNMENT_EXTENSION_NAME "VK_EXT_texel_buffer_alignment" +typedef struct VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 texelBufferAlignment; +} VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT; + +typedef VkPhysicalDeviceTexelBufferAlignmentProperties VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT; + + + +#define VK_QCOM_render_pass_transform 1 +#define VK_QCOM_RENDER_PASS_TRANSFORM_SPEC_VERSION 2 +#define VK_QCOM_RENDER_PASS_TRANSFORM_EXTENSION_NAME "VK_QCOM_render_pass_transform" +typedef struct VkRenderPassTransformBeginInfoQCOM { + VkStructureType sType; + void* pNext; + VkSurfaceTransformFlagBitsKHR transform; +} VkRenderPassTransformBeginInfoQCOM; + +typedef struct VkCommandBufferInheritanceRenderPassTransformInfoQCOM { + VkStructureType sType; + void* pNext; + VkSurfaceTransformFlagBitsKHR transform; + VkRect2D renderArea; +} VkCommandBufferInheritanceRenderPassTransformInfoQCOM; + + + +#define VK_EXT_device_memory_report 1 +#define VK_EXT_DEVICE_MEMORY_REPORT_SPEC_VERSION 2 +#define VK_EXT_DEVICE_MEMORY_REPORT_EXTENSION_NAME "VK_EXT_device_memory_report" + +typedef enum VkDeviceMemoryReportEventTypeEXT { + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATE_EXT = 0, + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_FREE_EXT = 1, + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_IMPORT_EXT = 2, + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_UNIMPORT_EXT = 3, + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATION_FAILED_EXT = 4, + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDeviceMemoryReportEventTypeEXT; +typedef VkFlags VkDeviceMemoryReportFlagsEXT; +typedef struct VkPhysicalDeviceDeviceMemoryReportFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 deviceMemoryReport; +} VkPhysicalDeviceDeviceMemoryReportFeaturesEXT; + +typedef struct VkDeviceMemoryReportCallbackDataEXT { + VkStructureType sType; + void* pNext; + VkDeviceMemoryReportFlagsEXT flags; + VkDeviceMemoryReportEventTypeEXT type; + uint64_t memoryObjectId; + VkDeviceSize size; + VkObjectType objectType; + uint64_t objectHandle; + uint32_t heapIndex; +} VkDeviceMemoryReportCallbackDataEXT; + +typedef void (VKAPI_PTR *PFN_vkDeviceMemoryReportCallbackEXT)( + const VkDeviceMemoryReportCallbackDataEXT* pCallbackData, + void* pUserData); + +typedef struct VkDeviceDeviceMemoryReportCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkDeviceMemoryReportFlagsEXT flags; + PFN_vkDeviceMemoryReportCallbackEXT pfnUserCallback; + void* pUserData; +} VkDeviceDeviceMemoryReportCreateInfoEXT; + + + +#define VK_EXT_acquire_drm_display 1 +#define VK_EXT_ACQUIRE_DRM_DISPLAY_SPEC_VERSION 1 +#define VK_EXT_ACQUIRE_DRM_DISPLAY_EXTENSION_NAME "VK_EXT_acquire_drm_display" +typedef VkResult (VKAPI_PTR *PFN_vkAcquireDrmDisplayEXT)(VkPhysicalDevice physicalDevice, int32_t drmFd, VkDisplayKHR display); +typedef VkResult (VKAPI_PTR *PFN_vkGetDrmDisplayEXT)(VkPhysicalDevice physicalDevice, int32_t drmFd, uint32_t connectorId, VkDisplayKHR* display); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkAcquireDrmDisplayEXT( + VkPhysicalDevice physicalDevice, + int32_t drmFd, + VkDisplayKHR display); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetDrmDisplayEXT( + VkPhysicalDevice physicalDevice, + int32_t drmFd, + uint32_t connectorId, + VkDisplayKHR* display); +#endif + + +#define VK_EXT_robustness2 1 +#define VK_EXT_ROBUSTNESS_2_SPEC_VERSION 1 +#define VK_EXT_ROBUSTNESS_2_EXTENSION_NAME "VK_EXT_robustness2" +typedef struct VkPhysicalDeviceRobustness2FeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 robustBufferAccess2; + VkBool32 robustImageAccess2; + VkBool32 nullDescriptor; +} VkPhysicalDeviceRobustness2FeaturesEXT; + +typedef struct VkPhysicalDeviceRobustness2PropertiesEXT { + VkStructureType sType; + void* pNext; + VkDeviceSize robustStorageBufferAccessSizeAlignment; + VkDeviceSize robustUniformBufferAccessSizeAlignment; +} VkPhysicalDeviceRobustness2PropertiesEXT; + + + +#define VK_EXT_custom_border_color 1 +#define VK_EXT_CUSTOM_BORDER_COLOR_SPEC_VERSION 12 +#define VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME "VK_EXT_custom_border_color" +typedef struct VkSamplerCustomBorderColorCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkClearColorValue customBorderColor; + VkFormat format; +} VkSamplerCustomBorderColorCreateInfoEXT; + +typedef struct VkPhysicalDeviceCustomBorderColorPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t maxCustomBorderColorSamplers; +} VkPhysicalDeviceCustomBorderColorPropertiesEXT; + +typedef struct VkPhysicalDeviceCustomBorderColorFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 customBorderColors; + VkBool32 customBorderColorWithoutFormat; +} VkPhysicalDeviceCustomBorderColorFeaturesEXT; + + + +#define VK_GOOGLE_user_type 1 +#define VK_GOOGLE_USER_TYPE_SPEC_VERSION 1 +#define VK_GOOGLE_USER_TYPE_EXTENSION_NAME "VK_GOOGLE_user_type" + + +#define VK_EXT_private_data 1 +typedef VkPrivateDataSlot VkPrivateDataSlotEXT; + +#define VK_EXT_PRIVATE_DATA_SPEC_VERSION 1 +#define VK_EXT_PRIVATE_DATA_EXTENSION_NAME "VK_EXT_private_data" +typedef VkPrivateDataSlotCreateFlags VkPrivateDataSlotCreateFlagsEXT; + +typedef VkPhysicalDevicePrivateDataFeatures VkPhysicalDevicePrivateDataFeaturesEXT; + +typedef VkDevicePrivateDataCreateInfo VkDevicePrivateDataCreateInfoEXT; + +typedef VkPrivateDataSlotCreateInfo VkPrivateDataSlotCreateInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkCreatePrivateDataSlotEXT)(VkDevice device, const VkPrivateDataSlotCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPrivateDataSlot* pPrivateDataSlot); +typedef void (VKAPI_PTR *PFN_vkDestroyPrivateDataSlotEXT)(VkDevice device, VkPrivateDataSlot privateDataSlot, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkSetPrivateDataEXT)(VkDevice device, VkObjectType objectType, uint64_t objectHandle, VkPrivateDataSlot privateDataSlot, uint64_t data); +typedef void (VKAPI_PTR *PFN_vkGetPrivateDataEXT)(VkDevice device, VkObjectType objectType, uint64_t objectHandle, VkPrivateDataSlot privateDataSlot, uint64_t* pData); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreatePrivateDataSlotEXT( + VkDevice device, + const VkPrivateDataSlotCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkPrivateDataSlot* pPrivateDataSlot); + +VKAPI_ATTR void VKAPI_CALL vkDestroyPrivateDataSlotEXT( + VkDevice device, + VkPrivateDataSlot privateDataSlot, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkSetPrivateDataEXT( + VkDevice device, + VkObjectType objectType, + uint64_t objectHandle, + VkPrivateDataSlot privateDataSlot, + uint64_t data); + +VKAPI_ATTR void VKAPI_CALL vkGetPrivateDataEXT( + VkDevice device, + VkObjectType objectType, + uint64_t objectHandle, + VkPrivateDataSlot privateDataSlot, + uint64_t* pData); +#endif + + +#define VK_EXT_pipeline_creation_cache_control 1 +#define VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_SPEC_VERSION 3 +#define VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_EXTENSION_NAME "VK_EXT_pipeline_creation_cache_control" +typedef VkPhysicalDevicePipelineCreationCacheControlFeatures VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT; + + + +#define VK_NV_device_diagnostics_config 1 +#define VK_NV_DEVICE_DIAGNOSTICS_CONFIG_SPEC_VERSION 2 +#define VK_NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME "VK_NV_device_diagnostics_config" + +typedef enum VkDeviceDiagnosticsConfigFlagBitsNV { + VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_DEBUG_INFO_BIT_NV = 0x00000001, + VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_RESOURCE_TRACKING_BIT_NV = 0x00000002, + VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_AUTOMATIC_CHECKPOINTS_BIT_NV = 0x00000004, + VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_ERROR_REPORTING_BIT_NV = 0x00000008, + VK_DEVICE_DIAGNOSTICS_CONFIG_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkDeviceDiagnosticsConfigFlagBitsNV; +typedef VkFlags VkDeviceDiagnosticsConfigFlagsNV; +typedef struct VkPhysicalDeviceDiagnosticsConfigFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 diagnosticsConfig; +} VkPhysicalDeviceDiagnosticsConfigFeaturesNV; + +typedef struct VkDeviceDiagnosticsConfigCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkDeviceDiagnosticsConfigFlagsNV flags; +} VkDeviceDiagnosticsConfigCreateInfoNV; + + + +#define VK_QCOM_render_pass_store_ops 1 +#define VK_QCOM_RENDER_PASS_STORE_OPS_SPEC_VERSION 2 +#define VK_QCOM_RENDER_PASS_STORE_OPS_EXTENSION_NAME "VK_QCOM_render_pass_store_ops" + + +#define VK_EXT_graphics_pipeline_library 1 +#define VK_EXT_GRAPHICS_PIPELINE_LIBRARY_SPEC_VERSION 1 +#define VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME "VK_EXT_graphics_pipeline_library" + +typedef enum VkGraphicsPipelineLibraryFlagBitsEXT { + VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT = 0x00000001, + VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT = 0x00000002, + VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT = 0x00000004, + VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT = 0x00000008, + VK_GRAPHICS_PIPELINE_LIBRARY_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkGraphicsPipelineLibraryFlagBitsEXT; +typedef VkFlags VkGraphicsPipelineLibraryFlagsEXT; +typedef struct VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 graphicsPipelineLibrary; +} VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT; + +typedef struct VkPhysicalDeviceGraphicsPipelineLibraryPropertiesEXT { + VkStructureType sType; + void* pNext; + VkBool32 graphicsPipelineLibraryFastLinking; + VkBool32 graphicsPipelineLibraryIndependentInterpolationDecoration; +} VkPhysicalDeviceGraphicsPipelineLibraryPropertiesEXT; + +typedef struct VkGraphicsPipelineLibraryCreateInfoEXT { + VkStructureType sType; + void* pNext; + VkGraphicsPipelineLibraryFlagsEXT flags; +} VkGraphicsPipelineLibraryCreateInfoEXT; + + + +#define VK_AMD_shader_early_and_late_fragment_tests 1 +#define VK_AMD_SHADER_EARLY_AND_LATE_FRAGMENT_TESTS_SPEC_VERSION 1 +#define VK_AMD_SHADER_EARLY_AND_LATE_FRAGMENT_TESTS_EXTENSION_NAME "VK_AMD_shader_early_and_late_fragment_tests" +typedef struct VkPhysicalDeviceShaderEarlyAndLateFragmentTestsFeaturesAMD { + VkStructureType sType; + void* pNext; + VkBool32 shaderEarlyAndLateFragmentTests; +} VkPhysicalDeviceShaderEarlyAndLateFragmentTestsFeaturesAMD; + + + +#define VK_NV_fragment_shading_rate_enums 1 +#define VK_NV_FRAGMENT_SHADING_RATE_ENUMS_SPEC_VERSION 1 +#define VK_NV_FRAGMENT_SHADING_RATE_ENUMS_EXTENSION_NAME "VK_NV_fragment_shading_rate_enums" + +typedef enum VkFragmentShadingRateTypeNV { + VK_FRAGMENT_SHADING_RATE_TYPE_FRAGMENT_SIZE_NV = 0, + VK_FRAGMENT_SHADING_RATE_TYPE_ENUMS_NV = 1, + VK_FRAGMENT_SHADING_RATE_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkFragmentShadingRateTypeNV; + +typedef enum VkFragmentShadingRateNV { + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_PIXEL_NV = 0, + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_1X2_PIXELS_NV = 1, + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X1_PIXELS_NV = 4, + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X2_PIXELS_NV = 5, + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X4_PIXELS_NV = 6, + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_4X2_PIXELS_NV = 9, + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_4X4_PIXELS_NV = 10, + VK_FRAGMENT_SHADING_RATE_2_INVOCATIONS_PER_PIXEL_NV = 11, + VK_FRAGMENT_SHADING_RATE_4_INVOCATIONS_PER_PIXEL_NV = 12, + VK_FRAGMENT_SHADING_RATE_8_INVOCATIONS_PER_PIXEL_NV = 13, + VK_FRAGMENT_SHADING_RATE_16_INVOCATIONS_PER_PIXEL_NV = 14, + VK_FRAGMENT_SHADING_RATE_NO_INVOCATIONS_NV = 15, + VK_FRAGMENT_SHADING_RATE_MAX_ENUM_NV = 0x7FFFFFFF +} VkFragmentShadingRateNV; +typedef struct VkPhysicalDeviceFragmentShadingRateEnumsFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 fragmentShadingRateEnums; + VkBool32 supersampleFragmentShadingRates; + VkBool32 noInvocationFragmentShadingRates; +} VkPhysicalDeviceFragmentShadingRateEnumsFeaturesNV; + +typedef struct VkPhysicalDeviceFragmentShadingRateEnumsPropertiesNV { + VkStructureType sType; + void* pNext; + VkSampleCountFlagBits maxFragmentShadingRateInvocationCount; +} VkPhysicalDeviceFragmentShadingRateEnumsPropertiesNV; + +typedef struct VkPipelineFragmentShadingRateEnumStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkFragmentShadingRateTypeNV shadingRateType; + VkFragmentShadingRateNV shadingRate; + VkFragmentShadingRateCombinerOpKHR combinerOps[2]; +} VkPipelineFragmentShadingRateEnumStateCreateInfoNV; + +typedef void (VKAPI_PTR *PFN_vkCmdSetFragmentShadingRateEnumNV)(VkCommandBuffer commandBuffer, VkFragmentShadingRateNV shadingRate, const VkFragmentShadingRateCombinerOpKHR combinerOps[2]); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetFragmentShadingRateEnumNV( + VkCommandBuffer commandBuffer, + VkFragmentShadingRateNV shadingRate, + const VkFragmentShadingRateCombinerOpKHR combinerOps[2]); +#endif + + +#define VK_NV_ray_tracing_motion_blur 1 +#define VK_NV_RAY_TRACING_MOTION_BLUR_SPEC_VERSION 1 +#define VK_NV_RAY_TRACING_MOTION_BLUR_EXTENSION_NAME "VK_NV_ray_tracing_motion_blur" + +typedef enum VkAccelerationStructureMotionInstanceTypeNV { + VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_STATIC_NV = 0, + VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_MATRIX_MOTION_NV = 1, + VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_SRT_MOTION_NV = 2, + VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkAccelerationStructureMotionInstanceTypeNV; +typedef VkFlags VkAccelerationStructureMotionInfoFlagsNV; +typedef VkFlags VkAccelerationStructureMotionInstanceFlagsNV; +typedef union VkDeviceOrHostAddressConstKHR { + VkDeviceAddress deviceAddress; + const void* hostAddress; +} VkDeviceOrHostAddressConstKHR; + +typedef struct VkAccelerationStructureGeometryMotionTrianglesDataNV { + VkStructureType sType; + const void* pNext; + VkDeviceOrHostAddressConstKHR vertexData; +} VkAccelerationStructureGeometryMotionTrianglesDataNV; + +typedef struct VkAccelerationStructureMotionInfoNV { + VkStructureType sType; + const void* pNext; + uint32_t maxInstances; + VkAccelerationStructureMotionInfoFlagsNV flags; +} VkAccelerationStructureMotionInfoNV; + +typedef struct VkAccelerationStructureMatrixMotionInstanceNV { + VkTransformMatrixKHR transformT0; + VkTransformMatrixKHR transformT1; + uint32_t instanceCustomIndex:24; + uint32_t mask:8; + uint32_t instanceShaderBindingTableRecordOffset:24; + VkGeometryInstanceFlagsKHR flags:8; + uint64_t accelerationStructureReference; +} VkAccelerationStructureMatrixMotionInstanceNV; + +typedef struct VkSRTDataNV { + float sx; + float a; + float b; + float pvx; + float sy; + float c; + float pvy; + float sz; + float pvz; + float qx; + float qy; + float qz; + float qw; + float tx; + float ty; + float tz; +} VkSRTDataNV; + +typedef struct VkAccelerationStructureSRTMotionInstanceNV { + VkSRTDataNV transformT0; + VkSRTDataNV transformT1; + uint32_t instanceCustomIndex:24; + uint32_t mask:8; + uint32_t instanceShaderBindingTableRecordOffset:24; + VkGeometryInstanceFlagsKHR flags:8; + uint64_t accelerationStructureReference; +} VkAccelerationStructureSRTMotionInstanceNV; + +typedef union VkAccelerationStructureMotionInstanceDataNV { + VkAccelerationStructureInstanceKHR staticInstance; + VkAccelerationStructureMatrixMotionInstanceNV matrixMotionInstance; + VkAccelerationStructureSRTMotionInstanceNV srtMotionInstance; +} VkAccelerationStructureMotionInstanceDataNV; + +typedef struct VkAccelerationStructureMotionInstanceNV { + VkAccelerationStructureMotionInstanceTypeNV type; + VkAccelerationStructureMotionInstanceFlagsNV flags; + VkAccelerationStructureMotionInstanceDataNV data; +} VkAccelerationStructureMotionInstanceNV; + +typedef struct VkPhysicalDeviceRayTracingMotionBlurFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 rayTracingMotionBlur; + VkBool32 rayTracingMotionBlurPipelineTraceRaysIndirect; +} VkPhysicalDeviceRayTracingMotionBlurFeaturesNV; + + + +#define VK_EXT_ycbcr_2plane_444_formats 1 +#define VK_EXT_YCBCR_2PLANE_444_FORMATS_SPEC_VERSION 1 +#define VK_EXT_YCBCR_2PLANE_444_FORMATS_EXTENSION_NAME "VK_EXT_ycbcr_2plane_444_formats" +typedef struct VkPhysicalDeviceYcbcr2Plane444FormatsFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 ycbcr2plane444Formats; +} VkPhysicalDeviceYcbcr2Plane444FormatsFeaturesEXT; + + + +#define VK_EXT_fragment_density_map2 1 +#define VK_EXT_FRAGMENT_DENSITY_MAP_2_SPEC_VERSION 1 +#define VK_EXT_FRAGMENT_DENSITY_MAP_2_EXTENSION_NAME "VK_EXT_fragment_density_map2" +typedef struct VkPhysicalDeviceFragmentDensityMap2FeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 fragmentDensityMapDeferred; +} VkPhysicalDeviceFragmentDensityMap2FeaturesEXT; + +typedef struct VkPhysicalDeviceFragmentDensityMap2PropertiesEXT { + VkStructureType sType; + void* pNext; + VkBool32 subsampledLoads; + VkBool32 subsampledCoarseReconstructionEarlyAccess; + uint32_t maxSubsampledArrayLayers; + uint32_t maxDescriptorSetSubsampledSamplers; +} VkPhysicalDeviceFragmentDensityMap2PropertiesEXT; + + + +#define VK_QCOM_rotated_copy_commands 1 +#define VK_QCOM_ROTATED_COPY_COMMANDS_SPEC_VERSION 1 +#define VK_QCOM_ROTATED_COPY_COMMANDS_EXTENSION_NAME "VK_QCOM_rotated_copy_commands" +typedef struct VkCopyCommandTransformInfoQCOM { + VkStructureType sType; + const void* pNext; + VkSurfaceTransformFlagBitsKHR transform; +} VkCopyCommandTransformInfoQCOM; + + + +#define VK_EXT_image_robustness 1 +#define VK_EXT_IMAGE_ROBUSTNESS_SPEC_VERSION 1 +#define VK_EXT_IMAGE_ROBUSTNESS_EXTENSION_NAME "VK_EXT_image_robustness" +typedef VkPhysicalDeviceImageRobustnessFeatures VkPhysicalDeviceImageRobustnessFeaturesEXT; + + + +#define VK_EXT_image_compression_control 1 +#define VK_EXT_IMAGE_COMPRESSION_CONTROL_SPEC_VERSION 1 +#define VK_EXT_IMAGE_COMPRESSION_CONTROL_EXTENSION_NAME "VK_EXT_image_compression_control" + +typedef enum VkImageCompressionFlagBitsEXT { + VK_IMAGE_COMPRESSION_DEFAULT_EXT = 0, + VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT = 0x00000001, + VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT = 0x00000002, + VK_IMAGE_COMPRESSION_DISABLED_EXT = 0x00000004, + VK_IMAGE_COMPRESSION_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkImageCompressionFlagBitsEXT; +typedef VkFlags VkImageCompressionFlagsEXT; + +typedef enum VkImageCompressionFixedRateFlagBitsEXT { + VK_IMAGE_COMPRESSION_FIXED_RATE_NONE_EXT = 0, + VK_IMAGE_COMPRESSION_FIXED_RATE_1BPC_BIT_EXT = 0x00000001, + VK_IMAGE_COMPRESSION_FIXED_RATE_2BPC_BIT_EXT = 0x00000002, + VK_IMAGE_COMPRESSION_FIXED_RATE_3BPC_BIT_EXT = 0x00000004, + VK_IMAGE_COMPRESSION_FIXED_RATE_4BPC_BIT_EXT = 0x00000008, + VK_IMAGE_COMPRESSION_FIXED_RATE_5BPC_BIT_EXT = 0x00000010, + VK_IMAGE_COMPRESSION_FIXED_RATE_6BPC_BIT_EXT = 0x00000020, + VK_IMAGE_COMPRESSION_FIXED_RATE_7BPC_BIT_EXT = 0x00000040, + VK_IMAGE_COMPRESSION_FIXED_RATE_8BPC_BIT_EXT = 0x00000080, + VK_IMAGE_COMPRESSION_FIXED_RATE_9BPC_BIT_EXT = 0x00000100, + VK_IMAGE_COMPRESSION_FIXED_RATE_10BPC_BIT_EXT = 0x00000200, + VK_IMAGE_COMPRESSION_FIXED_RATE_11BPC_BIT_EXT = 0x00000400, + VK_IMAGE_COMPRESSION_FIXED_RATE_12BPC_BIT_EXT = 0x00000800, + VK_IMAGE_COMPRESSION_FIXED_RATE_13BPC_BIT_EXT = 0x00001000, + VK_IMAGE_COMPRESSION_FIXED_RATE_14BPC_BIT_EXT = 0x00002000, + VK_IMAGE_COMPRESSION_FIXED_RATE_15BPC_BIT_EXT = 0x00004000, + VK_IMAGE_COMPRESSION_FIXED_RATE_16BPC_BIT_EXT = 0x00008000, + VK_IMAGE_COMPRESSION_FIXED_RATE_17BPC_BIT_EXT = 0x00010000, + VK_IMAGE_COMPRESSION_FIXED_RATE_18BPC_BIT_EXT = 0x00020000, + VK_IMAGE_COMPRESSION_FIXED_RATE_19BPC_BIT_EXT = 0x00040000, + VK_IMAGE_COMPRESSION_FIXED_RATE_20BPC_BIT_EXT = 0x00080000, + VK_IMAGE_COMPRESSION_FIXED_RATE_21BPC_BIT_EXT = 0x00100000, + VK_IMAGE_COMPRESSION_FIXED_RATE_22BPC_BIT_EXT = 0x00200000, + VK_IMAGE_COMPRESSION_FIXED_RATE_23BPC_BIT_EXT = 0x00400000, + VK_IMAGE_COMPRESSION_FIXED_RATE_24BPC_BIT_EXT = 0x00800000, + VK_IMAGE_COMPRESSION_FIXED_RATE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkImageCompressionFixedRateFlagBitsEXT; +typedef VkFlags VkImageCompressionFixedRateFlagsEXT; +typedef struct VkPhysicalDeviceImageCompressionControlFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 imageCompressionControl; +} VkPhysicalDeviceImageCompressionControlFeaturesEXT; + +typedef struct VkImageCompressionControlEXT { + VkStructureType sType; + const void* pNext; + VkImageCompressionFlagsEXT flags; + uint32_t compressionControlPlaneCount; + VkImageCompressionFixedRateFlagsEXT* pFixedRateFlags; +} VkImageCompressionControlEXT; + +typedef struct VkSubresourceLayout2EXT { + VkStructureType sType; + void* pNext; + VkSubresourceLayout subresourceLayout; +} VkSubresourceLayout2EXT; + +typedef struct VkImageSubresource2EXT { + VkStructureType sType; + void* pNext; + VkImageSubresource imageSubresource; +} VkImageSubresource2EXT; + +typedef struct VkImageCompressionPropertiesEXT { + VkStructureType sType; + void* pNext; + VkImageCompressionFlagsEXT imageCompressionFlags; + VkImageCompressionFixedRateFlagsEXT imageCompressionFixedRateFlags; +} VkImageCompressionPropertiesEXT; + +typedef void (VKAPI_PTR *PFN_vkGetImageSubresourceLayout2EXT)(VkDevice device, VkImage image, const VkImageSubresource2EXT* pSubresource, VkSubresourceLayout2EXT* pLayout); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetImageSubresourceLayout2EXT( + VkDevice device, + VkImage image, + const VkImageSubresource2EXT* pSubresource, + VkSubresourceLayout2EXT* pLayout); +#endif + + +#define VK_EXT_4444_formats 1 +#define VK_EXT_4444_FORMATS_SPEC_VERSION 1 +#define VK_EXT_4444_FORMATS_EXTENSION_NAME "VK_EXT_4444_formats" +typedef struct VkPhysicalDevice4444FormatsFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 formatA4R4G4B4; + VkBool32 formatA4B4G4R4; +} VkPhysicalDevice4444FormatsFeaturesEXT; + + + +#define VK_ARM_rasterization_order_attachment_access 1 +#define VK_ARM_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_SPEC_VERSION 1 +#define VK_ARM_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_EXTENSION_NAME "VK_ARM_rasterization_order_attachment_access" +typedef struct VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesARM { + VkStructureType sType; + void* pNext; + VkBool32 rasterizationOrderColorAttachmentAccess; + VkBool32 rasterizationOrderDepthAttachmentAccess; + VkBool32 rasterizationOrderStencilAttachmentAccess; +} VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesARM; + + + +#define VK_EXT_rgba10x6_formats 1 +#define VK_EXT_RGBA10X6_FORMATS_SPEC_VERSION 1 +#define VK_EXT_RGBA10X6_FORMATS_EXTENSION_NAME "VK_EXT_rgba10x6_formats" +typedef struct VkPhysicalDeviceRGBA10X6FormatsFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 formatRgba10x6WithoutYCbCrSampler; +} VkPhysicalDeviceRGBA10X6FormatsFeaturesEXT; + + + +#define VK_NV_acquire_winrt_display 1 +#define VK_NV_ACQUIRE_WINRT_DISPLAY_SPEC_VERSION 1 +#define VK_NV_ACQUIRE_WINRT_DISPLAY_EXTENSION_NAME "VK_NV_acquire_winrt_display" +typedef VkResult (VKAPI_PTR *PFN_vkAcquireWinrtDisplayNV)(VkPhysicalDevice physicalDevice, VkDisplayKHR display); +typedef VkResult (VKAPI_PTR *PFN_vkGetWinrtDisplayNV)(VkPhysicalDevice physicalDevice, uint32_t deviceRelativeId, VkDisplayKHR* pDisplay); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkAcquireWinrtDisplayNV( + VkPhysicalDevice physicalDevice, + VkDisplayKHR display); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetWinrtDisplayNV( + VkPhysicalDevice physicalDevice, + uint32_t deviceRelativeId, + VkDisplayKHR* pDisplay); +#endif + + +#define VK_VALVE_mutable_descriptor_type 1 +#define VK_VALVE_MUTABLE_DESCRIPTOR_TYPE_SPEC_VERSION 1 +#define VK_VALVE_MUTABLE_DESCRIPTOR_TYPE_EXTENSION_NAME "VK_VALVE_mutable_descriptor_type" +typedef struct VkPhysicalDeviceMutableDescriptorTypeFeaturesVALVE { + VkStructureType sType; + void* pNext; + VkBool32 mutableDescriptorType; +} VkPhysicalDeviceMutableDescriptorTypeFeaturesVALVE; + +typedef struct VkMutableDescriptorTypeListVALVE { + uint32_t descriptorTypeCount; + const VkDescriptorType* pDescriptorTypes; +} VkMutableDescriptorTypeListVALVE; + +typedef struct VkMutableDescriptorTypeCreateInfoVALVE { + VkStructureType sType; + const void* pNext; + uint32_t mutableDescriptorTypeListCount; + const VkMutableDescriptorTypeListVALVE* pMutableDescriptorTypeLists; +} VkMutableDescriptorTypeCreateInfoVALVE; + + + +#define VK_EXT_vertex_input_dynamic_state 1 +#define VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_SPEC_VERSION 2 +#define VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME "VK_EXT_vertex_input_dynamic_state" +typedef struct VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 vertexInputDynamicState; +} VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT; + +typedef struct VkVertexInputBindingDescription2EXT { + VkStructureType sType; + void* pNext; + uint32_t binding; + uint32_t stride; + VkVertexInputRate inputRate; + uint32_t divisor; +} VkVertexInputBindingDescription2EXT; + +typedef struct VkVertexInputAttributeDescription2EXT { + VkStructureType sType; + void* pNext; + uint32_t location; + uint32_t binding; + VkFormat format; + uint32_t offset; +} VkVertexInputAttributeDescription2EXT; + +typedef void (VKAPI_PTR *PFN_vkCmdSetVertexInputEXT)(VkCommandBuffer commandBuffer, uint32_t vertexBindingDescriptionCount, const VkVertexInputBindingDescription2EXT* pVertexBindingDescriptions, uint32_t vertexAttributeDescriptionCount, const VkVertexInputAttributeDescription2EXT* pVertexAttributeDescriptions); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetVertexInputEXT( + VkCommandBuffer commandBuffer, + uint32_t vertexBindingDescriptionCount, + const VkVertexInputBindingDescription2EXT* pVertexBindingDescriptions, + uint32_t vertexAttributeDescriptionCount, + const VkVertexInputAttributeDescription2EXT* pVertexAttributeDescriptions); +#endif + + +#define VK_EXT_physical_device_drm 1 +#define VK_EXT_PHYSICAL_DEVICE_DRM_SPEC_VERSION 1 +#define VK_EXT_PHYSICAL_DEVICE_DRM_EXTENSION_NAME "VK_EXT_physical_device_drm" +typedef struct VkPhysicalDeviceDrmPropertiesEXT { + VkStructureType sType; + void* pNext; + VkBool32 hasPrimary; + VkBool32 hasRender; + int64_t primaryMajor; + int64_t primaryMinor; + int64_t renderMajor; + int64_t renderMinor; +} VkPhysicalDeviceDrmPropertiesEXT; + + + +#define VK_EXT_depth_clip_control 1 +#define VK_EXT_DEPTH_CLIP_CONTROL_SPEC_VERSION 1 +#define VK_EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME "VK_EXT_depth_clip_control" +typedef struct VkPhysicalDeviceDepthClipControlFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 depthClipControl; +} VkPhysicalDeviceDepthClipControlFeaturesEXT; + +typedef struct VkPipelineViewportDepthClipControlCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkBool32 negativeOneToOne; +} VkPipelineViewportDepthClipControlCreateInfoEXT; + + + +#define VK_EXT_primitive_topology_list_restart 1 +#define VK_EXT_PRIMITIVE_TOPOLOGY_LIST_RESTART_SPEC_VERSION 1 +#define VK_EXT_PRIMITIVE_TOPOLOGY_LIST_RESTART_EXTENSION_NAME "VK_EXT_primitive_topology_list_restart" +typedef struct VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 primitiveTopologyListRestart; + VkBool32 primitiveTopologyPatchListRestart; +} VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT; + + + +#define VK_HUAWEI_subpass_shading 1 +#define VK_HUAWEI_SUBPASS_SHADING_SPEC_VERSION 2 +#define VK_HUAWEI_SUBPASS_SHADING_EXTENSION_NAME "VK_HUAWEI_subpass_shading" +typedef struct VkSubpassShadingPipelineCreateInfoHUAWEI { + VkStructureType sType; + void* pNext; + VkRenderPass renderPass; + uint32_t subpass; +} VkSubpassShadingPipelineCreateInfoHUAWEI; + +typedef struct VkPhysicalDeviceSubpassShadingFeaturesHUAWEI { + VkStructureType sType; + void* pNext; + VkBool32 subpassShading; +} VkPhysicalDeviceSubpassShadingFeaturesHUAWEI; + +typedef struct VkPhysicalDeviceSubpassShadingPropertiesHUAWEI { + VkStructureType sType; + void* pNext; + uint32_t maxSubpassShadingWorkgroupSizeAspectRatio; +} VkPhysicalDeviceSubpassShadingPropertiesHUAWEI; + +typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI)(VkDevice device, VkRenderPass renderpass, VkExtent2D* pMaxWorkgroupSize); +typedef void (VKAPI_PTR *PFN_vkCmdSubpassShadingHUAWEI)(VkCommandBuffer commandBuffer); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI( + VkDevice device, + VkRenderPass renderpass, + VkExtent2D* pMaxWorkgroupSize); + +VKAPI_ATTR void VKAPI_CALL vkCmdSubpassShadingHUAWEI( + VkCommandBuffer commandBuffer); +#endif + + +#define VK_HUAWEI_invocation_mask 1 +#define VK_HUAWEI_INVOCATION_MASK_SPEC_VERSION 1 +#define VK_HUAWEI_INVOCATION_MASK_EXTENSION_NAME "VK_HUAWEI_invocation_mask" +typedef struct VkPhysicalDeviceInvocationMaskFeaturesHUAWEI { + VkStructureType sType; + void* pNext; + VkBool32 invocationMask; +} VkPhysicalDeviceInvocationMaskFeaturesHUAWEI; + +typedef void (VKAPI_PTR *PFN_vkCmdBindInvocationMaskHUAWEI)(VkCommandBuffer commandBuffer, VkImageView imageView, VkImageLayout imageLayout); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBindInvocationMaskHUAWEI( + VkCommandBuffer commandBuffer, + VkImageView imageView, + VkImageLayout imageLayout); +#endif + + +#define VK_NV_external_memory_rdma 1 +typedef void* VkRemoteAddressNV; +#define VK_NV_EXTERNAL_MEMORY_RDMA_SPEC_VERSION 1 +#define VK_NV_EXTERNAL_MEMORY_RDMA_EXTENSION_NAME "VK_NV_external_memory_rdma" +typedef struct VkMemoryGetRemoteAddressInfoNV { + VkStructureType sType; + const void* pNext; + VkDeviceMemory memory; + VkExternalMemoryHandleTypeFlagBits handleType; +} VkMemoryGetRemoteAddressInfoNV; + +typedef struct VkPhysicalDeviceExternalMemoryRDMAFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 externalMemoryRDMA; +} VkPhysicalDeviceExternalMemoryRDMAFeaturesNV; + +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryRemoteAddressNV)(VkDevice device, const VkMemoryGetRemoteAddressInfoNV* pMemoryGetRemoteAddressInfo, VkRemoteAddressNV* pAddress); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryRemoteAddressNV( + VkDevice device, + const VkMemoryGetRemoteAddressInfoNV* pMemoryGetRemoteAddressInfo, + VkRemoteAddressNV* pAddress); +#endif + + +#define VK_EXT_pipeline_properties 1 +#define VK_EXT_PIPELINE_PROPERTIES_SPEC_VERSION 1 +#define VK_EXT_PIPELINE_PROPERTIES_EXTENSION_NAME "VK_EXT_pipeline_properties" +typedef VkPipelineInfoKHR VkPipelineInfoEXT; + +typedef struct VkPipelinePropertiesIdentifierEXT { + VkStructureType sType; + void* pNext; + uint8_t pipelineIdentifier[VK_UUID_SIZE]; +} VkPipelinePropertiesIdentifierEXT; + +typedef struct VkPhysicalDevicePipelinePropertiesFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 pipelinePropertiesIdentifier; +} VkPhysicalDevicePipelinePropertiesFeaturesEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPipelinePropertiesEXT)(VkDevice device, const VkPipelineInfoEXT* pPipelineInfo, VkBaseOutStructure* pPipelineProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelinePropertiesEXT( + VkDevice device, + const VkPipelineInfoEXT* pPipelineInfo, + VkBaseOutStructure* pPipelineProperties); +#endif + + +#define VK_EXT_extended_dynamic_state2 1 +#define VK_EXT_EXTENDED_DYNAMIC_STATE_2_SPEC_VERSION 1 +#define VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME "VK_EXT_extended_dynamic_state2" +typedef struct VkPhysicalDeviceExtendedDynamicState2FeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 extendedDynamicState2; + VkBool32 extendedDynamicState2LogicOp; + VkBool32 extendedDynamicState2PatchControlPoints; +} VkPhysicalDeviceExtendedDynamicState2FeaturesEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdSetPatchControlPointsEXT)(VkCommandBuffer commandBuffer, uint32_t patchControlPoints); +typedef void (VKAPI_PTR *PFN_vkCmdSetRasterizerDiscardEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 rasterizerDiscardEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBiasEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 depthBiasEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetLogicOpEXT)(VkCommandBuffer commandBuffer, VkLogicOp logicOp); +typedef void (VKAPI_PTR *PFN_vkCmdSetPrimitiveRestartEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 primitiveRestartEnable); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetPatchControlPointsEXT( + VkCommandBuffer commandBuffer, + uint32_t patchControlPoints); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetRasterizerDiscardEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 rasterizerDiscardEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBiasEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 depthBiasEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetLogicOpEXT( + VkCommandBuffer commandBuffer, + VkLogicOp logicOp); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetPrimitiveRestartEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 primitiveRestartEnable); +#endif + + +#define VK_EXT_color_write_enable 1 +#define VK_EXT_COLOR_WRITE_ENABLE_SPEC_VERSION 1 +#define VK_EXT_COLOR_WRITE_ENABLE_EXTENSION_NAME "VK_EXT_color_write_enable" +typedef struct VkPhysicalDeviceColorWriteEnableFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 colorWriteEnable; +} VkPhysicalDeviceColorWriteEnableFeaturesEXT; + +typedef struct VkPipelineColorWriteCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t attachmentCount; + const VkBool32* pColorWriteEnables; +} VkPipelineColorWriteCreateInfoEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdSetColorWriteEnableEXT)(VkCommandBuffer commandBuffer, uint32_t attachmentCount, const VkBool32* pColorWriteEnables); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetColorWriteEnableEXT( + VkCommandBuffer commandBuffer, + uint32_t attachmentCount, + const VkBool32* pColorWriteEnables); +#endif + + +#define VK_EXT_primitives_generated_query 1 +#define VK_EXT_PRIMITIVES_GENERATED_QUERY_SPEC_VERSION 1 +#define VK_EXT_PRIMITIVES_GENERATED_QUERY_EXTENSION_NAME "VK_EXT_primitives_generated_query" +typedef struct VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 primitivesGeneratedQuery; + VkBool32 primitivesGeneratedQueryWithRasterizerDiscard; + VkBool32 primitivesGeneratedQueryWithNonZeroStreams; +} VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT; + + + +#define VK_EXT_global_priority_query 1 +#define VK_EXT_GLOBAL_PRIORITY_QUERY_SPEC_VERSION 1 +#define VK_EXT_GLOBAL_PRIORITY_QUERY_EXTENSION_NAME "VK_EXT_global_priority_query" +#define VK_MAX_GLOBAL_PRIORITY_SIZE_EXT VK_MAX_GLOBAL_PRIORITY_SIZE_KHR +typedef VkPhysicalDeviceGlobalPriorityQueryFeaturesKHR VkPhysicalDeviceGlobalPriorityQueryFeaturesEXT; + +typedef VkQueueFamilyGlobalPriorityPropertiesKHR VkQueueFamilyGlobalPriorityPropertiesEXT; + + + +#define VK_EXT_image_view_min_lod 1 +#define VK_EXT_IMAGE_VIEW_MIN_LOD_SPEC_VERSION 1 +#define VK_EXT_IMAGE_VIEW_MIN_LOD_EXTENSION_NAME "VK_EXT_image_view_min_lod" +typedef struct VkPhysicalDeviceImageViewMinLodFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 minLod; +} VkPhysicalDeviceImageViewMinLodFeaturesEXT; + +typedef struct VkImageViewMinLodCreateInfoEXT { + VkStructureType sType; + const void* pNext; + float minLod; +} VkImageViewMinLodCreateInfoEXT; + + + +#define VK_EXT_multi_draw 1 +#define VK_EXT_MULTI_DRAW_SPEC_VERSION 1 +#define VK_EXT_MULTI_DRAW_EXTENSION_NAME "VK_EXT_multi_draw" +typedef struct VkPhysicalDeviceMultiDrawFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 multiDraw; +} VkPhysicalDeviceMultiDrawFeaturesEXT; + +typedef struct VkPhysicalDeviceMultiDrawPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t maxMultiDrawCount; +} VkPhysicalDeviceMultiDrawPropertiesEXT; + +typedef struct VkMultiDrawInfoEXT { + uint32_t firstVertex; + uint32_t vertexCount; +} VkMultiDrawInfoEXT; + +typedef struct VkMultiDrawIndexedInfoEXT { + uint32_t firstIndex; + uint32_t indexCount; + int32_t vertexOffset; +} VkMultiDrawIndexedInfoEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdDrawMultiEXT)(VkCommandBuffer commandBuffer, uint32_t drawCount, const VkMultiDrawInfoEXT* pVertexInfo, uint32_t instanceCount, uint32_t firstInstance, uint32_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdDrawMultiIndexedEXT)(VkCommandBuffer commandBuffer, uint32_t drawCount, const VkMultiDrawIndexedInfoEXT* pIndexInfo, uint32_t instanceCount, uint32_t firstInstance, uint32_t stride, const int32_t* pVertexOffset); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawMultiEXT( + VkCommandBuffer commandBuffer, + uint32_t drawCount, + const VkMultiDrawInfoEXT* pVertexInfo, + uint32_t instanceCount, + uint32_t firstInstance, + uint32_t stride); + +VKAPI_ATTR void VKAPI_CALL vkCmdDrawMultiIndexedEXT( + VkCommandBuffer commandBuffer, + uint32_t drawCount, + const VkMultiDrawIndexedInfoEXT* pIndexInfo, + uint32_t instanceCount, + uint32_t firstInstance, + uint32_t stride, + const int32_t* pVertexOffset); +#endif + + +#define VK_EXT_image_2d_view_of_3d 1 +#define VK_EXT_IMAGE_2D_VIEW_OF_3D_SPEC_VERSION 1 +#define VK_EXT_IMAGE_2D_VIEW_OF_3D_EXTENSION_NAME "VK_EXT_image_2d_view_of_3d" +typedef struct VkPhysicalDeviceImage2DViewOf3DFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 image2DViewOf3D; + VkBool32 sampler2DViewOf3D; +} VkPhysicalDeviceImage2DViewOf3DFeaturesEXT; + + + +#define VK_EXT_load_store_op_none 1 +#define VK_EXT_LOAD_STORE_OP_NONE_SPEC_VERSION 1 +#define VK_EXT_LOAD_STORE_OP_NONE_EXTENSION_NAME "VK_EXT_load_store_op_none" + + +#define VK_EXT_border_color_swizzle 1 +#define VK_EXT_BORDER_COLOR_SWIZZLE_SPEC_VERSION 1 +#define VK_EXT_BORDER_COLOR_SWIZZLE_EXTENSION_NAME "VK_EXT_border_color_swizzle" +typedef struct VkPhysicalDeviceBorderColorSwizzleFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 borderColorSwizzle; + VkBool32 borderColorSwizzleFromImage; +} VkPhysicalDeviceBorderColorSwizzleFeaturesEXT; + +typedef struct VkSamplerBorderColorComponentMappingCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkComponentMapping components; + VkBool32 srgb; +} VkSamplerBorderColorComponentMappingCreateInfoEXT; + + + +#define VK_EXT_pageable_device_local_memory 1 +#define VK_EXT_PAGEABLE_DEVICE_LOCAL_MEMORY_SPEC_VERSION 1 +#define VK_EXT_PAGEABLE_DEVICE_LOCAL_MEMORY_EXTENSION_NAME "VK_EXT_pageable_device_local_memory" +typedef struct VkPhysicalDevicePageableDeviceLocalMemoryFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 pageableDeviceLocalMemory; +} VkPhysicalDevicePageableDeviceLocalMemoryFeaturesEXT; + +typedef void (VKAPI_PTR *PFN_vkSetDeviceMemoryPriorityEXT)(VkDevice device, VkDeviceMemory memory, float priority); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkSetDeviceMemoryPriorityEXT( + VkDevice device, + VkDeviceMemory memory, + float priority); +#endif + + +#define VK_VALVE_descriptor_set_host_mapping 1 +#define VK_VALVE_DESCRIPTOR_SET_HOST_MAPPING_SPEC_VERSION 1 +#define VK_VALVE_DESCRIPTOR_SET_HOST_MAPPING_EXTENSION_NAME "VK_VALVE_descriptor_set_host_mapping" +typedef struct VkPhysicalDeviceDescriptorSetHostMappingFeaturesVALVE { + VkStructureType sType; + void* pNext; + VkBool32 descriptorSetHostMapping; +} VkPhysicalDeviceDescriptorSetHostMappingFeaturesVALVE; + +typedef struct VkDescriptorSetBindingReferenceVALVE { + VkStructureType sType; + const void* pNext; + VkDescriptorSetLayout descriptorSetLayout; + uint32_t binding; +} VkDescriptorSetBindingReferenceVALVE; + +typedef struct VkDescriptorSetLayoutHostMappingInfoVALVE { + VkStructureType sType; + void* pNext; + size_t descriptorOffset; + uint32_t descriptorSize; +} VkDescriptorSetLayoutHostMappingInfoVALVE; + +typedef void (VKAPI_PTR *PFN_vkGetDescriptorSetLayoutHostMappingInfoVALVE)(VkDevice device, const VkDescriptorSetBindingReferenceVALVE* pBindingReference, VkDescriptorSetLayoutHostMappingInfoVALVE* pHostMapping); +typedef void (VKAPI_PTR *PFN_vkGetDescriptorSetHostMappingVALVE)(VkDevice device, VkDescriptorSet descriptorSet, void** ppData); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutHostMappingInfoVALVE( + VkDevice device, + const VkDescriptorSetBindingReferenceVALVE* pBindingReference, + VkDescriptorSetLayoutHostMappingInfoVALVE* pHostMapping); + +VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetHostMappingVALVE( + VkDevice device, + VkDescriptorSet descriptorSet, + void** ppData); +#endif + + +#define VK_EXT_non_seamless_cube_map 1 +#define VK_EXT_NON_SEAMLESS_CUBE_MAP_SPEC_VERSION 1 +#define VK_EXT_NON_SEAMLESS_CUBE_MAP_EXTENSION_NAME "VK_EXT_non_seamless_cube_map" +typedef struct VkPhysicalDeviceNonSeamlessCubeMapFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 nonSeamlessCubeMap; +} VkPhysicalDeviceNonSeamlessCubeMapFeaturesEXT; + + + +#define VK_QCOM_fragment_density_map_offset 1 +#define VK_QCOM_FRAGMENT_DENSITY_MAP_OFFSET_SPEC_VERSION 1 +#define VK_QCOM_FRAGMENT_DENSITY_MAP_OFFSET_EXTENSION_NAME "VK_QCOM_fragment_density_map_offset" +typedef struct VkPhysicalDeviceFragmentDensityMapOffsetFeaturesQCOM { + VkStructureType sType; + void* pNext; + VkBool32 fragmentDensityMapOffset; +} VkPhysicalDeviceFragmentDensityMapOffsetFeaturesQCOM; + +typedef struct VkPhysicalDeviceFragmentDensityMapOffsetPropertiesQCOM { + VkStructureType sType; + void* pNext; + VkExtent2D fragmentDensityOffsetGranularity; +} VkPhysicalDeviceFragmentDensityMapOffsetPropertiesQCOM; + +typedef struct VkSubpassFragmentDensityMapOffsetEndInfoQCOM { + VkStructureType sType; + const void* pNext; + uint32_t fragmentDensityOffsetCount; + const VkOffset2D* pFragmentDensityOffsets; +} VkSubpassFragmentDensityMapOffsetEndInfoQCOM; + + + +#define VK_NV_linear_color_attachment 1 +#define VK_NV_LINEAR_COLOR_ATTACHMENT_SPEC_VERSION 1 +#define VK_NV_LINEAR_COLOR_ATTACHMENT_EXTENSION_NAME "VK_NV_linear_color_attachment" +typedef struct VkPhysicalDeviceLinearColorAttachmentFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 linearColorAttachment; +} VkPhysicalDeviceLinearColorAttachmentFeaturesNV; + + + +#define VK_GOOGLE_surfaceless_query 1 +#define VK_GOOGLE_SURFACELESS_QUERY_SPEC_VERSION 1 +#define VK_GOOGLE_SURFACELESS_QUERY_EXTENSION_NAME "VK_GOOGLE_surfaceless_query" + + +#define VK_EXT_image_compression_control_swapchain 1 +#define VK_EXT_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_SPEC_VERSION 1 +#define VK_EXT_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_EXTENSION_NAME "VK_EXT_image_compression_control_swapchain" +typedef struct VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 imageCompressionControlSwapchain; +} VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT; + + + +#define VK_EXT_subpass_merge_feedback 1 +#define VK_EXT_SUBPASS_MERGE_FEEDBACK_SPEC_VERSION 2 +#define VK_EXT_SUBPASS_MERGE_FEEDBACK_EXTENSION_NAME "VK_EXT_subpass_merge_feedback" + +typedef enum VkSubpassMergeStatusEXT { + VK_SUBPASS_MERGE_STATUS_MERGED_EXT = 0, + VK_SUBPASS_MERGE_STATUS_DISALLOWED_EXT = 1, + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_SIDE_EFFECTS_EXT = 2, + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_SAMPLES_MISMATCH_EXT = 3, + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_VIEWS_MISMATCH_EXT = 4, + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_ALIASING_EXT = 5, + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_DEPENDENCIES_EXT = 6, + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_INCOMPATIBLE_INPUT_ATTACHMENT_EXT = 7, + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_TOO_MANY_ATTACHMENTS_EXT = 8, + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_INSUFFICIENT_STORAGE_EXT = 9, + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_DEPTH_STENCIL_COUNT_EXT = 10, + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_RESOLVE_ATTACHMENT_REUSE_EXT = 11, + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_SINGLE_SUBPASS_EXT = 12, + VK_SUBPASS_MERGE_STATUS_NOT_MERGED_UNSPECIFIED_EXT = 13, + VK_SUBPASS_MERGE_STATUS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkSubpassMergeStatusEXT; +typedef struct VkPhysicalDeviceSubpassMergeFeedbackFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 subpassMergeFeedback; +} VkPhysicalDeviceSubpassMergeFeedbackFeaturesEXT; + +typedef struct VkRenderPassCreationControlEXT { + VkStructureType sType; + const void* pNext; + VkBool32 disallowMerging; +} VkRenderPassCreationControlEXT; + +typedef struct VkRenderPassCreationFeedbackInfoEXT { + uint32_t postMergeSubpassCount; +} VkRenderPassCreationFeedbackInfoEXT; + +typedef struct VkRenderPassCreationFeedbackCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkRenderPassCreationFeedbackInfoEXT* pRenderPassFeedback; +} VkRenderPassCreationFeedbackCreateInfoEXT; + +typedef struct VkRenderPassSubpassFeedbackInfoEXT { + VkSubpassMergeStatusEXT subpassMergeStatus; + char description[VK_MAX_DESCRIPTION_SIZE]; + uint32_t postMergeIndex; +} VkRenderPassSubpassFeedbackInfoEXT; + +typedef struct VkRenderPassSubpassFeedbackCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkRenderPassSubpassFeedbackInfoEXT* pSubpassFeedback; +} VkRenderPassSubpassFeedbackCreateInfoEXT; + + + +#define VK_KHR_acceleration_structure 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkAccelerationStructureKHR) +#define VK_KHR_ACCELERATION_STRUCTURE_SPEC_VERSION 13 +#define VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME "VK_KHR_acceleration_structure" + +typedef enum VkBuildAccelerationStructureModeKHR { + VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR = 0, + VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR = 1, + VK_BUILD_ACCELERATION_STRUCTURE_MODE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkBuildAccelerationStructureModeKHR; + +typedef enum VkAccelerationStructureBuildTypeKHR { + VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR = 0, + VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR = 1, + VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_OR_DEVICE_KHR = 2, + VK_ACCELERATION_STRUCTURE_BUILD_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAccelerationStructureBuildTypeKHR; + +typedef enum VkAccelerationStructureCompatibilityKHR { + VK_ACCELERATION_STRUCTURE_COMPATIBILITY_COMPATIBLE_KHR = 0, + VK_ACCELERATION_STRUCTURE_COMPATIBILITY_INCOMPATIBLE_KHR = 1, + VK_ACCELERATION_STRUCTURE_COMPATIBILITY_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAccelerationStructureCompatibilityKHR; + +typedef enum VkAccelerationStructureCreateFlagBitsKHR { + VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR = 0x00000001, + VK_ACCELERATION_STRUCTURE_CREATE_MOTION_BIT_NV = 0x00000004, + VK_ACCELERATION_STRUCTURE_CREATE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAccelerationStructureCreateFlagBitsKHR; +typedef VkFlags VkAccelerationStructureCreateFlagsKHR; +typedef union VkDeviceOrHostAddressKHR { + VkDeviceAddress deviceAddress; + void* hostAddress; +} VkDeviceOrHostAddressKHR; + +typedef struct VkAccelerationStructureBuildRangeInfoKHR { + uint32_t primitiveCount; + uint32_t primitiveOffset; + uint32_t firstVertex; + uint32_t transformOffset; +} VkAccelerationStructureBuildRangeInfoKHR; + +typedef struct VkAccelerationStructureGeometryTrianglesDataKHR { + VkStructureType sType; + const void* pNext; + VkFormat vertexFormat; + VkDeviceOrHostAddressConstKHR vertexData; + VkDeviceSize vertexStride; + uint32_t maxVertex; + VkIndexType indexType; + VkDeviceOrHostAddressConstKHR indexData; + VkDeviceOrHostAddressConstKHR transformData; +} VkAccelerationStructureGeometryTrianglesDataKHR; + +typedef struct VkAccelerationStructureGeometryAabbsDataKHR { + VkStructureType sType; + const void* pNext; + VkDeviceOrHostAddressConstKHR data; + VkDeviceSize stride; +} VkAccelerationStructureGeometryAabbsDataKHR; + +typedef struct VkAccelerationStructureGeometryInstancesDataKHR { + VkStructureType sType; + const void* pNext; + VkBool32 arrayOfPointers; + VkDeviceOrHostAddressConstKHR data; +} VkAccelerationStructureGeometryInstancesDataKHR; + +typedef union VkAccelerationStructureGeometryDataKHR { + VkAccelerationStructureGeometryTrianglesDataKHR triangles; + VkAccelerationStructureGeometryAabbsDataKHR aabbs; + VkAccelerationStructureGeometryInstancesDataKHR instances; +} VkAccelerationStructureGeometryDataKHR; + +typedef struct VkAccelerationStructureGeometryKHR { + VkStructureType sType; + const void* pNext; + VkGeometryTypeKHR geometryType; + VkAccelerationStructureGeometryDataKHR geometry; + VkGeometryFlagsKHR flags; +} VkAccelerationStructureGeometryKHR; + +typedef struct VkAccelerationStructureBuildGeometryInfoKHR { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureTypeKHR type; + VkBuildAccelerationStructureFlagsKHR flags; + VkBuildAccelerationStructureModeKHR mode; + VkAccelerationStructureKHR srcAccelerationStructure; + VkAccelerationStructureKHR dstAccelerationStructure; + uint32_t geometryCount; + const VkAccelerationStructureGeometryKHR* pGeometries; + const VkAccelerationStructureGeometryKHR* const* ppGeometries; + VkDeviceOrHostAddressKHR scratchData; +} VkAccelerationStructureBuildGeometryInfoKHR; + +typedef struct VkAccelerationStructureCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureCreateFlagsKHR createFlags; + VkBuffer buffer; + VkDeviceSize offset; + VkDeviceSize size; + VkAccelerationStructureTypeKHR type; + VkDeviceAddress deviceAddress; +} VkAccelerationStructureCreateInfoKHR; + +typedef struct VkWriteDescriptorSetAccelerationStructureKHR { + VkStructureType sType; + const void* pNext; + uint32_t accelerationStructureCount; + const VkAccelerationStructureKHR* pAccelerationStructures; +} VkWriteDescriptorSetAccelerationStructureKHR; + +typedef struct VkPhysicalDeviceAccelerationStructureFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 accelerationStructure; + VkBool32 accelerationStructureCaptureReplay; + VkBool32 accelerationStructureIndirectBuild; + VkBool32 accelerationStructureHostCommands; + VkBool32 descriptorBindingAccelerationStructureUpdateAfterBind; +} VkPhysicalDeviceAccelerationStructureFeaturesKHR; + +typedef struct VkPhysicalDeviceAccelerationStructurePropertiesKHR { + VkStructureType sType; + void* pNext; + uint64_t maxGeometryCount; + uint64_t maxInstanceCount; + uint64_t maxPrimitiveCount; + uint32_t maxPerStageDescriptorAccelerationStructures; + uint32_t maxPerStageDescriptorUpdateAfterBindAccelerationStructures; + uint32_t maxDescriptorSetAccelerationStructures; + uint32_t maxDescriptorSetUpdateAfterBindAccelerationStructures; + uint32_t minAccelerationStructureScratchOffsetAlignment; +} VkPhysicalDeviceAccelerationStructurePropertiesKHR; + +typedef struct VkAccelerationStructureDeviceAddressInfoKHR { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureKHR accelerationStructure; +} VkAccelerationStructureDeviceAddressInfoKHR; + +typedef struct VkAccelerationStructureVersionInfoKHR { + VkStructureType sType; + const void* pNext; + const uint8_t* pVersionData; +} VkAccelerationStructureVersionInfoKHR; + +typedef struct VkCopyAccelerationStructureToMemoryInfoKHR { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureKHR src; + VkDeviceOrHostAddressKHR dst; + VkCopyAccelerationStructureModeKHR mode; +} VkCopyAccelerationStructureToMemoryInfoKHR; + +typedef struct VkCopyMemoryToAccelerationStructureInfoKHR { + VkStructureType sType; + const void* pNext; + VkDeviceOrHostAddressConstKHR src; + VkAccelerationStructureKHR dst; + VkCopyAccelerationStructureModeKHR mode; +} VkCopyMemoryToAccelerationStructureInfoKHR; + +typedef struct VkCopyAccelerationStructureInfoKHR { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureKHR src; + VkAccelerationStructureKHR dst; + VkCopyAccelerationStructureModeKHR mode; +} VkCopyAccelerationStructureInfoKHR; + +typedef struct VkAccelerationStructureBuildSizesInfoKHR { + VkStructureType sType; + const void* pNext; + VkDeviceSize accelerationStructureSize; + VkDeviceSize updateScratchSize; + VkDeviceSize buildScratchSize; +} VkAccelerationStructureBuildSizesInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateAccelerationStructureKHR)(VkDevice device, const VkAccelerationStructureCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkAccelerationStructureKHR* pAccelerationStructure); +typedef void (VKAPI_PTR *PFN_vkDestroyAccelerationStructureKHR)(VkDevice device, VkAccelerationStructureKHR accelerationStructure, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructuresKHR)(VkCommandBuffer commandBuffer, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos); +typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructuresIndirectKHR)(VkCommandBuffer commandBuffer, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, const VkDeviceAddress* pIndirectDeviceAddresses, const uint32_t* pIndirectStrides, const uint32_t* const* ppMaxPrimitiveCounts); +typedef VkResult (VKAPI_PTR *PFN_vkBuildAccelerationStructuresKHR)(VkDevice device, VkDeferredOperationKHR deferredOperation, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos); +typedef VkResult (VKAPI_PTR *PFN_vkCopyAccelerationStructureKHR)(VkDevice device, VkDeferredOperationKHR deferredOperation, const VkCopyAccelerationStructureInfoKHR* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCopyAccelerationStructureToMemoryKHR)(VkDevice device, VkDeferredOperationKHR deferredOperation, const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCopyMemoryToAccelerationStructureKHR)(VkDevice device, VkDeferredOperationKHR deferredOperation, const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkWriteAccelerationStructuresPropertiesKHR)(VkDevice device, uint32_t accelerationStructureCount, const VkAccelerationStructureKHR* pAccelerationStructures, VkQueryType queryType, size_t dataSize, void* pData, size_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureKHR)(VkCommandBuffer commandBuffer, const VkCopyAccelerationStructureInfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureToMemoryKHR)(VkCommandBuffer commandBuffer, const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyMemoryToAccelerationStructureKHR)(VkCommandBuffer commandBuffer, const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo); +typedef VkDeviceAddress (VKAPI_PTR *PFN_vkGetAccelerationStructureDeviceAddressKHR)(VkDevice device, const VkAccelerationStructureDeviceAddressInfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdWriteAccelerationStructuresPropertiesKHR)(VkCommandBuffer commandBuffer, uint32_t accelerationStructureCount, const VkAccelerationStructureKHR* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery); +typedef void (VKAPI_PTR *PFN_vkGetDeviceAccelerationStructureCompatibilityKHR)(VkDevice device, const VkAccelerationStructureVersionInfoKHR* pVersionInfo, VkAccelerationStructureCompatibilityKHR* pCompatibility); +typedef void (VKAPI_PTR *PFN_vkGetAccelerationStructureBuildSizesKHR)(VkDevice device, VkAccelerationStructureBuildTypeKHR buildType, const VkAccelerationStructureBuildGeometryInfoKHR* pBuildInfo, const uint32_t* pMaxPrimitiveCounts, VkAccelerationStructureBuildSizesInfoKHR* pSizeInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateAccelerationStructureKHR( + VkDevice device, + const VkAccelerationStructureCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkAccelerationStructureKHR* pAccelerationStructure); + +VKAPI_ATTR void VKAPI_CALL vkDestroyAccelerationStructureKHR( + VkDevice device, + VkAccelerationStructureKHR accelerationStructure, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructuresKHR( + VkCommandBuffer commandBuffer, + uint32_t infoCount, + const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, + const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos); + +VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructuresIndirectKHR( + VkCommandBuffer commandBuffer, + uint32_t infoCount, + const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, + const VkDeviceAddress* pIndirectDeviceAddresses, + const uint32_t* pIndirectStrides, + const uint32_t* const* ppMaxPrimitiveCounts); + +VKAPI_ATTR VkResult VKAPI_CALL vkBuildAccelerationStructuresKHR( + VkDevice device, + VkDeferredOperationKHR deferredOperation, + uint32_t infoCount, + const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, + const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos); + +VKAPI_ATTR VkResult VKAPI_CALL vkCopyAccelerationStructureKHR( + VkDevice device, + VkDeferredOperationKHR deferredOperation, + const VkCopyAccelerationStructureInfoKHR* pInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkCopyAccelerationStructureToMemoryKHR( + VkDevice device, + VkDeferredOperationKHR deferredOperation, + const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkCopyMemoryToAccelerationStructureKHR( + VkDevice device, + VkDeferredOperationKHR deferredOperation, + const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkWriteAccelerationStructuresPropertiesKHR( + VkDevice device, + uint32_t accelerationStructureCount, + const VkAccelerationStructureKHR* pAccelerationStructures, + VkQueryType queryType, + size_t dataSize, + void* pData, + size_t stride); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureKHR( + VkCommandBuffer commandBuffer, + const VkCopyAccelerationStructureInfoKHR* pInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureToMemoryKHR( + VkCommandBuffer commandBuffer, + const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyMemoryToAccelerationStructureKHR( + VkCommandBuffer commandBuffer, + const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo); + +VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetAccelerationStructureDeviceAddressKHR( + VkDevice device, + const VkAccelerationStructureDeviceAddressInfoKHR* pInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdWriteAccelerationStructuresPropertiesKHR( + VkCommandBuffer commandBuffer, + uint32_t accelerationStructureCount, + const VkAccelerationStructureKHR* pAccelerationStructures, + VkQueryType queryType, + VkQueryPool queryPool, + uint32_t firstQuery); + +VKAPI_ATTR void VKAPI_CALL vkGetDeviceAccelerationStructureCompatibilityKHR( + VkDevice device, + const VkAccelerationStructureVersionInfoKHR* pVersionInfo, + VkAccelerationStructureCompatibilityKHR* pCompatibility); + +VKAPI_ATTR void VKAPI_CALL vkGetAccelerationStructureBuildSizesKHR( + VkDevice device, + VkAccelerationStructureBuildTypeKHR buildType, + const VkAccelerationStructureBuildGeometryInfoKHR* pBuildInfo, + const uint32_t* pMaxPrimitiveCounts, + VkAccelerationStructureBuildSizesInfoKHR* pSizeInfo); +#endif + + +#define VK_KHR_ray_tracing_pipeline 1 +#define VK_KHR_RAY_TRACING_PIPELINE_SPEC_VERSION 1 +#define VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME "VK_KHR_ray_tracing_pipeline" + +typedef enum VkShaderGroupShaderKHR { + VK_SHADER_GROUP_SHADER_GENERAL_KHR = 0, + VK_SHADER_GROUP_SHADER_CLOSEST_HIT_KHR = 1, + VK_SHADER_GROUP_SHADER_ANY_HIT_KHR = 2, + VK_SHADER_GROUP_SHADER_INTERSECTION_KHR = 3, + VK_SHADER_GROUP_SHADER_MAX_ENUM_KHR = 0x7FFFFFFF +} VkShaderGroupShaderKHR; +typedef struct VkRayTracingShaderGroupCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkRayTracingShaderGroupTypeKHR type; + uint32_t generalShader; + uint32_t closestHitShader; + uint32_t anyHitShader; + uint32_t intersectionShader; + const void* pShaderGroupCaptureReplayHandle; +} VkRayTracingShaderGroupCreateInfoKHR; + +typedef struct VkRayTracingPipelineInterfaceCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t maxPipelineRayPayloadSize; + uint32_t maxPipelineRayHitAttributeSize; +} VkRayTracingPipelineInterfaceCreateInfoKHR; + +typedef struct VkRayTracingPipelineCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkPipelineCreateFlags flags; + uint32_t stageCount; + const VkPipelineShaderStageCreateInfo* pStages; + uint32_t groupCount; + const VkRayTracingShaderGroupCreateInfoKHR* pGroups; + uint32_t maxPipelineRayRecursionDepth; + const VkPipelineLibraryCreateInfoKHR* pLibraryInfo; + const VkRayTracingPipelineInterfaceCreateInfoKHR* pLibraryInterface; + const VkPipelineDynamicStateCreateInfo* pDynamicState; + VkPipelineLayout layout; + VkPipeline basePipelineHandle; + int32_t basePipelineIndex; +} VkRayTracingPipelineCreateInfoKHR; + +typedef struct VkPhysicalDeviceRayTracingPipelineFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 rayTracingPipeline; + VkBool32 rayTracingPipelineShaderGroupHandleCaptureReplay; + VkBool32 rayTracingPipelineShaderGroupHandleCaptureReplayMixed; + VkBool32 rayTracingPipelineTraceRaysIndirect; + VkBool32 rayTraversalPrimitiveCulling; +} VkPhysicalDeviceRayTracingPipelineFeaturesKHR; + +typedef struct VkPhysicalDeviceRayTracingPipelinePropertiesKHR { + VkStructureType sType; + void* pNext; + uint32_t shaderGroupHandleSize; + uint32_t maxRayRecursionDepth; + uint32_t maxShaderGroupStride; + uint32_t shaderGroupBaseAlignment; + uint32_t shaderGroupHandleCaptureReplaySize; + uint32_t maxRayDispatchInvocationCount; + uint32_t shaderGroupHandleAlignment; + uint32_t maxRayHitAttributeSize; +} VkPhysicalDeviceRayTracingPipelinePropertiesKHR; + +typedef struct VkStridedDeviceAddressRegionKHR { + VkDeviceAddress deviceAddress; + VkDeviceSize stride; + VkDeviceSize size; +} VkStridedDeviceAddressRegionKHR; + +typedef struct VkTraceRaysIndirectCommandKHR { + uint32_t width; + uint32_t height; + uint32_t depth; +} VkTraceRaysIndirectCommandKHR; + +typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysKHR)(VkCommandBuffer commandBuffer, const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, uint32_t width, uint32_t height, uint32_t depth); +typedef VkResult (VKAPI_PTR *PFN_vkCreateRayTracingPipelinesKHR)(VkDevice device, VkDeferredOperationKHR deferredOperation, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoKHR* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); +typedef VkResult (VKAPI_PTR *PFN_vkGetRayTracingCaptureReplayShaderGroupHandlesKHR)(VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData); +typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysIndirectKHR)(VkCommandBuffer commandBuffer, const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, VkDeviceAddress indirectDeviceAddress); +typedef VkDeviceSize (VKAPI_PTR *PFN_vkGetRayTracingShaderGroupStackSizeKHR)(VkDevice device, VkPipeline pipeline, uint32_t group, VkShaderGroupShaderKHR groupShader); +typedef void (VKAPI_PTR *PFN_vkCmdSetRayTracingPipelineStackSizeKHR)(VkCommandBuffer commandBuffer, uint32_t pipelineStackSize); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysKHR( + VkCommandBuffer commandBuffer, + const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, + uint32_t width, + uint32_t height, + uint32_t depth); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateRayTracingPipelinesKHR( + VkDevice device, + VkDeferredOperationKHR deferredOperation, + VkPipelineCache pipelineCache, + uint32_t createInfoCount, + const VkRayTracingPipelineCreateInfoKHR* pCreateInfos, + const VkAllocationCallbacks* pAllocator, + VkPipeline* pPipelines); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetRayTracingCaptureReplayShaderGroupHandlesKHR( + VkDevice device, + VkPipeline pipeline, + uint32_t firstGroup, + uint32_t groupCount, + size_t dataSize, + void* pData); + +VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysIndirectKHR( + VkCommandBuffer commandBuffer, + const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, + VkDeviceAddress indirectDeviceAddress); + +VKAPI_ATTR VkDeviceSize VKAPI_CALL vkGetRayTracingShaderGroupStackSizeKHR( + VkDevice device, + VkPipeline pipeline, + uint32_t group, + VkShaderGroupShaderKHR groupShader); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetRayTracingPipelineStackSizeKHR( + VkCommandBuffer commandBuffer, + uint32_t pipelineStackSize); +#endif + + +#define VK_KHR_ray_query 1 +#define VK_KHR_RAY_QUERY_SPEC_VERSION 1 +#define VK_KHR_RAY_QUERY_EXTENSION_NAME "VK_KHR_ray_query" +typedef struct VkPhysicalDeviceRayQueryFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 rayQuery; +} VkPhysicalDeviceRayQueryFeaturesKHR; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/utils/dxvk-1.10.3/include/vulkan/vulkan_win32.h b/utils/dxvk-1.10.3/include/vulkan/vulkan_win32.h new file mode 100644 index 00000000000..1b680f0b1a2 --- /dev/null +++ b/utils/dxvk-1.10.3/include/vulkan/vulkan_win32.h @@ -0,0 +1,315 @@ +#ifndef VULKAN_WIN32_H_ +#define VULKAN_WIN32_H_ 1 + +/* +** Copyright 2015-2021 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +#define VK_KHR_win32_surface 1 +#define VK_KHR_WIN32_SURFACE_SPEC_VERSION 6 +#define VK_KHR_WIN32_SURFACE_EXTENSION_NAME "VK_KHR_win32_surface" +typedef VkFlags VkWin32SurfaceCreateFlagsKHR; +typedef struct VkWin32SurfaceCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkWin32SurfaceCreateFlagsKHR flags; + HINSTANCE hinstance; + HWND hwnd; +} VkWin32SurfaceCreateInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateWin32SurfaceKHR)(VkInstance instance, const VkWin32SurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); +typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateWin32SurfaceKHR( + VkInstance instance, + const VkWin32SurfaceCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); + +VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWin32PresentationSupportKHR( + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex); +#endif + + +#define VK_KHR_external_memory_win32 1 +#define VK_KHR_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_KHR_external_memory_win32" +typedef struct VkImportMemoryWin32HandleInfoKHR { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlagBits handleType; + HANDLE handle; + LPCWSTR name; +} VkImportMemoryWin32HandleInfoKHR; + +typedef struct VkExportMemoryWin32HandleInfoKHR { + VkStructureType sType; + const void* pNext; + const SECURITY_ATTRIBUTES* pAttributes; + DWORD dwAccess; + LPCWSTR name; +} VkExportMemoryWin32HandleInfoKHR; + +typedef struct VkMemoryWin32HandlePropertiesKHR { + VkStructureType sType; + void* pNext; + uint32_t memoryTypeBits; +} VkMemoryWin32HandlePropertiesKHR; + +typedef struct VkMemoryGetWin32HandleInfoKHR { + VkStructureType sType; + const void* pNext; + VkDeviceMemory memory; + VkExternalMemoryHandleTypeFlagBits handleType; +} VkMemoryGetWin32HandleInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandleKHR)(VkDevice device, const VkMemoryGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle); +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandlePropertiesKHR)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, HANDLE handle, VkMemoryWin32HandlePropertiesKHR* pMemoryWin32HandleProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandleKHR( + VkDevice device, + const VkMemoryGetWin32HandleInfoKHR* pGetWin32HandleInfo, + HANDLE* pHandle); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandlePropertiesKHR( + VkDevice device, + VkExternalMemoryHandleTypeFlagBits handleType, + HANDLE handle, + VkMemoryWin32HandlePropertiesKHR* pMemoryWin32HandleProperties); +#endif + + +#define VK_KHR_win32_keyed_mutex 1 +#define VK_KHR_WIN32_KEYED_MUTEX_SPEC_VERSION 1 +#define VK_KHR_WIN32_KEYED_MUTEX_EXTENSION_NAME "VK_KHR_win32_keyed_mutex" +typedef struct VkWin32KeyedMutexAcquireReleaseInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t acquireCount; + const VkDeviceMemory* pAcquireSyncs; + const uint64_t* pAcquireKeys; + const uint32_t* pAcquireTimeouts; + uint32_t releaseCount; + const VkDeviceMemory* pReleaseSyncs; + const uint64_t* pReleaseKeys; +} VkWin32KeyedMutexAcquireReleaseInfoKHR; + + + +#define VK_KHR_external_semaphore_win32 1 +#define VK_KHR_EXTERNAL_SEMAPHORE_WIN32_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME "VK_KHR_external_semaphore_win32" +typedef struct VkImportSemaphoreWin32HandleInfoKHR { + VkStructureType sType; + const void* pNext; + VkSemaphore semaphore; + VkSemaphoreImportFlags flags; + VkExternalSemaphoreHandleTypeFlagBits handleType; + HANDLE handle; + LPCWSTR name; +} VkImportSemaphoreWin32HandleInfoKHR; + +typedef struct VkExportSemaphoreWin32HandleInfoKHR { + VkStructureType sType; + const void* pNext; + const SECURITY_ATTRIBUTES* pAttributes; + DWORD dwAccess; + LPCWSTR name; +} VkExportSemaphoreWin32HandleInfoKHR; + +typedef struct VkD3D12FenceSubmitInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t waitSemaphoreValuesCount; + const uint64_t* pWaitSemaphoreValues; + uint32_t signalSemaphoreValuesCount; + const uint64_t* pSignalSemaphoreValues; +} VkD3D12FenceSubmitInfoKHR; + +typedef struct VkSemaphoreGetWin32HandleInfoKHR { + VkStructureType sType; + const void* pNext; + VkSemaphore semaphore; + VkExternalSemaphoreHandleTypeFlagBits handleType; +} VkSemaphoreGetWin32HandleInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkImportSemaphoreWin32HandleKHR)(VkDevice device, const VkImportSemaphoreWin32HandleInfoKHR* pImportSemaphoreWin32HandleInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreWin32HandleKHR)(VkDevice device, const VkSemaphoreGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkImportSemaphoreWin32HandleKHR( + VkDevice device, + const VkImportSemaphoreWin32HandleInfoKHR* pImportSemaphoreWin32HandleInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreWin32HandleKHR( + VkDevice device, + const VkSemaphoreGetWin32HandleInfoKHR* pGetWin32HandleInfo, + HANDLE* pHandle); +#endif + + +#define VK_KHR_external_fence_win32 1 +#define VK_KHR_EXTERNAL_FENCE_WIN32_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_FENCE_WIN32_EXTENSION_NAME "VK_KHR_external_fence_win32" +typedef struct VkImportFenceWin32HandleInfoKHR { + VkStructureType sType; + const void* pNext; + VkFence fence; + VkFenceImportFlags flags; + VkExternalFenceHandleTypeFlagBits handleType; + HANDLE handle; + LPCWSTR name; +} VkImportFenceWin32HandleInfoKHR; + +typedef struct VkExportFenceWin32HandleInfoKHR { + VkStructureType sType; + const void* pNext; + const SECURITY_ATTRIBUTES* pAttributes; + DWORD dwAccess; + LPCWSTR name; +} VkExportFenceWin32HandleInfoKHR; + +typedef struct VkFenceGetWin32HandleInfoKHR { + VkStructureType sType; + const void* pNext; + VkFence fence; + VkExternalFenceHandleTypeFlagBits handleType; +} VkFenceGetWin32HandleInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkImportFenceWin32HandleKHR)(VkDevice device, const VkImportFenceWin32HandleInfoKHR* pImportFenceWin32HandleInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetFenceWin32HandleKHR)(VkDevice device, const VkFenceGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkImportFenceWin32HandleKHR( + VkDevice device, + const VkImportFenceWin32HandleInfoKHR* pImportFenceWin32HandleInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceWin32HandleKHR( + VkDevice device, + const VkFenceGetWin32HandleInfoKHR* pGetWin32HandleInfo, + HANDLE* pHandle); +#endif + + +#define VK_NV_external_memory_win32 1 +#define VK_NV_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1 +#define VK_NV_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_NV_external_memory_win32" +typedef struct VkImportMemoryWin32HandleInfoNV { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlagsNV handleType; + HANDLE handle; +} VkImportMemoryWin32HandleInfoNV; + +typedef struct VkExportMemoryWin32HandleInfoNV { + VkStructureType sType; + const void* pNext; + const SECURITY_ATTRIBUTES* pAttributes; + DWORD dwAccess; +} VkExportMemoryWin32HandleInfoNV; + +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandleNV)(VkDevice device, VkDeviceMemory memory, VkExternalMemoryHandleTypeFlagsNV handleType, HANDLE* pHandle); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandleNV( + VkDevice device, + VkDeviceMemory memory, + VkExternalMemoryHandleTypeFlagsNV handleType, + HANDLE* pHandle); +#endif + + +#define VK_NV_win32_keyed_mutex 1 +#define VK_NV_WIN32_KEYED_MUTEX_SPEC_VERSION 2 +#define VK_NV_WIN32_KEYED_MUTEX_EXTENSION_NAME "VK_NV_win32_keyed_mutex" +typedef struct VkWin32KeyedMutexAcquireReleaseInfoNV { + VkStructureType sType; + const void* pNext; + uint32_t acquireCount; + const VkDeviceMemory* pAcquireSyncs; + const uint64_t* pAcquireKeys; + const uint32_t* pAcquireTimeoutMilliseconds; + uint32_t releaseCount; + const VkDeviceMemory* pReleaseSyncs; + const uint64_t* pReleaseKeys; +} VkWin32KeyedMutexAcquireReleaseInfoNV; + + + +#define VK_EXT_full_screen_exclusive 1 +#define VK_EXT_FULL_SCREEN_EXCLUSIVE_SPEC_VERSION 4 +#define VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME "VK_EXT_full_screen_exclusive" + +typedef enum VkFullScreenExclusiveEXT { + VK_FULL_SCREEN_EXCLUSIVE_DEFAULT_EXT = 0, + VK_FULL_SCREEN_EXCLUSIVE_ALLOWED_EXT = 1, + VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT = 2, + VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT = 3, + VK_FULL_SCREEN_EXCLUSIVE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkFullScreenExclusiveEXT; +typedef struct VkSurfaceFullScreenExclusiveInfoEXT { + VkStructureType sType; + void* pNext; + VkFullScreenExclusiveEXT fullScreenExclusive; +} VkSurfaceFullScreenExclusiveInfoEXT; + +typedef struct VkSurfaceCapabilitiesFullScreenExclusiveEXT { + VkStructureType sType; + void* pNext; + VkBool32 fullScreenExclusiveSupported; +} VkSurfaceCapabilitiesFullScreenExclusiveEXT; + +typedef struct VkSurfaceFullScreenExclusiveWin32InfoEXT { + VkStructureType sType; + const void* pNext; + HMONITOR hmonitor; +} VkSurfaceFullScreenExclusiveWin32InfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfacePresentModes2EXT)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, uint32_t* pPresentModeCount, VkPresentModeKHR* pPresentModes); +typedef VkResult (VKAPI_PTR *PFN_vkAcquireFullScreenExclusiveModeEXT)(VkDevice device, VkSwapchainKHR swapchain); +typedef VkResult (VKAPI_PTR *PFN_vkReleaseFullScreenExclusiveModeEXT)(VkDevice device, VkSwapchainKHR swapchain); +typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceGroupSurfacePresentModes2EXT)(VkDevice device, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkDeviceGroupPresentModeFlagsKHR* pModes); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfacePresentModes2EXT( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, + uint32_t* pPresentModeCount, + VkPresentModeKHR* pPresentModes); + +VKAPI_ATTR VkResult VKAPI_CALL vkAcquireFullScreenExclusiveModeEXT( + VkDevice device, + VkSwapchainKHR swapchain); + +VKAPI_ATTR VkResult VKAPI_CALL vkReleaseFullScreenExclusiveModeEXT( + VkDevice device, + VkSwapchainKHR swapchain); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupSurfacePresentModes2EXT( + VkDevice device, + const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, + VkDeviceGroupPresentModeFlagsKHR* pModes); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/utils/dxvk-1.10.3/lib/libd3dcompiler_43.def b/utils/dxvk-1.10.3/lib/libd3dcompiler_43.def new file mode 100644 index 00000000000..344fbe0dfda --- /dev/null +++ b/utils/dxvk-1.10.3/lib/libd3dcompiler_43.def @@ -0,0 +1,17 @@ +; File generated automatically from d3dcompiler_43.spec; do not edit! + +LIBRARY d3dcompiler_43.dll + +EXPORTS + D3DAssemble @1 + D3DCompile @3 + D3DCreateBlob @5 + D3DDisassemble @8 + D3DGetBlobPart @9 + D3DGetDebugInfo @10 + D3DGetInputAndOutputSignatureBlob @11 + D3DGetInputSignatureBlob @12 + D3DGetOutputSignatureBlob @13 + D3DPreprocess @14 + D3DReflect @15 + D3DStripShader @17 diff --git a/utils/dxvk-1.10.3/lib32/libd3dcompiler_43.def b/utils/dxvk-1.10.3/lib32/libd3dcompiler_43.def new file mode 100644 index 00000000000..22d78e63287 --- /dev/null +++ b/utils/dxvk-1.10.3/lib32/libd3dcompiler_43.def @@ -0,0 +1,17 @@ +; File generated automatically from d3dcompiler_43.spec; do not edit! + +LIBRARY d3dcompiler_43.dll + +EXPORTS + D3DAssemble@32 @1 + D3DCompile@44 @3 + D3DCreateBlob@8 @5 + D3DDisassemble@20 @8 + D3DGetBlobPart@20 @9 + D3DGetDebugInfo@12 @10 + D3DGetInputAndOutputSignatureBlob@12 @11 + D3DGetInputSignatureBlob@12 @12 + D3DGetOutputSignatureBlob@12 @13 + D3DPreprocess@28 @14 + D3DReflect@16 @15 + D3DStripShader@16 @17 diff --git a/utils/dxvk-1.10.3/meson.build b/utils/dxvk-1.10.3/meson.build new file mode 100644 index 00000000000..248efdb0c98 --- /dev/null +++ b/utils/dxvk-1.10.3/meson.build @@ -0,0 +1,122 @@ +project('dxvk', ['c', 'cpp'], version : 'v1.10.3', meson_version : '>= 0.49', default_options : [ 'cpp_std=c++17' ]) + +cpu_family = target_machine.cpu_family() + +cpp = meson.get_compiler('cpp') +cc = meson.get_compiler('c') +dxvk_is_msvc = cpp.get_id() == 'msvc' + +compiler_args = [ + '-DNOMINMAX', + '-D_WIN32_WINNT=0xa00', + '-msse', + '-msse2', + '-msse3', + '-mfpmath=sse', + '-Wimplicit-fallthrough', + # clang + '-Wno-unused-private-field', + '-Wno-microsoft-exception-spec', +] + +link_args = [ + '-static', + '-static-libgcc', + '-static-libstdc++', + # We need to set the section alignment for debug symbols to + # work properly as well as avoiding a memcpy from the Wine loader. + '-Wl,--file-alignment=4096', +] + +# Wine's built-in back traces only work with dwarf2 symbols +if get_option('debug') and target_machine.system() == 'windows' + compiler_args += [ + '-gstrict-dwarf', + '-gdwarf-2', + ] +endif + +if get_option('build_id') + link_args += [ + '-Wl,--build-id', + ] +endif + +if cpu_family == 'x86' + link_args += [ + '-Wl,--enable-stdcall-fixup', + '-Wl,--add-stdcall-alias', + ] +endif + +add_project_arguments(cpp.get_supported_arguments(compiler_args), language: 'cpp') +add_project_arguments(cc.get_supported_arguments(compiler_args), language: 'c') +add_project_link_arguments(cpp.get_supported_link_arguments(link_args), language: 'cpp') +add_project_link_arguments(cc.get_supported_link_arguments(link_args), language: 'c') + +dxvk_include_path = include_directories('./include') + +if (cpu_family == 'x86_64') + dxvk_library_path = meson.source_root() + '/lib' +else + dxvk_library_path = meson.source_root() + '/lib32' +endif + +dxvk_extradep = [ ] + +lib_vulkan = cpp.find_library('vulkan-1', dirs : dxvk_library_path) +lib_d3d9 = cpp.find_library('d3d9') +lib_d3d11 = cpp.find_library('d3d11') +lib_dxgi = cpp.find_library('dxgi') +lib_d3dcompiler_43 = cpp.find_library('d3dcompiler_43', dirs : dxvk_library_path) + +if dxvk_is_msvc + lib_d3dcompiler_47 = cpp.find_library('d3dcompiler') +else + lib_d3dcompiler_47 = cpp.find_library('d3dcompiler_47') +endif + +exe_ext = '' +dll_ext = '' + +def_spec_ext = '.def' + +glsl_compiler = find_program('glslangValidator') +glsl_args = [ '-V', '--vn', '@BASENAME@', '@INPUT@', '-o', '@OUTPUT@' ] +if run_command(glsl_compiler, [ '--quiet', '--version' ], check : false).returncode() == 0 + glsl_args += [ '--quiet' ] +endif +glsl_generator = generator(glsl_compiler, + output : [ '@BASENAME@.h' ], + arguments : glsl_args, +) + +if dxvk_is_msvc + res_ext = '.res' + wrc = find_program('rc') + wrc_generator = generator(wrc, + output : [ '@BASENAME@' + res_ext ], + arguments : [ '/fo', '@OUTPUT@', '@INPUT@' ], + ) +else + res_ext = '.o' + wrc = find_program('windres') + wrc_generator = generator(wrc, + output : [ '@BASENAME@' + res_ext ], + arguments : [ '-i', '@INPUT@', '-o', '@OUTPUT@' ], + ) +endif + +dxvk_version = vcs_tag( + command: ['git', 'describe', '--dirty=+'], + input: 'version.h.in', + output: 'version.h', +) + +subdir('src') + +enable_tests = get_option('enable_tests') + +if enable_tests + subdir('tests') +endif diff --git a/utils/dxvk-1.10.3/meson_options.txt b/utils/dxvk-1.10.3/meson_options.txt new file mode 100644 index 00000000000..6af1f6b741f --- /dev/null +++ b/utils/dxvk-1.10.3/meson_options.txt @@ -0,0 +1,6 @@ +option('enable_tests', type : 'boolean', value : false) +option('enable_dxgi', type : 'boolean', value : true, description: 'Build DXGI') +option('enable_d3d9', type : 'boolean', value : true, description: 'Build D3D9') +option('enable_d3d10', type : 'boolean', value : true, description: 'Build D3D10') +option('enable_d3d11', type : 'boolean', value : true, description: 'Build D3D11') +option('build_id', type : 'boolean', value : false) diff --git a/utils/dxvk-1.10.3/package-release.sh b/utils/dxvk-1.10.3/package-release.sh new file mode 100644 index 00000000000..9318226cbbe --- /dev/null +++ b/utils/dxvk-1.10.3/package-release.sh @@ -0,0 +1,97 @@ +#!/usr/bin/env bash + +set -e + +shopt -s extglob + +if [ -z "$1" ] || [ -z "$2" ]; then + echo "Usage: $0 version destdir [--no-package] [--dev-build]" + exit 1 +fi + +DXVK_VERSION="$1" +DXVK_SRC_DIR=`dirname $(readlink -f $0)` +DXVK_BUILD_DIR=$(realpath "$2")"/dxvk-$DXVK_VERSION" +DXVK_ARCHIVE_PATH=$(realpath "$2")"/dxvk-$DXVK_VERSION.tar.gz" + +if [ -e "$DXVK_BUILD_DIR" ]; then + echo "Build directory $DXVK_BUILD_DIR already exists" + exit 1 +fi + +shift 2 + +opt_nopackage=0 +opt_devbuild=0 +opt_buildid=false + +crossfile="build-win" + +while [ $# -gt 0 ]; do + case "$1" in + "--no-package") + opt_nopackage=1 + ;; + "--dev-build") + opt_nopackage=1 + opt_devbuild=1 + ;; + "--build-id") + opt_buildid=true + ;; + *) + echo "Unrecognized option: $1" >&2 + exit 1 + esac + shift +done + +function build_arch { + export WINEARCH="win$1" + export WINEPREFIX="$DXVK_BUILD_DIR/wine.$1" + + cd "$DXVK_SRC_DIR" + + opt_strip= + if [ $opt_devbuild -eq 0 ]; then + opt_strip=--strip + fi + + meson --cross-file "$DXVK_SRC_DIR/$crossfile$1.txt" \ + --buildtype "release" \ + --prefix "$DXVK_BUILD_DIR" \ + $opt_strip \ + --bindir "x$1" \ + --libdir "x$1" \ + -Denable_tests=false \ + -Dbuild_id=$opt_buildid \ + "$DXVK_BUILD_DIR/build.$1" + + cd "$DXVK_BUILD_DIR/build.$1" + ninja install + + if [ $opt_devbuild -eq 0 ]; then + # get rid of some useless .a files + rm "$DXVK_BUILD_DIR/x$1/"*.!(dll) + rm -R "$DXVK_BUILD_DIR/build.$1" + fi +} + +function build_script { + cp "$DXVK_SRC_DIR/setup_dxvk.sh" "$DXVK_BUILD_DIR/setup_dxvk.sh" + chmod +x "$DXVK_BUILD_DIR/setup_dxvk.sh" +} + +function package { + cd "$DXVK_BUILD_DIR/.." + tar -czf "$DXVK_ARCHIVE_PATH" "dxvk-$DXVK_VERSION" + rm -R "dxvk-$DXVK_VERSION" +} + +build_arch 64 +build_arch 32 +build_script + +if [ $opt_nopackage -eq 0 ]; then + package +fi diff --git a/utils/dxvk-1.10.3/setup_dxvk.sh b/utils/dxvk-1.10.3/setup_dxvk.sh new file mode 100644 index 00000000000..3e63ecf0c5d --- /dev/null +++ b/utils/dxvk-1.10.3/setup_dxvk.sh @@ -0,0 +1,216 @@ +#!/usr/bin/env bash + +# default directories +dxvk_lib32=${dxvk_lib32:-"x32"} +dxvk_lib64=${dxvk_lib64:-"x64"} + +# figure out where we are +basedir=$(dirname "$(readlink -f $0)") + +# figure out which action to perform +action="$1" + +case "$action" in +install) + ;; +uninstall) + ;; +*) + echo "Unrecognized action: $action" + echo "Usage: $0 [install|uninstall] [--without-dxgi] [--with-d3d10] [--symlink]" + exit 1 +esac + +# process arguments +shift + +with_dxgi=true +with_d3d10=false +file_cmd="cp -v" + +while (($# > 0)); do + case "$1" in + "--without-dxgi") + with_dxgi=false + ;; + "--with-d3d10") + with_d3d10=true + ;; + "--symlink") + file_cmd="ln -s -v" + ;; + esac + shift +done + +# check wine prefix before invoking wine, so that we +# don't accidentally create one if the user screws up +if [ -n "$WINEPREFIX" ] && ! [ -f "$WINEPREFIX/system.reg" ]; then + echo "$WINEPREFIX:"' Not a valid wine prefix.' >&2 + exit 1 +fi + +# find wine executable +export WINEDEBUG=-all +# disable mscoree and mshtml to avoid downloading +# wine gecko and mono +export WINEDLLOVERRIDES="mscoree,mshtml=" + +wine="wine" +wine64="wine64" +wineboot="wineboot" + +# $PATH is the way for user to control where wine is located (including custom Wine versions). +# Pure 64-bit Wine (non Wow64) requries skipping 32-bit steps. +# In such case, wine64 and winebooot will be present, but wine binary will be missing, +# however it can be present in other PATHs, so it shouldn't be used, to avoid versions mixing. +wine_path=$(dirname "$(which $wineboot)") +wow64=true +if ! [ -f "$wine_path/$wine" ]; then + wine=$wine64 + wow64=false +fi + +# resolve 32-bit and 64-bit system32 path +winever=$($wine --version | grep wine) +if [ -z "$winever" ]; then + echo "$wine:"' Not a wine executable. Check your $wine.' >&2 + exit 1 +fi + +# ensure wine placeholder dlls are recreated +# if they are missing +$wineboot -u + +win64_sys_path=$($wine64 winepath -u 'C:\windows\system32' 2> /dev/null) +win64_sys_path="${win64_sys_path/$'\r'/}" +if $wow64; then + win32_sys_path=$($wine winepath -u 'C:\windows\system32' 2> /dev/null) + win32_sys_path="${win32_sys_path/$'\r'/}" +fi + +if [ -z "$win32_sys_path" ] && [ -z "$win64_sys_path" ]; then + echo 'Failed to resolve C:\windows\system32.' >&2 + exit 1 +fi + +# create native dll override +overrideDll() { + $wine reg add 'HKEY_CURRENT_USER\Software\Wine\DllOverrides' /v $1 /d native /f >/dev/null 2>&1 + if [ $? -ne 0 ]; then + echo -e "Failed to add override for $1" + exit 1 + fi +} + +# remove dll override +restoreDll() { + $wine reg delete 'HKEY_CURRENT_USER\Software\Wine\DllOverrides' /v $1 /f > /dev/null 2>&1 + if [ $? -ne 0 ]; then + echo "Failed to remove override for $1" + fi +} + +# copy or link dxvk dll, back up original file +installFile() { + dstfile="${1}/${3}.dll" + srcfile="${basedir}/${2}/${3}.dll" + + if [ -f "${srcfile}.so" ]; then + srcfile="${srcfile}.so" + fi + + if ! [ -f "${srcfile}" ]; then + echo "${srcfile}: File not found. Skipping." >&2 + return 1 + fi + + if [ -n "$1" ]; then + if [ -f "${dstfile}" ] || [ -h "${dstfile}" ]; then + if ! [ -f "${dstfile}.old" ]; then + mv -v "${dstfile}" "${dstfile}.old" + else + rm -v "${dstfile}" + fi + $file_cmd "${srcfile}" "${dstfile}" + else + echo "${dstfile}: File not found in wine prefix" >&2 + return 1 + fi + fi + return 0 +} + +# remove dxvk dll, restore original file +uninstallFile() { + dstfile="${1}/${3}.dll" + srcfile="${basedir}/${2}/${3}.dll" + + if [ -f "${srcfile}.so" ]; then + srcfile="${srcfile}.so" + fi + + if ! [ -f "${srcfile}" ]; then + echo "${srcfile}: File not found. Skipping." >&2 + return 1 + fi + + if ! [ -f "${dstfile}" ] && ! [ -h "${dstfile}" ]; then + echo "${dstfile}: File not found. Skipping." >&2 + return 1 + fi + + if [ -f "${dstfile}.old" ]; then + rm -v "${dstfile}" + mv -v "${dstfile}.old" "${dstfile}" + return 0 + else + return 1 + fi +} + +install() { + installFile "$win64_sys_path" "$dxvk_lib64" "$1" + inst64_ret="$?" + + inst32_ret=-1 + if $wow64; then + installFile "$win32_sys_path" "$dxvk_lib32" "$1" + inst32_ret="$?" + fi + + if (( ($inst32_ret == 0) || ($inst64_ret == 0) )); then + overrideDll "$1" + fi +} + +uninstall() { + uninstallFile "$win64_sys_path" "$dxvk_lib64" "$1" + uninst64_ret="$?" + + uninst32_ret=-1 + if $wow64; then + uninstallFile "$win32_sys_path" "$dxvk_lib32" "$1" + uninst32_ret="$?" + fi + + if (( ($uninst32_ret == 0) || ($uninst64_ret == 0) )); then + restoreDll "$1" + fi +} + +# skip dxgi during install if not explicitly +# enabled, but always try to uninstall it +if $with_dxgi || [ "$action" == "uninstall" ]; then + $action dxgi +fi + +$action d3d9 + +if $with_d3d10 || [ "$action" == "uninstall" ]; then + $action d3d10 + $action d3d10_1 +fi + +$action d3d10core +$action d3d11 diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10.def b/utils/dxvk-1.10.3/src/d3d10/d3d10.def new file mode 100644 index 00000000000..6da63131673 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10.def @@ -0,0 +1,29 @@ +LIBRARY D3D10.DLL +EXPORTS + D3D10CreateDevice + D3D10CreateDeviceAndSwapChain + D3D10GetVertexShaderProfile + D3D10GetGeometryShaderProfile + D3D10GetPixelShaderProfile + D3D10CreateBlob + D3D10GetInputSignatureBlob + D3D10GetOutputSignatureBlob + D3D10ReflectShader + D3D10CompileShader + D3D10CreateEffectFromMemory + D3D10CreateEffectPoolFromMemory + D3D10CompileEffectFromMemory + D3D10DisassembleEffect + D3D10DisassembleShader + D3D10PreprocessShader + D3D10CreateStateBlock + D3D10StateBlockMaskDifference + D3D10StateBlockMaskDisableAll + D3D10StateBlockMaskDisableCapture + D3D10StateBlockMaskEnableAll + D3D10StateBlockMaskEnableCapture + D3D10StateBlockMaskGetSetting + D3D10StateBlockMaskIntersect + D3D10StateBlockMaskUnion + D3D10GetVersion + D3D10RegisterLayers diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_1.def b/utils/dxvk-1.10.3/src/d3d10/d3d10_1.def new file mode 100644 index 00000000000..d32e4e1a655 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_1.def @@ -0,0 +1,29 @@ +LIBRARY D3D10_1.DLL +EXPORTS + D3D10CreateDevice1 + D3D10CreateDeviceAndSwapChain1 + D3D10GetVertexShaderProfile + D3D10GetGeometryShaderProfile + D3D10GetPixelShaderProfile + D3D10CreateBlob + D3D10GetInputSignatureBlob + D3D10GetOutputSignatureBlob + D3D10ReflectShader + D3D10CompileShader + D3D10CreateEffectFromMemory + D3D10CreateEffectPoolFromMemory + D3D10CompileEffectFromMemory + D3D10DisassembleEffect + D3D10DisassembleShader + D3D10PreprocessShader + D3D10CreateStateBlock + D3D10StateBlockMaskDifference + D3D10StateBlockMaskDisableAll + D3D10StateBlockMaskDisableCapture + D3D10StateBlockMaskEnableAll + D3D10StateBlockMaskEnableCapture + D3D10StateBlockMaskGetSetting + D3D10StateBlockMaskIntersect + D3D10StateBlockMaskUnion + D3D10GetVersion + D3D10RegisterLayers \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_blend.cpp b/utils/dxvk-1.10.3/src/d3d10/d3d10_blend.cpp new file mode 100644 index 00000000000..3dc637d1d07 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_blend.cpp @@ -0,0 +1,81 @@ +#include "d3d10_blend.h" + +#include "../d3d11/d3d11_blend.h" +#include "../d3d11/d3d11_device.h" + +namespace dxvk { + + HRESULT STDMETHODCALLTYPE D3D10BlendState::QueryInterface( + REFIID riid, + void** ppvObject) { + return m_d3d11->QueryInterface(riid, ppvObject); + } + + + ULONG STDMETHODCALLTYPE D3D10BlendState::AddRef() { + return m_d3d11->AddRef(); + } + + + ULONG STDMETHODCALLTYPE D3D10BlendState::Release() { + return m_d3d11->Release(); + } + + + void STDMETHODCALLTYPE D3D10BlendState::GetDevice( + ID3D10Device** ppDevice) { + GetD3D10Device(m_d3d11, ppDevice); + } + + + HRESULT STDMETHODCALLTYPE D3D10BlendState::GetPrivateData( + REFGUID guid, + UINT* pDataSize, + void* pData) { + return m_d3d11->GetPrivateData(guid, pDataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D10BlendState::SetPrivateData( + REFGUID guid, + UINT DataSize, + const void* pData) { + return m_d3d11->SetPrivateData(guid, DataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D10BlendState::SetPrivateDataInterface( + REFGUID guid, + const IUnknown* pData) { + return m_d3d11->SetPrivateDataInterface(guid, pData); + } + + + void STDMETHODCALLTYPE D3D10BlendState::GetDesc( + D3D10_BLEND_DESC* pDesc) { + D3D11_BLEND_DESC d3d11Desc; + m_d3d11->GetDesc(&d3d11Desc); + + pDesc->AlphaToCoverageEnable = d3d11Desc.AlphaToCoverageEnable; + pDesc->SrcBlend = D3D10_BLEND (d3d11Desc.RenderTarget[0].SrcBlend); + pDesc->DestBlend = D3D10_BLEND (d3d11Desc.RenderTarget[0].DestBlend); + pDesc->BlendOp = D3D10_BLEND_OP(d3d11Desc.RenderTarget[0].BlendOp); + pDesc->SrcBlendAlpha = D3D10_BLEND (d3d11Desc.RenderTarget[0].SrcBlendAlpha); + pDesc->DestBlendAlpha = D3D10_BLEND (d3d11Desc.RenderTarget[0].DestBlendAlpha); + pDesc->BlendOpAlpha = D3D10_BLEND_OP(d3d11Desc.RenderTarget[0].BlendOpAlpha); + + for (uint32_t i = 0; i < 8; i++) { + uint32_t srcId = d3d11Desc.IndependentBlendEnable ? i : 0; + pDesc->BlendEnable[i] = d3d11Desc.RenderTarget[srcId].BlendEnable; + pDesc->RenderTargetWriteMask[i] = d3d11Desc.RenderTarget[srcId].RenderTargetWriteMask; + } + } + + + void STDMETHODCALLTYPE D3D10BlendState::GetDesc1( + D3D10_BLEND_DESC1* pDesc) { + static_assert(sizeof(D3D10_BLEND_DESC1) == sizeof(D3D11_BLEND_DESC)); + m_d3d11->GetDesc(reinterpret_cast(pDesc)); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_blend.h b/utils/dxvk-1.10.3/src/d3d10/d3d10_blend.h new file mode 100644 index 00000000000..d5d201d7ba3 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_blend.h @@ -0,0 +1,58 @@ +#pragma once + +#include "d3d10_util.h" + +namespace dxvk { + + class D3D11BlendState; + class D3D11Device; + + class D3D10BlendState : public ID3D10BlendState1 { + + public: + + D3D10BlendState(D3D11BlendState* pParent) + : m_d3d11(pParent) { } + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + ULONG STDMETHODCALLTYPE AddRef(); + + ULONG STDMETHODCALLTYPE Release(); + + void STDMETHODCALLTYPE GetDevice( + ID3D10Device** ppDevice); + + HRESULT STDMETHODCALLTYPE GetPrivateData( + REFGUID guid, + UINT* pDataSize, + void* pData); + + HRESULT STDMETHODCALLTYPE SetPrivateData( + REFGUID guid, + UINT DataSize, + const void* pData); + + HRESULT STDMETHODCALLTYPE SetPrivateDataInterface( + REFGUID guid, + const IUnknown* pData); + + void STDMETHODCALLTYPE GetDesc( + D3D10_BLEND_DESC* pDesc); + + void STDMETHODCALLTYPE GetDesc1( + D3D10_BLEND_DESC1* pDesc); + + D3D11BlendState* GetD3D11Iface() { + return m_d3d11; + } + + private: + + D3D11BlendState* m_d3d11; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_buffer.cpp b/utils/dxvk-1.10.3/src/d3d10/d3d10_buffer.cpp new file mode 100644 index 00000000000..2bd089b0fca --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_buffer.cpp @@ -0,0 +1,113 @@ +#include "d3d10_buffer.h" + +#include "../d3d11/d3d11_buffer.h" +#include "../d3d11/d3d11_device.h" +#include "../d3d11/d3d11_context.h" + +namespace dxvk { + + HRESULT STDMETHODCALLTYPE D3D10Buffer::QueryInterface( + REFIID riid, + void** ppvObject) { + return m_d3d11->QueryInterface(riid, ppvObject); + } + + + ULONG STDMETHODCALLTYPE D3D10Buffer::AddRef() { + return m_d3d11->AddRef(); + } + + + ULONG STDMETHODCALLTYPE D3D10Buffer::Release() { + return m_d3d11->Release(); + } + + + void STDMETHODCALLTYPE D3D10Buffer::GetDevice( + ID3D10Device** ppDevice) { + GetD3D10Device(m_d3d11, ppDevice); + } + + + HRESULT STDMETHODCALLTYPE D3D10Buffer::GetPrivateData( + REFGUID guid, + UINT* pDataSize, + void* pData) { + return m_d3d11->GetPrivateData(guid, pDataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D10Buffer::SetPrivateData( + REFGUID guid, + UINT DataSize, + const void* pData) { + return m_d3d11->SetPrivateData(guid, DataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D10Buffer::SetPrivateDataInterface( + REFGUID guid, + const IUnknown* pData) { + return m_d3d11->SetPrivateDataInterface(guid, pData); + } + + + void STDMETHODCALLTYPE D3D10Buffer::GetType( + D3D10_RESOURCE_DIMENSION* rType) { + *rType = D3D10_RESOURCE_DIMENSION_BUFFER; + } + + + void STDMETHODCALLTYPE D3D10Buffer::SetEvictionPriority( + UINT EvictionPriority) { + m_d3d11->SetEvictionPriority(EvictionPriority); + } + + + UINT STDMETHODCALLTYPE D3D10Buffer::GetEvictionPriority() { + return m_d3d11->GetEvictionPriority(); + } + + + HRESULT STDMETHODCALLTYPE D3D10Buffer::Map( + D3D10_MAP MapType, + UINT MapFlags, + void** ppData) { + Com ctx; + GetD3D11Context(m_d3d11, &ctx); + + D3D11_MAPPED_SUBRESOURCE sr; + HRESULT hr = ctx->Map(m_d3d11, 0, + D3D11_MAP(MapType), MapFlags, &sr); + + if (FAILED(hr)) + return hr; + + if (ppData != nullptr) { + *ppData = sr.pData; + return S_OK; + } return S_FALSE; + } + + + void STDMETHODCALLTYPE D3D10Buffer::Unmap() { + Com ctx; + GetD3D11Context(m_d3d11, &ctx); + + ctx->Unmap(m_d3d11, 0); + } + + + void STDMETHODCALLTYPE D3D10Buffer::GetDesc( + D3D10_BUFFER_DESC* pDesc) { + D3D11_BUFFER_DESC d3d11Desc; + m_d3d11->GetDesc(&d3d11Desc); + + pDesc->ByteWidth = d3d11Desc.ByteWidth; + pDesc->Usage = D3D10_USAGE(d3d11Desc.Usage); + pDesc->BindFlags = d3d11Desc.BindFlags; + pDesc->CPUAccessFlags = d3d11Desc.CPUAccessFlags; + pDesc->MiscFlags = ConvertD3D11ResourceFlags(d3d11Desc.MiscFlags); + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_buffer.h b/utils/dxvk-1.10.3/src/d3d10/d3d10_buffer.h new file mode 100644 index 00000000000..f26a7154aaf --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_buffer.h @@ -0,0 +1,71 @@ +#pragma once + +#include "d3d10_util.h" + +namespace dxvk { + + class D3D11Buffer; + class D3D11Device; + class D3D10Device; + + class D3D10Buffer : public ID3D10Buffer { + + public: + + D3D10Buffer(D3D11Buffer* pParent) + : m_d3d11(pParent) { } + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + ULONG STDMETHODCALLTYPE AddRef(); + + ULONG STDMETHODCALLTYPE Release(); + + void STDMETHODCALLTYPE GetDevice( + ID3D10Device** ppDevice); + + HRESULT STDMETHODCALLTYPE GetPrivateData( + REFGUID guid, + UINT* pDataSize, + void* pData); + + HRESULT STDMETHODCALLTYPE SetPrivateData( + REFGUID guid, + UINT DataSize, + const void* pData); + + HRESULT STDMETHODCALLTYPE SetPrivateDataInterface( + REFGUID guid, + const IUnknown* pData); + + void STDMETHODCALLTYPE GetType( + D3D10_RESOURCE_DIMENSION* rType); + + void STDMETHODCALLTYPE SetEvictionPriority( + UINT EvictionPriority); + + UINT STDMETHODCALLTYPE GetEvictionPriority(); + + HRESULT STDMETHODCALLTYPE Map( + D3D10_MAP MapType, + UINT MapFlags, + void** ppData); + + void STDMETHODCALLTYPE Unmap(); + + void STDMETHODCALLTYPE GetDesc( + D3D10_BUFFER_DESC* pDesc); + + D3D11Buffer* GetD3D11Iface() { + return m_d3d11; + } + + private: + + D3D11Buffer* m_d3d11; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_core.cpp b/utils/dxvk-1.10.3/src/d3d10/d3d10_core.cpp new file mode 100644 index 00000000000..d4d229ed849 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_core.cpp @@ -0,0 +1,67 @@ +#include +#include + +#include "../dxgi/dxgi_interfaces.h" + +extern "C" { + using namespace dxvk; + + HRESULT __stdcall D3D11CoreCreateDevice( + IDXGIFactory* pFactory, + IDXGIAdapter* pAdapter, + UINT Flags, + const D3D_FEATURE_LEVEL* pFeatureLevels, + UINT FeatureLevels, + ID3D11Device** ppDevice); + + + DLLEXPORT HRESULT __stdcall D3D10CoreCreateDevice( + IDXGIFactory* pFactory, + IDXGIAdapter* pAdapter, + UINT Flags, + D3D_FEATURE_LEVEL FeatureLevel, + ID3D10Device** ppDevice) { + InitReturnPtr(ppDevice); + + Com d3d11Device; + + HRESULT hr = pAdapter->CheckInterfaceSupport( + __uuidof(ID3D10Device), nullptr); + + if (FAILED(hr)) + return hr; + + hr = D3D11CoreCreateDevice(pFactory, pAdapter, + Flags, &FeatureLevel, 1, &d3d11Device); + + if (FAILED(hr)) + return hr; + + Com multithread; + d3d11Device->QueryInterface(__uuidof(ID3D10Multithread), reinterpret_cast(&multithread)); + multithread->SetMultithreadProtected(!(Flags & D3D10_CREATE_DEVICE_SINGLETHREADED)); + + Com dxvkDevice; + d3d11Device->QueryInterface(__uuidof(IDXGIDXVKDevice), reinterpret_cast(&dxvkDevice)); + dxvkDevice->SetAPIVersion(10); + + if (FAILED(d3d11Device->QueryInterface( + __uuidof(ID3D10Device), reinterpret_cast(ppDevice)))) + return E_FAIL; + + return S_OK; + } + + + UINT64 STDMETHODCALLTYPE D3D10CoreGetVersion() { + // Match the Windows 10 return value, but we + // don't know the exact function signature + return 0xa000100041770ull; + } + + + HRESULT STDMETHODCALLTYPE D3D10CoreRegisterLayers() { + return E_NOTIMPL; + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_depth_stencil.cpp b/utils/dxvk-1.10.3/src/d3d10/d3d10_depth_stencil.cpp new file mode 100644 index 00000000000..a56749cbbd6 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_depth_stencil.cpp @@ -0,0 +1,60 @@ +#include "d3d10_depth_stencil.h" + +#include "../d3d11/d3d11_depth_stencil.h" +#include "../d3d11/d3d11_device.h" + +namespace dxvk { + + HRESULT STDMETHODCALLTYPE D3D10DepthStencilState::QueryInterface( + REFIID riid, + void** ppvObject) { + return m_d3d11->QueryInterface(riid, ppvObject); + } + + + ULONG STDMETHODCALLTYPE D3D10DepthStencilState::AddRef() { + return m_d3d11->AddRef(); + } + + + ULONG STDMETHODCALLTYPE D3D10DepthStencilState::Release() { + return m_d3d11->Release(); + } + + + void STDMETHODCALLTYPE D3D10DepthStencilState::GetDevice( + ID3D10Device** ppDevice) { + GetD3D10Device(m_d3d11, ppDevice); + } + + + HRESULT STDMETHODCALLTYPE D3D10DepthStencilState::GetPrivateData( + REFGUID guid, + UINT* pDataSize, + void* pData) { + return m_d3d11->GetPrivateData(guid, pDataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D10DepthStencilState::SetPrivateData( + REFGUID guid, + UINT DataSize, + const void* pData) { + return m_d3d11->SetPrivateData(guid, DataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D10DepthStencilState::SetPrivateDataInterface( + REFGUID guid, + const IUnknown* pData) { + return m_d3d11->SetPrivateDataInterface(guid, pData); + } + + + void STDMETHODCALLTYPE D3D10DepthStencilState::GetDesc( + D3D10_DEPTH_STENCIL_DESC* pDesc) { + static_assert(sizeof(D3D10_DEPTH_STENCIL_DESC) == sizeof(D3D11_DEPTH_STENCIL_DESC)); + m_d3d11->GetDesc(reinterpret_cast(pDesc)); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_depth_stencil.h b/utils/dxvk-1.10.3/src/d3d10/d3d10_depth_stencil.h new file mode 100644 index 00000000000..953a8b0c165 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_depth_stencil.h @@ -0,0 +1,55 @@ +#pragma once + +#include "d3d10_util.h" + +namespace dxvk { + + class D3D11DepthStencilState; + class D3D11Device; + + class D3D10DepthStencilState : public ID3D10DepthStencilState { + + public: + + D3D10DepthStencilState(D3D11DepthStencilState* pParent) + : m_d3d11(pParent) { } + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + ULONG STDMETHODCALLTYPE AddRef(); + + ULONG STDMETHODCALLTYPE Release(); + + void STDMETHODCALLTYPE GetDevice( + ID3D10Device** ppDevice); + + HRESULT STDMETHODCALLTYPE GetPrivateData( + REFGUID guid, + UINT* pDataSize, + void* pData); + + HRESULT STDMETHODCALLTYPE SetPrivateData( + REFGUID guid, + UINT DataSize, + const void* pData); + + HRESULT STDMETHODCALLTYPE SetPrivateDataInterface( + REFGUID guid, + const IUnknown* pData); + + void STDMETHODCALLTYPE GetDesc( + D3D10_DEPTH_STENCIL_DESC* pDesc); + + D3D11DepthStencilState* GetD3D11Iface() { + return m_d3d11; + } + + private: + + D3D11DepthStencilState* m_d3d11; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_device.cpp b/utils/dxvk-1.10.3/src/d3d10/d3d10_device.cpp new file mode 100644 index 00000000000..d301a4752a0 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_device.cpp @@ -0,0 +1,1598 @@ +#include "d3d10_device.h" + +#include "../d3d11/d3d11_device.h" +#include "../d3d11/d3d11_context_imm.h" + +namespace dxvk { + + D3D10Device::D3D10Device( + D3D11Device* pDevice, + D3D11ImmediateContext* pContext) + : m_device(pDevice), m_context(pContext) { + } + + + D3D10Device::~D3D10Device() { + + } + + + HRESULT STDMETHODCALLTYPE D3D10Device::QueryInterface( + REFIID riid, + void** ppvObject) { + return m_device->QueryInterface(riid, ppvObject); + } + + + ULONG STDMETHODCALLTYPE D3D10Device::AddRef() { + return m_device->AddRef(); + } + + + ULONG STDMETHODCALLTYPE D3D10Device::Release() { + return m_device->Release(); + } + + + HRESULT STDMETHODCALLTYPE D3D10Device::GetPrivateData( + REFGUID guid, + UINT* pDataSize, + void* pData) { + return m_device->GetPrivateData(guid, pDataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D10Device::SetPrivateData( + REFGUID guid, + UINT DataSize, + const void* pData) { + return m_device->SetPrivateData(guid, DataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D10Device::SetPrivateDataInterface( + REFGUID guid, + const IUnknown* pData) { + return m_device->SetPrivateDataInterface(guid, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D10Device::GetDeviceRemovedReason() { + return m_device->GetDeviceRemovedReason(); + } + + + HRESULT STDMETHODCALLTYPE D3D10Device::SetExceptionMode( + UINT RaiseFlags) { + return m_device->SetExceptionMode(RaiseFlags); + } + + + UINT STDMETHODCALLTYPE D3D10Device::GetExceptionMode() { + return m_device->GetExceptionMode(); + } + + + D3D10_FEATURE_LEVEL1 STDMETHODCALLTYPE D3D10Device::GetFeatureLevel() { + return D3D10_FEATURE_LEVEL1(m_device->GetFeatureLevel()); + } + + + void STDMETHODCALLTYPE D3D10Device::ClearState() { + m_context->ClearState(); + } + + + void STDMETHODCALLTYPE D3D10Device::Flush() { + m_context->Flush(); + } + + + HRESULT STDMETHODCALLTYPE D3D10Device::CreateBuffer( + const D3D10_BUFFER_DESC* pDesc, + const D3D10_SUBRESOURCE_DATA* pInitialData, + ID3D10Buffer** ppBuffer) { + InitReturnPtr(ppBuffer); + + if (pDesc == nullptr) + return E_INVALIDARG; + + D3D11_BUFFER_DESC d3d11Desc; + d3d11Desc.ByteWidth = pDesc->ByteWidth; + d3d11Desc.Usage = D3D11_USAGE(pDesc->Usage); + d3d11Desc.BindFlags = pDesc->BindFlags; + d3d11Desc.CPUAccessFlags = pDesc->CPUAccessFlags; + d3d11Desc.MiscFlags = ConvertD3D10ResourceFlags(pDesc->MiscFlags); + d3d11Desc.StructureByteStride = 0; + + ID3D11Buffer* d3d11Buffer = nullptr; + HRESULT hr = m_device->CreateBuffer(&d3d11Desc, + reinterpret_cast(pInitialData), + ppBuffer != nullptr ? &d3d11Buffer : nullptr); + + if (hr != S_OK) + return hr; + + *ppBuffer = static_cast(d3d11Buffer)->GetD3D10Iface(); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D10Device::CreateTexture1D( + const D3D10_TEXTURE1D_DESC* pDesc, + const D3D10_SUBRESOURCE_DATA* pInitialData, + ID3D10Texture1D** ppTexture1D) { + InitReturnPtr(ppTexture1D); + + if (pDesc == nullptr) + return E_INVALIDARG; + + D3D11_TEXTURE1D_DESC d3d11Desc; + d3d11Desc.Width = pDesc->Width; + d3d11Desc.MipLevels = pDesc->MipLevels; + d3d11Desc.ArraySize = pDesc->ArraySize; + d3d11Desc.Format = pDesc->Format; + d3d11Desc.Usage = D3D11_USAGE(pDesc->Usage); + d3d11Desc.BindFlags = pDesc->BindFlags; + d3d11Desc.CPUAccessFlags = pDesc->CPUAccessFlags; + d3d11Desc.MiscFlags = ConvertD3D10ResourceFlags(pDesc->MiscFlags); + + ID3D11Texture1D* d3d11Texture1D = nullptr; + HRESULT hr = m_device->CreateTexture1D(&d3d11Desc, + reinterpret_cast(pInitialData), + ppTexture1D != nullptr ? &d3d11Texture1D : nullptr); + + if (hr != S_OK) + return hr; + + *ppTexture1D = static_cast(d3d11Texture1D)->GetD3D10Iface(); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D10Device::CreateTexture2D( + const D3D10_TEXTURE2D_DESC* pDesc, + const D3D10_SUBRESOURCE_DATA* pInitialData, + ID3D10Texture2D** ppTexture2D) { + InitReturnPtr(ppTexture2D); + + if (pDesc == nullptr) + return E_INVALIDARG; + + D3D11_TEXTURE2D_DESC d3d11Desc; + d3d11Desc.Width = pDesc->Width; + d3d11Desc.Height = pDesc->Height; + d3d11Desc.MipLevels = pDesc->MipLevels; + d3d11Desc.ArraySize = pDesc->ArraySize; + d3d11Desc.Format = pDesc->Format; + d3d11Desc.SampleDesc = pDesc->SampleDesc; + d3d11Desc.Usage = D3D11_USAGE(pDesc->Usage); + d3d11Desc.BindFlags = pDesc->BindFlags; + d3d11Desc.CPUAccessFlags = pDesc->CPUAccessFlags; + d3d11Desc.MiscFlags = ConvertD3D10ResourceFlags(pDesc->MiscFlags); + + ID3D11Texture2D* d3d11Texture2D = nullptr; + HRESULT hr = m_device->CreateTexture2D(&d3d11Desc, + reinterpret_cast(pInitialData), + ppTexture2D != nullptr ? &d3d11Texture2D : nullptr); + + if (hr != S_OK) + return hr; + + *ppTexture2D = static_cast(d3d11Texture2D)->GetD3D10Iface(); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D10Device::CreateTexture3D( + const D3D10_TEXTURE3D_DESC* pDesc, + const D3D10_SUBRESOURCE_DATA* pInitialData, + ID3D10Texture3D** ppTexture3D) { + InitReturnPtr(ppTexture3D); + + if (pDesc == nullptr) + return E_INVALIDARG; + + D3D11_TEXTURE3D_DESC d3d11Desc; + d3d11Desc.Width = pDesc->Width; + d3d11Desc.Height = pDesc->Height; + d3d11Desc.Depth = pDesc->Depth; + d3d11Desc.MipLevels = pDesc->MipLevels; + d3d11Desc.Format = pDesc->Format; + d3d11Desc.Usage = D3D11_USAGE(pDesc->Usage); + d3d11Desc.BindFlags = pDesc->BindFlags; + d3d11Desc.CPUAccessFlags = pDesc->CPUAccessFlags; + d3d11Desc.MiscFlags = ConvertD3D10ResourceFlags(pDesc->MiscFlags); + + ID3D11Texture3D* d3d11Texture3D = nullptr; + HRESULT hr = m_device->CreateTexture3D(&d3d11Desc, + reinterpret_cast(pInitialData), + ppTexture3D != nullptr ? &d3d11Texture3D : nullptr); + + if (hr != S_OK) + return hr; + + *ppTexture3D = static_cast(d3d11Texture3D)->GetD3D10Iface(); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D10Device::CreateShaderResourceView( + ID3D10Resource* pResource, + const D3D10_SHADER_RESOURCE_VIEW_DESC* pDesc, + ID3D10ShaderResourceView** ppSRView) { + InitReturnPtr(ppSRView); + + if (!pResource) + return E_INVALIDARG; + + Com d3d11Resource; + GetD3D11Resource(pResource, &d3d11Resource); + + ID3D11ShaderResourceView* d3d11Srv = nullptr; + HRESULT hr = m_device->CreateShaderResourceView(d3d11Resource.ptr(), + reinterpret_cast(pDesc), + ppSRView ? &d3d11Srv : nullptr); + + if (hr != S_OK) + return hr; + + *ppSRView = static_cast(d3d11Srv)->GetD3D10Iface(); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D10Device::CreateShaderResourceView1( + ID3D10Resource* pResource, + const D3D10_SHADER_RESOURCE_VIEW_DESC1* pDesc, + ID3D10ShaderResourceView1** ppSRView) { + InitReturnPtr(ppSRView); + + if (!pResource) + return E_INVALIDARG; + + Com d3d11Resource; + GetD3D11Resource(pResource, &d3d11Resource); + + ID3D11ShaderResourceView* d3d11View = nullptr; + HRESULT hr = m_device->CreateShaderResourceView(d3d11Resource.ptr(), + reinterpret_cast(pDesc), + ppSRView ? &d3d11View : nullptr); + + if (hr != S_OK) + return hr; + + *ppSRView = static_cast(d3d11View)->GetD3D10Iface(); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D10Device::CreateRenderTargetView( + ID3D10Resource* pResource, + const D3D10_RENDER_TARGET_VIEW_DESC* pDesc, + ID3D10RenderTargetView** ppRTView) { + InitReturnPtr(ppRTView); + + if (!pResource) + return E_INVALIDARG; + + Com d3d11Resource; + GetD3D11Resource(pResource, &d3d11Resource); + + ID3D11RenderTargetView* d3d11View = nullptr; + HRESULT hr = m_device->CreateRenderTargetView(d3d11Resource.ptr(), + reinterpret_cast(pDesc), + ppRTView ? &d3d11View : nullptr); + + if (hr != S_OK) + return hr; + + *ppRTView = static_cast(d3d11View)->GetD3D10Iface(); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D10Device::CreateDepthStencilView( + ID3D10Resource* pResource, + const D3D10_DEPTH_STENCIL_VIEW_DESC* pDesc, + ID3D10DepthStencilView** ppDepthStencilView) { + InitReturnPtr(ppDepthStencilView); + + if (!pResource) + return E_INVALIDARG; + + Com d3d11Resource; + GetD3D11Resource(pResource, &d3d11Resource); + + // D3D10 doesn't have the Flags member, so we have + // to convert the structure. pDesc can be nullptr. + D3D11_DEPTH_STENCIL_VIEW_DESC d3d11Desc; + + if (pDesc != nullptr) { + d3d11Desc.ViewDimension = D3D11_DSV_DIMENSION(pDesc->ViewDimension); + d3d11Desc.Format = pDesc->Format; + d3d11Desc.Flags = 0; + + switch (pDesc->ViewDimension) { + case D3D10_DSV_DIMENSION_UNKNOWN: + break; + + case D3D10_DSV_DIMENSION_TEXTURE1D: + d3d11Desc.Texture1D.MipSlice = pDesc->Texture1D.MipSlice; + break; + + case D3D10_DSV_DIMENSION_TEXTURE1DARRAY: + d3d11Desc.Texture1DArray.MipSlice = pDesc->Texture1DArray.MipSlice; + d3d11Desc.Texture1DArray.FirstArraySlice = pDesc->Texture1DArray.FirstArraySlice; + d3d11Desc.Texture1DArray.ArraySize = pDesc->Texture1DArray.ArraySize; + break; + + case D3D10_DSV_DIMENSION_TEXTURE2D: + d3d11Desc.Texture2D.MipSlice = pDesc->Texture2D.MipSlice; + break; + + case D3D10_DSV_DIMENSION_TEXTURE2DARRAY: + d3d11Desc.Texture2DArray.MipSlice = pDesc->Texture2DArray.MipSlice; + d3d11Desc.Texture2DArray.FirstArraySlice = pDesc->Texture2DArray.FirstArraySlice; + d3d11Desc.Texture2DArray.ArraySize = pDesc->Texture2DArray.ArraySize; + break; + + case D3D10_DSV_DIMENSION_TEXTURE2DMS: + break; + + case D3D10_DSV_DIMENSION_TEXTURE2DMSARRAY: + d3d11Desc.Texture2DMSArray.FirstArraySlice = pDesc->Texture2DMSArray.FirstArraySlice; + d3d11Desc.Texture2DMSArray.ArraySize = pDesc->Texture2DMSArray.ArraySize; + break; + } + } + + ID3D11DepthStencilView* d3d11View = nullptr; + HRESULT hr = m_device->CreateDepthStencilView( + d3d11Resource.ptr(), pDesc ? &d3d11Desc : nullptr, + ppDepthStencilView ? &d3d11View : nullptr); + + if (hr != S_OK) + return hr; + + *ppDepthStencilView = static_cast(d3d11View)->GetD3D10Iface(); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D10Device::CreateInputLayout( + const D3D10_INPUT_ELEMENT_DESC* pInputElementDescs, + UINT NumElements, + const void* pShaderBytecodeWithInputSignature, + SIZE_T BytecodeLength, + ID3D10InputLayout** ppInputLayout) { + InitReturnPtr(ppInputLayout); + + static_assert(sizeof(D3D10_INPUT_ELEMENT_DESC) == + sizeof(D3D11_INPUT_ELEMENT_DESC)); + + ID3D11InputLayout* d3d11InputLayout = nullptr; + HRESULT hr = m_device->CreateInputLayout( + reinterpret_cast(pInputElementDescs), + NumElements, pShaderBytecodeWithInputSignature, BytecodeLength, + ppInputLayout ? &d3d11InputLayout : nullptr); + + if (hr != S_OK) + return hr; + + *ppInputLayout = static_cast(d3d11InputLayout)->GetD3D10Iface(); + return hr; + } + + + HRESULT STDMETHODCALLTYPE D3D10Device::CreateVertexShader( + const void* pShaderBytecode, + SIZE_T BytecodeLength, + ID3D10VertexShader** ppVertexShader) { + InitReturnPtr(ppVertexShader); + + ID3D11VertexShader* d3d11Shader = nullptr; + + HRESULT hr = m_device->CreateVertexShader( + pShaderBytecode, BytecodeLength, nullptr, + ppVertexShader ? &d3d11Shader : nullptr); + + if (hr != S_OK) + return hr; + + *ppVertexShader = static_cast(d3d11Shader)->GetD3D10Iface(); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D10Device::CreateGeometryShader( + const void* pShaderBytecode, + SIZE_T BytecodeLength, + ID3D10GeometryShader** ppGeometryShader) { + InitReturnPtr(ppGeometryShader); + + ID3D11GeometryShader* d3d11Shader = nullptr; + + HRESULT hr = m_device->CreateGeometryShader( + pShaderBytecode, BytecodeLength, nullptr, + ppGeometryShader ? &d3d11Shader : nullptr); + + if (hr != S_OK) + return hr; + + *ppGeometryShader = static_cast(d3d11Shader)->GetD3D10Iface(); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D10Device::CreateGeometryShaderWithStreamOutput( + const void* pShaderBytecode, + SIZE_T BytecodeLength, + const D3D10_SO_DECLARATION_ENTRY* pSODeclaration, + UINT NumEntries, + UINT OutputStreamStride, + ID3D10GeometryShader** ppGeometryShader) { + InitReturnPtr(ppGeometryShader); + + std::vector d3d11Entries(NumEntries); + + for (uint32_t i = 0; i < NumEntries; i++) { + d3d11Entries[i].Stream = 0; + d3d11Entries[i].SemanticName = pSODeclaration[i].SemanticName; + d3d11Entries[i].SemanticIndex = pSODeclaration[i].SemanticIndex; + d3d11Entries[i].StartComponent = pSODeclaration[i].StartComponent; + d3d11Entries[i].ComponentCount = pSODeclaration[i].ComponentCount; + d3d11Entries[i].OutputSlot = pSODeclaration[i].OutputSlot; + } + + ID3D11GeometryShader* d3d11Shader = nullptr; + + HRESULT hr = m_device->CreateGeometryShaderWithStreamOutput( + pShaderBytecode, BytecodeLength, + d3d11Entries.data(), + d3d11Entries.size(), + &OutputStreamStride, 1, + D3D11_SO_NO_RASTERIZED_STREAM, nullptr, + ppGeometryShader ? &d3d11Shader : nullptr); + + if (hr != S_OK) + return hr; + + *ppGeometryShader = static_cast(d3d11Shader)->GetD3D10Iface(); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D10Device::CreatePixelShader( + const void* pShaderBytecode, + SIZE_T BytecodeLength, + ID3D10PixelShader** ppPixelShader) { + InitReturnPtr(ppPixelShader); + + ID3D11PixelShader* d3d11Shader = nullptr; + + HRESULT hr = m_device->CreatePixelShader( + pShaderBytecode, BytecodeLength, nullptr, + ppPixelShader ? &d3d11Shader : nullptr); + + if (hr != S_OK) + return hr; + + *ppPixelShader = static_cast(d3d11Shader)->GetD3D10Iface(); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D10Device::CreateBlendState( + const D3D10_BLEND_DESC* pBlendStateDesc, + ID3D10BlendState** ppBlendState) { + InitReturnPtr(ppBlendState); + + D3D11_BLEND_DESC d3d11Desc; + + if (pBlendStateDesc != nullptr) { + d3d11Desc.AlphaToCoverageEnable = pBlendStateDesc->AlphaToCoverageEnable; + d3d11Desc.IndependentBlendEnable = TRUE; + + for (uint32_t i = 0; i < 8; i++) { + d3d11Desc.RenderTarget[i].BlendEnable = pBlendStateDesc->BlendEnable[i]; + d3d11Desc.RenderTarget[i].SrcBlend = D3D11_BLEND (pBlendStateDesc->SrcBlend); + d3d11Desc.RenderTarget[i].DestBlend = D3D11_BLEND (pBlendStateDesc->DestBlend); + d3d11Desc.RenderTarget[i].BlendOp = D3D11_BLEND_OP(pBlendStateDesc->BlendOp); + d3d11Desc.RenderTarget[i].SrcBlendAlpha = D3D11_BLEND (pBlendStateDesc->SrcBlendAlpha); + d3d11Desc.RenderTarget[i].DestBlendAlpha = D3D11_BLEND (pBlendStateDesc->DestBlendAlpha); + d3d11Desc.RenderTarget[i].BlendOpAlpha = D3D11_BLEND_OP(pBlendStateDesc->BlendOpAlpha); + d3d11Desc.RenderTarget[i].RenderTargetWriteMask = pBlendStateDesc->RenderTargetWriteMask[i]; + } + } + + ID3D11BlendState* d3d11BlendState = nullptr; + HRESULT hr = m_device->CreateBlendState(&d3d11Desc, + ppBlendState ? &d3d11BlendState : nullptr); + + if (hr != S_OK) + return hr; + + *ppBlendState = static_cast(d3d11BlendState)->GetD3D10Iface(); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D10Device::CreateBlendState1( + const D3D10_BLEND_DESC1* pBlendStateDesc, + ID3D10BlendState1** ppBlendState) { + InitReturnPtr(ppBlendState); + + ID3D11BlendState* d3d11BlendState = nullptr; + HRESULT hr = m_device->CreateBlendState( + reinterpret_cast(pBlendStateDesc), + ppBlendState ? &d3d11BlendState : nullptr); + + if (hr != S_OK) + return hr; + + *ppBlendState = static_cast(d3d11BlendState)->GetD3D10Iface(); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D10Device::CreateDepthStencilState( + const D3D10_DEPTH_STENCIL_DESC* pDepthStencilDesc, + ID3D10DepthStencilState** ppDepthStencilState) { + InitReturnPtr(ppDepthStencilState); + + ID3D11DepthStencilState* d3d11DepthStencilState = nullptr; + HRESULT hr = m_device->CreateDepthStencilState( + reinterpret_cast(pDepthStencilDesc), + ppDepthStencilState ? &d3d11DepthStencilState : nullptr); + + if (hr != S_OK) + return hr; + + *ppDepthStencilState = static_cast(d3d11DepthStencilState)->GetD3D10Iface(); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D10Device::CreateRasterizerState( + const D3D10_RASTERIZER_DESC* pRasterizerDesc, + ID3D10RasterizerState** ppRasterizerState) { + InitReturnPtr(ppRasterizerState); + + ID3D11RasterizerState* d3d11RasterizerState = nullptr; + HRESULT hr = m_device->CreateRasterizerState( + reinterpret_cast(pRasterizerDesc), + ppRasterizerState ? &d3d11RasterizerState : nullptr); + + if (hr != S_OK) + return hr; + + *ppRasterizerState = static_cast(d3d11RasterizerState)->GetD3D10Iface(); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D10Device::CreateSamplerState( + const D3D10_SAMPLER_DESC* pSamplerDesc, + ID3D10SamplerState** ppSamplerState) { + InitReturnPtr(ppSamplerState); + + if (pSamplerDesc == nullptr) + return E_INVALIDARG; + + D3D11_SAMPLER_DESC d3d11Desc; + d3d11Desc.Filter = D3D11_FILTER(pSamplerDesc->Filter); + d3d11Desc.AddressU = D3D11_TEXTURE_ADDRESS_MODE(pSamplerDesc->AddressU); + d3d11Desc.AddressV = D3D11_TEXTURE_ADDRESS_MODE(pSamplerDesc->AddressV); + d3d11Desc.AddressW = D3D11_TEXTURE_ADDRESS_MODE(pSamplerDesc->AddressW); + d3d11Desc.MipLODBias = pSamplerDesc->MipLODBias; + d3d11Desc.MaxAnisotropy = pSamplerDesc->MaxAnisotropy; + d3d11Desc.ComparisonFunc = D3D11_COMPARISON_FUNC(pSamplerDesc->ComparisonFunc); + d3d11Desc.MinLOD = pSamplerDesc->MinLOD; + d3d11Desc.MaxLOD = pSamplerDesc->MaxLOD; + + for (uint32_t i = 0; i < 4; i++) + d3d11Desc.BorderColor[i] = pSamplerDesc->BorderColor[i]; + + ID3D11SamplerState* d3d11SamplerState = nullptr; + HRESULT hr = m_device->CreateSamplerState(&d3d11Desc, + ppSamplerState ? &d3d11SamplerState : nullptr); + + if (hr != S_OK) + return hr; + + *ppSamplerState = static_cast(d3d11SamplerState)->GetD3D10Iface(); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D10Device::CreateQuery( + const D3D10_QUERY_DESC* pQueryDesc, + ID3D10Query** ppQuery) { + InitReturnPtr(ppQuery); + + if (pQueryDesc == nullptr) + return E_INVALIDARG; + + D3D11_QUERY_DESC d3d11Desc; + d3d11Desc.Query = D3D11_QUERY(pQueryDesc->Query); + d3d11Desc.MiscFlags = pQueryDesc->MiscFlags; + + ID3D11Query* d3d11Query = nullptr; + HRESULT hr = m_device->CreateQuery(&d3d11Desc, + ppQuery ? &d3d11Query : nullptr); + + if (hr != S_OK) + return hr; + + *ppQuery = static_cast(d3d11Query)->GetD3D10Iface(); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D10Device::CreatePredicate( + const D3D10_QUERY_DESC* pPredicateDesc, + ID3D10Predicate** ppPredicate) { + InitReturnPtr(ppPredicate); + + D3D11_QUERY_DESC d3d11Desc; + d3d11Desc.Query = D3D11_QUERY(pPredicateDesc->Query); + d3d11Desc.MiscFlags = pPredicateDesc->MiscFlags; + + ID3D11Predicate* d3d11Predicate = nullptr; + HRESULT hr = m_device->CreatePredicate(&d3d11Desc, + ppPredicate ? &d3d11Predicate : nullptr); + + if (hr != S_OK) + return hr; + + *ppPredicate = D3D11Query::FromPredicate(d3d11Predicate)->GetD3D10Iface(); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D10Device::CreateCounter( + const D3D10_COUNTER_DESC* pCounterDesc, + ID3D10Counter** ppCounter) { + Logger::err("D3D10Device::CreateCounter: Not implemented"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE D3D10Device::CheckFormatSupport( + DXGI_FORMAT Format, + UINT* pFormatSupport) { + return m_device->CheckFormatSupport(Format, pFormatSupport); + } + + + HRESULT STDMETHODCALLTYPE D3D10Device::CheckMultisampleQualityLevels( + DXGI_FORMAT Format, + UINT SampleCount, + UINT* pNumQualityLevels) { + return m_device->CheckMultisampleQualityLevels( + Format, SampleCount, pNumQualityLevels); + } + + + void STDMETHODCALLTYPE D3D10Device::CheckCounterInfo( + D3D10_COUNTER_INFO* pCounterInfo) { + Logger::err("D3D10Device::CheckCounterInfo: Not implemented"); + } + + + HRESULT STDMETHODCALLTYPE D3D10Device::CheckCounter( + const D3D10_COUNTER_DESC* pDesc, + D3D10_COUNTER_TYPE* pType, + UINT* pActiveCounters, + char* name, + UINT* pNameLength, + char* units, + UINT* pUnitsLength, + char* description, + UINT* pDescriptionLength) { + Logger::err("D3D10Device::CheckCounter: Not implemented"); + return E_NOTIMPL; + } + + + UINT STDMETHODCALLTYPE D3D10Device::GetCreationFlags() { + return m_device->GetCreationFlags(); + } + + + HRESULT STDMETHODCALLTYPE D3D10Device::OpenSharedResource( + HANDLE hResource, + REFIID ReturnedInterface, + void** ppResource) { + return m_device->OpenSharedResource(hResource, ReturnedInterface, ppResource); + } + + + void STDMETHODCALLTYPE D3D10Device::ClearRenderTargetView( + ID3D10RenderTargetView* pRenderTargetView, + const FLOAT ColorRGBA[4]) { + D3D10RenderTargetView* d3d10View = static_cast(pRenderTargetView); + D3D11RenderTargetView* d3d11View = d3d10View ? d3d10View->GetD3D11Iface() : nullptr; + + m_context->ClearRenderTargetView(d3d11View, ColorRGBA); + } + + + void STDMETHODCALLTYPE D3D10Device::ClearDepthStencilView( + ID3D10DepthStencilView* pDepthStencilView, + UINT ClearFlags, + FLOAT Depth, + UINT8 Stencil) { + D3D10DepthStencilView* d3d10View = static_cast(pDepthStencilView); + D3D11DepthStencilView* d3d11View = d3d10View ? d3d10View->GetD3D11Iface() : nullptr; + + m_context->ClearDepthStencilView(d3d11View, ClearFlags, Depth, Stencil); + } + + + void STDMETHODCALLTYPE D3D10Device::SetPredication( + ID3D10Predicate* pPredicate, + BOOL PredicateValue) { + D3D10Query* d3d10Predicate = static_cast(pPredicate); + D3D11Query* d3d11Predicate = d3d10Predicate ? d3d10Predicate->GetD3D11Iface() : nullptr; + + m_context->SetPredication(D3D11Query::AsPredicate(d3d11Predicate), PredicateValue); + } + + + void STDMETHODCALLTYPE D3D10Device::GetPredication( + ID3D10Predicate** ppPredicate, + BOOL* pPredicateValue) { + ID3D11Predicate* d3d11Predicate = nullptr; + + m_context->GetPredication( + ppPredicate ? &d3d11Predicate : nullptr, + pPredicateValue); + + if (ppPredicate) + *ppPredicate = d3d11Predicate ? D3D11Query::FromPredicate(d3d11Predicate)->GetD3D10Iface() : nullptr; + } + + + void STDMETHODCALLTYPE D3D10Device::CopySubresourceRegion( + ID3D10Resource* pDstResource, + UINT DstSubresource, + UINT DstX, + UINT DstY, + UINT DstZ, + ID3D10Resource* pSrcResource, + UINT SrcSubresource, + const D3D10_BOX* pSrcBox) { + if (!pDstResource || !pSrcResource) + return; + + Com d3d11DstResource; + Com d3d11SrcResource; + + GetD3D11Resource(pDstResource, &d3d11DstResource); + GetD3D11Resource(pSrcResource, &d3d11SrcResource); + + m_context->CopySubresourceRegion( + d3d11DstResource.ptr(), DstSubresource, DstX, DstY, DstZ, + d3d11SrcResource.ptr(), SrcSubresource, + reinterpret_cast(pSrcBox)); + } + + + void STDMETHODCALLTYPE D3D10Device::CopyResource( + ID3D10Resource* pDstResource, + ID3D10Resource* pSrcResource) { + if (!pDstResource || !pSrcResource) + return; + + Com d3d11DstResource; + Com d3d11SrcResource; + + GetD3D11Resource(pDstResource, &d3d11DstResource); + GetD3D11Resource(pSrcResource, &d3d11SrcResource); + + m_context->CopyResource( + d3d11DstResource.ptr(), + d3d11SrcResource.ptr()); + } + + + void STDMETHODCALLTYPE D3D10Device::UpdateSubresource( + ID3D10Resource* pDstResource, + UINT DstSubresource, + const D3D10_BOX* pDstBox, + const void* pSrcData, + UINT SrcRowPitch, + UINT SrcDepthPitch) { + if (!pDstResource) + return; + + Com d3d11DstResource; + GetD3D11Resource(pDstResource, &d3d11DstResource); + + m_context->UpdateSubresource( + d3d11DstResource.ptr(), DstSubresource, + reinterpret_cast(pDstBox), + pSrcData, SrcRowPitch, SrcDepthPitch); + } + + + void STDMETHODCALLTYPE D3D10Device::GenerateMips( + ID3D10ShaderResourceView* pShaderResourceView) { + D3D10ShaderResourceView* d3d10View = static_cast(pShaderResourceView); + D3D11ShaderResourceView* d3d11View = d3d10View ? d3d10View->GetD3D11Iface() : nullptr; + + m_context->GenerateMips(d3d11View); + } + + + void STDMETHODCALLTYPE D3D10Device::ResolveSubresource( + ID3D10Resource* pDstResource, + UINT DstSubresource, + ID3D10Resource* pSrcResource, + UINT SrcSubresource, + DXGI_FORMAT Format) { + if (!pDstResource || !pSrcResource) + return; + + Com d3d11DstResource; + Com d3d11SrcResource; + + GetD3D11Resource(pDstResource, &d3d11DstResource); + GetD3D11Resource(pSrcResource, &d3d11SrcResource); + + m_context->ResolveSubresource( + d3d11DstResource.ptr(), DstSubresource, + d3d11SrcResource.ptr(), SrcSubresource, + Format); + } + + + void STDMETHODCALLTYPE D3D10Device::Draw( + UINT VertexCount, + UINT StartVertexLocation) { + m_context->Draw(VertexCount, + StartVertexLocation); + } + + + void STDMETHODCALLTYPE D3D10Device::DrawIndexed( + UINT IndexCount, + UINT StartIndexLocation, + INT BaseVertexLocation) { + m_context->DrawIndexed(IndexCount, + StartIndexLocation, + BaseVertexLocation); + } + + + void STDMETHODCALLTYPE D3D10Device::DrawInstanced( + UINT VertexCountPerInstance, + UINT InstanceCount, + UINT StartVertexLocation, + UINT StartInstanceLocation) { + m_context->DrawInstanced( + VertexCountPerInstance, + InstanceCount, + StartVertexLocation, + StartInstanceLocation); + } + + + void STDMETHODCALLTYPE D3D10Device::DrawIndexedInstanced( + UINT IndexCountPerInstance, + UINT InstanceCount, + UINT StartIndexLocation, + INT BaseVertexLocation, + UINT StartInstanceLocation) { + m_context->DrawIndexedInstanced( + IndexCountPerInstance, + InstanceCount, + StartIndexLocation, + BaseVertexLocation, + StartInstanceLocation); + } + + + void STDMETHODCALLTYPE D3D10Device::DrawAuto() { + m_context->DrawAuto(); + } + + + void STDMETHODCALLTYPE D3D10Device::IASetInputLayout( + ID3D10InputLayout* pInputLayout) { + D3D10InputLayout* d3d10InputLayout = static_cast(pInputLayout); + D3D11InputLayout* d3d11InputLayout = d3d10InputLayout ? d3d10InputLayout->GetD3D11Iface() : nullptr; + + m_context->IASetInputLayout(d3d11InputLayout); + } + + + void STDMETHODCALLTYPE D3D10Device::IASetPrimitiveTopology( + D3D10_PRIMITIVE_TOPOLOGY Topology) { + m_context->IASetPrimitiveTopology( + D3D11_PRIMITIVE_TOPOLOGY(Topology)); + } + + + void STDMETHODCALLTYPE D3D10Device::IASetVertexBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D10Buffer* const* ppVertexBuffers, + const UINT* pStrides, + const UINT* pOffsets) { + ID3D11Buffer* d3d11Buffers[D3D10_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT]; + + if (NumBuffers > D3D10_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT) + return; + + for (uint32_t i = 0; i < NumBuffers; i++) { + d3d11Buffers[i] = ppVertexBuffers[i] + ? static_cast(ppVertexBuffers[i])->GetD3D11Iface() + : nullptr; + } + + m_context->IASetVertexBuffers( + StartSlot, NumBuffers, d3d11Buffers, + pStrides, pOffsets); + } + + + void STDMETHODCALLTYPE D3D10Device::IASetIndexBuffer( + ID3D10Buffer* pIndexBuffer, + DXGI_FORMAT Format, + UINT Offset) { + D3D10Buffer* d3d10Buffer = static_cast(pIndexBuffer); + D3D11Buffer* d3d11Buffer = d3d10Buffer ? d3d10Buffer->GetD3D11Iface() : nullptr; + + m_context->IASetIndexBuffer(d3d11Buffer, Format, Offset); + } + + + void STDMETHODCALLTYPE D3D10Device::IAGetInputLayout( + ID3D10InputLayout** ppInputLayout) { + ID3D11InputLayout* d3d11InputLayout = nullptr; + m_context->IAGetInputLayout(&d3d11InputLayout); + + *ppInputLayout = d3d11InputLayout + ? static_cast(d3d11InputLayout)->GetD3D10Iface() + : nullptr; + } + + + void STDMETHODCALLTYPE D3D10Device::IAGetPrimitiveTopology( + D3D10_PRIMITIVE_TOPOLOGY* pTopology) { + D3D11_PRIMITIVE_TOPOLOGY d3d11Topology; + m_context->IAGetPrimitiveTopology(&d3d11Topology); + + *pTopology = d3d11Topology <= 32 /* begin patch list */ + ? D3D10_PRIMITIVE_TOPOLOGY(d3d11Topology) + : D3D10_PRIMITIVE_TOPOLOGY_UNDEFINED; + } + + + void STDMETHODCALLTYPE D3D10Device::IAGetVertexBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D10Buffer** ppVertexBuffers, + UINT* pStrides, + UINT* pOffsets) { + ID3D11Buffer* d3d11Buffers[D3D10_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT]; + + m_context->IAGetVertexBuffers( + StartSlot, NumBuffers, + ppVertexBuffers ? d3d11Buffers : nullptr, + pStrides, pOffsets); + + if (ppVertexBuffers) { + for (uint32_t i = 0; i < NumBuffers; i++) { + ppVertexBuffers[i] = d3d11Buffers[i] + ? static_cast(d3d11Buffers[i])->GetD3D10Iface() + : nullptr; + } + } + } + + + void STDMETHODCALLTYPE D3D10Device::IAGetIndexBuffer( + ID3D10Buffer** pIndexBuffer, + DXGI_FORMAT* Format, + UINT* Offset) { + ID3D11Buffer* d3d11Buffer = nullptr; + + m_context->IAGetIndexBuffer( + pIndexBuffer ? &d3d11Buffer : nullptr, + Format, Offset); + + if (pIndexBuffer) + *pIndexBuffer = d3d11Buffer ? static_cast(d3d11Buffer)->GetD3D10Iface() : nullptr; + } + + + void STDMETHODCALLTYPE D3D10Device::VSSetShader( + ID3D10VertexShader* pVertexShader) { + D3D10VertexShader* d3d10Shader = static_cast(pVertexShader); + D3D11VertexShader* d3d11Shader = d3d10Shader ? d3d10Shader->GetD3D11Iface() : nullptr; + + m_context->VSSetShader(d3d11Shader, nullptr, 0); + } + + + void STDMETHODCALLTYPE D3D10Device::VSSetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D10Buffer* const* ppConstantBuffers) { + ID3D11Buffer* d3d11Buffers[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT]; + + if (NumBuffers > D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT) + return; + + for (uint32_t i = 0; i < NumBuffers; i++) { + d3d11Buffers[i] = ppConstantBuffers && ppConstantBuffers[i] + ? static_cast(ppConstantBuffers[i])->GetD3D11Iface() + : nullptr; + } + + m_context->VSSetConstantBuffers(StartSlot, NumBuffers, d3d11Buffers); + } + + + void STDMETHODCALLTYPE D3D10Device::VSSetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D10ShaderResourceView* const* ppShaderResourceViews) { + ID3D11ShaderResourceView* d3d11Views[D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT]; + + if (NumViews > D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT) + return; + + for (uint32_t i = 0; i < NumViews; i++) { + d3d11Views[i] = ppShaderResourceViews && ppShaderResourceViews[i] + ? static_cast(ppShaderResourceViews[i])->GetD3D11Iface() + : nullptr; + } + + m_context->VSSetShaderResources(StartSlot, NumViews, d3d11Views); + } + + + void STDMETHODCALLTYPE D3D10Device::VSSetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D10SamplerState* const* ppSamplers) { + ID3D11SamplerState* d3d11Samplers[D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT]; + + if (NumSamplers > D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT) + return; + + for (uint32_t i = 0; i < NumSamplers; i++) { + d3d11Samplers[i] = ppSamplers && ppSamplers[i] + ? static_cast(ppSamplers[i])->GetD3D11Iface() + : nullptr; + } + + m_context->VSSetSamplers(StartSlot, NumSamplers, d3d11Samplers); + } + + + void STDMETHODCALLTYPE D3D10Device::VSGetShader( + ID3D10VertexShader** ppVertexShader) { + ID3D11VertexShader* d3d11Shader = nullptr; + m_context->VSGetShader(&d3d11Shader, nullptr, nullptr); + + *ppVertexShader = d3d11Shader ? static_cast(d3d11Shader)->GetD3D10Iface() : nullptr; + } + + + void STDMETHODCALLTYPE D3D10Device::VSGetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D10Buffer** ppConstantBuffers) { + ID3D11Buffer* d3d11Buffers[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT]; + m_context->VSGetConstantBuffers(StartSlot, NumBuffers, d3d11Buffers); + + for (uint32_t i = 0; i < NumBuffers; i++) { + ppConstantBuffers[i] = d3d11Buffers[i] + ? static_cast(d3d11Buffers[i])->GetD3D10Iface() + : nullptr; + } + } + + + void STDMETHODCALLTYPE D3D10Device::VSGetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D10ShaderResourceView** ppShaderResourceViews) { + ID3D11ShaderResourceView* d3d11Views[D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT]; + m_context->VSGetShaderResources(StartSlot, NumViews, d3d11Views); + + for (uint32_t i = 0; i < NumViews; i++) { + ppShaderResourceViews[i] = d3d11Views[i] + ? static_cast(d3d11Views[i])->GetD3D10Iface() + : nullptr; + } + } + + + void STDMETHODCALLTYPE D3D10Device::VSGetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D10SamplerState** ppSamplers) { + ID3D11SamplerState* d3d11Samplers[D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT]; + m_context->VSGetSamplers(StartSlot, NumSamplers, d3d11Samplers); + + for (uint32_t i = 0; i < NumSamplers; i++) { + ppSamplers[i] = d3d11Samplers[i] + ? static_cast(d3d11Samplers[i])->GetD3D10Iface() + : nullptr; + } + } + + + void STDMETHODCALLTYPE D3D10Device::GSSetShader( + ID3D10GeometryShader* pShader) { + D3D10GeometryShader* d3d10Shader = static_cast(pShader); + D3D11GeometryShader* d3d11Shader = d3d10Shader ? d3d10Shader->GetD3D11Iface() : nullptr; + + m_context->GSSetShader(d3d11Shader, nullptr, 0); + } + + + void STDMETHODCALLTYPE D3D10Device::GSSetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D10Buffer* const* ppConstantBuffers) { + ID3D11Buffer* d3d11Buffers[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT]; + + if (NumBuffers > D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT) + return; + + for (uint32_t i = 0; i < NumBuffers; i++) { + d3d11Buffers[i] = ppConstantBuffers && ppConstantBuffers[i] + ? static_cast(ppConstantBuffers[i])->GetD3D11Iface() + : nullptr; + } + + m_context->GSSetConstantBuffers(StartSlot, NumBuffers, d3d11Buffers); + } + + + void STDMETHODCALLTYPE D3D10Device::GSSetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D10ShaderResourceView* const* ppShaderResourceViews) { + ID3D11ShaderResourceView* d3d11Views[D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT]; + + if (NumViews > D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT) + return; + + for (uint32_t i = 0; i < NumViews; i++) { + d3d11Views[i] = ppShaderResourceViews && ppShaderResourceViews[i] + ? static_cast(ppShaderResourceViews[i])->GetD3D11Iface() + : nullptr; + } + + m_context->GSSetShaderResources(StartSlot, NumViews, d3d11Views); + } + + + void STDMETHODCALLTYPE D3D10Device::GSSetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D10SamplerState* const* ppSamplers) { + ID3D11SamplerState* d3d11Samplers[D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT]; + + if (NumSamplers > D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT) + return; + + for (uint32_t i = 0; i < NumSamplers; i++) { + d3d11Samplers[i] = ppSamplers && ppSamplers[i] + ? static_cast(ppSamplers[i])->GetD3D11Iface() + : nullptr; + } + + m_context->GSSetSamplers(StartSlot, NumSamplers, d3d11Samplers); + } + + + void STDMETHODCALLTYPE D3D10Device::GSGetShader( + ID3D10GeometryShader** ppGeometryShader) { + ID3D11GeometryShader* d3d11Shader = nullptr; + m_context->GSGetShader(&d3d11Shader, nullptr, nullptr); + + *ppGeometryShader = d3d11Shader ? static_cast(d3d11Shader)->GetD3D10Iface() : nullptr; + } + + + void STDMETHODCALLTYPE D3D10Device::GSGetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D10Buffer** ppConstantBuffers) { + ID3D11Buffer* d3d11Buffers[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT]; + m_context->GSGetConstantBuffers(StartSlot, NumBuffers, d3d11Buffers); + + for (uint32_t i = 0; i < NumBuffers; i++) { + ppConstantBuffers[i] = d3d11Buffers[i] + ? static_cast(d3d11Buffers[i])->GetD3D10Iface() + : nullptr; + } + } + + + void STDMETHODCALLTYPE D3D10Device::GSGetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D10ShaderResourceView** ppShaderResourceViews) { + ID3D11ShaderResourceView* d3d11Views[D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT]; + m_context->GSGetShaderResources(StartSlot, NumViews, d3d11Views); + + for (uint32_t i = 0; i < NumViews; i++) { + ppShaderResourceViews[i] = d3d11Views[i] + ? static_cast(d3d11Views[i])->GetD3D10Iface() + : nullptr; + } + } + + + void STDMETHODCALLTYPE D3D10Device::GSGetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D10SamplerState** ppSamplers) { + ID3D11SamplerState* d3d11Samplers[D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT]; + m_context->GSGetSamplers(StartSlot, NumSamplers, d3d11Samplers); + + for (uint32_t i = 0; i < NumSamplers; i++) { + ppSamplers[i] = d3d11Samplers[i] + ? static_cast(d3d11Samplers[i])->GetD3D10Iface() + : nullptr; + } + } + + + void STDMETHODCALLTYPE D3D10Device::PSSetShader( + ID3D10PixelShader* pPixelShader) { + D3D10PixelShader* d3d10Shader = static_cast(pPixelShader); + D3D11PixelShader* d3d11Shader = d3d10Shader ? d3d10Shader->GetD3D11Iface() : nullptr; + + m_context->PSSetShader(d3d11Shader, nullptr, 0); + } + + + void STDMETHODCALLTYPE D3D10Device::PSSetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D10Buffer* const* ppConstantBuffers) { + ID3D11Buffer* d3d11Buffers[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT]; + + if (NumBuffers > D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT) + return; + + for (uint32_t i = 0; i < NumBuffers; i++) { + d3d11Buffers[i] = ppConstantBuffers && ppConstantBuffers[i] + ? static_cast(ppConstantBuffers[i])->GetD3D11Iface() + : nullptr; + } + + m_context->PSSetConstantBuffers(StartSlot, NumBuffers, d3d11Buffers); + } + + + void STDMETHODCALLTYPE D3D10Device::PSSetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D10ShaderResourceView* const* ppShaderResourceViews) { + ID3D11ShaderResourceView* d3d11Views[D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT]; + + if (NumViews > D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT) + return; + + for (uint32_t i = 0; i < NumViews; i++) { + d3d11Views[i] = ppShaderResourceViews && ppShaderResourceViews[i] + ? static_cast(ppShaderResourceViews[i])->GetD3D11Iface() + : nullptr; + } + + m_context->PSSetShaderResources(StartSlot, NumViews, d3d11Views); + } + + + void STDMETHODCALLTYPE D3D10Device::PSSetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D10SamplerState* const* ppSamplers) { + ID3D11SamplerState* d3d11Samplers[D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT]; + + if (NumSamplers > D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT) + return; + + for (uint32_t i = 0; i < NumSamplers; i++) { + d3d11Samplers[i] = ppSamplers && ppSamplers[i] + ? static_cast(ppSamplers[i])->GetD3D11Iface() + : nullptr; + } + + m_context->PSSetSamplers(StartSlot, NumSamplers, d3d11Samplers); + } + + + void STDMETHODCALLTYPE D3D10Device::PSGetShader( + ID3D10PixelShader** ppPixelShader) { + ID3D11PixelShader* d3d11Shader = nullptr; + m_context->PSGetShader(&d3d11Shader, nullptr, nullptr); + + *ppPixelShader = d3d11Shader ? static_cast(d3d11Shader)->GetD3D10Iface() : nullptr; + } + + + void STDMETHODCALLTYPE D3D10Device::PSGetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D10Buffer** ppConstantBuffers) { + ID3D11Buffer* d3d11Buffers[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT]; + m_context->PSGetConstantBuffers(StartSlot, NumBuffers, d3d11Buffers); + + for (uint32_t i = 0; i < NumBuffers; i++) { + ppConstantBuffers[i] = d3d11Buffers[i] + ? static_cast(d3d11Buffers[i])->GetD3D10Iface() + : nullptr; + } + } + + + void STDMETHODCALLTYPE D3D10Device::PSGetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D10ShaderResourceView** ppShaderResourceViews) { + ID3D11ShaderResourceView* d3d11Views[D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT]; + m_context->PSGetShaderResources(StartSlot, NumViews, d3d11Views); + + for (uint32_t i = 0; i < NumViews; i++) { + ppShaderResourceViews[i] = d3d11Views[i] + ? static_cast(d3d11Views[i])->GetD3D10Iface() + : nullptr; + } + } + + + void STDMETHODCALLTYPE D3D10Device::PSGetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D10SamplerState** ppSamplers) { + ID3D11SamplerState* d3d11Samplers[D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT]; + m_context->PSGetSamplers(StartSlot, NumSamplers, d3d11Samplers); + + for (uint32_t i = 0; i < NumSamplers; i++) { + ppSamplers[i] = d3d11Samplers[i] + ? static_cast(d3d11Samplers[i])->GetD3D10Iface() + : nullptr; + } + } + + + void STDMETHODCALLTYPE D3D10Device::OMSetRenderTargets( + UINT NumViews, + ID3D10RenderTargetView* const* ppRenderTargetViews, + ID3D10DepthStencilView* pDepthStencilView) { + ID3D11RenderTargetView* d3d11Rtv[D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT]; + + if (NumViews > D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT) + return; + + for (uint32_t i = 0; i < NumViews; i++) { + d3d11Rtv[i] = ppRenderTargetViews && ppRenderTargetViews[i] + ? static_cast(ppRenderTargetViews[i])->GetD3D11Iface() + : nullptr; + } + + D3D10DepthStencilView* d3d10Dsv = static_cast(pDepthStencilView); + D3D11DepthStencilView* d3d11Dsv = d3d10Dsv ? d3d10Dsv->GetD3D11Iface() : nullptr; + + m_context->OMSetRenderTargets(NumViews, d3d11Rtv, d3d11Dsv); + } + + + void STDMETHODCALLTYPE D3D10Device::OMSetBlendState( + ID3D10BlendState* pBlendState, + const FLOAT BlendFactor[4], + UINT SampleMask) { + D3D10BlendState* d3d10BlendState = static_cast(pBlendState); + D3D11BlendState* d3d11BlendState = d3d10BlendState ? d3d10BlendState->GetD3D11Iface() : nullptr; + + m_context->OMSetBlendState(d3d11BlendState, BlendFactor, SampleMask); + } + + + void STDMETHODCALLTYPE D3D10Device::OMSetDepthStencilState( + ID3D10DepthStencilState* pDepthStencilState, + UINT StencilRef) { + D3D10DepthStencilState* d3d10DepthStencilState = static_cast(pDepthStencilState); + D3D11DepthStencilState* d3d11DepthStencilState = d3d10DepthStencilState ? d3d10DepthStencilState->GetD3D11Iface() : nullptr; + + m_context->OMSetDepthStencilState(d3d11DepthStencilState, StencilRef); + } + + + void STDMETHODCALLTYPE D3D10Device::OMGetRenderTargets( + UINT NumViews, + ID3D10RenderTargetView** ppRenderTargetViews, + ID3D10DepthStencilView** ppDepthStencilView) { + ID3D11RenderTargetView* d3d11Rtv[D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT]; + ID3D11DepthStencilView* d3d11Dsv = nullptr; + + m_context->OMGetRenderTargets(NumViews, + ppRenderTargetViews ? d3d11Rtv : nullptr, + ppDepthStencilView ? &d3d11Dsv : nullptr); + + if (ppRenderTargetViews != nullptr) { + for (uint32_t i = 0; i < NumViews; i++) { + ppRenderTargetViews[i] = d3d11Rtv[i] + ? static_cast(d3d11Rtv[i])->GetD3D10Iface() + : nullptr; + } + } + + if (ppDepthStencilView) + *ppDepthStencilView = d3d11Dsv ? static_cast(d3d11Dsv)->GetD3D10Iface() : nullptr; + } + + + void STDMETHODCALLTYPE D3D10Device::OMGetBlendState( + ID3D10BlendState** ppBlendState, + FLOAT BlendFactor[4], + UINT* pSampleMask) { + ID3D11BlendState* d3d11BlendState = nullptr; + + m_context->OMGetBlendState( + ppBlendState ? &d3d11BlendState : nullptr, + BlendFactor, pSampleMask); + + if (ppBlendState != nullptr) + *ppBlendState = d3d11BlendState ? static_cast(d3d11BlendState)->GetD3D10Iface() : nullptr; + } + + + void STDMETHODCALLTYPE D3D10Device::OMGetDepthStencilState( + ID3D10DepthStencilState** ppDepthStencilState, + UINT* pStencilRef) { + ID3D11DepthStencilState* d3d11DepthStencilState = nullptr; + + m_context->OMGetDepthStencilState( + ppDepthStencilState ? &d3d11DepthStencilState : nullptr, + pStencilRef); + + if (ppDepthStencilState != nullptr) + *ppDepthStencilState = d3d11DepthStencilState ? static_cast(d3d11DepthStencilState)->GetD3D10Iface() : nullptr; + } + + + void STDMETHODCALLTYPE D3D10Device::RSSetState( + ID3D10RasterizerState* pRasterizerState) { + D3D10RasterizerState* d3d10RasterizerState = static_cast(pRasterizerState); + D3D11RasterizerState* d3d11RasterizerState = d3d10RasterizerState ? d3d10RasterizerState->GetD3D11Iface() : nullptr; + + m_context->RSSetState(d3d11RasterizerState); + } + + + void STDMETHODCALLTYPE D3D10Device::RSSetViewports( + UINT NumViewports, + const D3D10_VIEWPORT* pViewports) { + D3D11_VIEWPORT vp[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + + if (NumViewports > D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE) + return; + + for (uint32_t i = 0; i < NumViewports; i++) { + vp[i].TopLeftX = float(pViewports[i].TopLeftX); + vp[i].TopLeftY = float(pViewports[i].TopLeftY); + vp[i].Width = float(pViewports[i].Width); + vp[i].Height = float(pViewports[i].Height); + vp[i].MinDepth = pViewports[i].MinDepth; + vp[i].MaxDepth = pViewports[i].MaxDepth; + } + + m_context->RSSetViewports(NumViewports, vp); + } + + + void STDMETHODCALLTYPE D3D10Device::RSSetScissorRects( + UINT NumRects, + const D3D10_RECT* pRects) { + m_context->RSSetScissorRects(NumRects, pRects); + } + + + void STDMETHODCALLTYPE D3D10Device::RSGetState( + ID3D10RasterizerState** ppRasterizerState) { + ID3D11RasterizerState* d3d11RasterizerState = nullptr; + m_context->RSGetState(&d3d11RasterizerState); + + *ppRasterizerState = d3d11RasterizerState ? static_cast(d3d11RasterizerState)->GetD3D10Iface() : nullptr; + } + + + void STDMETHODCALLTYPE D3D10Device::RSGetViewports( + UINT* NumViewports, + D3D10_VIEWPORT* pViewports) { + D3D11_VIEWPORT vp[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + m_context->RSGetViewports(NumViewports, pViewports != nullptr ? vp : nullptr); + + if (pViewports != nullptr) { + for (uint32_t i = 0; i < *NumViewports; i++) { + pViewports[i].TopLeftX = int32_t(vp[i].TopLeftX); + pViewports[i].TopLeftY = int32_t(vp[i].TopLeftY); + pViewports[i].Width = uint32_t(vp[i].Width); + pViewports[i].Height = uint32_t(vp[i].Height); + pViewports[i].MinDepth = vp[i].MinDepth; + pViewports[i].MaxDepth = vp[i].MaxDepth; + } + } + } + + + void STDMETHODCALLTYPE D3D10Device::RSGetScissorRects( + UINT* NumRects, + D3D10_RECT* pRects) { + m_context->RSGetScissorRects(NumRects, pRects); + } + + + void STDMETHODCALLTYPE D3D10Device::SOSetTargets( + UINT NumBuffers, + ID3D10Buffer* const* ppSOTargets, + const UINT* pOffsets) { + ID3D11Buffer* d3d11Buffers[D3D10_SO_BUFFER_SLOT_COUNT]; + + if (NumBuffers > D3D10_SO_BUFFER_SLOT_COUNT) + return; + + for (uint32_t i = 0; i < NumBuffers; i++) { + d3d11Buffers[i] = ppSOTargets && ppSOTargets[i] + ? static_cast(ppSOTargets[i])->GetD3D11Iface() + : nullptr; + } + + m_context->SOSetTargets(NumBuffers, d3d11Buffers, pOffsets); + } + + + void STDMETHODCALLTYPE D3D10Device::SOGetTargets( + UINT NumBuffers, + ID3D10Buffer** ppSOTargets, + UINT* pOffsets) { + ID3D11Buffer* d3d11Buffers[D3D10_SO_BUFFER_SLOT_COUNT]; + + m_context->SOGetTargetsWithOffsets(NumBuffers, + ppSOTargets ? d3d11Buffers : nullptr, + pOffsets); + + if (ppSOTargets != nullptr) { + for (uint32_t i = 0; i < NumBuffers; i++) { + ppSOTargets[i] = d3d11Buffers[i] + ? static_cast(d3d11Buffers[i])->GetD3D10Iface() + : nullptr; + } + } + } + + + void STDMETHODCALLTYPE D3D10Device::SetTextFilterSize( + UINT Width, + UINT Height) { + // D3D10 doesn't seem to actually store or do anything with these values, + // as when calling GetTextFilterSize, it just makes the values 0. + } + + + void STDMETHODCALLTYPE D3D10Device::GetTextFilterSize( + UINT* pWidth, + UINT* pHeight) { + if (pWidth) + *pWidth = 0; + + if (pHeight) + *pHeight = 0; + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_device.h b/utils/dxvk-1.10.3/src/d3d10/d3d10_device.h new file mode 100644 index 00000000000..c3494cfe130 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_device.h @@ -0,0 +1,480 @@ +#pragma once + +#include "d3d10_multithread.h" + +namespace dxvk { + + class D3D11Device; + class D3D11ImmediateContext; + + class D3D10Device final : public ID3D10Device1 { + + public: + + D3D10Device( + D3D11Device* pDevice, + D3D11ImmediateContext* pContext); + + ~D3D10Device(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + ULONG STDMETHODCALLTYPE AddRef(); + + ULONG STDMETHODCALLTYPE Release(); + + HRESULT STDMETHODCALLTYPE GetPrivateData( + REFGUID guid, + UINT* pDataSize, + void* pData); + + HRESULT STDMETHODCALLTYPE SetPrivateData( + REFGUID guid, + UINT DataSize, + const void* pData); + + HRESULT STDMETHODCALLTYPE SetPrivateDataInterface( + REFGUID guid, + const IUnknown* pData); + + HRESULT STDMETHODCALLTYPE GetDeviceRemovedReason(); + + HRESULT STDMETHODCALLTYPE SetExceptionMode( + UINT RaiseFlags); + + UINT STDMETHODCALLTYPE GetExceptionMode(); + + D3D10_FEATURE_LEVEL1 STDMETHODCALLTYPE GetFeatureLevel(); + + void STDMETHODCALLTYPE ClearState(); + + void STDMETHODCALLTYPE Flush(); + + HRESULT STDMETHODCALLTYPE CreateBuffer( + const D3D10_BUFFER_DESC* pDesc, + const D3D10_SUBRESOURCE_DATA* pInitialData, + ID3D10Buffer** ppBuffer); + + HRESULT STDMETHODCALLTYPE CreateTexture1D( + const D3D10_TEXTURE1D_DESC* pDesc, + const D3D10_SUBRESOURCE_DATA* pInitialData, + ID3D10Texture1D** ppTexture1D); + + HRESULT STDMETHODCALLTYPE CreateTexture2D( + const D3D10_TEXTURE2D_DESC* pDesc, + const D3D10_SUBRESOURCE_DATA* pInitialData, + ID3D10Texture2D** ppTexture2D); + + HRESULT STDMETHODCALLTYPE CreateTexture3D( + const D3D10_TEXTURE3D_DESC* pDesc, + const D3D10_SUBRESOURCE_DATA* pInitialData, + ID3D10Texture3D** ppTexture3D); + + HRESULT STDMETHODCALLTYPE CreateShaderResourceView( + ID3D10Resource* pResource, + const D3D10_SHADER_RESOURCE_VIEW_DESC* pDesc, + ID3D10ShaderResourceView** ppSRView); + + HRESULT STDMETHODCALLTYPE CreateShaderResourceView1( + ID3D10Resource* pResource, + const D3D10_SHADER_RESOURCE_VIEW_DESC1* pDesc, + ID3D10ShaderResourceView1** ppSRView); + + HRESULT STDMETHODCALLTYPE CreateRenderTargetView( + ID3D10Resource* pResource, + const D3D10_RENDER_TARGET_VIEW_DESC* pDesc, + ID3D10RenderTargetView** ppRTView); + + HRESULT STDMETHODCALLTYPE CreateDepthStencilView( + ID3D10Resource* pResource, + const D3D10_DEPTH_STENCIL_VIEW_DESC* pDesc, + ID3D10DepthStencilView** ppDepthStencilView); + + HRESULT STDMETHODCALLTYPE CreateInputLayout( + const D3D10_INPUT_ELEMENT_DESC* pInputElementDescs, + UINT NumElements, + const void* pShaderBytecodeWithInputSignature, + SIZE_T BytecodeLength, + ID3D10InputLayout** ppInputLayout); + + HRESULT STDMETHODCALLTYPE CreateVertexShader( + const void* pShaderBytecode, + SIZE_T BytecodeLength, + ID3D10VertexShader** ppVertexShader); + + HRESULT STDMETHODCALLTYPE CreateGeometryShader( + const void* pShaderBytecode, + SIZE_T BytecodeLength, + ID3D10GeometryShader** ppGeometryShader); + + HRESULT STDMETHODCALLTYPE CreateGeometryShaderWithStreamOutput( + const void* pShaderBytecode, + SIZE_T BytecodeLength, + const D3D10_SO_DECLARATION_ENTRY* pSODeclaration, + UINT NumEntries, + UINT OutputStreamStride, + ID3D10GeometryShader** ppGeometryShader); + + HRESULT STDMETHODCALLTYPE CreatePixelShader( + const void* pShaderBytecode, + SIZE_T BytecodeLength, + ID3D10PixelShader** ppPixelShader); + + HRESULT STDMETHODCALLTYPE CreateBlendState( + const D3D10_BLEND_DESC* pBlendStateDesc, + ID3D10BlendState** ppBlendState); + + HRESULT STDMETHODCALLTYPE CreateBlendState1( + const D3D10_BLEND_DESC1* pBlendStateDesc, + ID3D10BlendState1** ppBlendState); + + HRESULT STDMETHODCALLTYPE CreateDepthStencilState( + const D3D10_DEPTH_STENCIL_DESC* pDepthStencilDesc, + ID3D10DepthStencilState** ppDepthStencilState); + + HRESULT STDMETHODCALLTYPE CreateRasterizerState( + const D3D10_RASTERIZER_DESC* pRasterizerDesc, + ID3D10RasterizerState** ppRasterizerState); + + HRESULT STDMETHODCALLTYPE CreateSamplerState( + const D3D10_SAMPLER_DESC* pSamplerDesc, + ID3D10SamplerState** ppSamplerState); + + HRESULT STDMETHODCALLTYPE CreateQuery( + const D3D10_QUERY_DESC* pQueryDesc, + ID3D10Query** ppQuery); + + HRESULT STDMETHODCALLTYPE CreatePredicate( + const D3D10_QUERY_DESC* pPredicateDesc, + ID3D10Predicate** ppPredicate); + + HRESULT STDMETHODCALLTYPE CreateCounter( + const D3D10_COUNTER_DESC* pCounterDesc, + ID3D10Counter** ppCounter); + + HRESULT STDMETHODCALLTYPE CheckFormatSupport( + DXGI_FORMAT Format, + UINT* pFormatSupport); + + HRESULT STDMETHODCALLTYPE CheckMultisampleQualityLevels( + DXGI_FORMAT Format, + UINT SampleCount, + UINT* pNumQualityLevels); + + void STDMETHODCALLTYPE CheckCounterInfo( + D3D10_COUNTER_INFO* pCounterInfo); + + HRESULT STDMETHODCALLTYPE CheckCounter( + const D3D10_COUNTER_DESC* pDesc, + D3D10_COUNTER_TYPE* pType, + UINT* pActiveCounters, + char* name, + UINT* pNameLength, + char* units, + UINT* pUnitsLength, + char* description, + UINT* pDescriptionLength); + + UINT STDMETHODCALLTYPE GetCreationFlags(); + + HRESULT STDMETHODCALLTYPE OpenSharedResource( + HANDLE hResource, + REFIID ReturnedInterface, + void** ppResource); + + void STDMETHODCALLTYPE ClearRenderTargetView( + ID3D10RenderTargetView* pRenderTargetView, + const FLOAT ColorRGBA[4]); + + void STDMETHODCALLTYPE ClearDepthStencilView( + ID3D10DepthStencilView* pDepthStencilView, + UINT ClearFlags, + FLOAT Depth, + UINT8 Stencil); + + void STDMETHODCALLTYPE SetPredication( + ID3D10Predicate* pPredicate, + BOOL PredicateValue); + + void STDMETHODCALLTYPE GetPredication( + ID3D10Predicate** ppPredicate, + BOOL* pPredicateValue); + + void STDMETHODCALLTYPE CopySubresourceRegion( + ID3D10Resource* pDstResource, + UINT DstSubresource, + UINT DstX, + UINT DstY, + UINT DstZ, + ID3D10Resource* pSrcResource, + UINT SrcSubresource, + const D3D10_BOX* pSrcBox); + + void STDMETHODCALLTYPE CopyResource( + ID3D10Resource* pDstResource, + ID3D10Resource* pSrcResource); + + void STDMETHODCALLTYPE UpdateSubresource( + ID3D10Resource* pDstResource, + UINT DstSubresource, + const D3D10_BOX* pDstBox, + const void* pSrcData, + UINT SrcRowPitch, + UINT SrcDepthPitch); + + void STDMETHODCALLTYPE GenerateMips( + ID3D10ShaderResourceView* pShaderResourceView); + + void STDMETHODCALLTYPE ResolveSubresource( + ID3D10Resource* pDstResource, + UINT DstSubresource, + ID3D10Resource* pSrcResource, + UINT SrcSubresource, + DXGI_FORMAT Format); + + void STDMETHODCALLTYPE Draw( + UINT VertexCount, + UINT StartVertexLocation); + + void STDMETHODCALLTYPE DrawIndexed( + UINT IndexCount, + UINT StartIndexLocation, + INT BaseVertexLocation); + + void STDMETHODCALLTYPE DrawInstanced( + UINT VertexCountPerInstance, + UINT InstanceCount, + UINT StartVertexLocation, + UINT StartInstanceLocation); + + void STDMETHODCALLTYPE DrawIndexedInstanced( + UINT IndexCountPerInstance, + UINT InstanceCount, + UINT StartIndexLocation, + INT BaseVertexLocation, + UINT StartInstanceLocation); + + void STDMETHODCALLTYPE DrawAuto(); + + void STDMETHODCALLTYPE IASetInputLayout( + ID3D10InputLayout* pInputLayout); + + void STDMETHODCALLTYPE IASetPrimitiveTopology( + D3D10_PRIMITIVE_TOPOLOGY Topology); + + void STDMETHODCALLTYPE IASetVertexBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D10Buffer* const* ppVertexBuffers, + const UINT* pStrides, + const UINT* pOffsets); + + void STDMETHODCALLTYPE IASetIndexBuffer( + ID3D10Buffer* pIndexBuffer, + DXGI_FORMAT Format, + UINT Offset); + + void STDMETHODCALLTYPE IAGetInputLayout( + ID3D10InputLayout** ppInputLayout); + + void STDMETHODCALLTYPE IAGetPrimitiveTopology( + D3D10_PRIMITIVE_TOPOLOGY* pTopology); + + void STDMETHODCALLTYPE IAGetVertexBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D10Buffer** ppVertexBuffers, + UINT* pStrides, + UINT* pOffsets); + + void STDMETHODCALLTYPE IAGetIndexBuffer( + ID3D10Buffer** pIndexBuffer, + DXGI_FORMAT* Format, + UINT* Offset); + + void STDMETHODCALLTYPE VSSetShader( + ID3D10VertexShader* pVertexShader); + + void STDMETHODCALLTYPE VSSetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D10Buffer* const* ppConstantBuffers); + + void STDMETHODCALLTYPE VSSetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D10ShaderResourceView* const* ppShaderResourceViews); + + void STDMETHODCALLTYPE VSSetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D10SamplerState* const* ppSamplers); + + void STDMETHODCALLTYPE VSGetShader( + ID3D10VertexShader** ppVertexShader); + + void STDMETHODCALLTYPE VSGetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D10Buffer** ppConstantBuffers); + + void STDMETHODCALLTYPE VSGetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D10ShaderResourceView** ppShaderResourceViews); + + void STDMETHODCALLTYPE VSGetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D10SamplerState** ppSamplers); + + void STDMETHODCALLTYPE GSSetShader( + ID3D10GeometryShader* pShader); + + void STDMETHODCALLTYPE GSSetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D10Buffer* const* ppConstantBuffers); + + void STDMETHODCALLTYPE GSSetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D10ShaderResourceView* const* ppShaderResourceViews); + + void STDMETHODCALLTYPE GSSetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D10SamplerState* const* ppSamplers); + + void STDMETHODCALLTYPE GSGetShader( + ID3D10GeometryShader** ppGeometryShader); + + void STDMETHODCALLTYPE GSGetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D10Buffer** ppConstantBuffers); + + void STDMETHODCALLTYPE GSGetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D10ShaderResourceView** ppShaderResourceViews); + + void STDMETHODCALLTYPE GSGetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D10SamplerState** ppSamplers); + + void STDMETHODCALLTYPE PSSetShader( + ID3D10PixelShader* pPixelShader); + + void STDMETHODCALLTYPE PSSetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D10Buffer* const* ppConstantBuffers); + + void STDMETHODCALLTYPE PSSetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D10ShaderResourceView* const* ppShaderResourceViews); + + void STDMETHODCALLTYPE PSSetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D10SamplerState* const* ppSamplers); + + void STDMETHODCALLTYPE PSGetShader( + ID3D10PixelShader** ppPixelShader); + + void STDMETHODCALLTYPE PSGetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D10Buffer** ppConstantBuffers); + + void STDMETHODCALLTYPE PSGetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D10ShaderResourceView** ppShaderResourceViews); + + void STDMETHODCALLTYPE PSGetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D10SamplerState** ppSamplers); + + void STDMETHODCALLTYPE OMSetRenderTargets( + UINT NumViews, + ID3D10RenderTargetView* const* ppRenderTargetViews, + ID3D10DepthStencilView* pDepthStencilView); + + void STDMETHODCALLTYPE OMSetBlendState( + ID3D10BlendState* pBlendState, + const FLOAT BlendFactor[4], + UINT SampleMask); + + void STDMETHODCALLTYPE OMSetDepthStencilState( + ID3D10DepthStencilState* pDepthStencilState, + UINT StencilRef); + + void STDMETHODCALLTYPE OMGetRenderTargets( + UINT NumViews, + ID3D10RenderTargetView** ppRenderTargetViews, + ID3D10DepthStencilView** ppDepthStencilView); + + void STDMETHODCALLTYPE OMGetBlendState( + ID3D10BlendState** ppBlendState, + FLOAT BlendFactor[4], + UINT* pSampleMask); + + void STDMETHODCALLTYPE OMGetDepthStencilState( + ID3D10DepthStencilState** ppDepthStencilState, + UINT* pStencilRef); + + void STDMETHODCALLTYPE RSSetState( + ID3D10RasterizerState* pRasterizerState); + + void STDMETHODCALLTYPE RSSetViewports( + UINT NumViewports, + const D3D10_VIEWPORT* pViewports); + + void STDMETHODCALLTYPE RSSetScissorRects( + UINT NumRects, + const D3D10_RECT* pRects); + + void STDMETHODCALLTYPE RSGetState( + ID3D10RasterizerState** ppRasterizerState); + + void STDMETHODCALLTYPE RSGetViewports( + UINT* NumViewports, + D3D10_VIEWPORT* pViewports); + + void STDMETHODCALLTYPE RSGetScissorRects( + UINT* NumRects, + D3D10_RECT* pRects); + + void STDMETHODCALLTYPE SOSetTargets( + UINT NumBuffers, + ID3D10Buffer* const* ppSOTargets, + const UINT* pOffsets); + + void STDMETHODCALLTYPE SOGetTargets( + UINT NumBuffers, + ID3D10Buffer** ppSOTargets, + UINT* pOffsets); + + void STDMETHODCALLTYPE SetTextFilterSize( + UINT Width, + UINT Height); + + void STDMETHODCALLTYPE GetTextFilterSize( + UINT* pWidth, + UINT* pHeight); + + private: + + D3D11Device* m_device; + D3D11ImmediateContext* m_context; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_include.h b/utils/dxvk-1.10.3/src/d3d10/d3d10_include.h new file mode 100644 index 00000000000..17143a08bf3 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_include.h @@ -0,0 +1,9 @@ +#pragma once + +#include "../dxgi/dxgi_include.h" + +#include "../util/sync/sync_spinlock.h" +#include "../util/sync/sync_recursive.h" + +#include +#include diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_input_layout.cpp b/utils/dxvk-1.10.3/src/d3d10/d3d10_input_layout.cpp new file mode 100644 index 00000000000..c9e74de8c96 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_input_layout.cpp @@ -0,0 +1,53 @@ +#include "d3d10_input_layout.h" + +#include "../d3d11/d3d11_device.h" +#include "../d3d11/d3d11_input_layout.h" + +namespace dxvk { + + HRESULT STDMETHODCALLTYPE D3D10InputLayout::QueryInterface( + REFIID riid, + void** ppvObject) { + return m_d3d11->QueryInterface(riid, ppvObject); + } + + + ULONG STDMETHODCALLTYPE D3D10InputLayout::AddRef() { + return m_d3d11->AddRef(); + } + + + ULONG STDMETHODCALLTYPE D3D10InputLayout::Release() { + return m_d3d11->Release(); + } + + + void STDMETHODCALLTYPE D3D10InputLayout::GetDevice( + ID3D10Device** ppDevice) { + GetD3D10Device(m_d3d11, ppDevice); + } + + + HRESULT STDMETHODCALLTYPE D3D10InputLayout::GetPrivateData( + REFGUID guid, + UINT* pDataSize, + void* pData) { + return m_d3d11->GetPrivateData(guid, pDataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D10InputLayout::SetPrivateData( + REFGUID guid, + UINT DataSize, + const void* pData) { + return m_d3d11->SetPrivateData(guid, DataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D10InputLayout::SetPrivateDataInterface( + REFGUID guid, + const IUnknown* pData) { + return m_d3d11->SetPrivateDataInterface(guid, pData); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_input_layout.h b/utils/dxvk-1.10.3/src/d3d10/d3d10_input_layout.h new file mode 100644 index 00000000000..731692271a4 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_input_layout.h @@ -0,0 +1,52 @@ +#pragma once + +#include "d3d10_util.h" + +namespace dxvk { + + class D3D11Device; + class D3D11InputLayout; + + class D3D10InputLayout : public ID3D10InputLayout { + + public: + + D3D10InputLayout(D3D11InputLayout* pParent) + : m_d3d11(pParent) { } + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + ULONG STDMETHODCALLTYPE AddRef(); + + ULONG STDMETHODCALLTYPE Release(); + + void STDMETHODCALLTYPE GetDevice( + ID3D10Device** ppDevice); + + HRESULT STDMETHODCALLTYPE GetPrivateData( + REFGUID guid, + UINT* pDataSize, + void* pData); + + HRESULT STDMETHODCALLTYPE SetPrivateData( + REFGUID guid, + UINT DataSize, + const void* pData); + + HRESULT STDMETHODCALLTYPE SetPrivateDataInterface( + REFGUID guid, + const IUnknown* pData); + + D3D11InputLayout* GetD3D11Iface() { + return m_d3d11; + } + + private: + + D3D11InputLayout* m_d3d11; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_interfaces.h b/utils/dxvk-1.10.3/src/d3d10/d3d10_interfaces.h new file mode 100644 index 00000000000..aa028ab575c --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_interfaces.h @@ -0,0 +1,9 @@ +#pragma once + +#include "d3d10_include.h" + +#ifdef _MSC_VER +struct __declspec(uuid("0803425a-57f5-4dd6-9465-a87570834a08")) ID3D10StateBlock; +#else +__CRT_UUID_DECL(ID3D10StateBlock, 0x0803425a,0x57f5,0x4dd6,0x94,0x65,0xa8,0x75,0x70,0x83,0x4a,0x08); +#endif diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_main.cpp b/utils/dxvk-1.10.3/src/d3d10/d3d10_main.cpp new file mode 100644 index 00000000000..7bec4d0be77 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_main.cpp @@ -0,0 +1,335 @@ +#include + +#include "d3d10_include.h" +#include "d3d10_reflection.h" + +#include "../dxgi/dxgi_adapter.h" + +namespace dxvk { + Logger Logger::s_instance("d3d10.log"); +} + +extern "C" { + using namespace dxvk; + + HRESULT __stdcall D3D10CoreCreateDevice( + IDXGIFactory* pFactory, + IDXGIAdapter* pAdapter, + UINT Flags, + D3D_FEATURE_LEVEL FeatureLevel, + ID3D10Device** ppDevice); + + static HRESULT D3D10InternalCreateDeviceAndSwapChain( + IDXGIAdapter* pAdapter, + D3D10_DRIVER_TYPE DriverType, + HMODULE Software, + UINT Flags, + D3D10_FEATURE_LEVEL1 HardwareLevel, + UINT SDKVersion, + DXGI_SWAP_CHAIN_DESC* pSwapChainDesc, + IDXGISwapChain** ppSwapChain, + REFIID deviceIID, + void** ppDevice) { + InitReturnPtr(ppDevice); + InitReturnPtr(ppSwapChain); + + if (ppSwapChain && !pSwapChainDesc) + return E_INVALIDARG; + + HRESULT hr; + + // Get DXGI factory and adapter. This is mostly + // copied from the equivalent D3D11 functions. + Com dxgiFactory = nullptr; + Com dxgiAdapter = pAdapter; + Com device = nullptr; + + if (!pAdapter) { + if (DriverType != D3D10_DRIVER_TYPE_HARDWARE) + Logger::warn("D3D10CreateDevice: Unsupported driver type"); + + hr = CreateDXGIFactory(__uuidof(IDXGIFactory), reinterpret_cast(&dxgiFactory)); + + if (FAILED(hr)) { + Logger::err("D3D10CreateDevice: Failed to create a DXGI factory"); + return hr; + } + + hr = dxgiFactory->EnumAdapters(0, &dxgiAdapter); + + if (FAILED(hr)) { + Logger::err("D3D10CreateDevice: No default adapter available"); + return hr; + } + } else { + if (FAILED(dxgiAdapter->GetParent(__uuidof(IDXGIFactory), reinterpret_cast(&dxgiFactory)))) { + Logger::err("D3D10CreateDevice: Failed to query DXGI factory from DXGI adapter"); + return E_INVALIDARG; + } + + if (DriverType != D3D10_DRIVER_TYPE_HARDWARE || Software) + return E_INVALIDARG; + } + + hr = D3D10CoreCreateDevice( + dxgiFactory.ptr(), dxgiAdapter.ptr(), + Flags, D3D_FEATURE_LEVEL(HardwareLevel), + &device); + + if (FAILED(hr)) + return hr; + + if (ppSwapChain) { + DXGI_SWAP_CHAIN_DESC desc = *pSwapChainDesc; + hr = dxgiFactory->CreateSwapChain(device.ptr(), &desc, ppSwapChain); + + if (FAILED(hr)) { + Logger::err("D3D10CreateDevice: Failed to create swap chain"); + return hr; + } + } + + if (ppDevice) { + // Just assume that this succeeds + device->QueryInterface(deviceIID, ppDevice); + } + + if (!ppDevice && !ppSwapChain) + return S_FALSE; + + return S_OK; + } + + + DLLEXPORT HRESULT __stdcall D3D10CreateDevice( + IDXGIAdapter* pAdapter, + D3D10_DRIVER_TYPE DriverType, + HMODULE Software, + UINT Flags, + UINT SDKVersion, + ID3D10Device** ppDevice) { + return D3D10InternalCreateDeviceAndSwapChain( + pAdapter, DriverType, Software, Flags, + D3D10_FEATURE_LEVEL_10_0, SDKVersion, + nullptr, nullptr, + __uuidof(ID3D10Device), + reinterpret_cast(ppDevice)); + } + + + DLLEXPORT HRESULT __stdcall D3D10CreateDevice1( + IDXGIAdapter* pAdapter, + D3D10_DRIVER_TYPE DriverType, + HMODULE Software, + UINT Flags, + D3D10_FEATURE_LEVEL1 HardwareLevel, + UINT SDKVersion, + ID3D10Device1** ppDevice) { + return D3D10InternalCreateDeviceAndSwapChain( + pAdapter, DriverType, Software, Flags, + HardwareLevel, SDKVersion, + nullptr, nullptr, + __uuidof(ID3D10Device1), + reinterpret_cast(ppDevice)); + } + + + DLLEXPORT HRESULT __stdcall D3D10CreateDeviceAndSwapChain( + IDXGIAdapter* pAdapter, + D3D10_DRIVER_TYPE DriverType, + HMODULE Software, + UINT Flags, + UINT SDKVersion, + DXGI_SWAP_CHAIN_DESC* pSwapChainDesc, + IDXGISwapChain** ppSwapChain, + ID3D10Device** ppDevice) { + return D3D10InternalCreateDeviceAndSwapChain( + pAdapter, DriverType, Software, Flags, + D3D10_FEATURE_LEVEL_10_0, SDKVersion, + pSwapChainDesc, ppSwapChain, + __uuidof(ID3D10Device), + reinterpret_cast(ppDevice)); + } + + + DLLEXPORT HRESULT __stdcall D3D10CreateDeviceAndSwapChain1( + IDXGIAdapter* pAdapter, + D3D10_DRIVER_TYPE DriverType, + HMODULE Software, + UINT Flags, + D3D10_FEATURE_LEVEL1 HardwareLevel, + UINT SDKVersion, + DXGI_SWAP_CHAIN_DESC* pSwapChainDesc, + IDXGISwapChain** ppSwapChain, + ID3D10Device1** ppDevice) { + return D3D10InternalCreateDeviceAndSwapChain( + pAdapter, DriverType, Software, Flags, + HardwareLevel, SDKVersion, + pSwapChainDesc, ppSwapChain, + __uuidof(ID3D10Device1), + reinterpret_cast(ppDevice)); + } + + + const char* STDMETHODCALLTYPE D3D10GetVertexShaderProfile (ID3D10Device*) { return "vs_4_1"; } + const char* STDMETHODCALLTYPE D3D10GetGeometryShaderProfile (ID3D10Device*) { return "gs_4_1"; } + const char* STDMETHODCALLTYPE D3D10GetPixelShaderProfile (ID3D10Device*) { return "ps_4_1"; } + + + HRESULT STDMETHODCALLTYPE D3D10CreateBlob(SIZE_T size, LPD3D10BLOB* ppBuffer) { + return D3DCreateBlob(size, ppBuffer); + } + + + HRESULT STDMETHODCALLTYPE D3D10GetInputSignatureBlob( + const void* pShaderBytecode, + SIZE_T BytecodeLength, + ID3D10Blob** ppSignatureBlob) { + return D3DGetInputSignatureBlob( + pShaderBytecode, + BytecodeLength, + ppSignatureBlob); + } + + + HRESULT STDMETHODCALLTYPE D3D10GetOutputSignatureBlob( + const void* pShaderBytecode, + SIZE_T BytecodeLength, + ID3D10Blob** ppSignatureBlob) { + return D3DGetOutputSignatureBlob( + pShaderBytecode, + BytecodeLength, + ppSignatureBlob); + } + + + HRESULT STDMETHODCALLTYPE D3D10ReflectShader( + const void* pShaderBytecode, + SIZE_T BytecodeLength, + ID3D10ShaderReflection** ppReflector) { + static const GUID IID_ID3D11ShaderReflection = + {0x0a233719,0x3960,0x4578,{0x9d,0x7c,0x20,0x3b,0x8b,0x1d,0x9c,0xc1}}; + + InitReturnPtr(ppReflector); + + Com d3d11Reflector = nullptr; + + HRESULT hr = D3DReflect(pShaderBytecode, + BytecodeLength, IID_ID3D11ShaderReflection, + reinterpret_cast(&d3d11Reflector)); + + if (FAILED(hr)) { + Logger::err("D3D10ReflectShader: Failed to create ID3D11ShaderReflection"); + return hr; + } + + *ppReflector = ref(new D3D10ShaderReflection(d3d11Reflector.ptr())); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D10CompileShader( + LPCSTR pSrcData, + SIZE_T SrcDataSize, + LPCSTR pFileName, + const D3D10_SHADER_MACRO* pDefines, + LPD3D10INCLUDE pInclude, + LPCSTR pFunctionName, + LPCSTR pProfile, + UINT Flags, + ID3D10Blob** ppShader, + ID3D10Blob** ppErrorMsgs) { + return D3DCompile(pSrcData, SrcDataSize, pFileName, + pDefines, pInclude, pFunctionName, pProfile, Flags, + 0, ppShader, ppErrorMsgs); + } + + + HRESULT STDMETHODCALLTYPE D3D10CreateEffectFromMemory( + void* pData, + SIZE_T DataSize, + UINT EffectFlags, + ID3D10Device* pDevice, + ID3D10EffectPool* pEffectPool, + ID3D10Effect** ppEffect) { + Logger::warn("D3D10CreateEffectFromMemory: Not implemented"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE D3D10CreateEffectPoolFromMemory( + void* pData, + SIZE_T DataSize, + UINT EffectFlags, + ID3D10Device* pDevice, + ID3D10EffectPool** ppEffectPool) { + Logger::warn("D3D10CreateEffectPoolFromMemory: Not implemented"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE D3D10CompileEffectFromMemory( + void* pData, + SIZE_T DataLength, + LPCSTR pSrcFileName, + const D3D10_SHADER_MACRO* pDefines, + ID3D10Include* pInclude, + UINT ShaderFlags, + UINT EffectFlags, + ID3D10Blob** ppCompiledEffect, + ID3D10Blob** ppErrors) { + Logger::warn("D3D10CompileEffectFromMemory: Not implemented"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE D3D10DisassembleEffect( + ID3D10Effect* pEffect, + BOOL EnableColorCode, + ID3D10Blob** ppDisassembly) { + Logger::warn("D3D10DisassembleEffect: Not implemented"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE D3D10DisassembleShader( + const void* pShader, + SIZE_T BytecodeLength, + BOOL EnableColorCode, + LPCSTR pComments, + ID3D10Blob** ppDisassembly) { + return D3DDisassemble( + pShader, BytecodeLength, + 0, pComments, ppDisassembly); + } + + + HRESULT STDMETHODCALLTYPE D3D10PreprocessShader( + LPCSTR pSrcData, + SIZE_T SrcDataSize, + LPCSTR pFileName, + const D3D10_SHADER_MACRO* pDefines, + LPD3D10INCLUDE pInclude, + ID3D10Blob** ppShaderText, + ID3D10Blob** ppErrorMsgs) { + return D3DPreprocess( + pSrcData, SrcDataSize, + pFileName, pDefines, + pInclude, + ppShaderText, + ppErrorMsgs); + } + + + UINT64 STDMETHODCALLTYPE D3D10GetVersion() { + return 0xa000100041770ull; + } + + + HRESULT STDMETHODCALLTYPE D3D10RegisterLayers() { + return E_NOTIMPL; + } + +} + + diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_multithread.cpp b/utils/dxvk-1.10.3/src/d3d10/d3d10_multithread.cpp new file mode 100644 index 00000000000..65932b53d07 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_multithread.cpp @@ -0,0 +1,60 @@ +#include + +#include "d3d10_device.h" + +namespace dxvk { + + D3D10Multithread::D3D10Multithread( + IUnknown* pParent, + BOOL Protected) + : m_parent (pParent), + m_protected (Protected) { + + } + + + D3D10Multithread::~D3D10Multithread() { + + } + + + ULONG STDMETHODCALLTYPE D3D10Multithread::AddRef() { + return m_parent->AddRef(); + } + + + ULONG STDMETHODCALLTYPE D3D10Multithread::Release() { + return m_parent->Release(); + } + + + HRESULT STDMETHODCALLTYPE D3D10Multithread::QueryInterface( + REFIID riid, + void** ppvObject) { + return m_parent->QueryInterface(riid, ppvObject); + } + + + void STDMETHODCALLTYPE D3D10Multithread::Enter() { + if (m_protected) + m_mutex.lock(); + } + + + void STDMETHODCALLTYPE D3D10Multithread::Leave() { + if (m_protected) + m_mutex.unlock(); + } + + + BOOL STDMETHODCALLTYPE D3D10Multithread::SetMultithreadProtected( + BOOL bMTProtect) { + return std::exchange(m_protected, bMTProtect); + } + + + BOOL STDMETHODCALLTYPE D3D10Multithread::GetMultithreadProtected() { + return m_protected; + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_multithread.h b/utils/dxvk-1.10.3/src/d3d10/d3d10_multithread.h new file mode 100644 index 00000000000..39a736cc0eb --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_multithread.h @@ -0,0 +1,103 @@ +#pragma once + +#include "d3d10_include.h" + +namespace dxvk { + + /** + * \brief Device lock + * + * Lightweight RAII wrapper that implements + * a subset of the functionality provided by + * \c std::unique_lock, with the goal of being + * cheaper to construct and destroy. + */ + class D3D10DeviceLock { + + public: + + D3D10DeviceLock() + : m_mutex(nullptr) { } + + D3D10DeviceLock(sync::RecursiveSpinlock& mutex) + : m_mutex(&mutex) { + mutex.lock(); + } + + D3D10DeviceLock(D3D10DeviceLock&& other) + : m_mutex(other.m_mutex) { + other.m_mutex = nullptr; + } + + D3D10DeviceLock& operator = (D3D10DeviceLock&& other) { + if (m_mutex) + m_mutex->unlock(); + + m_mutex = other.m_mutex; + other.m_mutex = nullptr; + return *this; + } + + ~D3D10DeviceLock() { + if (unlikely(m_mutex != nullptr)) + m_mutex->unlock(); + } + + private: + + sync::RecursiveSpinlock* m_mutex; + + }; + + + /** + * \brief D3D10 device and D3D11 context lock + * + * Can be queried from the D3D10 device or from + * any D3D11 context in order to make individual + * calls thread-safe. Provides methods to lock + * the device or context explicitly. + */ + class D3D10Multithread : public ID3D10Multithread { + + public: + + D3D10Multithread( + IUnknown* pParent, + BOOL Protected); + + ~D3D10Multithread(); + + ULONG STDMETHODCALLTYPE AddRef() final; + + ULONG STDMETHODCALLTYPE Release() final; + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject) final; + + void STDMETHODCALLTYPE Enter() final; + + void STDMETHODCALLTYPE Leave() final; + + BOOL STDMETHODCALLTYPE SetMultithreadProtected( + BOOL bMTProtect) final; + + BOOL STDMETHODCALLTYPE GetMultithreadProtected() final; + + D3D10DeviceLock AcquireLock() { + return unlikely(m_protected) + ? D3D10DeviceLock(m_mutex) + : D3D10DeviceLock(); + } + + private: + + IUnknown* m_parent; + BOOL m_protected; + + sync::RecursiveSpinlock m_mutex; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_query.cpp b/utils/dxvk-1.10.3/src/d3d10/d3d10_query.cpp new file mode 100644 index 00000000000..8730a611e7b --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_query.cpp @@ -0,0 +1,98 @@ +#include "d3d10_query.h" +#include "d3d10_device.h" + +#include "../d3d11/d3d11_device.h" +#include "../d3d11/d3d11_context.h" +#include "../d3d11/d3d11_query.h" + +namespace dxvk { + + HRESULT STDMETHODCALLTYPE D3D10Query::QueryInterface( + REFIID riid, + void** ppvObject) { + return m_d3d11->QueryInterface(riid, ppvObject); + } + + + ULONG STDMETHODCALLTYPE D3D10Query::AddRef() { + return m_d3d11->AddRef(); + } + + + ULONG STDMETHODCALLTYPE D3D10Query::Release() { + return m_d3d11->Release(); + } + + + void STDMETHODCALLTYPE D3D10Query::GetDevice( + ID3D10Device** ppDevice) { + GetD3D10Device(m_d3d11, ppDevice); + } + + + HRESULT STDMETHODCALLTYPE D3D10Query::GetPrivateData( + REFGUID guid, + UINT* pDataSize, + void* pData) { + return m_d3d11->GetPrivateData(guid, pDataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D10Query::SetPrivateData( + REFGUID guid, + UINT DataSize, + const void* pData) { + return m_d3d11->SetPrivateData(guid, DataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D10Query::SetPrivateDataInterface( + REFGUID guid, + const IUnknown* pData) { + return m_d3d11->SetPrivateDataInterface(guid, pData); + } + + + void STDMETHODCALLTYPE D3D10Query::Begin() { + Com ctx; + GetD3D11Context(m_d3d11, &ctx); + + ctx->Begin(m_d3d11); + } + + + void STDMETHODCALLTYPE D3D10Query::End() { + Com ctx; + GetD3D11Context(m_d3d11, &ctx); + + ctx->End(m_d3d11); + } + + + HRESULT STDMETHODCALLTYPE D3D10Query::GetData( + void* pData, + UINT DataSize, + UINT GetDataFlags) { + Com ctx; + GetD3D11Context(m_d3d11, &ctx); + + return ctx->GetData(m_d3d11, + pData, DataSize, GetDataFlags); + } + + + UINT STDMETHODCALLTYPE D3D10Query::GetDataSize() { + return m_d3d11->GetDataSize(); + } + + + void STDMETHODCALLTYPE D3D10Query::GetDesc( + D3D10_QUERY_DESC* pDesc) { + D3D11_QUERY_DESC d3d11Desc; + m_d3d11->GetDesc(&d3d11Desc); + + pDesc->Query = D3D10_QUERY(d3d11Desc.Query); + pDesc->MiscFlags = d3d11Desc.MiscFlags; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_query.h b/utils/dxvk-1.10.3/src/d3d10/d3d10_query.h new file mode 100644 index 00000000000..c189e97987a --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_query.h @@ -0,0 +1,68 @@ +#pragma once + +#include "d3d10_util.h" + +namespace dxvk { + + class D3D10Device; + class D3D11Device; + class D3D11DeviceContext; + class D3D11Query; + + class D3D10Query : public ID3D10Predicate { + + public: + + D3D10Query(D3D11Query* pParent) + : m_d3d11(pParent) { } + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + ULONG STDMETHODCALLTYPE AddRef(); + + ULONG STDMETHODCALLTYPE Release(); + + void STDMETHODCALLTYPE GetDevice( + ID3D10Device** ppDevice); + + HRESULT STDMETHODCALLTYPE GetPrivateData( + REFGUID guid, + UINT* pDataSize, + void* pData); + + HRESULT STDMETHODCALLTYPE SetPrivateData( + REFGUID guid, + UINT DataSize, + const void* pData); + + HRESULT STDMETHODCALLTYPE SetPrivateDataInterface( + REFGUID guid, + const IUnknown* pData); + + void STDMETHODCALLTYPE Begin(); + + void STDMETHODCALLTYPE End(); + + HRESULT STDMETHODCALLTYPE GetData( + void* pData, + UINT DataSize, + UINT GetDataFlags); + + UINT STDMETHODCALLTYPE GetDataSize(); + + void STDMETHODCALLTYPE GetDesc( + D3D10_QUERY_DESC* pDesc); + + D3D11Query* GetD3D11Iface() { + return m_d3d11; + } + + private: + + D3D11Query* m_d3d11; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_rasterizer.cpp b/utils/dxvk-1.10.3/src/d3d10/d3d10_rasterizer.cpp new file mode 100644 index 00000000000..42de25ec913 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_rasterizer.cpp @@ -0,0 +1,60 @@ +#include "d3d10_rasterizer.h" + +#include "../d3d11/d3d11_device.h" +#include "../d3d11/d3d11_rasterizer.h" + +namespace dxvk { + + HRESULT STDMETHODCALLTYPE D3D10RasterizerState::QueryInterface( + REFIID riid, + void** ppvObject) { + return m_d3d11->QueryInterface(riid, ppvObject); + } + + + ULONG STDMETHODCALLTYPE D3D10RasterizerState::AddRef() { + return m_d3d11->AddRef(); + } + + + ULONG STDMETHODCALLTYPE D3D10RasterizerState::Release() { + return m_d3d11->Release(); + } + + + void STDMETHODCALLTYPE D3D10RasterizerState::GetDevice( + ID3D10Device** ppDevice) { + GetD3D10Device(m_d3d11, ppDevice); + } + + + HRESULT STDMETHODCALLTYPE D3D10RasterizerState::GetPrivateData( + REFGUID guid, + UINT* pDataSize, + void* pData) { + return m_d3d11->GetPrivateData(guid, pDataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D10RasterizerState::SetPrivateData( + REFGUID guid, + UINT DataSize, + const void* pData) { + return m_d3d11->SetPrivateData(guid, DataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D10RasterizerState::SetPrivateDataInterface( + REFGUID guid, + const IUnknown* pData) { + return m_d3d11->SetPrivateDataInterface(guid, pData); + } + + + void STDMETHODCALLTYPE D3D10RasterizerState::GetDesc( + D3D10_RASTERIZER_DESC* pDesc) { + static_assert(sizeof(D3D10_RASTERIZER_DESC) == sizeof(D3D11_RASTERIZER_DESC)); + m_d3d11->GetDesc(reinterpret_cast(pDesc)); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_rasterizer.h b/utils/dxvk-1.10.3/src/d3d10/d3d10_rasterizer.h new file mode 100644 index 00000000000..9ccad042caa --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_rasterizer.h @@ -0,0 +1,55 @@ +#pragma once + +#include "d3d10_util.h" + +namespace dxvk { + + class D3D11RasterizerState; + class D3D11Device; + + class D3D10RasterizerState : public ID3D10RasterizerState { + + public: + + D3D10RasterizerState(D3D11RasterizerState* pParent) + : m_d3d11(pParent) { } + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + ULONG STDMETHODCALLTYPE AddRef(); + + ULONG STDMETHODCALLTYPE Release(); + + void STDMETHODCALLTYPE GetDevice( + ID3D10Device** ppDevice); + + HRESULT STDMETHODCALLTYPE GetPrivateData( + REFGUID guid, + UINT* pDataSize, + void* pData); + + HRESULT STDMETHODCALLTYPE SetPrivateData( + REFGUID guid, + UINT DataSize, + const void* pData); + + HRESULT STDMETHODCALLTYPE SetPrivateDataInterface( + REFGUID guid, + const IUnknown* pData); + + void STDMETHODCALLTYPE GetDesc( + D3D10_RASTERIZER_DESC* pDesc); + + D3D11RasterizerState* GetD3D11Iface() { + return m_d3d11; + } + + private: + + D3D11RasterizerState* m_d3d11; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_reflection.cpp b/utils/dxvk-1.10.3/src/d3d10/d3d10_reflection.cpp new file mode 100644 index 00000000000..d49dea90570 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_reflection.cpp @@ -0,0 +1,326 @@ +#include "d3d10_reflection.h" + +namespace dxvk { + + D3D10ShaderReflectionType::D3D10ShaderReflectionType( + ID3D11ShaderReflectionType* d3d11) + : m_d3d11(d3d11) { + + } + + + D3D10ShaderReflectionType::~D3D10ShaderReflectionType() { + + } + + + HRESULT STDMETHODCALLTYPE D3D10ShaderReflectionType::GetDesc( + D3D10_SHADER_TYPE_DESC* pDesc) { + D3D11_SHADER_TYPE_DESC d3d11Desc; + HRESULT hr = m_d3d11->GetDesc(&d3d11Desc); + + if (FAILED(hr)) + return hr; + + pDesc->Class = D3D10_SHADER_VARIABLE_CLASS(d3d11Desc.Class); + pDesc->Type = D3D10_SHADER_VARIABLE_TYPE (d3d11Desc.Type); + pDesc->Rows = d3d11Desc.Rows; + pDesc->Columns = d3d11Desc.Columns; + pDesc->Elements = d3d11Desc.Elements; + pDesc->Members = d3d11Desc.Members; + pDesc->Offset = d3d11Desc.Offset; + return S_OK; + } + + + ID3D10ShaderReflectionType* STDMETHODCALLTYPE D3D10ShaderReflectionType::GetMemberTypeByIndex( + UINT Index) { + return FindMemberType(m_d3d11->GetMemberTypeByIndex(Index)); + } + + + ID3D10ShaderReflectionType* STDMETHODCALLTYPE D3D10ShaderReflectionType::GetMemberTypeByName( + const char* Name) { + return FindMemberType(m_d3d11->GetMemberTypeByName(Name)); + } + + + const char* STDMETHODCALLTYPE D3D10ShaderReflectionType::GetMemberTypeName( + UINT Index) { + return m_d3d11->GetMemberTypeName(Index); + } + + + ID3D10ShaderReflectionType* D3D10ShaderReflectionType::FindMemberType( + ID3D11ShaderReflectionType* pMemberType) { + if (!pMemberType) + return nullptr; + + auto entry = m_members.find(pMemberType); + + if (entry == m_members.end()) { + entry = m_members.insert({ pMemberType, + std::make_unique(pMemberType) }).first; + } + + return entry->second.get(); + } + + + D3D10ShaderReflectionVariable::D3D10ShaderReflectionVariable(ID3D11ShaderReflectionVariable* d3d11) + : m_d3d11(d3d11), m_type(m_d3d11->GetType()) { + + } + + + D3D10ShaderReflectionVariable::~D3D10ShaderReflectionVariable() { + + } + + + HRESULT STDMETHODCALLTYPE D3D10ShaderReflectionVariable::GetDesc( + D3D10_SHADER_VARIABLE_DESC* pDesc) { + D3D11_SHADER_VARIABLE_DESC d3d11Desc; + HRESULT hr = m_d3d11->GetDesc(&d3d11Desc); + + if (FAILED(hr)) + return hr; + + pDesc->Name = d3d11Desc.Name; + pDesc->StartOffset = d3d11Desc.StartOffset; + pDesc->Size = d3d11Desc.Size; + pDesc->uFlags = d3d11Desc.uFlags; + pDesc->DefaultValue = d3d11Desc.DefaultValue; + return S_OK; + } + + + ID3D10ShaderReflectionType* STDMETHODCALLTYPE D3D10ShaderReflectionVariable::GetType() { + return &m_type; + } + + + D3D10ShaderReflectionConstantBuffer::D3D10ShaderReflectionConstantBuffer( + ID3D11ShaderReflectionConstantBuffer* d3d11) + : m_d3d11(d3d11) { + + } + + + D3D10ShaderReflectionConstantBuffer::~D3D10ShaderReflectionConstantBuffer() { + + } + + + HRESULT STDMETHODCALLTYPE D3D10ShaderReflectionConstantBuffer::GetDesc( + D3D10_SHADER_BUFFER_DESC* pDesc) { + D3D11_SHADER_BUFFER_DESC d3d11Desc; + HRESULT hr = m_d3d11->GetDesc(&d3d11Desc); + + if (FAILED(hr)) + return hr; + + pDesc->Name = d3d11Desc.Name; + pDesc->Type = D3D10_CBUFFER_TYPE(d3d11Desc.Type); + pDesc->Variables = d3d11Desc.Variables; + pDesc->Size = d3d11Desc.Size; + pDesc->uFlags = d3d11Desc.uFlags; + return S_OK; + } + + + ID3D10ShaderReflectionVariable* STDMETHODCALLTYPE D3D10ShaderReflectionConstantBuffer::GetVariableByIndex( + UINT Index) { + return FindVariable(m_d3d11->GetVariableByIndex(Index)); + } + + + ID3D10ShaderReflectionVariable* STDMETHODCALLTYPE D3D10ShaderReflectionConstantBuffer::GetVariableByName( + LPCSTR Name) { + return FindVariable(m_d3d11->GetVariableByName(Name)); + } + + + ID3D10ShaderReflectionVariable* D3D10ShaderReflectionConstantBuffer::FindVariable( + ID3D11ShaderReflectionVariable* pVariable) { + if (!pVariable) + return nullptr; + + auto entry = m_variables.find(pVariable); + + if (entry == m_variables.end()) { + entry = m_variables.emplace( + std::piecewise_construct, + std::forward_as_tuple(pVariable), + std::forward_as_tuple(pVariable)).first; + } + + return &entry->second; + } + + + D3D10ShaderReflection::D3D10ShaderReflection(ID3D11ShaderReflection* d3d11) + : m_d3d11(d3d11) { + + } + + + D3D10ShaderReflection::~D3D10ShaderReflection() { + + } + + + HRESULT STDMETHODCALLTYPE D3D10ShaderReflection::QueryInterface( + REFIID riid, + void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + static const GUID IID_ID3D10ShaderReflection + = {0xd40e20b6,0xf8f7,0x42ad,{0xab,0x20,0x4b,0xaf,0x8f,0x15,0xdf,0xaa}}; + + if (riid == __uuidof(IUnknown) + || riid == IID_ID3D10ShaderReflection) { + *ppvObject = ref(this); + return S_OK; + } + + return E_NOINTERFACE; + } + + + HRESULT STDMETHODCALLTYPE D3D10ShaderReflection::GetDesc( + D3D10_SHADER_DESC* pDesc) { + D3D11_SHADER_DESC d3d11Desc; + HRESULT hr = m_d3d11->GetDesc(&d3d11Desc); + + if (FAILED(hr)) + return hr; + + pDesc->Version = d3d11Desc.Version; + pDesc->Creator = d3d11Desc.Creator; + pDesc->Flags = d3d11Desc.Flags; + pDesc->ConstantBuffers = d3d11Desc.ConstantBuffers; + pDesc->BoundResources = d3d11Desc.BoundResources; + pDesc->InputParameters = d3d11Desc.InputParameters; + pDesc->OutputParameters = d3d11Desc.OutputParameters; + pDesc->InstructionCount = d3d11Desc.InstructionCount; + pDesc->TempRegisterCount = d3d11Desc.TempRegisterCount; + pDesc->TempArrayCount = d3d11Desc.TempArrayCount; + pDesc->DefCount = d3d11Desc.DefCount; + pDesc->DclCount = d3d11Desc.DclCount; + pDesc->TextureNormalInstructions = d3d11Desc.TextureNormalInstructions; + pDesc->TextureLoadInstructions = d3d11Desc.TextureLoadInstructions; + pDesc->TextureCompInstructions = d3d11Desc.TextureCompInstructions; + pDesc->TextureBiasInstructions = d3d11Desc.TextureBiasInstructions; + pDesc->TextureGradientInstructions = d3d11Desc.TextureGradientInstructions; + pDesc->FloatInstructionCount = d3d11Desc.FloatInstructionCount; + pDesc->IntInstructionCount = d3d11Desc.IntInstructionCount; + pDesc->UintInstructionCount = d3d11Desc.UintInstructionCount; + pDesc->StaticFlowControlCount = d3d11Desc.StaticFlowControlCount; + pDesc->DynamicFlowControlCount = d3d11Desc.DynamicFlowControlCount; + pDesc->MacroInstructionCount = d3d11Desc.MacroInstructionCount; + pDesc->ArrayInstructionCount = d3d11Desc.ArrayInstructionCount; + pDesc->CutInstructionCount = d3d11Desc.CutInstructionCount; + pDesc->EmitInstructionCount = d3d11Desc.EmitInstructionCount; + pDesc->GSOutputTopology = D3D10_PRIMITIVE_TOPOLOGY(d3d11Desc.GSOutputTopology); + pDesc->GSMaxOutputVertexCount = d3d11Desc.GSMaxOutputVertexCount; + return S_OK; + } + + + ID3D10ShaderReflectionConstantBuffer* STDMETHODCALLTYPE + D3D10ShaderReflection::GetConstantBufferByIndex( + UINT Index) { + return FindConstantBuffer(m_d3d11->GetConstantBufferByIndex(Index)); + } + + + ID3D10ShaderReflectionConstantBuffer* STDMETHODCALLTYPE + D3D10ShaderReflection::GetConstantBufferByName( + LPCSTR Name) { + return FindConstantBuffer(m_d3d11->GetConstantBufferByName(Name)); + } + + + HRESULT STDMETHODCALLTYPE D3D10ShaderReflection::GetInputParameterDesc( + UINT ParameterIndex, + D3D10_SIGNATURE_PARAMETER_DESC* pDesc) { + D3D11_SIGNATURE_PARAMETER_DESC d3d11Desc; + HRESULT hr = m_d3d11->GetInputParameterDesc(ParameterIndex, &d3d11Desc); + + if (FAILED(hr)) + return hr; + + ConvertSignatureParameterDesc(&d3d11Desc, pDesc); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D10ShaderReflection::GetOutputParameterDesc( + UINT ParameterIndex, + D3D10_SIGNATURE_PARAMETER_DESC* pDesc) { + D3D11_SIGNATURE_PARAMETER_DESC d3d11Desc; + HRESULT hr = m_d3d11->GetOutputParameterDesc(ParameterIndex, &d3d11Desc); + + if (FAILED(hr)) + return hr; + + ConvertSignatureParameterDesc(&d3d11Desc, pDesc); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D10ShaderReflection::GetResourceBindingDesc( + UINT ResourceIndex, + D3D10_SHADER_INPUT_BIND_DESC* pDesc) { + D3D11_SHADER_INPUT_BIND_DESC d3d11Desc; + HRESULT hr = m_d3d11->GetResourceBindingDesc( + ResourceIndex, &d3d11Desc); + + if (FAILED(hr)) + return hr; + + pDesc->Name = d3d11Desc.Name; + pDesc->Type = D3D10_SHADER_INPUT_TYPE(d3d11Desc.Type); + pDesc->BindPoint = d3d11Desc.BindPoint; + pDesc->BindCount = d3d11Desc.BindCount; + pDesc->uFlags = d3d11Desc.uFlags; + pDesc->ReturnType = D3D10_RESOURCE_RETURN_TYPE(d3d11Desc.ReturnType); + pDesc->Dimension = D3D10_SRV_DIMENSION (d3d11Desc.Dimension); + pDesc->NumSamples = d3d11Desc.NumSamples; + return S_OK; + } + + + ID3D10ShaderReflectionConstantBuffer* D3D10ShaderReflection::FindConstantBuffer( + ID3D11ShaderReflectionConstantBuffer* pConstantBuffer) { + if (!pConstantBuffer) + return nullptr; + + auto entry = m_constantBuffers.find(pConstantBuffer); + + if (entry == m_constantBuffers.end()) { + entry = m_constantBuffers.emplace( + std::piecewise_construct, + std::forward_as_tuple(pConstantBuffer), + std::forward_as_tuple(pConstantBuffer)).first; + } + + return &entry->second; + } + + + void D3D10ShaderReflection::ConvertSignatureParameterDesc( + const D3D11_SIGNATURE_PARAMETER_DESC* pSrcDesc, + D3D10_SIGNATURE_PARAMETER_DESC* pDstDesc) { + pDstDesc->SemanticName = pSrcDesc->SemanticName; + pDstDesc->SemanticIndex = pSrcDesc->SemanticIndex; + pDstDesc->Register = pSrcDesc->Register; + pDstDesc->SystemValueType = D3D10_NAME(pSrcDesc->SystemValueType); + pDstDesc->ComponentType = D3D10_REGISTER_COMPONENT_TYPE(pSrcDesc->ComponentType); + pDstDesc->Mask = pSrcDesc->Mask; + pDstDesc->ReadWriteMask = pSrcDesc->ReadWriteMask; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_reflection.h b/utils/dxvk-1.10.3/src/d3d10/d3d10_reflection.h new file mode 100644 index 00000000000..b25a92cebb5 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_reflection.h @@ -0,0 +1,163 @@ +#pragma once + +#include +#include + +#include "d3d10_include.h" + +#include +#include + +namespace dxvk { + + class D3D10ShaderReflectionType : public ID3D10ShaderReflectionType { + + public: + + D3D10ShaderReflectionType( + ID3D11ShaderReflectionType* d3d11); + + ~D3D10ShaderReflectionType(); + + HRESULT STDMETHODCALLTYPE GetDesc( + D3D10_SHADER_TYPE_DESC* pDesc); + + ID3D10ShaderReflectionType* STDMETHODCALLTYPE GetMemberTypeByIndex( + UINT Index); + + ID3D10ShaderReflectionType* STDMETHODCALLTYPE GetMemberTypeByName( + const char* Name); + + const char* STDMETHODCALLTYPE GetMemberTypeName( + UINT Index); + + ID3D11ShaderReflectionType* GetD3D11Iface() { + return m_d3d11; + } + + private: + + ID3D11ShaderReflectionType* m_d3d11; + + std::unordered_map< + ID3D11ShaderReflectionType*, + std::unique_ptr> m_members; + + ID3D10ShaderReflectionType* FindMemberType( + ID3D11ShaderReflectionType* pMemberType); + + }; + + + class D3D10ShaderReflectionVariable : public ID3D10ShaderReflectionVariable { + + public: + + D3D10ShaderReflectionVariable( + ID3D11ShaderReflectionVariable* d3d11); + + ~D3D10ShaderReflectionVariable(); + + HRESULT STDMETHODCALLTYPE GetDesc( + D3D10_SHADER_VARIABLE_DESC* pDesc); + + ID3D10ShaderReflectionType* STDMETHODCALLTYPE GetType(); + + ID3D11ShaderReflectionVariable* STDMETHODCALLTYPE GetD3D11Iface() { + return m_d3d11; + } + + private: + + ID3D11ShaderReflectionVariable* m_d3d11; + D3D10ShaderReflectionType m_type; + + }; + + + class D3D10ShaderReflectionConstantBuffer : public ID3D10ShaderReflectionConstantBuffer { + + public: + + D3D10ShaderReflectionConstantBuffer( + ID3D11ShaderReflectionConstantBuffer* d3d11); + + ~D3D10ShaderReflectionConstantBuffer(); + + HRESULT STDMETHODCALLTYPE GetDesc( + D3D10_SHADER_BUFFER_DESC* pDesc); + + ID3D10ShaderReflectionVariable* STDMETHODCALLTYPE GetVariableByIndex( + UINT Index); + + ID3D10ShaderReflectionVariable* STDMETHODCALLTYPE GetVariableByName( + LPCSTR Name); + + ID3D11ShaderReflectionConstantBuffer* STDMETHODCALLTYPE GetD3D11Iface() { + return m_d3d11; + } + + private: + + ID3D11ShaderReflectionConstantBuffer* m_d3d11; + + std::unordered_map< + ID3D11ShaderReflectionVariable*, + D3D10ShaderReflectionVariable> m_variables; + + ID3D10ShaderReflectionVariable* FindVariable( + ID3D11ShaderReflectionVariable* pVariable); + + }; + + + class D3D10ShaderReflection : public ComObject { + + public: + + D3D10ShaderReflection(ID3D11ShaderReflection* d3d11); + ~D3D10ShaderReflection(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + HRESULT STDMETHODCALLTYPE GetDesc( + D3D10_SHADER_DESC* pDesc); + + ID3D10ShaderReflectionConstantBuffer* STDMETHODCALLTYPE GetConstantBufferByIndex( + UINT Index); + + ID3D10ShaderReflectionConstantBuffer* STDMETHODCALLTYPE GetConstantBufferByName( + LPCSTR Name); + + HRESULT STDMETHODCALLTYPE GetInputParameterDesc( + UINT ParameterIndex, + D3D10_SIGNATURE_PARAMETER_DESC* pDesc); + + HRESULT STDMETHODCALLTYPE GetOutputParameterDesc( + UINT ParameterIndex, + D3D10_SIGNATURE_PARAMETER_DESC* pDesc); + + HRESULT STDMETHODCALLTYPE GetResourceBindingDesc( + UINT ResourceIndex, + D3D10_SHADER_INPUT_BIND_DESC* pDesc); + + private: + + Com m_d3d11; + + std::unordered_map< + ID3D11ShaderReflectionConstantBuffer*, + D3D10ShaderReflectionConstantBuffer> m_constantBuffers; + + ID3D10ShaderReflectionConstantBuffer* FindConstantBuffer( + ID3D11ShaderReflectionConstantBuffer* pConstantBuffer); + + void ConvertSignatureParameterDesc( + const D3D11_SIGNATURE_PARAMETER_DESC* pSrcDesc, + D3D10_SIGNATURE_PARAMETER_DESC* pDstDesc); + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_sampler.cpp b/utils/dxvk-1.10.3/src/d3d10/d3d10_sampler.cpp new file mode 100644 index 00000000000..3db1450a190 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_sampler.cpp @@ -0,0 +1,73 @@ +#include "d3d10_sampler.h" + +#include "../d3d11/d3d11_device.h" +#include "../d3d11/d3d11_sampler.h" + +namespace dxvk { + + HRESULT STDMETHODCALLTYPE D3D10SamplerState::QueryInterface( + REFIID riid, + void** ppvObject) { + return m_d3d11->QueryInterface(riid, ppvObject); + } + + + ULONG STDMETHODCALLTYPE D3D10SamplerState::AddRef() { + return m_d3d11->AddRef(); + } + + + ULONG STDMETHODCALLTYPE D3D10SamplerState::Release() { + return m_d3d11->Release(); + } + + + void STDMETHODCALLTYPE D3D10SamplerState::GetDevice( + ID3D10Device** ppDevice) { + GetD3D10Device(m_d3d11, ppDevice); + } + + + HRESULT STDMETHODCALLTYPE D3D10SamplerState::GetPrivateData( + REFGUID guid, + UINT* pDataSize, + void* pData) { + return m_d3d11->GetPrivateData(guid, pDataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D10SamplerState::SetPrivateData( + REFGUID guid, + UINT DataSize, + const void* pData) { + return m_d3d11->SetPrivateData(guid, DataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D10SamplerState::SetPrivateDataInterface( + REFGUID guid, + const IUnknown* pData) { + return m_d3d11->SetPrivateDataInterface(guid, pData); + } + + + void STDMETHODCALLTYPE D3D10SamplerState::GetDesc( + D3D10_SAMPLER_DESC* pDesc) { + D3D11_SAMPLER_DESC d3d11Desc; + m_d3d11->GetDesc(&d3d11Desc); + + pDesc->Filter = D3D10_FILTER(d3d11Desc.Filter); + pDesc->AddressU = D3D10_TEXTURE_ADDRESS_MODE(d3d11Desc.AddressU); + pDesc->AddressV = D3D10_TEXTURE_ADDRESS_MODE(d3d11Desc.AddressV); + pDesc->AddressW = D3D10_TEXTURE_ADDRESS_MODE(d3d11Desc.AddressW); + pDesc->MipLODBias = d3d11Desc.MipLODBias; + pDesc->MaxAnisotropy = d3d11Desc.MaxAnisotropy; + pDesc->ComparisonFunc = D3D10_COMPARISON_FUNC(d3d11Desc.ComparisonFunc); + pDesc->MinLOD = d3d11Desc.MinLOD; + pDesc->MaxLOD = d3d11Desc.MaxLOD; + + for (uint32_t i = 0; i < 4; i++) + pDesc->BorderColor[i] = d3d11Desc.BorderColor[i]; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_sampler.h b/utils/dxvk-1.10.3/src/d3d10/d3d10_sampler.h new file mode 100644 index 00000000000..82633e84a63 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_sampler.h @@ -0,0 +1,55 @@ +#pragma once + +#include "d3d10_util.h" + +namespace dxvk { + + class D3D11Device; + class D3D11SamplerState; + + class D3D10SamplerState : public ID3D10SamplerState { + + public: + + D3D10SamplerState(D3D11SamplerState* pParent) + : m_d3d11(pParent) { } + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + ULONG STDMETHODCALLTYPE AddRef(); + + ULONG STDMETHODCALLTYPE Release(); + + void STDMETHODCALLTYPE GetDevice( + ID3D10Device** ppDevice); + + HRESULT STDMETHODCALLTYPE GetPrivateData( + REFGUID guid, + UINT* pDataSize, + void* pData); + + HRESULT STDMETHODCALLTYPE SetPrivateData( + REFGUID guid, + UINT DataSize, + const void* pData); + + HRESULT STDMETHODCALLTYPE SetPrivateDataInterface( + REFGUID guid, + const IUnknown* pData); + + void STDMETHODCALLTYPE GetDesc( + D3D10_SAMPLER_DESC* pDesc); + + D3D11SamplerState* GetD3D11Iface() { + return m_d3d11; + } + + private: + + D3D11SamplerState* m_d3d11; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_shader.h b/utils/dxvk-1.10.3/src/d3d10/d3d10_shader.h new file mode 100644 index 00000000000..01176a22c82 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_shader.h @@ -0,0 +1,78 @@ +#pragma once + +#include "d3d10_util.h" + +namespace dxvk { + + template + class D3D11Shader; + + template + class D3D10Shader : public D3D10Interface { + using D3D11ShaderClass = D3D11Shader; + public: + + D3D10Shader(D3D11Shader* pParent) + : m_d3d11(pParent) { } + + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject) { + return m_d3d11->QueryInterface(riid, ppvObject); + } + + + ULONG STDMETHODCALLTYPE AddRef() { + return m_d3d11->AddRef(); + } + + + ULONG STDMETHODCALLTYPE Release() { + return m_d3d11->Release(); + } + + + void STDMETHODCALLTYPE GetDevice( + ID3D10Device** ppDevice) { + GetD3D10Device(m_d3d11, ppDevice); + } + + + HRESULT STDMETHODCALLTYPE GetPrivateData( + REFGUID guid, + UINT* pDataSize, + void* pData) { + return m_d3d11->GetPrivateData(guid, pDataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE SetPrivateData( + REFGUID guid, + UINT DataSize, + const void* pData) { + return m_d3d11->SetPrivateData(guid, DataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE SetPrivateDataInterface( + REFGUID guid, + const IUnknown* pData) { + return m_d3d11->SetPrivateDataInterface(guid, pData); + } + + D3D11ShaderClass* GetD3D11Iface() { + return m_d3d11; + } + + private: + + D3D11ShaderClass* m_d3d11; + + }; + + using D3D10VertexShader = D3D10Shader; + using D3D10GeometryShader = D3D10Shader; + using D3D10PixelShader = D3D10Shader; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_state_block.cpp b/utils/dxvk-1.10.3/src/d3d10/d3d10_state_block.cpp new file mode 100644 index 00000000000..af628eb465f --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_state_block.cpp @@ -0,0 +1,432 @@ +#include "d3d10_state_block.h" + +#define MAKE_STATE_TYPE(field, count) { offsetof(D3D10_STATE_BLOCK_MASK, field), count } + +namespace dxvk { + + static const std::array, 24> g_stateTypes = {{ + MAKE_STATE_TYPE(SOBuffers, 1), + MAKE_STATE_TYPE(OMRenderTargets, 1), + MAKE_STATE_TYPE(OMDepthStencilState, 1), + MAKE_STATE_TYPE(OMBlendState, 1), + MAKE_STATE_TYPE(VS, 1), + MAKE_STATE_TYPE(VSSamplers, D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT), + MAKE_STATE_TYPE(VSShaderResources, D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT), + MAKE_STATE_TYPE(VSConstantBuffers, D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT), + MAKE_STATE_TYPE(GS, 1), + MAKE_STATE_TYPE(GSSamplers, D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT), + MAKE_STATE_TYPE(GSShaderResources, D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT), + MAKE_STATE_TYPE(GSConstantBuffers, D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT), + MAKE_STATE_TYPE(PS, 1), + MAKE_STATE_TYPE(PSSamplers, D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT), + MAKE_STATE_TYPE(PSShaderResources, D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT), + MAKE_STATE_TYPE(PSConstantBuffers, D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT), + MAKE_STATE_TYPE(IAVertexBuffers, D3D10_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT), + MAKE_STATE_TYPE(IAIndexBuffer, 1), + MAKE_STATE_TYPE(IAInputLayout, 1), + MAKE_STATE_TYPE(IAPrimitiveTopology, 1), + MAKE_STATE_TYPE(RSViewports, 1), + MAKE_STATE_TYPE(RSScissorRects, 1), + MAKE_STATE_TYPE(RSRasterizerState, 1), + MAKE_STATE_TYPE(Predication, 1), + }}; + + + D3D10StateBlock::D3D10StateBlock( + ID3D10Device* pDevice, + const D3D10_STATE_BLOCK_MASK* pMask) + : m_device(pDevice), m_mask(*pMask) { + + } + + + D3D10StateBlock::~D3D10StateBlock() { + + } + + + HRESULT STDMETHODCALLTYPE D3D10StateBlock::QueryInterface( + REFIID riid, + void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(ID3D10StateBlock)) { + *ppvObject = ref(this); + return S_OK; + } + + Logger::warn("D3D10StateBlock::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + HRESULT STDMETHODCALLTYPE D3D10StateBlock::Capture() { + m_state = D3D10_STATE_BLOCK_STATE(); + + if (TestBit(&m_mask.VS, 0)) m_device->VSGetShader(&m_state.vs); + if (TestBit(&m_mask.GS, 0)) m_device->GSGetShader(&m_state.gs); + if (TestBit(&m_mask.PS, 0)) m_device->PSGetShader(&m_state.ps); + + for (uint32_t i = 0; i < D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT; i++) { + if (TestBit(m_mask.VSSamplers, i)) m_device->VSGetSamplers(i, 1, &m_state.vsSso[i]); + if (TestBit(m_mask.GSSamplers, i)) m_device->GSGetSamplers(i, 1, &m_state.gsSso[i]); + if (TestBit(m_mask.PSSamplers, i)) m_device->PSGetSamplers(i, 1, &m_state.psSso[i]); + } + + for (uint32_t i = 0; i < D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; i++) { + if (TestBit(m_mask.VSShaderResources, i)) m_device->VSGetShaderResources(i, 1, &m_state.vsSrv[i]); + if (TestBit(m_mask.GSShaderResources, i)) m_device->GSGetShaderResources(i, 1, &m_state.gsSrv[i]); + if (TestBit(m_mask.PSShaderResources, i)) m_device->PSGetShaderResources(i, 1, &m_state.psSrv[i]); + } + + for (uint32_t i = 0; i < D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; i++) { + if (TestBit(m_mask.VSConstantBuffers, i)) m_device->VSGetConstantBuffers(i, 1, &m_state.vsCbo[i]); + if (TestBit(m_mask.GSConstantBuffers, i)) m_device->GSGetConstantBuffers(i, 1, &m_state.gsCbo[i]); + if (TestBit(m_mask.PSConstantBuffers, i)) m_device->PSGetConstantBuffers(i, 1, &m_state.psCbo[i]); + } + + for (uint32_t i = 0; i < D3D10_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; i++) { + if (TestBit(m_mask.IAVertexBuffers, i)) { + m_device->IAGetVertexBuffers(i, 1, + &m_state.iaVertexBuffers[i], + &m_state.iaVertexOffsets[i], + &m_state.iaVertexStrides[i]); + } + } + + if (TestBit(&m_mask.IAIndexBuffer, 0)) { + m_device->IAGetIndexBuffer( + &m_state.iaIndexBuffer, + &m_state.iaIndexFormat, + &m_state.iaIndexOffset); + } + + if (TestBit(&m_mask.IAInputLayout, 0)) + m_device->IAGetInputLayout(&m_state.iaInputLayout); + + if (TestBit(&m_mask.IAPrimitiveTopology, 0)) + m_device->IAGetPrimitiveTopology(&m_state.iaTopology); + + if (TestBit(&m_mask.OMRenderTargets, 0)) { + m_device->OMGetRenderTargets( + D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT, + &m_state.omRtv[0], &m_state.omDsv); + } + + if (TestBit(&m_mask.OMDepthStencilState, 0)) { + m_device->OMGetDepthStencilState( + &m_state.omDepthStencilState, + &m_state.omStencilRef); + } + + if (TestBit(&m_mask.OMBlendState, 0)) { + m_device->OMGetBlendState( + &m_state.omBlendState, + m_state.omBlendFactor, + &m_state.omSampleMask); + } + + if (TestBit(&m_mask.RSViewports, 0)) { + m_device->RSGetViewports(&m_state.rsViewportCount, nullptr); + m_device->RSGetViewports(&m_state.rsViewportCount, m_state.rsViewports); + } + + if (TestBit(&m_mask.RSScissorRects, 0)) { + m_device->RSGetScissorRects(&m_state.rsScissorCount, nullptr); + m_device->RSGetScissorRects(&m_state.rsScissorCount, m_state.rsScissors); + } + + if (TestBit(&m_mask.RSRasterizerState, 0)) + m_device->RSGetState(&m_state.rsState); + + if (TestBit(&m_mask.SOBuffers, 0)) { + m_device->SOGetTargets( + D3D10_SO_BUFFER_SLOT_COUNT, + &m_state.soBuffers[0], + &m_state.soOffsets[0]); + } + + if (TestBit(&m_mask.Predication, 0)) + m_device->GetPredication(&m_state.predicate, &m_state.predicateInvert); + + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D10StateBlock::Apply() { + if (TestBit(&m_mask.VS, 0)) m_device->VSSetShader(m_state.vs.ptr()); + if (TestBit(&m_mask.GS, 0)) m_device->GSSetShader(m_state.gs.ptr()); + if (TestBit(&m_mask.PS, 0)) m_device->PSSetShader(m_state.ps.ptr()); + + for (uint32_t i = 0; i < D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT; i++) { + if (TestBit(m_mask.VSSamplers, i)) m_device->VSSetSamplers(i, 1, &m_state.vsSso[i]); + if (TestBit(m_mask.GSSamplers, i)) m_device->GSSetSamplers(i, 1, &m_state.gsSso[i]); + if (TestBit(m_mask.PSSamplers, i)) m_device->PSSetSamplers(i, 1, &m_state.psSso[i]); + } + + for (uint32_t i = 0; i < D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; i++) { + if (TestBit(m_mask.VSShaderResources, i)) m_device->VSSetShaderResources(i, 1, &m_state.vsSrv[i]); + if (TestBit(m_mask.GSShaderResources, i)) m_device->GSSetShaderResources(i, 1, &m_state.gsSrv[i]); + if (TestBit(m_mask.PSShaderResources, i)) m_device->PSSetShaderResources(i, 1, &m_state.psSrv[i]); + } + + for (uint32_t i = 0; i < D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; i++) { + if (TestBit(m_mask.VSConstantBuffers, i)) m_device->VSSetConstantBuffers(i, 1, &m_state.vsCbo[i]); + if (TestBit(m_mask.GSConstantBuffers, i)) m_device->GSSetConstantBuffers(i, 1, &m_state.gsCbo[i]); + if (TestBit(m_mask.PSConstantBuffers, i)) m_device->PSSetConstantBuffers(i, 1, &m_state.psCbo[i]); + } + + for (uint32_t i = 0; i < D3D10_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; i++) { + if (TestBit(m_mask.IAVertexBuffers, i)) { + m_device->IASetVertexBuffers(i, 1, + &m_state.iaVertexBuffers[i], + &m_state.iaVertexOffsets[i], + &m_state.iaVertexStrides[i]); + } + } + + if (TestBit(&m_mask.IAIndexBuffer, 0)) { + m_device->IASetIndexBuffer( + m_state.iaIndexBuffer.ptr(), + m_state.iaIndexFormat, + m_state.iaIndexOffset); + } + + if (TestBit(&m_mask.IAInputLayout, 0)) + m_device->IASetInputLayout(m_state.iaInputLayout.ptr()); + + if (TestBit(&m_mask.IAPrimitiveTopology, 0)) + m_device->IASetPrimitiveTopology(m_state.iaTopology); + + if (TestBit(&m_mask.OMRenderTargets, 0)) { + m_device->OMSetRenderTargets( + D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT, + &m_state.omRtv[0], m_state.omDsv.ptr()); + } + + if (TestBit(&m_mask.OMDepthStencilState, 0)) { + m_device->OMSetDepthStencilState( + m_state.omDepthStencilState.ptr(), + m_state.omStencilRef); + } + + if (TestBit(&m_mask.OMBlendState, 0)) { + m_device->OMSetBlendState( + m_state.omBlendState.ptr(), + m_state.omBlendFactor, + m_state.omSampleMask); + } + + if (TestBit(&m_mask.RSViewports, 0)) + m_device->RSSetViewports(m_state.rsViewportCount, m_state.rsViewports); + + if (TestBit(&m_mask.RSScissorRects, 0)) + m_device->RSSetScissorRects(m_state.rsScissorCount, m_state.rsScissors); + + if (TestBit(&m_mask.RSRasterizerState, 0)) + m_device->RSSetState(m_state.rsState.ptr()); + + if (TestBit(&m_mask.SOBuffers, 0)) { + m_device->SOSetTargets( + D3D10_SO_BUFFER_SLOT_COUNT, + &m_state.soBuffers[0], + &m_state.soOffsets[0]); + } + + if (TestBit(&m_mask.Predication, 0)) + m_device->SetPredication(m_state.predicate.ptr(), m_state.predicateInvert); + + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D10StateBlock::GetDevice( + ID3D10Device** ppDevice) { + Logger::err("D3D10StateBlock::GetDevice: Stub"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE D3D10StateBlock::ReleaseAllDeviceObjects() { + // Not entirely sure if this is correct? + m_state = D3D10_STATE_BLOCK_STATE(); + return S_OK; + } + + + BOOL D3D10StateBlock::TestBit( + const BYTE* pMask, + UINT Idx) { + uint32_t byte = Idx / 8; + uint32_t bit = Idx % 8; + return (pMask[byte] & (1 << bit)) != 0; + } + +} + +extern "C" { + using namespace dxvk; + + HRESULT STDMETHODCALLTYPE D3D10CreateStateBlock( + ID3D10Device* pDevice, + D3D10_STATE_BLOCK_MASK* pStateBlockMask, + ID3D10StateBlock** ppStateBlock) { + InitReturnPtr(ppStateBlock); + + if (!pDevice || !pStateBlockMask || !ppStateBlock) + return E_INVALIDARG; + + *ppStateBlock = ref(new D3D10StateBlock(pDevice, pStateBlockMask)); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D10StateBlockMaskEnableCapture( + D3D10_STATE_BLOCK_MASK* pMask, + D3D10_DEVICE_STATE_TYPES StateType, + UINT StartIdx, + UINT Count) { + if (!pMask || !StateType || StateType > g_stateTypes.size()) + return E_INVALIDARG; + + auto pair = g_stateTypes[uint32_t(StateType) - 1]; + auto mask = reinterpret_cast(pMask) + pair.first; + + if (StartIdx + Count > pair.second) + return E_INVALIDARG; + + for (uint32_t i = StartIdx; i < StartIdx + Count; i++) { + uint32_t byte = i / 8; + uint32_t bit = i % 8; + mask[byte] |= 1 << bit; + } + + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D10StateBlockMaskDisableCapture( + D3D10_STATE_BLOCK_MASK* pMask, + D3D10_DEVICE_STATE_TYPES StateType, + UINT StartIdx, + UINT Count) { + if (!pMask || !StateType || StateType > g_stateTypes.size()) + return E_INVALIDARG; + + auto pair = g_stateTypes[uint32_t(StateType) - 1]; + auto mask = reinterpret_cast(pMask) + pair.first; + + if (StartIdx + Count > pair.second) + return E_INVALIDARG; + + for (uint32_t i = StartIdx; i < StartIdx + Count; i++) { + uint32_t byte = i / 8; + uint32_t bit = i % 8; + mask[byte] &= ~(1 << bit); + } + + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D10StateBlockMaskEnableAll( + D3D10_STATE_BLOCK_MASK* pMask) { + if (!pMask) + return E_INVALIDARG; + + *pMask = D3D10_STATE_BLOCK_MASK(); + for (size_t i = 0; i < g_stateTypes.size(); i++) { + D3D10StateBlockMaskEnableCapture(pMask, + D3D10_DEVICE_STATE_TYPES(i + 1), + 0, g_stateTypes[i].second); + } + + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D10StateBlockMaskDisableAll( + D3D10_STATE_BLOCK_MASK* pMask) { + if (!pMask) + return E_INVALIDARG; + + *pMask = D3D10_STATE_BLOCK_MASK(); + return S_OK; + } + + + BOOL STDMETHODCALLTYPE D3D10StateBlockMaskGetSetting( + D3D10_STATE_BLOCK_MASK* pMask, + D3D10_DEVICE_STATE_TYPES StateType, + UINT Idx) { + if (!pMask || !StateType || StateType > g_stateTypes.size()) + return FALSE; + + auto pair = g_stateTypes[uint32_t(StateType) - 1]; + auto mask = reinterpret_cast(pMask) + pair.first; + + if (Idx >= pair.second) + return FALSE; + + uint32_t byte = Idx / 8; + uint32_t bit = Idx % 8; + return (mask[byte] & (1 << bit)) != 0; + } + + + HRESULT STDMETHODCALLTYPE D3D10StateBlockMaskDifference( + D3D10_STATE_BLOCK_MASK* pA, + D3D10_STATE_BLOCK_MASK* pB, + D3D10_STATE_BLOCK_MASK* pResult) { + if (!pA || !pB || !pResult) + return E_INVALIDARG; + + auto a = reinterpret_cast(pA); + auto b = reinterpret_cast(pB); + auto r = reinterpret_cast(pResult); + + for (size_t i = 0; i < sizeof(D3D10_STATE_BLOCK_MASK); i++) + r[i] = a[i] ^ b[i]; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D10StateBlockMaskIntersect( + D3D10_STATE_BLOCK_MASK* pA, + D3D10_STATE_BLOCK_MASK* pB, + D3D10_STATE_BLOCK_MASK* pResult) { + if (!pA || !pB || !pResult) + return E_INVALIDARG; + + auto a = reinterpret_cast(pA); + auto b = reinterpret_cast(pB); + auto r = reinterpret_cast(pResult); + + for (size_t i = 0; i < sizeof(D3D10_STATE_BLOCK_MASK); i++) + r[i] = a[i] & b[i]; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D10StateBlockMaskUnion( + D3D10_STATE_BLOCK_MASK* pA, + D3D10_STATE_BLOCK_MASK* pB, + D3D10_STATE_BLOCK_MASK* pResult) { + if (!pA || !pB || !pResult) + return E_INVALIDARG; + + auto a = reinterpret_cast(pA); + auto b = reinterpret_cast(pB); + auto r = reinterpret_cast(pResult); + + for (size_t i = 0; i < sizeof(D3D10_STATE_BLOCK_MASK); i++) + r[i] = a[i] | b[i]; + return S_OK; + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_state_block.h b/utils/dxvk-1.10.3/src/d3d10/d3d10_state_block.h new file mode 100644 index 00000000000..b899034d53a --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_state_block.h @@ -0,0 +1,82 @@ +#pragma once + +#include "d3d10_include.h" +#include "d3d10_interfaces.h" + +namespace dxvk { + + struct D3D10_STATE_BLOCK_STATE { + Com vs = { }; + Com vsSso[D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT] = { }; + Com vsSrv[D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT] = { }; + Com vsCbo[D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT] = { }; + Com gs = { }; + Com gsSso[D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT] = { }; + Com gsSrv[D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT] = { }; + Com gsCbo[D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT] = { }; + Com ps = { }; + Com psSso[D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT] = { }; + Com psSrv[D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT] = { }; + Com psCbo[D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT] = { }; + Com iaVertexBuffers[D3D10_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT] = { }; + UINT iaVertexOffsets[D3D10_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT] = { }; + UINT iaVertexStrides[D3D10_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT] = { }; + Com iaIndexBuffer = { }; + DXGI_FORMAT iaIndexFormat = DXGI_FORMAT_UNKNOWN; + UINT iaIndexOffset = 0; + Com iaInputLayout = nullptr; + D3D10_PRIMITIVE_TOPOLOGY iaTopology = D3D10_PRIMITIVE_TOPOLOGY_UNDEFINED; + Com omRtv[D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT] = { }; + Com omDsv = { }; + Com omDepthStencilState = { }; + UINT omStencilRef = 0; + Com omBlendState = { }; + FLOAT omBlendFactor[4] = { }; + UINT omSampleMask = 0; + UINT rsViewportCount = 0; + D3D10_VIEWPORT rsViewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE] = { }; + UINT rsScissorCount = 0; + RECT rsScissors [D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE] = { }; + Com rsState = { }; + Com soBuffers[D3D10_SO_BUFFER_SLOT_COUNT] = { }; + UINT soOffsets[D3D10_SO_BUFFER_SLOT_COUNT] = { }; + Com predicate = { }; + BOOL predicateInvert = FALSE; + }; + + + class D3D10StateBlock : public ComObject { + + public: + D3D10StateBlock( + ID3D10Device* pDevice, + const D3D10_STATE_BLOCK_MASK* pMask); + + ~D3D10StateBlock(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + HRESULT STDMETHODCALLTYPE Capture(); + + HRESULT STDMETHODCALLTYPE Apply(); + + HRESULT STDMETHODCALLTYPE GetDevice( + ID3D10Device** ppDevice); + + HRESULT STDMETHODCALLTYPE ReleaseAllDeviceObjects(); + + private: + + Com m_device; + D3D10_STATE_BLOCK_MASK m_mask; + D3D10_STATE_BLOCK_STATE m_state; + + static BOOL TestBit( + const BYTE* pMask, + UINT Idx); + + }; + +} diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_texture.cpp b/utils/dxvk-1.10.3/src/d3d10/d3d10_texture.cpp new file mode 100644 index 00000000000..d04267cbcfa --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_texture.cpp @@ -0,0 +1,345 @@ +#include "d3d10_texture.h" +#include "d3d10_device.h" + +#include "../d3d11/d3d11_device.h" +#include "../d3d11/d3d11_context.h" +#include "../d3d11/d3d11_texture.h" + +namespace dxvk { + + HRESULT STDMETHODCALLTYPE D3D10Texture1D::QueryInterface( + REFIID riid, + void** ppvObject) { + return m_d3d11->QueryInterface(riid, ppvObject); + } + + + ULONG STDMETHODCALLTYPE D3D10Texture1D::AddRef() { + return m_d3d11->AddRef(); + } + + + ULONG STDMETHODCALLTYPE D3D10Texture1D::Release() { + return m_d3d11->Release(); + } + + + void STDMETHODCALLTYPE D3D10Texture1D::GetDevice( + ID3D10Device** ppDevice) { + GetD3D10Device(m_d3d11, ppDevice); + } + + + HRESULT STDMETHODCALLTYPE D3D10Texture1D::GetPrivateData( + REFGUID guid, + UINT* pDataSize, + void* pData) { + return m_d3d11->GetPrivateData(guid, pDataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D10Texture1D::SetPrivateData( + REFGUID guid, + UINT DataSize, + const void* pData) { + return m_d3d11->SetPrivateData(guid, DataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D10Texture1D::SetPrivateDataInterface( + REFGUID guid, + const IUnknown* pData) { + return m_d3d11->SetPrivateDataInterface(guid, pData); + } + + + void STDMETHODCALLTYPE D3D10Texture1D::GetType( + D3D10_RESOURCE_DIMENSION* rType) { + *rType = D3D10_RESOURCE_DIMENSION_TEXTURE1D; + } + + + void STDMETHODCALLTYPE D3D10Texture1D::SetEvictionPriority( + UINT EvictionPriority) { + m_d3d11->SetEvictionPriority(EvictionPriority); + } + + + UINT STDMETHODCALLTYPE D3D10Texture1D::GetEvictionPriority() { + return m_d3d11->GetEvictionPriority(); + } + + + HRESULT STDMETHODCALLTYPE D3D10Texture1D::Map( + UINT Subresource, + D3D10_MAP MapType, + UINT MapFlags, + void** ppData) { + Com ctx; + GetD3D11Context(m_d3d11, &ctx); + + D3D11_MAPPED_SUBRESOURCE sr; + HRESULT hr = ctx->Map(m_d3d11, Subresource, + D3D11_MAP(MapType), MapFlags, &sr); + + if (FAILED(hr)) + return hr; + + if (ppData != nullptr) { + *ppData = sr.pData; + return S_OK; + } return S_FALSE; + } + + + void STDMETHODCALLTYPE D3D10Texture1D::Unmap( + UINT Subresource) { + Com ctx; + GetD3D11Context(m_d3d11, &ctx); + + ctx->Unmap(m_d3d11, Subresource); + } + + + void STDMETHODCALLTYPE D3D10Texture1D::GetDesc( + D3D10_TEXTURE1D_DESC* pDesc) { + D3D11_TEXTURE1D_DESC d3d11Desc; + m_d3d11->GetDesc(&d3d11Desc); + + pDesc->Width = d3d11Desc.Width; + pDesc->MipLevels = d3d11Desc.MipLevels; + pDesc->ArraySize = d3d11Desc.ArraySize; + pDesc->Format = d3d11Desc.Format; + pDesc->Usage = D3D10_USAGE(d3d11Desc.Usage); + pDesc->BindFlags = d3d11Desc.BindFlags; + pDesc->CPUAccessFlags = d3d11Desc.CPUAccessFlags; + pDesc->MiscFlags = ConvertD3D11ResourceFlags(d3d11Desc.MiscFlags); + } + + + HRESULT STDMETHODCALLTYPE D3D10Texture2D::QueryInterface( + REFIID riid, + void** ppvObject) { + return m_d3d11->QueryInterface(riid, ppvObject); + } + + + ULONG STDMETHODCALLTYPE D3D10Texture2D::AddRef() { + return m_d3d11->AddRef(); + } + + + ULONG STDMETHODCALLTYPE D3D10Texture2D::Release() { + return m_d3d11->Release(); + } + + + void STDMETHODCALLTYPE D3D10Texture2D::GetDevice( + ID3D10Device** ppDevice) { + GetD3D10Device(m_d3d11, ppDevice); + } + + + HRESULT STDMETHODCALLTYPE D3D10Texture2D::GetPrivateData( + REFGUID guid, + UINT* pDataSize, + void* pData) { + return m_d3d11->GetPrivateData(guid, pDataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D10Texture2D::SetPrivateData( + REFGUID guid, + UINT DataSize, + const void* pData) { + return m_d3d11->SetPrivateData(guid, DataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D10Texture2D::SetPrivateDataInterface( + REFGUID guid, + const IUnknown* pData) { + return m_d3d11->SetPrivateDataInterface(guid, pData); + } + + + void STDMETHODCALLTYPE D3D10Texture2D::GetType( + D3D10_RESOURCE_DIMENSION* rType) { + *rType = D3D10_RESOURCE_DIMENSION_TEXTURE2D; + } + + + void STDMETHODCALLTYPE D3D10Texture2D::SetEvictionPriority( + UINT EvictionPriority) { + m_d3d11->SetEvictionPriority(EvictionPriority); + } + + + UINT STDMETHODCALLTYPE D3D10Texture2D::GetEvictionPriority() { + return m_d3d11->GetEvictionPriority(); + } + + + HRESULT STDMETHODCALLTYPE D3D10Texture2D::Map( + UINT Subresource, + D3D10_MAP MapType, + UINT MapFlags, + D3D10_MAPPED_TEXTURE2D* pMappedTex2D) { + Com ctx; + GetD3D11Context(m_d3d11, &ctx); + + D3D11_MAPPED_SUBRESOURCE sr; + HRESULT hr = ctx->Map(m_d3d11, Subresource, + D3D11_MAP(MapType), MapFlags, &sr); + + if (FAILED(hr)) + return hr; + + if (pMappedTex2D != nullptr) { + pMappedTex2D->pData = sr.pData; + pMappedTex2D->RowPitch = sr.RowPitch; + return S_OK; + } return S_FALSE; + } + + + void STDMETHODCALLTYPE D3D10Texture2D::Unmap( + UINT Subresource) { + Com ctx; + GetD3D11Context(m_d3d11, &ctx); + + ctx->Unmap(m_d3d11, Subresource); + } + + + void STDMETHODCALLTYPE D3D10Texture2D::GetDesc( + D3D10_TEXTURE2D_DESC* pDesc) { + D3D11_TEXTURE2D_DESC d3d11Desc; + m_d3d11->GetDesc(&d3d11Desc); + + pDesc->Width = d3d11Desc.Width; + pDesc->Height = d3d11Desc.Height; + pDesc->MipLevels = d3d11Desc.MipLevels; + pDesc->ArraySize = d3d11Desc.ArraySize; + pDesc->Format = d3d11Desc.Format; + pDesc->SampleDesc = d3d11Desc.SampleDesc; + pDesc->Usage = D3D10_USAGE(d3d11Desc.Usage); + pDesc->BindFlags = d3d11Desc.BindFlags; + pDesc->CPUAccessFlags = d3d11Desc.CPUAccessFlags; + pDesc->MiscFlags = ConvertD3D11ResourceFlags(d3d11Desc.MiscFlags); + } + + + HRESULT STDMETHODCALLTYPE D3D10Texture3D::QueryInterface( + REFIID riid, + void** ppvObject) { + return m_d3d11->QueryInterface(riid, ppvObject); + } + + + ULONG STDMETHODCALLTYPE D3D10Texture3D::AddRef() { + return m_d3d11->AddRef(); + } + + + ULONG STDMETHODCALLTYPE D3D10Texture3D::Release() { + return m_d3d11->Release(); + } + + + void STDMETHODCALLTYPE D3D10Texture3D::GetDevice( + ID3D10Device** ppDevice) { + GetD3D10Device(m_d3d11, ppDevice); + } + + + HRESULT STDMETHODCALLTYPE D3D10Texture3D::GetPrivateData( + REFGUID guid, + UINT* pDataSize, + void* pData) { + return m_d3d11->GetPrivateData(guid, pDataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D10Texture3D::SetPrivateData( + REFGUID guid, + UINT DataSize, + const void* pData) { + return m_d3d11->SetPrivateData(guid, DataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D10Texture3D::SetPrivateDataInterface( + REFGUID guid, + const IUnknown* pData) { + return m_d3d11->SetPrivateDataInterface(guid, pData); + } + + + void STDMETHODCALLTYPE D3D10Texture3D::GetType( + D3D10_RESOURCE_DIMENSION* rType) { + *rType = D3D10_RESOURCE_DIMENSION_TEXTURE3D; + } + + + void STDMETHODCALLTYPE D3D10Texture3D::SetEvictionPriority( + UINT EvictionPriority) { + m_d3d11->SetEvictionPriority(EvictionPriority); + } + + + UINT STDMETHODCALLTYPE D3D10Texture3D::GetEvictionPriority() { + return m_d3d11->GetEvictionPriority(); + } + + + HRESULT STDMETHODCALLTYPE D3D10Texture3D::Map( + UINT Subresource, + D3D10_MAP MapType, + UINT MapFlags, + D3D10_MAPPED_TEXTURE3D* pMappedTex3D) { + Com ctx; + GetD3D11Context(m_d3d11, &ctx); + + D3D11_MAPPED_SUBRESOURCE sr; + HRESULT hr = ctx->Map(m_d3d11, Subresource, + D3D11_MAP(MapType), MapFlags, &sr); + + if (FAILED(hr)) + return hr; + + if (pMappedTex3D != nullptr) { + pMappedTex3D->pData = sr.pData; + pMappedTex3D->RowPitch = sr.RowPitch; + pMappedTex3D->DepthPitch = sr.DepthPitch; + return S_OK; + } return S_FALSE; + } + + + void STDMETHODCALLTYPE D3D10Texture3D::Unmap( + UINT Subresource) { + Com ctx; + GetD3D11Context(m_d3d11, &ctx); + + ctx->Unmap(m_d3d11, Subresource); + } + + + void STDMETHODCALLTYPE D3D10Texture3D::GetDesc( + D3D10_TEXTURE3D_DESC* pDesc) { + D3D11_TEXTURE3D_DESC d3d11Desc; + m_d3d11->GetDesc(&d3d11Desc); + + pDesc->Width = d3d11Desc.Width; + pDesc->Height = d3d11Desc.Height; + pDesc->Depth = d3d11Desc.Depth; + pDesc->MipLevels = d3d11Desc.MipLevels; + pDesc->Format = d3d11Desc.Format; + pDesc->Usage = D3D10_USAGE(d3d11Desc.Usage); + pDesc->BindFlags = d3d11Desc.BindFlags; + pDesc->CPUAccessFlags = d3d11Desc.CPUAccessFlags; + pDesc->MiscFlags = ConvertD3D11ResourceFlags(d3d11Desc.MiscFlags); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_texture.h b/utils/dxvk-1.10.3/src/d3d10/d3d10_texture.h new file mode 100644 index 00000000000..9c663300172 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_texture.h @@ -0,0 +1,207 @@ +#pragma once + +#include "d3d10_util.h" + +namespace dxvk { + + class D3D10Device; + class D3D11Device; + class D3D11Texture1D; + class D3D11Texture2D; + class D3D11Texture3D; + + /////////////////////////////////////////// + // D 3 D 1 0 T E X T U R E 1 D + class D3D10Texture1D : public ID3D10Texture1D { + + public: + + D3D10Texture1D(D3D11Texture1D* pParent) + : m_d3d11(pParent) { } + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + ULONG STDMETHODCALLTYPE AddRef(); + + ULONG STDMETHODCALLTYPE Release(); + + void STDMETHODCALLTYPE GetDevice( + ID3D10Device** ppDevice); + + HRESULT STDMETHODCALLTYPE GetPrivateData( + REFGUID guid, + UINT* pDataSize, + void* pData); + + HRESULT STDMETHODCALLTYPE SetPrivateData( + REFGUID guid, + UINT DataSize, + const void* pData); + + HRESULT STDMETHODCALLTYPE SetPrivateDataInterface( + REFGUID guid, + const IUnknown* pData); + + void STDMETHODCALLTYPE GetType( + D3D10_RESOURCE_DIMENSION* rType); + + void STDMETHODCALLTYPE SetEvictionPriority( + UINT EvictionPriority); + + UINT STDMETHODCALLTYPE GetEvictionPriority(); + + HRESULT STDMETHODCALLTYPE Map( + UINT Subresource, + D3D10_MAP MapType, + UINT MapFlags, + void** ppData); + + void STDMETHODCALLTYPE Unmap( + UINT Subresource); + + void STDMETHODCALLTYPE GetDesc( + D3D10_TEXTURE1D_DESC* pDesc); + + D3D11Texture1D* GetD3D11Iface() { + return m_d3d11; + } + + private: + + D3D11Texture1D* m_d3d11; + + }; + + + /////////////////////////////////////////// + // D 3 D 1 0 T E X T U R E 2 D + class D3D10Texture2D : public ID3D10Texture2D { + + public: + + D3D10Texture2D(D3D11Texture2D* pParent) + : m_d3d11(pParent) { } + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + ULONG STDMETHODCALLTYPE AddRef(); + + ULONG STDMETHODCALLTYPE Release(); + + void STDMETHODCALLTYPE GetDevice( + ID3D10Device** ppDevice); + + HRESULT STDMETHODCALLTYPE GetPrivateData( + REFGUID guid, + UINT* pDataSize, + void* pData); + + HRESULT STDMETHODCALLTYPE SetPrivateData( + REFGUID guid, + UINT DataSize, + const void* pData); + + HRESULT STDMETHODCALLTYPE SetPrivateDataInterface( + REFGUID guid, + const IUnknown* pData); + + void STDMETHODCALLTYPE GetType( + D3D10_RESOURCE_DIMENSION* rType); + + void STDMETHODCALLTYPE SetEvictionPriority( + UINT EvictionPriority); + + UINT STDMETHODCALLTYPE GetEvictionPriority(); + + HRESULT STDMETHODCALLTYPE Map( + UINT Subresource, + D3D10_MAP MapType, + UINT MapFlags, + D3D10_MAPPED_TEXTURE2D* pMappedTex2D); + + void STDMETHODCALLTYPE Unmap( + UINT Subresource); + + void STDMETHODCALLTYPE GetDesc( + D3D10_TEXTURE2D_DESC* pDesc); + + D3D11Texture2D* GetD3D11Iface() { + return m_d3d11; + } + + private: + + D3D11Texture2D* m_d3d11; + + }; + + + /////////////////////////////////////////// + // D 3 D 1 0 T E X T U R E 3 D + class D3D10Texture3D : public ID3D10Texture3D { + + public: + + D3D10Texture3D(D3D11Texture3D* pParent) + : m_d3d11(pParent) { } + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + ULONG STDMETHODCALLTYPE AddRef(); + + ULONG STDMETHODCALLTYPE Release(); + + void STDMETHODCALLTYPE GetDevice( + ID3D10Device** ppDevice); + + HRESULT STDMETHODCALLTYPE GetPrivateData( + REFGUID guid, + UINT* pDataSize, + void* pData); + + HRESULT STDMETHODCALLTYPE SetPrivateData( + REFGUID guid, + UINT DataSize, + const void* pData); + + HRESULT STDMETHODCALLTYPE SetPrivateDataInterface( + REFGUID guid, + const IUnknown* pData); + + void STDMETHODCALLTYPE GetType( + D3D10_RESOURCE_DIMENSION* rType); + + void STDMETHODCALLTYPE SetEvictionPriority( + UINT EvictionPriority); + + UINT STDMETHODCALLTYPE GetEvictionPriority(); + + HRESULT STDMETHODCALLTYPE Map( + UINT Subresource, + D3D10_MAP MapType, + UINT MapFlags, + D3D10_MAPPED_TEXTURE3D* pMappedTex3D); + + void STDMETHODCALLTYPE Unmap( + UINT Subresource); + + void STDMETHODCALLTYPE GetDesc( + D3D10_TEXTURE3D_DESC* pDesc); + + D3D11Texture3D* GetD3D11Iface() { + return m_d3d11; + } + + private: + + D3D11Texture3D* m_d3d11; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_util.cpp b/utils/dxvk-1.10.3/src/d3d10/d3d10_util.cpp new file mode 100644 index 00000000000..ad55eed9df4 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_util.cpp @@ -0,0 +1,100 @@ +#include "d3d10_util.h" +#include "d3d10_device.h" + +#include "../d3d11/d3d11_device.h" + +namespace dxvk { + + UINT ConvertD3D10ResourceFlags(UINT MiscFlags) { + UINT result = 0; + if (MiscFlags & D3D10_RESOURCE_MISC_GENERATE_MIPS) + result |= D3D11_RESOURCE_MISC_GENERATE_MIPS; + if (MiscFlags & D3D10_RESOURCE_MISC_SHARED) + result |= D3D11_RESOURCE_MISC_SHARED; + if (MiscFlags & D3D10_RESOURCE_MISC_TEXTURECUBE) + result |= D3D11_RESOURCE_MISC_TEXTURECUBE; + if (MiscFlags & D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX) + result |= D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX; + if (MiscFlags & D3D10_RESOURCE_MISC_GDI_COMPATIBLE) + result |= D3D11_RESOURCE_MISC_GDI_COMPATIBLE; + return result; + } + + + UINT ConvertD3D11ResourceFlags(UINT MiscFlags) { + UINT result = 0; + if (MiscFlags & D3D11_RESOURCE_MISC_GENERATE_MIPS) + result |= D3D10_RESOURCE_MISC_GENERATE_MIPS; + if (MiscFlags & D3D11_RESOURCE_MISC_SHARED) + result |= D3D10_RESOURCE_MISC_SHARED; + if (MiscFlags & D3D11_RESOURCE_MISC_TEXTURECUBE) + result |= D3D10_RESOURCE_MISC_TEXTURECUBE; + if (MiscFlags & D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX) + result |= D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX; + if (MiscFlags & D3D11_RESOURCE_MISC_GDI_COMPATIBLE) + result |= D3D10_RESOURCE_MISC_GDI_COMPATIBLE; + return result; + } + + + void GetD3D10ResourceFromView( + ID3D11View* pSrcView, + ID3D10Resource** ppDstResource) { + Com d3d11Resource; + pSrcView->GetResource(&d3d11Resource); + GetD3D10Resource(d3d11Resource.ptr(), ppDstResource); + } + + + void GetD3D11ResourceFromView( + ID3D10View* pSrcView, + ID3D11Resource** ppDstResource) { + Com d3d10Resource; + pSrcView->GetResource(&d3d10Resource); + GetD3D11Resource(d3d10Resource.ptr(), ppDstResource); + } + + + void GetD3D10Resource( + ID3D11Resource* pSrcResource, + ID3D10Resource** ppDstResource) { + pSrcResource->QueryInterface( + __uuidof(ID3D10Resource), + reinterpret_cast(ppDstResource)); + } + + + void GetD3D11Resource( + ID3D10Resource* pSrcResource, + ID3D11Resource** ppDstResource) { + pSrcResource->QueryInterface( + __uuidof(ID3D11Resource), + reinterpret_cast(ppDstResource)); + } + + + void GetD3D10Device( + ID3D11DeviceChild* pObject, + ID3D10Device** ppDevice) { + ID3D11Device* d3d11Device = nullptr; + pObject->GetDevice(&d3d11Device); + *ppDevice = static_cast(d3d11Device)->GetD3D10Interface(); + } + + + void GetD3D11Device( + ID3D11DeviceChild* pObject, + ID3D11Device** ppDevice) { + pObject->GetDevice(ppDevice); + } + + + void GetD3D11Context( + ID3D11DeviceChild* pObject, + ID3D11DeviceContext** ppContext) { + Com d3d11Device; + pObject->GetDevice(&d3d11Device); + d3d11Device->GetImmediateContext(ppContext); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_util.h b/utils/dxvk-1.10.3/src/d3d10/d3d10_util.h new file mode 100644 index 00000000000..72c9c6e7f62 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_util.h @@ -0,0 +1,88 @@ +#pragma once + +#include "d3d10_include.h" + +namespace dxvk { + + /** + * \brief Converts misc. resource flags + * + * Converts the D3D11 misc. resource flags to + * their D3D10 equivalents and vice versa. + * \param [in] MiscFlags Original bit mask + * \returns Converted bit mask + */ + UINT ConvertD3D10ResourceFlags(UINT MiscFlags); + UINT ConvertD3D11ResourceFlags(UINT MiscFlags); + + /** + * \brief Retrieves D3D10 resource from D3D11 view + * + * \param [in] pSrcView The D3D11 resource view + * \param [out] ppDstResource The D3D10 resource + */ + void GetD3D10ResourceFromView( + ID3D11View* pSrcView, + ID3D10Resource** ppDstResource); + + /** + * \brief Retrieves D3D11 resource from D3D10 view + * + * \param [in] pSrcView The D3D10 resource view + * \param [out] ppDstResource The D3D11 resource + */ + void GetD3D11ResourceFromView( + ID3D10View* pSrcView, + ID3D11Resource** ppDstResource); + + /** + * \brief Retrieves D3D10 resource from D3D11 resource + * + * \param [in] pSrcResource The D3D11 resource + * \param [out] ppDstResource The D3D10 resource + */ + void GetD3D10Resource( + ID3D11Resource* pSrcResource, + ID3D10Resource** ppDstResource); + + /** + * \brief Retrieves D3D11 resource from D3D10 resource + * + * \param [in] pSrcResource The D3D10 resource + * \param [out] ppDstResource The D3D11 resource + */ + void GetD3D11Resource( + ID3D10Resource* pSrcResource, + ID3D11Resource** ppDstResource); + + /** + * \brief Retrieves D3D10 device from D3D11 object + * + * \param [in] pObject The D3D11 device child + * \param [out] ppDevice The D3D10 device pointer + */ + void GetD3D10Device( + ID3D11DeviceChild* pObject, + ID3D10Device** ppDevice); + + /** + * \brief Retrieves D3D11 device from D3D11 object + * + * \param [in] pObject The D3D11 device child + * \param [out] ppDevice The D3D11 device pointer + */ + void GetD3D11Device( + ID3D11DeviceChild* pObject, + ID3D11Device** ppDevice); + + /** + * \brief Retrieves D3D11 context from D3D11 object + * + * \param [in] pObject The D3D11 device child + * \param [out] ppContext The D3D11 immediate context + */ + void GetD3D11Context( + ID3D11DeviceChild* pObject, + ID3D11DeviceContext** ppContext); + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_view_dsv.cpp b/utils/dxvk-1.10.3/src/d3d10/d3d10_view_dsv.cpp new file mode 100644 index 00000000000..4d8df98a12b --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_view_dsv.cpp @@ -0,0 +1,102 @@ +#include "d3d10_view_dsv.h" + +#include "../d3d11/d3d11_device.h" +#include "../d3d11/d3d11_view_dsv.h" + +namespace dxvk { + + HRESULT STDMETHODCALLTYPE D3D10DepthStencilView::QueryInterface( + REFIID riid, + void** ppvObject) { + return m_d3d11->QueryInterface(riid, ppvObject); + } + + + ULONG STDMETHODCALLTYPE D3D10DepthStencilView::AddRef() { + return m_d3d11->AddRef(); + } + + + ULONG STDMETHODCALLTYPE D3D10DepthStencilView::Release() { + return m_d3d11->Release(); + } + + + void STDMETHODCALLTYPE D3D10DepthStencilView::GetDevice( + ID3D10Device** ppDevice) { + GetD3D10Device(m_d3d11, ppDevice); + } + + + HRESULT STDMETHODCALLTYPE D3D10DepthStencilView::GetPrivateData( + REFGUID guid, + UINT* pDataSize, + void* pData) { + return m_d3d11->GetPrivateData(guid, pDataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D10DepthStencilView::SetPrivateData( + REFGUID guid, + UINT DataSize, + const void* pData) { + return m_d3d11->SetPrivateData(guid, DataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D10DepthStencilView::SetPrivateDataInterface( + REFGUID guid, + const IUnknown* pData) { + return m_d3d11->SetPrivateDataInterface(guid, pData); + } + + + void STDMETHODCALLTYPE D3D10DepthStencilView::GetResource( + ID3D10Resource** ppResource) { + GetD3D10ResourceFromView(m_d3d11, ppResource); + } + + + void STDMETHODCALLTYPE D3D10DepthStencilView::GetDesc( + D3D10_DEPTH_STENCIL_VIEW_DESC* pDesc) { + D3D11_DEPTH_STENCIL_VIEW_DESC d3d11Desc; + m_d3d11->GetDesc(&d3d11Desc); + + pDesc->ViewDimension = D3D10_DSV_DIMENSION(d3d11Desc.ViewDimension); + pDesc->Format = d3d11Desc.Format; + + switch (d3d11Desc.ViewDimension) { + case D3D11_DSV_DIMENSION_UNKNOWN: + break; + + case D3D11_DSV_DIMENSION_TEXTURE1D: + pDesc->Texture1D.MipSlice = d3d11Desc.Texture1D.MipSlice; + break; + + case D3D11_DSV_DIMENSION_TEXTURE1DARRAY: + pDesc->Texture1DArray.MipSlice = d3d11Desc.Texture1DArray.MipSlice; + pDesc->Texture1DArray.FirstArraySlice = d3d11Desc.Texture1DArray.FirstArraySlice; + pDesc->Texture1DArray.ArraySize = d3d11Desc.Texture1DArray.ArraySize; + break; + + case D3D11_DSV_DIMENSION_TEXTURE2D: + pDesc->Texture2D.MipSlice = d3d11Desc.Texture2D.MipSlice; + break; + + case D3D11_DSV_DIMENSION_TEXTURE2DARRAY: + pDesc->Texture2DArray.MipSlice = d3d11Desc.Texture2DArray.MipSlice; + pDesc->Texture2DArray.FirstArraySlice = d3d11Desc.Texture2DArray.FirstArraySlice; + pDesc->Texture2DArray.ArraySize = d3d11Desc.Texture2DArray.ArraySize; + break; + + case D3D11_DSV_DIMENSION_TEXTURE2DMS: + break; + + case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY: + pDesc->Texture2DMSArray.FirstArraySlice = d3d11Desc.Texture2DMSArray.FirstArraySlice; + pDesc->Texture2DMSArray.ArraySize = d3d11Desc.Texture2DMSArray.ArraySize; + break; + } + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_view_dsv.h b/utils/dxvk-1.10.3/src/d3d10/d3d10_view_dsv.h new file mode 100644 index 00000000000..e78c7642cee --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_view_dsv.h @@ -0,0 +1,58 @@ +#pragma once + +#include "d3d10_util.h" + +namespace dxvk { + + class D3D11Device; + class D3D11DepthStencilView; + + class D3D10DepthStencilView : public ID3D10DepthStencilView { + + public: + + D3D10DepthStencilView(D3D11DepthStencilView* pParent) + : m_d3d11(pParent) { } + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + ULONG STDMETHODCALLTYPE AddRef(); + + ULONG STDMETHODCALLTYPE Release(); + + void STDMETHODCALLTYPE GetDevice( + ID3D10Device** ppDevice); + + HRESULT STDMETHODCALLTYPE GetPrivateData( + REFGUID guid, + UINT* pDataSize, + void* pData); + + HRESULT STDMETHODCALLTYPE SetPrivateData( + REFGUID guid, + UINT DataSize, + const void* pData); + + HRESULT STDMETHODCALLTYPE SetPrivateDataInterface( + REFGUID guid, + const IUnknown* pData); + + void STDMETHODCALLTYPE GetResource( + ID3D10Resource** ppResource); + + void STDMETHODCALLTYPE GetDesc( + D3D10_DEPTH_STENCIL_VIEW_DESC* pDesc); + + D3D11DepthStencilView* GetD3D11Iface() { + return m_d3d11; + } + + private: + + D3D11DepthStencilView* m_d3d11; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_view_rtv.cpp b/utils/dxvk-1.10.3/src/d3d10/d3d10_view_rtv.cpp new file mode 100644 index 00000000000..7170a6494d4 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_view_rtv.cpp @@ -0,0 +1,68 @@ +#include "d3d10_view_rtv.h" + +#include "../d3d11/d3d11_device.h" +#include "../d3d11/d3d11_view_rtv.h" + +namespace dxvk { + + HRESULT STDMETHODCALLTYPE D3D10RenderTargetView::QueryInterface( + REFIID riid, + void** ppvObject) { + return m_d3d11->QueryInterface(riid, ppvObject); + } + + + ULONG STDMETHODCALLTYPE D3D10RenderTargetView::AddRef() { + return m_d3d11->AddRef(); + } + + + ULONG STDMETHODCALLTYPE D3D10RenderTargetView::Release() { + return m_d3d11->Release(); + } + + + void STDMETHODCALLTYPE D3D10RenderTargetView::GetDevice( + ID3D10Device** ppDevice) { + GetD3D10Device(m_d3d11, ppDevice); + } + + + HRESULT STDMETHODCALLTYPE D3D10RenderTargetView::GetPrivateData( + REFGUID guid, + UINT* pDataSize, + void* pData) { + return m_d3d11->GetPrivateData(guid, pDataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D10RenderTargetView::SetPrivateData( + REFGUID guid, + UINT DataSize, + const void* pData) { + return m_d3d11->SetPrivateData(guid, DataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D10RenderTargetView::SetPrivateDataInterface( + REFGUID guid, + const IUnknown* pData) { + return m_d3d11->SetPrivateDataInterface(guid, pData); + } + + + void STDMETHODCALLTYPE D3D10RenderTargetView::GetResource( + ID3D10Resource** ppResource) { + GetD3D10ResourceFromView(m_d3d11, ppResource); + } + + + void STDMETHODCALLTYPE D3D10RenderTargetView::GetDesc( + D3D10_RENDER_TARGET_VIEW_DESC* pDesc) { + static_assert(sizeof(D3D10_RENDER_TARGET_VIEW_DESC) == + sizeof(D3D11_RENDER_TARGET_VIEW_DESC)); + + m_d3d11->GetDesc(reinterpret_cast(pDesc)); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_view_rtv.h b/utils/dxvk-1.10.3/src/d3d10/d3d10_view_rtv.h new file mode 100644 index 00000000000..e6a46c56728 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_view_rtv.h @@ -0,0 +1,58 @@ +#pragma once + +#include "d3d10_util.h" + +namespace dxvk { + + class D3D11Device; + class D3D11RenderTargetView; + + class D3D10RenderTargetView : public ID3D10RenderTargetView { + + public: + + D3D10RenderTargetView(D3D11RenderTargetView* pParent) + : m_d3d11(pParent) { } + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + ULONG STDMETHODCALLTYPE AddRef(); + + ULONG STDMETHODCALLTYPE Release(); + + void STDMETHODCALLTYPE GetDevice( + ID3D10Device** ppDevice); + + HRESULT STDMETHODCALLTYPE GetPrivateData( + REFGUID guid, + UINT* pDataSize, + void* pData); + + HRESULT STDMETHODCALLTYPE SetPrivateData( + REFGUID guid, + UINT DataSize, + const void* pData); + + HRESULT STDMETHODCALLTYPE SetPrivateDataInterface( + REFGUID guid, + const IUnknown* pData); + + void STDMETHODCALLTYPE GetResource( + ID3D10Resource** ppResource); + + void STDMETHODCALLTYPE GetDesc( + D3D10_RENDER_TARGET_VIEW_DESC* pDesc); + + D3D11RenderTargetView* GetD3D11Iface() { + return m_d3d11; + } + + private: + + D3D11RenderTargetView* m_d3d11; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_view_srv.cpp b/utils/dxvk-1.10.3/src/d3d10/d3d10_view_srv.cpp new file mode 100644 index 00000000000..d8fdd24d9e6 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_view_srv.cpp @@ -0,0 +1,83 @@ +#include "d3d10_view_srv.h" + +#include "../d3d11/d3d11_device.h" +#include "../d3d11/d3d11_view_srv.h" + +namespace dxvk { + + HRESULT STDMETHODCALLTYPE D3D10ShaderResourceView::QueryInterface( + REFIID riid, + void** ppvObject) { + return m_d3d11->QueryInterface(riid, ppvObject); + } + + + ULONG STDMETHODCALLTYPE D3D10ShaderResourceView::AddRef() { + return m_d3d11->AddRef(); + } + + + ULONG STDMETHODCALLTYPE D3D10ShaderResourceView::Release() { + return m_d3d11->Release(); + } + + + void STDMETHODCALLTYPE D3D10ShaderResourceView::GetDevice( + ID3D10Device** ppDevice) { + GetD3D10Device(m_d3d11, ppDevice); + } + + + HRESULT STDMETHODCALLTYPE D3D10ShaderResourceView::GetPrivateData( + REFGUID guid, + UINT* pDataSize, + void* pData) { + return m_d3d11->GetPrivateData(guid, pDataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D10ShaderResourceView::SetPrivateData( + REFGUID guid, + UINT DataSize, + const void* pData) { + return m_d3d11->SetPrivateData(guid, DataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D10ShaderResourceView::SetPrivateDataInterface( + REFGUID guid, + const IUnknown* pData) { + return m_d3d11->SetPrivateDataInterface(guid, pData); + } + + + void STDMETHODCALLTYPE D3D10ShaderResourceView::GetResource( + ID3D10Resource** ppResource) { + GetD3D10ResourceFromView(m_d3d11, ppResource); + } + + + void STDMETHODCALLTYPE D3D10ShaderResourceView::GetDesc( + D3D10_SHADER_RESOURCE_VIEW_DESC* pDesc) { + static_assert(sizeof(D3D10_SHADER_RESOURCE_VIEW_DESC) == + sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC)); + + m_d3d11->GetDesc(reinterpret_cast(pDesc)); + + if (pDesc->ViewDimension > D3D10_SRV_DIMENSION_TEXTURECUBE) + pDesc->ViewDimension = D3D10_SRV_DIMENSION_UNKNOWN; + } + + + void STDMETHODCALLTYPE D3D10ShaderResourceView::GetDesc1( + D3D10_SHADER_RESOURCE_VIEW_DESC1* pDesc) { + static_assert(sizeof(D3D10_SHADER_RESOURCE_VIEW_DESC1) == + sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC)); + + m_d3d11->GetDesc(reinterpret_cast(pDesc)); + + if (pDesc->ViewDimension > D3D10_1_SRV_DIMENSION_TEXTURECUBEARRAY) + pDesc->ViewDimension = D3D10_1_SRV_DIMENSION_UNKNOWN; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10_view_srv.h b/utils/dxvk-1.10.3/src/d3d10/d3d10_view_srv.h new file mode 100644 index 00000000000..7cbaffe9426 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10_view_srv.h @@ -0,0 +1,61 @@ +#pragma once + +#include "d3d10_util.h" + +namespace dxvk { + + class D3D11Device; + class D3D11ShaderResourceView; + + class D3D10ShaderResourceView : public ID3D10ShaderResourceView1 { + + public: + + D3D10ShaderResourceView(D3D11ShaderResourceView* pParent) + : m_d3d11(pParent) { } + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + ULONG STDMETHODCALLTYPE AddRef(); + + ULONG STDMETHODCALLTYPE Release(); + + void STDMETHODCALLTYPE GetDevice( + ID3D10Device** ppDevice); + + HRESULT STDMETHODCALLTYPE GetPrivateData( + REFGUID guid, + UINT* pDataSize, + void* pData); + + HRESULT STDMETHODCALLTYPE SetPrivateData( + REFGUID guid, + UINT DataSize, + const void* pData); + + HRESULT STDMETHODCALLTYPE SetPrivateDataInterface( + REFGUID guid, + const IUnknown* pData); + + void STDMETHODCALLTYPE GetResource( + ID3D10Resource** ppResource); + + void STDMETHODCALLTYPE GetDesc( + D3D10_SHADER_RESOURCE_VIEW_DESC* pDesc); + + void STDMETHODCALLTYPE GetDesc1( + D3D10_SHADER_RESOURCE_VIEW_DESC1* pDesc); + + D3D11ShaderResourceView* GetD3D11Iface() { + return m_d3d11; + } + + private: + + D3D11ShaderResourceView* m_d3d11; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d10/d3d10core.def b/utils/dxvk-1.10.3/src/d3d10/d3d10core.def new file mode 100644 index 00000000000..39c659686bf --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/d3d10core.def @@ -0,0 +1,5 @@ +LIBRARY D3D10CORE.DLL +EXPORTS + D3D10CoreCreateDevice + D3D10CoreGetVersion + D3D10CoreRegisterLayers diff --git a/utils/dxvk-1.10.3/src/d3d10/meson.build b/utils/dxvk-1.10.3/src/d3d10/meson.build new file mode 100644 index 00000000000..0a78fcc37f7 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/meson.build @@ -0,0 +1,48 @@ +d3d10_res = wrc_generator.process('version10.rc') +d3d10_1_res = wrc_generator.process('version10_1.rc') +d3d10_core_res = wrc_generator.process('version10_core.rc') + +d3d10_core_src = [ + 'd3d10_core.cpp', +] + +d3d10_main_src = [ + 'd3d10_main.cpp', + 'd3d10_reflection.cpp', + 'd3d10_state_block.cpp', +] + +d3d10_core_dll = shared_library('d3d10core'+dll_ext, d3d10_core_src, d3d10_core_res, + name_prefix : '', + dependencies : [ d3d11_dep ], + include_directories : dxvk_include_path, + install : true, + vs_module_defs : 'd3d10core'+def_spec_ext, +) + +d3d10_core_dep = declare_dependency( + link_with : [ d3d10_core_dll ], +) + +d3d10_deps = [ lib_d3dcompiler_43, lib_dxgi, dxbc_dep, dxvk_dep, d3d10_core_dep ] + +d3d10_dll = shared_library('d3d10'+dll_ext, d3d10_main_src, d3d10_res, + name_prefix : '', + dependencies : [ d3d10_deps ], + include_directories : dxvk_include_path, + install : true, + vs_module_defs : 'd3d10'+def_spec_ext, +) + +d3d10_1_dll = shared_library('d3d10_1'+dll_ext, d3d10_main_src, d3d10_1_res, + name_prefix : '', + dependencies : [ d3d10_deps ], + include_directories : dxvk_include_path, + install : true, + vs_module_defs : 'd3d10_1'+def_spec_ext, +) + +d3d10_dep = declare_dependency( + link_with : [ d3d10_dll, d3d10_1_dll, d3d10_core_dll ], + include_directories : [ dxvk_include_path ], +) diff --git a/utils/dxvk-1.10.3/src/d3d10/version10.rc b/utils/dxvk-1.10.3/src/d3d10/version10.rc new file mode 100644 index 00000000000..43d7a62fdbf --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/version10.rc @@ -0,0 +1,32 @@ +#include + +// DLL version information. +VS_VERSION_INFO VERSIONINFO +FILEVERSION 10,0,17763,1 +PRODUCTVERSION 10,0,17763,1 +FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +FILEFLAGS 0 +FILEOS VOS_NT_WINDOWS32 +FILETYPE VFT_DLL +FILESUBTYPE VFT2_UNKNOWN +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "080904b0" + BEGIN + VALUE "CompanyName", "DXVK" + VALUE "FileDescription", "Direct3D 10 Runtime" + VALUE "FileVersion", "10.0.17763.1 (WinBuild.160101.0800)" + VALUE "InternalName", "D3D10.dll" + VALUE "LegalCopyright", "zlib/libpng license" + VALUE "OriginalFilename", "D3D10.dll" + VALUE "ProductName", "DXVK" + VALUE "ProductVersion", "10.0.17763.1" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0809, 1200 + END +END + diff --git a/utils/dxvk-1.10.3/src/d3d10/version10_1.rc b/utils/dxvk-1.10.3/src/d3d10/version10_1.rc new file mode 100644 index 00000000000..92550d32254 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/version10_1.rc @@ -0,0 +1,32 @@ +#include + +// DLL version information. +VS_VERSION_INFO VERSIONINFO +FILEVERSION 10,0,17763,1 +PRODUCTVERSION 10,0,17763,1 +FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +FILEFLAGS 0 +FILEOS VOS_NT_WINDOWS32 +FILETYPE VFT_DLL +FILESUBTYPE VFT2_UNKNOWN +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "080904b0" + BEGIN + VALUE "CompanyName", "DXVK" + VALUE "FileDescription", "Direct3D 10.1 Runtime" + VALUE "FileVersion", "10.0.17763.1 (WinBuild.160101.0800)" + VALUE "InternalName", "D3D10_1.dll" + VALUE "LegalCopyright", "zlib/libpng license" + VALUE "OriginalFilename", "D3D10_1.dll" + VALUE "ProductName", "DXVK" + VALUE "ProductVersion", "10.0.17763.1" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0809, 1200 + END +END + diff --git a/utils/dxvk-1.10.3/src/d3d10/version10_core.rc b/utils/dxvk-1.10.3/src/d3d10/version10_core.rc new file mode 100644 index 00000000000..30e0c056b3b --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d10/version10_core.rc @@ -0,0 +1,32 @@ +#include + +// DLL version information. +VS_VERSION_INFO VERSIONINFO +FILEVERSION 10,0,17763,1 +PRODUCTVERSION 10,0,17763,1 +FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +FILEFLAGS 0 +FILEOS VOS_NT_WINDOWS32 +FILETYPE VFT_DLL +FILESUBTYPE VFT2_UNKNOWN +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "080904b0" + BEGIN + VALUE "CompanyName", "DXVK" + VALUE "FileDescription", "Direct3D 10 Runtime" + VALUE "FileVersion", "10.0.17763.1 (WinBuild.160101.0800)" + VALUE "InternalName", "D3D10Core.dll" + VALUE "LegalCopyright", "zlib/libpng license" + VALUE "OriginalFilename", "D3D10Core.dll" + VALUE "ProductName", "DXVK" + VALUE "ProductVersion", "10.0.17763.1" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0809, 1200 + END +END + diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11.def b/utils/dxvk-1.10.3/src/d3d11/d3d11.def new file mode 100644 index 00000000000..d406ba0b3b5 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11.def @@ -0,0 +1,6 @@ +LIBRARY D3D11.DLL +EXPORTS + D3D11CoreCreateDevice @18 + D3D11CreateDevice @22 + D3D11CreateDeviceAndSwapChain @23 + D3D11On12CreateDevice @24 diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_annotation.cpp b/utils/dxvk-1.10.3/src/d3d11/d3d11_annotation.cpp new file mode 100644 index 00000000000..7c74b7ad347 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_annotation.cpp @@ -0,0 +1,129 @@ +#include "d3d11_annotation.h" +#include "d3d11_context.h" +#include "d3d11_device.h" + +#include "../util/util_misc.h" + +namespace dxvk { + + template + static void RegisterUserDefinedAnnotation(IDXVKUserDefinedAnnotation* annotation) { + using RegistrationFunctionType = void(__stdcall *)(IDXVKUserDefinedAnnotation*); + static const int16_t RegisterOrdinal = 28257; + static const int16_t UnregisterOrdinal = 28258; + + HMODULE d3d9Module = ::LoadLibraryA("d3d9.dll"); + if (!d3d9Module) { + Logger::info("Unable to find d3d9, some annotations may be missed."); + return; + } + + const int16_t ordinal = Register ? RegisterOrdinal : UnregisterOrdinal; + auto registrationFunction = reinterpret_cast(::GetProcAddress(d3d9Module, + reinterpret_cast(static_cast(ordinal)))); + + if (!registrationFunction) { + Logger::info("Unable to find DXVK_RegisterAnnotation, some annotations may be missed."); + return; + } + + registrationFunction(annotation); + } + + D3D11UserDefinedAnnotation::D3D11UserDefinedAnnotation(D3D11DeviceContext* ctx) + : m_container(ctx), + m_eventDepth(0) { + if (m_container->IsAnnotationEnabled()) + RegisterUserDefinedAnnotation(this); + } + + D3D11UserDefinedAnnotation::D3D11UserDefinedAnnotation(const D3D11UserDefinedAnnotation&) + { + if (m_container->IsAnnotationEnabled()) + RegisterUserDefinedAnnotation(this); + } + + D3D11UserDefinedAnnotation::~D3D11UserDefinedAnnotation() { + if (m_container->IsAnnotationEnabled()) + RegisterUserDefinedAnnotation(this); + } + + + ULONG STDMETHODCALLTYPE D3D11UserDefinedAnnotation::AddRef() { + return m_container->AddRef(); + } + + + ULONG STDMETHODCALLTYPE D3D11UserDefinedAnnotation::Release() { + return m_container->Release(); + } + + + HRESULT STDMETHODCALLTYPE D3D11UserDefinedAnnotation::QueryInterface( + REFIID riid, + void** ppvObject) { + return m_container->QueryInterface(riid, ppvObject); + } + + + INT STDMETHODCALLTYPE D3D11UserDefinedAnnotation::BeginEvent( + D3DCOLOR Color, + LPCWSTR Name) { + if (!m_container->IsAnnotationEnabled()) + return -1; + + D3D10DeviceLock lock = m_container->LockContext(); + + m_container->EmitCs([color = Color, labelName = dxvk::str::fromws(Name)](DxvkContext *ctx) { + VkDebugUtilsLabelEXT label; + label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT; + label.pNext = nullptr; + label.pLabelName = labelName.c_str(); + DecodeD3DCOLOR(color, label.color); + + ctx->beginDebugLabel(&label); + }); + + return m_eventDepth++; + } + + + INT STDMETHODCALLTYPE D3D11UserDefinedAnnotation::EndEvent() { + if (!m_container->IsAnnotationEnabled()) + return -1; + + D3D10DeviceLock lock = m_container->LockContext(); + + m_container->EmitCs([](DxvkContext *ctx) { + ctx->endDebugLabel(); + }); + + return m_eventDepth--; + } + + + void STDMETHODCALLTYPE D3D11UserDefinedAnnotation::SetMarker( + D3DCOLOR Color, + LPCWSTR Name) { + if (!m_container->IsAnnotationEnabled()) + return; + + D3D10DeviceLock lock = m_container->LockContext(); + + m_container->EmitCs([color = Color, labelName = dxvk::str::fromws(Name)](DxvkContext *ctx) { + VkDebugUtilsLabelEXT label; + label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT; + label.pNext = nullptr; + label.pLabelName = labelName.c_str(); + DecodeD3DCOLOR(color, label.color); + + ctx->insertDebugLabel(&label); + }); + } + + + BOOL STDMETHODCALLTYPE D3D11UserDefinedAnnotation::GetStatus() { + return m_container->IsAnnotationEnabled(); + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_annotation.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_annotation.h new file mode 100644 index 00000000000..06d80af6163 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_annotation.h @@ -0,0 +1,46 @@ +#pragma once + +#include "d3d11_include.h" +#include "../dxvk/dxvk_annotation.h" + +namespace dxvk { + + class D3D11DeviceContext; + + class D3D11UserDefinedAnnotation final : public IDXVKUserDefinedAnnotation { + + public: + + D3D11UserDefinedAnnotation(D3D11DeviceContext* ctx); + D3D11UserDefinedAnnotation(const D3D11UserDefinedAnnotation&); + ~D3D11UserDefinedAnnotation(); + + ULONG STDMETHODCALLTYPE AddRef(); + + ULONG STDMETHODCALLTYPE Release(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + INT STDMETHODCALLTYPE BeginEvent( + D3DCOLOR Color, + LPCWSTR Name); + + INT STDMETHODCALLTYPE EndEvent(); + + void STDMETHODCALLTYPE SetMarker( + D3DCOLOR Color, + LPCWSTR Name); + + BOOL STDMETHODCALLTYPE GetStatus(); + + private: + + D3D11DeviceContext* m_container; + + // Stack depth for non-finalized BeginEvent calls + int32_t m_eventDepth; + }; + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_blend.cpp b/utils/dxvk-1.10.3/src/d3d11/d3d11_blend.cpp new file mode 100644 index 00000000000..caacc869e52 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_blend.cpp @@ -0,0 +1,309 @@ +#include "d3d11_blend.h" +#include "d3d11_device.h" + +namespace dxvk { + + D3D11BlendState::D3D11BlendState( + D3D11Device* device, + const D3D11_BLEND_DESC1& desc) + : D3D11StateObject(device), + m_desc(desc), m_d3d10(this) { + // If Independent Blend is disabled, we must ignore the + // blend modes for render target 1 to 7. In Vulkan, all + // blend modes need to be identical in that case. + for (uint32_t i = 0; i < m_blendModes.size(); i++) { + m_blendModes.at(i) = DecodeBlendMode( + desc.IndependentBlendEnable + ? desc.RenderTarget[i] + : desc.RenderTarget[0]); + } + + // Multisample state is part of the blend state in D3D11 + m_msState.sampleMask = 0; // Set during bind + m_msState.enableAlphaToCoverage = desc.AlphaToCoverageEnable; + + // Vulkan only supports a global logic op for the blend + // state, which might be problematic in some cases. + if (desc.IndependentBlendEnable && desc.RenderTarget[0].LogicOpEnable) + Logger::warn("D3D11: Per-target logic ops not supported"); + + m_loState.enableLogicOp = desc.RenderTarget[0].LogicOpEnable; + m_loState.logicOp = DecodeLogicOp(desc.RenderTarget[0].LogicOp); + } + + + D3D11BlendState::~D3D11BlendState() { + + } + + + HRESULT STDMETHODCALLTYPE D3D11BlendState::QueryInterface(REFIID riid, void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(ID3D11DeviceChild) + || riid == __uuidof(ID3D11BlendState) + || riid == __uuidof(ID3D11BlendState1)) { + *ppvObject = ref(this); + return S_OK; + } + + if (riid == __uuidof(ID3D10DeviceChild) + || riid == __uuidof(ID3D10BlendState) + || riid == __uuidof(ID3D10BlendState1)) { + *ppvObject = ref(&m_d3d10); + return S_OK; + } + + Logger::warn("D3D11BlendState::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + void STDMETHODCALLTYPE D3D11BlendState::GetDesc(D3D11_BLEND_DESC* pDesc) { + pDesc->AlphaToCoverageEnable = m_desc.AlphaToCoverageEnable; + pDesc->IndependentBlendEnable = m_desc.IndependentBlendEnable; + + for (uint32_t i = 0; i < 8; i++) { + pDesc->RenderTarget[i].BlendEnable = m_desc.RenderTarget[i].BlendEnable; + pDesc->RenderTarget[i].SrcBlend = m_desc.RenderTarget[i].SrcBlend; + pDesc->RenderTarget[i].DestBlend = m_desc.RenderTarget[i].DestBlend; + pDesc->RenderTarget[i].BlendOp = m_desc.RenderTarget[i].BlendOp; + pDesc->RenderTarget[i].SrcBlendAlpha = m_desc.RenderTarget[i].SrcBlendAlpha; + pDesc->RenderTarget[i].DestBlendAlpha = m_desc.RenderTarget[i].DestBlendAlpha; + pDesc->RenderTarget[i].BlendOpAlpha = m_desc.RenderTarget[i].BlendOpAlpha; + pDesc->RenderTarget[i].RenderTargetWriteMask = m_desc.RenderTarget[i].RenderTargetWriteMask; + } + } + + + void STDMETHODCALLTYPE D3D11BlendState::GetDesc1(D3D11_BLEND_DESC1* pDesc) { + *pDesc = m_desc; + } + + + void D3D11BlendState::BindToContext( + const Rc& ctx, + uint32_t sampleMask) const { + // We handled Independent Blend during object creation + // already, so if it is disabled, all elements in the + // blend mode array will be identical + for (uint32_t i = 0; i < m_blendModes.size(); i++) + ctx->setBlendMode(i, m_blendModes.at(i)); + + // The sample mask is dynamic state in D3D11 + DxvkMultisampleState msState = m_msState; + msState.sampleMask = sampleMask; + ctx->setMultisampleState(msState); + + // Set up logic op state as well + ctx->setLogicOpState(m_loState); + } + + + D3D11_BLEND_DESC1 D3D11BlendState::PromoteDesc(const D3D11_BLEND_DESC* pSrcDesc) { + D3D11_BLEND_DESC1 dstDesc; + dstDesc.AlphaToCoverageEnable = pSrcDesc->AlphaToCoverageEnable; + dstDesc.IndependentBlendEnable = pSrcDesc->IndependentBlendEnable; + + for (uint32_t i = 0; i < 8; i++) { + dstDesc.RenderTarget[i].BlendEnable = pSrcDesc->RenderTarget[i].BlendEnable; + dstDesc.RenderTarget[i].LogicOpEnable = FALSE; + dstDesc.RenderTarget[i].SrcBlend = pSrcDesc->RenderTarget[i].SrcBlend; + dstDesc.RenderTarget[i].DestBlend = pSrcDesc->RenderTarget[i].DestBlend; + dstDesc.RenderTarget[i].BlendOp = pSrcDesc->RenderTarget[i].BlendOp; + dstDesc.RenderTarget[i].SrcBlendAlpha = pSrcDesc->RenderTarget[i].SrcBlendAlpha; + dstDesc.RenderTarget[i].DestBlendAlpha = pSrcDesc->RenderTarget[i].DestBlendAlpha; + dstDesc.RenderTarget[i].BlendOpAlpha = pSrcDesc->RenderTarget[i].BlendOpAlpha; + dstDesc.RenderTarget[i].LogicOp = D3D11_LOGIC_OP_NOOP; + dstDesc.RenderTarget[i].RenderTargetWriteMask = pSrcDesc->RenderTarget[i].RenderTargetWriteMask; + } + + return dstDesc; + } + + + HRESULT D3D11BlendState::NormalizeDesc(D3D11_BLEND_DESC1* pDesc) { + if (pDesc->AlphaToCoverageEnable) + pDesc->AlphaToCoverageEnable = TRUE; + + if (pDesc->IndependentBlendEnable) + pDesc->IndependentBlendEnable = TRUE; + + const uint32_t numRenderTargets = pDesc->IndependentBlendEnable ? 8 : 1; + + for (uint32_t i = 0; i < numRenderTargets; i++) { + D3D11_RENDER_TARGET_BLEND_DESC1* rt = &pDesc->RenderTarget[i]; + + if (rt->BlendEnable) { + rt->BlendEnable = TRUE; + + if (rt->LogicOpEnable) + return E_INVALIDARG; + + if (!ValidateBlendOperations( + rt->SrcBlend, rt->SrcBlendAlpha, + rt->DestBlend, rt->DestBlendAlpha, + rt->BlendOp, rt->BlendOpAlpha)) + return E_INVALIDARG; + } else { + rt->SrcBlend = D3D11_BLEND_ONE; + rt->DestBlend = D3D11_BLEND_ZERO; + rt->BlendOp = D3D11_BLEND_OP_ADD; + rt->SrcBlendAlpha = D3D11_BLEND_ONE; + rt->DestBlendAlpha = D3D11_BLEND_ZERO; + rt->BlendOpAlpha = D3D11_BLEND_OP_ADD; + } + + if (rt->LogicOpEnable) { + rt->LogicOpEnable = TRUE; + + // Blending must be disabled + // if the logic op is enabled + if (rt->BlendEnable + || pDesc->IndependentBlendEnable + || !ValidateLogicOp(rt->LogicOp)) + return E_INVALIDARG; + } else { + rt->LogicOp = D3D11_LOGIC_OP_NOOP; + } + + if (rt->RenderTargetWriteMask > D3D11_COLOR_WRITE_ENABLE_ALL) + return E_INVALIDARG; + } + + for (uint32_t i = numRenderTargets; i < 8; i++) { + // Render targets blend operations are the same + // across all render targets when blend is enabled + // on rendertarget[0] with independent blend disabled + pDesc->RenderTarget[i] = pDesc->RenderTarget[0]; + } + + return S_OK; + } + + + DxvkBlendMode D3D11BlendState::DecodeBlendMode( + const D3D11_RENDER_TARGET_BLEND_DESC1& BlendDesc) { + DxvkBlendMode mode; + mode.enableBlending = BlendDesc.BlendEnable; + mode.colorSrcFactor = DecodeBlendFactor(BlendDesc.SrcBlend, false); + mode.colorDstFactor = DecodeBlendFactor(BlendDesc.DestBlend, false); + mode.colorBlendOp = DecodeBlendOp(BlendDesc.BlendOp); + mode.alphaSrcFactor = DecodeBlendFactor(BlendDesc.SrcBlendAlpha, true); + mode.alphaDstFactor = DecodeBlendFactor(BlendDesc.DestBlendAlpha, true); + mode.alphaBlendOp = DecodeBlendOp(BlendDesc.BlendOpAlpha); + mode.writeMask = BlendDesc.RenderTargetWriteMask; + return mode; + } + + + VkBlendFactor D3D11BlendState::DecodeBlendFactor(D3D11_BLEND BlendFactor, bool IsAlpha) { + switch (BlendFactor) { + case D3D11_BLEND_ZERO: return VK_BLEND_FACTOR_ZERO; + case D3D11_BLEND_ONE: return VK_BLEND_FACTOR_ONE; + case D3D11_BLEND_SRC_COLOR: return VK_BLEND_FACTOR_SRC_COLOR; + case D3D11_BLEND_INV_SRC_COLOR: return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR; + case D3D11_BLEND_SRC_ALPHA: return VK_BLEND_FACTOR_SRC_ALPHA; + case D3D11_BLEND_INV_SRC_ALPHA: return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + case D3D11_BLEND_DEST_ALPHA: return VK_BLEND_FACTOR_DST_ALPHA; + case D3D11_BLEND_INV_DEST_ALPHA: return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA; + case D3D11_BLEND_DEST_COLOR: return VK_BLEND_FACTOR_DST_COLOR; + case D3D11_BLEND_INV_DEST_COLOR: return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR; + case D3D11_BLEND_SRC_ALPHA_SAT: return VK_BLEND_FACTOR_SRC_ALPHA_SATURATE; + case D3D11_BLEND_BLEND_FACTOR: return IsAlpha ? VK_BLEND_FACTOR_CONSTANT_ALPHA : VK_BLEND_FACTOR_CONSTANT_COLOR; + case D3D11_BLEND_INV_BLEND_FACTOR: return IsAlpha ? VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA : VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR; + case D3D11_BLEND_SRC1_COLOR: return VK_BLEND_FACTOR_SRC1_COLOR; + case D3D11_BLEND_INV_SRC1_COLOR: return VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR; + case D3D11_BLEND_SRC1_ALPHA: return VK_BLEND_FACTOR_SRC1_ALPHA; + case D3D11_BLEND_INV_SRC1_ALPHA: return VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA; + default: return VK_BLEND_FACTOR_ZERO; + } + } + + + VkBlendOp D3D11BlendState::DecodeBlendOp(D3D11_BLEND_OP BlendOp) { + switch (BlendOp) { + case D3D11_BLEND_OP_ADD: return VK_BLEND_OP_ADD; + case D3D11_BLEND_OP_SUBTRACT: return VK_BLEND_OP_SUBTRACT; + case D3D11_BLEND_OP_REV_SUBTRACT: return VK_BLEND_OP_REVERSE_SUBTRACT; + case D3D11_BLEND_OP_MIN: return VK_BLEND_OP_MIN; + case D3D11_BLEND_OP_MAX: return VK_BLEND_OP_MAX; + default: return VK_BLEND_OP_ADD; + } + } + + + VkLogicOp D3D11BlendState::DecodeLogicOp(D3D11_LOGIC_OP LogicOp) { + switch (LogicOp) { + case D3D11_LOGIC_OP_CLEAR: return VK_LOGIC_OP_CLEAR; + case D3D11_LOGIC_OP_SET: return VK_LOGIC_OP_SET; + case D3D11_LOGIC_OP_COPY: return VK_LOGIC_OP_COPY; + case D3D11_LOGIC_OP_COPY_INVERTED: return VK_LOGIC_OP_COPY_INVERTED; + case D3D11_LOGIC_OP_NOOP: return VK_LOGIC_OP_NO_OP; + case D3D11_LOGIC_OP_INVERT: return VK_LOGIC_OP_INVERT; + case D3D11_LOGIC_OP_AND: return VK_LOGIC_OP_AND; + case D3D11_LOGIC_OP_NAND: return VK_LOGIC_OP_NAND; + case D3D11_LOGIC_OP_OR: return VK_LOGIC_OP_OR; + case D3D11_LOGIC_OP_NOR: return VK_LOGIC_OP_NOR; + case D3D11_LOGIC_OP_XOR: return VK_LOGIC_OP_XOR; + case D3D11_LOGIC_OP_EQUIV: return VK_LOGIC_OP_EQUIVALENT; + case D3D11_LOGIC_OP_AND_REVERSE: return VK_LOGIC_OP_AND_REVERSE; + case D3D11_LOGIC_OP_AND_INVERTED: return VK_LOGIC_OP_AND_INVERTED; + case D3D11_LOGIC_OP_OR_REVERSE: return VK_LOGIC_OP_OR_REVERSE; + case D3D11_LOGIC_OP_OR_INVERTED: return VK_LOGIC_OP_OR_INVERTED; + default: return VK_LOGIC_OP_NO_OP; + } + } + + + bool D3D11BlendState::ValidateBlendFactor(D3D11_BLEND Blend) { + return Blend >= D3D11_BLEND_ZERO + && Blend <= D3D11_BLEND_INV_SRC1_ALPHA; + } + + + bool D3D11BlendState::ValidateBlendFactorAlpha(D3D11_BLEND BlendAlpha) { + return BlendAlpha >= D3D11_BLEND_ZERO + && BlendAlpha <= D3D11_BLEND_INV_SRC1_ALPHA + && BlendAlpha != D3D11_BLEND_SRC_COLOR + && BlendAlpha != D3D11_BLEND_INV_SRC_COLOR + && BlendAlpha != D3D11_BLEND_DEST_COLOR + && BlendAlpha != D3D11_BLEND_INV_DEST_COLOR + && BlendAlpha != D3D11_BLEND_SRC1_COLOR + && BlendAlpha != D3D11_BLEND_INV_SRC1_COLOR; + } + + + bool D3D11BlendState::ValidateBlendOp(D3D11_BLEND_OP BlendOp) { + return BlendOp >= D3D11_BLEND_OP_ADD + && BlendOp <= D3D11_BLEND_OP_MAX; + } + + + bool D3D11BlendState::ValidateLogicOp(D3D11_LOGIC_OP LogicOp) { + return LogicOp >= D3D11_LOGIC_OP_CLEAR + && LogicOp <= D3D11_LOGIC_OP_OR_INVERTED; + } + + + bool D3D11BlendState::ValidateBlendOperations( + D3D11_BLEND SrcBlend, + D3D11_BLEND SrcBlendAlpha, + D3D11_BLEND DestBlend, + D3D11_BLEND DestBlendAlpha, + D3D11_BLEND_OP BlendOp, + D3D11_BLEND_OP BlendOpAlpha) { + return ValidateBlendOp(BlendOp) + && ValidateBlendOp(BlendOpAlpha) + && ValidateBlendFactor(SrcBlend) + && ValidateBlendFactor(DestBlend) + && ValidateBlendFactorAlpha(SrcBlendAlpha) + && ValidateBlendFactorAlpha(DestBlendAlpha); + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_blend.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_blend.h new file mode 100644 index 00000000000..5761d3ca724 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_blend.h @@ -0,0 +1,93 @@ +#pragma once + +#include "../dxvk/dxvk_device.h" + +#include "../d3d10/d3d10_blend.h" + +#include "d3d11_device_child.h" +#include "d3d11_util.h" + +namespace dxvk { + + class D3D11Device; + + class D3D11BlendState : public D3D11StateObject { + + public: + + using DescType = D3D11_BLEND_DESC1; + + D3D11BlendState( + D3D11Device* device, + const D3D11_BLEND_DESC1& desc); + ~D3D11BlendState(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject) final; + + void STDMETHODCALLTYPE GetDesc( + D3D11_BLEND_DESC* pDesc) final; + + void STDMETHODCALLTYPE GetDesc1( + D3D11_BLEND_DESC1* pDesc) final; + + void BindToContext( + const Rc& ctx, + UINT sampleMask) const; + + D3D10BlendState* GetD3D10Iface() { + return &m_d3d10; + } + + static D3D11_BLEND_DESC1 PromoteDesc( + const D3D11_BLEND_DESC* pSrcDesc); + + static HRESULT NormalizeDesc( + D3D11_BLEND_DESC1* pDesc); + + private: + + D3D11_BLEND_DESC1 m_desc; + + std::array m_blendModes; + DxvkMultisampleState m_msState; + DxvkLogicOpState m_loState; + + D3D10BlendState m_d3d10; + + static DxvkBlendMode DecodeBlendMode( + const D3D11_RENDER_TARGET_BLEND_DESC1& BlendDesc); + + static VkBlendFactor DecodeBlendFactor( + D3D11_BLEND BlendFactor, + bool IsAlpha); + + static VkBlendOp DecodeBlendOp( + D3D11_BLEND_OP BlendOp); + + static VkLogicOp DecodeLogicOp( + D3D11_LOGIC_OP LogicOp); + + static bool ValidateBlendFactor( + D3D11_BLEND Blend); + + static bool ValidateBlendFactorAlpha( + D3D11_BLEND BlendAlpha); + + static bool ValidateBlendOp( + D3D11_BLEND_OP BlendOp); + + static bool ValidateLogicOp( + D3D11_LOGIC_OP LogicOp); + + static bool ValidateBlendOperations( + D3D11_BLEND SrcBlend, + D3D11_BLEND SrcBlendAlpha, + D3D11_BLEND SestBlend, + D3D11_BLEND DestBlendAlpha, + D3D11_BLEND_OP BlendOp, + D3D11_BLEND_OP BlendOpAlpha); + }; + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_buffer.cpp b/utils/dxvk-1.10.3/src/d3d11/d3d11_buffer.cpp new file mode 100644 index 00000000000..eb72fc1b9db --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_buffer.cpp @@ -0,0 +1,299 @@ +#include "d3d11_buffer.h" +#include "d3d11_context.h" +#include "d3d11_device.h" + +#include "../dxvk/dxvk_data.h" + +namespace dxvk { + + D3D11Buffer::D3D11Buffer( + D3D11Device* pDevice, + const D3D11_BUFFER_DESC* pDesc) + : D3D11DeviceChild(pDevice), + m_desc (*pDesc), + m_resource (this), + m_d3d10 (this) { + DxvkBufferCreateInfo info; + info.size = pDesc->ByteWidth; + info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT + | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT; + info.access = VK_ACCESS_TRANSFER_READ_BIT + | VK_ACCESS_TRANSFER_WRITE_BIT; + + if (pDesc->BindFlags & D3D11_BIND_VERTEX_BUFFER) { + info.usage |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; + info.stages |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT; + info.access |= VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; + } + + if (pDesc->BindFlags & D3D11_BIND_INDEX_BUFFER) { + info.usage |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT; + info.stages |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT; + info.access |= VK_ACCESS_INDEX_READ_BIT; + } + + if (pDesc->BindFlags & D3D11_BIND_CONSTANT_BUFFER) { + info.usage |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; + info.stages |= m_parent->GetEnabledShaderStages(); + info.access |= VK_ACCESS_UNIFORM_READ_BIT; + + if (m_parent->GetOptions()->constantBufferRangeCheck) + info.usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + } + + if (pDesc->BindFlags & D3D11_BIND_SHADER_RESOURCE) { + info.usage |= VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT + | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + info.stages |= m_parent->GetEnabledShaderStages(); + info.access |= VK_ACCESS_SHADER_READ_BIT; + } + + if (pDesc->BindFlags & D3D11_BIND_STREAM_OUTPUT) { + info.usage |= VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT; + info.stages |= VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT; + info.access |= VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT; + } + + if (pDesc->BindFlags & D3D11_BIND_UNORDERED_ACCESS) { + info.usage |= VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT + | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + info.stages |= m_parent->GetEnabledShaderStages(); + info.access |= VK_ACCESS_SHADER_READ_BIT + | VK_ACCESS_SHADER_WRITE_BIT; + } + + if (pDesc->MiscFlags & D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS) { + info.usage |= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT; + info.stages |= VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT; + info.access |= VK_ACCESS_INDIRECT_COMMAND_READ_BIT; + } + + // Create the buffer and set the entire buffer slice as mapped, + // so that we only have to update it when invalidating th buffer + m_buffer = m_parent->GetDXVKDevice()->createBuffer(info, GetMemoryFlags()); + m_mapped = m_buffer->getSliceHandle(); + + m_mapMode = DetermineMapMode(); + + // For Stream Output buffers we need a counter + if (pDesc->BindFlags & D3D11_BIND_STREAM_OUTPUT) + m_soCounter = CreateSoCounterBuffer(); + } + + + D3D11Buffer::~D3D11Buffer() { + + } + + + HRESULT STDMETHODCALLTYPE D3D11Buffer::QueryInterface(REFIID riid, void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(ID3D11DeviceChild) + || riid == __uuidof(ID3D11Resource) + || riid == __uuidof(ID3D11Buffer)) { + *ppvObject = ref(this); + return S_OK; + } + + if (riid == __uuidof(ID3D10DeviceChild) + || riid == __uuidof(ID3D10Resource) + || riid == __uuidof(ID3D10Buffer)) { + *ppvObject = ref(&m_d3d10); + return S_OK; + } + + if (riid == __uuidof(IDXGIObject) + || riid == __uuidof(IDXGIDeviceSubObject) + || riid == __uuidof(IDXGIResource) + || riid == __uuidof(IDXGIResource1)) { + *ppvObject = ref(&m_resource); + return S_OK; + } + + Logger::warn("D3D11Buffer::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + UINT STDMETHODCALLTYPE D3D11Buffer::GetEvictionPriority() { + return DXGI_RESOURCE_PRIORITY_NORMAL; + } + + + void STDMETHODCALLTYPE D3D11Buffer::SetEvictionPriority(UINT EvictionPriority) { + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::warn("D3D11Buffer::SetEvictionPriority: Stub"); + } + + + void STDMETHODCALLTYPE D3D11Buffer::GetType(D3D11_RESOURCE_DIMENSION* pResourceDimension) { + *pResourceDimension = D3D11_RESOURCE_DIMENSION_BUFFER; + } + + + void STDMETHODCALLTYPE D3D11Buffer::GetDesc(D3D11_BUFFER_DESC* pDesc) { + *pDesc = m_desc; + } + + + bool D3D11Buffer::CheckViewCompatibility( + UINT BindFlags, + DXGI_FORMAT Format) const { + // Check whether the given bind flags are supported + if ((m_desc.BindFlags & BindFlags) != BindFlags) + return false; + + // Structured buffer views use no format + if (Format == DXGI_FORMAT_UNKNOWN) + return (m_desc.MiscFlags & D3D11_RESOURCE_MISC_BUFFER_STRUCTURED) != 0; + + // Check whether the given combination of buffer view + // type and view format is supported by the device + DXGI_VK_FORMAT_INFO viewFormat = m_parent->LookupFormat(Format, DXGI_VK_FORMAT_MODE_ANY); + VkFormatFeatureFlags features = GetBufferFormatFeatures(BindFlags); + + return CheckFormatFeatureSupport(viewFormat.Format, features); + } + + + HRESULT D3D11Buffer::NormalizeBufferProperties(D3D11_BUFFER_DESC* pDesc) { + // Zero-sized buffers are illegal + if (!pDesc->ByteWidth) + return E_INVALIDARG; + + // We don't support tiled resources + if (pDesc->MiscFlags & (D3D11_RESOURCE_MISC_TILE_POOL | D3D11_RESOURCE_MISC_TILED)) + return E_INVALIDARG; + + // Constant buffer size must be a multiple of 16 + if ((pDesc->BindFlags & D3D11_BIND_CONSTANT_BUFFER) + && (pDesc->ByteWidth & 0xF)) + return E_INVALIDARG; + + // Basic validation for structured buffers + if ((pDesc->MiscFlags & D3D11_RESOURCE_MISC_BUFFER_STRUCTURED) + && ((pDesc->MiscFlags & D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS) + || (pDesc->StructureByteStride == 0) + || (pDesc->StructureByteStride & 0x3))) + return E_INVALIDARG; + + // Basic validation for raw buffers + if ((pDesc->MiscFlags & D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS) + && (!(pDesc->BindFlags & (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS)))) + return E_INVALIDARG; + + // Mip generation obviously doesn't work for buffers + if (pDesc->MiscFlags & D3D11_RESOURCE_MISC_GENERATE_MIPS) + return E_INVALIDARG; + + if (!(pDesc->MiscFlags & D3D11_RESOURCE_MISC_BUFFER_STRUCTURED)) + pDesc->StructureByteStride = 0; + + return S_OK; + } + + + BOOL D3D11Buffer::CheckFormatFeatureSupport( + VkFormat Format, + VkFormatFeatureFlags Features) const { + VkFormatProperties properties = m_parent->GetDXVKDevice()->adapter()->formatProperties(Format); + return (properties.bufferFeatures & Features) == Features; + } + + + VkMemoryPropertyFlags D3D11Buffer::GetMemoryFlags() const { + VkMemoryPropertyFlags memoryFlags = 0; + + switch (m_desc.Usage) { + case D3D11_USAGE_IMMUTABLE: + memoryFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + break; + + case D3D11_USAGE_DEFAULT: + memoryFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + + if ((m_desc.BindFlags & D3D11_BIND_CONSTANT_BUFFER) || m_desc.CPUAccessFlags) { + memoryFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT + | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + } + + if (m_desc.CPUAccessFlags & D3D11_CPU_ACCESS_READ) { + memoryFlags |= VK_MEMORY_PROPERTY_HOST_CACHED_BIT; + memoryFlags &= ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + } + break; + + case D3D11_USAGE_DYNAMIC: + memoryFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT + | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + + if (m_desc.BindFlags) + memoryFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + break; + + case D3D11_USAGE_STAGING: + memoryFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT + | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT + | VK_MEMORY_PROPERTY_HOST_CACHED_BIT; + break; + } + + bool useCached = (m_parent->GetOptions()->cachedDynamicResources == ~0u) + || (m_parent->GetOptions()->cachedDynamicResources & m_desc.BindFlags); + + if ((memoryFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) && useCached) { + memoryFlags |= VK_MEMORY_PROPERTY_HOST_COHERENT_BIT + | VK_MEMORY_PROPERTY_HOST_CACHED_BIT; + } + + return memoryFlags; + } + + + Rc D3D11Buffer::CreateSoCounterBuffer() { + Rc device = m_parent->GetDXVKDevice(); + + DxvkBufferCreateInfo info; + info.size = sizeof(D3D11SOCounter); + info.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_TRANSFER_SRC_BIT + | VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT + | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT; + info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT + | VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT + | VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT; + info.access = VK_ACCESS_TRANSFER_READ_BIT + | VK_ACCESS_TRANSFER_WRITE_BIT + | VK_ACCESS_INDIRECT_COMMAND_READ_BIT + | VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT + | VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT; + return device->createBuffer(info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + } + + + D3D11_COMMON_BUFFER_MAP_MODE D3D11Buffer::DetermineMapMode() { + return (m_buffer->memFlags() & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) + ? D3D11_COMMON_BUFFER_MAP_MODE_DIRECT + : D3D11_COMMON_BUFFER_MAP_MODE_NONE; + } + + + D3D11Buffer* GetCommonBuffer(ID3D11Resource* pResource) { + D3D11_RESOURCE_DIMENSION dimension = D3D11_RESOURCE_DIMENSION_UNKNOWN; + pResource->GetType(&dimension); + + return dimension == D3D11_RESOURCE_DIMENSION_BUFFER + ? static_cast(pResource) + : nullptr; + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_buffer.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_buffer.h new file mode 100644 index 00000000000..c0472fd65ce --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_buffer.h @@ -0,0 +1,180 @@ +#pragma once + +#include "../dxvk/dxvk_cs.h" +#include "../dxvk/dxvk_device.h" + +#include "../d3d10/d3d10_buffer.h" + +#include "d3d11_device_child.h" +#include "d3d11_interfaces.h" +#include "d3d11_resource.h" + +namespace dxvk { + + class D3D11Device; + class D3D11DeviceContext; + + + /** + * \brief Buffer map mode + */ + enum D3D11_COMMON_BUFFER_MAP_MODE { + D3D11_COMMON_BUFFER_MAP_MODE_NONE, + D3D11_COMMON_BUFFER_MAP_MODE_DIRECT, + }; + + + /** + * \brief Stream output buffer offset + * + * A byte offset into the buffer that + * stores the byte offset where new + * data will be written to. + */ + struct D3D11SOCounter { + uint32_t byteOffset; + }; + + + class D3D11Buffer : public D3D11DeviceChild { + static constexpr VkDeviceSize BufferSliceAlignment = 64; + public: + + D3D11Buffer( + D3D11Device* pDevice, + const D3D11_BUFFER_DESC* pDesc); + ~D3D11Buffer(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject) final; + + void STDMETHODCALLTYPE GetType( + D3D11_RESOURCE_DIMENSION *pResourceDimension) final; + + UINT STDMETHODCALLTYPE GetEvictionPriority() final; + + void STDMETHODCALLTYPE SetEvictionPriority(UINT EvictionPriority) final; + + void STDMETHODCALLTYPE GetDesc( + D3D11_BUFFER_DESC *pDesc) final; + + bool CheckViewCompatibility( + UINT BindFlags, + DXGI_FORMAT Format) const; + + const D3D11_BUFFER_DESC* Desc() const { + return &m_desc; + } + + D3D11_COMMON_BUFFER_MAP_MODE GetMapMode() const { + return m_mapMode; + } + + Rc GetBuffer() const { + return m_buffer; + } + + DxvkBufferSlice GetBufferSlice() const { + return DxvkBufferSlice(m_buffer, 0, m_desc.ByteWidth); + } + + DxvkBufferSlice GetBufferSlice(VkDeviceSize offset) const { + VkDeviceSize size = m_desc.ByteWidth; + + return likely(offset < size) + ? DxvkBufferSlice(m_buffer, offset, size - offset) + : DxvkBufferSlice(); + } + + DxvkBufferSlice GetBufferSlice(VkDeviceSize offset, VkDeviceSize length) const { + VkDeviceSize size = m_desc.ByteWidth; + + return likely(offset < size) + ? DxvkBufferSlice(m_buffer, offset, std::min(length, size - offset)) + : DxvkBufferSlice(); + } + + DxvkBufferSlice GetSOCounter() { + return m_soCounter != nullptr + ? DxvkBufferSlice(m_soCounter) + : DxvkBufferSlice(); + } + + DxvkBufferSliceHandle AllocSlice() { + return m_buffer->allocSlice(); + } + + DxvkBufferSliceHandle DiscardSlice() { + m_mapped = m_buffer->allocSlice(); + return m_mapped; + } + + DxvkBufferSliceHandle GetMappedSlice() const { + return m_mapped; + } + + D3D10Buffer* GetD3D10Iface() { + return &m_d3d10; + } + + bool HasSequenceNumber() const { + return m_mapMode != D3D11_COMMON_BUFFER_MAP_MODE_NONE + && !(m_desc.MiscFlags & D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS) + && !(m_desc.BindFlags); + } + + void TrackSequenceNumber(uint64_t Seq) { + m_seq = Seq; + } + + uint64_t GetSequenceNumber() { + return HasSequenceNumber() ? m_seq + : DxvkCsThread::SynchronizeAll; + } + + /** + * \brief Normalizes buffer description + * + * \param [in] pDesc Buffer description + * \returns \c S_OK if the parameters are valid + */ + static HRESULT NormalizeBufferProperties( + D3D11_BUFFER_DESC* pDesc); + + private: + + D3D11_BUFFER_DESC m_desc; + D3D11_COMMON_BUFFER_MAP_MODE m_mapMode; + + Rc m_buffer; + Rc m_soCounter; + DxvkBufferSliceHandle m_mapped; + uint64_t m_seq = 0ull; + + D3D11DXGIResource m_resource; + D3D10Buffer m_d3d10; + + BOOL CheckFormatFeatureSupport( + VkFormat Format, + VkFormatFeatureFlags Features) const; + + VkMemoryPropertyFlags GetMemoryFlags() const; + + Rc CreateSoCounterBuffer(); + + D3D11_COMMON_BUFFER_MAP_MODE DetermineMapMode(); + + }; + + + /** + * \brief Retrieves buffer from resource pointer + * + * \param [in] pResource The resource to query + * \returns Pointer to buffer, or \c nullptr + */ + D3D11Buffer* GetCommonBuffer( + ID3D11Resource* pResource); + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_class_linkage.cpp b/utils/dxvk-1.10.3/src/d3d11/d3d11_class_linkage.cpp new file mode 100644 index 00000000000..8070b660383 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_class_linkage.cpp @@ -0,0 +1,59 @@ +#include "d3d11_class_linkage.h" +#include "d3d11_device.h" + +namespace dxvk { + + D3D11ClassLinkage::D3D11ClassLinkage( + D3D11Device* pDevice) + : D3D11DeviceChild(pDevice) { + + } + + + D3D11ClassLinkage::~D3D11ClassLinkage() { + + } + + + HRESULT STDMETHODCALLTYPE D3D11ClassLinkage::QueryInterface(REFIID riid, void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(ID3D11DeviceChild) + || riid == __uuidof(ID3D11ClassLinkage)) { + *ppvObject = ref(this); + return S_OK; + } + + Logger::warn("D3D11ClassLinkage::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + HRESULT STDMETHODCALLTYPE D3D11ClassLinkage::CreateClassInstance( + LPCSTR pClassTypeName, + UINT ConstantBufferOffset, + UINT ConstantVectorOffset, + UINT TextureOffset, + UINT SamplerOffset, + ID3D11ClassInstance **ppInstance) { + InitReturnPtr(ppInstance); + + Logger::err("D3D11ClassLinkage::CreateClassInstance: Not implemented yet"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE D3D11ClassLinkage::GetClassInstance( + LPCSTR pClassInstanceName, + UINT InstanceIndex, + ID3D11ClassInstance **ppInstance) { + Logger::err("D3D11ClassLinkage::GetClassInstance: Not implemented yet"); + return E_NOTIMPL; + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_class_linkage.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_class_linkage.h new file mode 100644 index 00000000000..7d1c324cc01 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_class_linkage.h @@ -0,0 +1,38 @@ +#pragma once + +#include "d3d11_device_child.h" + +namespace dxvk { + + class D3D11Device; + + // TODO implement properly + class D3D11ClassLinkage : public D3D11DeviceChild { + + public: + + D3D11ClassLinkage( + D3D11Device* pDevice); + + ~D3D11ClassLinkage(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject) final; + + HRESULT STDMETHODCALLTYPE CreateClassInstance( + LPCSTR pClassTypeName, + UINT ConstantBufferOffset, + UINT ConstantVectorOffset, + UINT TextureOffset, + UINT SamplerOffset, + ID3D11ClassInstance **ppInstance); + + HRESULT STDMETHODCALLTYPE GetClassInstance( + LPCSTR pClassInstanceName, + UINT InstanceIndex, + ID3D11ClassInstance **ppInstance); + + }; + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_cmd.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_cmd.h new file mode 100644 index 00000000000..52f2f4dbc97 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_cmd.h @@ -0,0 +1,43 @@ +#pragma once + +#include "d3d11_include.h" + +namespace dxvk { + + /** + * \brief D3D11 command type + * + * Used to identify the type of command + * data most recently added to a CS chunk. + */ + enum class D3D11CmdType { + DrawIndirect, + DrawIndirectIndexed, + }; + + + /** + * \brief Command data header + * + * Stores the command type. All command + * data structs must inherit this struct. + */ + struct D3D11CmdData { + D3D11CmdType type; + }; + + + /** + * \brief Indirect draw command data + * + * Stores the offset into the draw buffer for + * the first draw, as well as the number of + * draws to execute. + */ + struct D3D11CmdDrawIndirectData : public D3D11CmdData { + uint32_t offset; + uint32_t count; + uint32_t stride; + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_cmdlist.cpp b/utils/dxvk-1.10.3/src/d3d11/d3d11_cmdlist.cpp new file mode 100644 index 00000000000..aeb1cd5a20e --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_cmdlist.cpp @@ -0,0 +1,137 @@ +#include "d3d11_cmdlist.h" +#include "d3d11_device.h" +#include "d3d11_buffer.h" +#include "d3d11_texture.h" + +namespace dxvk { + + D3D11CommandList::D3D11CommandList( + D3D11Device* pDevice, + UINT ContextFlags) + : D3D11DeviceChild(pDevice), + m_contextFlags(ContextFlags) { } + + + D3D11CommandList::~D3D11CommandList() { + + } + + + HRESULT STDMETHODCALLTYPE D3D11CommandList::QueryInterface(REFIID riid, void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(ID3D11DeviceChild) + || riid == __uuidof(ID3D11CommandList)) { + *ppvObject = ref(this); + return S_OK; + } + + Logger::warn("D3D11CommandList::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + UINT STDMETHODCALLTYPE D3D11CommandList::GetContextFlags() { + return m_contextFlags; + } + + + void D3D11CommandList::AddChunk(DxvkCsChunkRef&& Chunk) { + m_chunks.push_back(std::move(Chunk)); + } + + + void D3D11CommandList::AddQuery(D3D11Query* pQuery) { + m_queries.emplace_back(pQuery); + } + + + void D3D11CommandList::EmitToCommandList(ID3D11CommandList* pCommandList) { + auto cmdList = static_cast(pCommandList); + + for (const auto& chunk : m_chunks) + cmdList->m_chunks.push_back(chunk); + + for (const auto& query : m_queries) + cmdList->m_queries.push_back(query); + + for (const auto& resource : m_resources) + cmdList->m_resources.push_back(resource); + + MarkSubmitted(); + } + + + uint64_t D3D11CommandList::EmitToCsThread(DxvkCsThread* CsThread) { + uint64_t seq = 0; + + for (const auto& query : m_queries) + query->DoDeferredEnd(); + + for (const auto& chunk : m_chunks) + seq = CsThread->dispatchChunk(DxvkCsChunkRef(chunk)); + + for (const auto& resource : m_resources) + TrackResourceSequenceNumber(resource, seq); + + MarkSubmitted(); + return seq; + } + + + void D3D11CommandList::TrackResourceUsage( + ID3D11Resource* pResource, + D3D11_RESOURCE_DIMENSION ResourceType, + UINT Subresource) { + m_resources.emplace_back(pResource, Subresource, ResourceType); + } + + + void D3D11CommandList::TrackResourceSequenceNumber( + const D3D11ResourceRef& Resource, + uint64_t Seq) { + ID3D11Resource* iface = Resource.Get(); + UINT subresource = Resource.GetSubresource(); + + switch (Resource.GetType()) { + case D3D11_RESOURCE_DIMENSION_UNKNOWN: + break; + + case D3D11_RESOURCE_DIMENSION_BUFFER: { + auto impl = static_cast(iface); + impl->TrackSequenceNumber(Seq); + } break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE1D: { + auto impl = static_cast(iface)->GetCommonTexture(); + impl->TrackSequenceNumber(subresource, Seq); + } break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE2D: { + auto impl = static_cast(iface)->GetCommonTexture(); + impl->TrackSequenceNumber(subresource, Seq); + } break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE3D: { + auto impl = static_cast(iface)->GetCommonTexture(); + impl->TrackSequenceNumber(subresource, Seq); + } break; + } + } + + + void D3D11CommandList::MarkSubmitted() { + if (m_submitted.exchange(true) && !m_warned.exchange(true) + && m_parent->GetOptions()->dcSingleUseMode) { + Logger::warn( + "D3D11: Command list submitted multiple times,\n" + " but d3d11.dcSingleUseMode is enabled"); + } + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_cmdlist.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_cmdlist.h new file mode 100644 index 00000000000..8be313ad626 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_cmdlist.h @@ -0,0 +1,59 @@ +#pragma once + +#include "d3d11_context.h" + +namespace dxvk { + + class D3D11CommandList : public D3D11DeviceChild { + + public: + + D3D11CommandList( + D3D11Device* pDevice, + UINT ContextFlags); + + ~D3D11CommandList(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject) final; + + UINT STDMETHODCALLTYPE GetContextFlags() final; + + void AddChunk( + DxvkCsChunkRef&& Chunk); + + void AddQuery( + D3D11Query* pQuery); + + void EmitToCommandList( + ID3D11CommandList* pCommandList); + + uint64_t EmitToCsThread( + DxvkCsThread* CsThread); + + void TrackResourceUsage( + ID3D11Resource* pResource, + D3D11_RESOURCE_DIMENSION ResourceType, + UINT Subresource); + + private: + + UINT const m_contextFlags; + + std::vector m_chunks; + std::vector> m_queries; + std::vector m_resources; + + std::atomic m_submitted = { false }; + std::atomic m_warned = { false }; + + void TrackResourceSequenceNumber( + const D3D11ResourceRef& Resource, + uint64_t Seq); + + void MarkSubmitted(); + + }; + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_context.cpp b/utils/dxvk-1.10.3/src/d3d11/d3d11_context.cpp new file mode 100644 index 00000000000..c3cba249ca1 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_context.cpp @@ -0,0 +1,4616 @@ +#include + +#include "d3d11_context.h" +#include "d3d11_device.h" +#include "d3d11_query.h" +#include "d3d11_texture.h" +#include "d3d11_video.h" + +#include "../dxbc/dxbc_util.h" + +namespace dxvk { + + D3D11DeviceContext::D3D11DeviceContext( + D3D11Device* pParent, + const Rc& Device, + DxvkCsChunkFlags CsFlags) + : D3D11DeviceChild(pParent), + m_contextExt(this), + m_multithread(this, false), + m_device (Device), + m_staging (Device, StagingBufferSize), + m_annotation(this), + m_csFlags (CsFlags), + m_csChunk (AllocCsChunk()), + m_cmdData (nullptr) { + + } + + + D3D11DeviceContext::~D3D11DeviceContext() { + + } + + + HRESULT STDMETHODCALLTYPE D3D11DeviceContext::QueryInterface(REFIID riid, void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(ID3D11DeviceChild) + || riid == __uuidof(ID3D11DeviceContext) + || riid == __uuidof(ID3D11DeviceContext1) + || riid == __uuidof(ID3D11DeviceContext2) + || riid == __uuidof(ID3D11DeviceContext3) + || riid == __uuidof(ID3D11DeviceContext4)) { + *ppvObject = ref(this); + return S_OK; + } + + if (riid == __uuidof(ID3D11VkExtContext) + || riid == __uuidof(ID3D11VkExtContext1)) { + *ppvObject = ref(&m_contextExt); + return S_OK; + } + + if (riid == __uuidof(ID3DUserDefinedAnnotation) + || riid == __uuidof(IDXVKUserDefinedAnnotation)) { + *ppvObject = ref(&m_annotation); + return S_OK; + } + + if (riid == __uuidof(ID3D10Multithread)) { + *ppvObject = ref(&m_multithread); + return S_OK; + } + + Logger::warn("D3D11DeviceContext::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::DiscardResource(ID3D11Resource* pResource) { + D3D10DeviceLock lock = LockContext(); + + if (!pResource) + return; + + // We don't support the Discard API for images + D3D11_RESOURCE_DIMENSION resType = D3D11_RESOURCE_DIMENSION_UNKNOWN; + pResource->GetType(&resType); + + if (resType == D3D11_RESOURCE_DIMENSION_BUFFER) { + DiscardBuffer(pResource); + } else { + auto texture = GetCommonTexture(pResource); + + for (uint32_t i = 0; i < texture->CountSubresources(); i++) + DiscardTexture(pResource, i); + } + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::DiscardView(ID3D11View* pResourceView) { + DiscardView1(pResourceView, nullptr, 0); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::DiscardView1( + ID3D11View* pResourceView, + const D3D11_RECT* pRects, + UINT NumRects) { + D3D10DeviceLock lock = LockContext(); + + // We don't support discarding individual rectangles + if (!pResourceView || (NumRects && pRects)) + return; + + // ID3D11View has no methods to query the exact type of + // the view, so we'll have to check each possible class + auto dsv = dynamic_cast(pResourceView); + auto rtv = dynamic_cast(pResourceView); + auto uav = dynamic_cast(pResourceView); + + Rc view; + if (dsv) view = dsv->GetImageView(); + if (rtv) view = rtv->GetImageView(); + if (uav) view = uav->GetImageView(); + + if (view == nullptr) + return; + + // Get information about underlying resource + Com resource; + pResourceView->GetResource(&resource); + + uint32_t mipCount = GetCommonTexture(resource.ptr())->Desc()->MipLevels; + + // Discard mip levels one by one + VkImageSubresourceRange sr = view->subresources(); + + for (uint32_t layer = 0; layer < sr.layerCount; layer++) { + for (uint32_t mip = 0; mip < sr.levelCount; mip++) { + DiscardTexture(resource.ptr(), D3D11CalcSubresource( + sr.baseMipLevel + mip, sr.baseArrayLayer + layer, mipCount)); + } + } + + // Since we don't handle SRVs here, we can assume that the + // view covers all aspects of the underlying resource. + EmitCs([cView = view] (DxvkContext* ctx) { + ctx->discardImageView(cView, cView->formatInfo()->aspectMask); + }); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::ClearState() { + D3D10DeviceLock lock = LockContext(); + + // Default shaders + m_state.vs.shader = nullptr; + m_state.hs.shader = nullptr; + m_state.ds.shader = nullptr; + m_state.gs.shader = nullptr; + m_state.ps.shader = nullptr; + m_state.cs.shader = nullptr; + + // Default constant buffers + for (uint32_t i = 0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; i++) { + m_state.vs.constantBuffers[i] = { nullptr, 0, 0 }; + m_state.hs.constantBuffers[i] = { nullptr, 0, 0 }; + m_state.ds.constantBuffers[i] = { nullptr, 0, 0 }; + m_state.gs.constantBuffers[i] = { nullptr, 0, 0 }; + m_state.ps.constantBuffers[i] = { nullptr, 0, 0 }; + m_state.cs.constantBuffers[i] = { nullptr, 0, 0 }; + } + + // Default samplers + for (uint32_t i = 0; i < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; i++) { + m_state.vs.samplers[i] = nullptr; + m_state.hs.samplers[i] = nullptr; + m_state.ds.samplers[i] = nullptr; + m_state.gs.samplers[i] = nullptr; + m_state.ps.samplers[i] = nullptr; + m_state.cs.samplers[i] = nullptr; + } + + // Default shader resources + for (uint32_t i = 0; i < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; i++) { + m_state.vs.shaderResources.views[i] = nullptr; + m_state.hs.shaderResources.views[i] = nullptr; + m_state.ds.shaderResources.views[i] = nullptr; + m_state.gs.shaderResources.views[i] = nullptr; + m_state.ps.shaderResources.views[i] = nullptr; + m_state.cs.shaderResources.views[i] = nullptr; + } + + m_state.vs.shaderResources.hazardous.clear(); + m_state.hs.shaderResources.hazardous.clear(); + m_state.ds.shaderResources.hazardous.clear(); + m_state.gs.shaderResources.hazardous.clear(); + m_state.ps.shaderResources.hazardous.clear(); + m_state.cs.shaderResources.hazardous.clear(); + + // Default UAVs + for (uint32_t i = 0; i < D3D11_1_UAV_SLOT_COUNT; i++) { + m_state.ps.unorderedAccessViews[i] = nullptr; + m_state.cs.unorderedAccessViews[i] = nullptr; + } + + m_state.cs.uavMask.clear(); + + // Default ID state + m_state.id.argBuffer = nullptr; + + // Default IA state + m_state.ia.inputLayout = nullptr; + m_state.ia.primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED; + + for (uint32_t i = 0; i < D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; i++) { + m_state.ia.vertexBuffers[i].buffer = nullptr; + m_state.ia.vertexBuffers[i].offset = 0; + m_state.ia.vertexBuffers[i].stride = 0; + } + + m_state.ia.indexBuffer.buffer = nullptr; + m_state.ia.indexBuffer.offset = 0; + m_state.ia.indexBuffer.format = DXGI_FORMAT_UNKNOWN; + + // Default OM State + for (uint32_t i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) + m_state.om.renderTargetViews[i] = nullptr; + m_state.om.depthStencilView = nullptr; + + m_state.om.cbState = nullptr; + m_state.om.dsState = nullptr; + + for (uint32_t i = 0; i < 4; i++) + m_state.om.blendFactor[i] = 1.0f; + + m_state.om.sampleMask = D3D11_DEFAULT_SAMPLE_MASK; + m_state.om.stencilRef = D3D11_DEFAULT_STENCIL_REFERENCE; + + m_state.om.maxRtv = 0; + m_state.om.maxUav = 0; + + // Default RS state + m_state.rs.state = nullptr; + m_state.rs.numViewports = 0; + m_state.rs.numScissors = 0; + + for (uint32_t i = 0; i < D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; i++) { + m_state.rs.viewports[i] = D3D11_VIEWPORT { }; + m_state.rs.scissors [i] = D3D11_RECT { }; + } + + // Default SO state + for (uint32_t i = 0; i < D3D11_SO_BUFFER_SLOT_COUNT; i++) { + m_state.so.targets[i].buffer = nullptr; + m_state.so.targets[i].offset = 0; + } + + // Default predication + m_state.pr.predicateObject = nullptr; + m_state.pr.predicateValue = FALSE; + + // Make sure to apply all state + ResetState(); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::SetPredication( + ID3D11Predicate* pPredicate, + BOOL PredicateValue) { + D3D10DeviceLock lock = LockContext(); + + auto predicate = D3D11Query::FromPredicate(pPredicate); + m_state.pr.predicateObject = predicate; + m_state.pr.predicateValue = PredicateValue; + + static bool s_errorShown = false; + + if (pPredicate && !std::exchange(s_errorShown, true)) + Logger::err("D3D11DeviceContext::SetPredication: Stub"); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::GetPredication( + ID3D11Predicate** ppPredicate, + BOOL* pPredicateValue) { + D3D10DeviceLock lock = LockContext(); + + if (ppPredicate) + *ppPredicate = D3D11Query::AsPredicate(m_state.pr.predicateObject.ref()); + + if (pPredicateValue) + *pPredicateValue = m_state.pr.predicateValue; + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::CopySubresourceRegion( + ID3D11Resource* pDstResource, + UINT DstSubresource, + UINT DstX, + UINT DstY, + UINT DstZ, + ID3D11Resource* pSrcResource, + UINT SrcSubresource, + const D3D11_BOX* pSrcBox) { + CopySubresourceRegion1( + pDstResource, DstSubresource, DstX, DstY, DstZ, + pSrcResource, SrcSubresource, pSrcBox, 0); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::CopySubresourceRegion1( + ID3D11Resource* pDstResource, + UINT DstSubresource, + UINT DstX, + UINT DstY, + UINT DstZ, + ID3D11Resource* pSrcResource, + UINT SrcSubresource, + const D3D11_BOX* pSrcBox, + UINT CopyFlags) { + D3D10DeviceLock lock = LockContext(); + + if (!pDstResource || !pSrcResource) + return; + + if (pSrcBox + && (pSrcBox->left >= pSrcBox->right + || pSrcBox->top >= pSrcBox->bottom + || pSrcBox->front >= pSrcBox->back)) + return; + + D3D11_RESOURCE_DIMENSION dstResourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN; + D3D11_RESOURCE_DIMENSION srcResourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN; + + pDstResource->GetType(&dstResourceDim); + pSrcResource->GetType(&srcResourceDim); + + if (dstResourceDim == D3D11_RESOURCE_DIMENSION_BUFFER && srcResourceDim == D3D11_RESOURCE_DIMENSION_BUFFER) { + auto dstBuffer = static_cast(pDstResource); + auto srcBuffer = static_cast(pSrcResource); + + VkDeviceSize dstOffset = DstX; + VkDeviceSize srcOffset = 0; + VkDeviceSize byteCount = -1; + + if (pSrcBox) { + srcOffset = pSrcBox->left; + byteCount = pSrcBox->right - pSrcBox->left; + } + + CopyBuffer(dstBuffer, dstOffset, srcBuffer, srcOffset, byteCount); + } else if (dstResourceDim != D3D11_RESOURCE_DIMENSION_BUFFER && srcResourceDim != D3D11_RESOURCE_DIMENSION_BUFFER) { + auto dstTexture = GetCommonTexture(pDstResource); + auto srcTexture = GetCommonTexture(pSrcResource); + + if (DstSubresource >= dstTexture->CountSubresources() + || SrcSubresource >= srcTexture->CountSubresources()) + return; + + auto dstFormatInfo = imageFormatInfo(dstTexture->GetPackedFormat()); + auto srcFormatInfo = imageFormatInfo(srcTexture->GetPackedFormat()); + + auto dstLayers = vk::makeSubresourceLayers(dstTexture->GetSubresourceFromIndex(dstFormatInfo->aspectMask, DstSubresource)); + auto srcLayers = vk::makeSubresourceLayers(srcTexture->GetSubresourceFromIndex(srcFormatInfo->aspectMask, SrcSubresource)); + + VkOffset3D srcOffset = { 0, 0, 0 }; + VkOffset3D dstOffset = { int32_t(DstX), int32_t(DstY), int32_t(DstZ) }; + + VkExtent3D srcExtent = srcTexture->MipLevelExtent(srcLayers.mipLevel); + + if (pSrcBox != nullptr) { + srcOffset.x = pSrcBox->left; + srcOffset.y = pSrcBox->top; + srcOffset.z = pSrcBox->front; + + srcExtent.width = pSrcBox->right - pSrcBox->left; + srcExtent.height = pSrcBox->bottom - pSrcBox->top; + srcExtent.depth = pSrcBox->back - pSrcBox->front; + } + + CopyImage( + dstTexture, &dstLayers, dstOffset, + srcTexture, &srcLayers, srcOffset, + srcExtent); + } else { + Logger::err(str::format( + "D3D11: CopySubresourceRegion1: Incompatible resources", + "\n Dst resource type: ", dstResourceDim, + "\n Src resource type: ", srcResourceDim)); + } + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::CopyResource( + ID3D11Resource* pDstResource, + ID3D11Resource* pSrcResource) { + D3D10DeviceLock lock = LockContext(); + + if (!pDstResource || !pSrcResource || (pDstResource == pSrcResource)) + return; + + D3D11_RESOURCE_DIMENSION dstResourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN; + D3D11_RESOURCE_DIMENSION srcResourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN; + + pDstResource->GetType(&dstResourceDim); + pSrcResource->GetType(&srcResourceDim); + + if (dstResourceDim != srcResourceDim) { + Logger::err(str::format( + "D3D11: CopyResource: Incompatible resources", + "\n Dst resource type: ", dstResourceDim, + "\n Src resource type: ", srcResourceDim)); + return; + } + + if (dstResourceDim == D3D11_RESOURCE_DIMENSION_BUFFER) { + auto dstBuffer = static_cast(pDstResource); + auto srcBuffer = static_cast(pSrcResource); + + if (dstBuffer->Desc()->ByteWidth != srcBuffer->Desc()->ByteWidth) + return; + + CopyBuffer(dstBuffer, 0, srcBuffer, 0, -1); + } else { + auto dstTexture = GetCommonTexture(pDstResource); + auto srcTexture = GetCommonTexture(pSrcResource); + + auto dstDesc = dstTexture->Desc(); + auto srcDesc = srcTexture->Desc(); + + // The subresource count must match as well + if (dstDesc->ArraySize != srcDesc->ArraySize + || dstDesc->MipLevels != srcDesc->MipLevels) { + Logger::err("D3D11: CopyResource: Incompatible images"); + return; + } + + auto dstFormatInfo = imageFormatInfo(dstTexture->GetPackedFormat()); + auto srcFormatInfo = imageFormatInfo(srcTexture->GetPackedFormat()); + + for (uint32_t i = 0; i < dstDesc->MipLevels; i++) { + VkImageSubresourceLayers dstLayers = { dstFormatInfo->aspectMask, i, 0, dstDesc->ArraySize }; + VkImageSubresourceLayers srcLayers = { srcFormatInfo->aspectMask, i, 0, srcDesc->ArraySize }; + + CopyImage( + dstTexture, &dstLayers, VkOffset3D(), + srcTexture, &srcLayers, VkOffset3D(), + srcTexture->MipLevelExtent(i)); + } + } + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::CopyStructureCount( + ID3D11Buffer* pDstBuffer, + UINT DstAlignedByteOffset, + ID3D11UnorderedAccessView* pSrcView) { + D3D10DeviceLock lock = LockContext(); + + auto buf = static_cast(pDstBuffer); + auto uav = static_cast(pSrcView); + + if (!buf || !uav) + return; + + auto counterSlice = uav->GetCounterSlice(); + if (!counterSlice.defined()) + return; + + EmitCs([ + cDstSlice = buf->GetBufferSlice(DstAlignedByteOffset), + cSrcSlice = std::move(counterSlice) + ] (DxvkContext* ctx) { + ctx->copyBuffer( + cDstSlice.buffer(), + cDstSlice.offset(), + cSrcSlice.buffer(), + cSrcSlice.offset(), + sizeof(uint32_t)); + }); + + if (buf->HasSequenceNumber()) + TrackBufferSequenceNumber(buf); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::CopyTiles( + ID3D11Resource* pTiledResource, + const D3D11_TILED_RESOURCE_COORDINATE* pTileRegionStartCoordinate, + const D3D11_TILE_REGION_SIZE* pTileRegionSize, + ID3D11Buffer* pBuffer, + UINT64 BufferStartOffsetInBytes, + UINT Flags) { + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::err("D3D11DeviceContext::CopyTiles: Not implemented"); + } + + + HRESULT STDMETHODCALLTYPE D3D11DeviceContext::CopyTileMappings( + ID3D11Resource* pDestTiledResource, + const D3D11_TILED_RESOURCE_COORDINATE* pDestRegionStartCoordinate, + ID3D11Resource* pSourceTiledResource, + const D3D11_TILED_RESOURCE_COORDINATE* pSourceRegionStartCoordinate, + const D3D11_TILE_REGION_SIZE* pTileRegionSize, + UINT Flags) { + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::err("D3D11DeviceContext::CopyTileMappings: Not implemented"); + + return DXGI_ERROR_INVALID_CALL; + } + + + HRESULT STDMETHODCALLTYPE D3D11DeviceContext::ResizeTilePool( + ID3D11Buffer* pTilePool, + UINT64 NewSizeInBytes) { + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::err("D3D11DeviceContext::ResizeTilePool: Not implemented"); + + return DXGI_ERROR_INVALID_CALL; + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::TiledResourceBarrier( + ID3D11DeviceChild* pTiledResourceOrViewAccessBeforeBarrier, + ID3D11DeviceChild* pTiledResourceOrViewAccessAfterBarrier) { + + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::ClearRenderTargetView( + ID3D11RenderTargetView* pRenderTargetView, + const FLOAT ColorRGBA[4]) { + D3D10DeviceLock lock = LockContext(); + + auto rtv = static_cast(pRenderTargetView); + + if (!rtv) + return; + + auto view = rtv->GetImageView(); + auto color = ConvertColorValue(ColorRGBA, view->formatInfo()); + + EmitCs([ + cClearValue = color, + cImageView = std::move(view) + ] (DxvkContext* ctx) { + ctx->clearRenderTarget( + cImageView, + VK_IMAGE_ASPECT_COLOR_BIT, + cClearValue); + }); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::ClearUnorderedAccessViewUint( + ID3D11UnorderedAccessView* pUnorderedAccessView, + const UINT Values[4]) { + D3D10DeviceLock lock = LockContext(); + + auto uav = static_cast(pUnorderedAccessView); + + if (!uav) + return; + + // Gather UAV format info. We'll use this to determine + // whether we need to create a temporary view or not. + D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc; + uav->GetDesc(&uavDesc); + + VkFormat uavFormat = m_parent->LookupFormat(uavDesc.Format, DXGI_VK_FORMAT_MODE_ANY).Format; + VkFormat rawFormat = m_parent->LookupFormat(uavDesc.Format, DXGI_VK_FORMAT_MODE_RAW).Format; + + if (uavFormat != rawFormat && rawFormat == VK_FORMAT_UNDEFINED) { + Logger::err(str::format("D3D11: ClearUnorderedAccessViewUint: No raw format found for ", uavFormat)); + return; + } + + VkClearValue clearValue; + + // R11G11B10 is a special case since there's no corresponding + // integer format with the same bit layout. Use R32 instead. + if (uavFormat == VK_FORMAT_B10G11R11_UFLOAT_PACK32) { + clearValue.color.uint32[0] = ((Values[0] & 0x7FF) << 0) + | ((Values[1] & 0x7FF) << 11) + | ((Values[2] & 0x3FF) << 22); + clearValue.color.uint32[1] = 0; + clearValue.color.uint32[2] = 0; + clearValue.color.uint32[3] = 0; + } else { + clearValue.color.uint32[0] = Values[0]; + clearValue.color.uint32[1] = Values[1]; + clearValue.color.uint32[2] = Values[2]; + clearValue.color.uint32[3] = Values[3]; + } + + if (uav->GetResourceType() == D3D11_RESOURCE_DIMENSION_BUFFER) { + // In case of raw and structured buffers as well as typed + // buffers that can be used for atomic operations, we can + // use the fast Vulkan buffer clear function. + Rc bufferView = uav->GetBufferView(); + + if (bufferView->info().format == VK_FORMAT_R32_UINT + || bufferView->info().format == VK_FORMAT_R32_SINT + || bufferView->info().format == VK_FORMAT_R32_SFLOAT + || bufferView->info().format == VK_FORMAT_B10G11R11_UFLOAT_PACK32) { + EmitCs([ + cClearValue = clearValue.color.uint32[0], + cDstSlice = bufferView->slice() + ] (DxvkContext* ctx) { + ctx->clearBuffer( + cDstSlice.buffer(), + cDstSlice.offset(), + cDstSlice.length(), + cClearValue); + }); + } else { + // Create a view with an integer format if necessary + if (uavFormat != rawFormat) { + DxvkBufferViewCreateInfo info = bufferView->info(); + info.format = rawFormat; + + bufferView = m_device->createBufferView( + bufferView->buffer(), info); + } + + EmitCs([ + cClearValue = clearValue, + cDstView = bufferView + ] (DxvkContext* ctx) { + ctx->clearBufferView( + cDstView, 0, + cDstView->elementCount(), + cClearValue.color); + }); + } + } else { + Rc imageView = uav->GetImageView(); + + // If the clear value is zero, we can use the original view regardless of + // the format since the bit pattern will not change in any supported format. + bool isZeroClearValue = !(clearValue.color.uint32[0] | clearValue.color.uint32[1] + | clearValue.color.uint32[2] | clearValue.color.uint32[3]); + + // Check if we can create an image view with the given raw format. If not, + // we'll have to use a fallback using a texel buffer view and buffer copies. + bool isViewCompatible = uavFormat == rawFormat; + + if (!isViewCompatible && (imageView->imageInfo().flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT)) { + uint32_t formatCount = imageView->imageInfo().viewFormatCount; + isViewCompatible = formatCount == 0; + + for (uint32_t i = 0; i < formatCount && !isViewCompatible; i++) + isViewCompatible = imageView->imageInfo().viewFormats[i] == rawFormat; + } + + if (isViewCompatible || isZeroClearValue) { + // Create a view with an integer format if necessary + if (uavFormat != rawFormat && !isZeroClearValue) { + DxvkImageViewCreateInfo info = imageView->info(); + info.format = rawFormat; + + imageView = m_device->createImageView(imageView->image(), info); + } + + EmitCs([ + cClearValue = clearValue, + cDstView = imageView + ] (DxvkContext* ctx) { + ctx->clearImageView(cDstView, + VkOffset3D { 0, 0, 0 }, + cDstView->mipLevelExtent(0), + VK_IMAGE_ASPECT_COLOR_BIT, + cClearValue); + }); + } else { + DxvkBufferCreateInfo bufferInfo; + bufferInfo.size = imageView->formatInfo()->elementSize + * imageView->info().numLayers + * util::flattenImageExtent(imageView->mipLevelExtent(0)); + bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT + | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT; + bufferInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT + | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; + bufferInfo.access = VK_ACCESS_TRANSFER_READ_BIT + | VK_ACCESS_SHADER_WRITE_BIT; + + Rc buffer = m_device->createBuffer(bufferInfo, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + + DxvkBufferViewCreateInfo bufferViewInfo; + bufferViewInfo.format = rawFormat; + bufferViewInfo.rangeOffset = 0; + bufferViewInfo.rangeLength = bufferInfo.size; + + Rc bufferView = m_device->createBufferView(buffer, + bufferViewInfo); + + EmitCs([ + cDstView = std::move(imageView), + cSrcView = std::move(bufferView), + cClearValue = clearValue.color + ] (DxvkContext* ctx) { + ctx->clearBufferView( + cSrcView, 0, + cSrcView->elementCount(), + cClearValue); + + ctx->copyBufferToImage(cDstView->image(), + vk::pickSubresourceLayers(cDstView->subresources(), 0), + VkOffset3D { 0, 0, 0 }, + cDstView->mipLevelExtent(0), + cSrcView->buffer(), 0, 0, 0); + }); + } + } + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::ClearUnorderedAccessViewFloat( + ID3D11UnorderedAccessView* pUnorderedAccessView, + const FLOAT Values[4]) { + D3D10DeviceLock lock = LockContext(); + + auto uav = static_cast(pUnorderedAccessView); + + if (!uav) + return; + + auto imgView = uav->GetImageView(); + auto bufView = uav->GetBufferView(); + + const DxvkFormatInfo* info = nullptr; + if (imgView != nullptr) info = imgView->formatInfo(); + if (bufView != nullptr) info = bufView->formatInfo(); + + if (!info || info->flags.any(DxvkFormatFlag::SampledSInt, DxvkFormatFlag::SampledUInt)) + return; + + VkClearValue clearValue; + clearValue.color.float32[0] = Values[0]; + clearValue.color.float32[1] = Values[1]; + clearValue.color.float32[2] = Values[2]; + clearValue.color.float32[3] = Values[3]; + + if (uav->GetResourceType() == D3D11_RESOURCE_DIMENSION_BUFFER) { + EmitCs([ + cClearValue = clearValue, + cDstView = std::move(bufView) + ] (DxvkContext* ctx) { + ctx->clearBufferView( + cDstView, 0, + cDstView->elementCount(), + cClearValue.color); + }); + } else { + EmitCs([ + cClearValue = clearValue, + cDstView = std::move(imgView) + ] (DxvkContext* ctx) { + ctx->clearImageView(cDstView, + VkOffset3D { 0, 0, 0 }, + cDstView->mipLevelExtent(0), + VK_IMAGE_ASPECT_COLOR_BIT, + cClearValue); + }); + } + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::ClearDepthStencilView( + ID3D11DepthStencilView* pDepthStencilView, + UINT ClearFlags, + FLOAT Depth, + UINT8 Stencil) { + D3D10DeviceLock lock = LockContext(); + + auto dsv = static_cast(pDepthStencilView); + + if (!dsv) + return; + + // Figure out which aspects to clear based on + // the image view properties and clear flags. + VkImageAspectFlags aspectMask = 0; + + if (ClearFlags & D3D11_CLEAR_DEPTH) + aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT; + + if (ClearFlags & D3D11_CLEAR_STENCIL) + aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; + + aspectMask &= dsv->GetWritableAspectMask(); + + if (!aspectMask) + return; + + VkClearValue clearValue; + clearValue.depthStencil.depth = Depth; + clearValue.depthStencil.stencil = Stencil; + + EmitCs([ + cClearValue = clearValue, + cAspectMask = aspectMask, + cImageView = dsv->GetImageView() + ] (DxvkContext* ctx) { + ctx->clearRenderTarget( + cImageView, + cAspectMask, + cClearValue); + }); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::ClearView( + ID3D11View* pView, + const FLOAT Color[4], + const D3D11_RECT* pRect, + UINT NumRects) { + D3D10DeviceLock lock = LockContext(); + + if (NumRects && !pRect) + return; + + // ID3D11View has no methods to query the exact type of + // the view, so we'll have to check each possible class + auto dsv = dynamic_cast(pView); + auto rtv = dynamic_cast(pView); + auto uav = dynamic_cast(pView); + auto vov = dynamic_cast(pView); + + // Retrieve underlying resource view + Rc bufView; + Rc imgView; + + if (dsv != nullptr) + imgView = dsv->GetImageView(); + + if (rtv != nullptr) + imgView = rtv->GetImageView(); + + if (uav != nullptr) { + bufView = uav->GetBufferView(); + imgView = uav->GetImageView(); + } + + if (vov != nullptr) + imgView = vov->GetView(); + + // 3D views are unsupported + if (imgView != nullptr + && imgView->info().type == VK_IMAGE_VIEW_TYPE_3D) + return; + + // Query the view format. We'll have to convert + // the clear color based on the format's data type. + VkFormat format = VK_FORMAT_UNDEFINED; + + if (bufView != nullptr) + format = bufView->info().format; + + if (imgView != nullptr) + format = imgView->info().format; + + if (format == VK_FORMAT_UNDEFINED) + return; + + // We'll need the format info to determine the buffer + // element size, and we also need it for depth images. + const DxvkFormatInfo* formatInfo = imageFormatInfo(format); + + // Convert the clear color format. ClearView takes + // the clear value for integer formats as a set of + // integral floats, so we'll have to convert. + VkClearValue clearValue = ConvertColorValue(Color, formatInfo); + VkImageAspectFlags clearAspect = formatInfo->aspectMask & (VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT); + + // Clear all the rectangles that are specified + for (uint32_t i = 0; i < NumRects || i < 1; i++) { + if (pRect) { + if (pRect[i].left >= pRect[i].right + || pRect[i].top >= pRect[i].bottom) + continue; + } + + if (bufView != nullptr) { + VkDeviceSize offset = 0; + VkDeviceSize length = bufView->info().rangeLength / formatInfo->elementSize; + + if (pRect) { + offset = pRect[i].left; + length = pRect[i].right - pRect[i].left; + } + + EmitCs([ + cBufferView = bufView, + cRangeOffset = offset, + cRangeLength = length, + cClearValue = clearValue + ] (DxvkContext* ctx) { + ctx->clearBufferView( + cBufferView, + cRangeOffset, + cRangeLength, + cClearValue.color); + }); + } + + if (imgView != nullptr) { + VkOffset3D offset = { 0, 0, 0 }; + VkExtent3D extent = imgView->mipLevelExtent(0); + + if (pRect) { + offset = { pRect[i].left, pRect[i].top, 0 }; + extent = { + uint32_t(pRect[i].right - pRect[i].left), + uint32_t(pRect[i].bottom - pRect[i].top), 1 }; + } + + EmitCs([ + cImageView = imgView, + cAreaOffset = offset, + cAreaExtent = extent, + cClearAspect = clearAspect, + cClearValue = clearValue + ] (DxvkContext* ctx) { + const VkImageUsageFlags rtUsage = + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + + bool isFullSize = cImageView->mipLevelExtent(0) == cAreaExtent; + + if ((cImageView->info().usage & rtUsage) && isFullSize) { + ctx->clearRenderTarget( + cImageView, + cClearAspect, + cClearValue); + } else { + ctx->clearImageView( + cImageView, + cAreaOffset, + cAreaExtent, + cClearAspect, + cClearValue); + } + }); + } + } + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::GenerateMips(ID3D11ShaderResourceView* pShaderResourceView) { + D3D10DeviceLock lock = LockContext(); + + auto view = static_cast(pShaderResourceView); + + if (!view || view->GetResourceType() == D3D11_RESOURCE_DIMENSION_BUFFER) + return; + + D3D11_COMMON_RESOURCE_DESC resourceDesc = view->GetResourceDesc(); + + if (!(resourceDesc.MiscFlags & D3D11_RESOURCE_MISC_GENERATE_MIPS)) + return; + + EmitCs([cDstImageView = view->GetImageView()] + (DxvkContext* ctx) { + ctx->generateMipmaps(cDstImageView, VK_FILTER_LINEAR); + }); + } + + + HRESULT STDMETHODCALLTYPE D3D11DeviceContext::UpdateTileMappings( + ID3D11Resource* pTiledResource, + UINT NumTiledResourceRegions, + const D3D11_TILED_RESOURCE_COORDINATE* pTiledResourceRegionStartCoordinates, + const D3D11_TILE_REGION_SIZE* pTiledResourceRegionSizes, + ID3D11Buffer* pTilePool, + UINT NumRanges, + const UINT* pRangeFlags, + const UINT* pTilePoolStartOffsets, + const UINT* pRangeTileCounts, + UINT Flags) { + bool s_errorShown = false; + + if (std::exchange(s_errorShown, true)) + Logger::err("D3D11DeviceContext::UpdateTileMappings: Not implemented"); + + return DXGI_ERROR_INVALID_CALL; + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::UpdateTiles( + ID3D11Resource* pDestTiledResource, + const D3D11_TILED_RESOURCE_COORDINATE* pDestTileRegionStartCoordinate, + const D3D11_TILE_REGION_SIZE* pDestTileRegionSize, + const void* pSourceTileData, + UINT Flags) { + bool s_errorShown = false; + + if (std::exchange(s_errorShown, true)) + Logger::err("D3D11DeviceContext::UpdateTiles: Not implemented"); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::SetResourceMinLOD( + ID3D11Resource* pResource, + FLOAT MinLOD) { + bool s_errorShown = false; + + if (std::exchange(s_errorShown, true)) + Logger::err("D3D11DeviceContext::SetResourceMinLOD: Not implemented"); + } + + + FLOAT STDMETHODCALLTYPE D3D11DeviceContext::GetResourceMinLOD(ID3D11Resource* pResource) { + bool s_errorShown = false; + + if (std::exchange(s_errorShown, true)) + Logger::err("D3D11DeviceContext::GetResourceMinLOD: Not implemented"); + + return 0.0f; + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::ResolveSubresource( + ID3D11Resource* pDstResource, + UINT DstSubresource, + ID3D11Resource* pSrcResource, + UINT SrcSubresource, + DXGI_FORMAT Format) { + D3D10DeviceLock lock = LockContext(); + + bool isSameSubresource = pDstResource == pSrcResource + && DstSubresource == SrcSubresource; + + if (!pDstResource || !pSrcResource || isSameSubresource) + return; + + D3D11_RESOURCE_DIMENSION dstResourceType; + D3D11_RESOURCE_DIMENSION srcResourceType; + + pDstResource->GetType(&dstResourceType); + pSrcResource->GetType(&srcResourceType); + + if (dstResourceType != D3D11_RESOURCE_DIMENSION_TEXTURE2D + || srcResourceType != D3D11_RESOURCE_DIMENSION_TEXTURE2D) { + Logger::err(str::format( + "D3D11: ResolveSubresource: Incompatible resources", + "\n Dst resource type: ", dstResourceType, + "\n Src resource type: ", srcResourceType)); + return; + } + + auto dstTexture = static_cast(pDstResource); + auto srcTexture = static_cast(pSrcResource); + + D3D11_TEXTURE2D_DESC dstDesc; + D3D11_TEXTURE2D_DESC srcDesc; + + dstTexture->GetDesc(&dstDesc); + srcTexture->GetDesc(&srcDesc); + + if (dstDesc.SampleDesc.Count != 1) { + Logger::err(str::format( + "D3D11: ResolveSubresource: Invalid sample counts", + "\n Dst sample count: ", dstDesc.SampleDesc.Count, + "\n Src sample count: ", srcDesc.SampleDesc.Count)); + return; + } + + D3D11CommonTexture* dstTextureInfo = GetCommonTexture(pDstResource); + D3D11CommonTexture* srcTextureInfo = GetCommonTexture(pSrcResource); + + const DXGI_VK_FORMAT_INFO dstFormatInfo = m_parent->LookupFormat(dstDesc.Format, DXGI_VK_FORMAT_MODE_ANY); + const DXGI_VK_FORMAT_INFO srcFormatInfo = m_parent->LookupFormat(srcDesc.Format, DXGI_VK_FORMAT_MODE_ANY); + + auto dstVulkanFormatInfo = imageFormatInfo(dstFormatInfo.Format); + auto srcVulkanFormatInfo = imageFormatInfo(srcFormatInfo.Format); + + if (DstSubresource >= dstTextureInfo->CountSubresources() + || SrcSubresource >= srcTextureInfo->CountSubresources()) + return; + + const VkImageSubresource dstSubresource = + dstTextureInfo->GetSubresourceFromIndex( + dstVulkanFormatInfo->aspectMask, DstSubresource); + + const VkImageSubresource srcSubresource = + srcTextureInfo->GetSubresourceFromIndex( + srcVulkanFormatInfo->aspectMask, SrcSubresource); + + const VkImageSubresourceLayers dstSubresourceLayers = { + dstSubresource.aspectMask, + dstSubresource.mipLevel, + dstSubresource.arrayLayer, 1 }; + + const VkImageSubresourceLayers srcSubresourceLayers = { + srcSubresource.aspectMask, + srcSubresource.mipLevel, + srcSubresource.arrayLayer, 1 }; + + if (srcDesc.SampleDesc.Count == 1 || m_parent->GetOptions()->disableMsaa) { + EmitCs([ + cDstImage = dstTextureInfo->GetImage(), + cSrcImage = srcTextureInfo->GetImage(), + cDstLayers = dstSubresourceLayers, + cSrcLayers = srcSubresourceLayers + ] (DxvkContext* ctx) { + ctx->copyImage( + cDstImage, cDstLayers, VkOffset3D { 0, 0, 0 }, + cSrcImage, cSrcLayers, VkOffset3D { 0, 0, 0 }, + cDstImage->mipLevelExtent(cDstLayers.mipLevel)); + }); + } else { + const VkFormat format = m_parent->LookupFormat( + Format, DXGI_VK_FORMAT_MODE_ANY).Format; + + EmitCs([ + cDstImage = dstTextureInfo->GetImage(), + cSrcImage = srcTextureInfo->GetImage(), + cDstSubres = dstSubresourceLayers, + cSrcSubres = srcSubresourceLayers, + cFormat = format + ] (DxvkContext* ctx) { + VkImageResolve region; + region.srcSubresource = cSrcSubres; + region.srcOffset = VkOffset3D { 0, 0, 0 }; + region.dstSubresource = cDstSubres; + region.dstOffset = VkOffset3D { 0, 0, 0 }; + region.extent = cDstImage->mipLevelExtent(cDstSubres.mipLevel); + + ctx->resolveImage(cDstImage, cSrcImage, region, cFormat); + }); + } + + if (dstTextureInfo->HasSequenceNumber()) + TrackTextureSequenceNumber(dstTextureInfo, DstSubresource); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::DrawAuto() { + D3D10DeviceLock lock = LockContext(); + + D3D11Buffer* buffer = m_state.ia.vertexBuffers[0].buffer.ptr(); + + if (buffer == nullptr) + return; + + DxvkBufferSlice vtxBuf = buffer->GetBufferSlice(); + DxvkBufferSlice ctrBuf = buffer->GetSOCounter(); + + if (!ctrBuf.defined()) + return; + + EmitCs([=] (DxvkContext* ctx) { + ctx->drawIndirectXfb(ctrBuf, + vtxBuf.buffer()->getXfbVertexStride(), + vtxBuf.offset()); + }); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::Draw( + UINT VertexCount, + UINT StartVertexLocation) { + D3D10DeviceLock lock = LockContext(); + + EmitCs([=] (DxvkContext* ctx) { + ctx->draw( + VertexCount, 1, + StartVertexLocation, 0); + }); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::DrawIndexed( + UINT IndexCount, + UINT StartIndexLocation, + INT BaseVertexLocation) { + D3D10DeviceLock lock = LockContext(); + + EmitCs([=] (DxvkContext* ctx) { + ctx->drawIndexed( + IndexCount, 1, + StartIndexLocation, + BaseVertexLocation, 0); + }); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::DrawInstanced( + UINT VertexCountPerInstance, + UINT InstanceCount, + UINT StartVertexLocation, + UINT StartInstanceLocation) { + D3D10DeviceLock lock = LockContext(); + + EmitCs([=] (DxvkContext* ctx) { + ctx->draw( + VertexCountPerInstance, + InstanceCount, + StartVertexLocation, + StartInstanceLocation); + }); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::DrawIndexedInstanced( + UINT IndexCountPerInstance, + UINT InstanceCount, + UINT StartIndexLocation, + INT BaseVertexLocation, + UINT StartInstanceLocation) { + D3D10DeviceLock lock = LockContext(); + + EmitCs([=] (DxvkContext* ctx) { + ctx->drawIndexed( + IndexCountPerInstance, + InstanceCount, + StartIndexLocation, + BaseVertexLocation, + StartInstanceLocation); + }); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::DrawIndexedInstancedIndirect( + ID3D11Buffer* pBufferForArgs, + UINT AlignedByteOffsetForArgs) { + D3D10DeviceLock lock = LockContext(); + SetDrawBuffers(pBufferForArgs, nullptr); + + if (!ValidateDrawBufferSize(pBufferForArgs, AlignedByteOffsetForArgs, sizeof(VkDrawIndexedIndirectCommand))) + return; + + // If possible, batch up multiple indirect draw calls of + // the same type into one single multiDrawIndirect call + auto cmdData = static_cast(m_cmdData); + auto stride = 0u; + + if (cmdData && cmdData->type == D3D11CmdType::DrawIndirectIndexed) + stride = GetIndirectCommandStride(cmdData, AlignedByteOffsetForArgs, sizeof(VkDrawIndexedIndirectCommand)); + + if (stride) { + cmdData->count += 1; + cmdData->stride = stride; + } else { + cmdData = EmitCsCmd( + [] (DxvkContext* ctx, const D3D11CmdDrawIndirectData* data) { + ctx->drawIndexedIndirect(data->offset, data->count, data->stride); + }); + + cmdData->type = D3D11CmdType::DrawIndirectIndexed; + cmdData->offset = AlignedByteOffsetForArgs; + cmdData->count = 1; + cmdData->stride = 0; + } + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::DrawInstancedIndirect( + ID3D11Buffer* pBufferForArgs, + UINT AlignedByteOffsetForArgs) { + D3D10DeviceLock lock = LockContext(); + SetDrawBuffers(pBufferForArgs, nullptr); + + if (!ValidateDrawBufferSize(pBufferForArgs, AlignedByteOffsetForArgs, sizeof(VkDrawIndirectCommand))) + return; + + // If possible, batch up multiple indirect draw calls of + // the same type into one single multiDrawIndirect call + auto cmdData = static_cast(m_cmdData); + auto stride = 0u; + + if (cmdData && cmdData->type == D3D11CmdType::DrawIndirect) + stride = GetIndirectCommandStride(cmdData, AlignedByteOffsetForArgs, sizeof(VkDrawIndirectCommand)); + + if (stride) { + cmdData->count += 1; + cmdData->stride = stride; + } else { + cmdData = EmitCsCmd( + [] (DxvkContext* ctx, const D3D11CmdDrawIndirectData* data) { + ctx->drawIndirect(data->offset, data->count, data->stride); + }); + + cmdData->type = D3D11CmdType::DrawIndirect; + cmdData->offset = AlignedByteOffsetForArgs; + cmdData->count = 1; + cmdData->stride = 0; + } + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::Dispatch( + UINT ThreadGroupCountX, + UINT ThreadGroupCountY, + UINT ThreadGroupCountZ) { + D3D10DeviceLock lock = LockContext(); + + EmitCs([=] (DxvkContext* ctx) { + ctx->dispatch( + ThreadGroupCountX, + ThreadGroupCountY, + ThreadGroupCountZ); + }); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::DispatchIndirect( + ID3D11Buffer* pBufferForArgs, + UINT AlignedByteOffsetForArgs) { + D3D10DeviceLock lock = LockContext(); + SetDrawBuffers(pBufferForArgs, nullptr); + + if (!ValidateDrawBufferSize(pBufferForArgs, AlignedByteOffsetForArgs, sizeof(VkDispatchIndirectCommand))) + return; + + EmitCs([cOffset = AlignedByteOffsetForArgs] + (DxvkContext* ctx) { + ctx->dispatchIndirect(cOffset); + }); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::IASetInputLayout(ID3D11InputLayout* pInputLayout) { + D3D10DeviceLock lock = LockContext(); + + auto inputLayout = static_cast(pInputLayout); + + if (m_state.ia.inputLayout != inputLayout) { + bool equal = false; + + // Some games (e.g. Grim Dawn) create lots and lots of + // identical input layouts, so we'll only apply the state + // if the input layouts has actually changed between calls. + if (m_state.ia.inputLayout != nullptr && inputLayout != nullptr) + equal = m_state.ia.inputLayout->Compare(inputLayout); + + m_state.ia.inputLayout = inputLayout; + + if (!equal) + ApplyInputLayout(); + } + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY Topology) { + D3D10DeviceLock lock = LockContext(); + + if (m_state.ia.primitiveTopology != Topology) { + m_state.ia.primitiveTopology = Topology; + ApplyPrimitiveTopology(); + } + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::IASetVertexBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer* const* ppVertexBuffers, + const UINT* pStrides, + const UINT* pOffsets) { + D3D10DeviceLock lock = LockContext(); + + for (uint32_t i = 0; i < NumBuffers; i++) { + auto newBuffer = static_cast(ppVertexBuffers[i]); + bool needsUpdate = m_state.ia.vertexBuffers[StartSlot + i].buffer != newBuffer; + + if (needsUpdate) + m_state.ia.vertexBuffers[StartSlot + i].buffer = newBuffer; + + needsUpdate |= m_state.ia.vertexBuffers[StartSlot + i].offset != pOffsets[i] + || m_state.ia.vertexBuffers[StartSlot + i].stride != pStrides[i]; + + if (needsUpdate) { + m_state.ia.vertexBuffers[StartSlot + i].offset = pOffsets[i]; + m_state.ia.vertexBuffers[StartSlot + i].stride = pStrides[i]; + + BindVertexBuffer(StartSlot + i, newBuffer, pOffsets[i], pStrides[i]); + } + } + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::IASetIndexBuffer( + ID3D11Buffer* pIndexBuffer, + DXGI_FORMAT Format, + UINT Offset) { + D3D10DeviceLock lock = LockContext(); + + auto newBuffer = static_cast(pIndexBuffer); + bool needsUpdate = m_state.ia.indexBuffer.buffer != newBuffer; + + if (needsUpdate) + m_state.ia.indexBuffer.buffer = newBuffer; + + needsUpdate |= m_state.ia.indexBuffer.offset != Offset + || m_state.ia.indexBuffer.format != Format; + + if (needsUpdate) { + m_state.ia.indexBuffer.offset = Offset; + m_state.ia.indexBuffer.format = Format; + + BindIndexBuffer(newBuffer, Offset, Format); + } + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::IAGetInputLayout(ID3D11InputLayout** ppInputLayout) { + D3D10DeviceLock lock = LockContext(); + + *ppInputLayout = m_state.ia.inputLayout.ref(); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::IAGetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY* pTopology) { + D3D10DeviceLock lock = LockContext(); + + *pTopology = m_state.ia.primitiveTopology; + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::IAGetVertexBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer** ppVertexBuffers, + UINT* pStrides, + UINT* pOffsets) { + D3D10DeviceLock lock = LockContext(); + + for (uint32_t i = 0; i < NumBuffers; i++) { + const bool inRange = StartSlot + i < m_state.ia.vertexBuffers.size(); + + if (ppVertexBuffers != nullptr) { + ppVertexBuffers[i] = inRange + ? m_state.ia.vertexBuffers[StartSlot + i].buffer.ref() + : nullptr; + } + + if (pStrides != nullptr) { + pStrides[i] = inRange + ? m_state.ia.vertexBuffers[StartSlot + i].stride + : 0u; + } + + if (pOffsets != nullptr) { + pOffsets[i] = inRange + ? m_state.ia.vertexBuffers[StartSlot + i].offset + : 0u; + } + } + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::IAGetIndexBuffer( + ID3D11Buffer** ppIndexBuffer, + DXGI_FORMAT* pFormat, + UINT* pOffset) { + D3D10DeviceLock lock = LockContext(); + + if (ppIndexBuffer != nullptr) + *ppIndexBuffer = m_state.ia.indexBuffer.buffer.ref(); + + if (pFormat != nullptr) + *pFormat = m_state.ia.indexBuffer.format; + + if (pOffset != nullptr) + *pOffset = m_state.ia.indexBuffer.offset; + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::VSSetShader( + ID3D11VertexShader* pVertexShader, + ID3D11ClassInstance* const* ppClassInstances, + UINT NumClassInstances) { + D3D10DeviceLock lock = LockContext(); + + auto shader = static_cast(pVertexShader); + + if (NumClassInstances != 0) + Logger::err("D3D11: Class instances not supported"); + + if (m_state.vs.shader != shader) { + m_state.vs.shader = shader; + + BindShader(GetCommonShader(shader)); + } + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::VSSetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer* const* ppConstantBuffers) { + D3D10DeviceLock lock = LockContext(); + + SetConstantBuffers( + m_state.vs.constantBuffers, + StartSlot, NumBuffers, + ppConstantBuffers); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::VSSetConstantBuffers1( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer* const* ppConstantBuffers, + const UINT* pFirstConstant, + const UINT* pNumConstants) { + D3D10DeviceLock lock = LockContext(); + + SetConstantBuffers1( + m_state.vs.constantBuffers, + StartSlot, NumBuffers, + ppConstantBuffers, + pFirstConstant, + pNumConstants); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::VSSetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D11ShaderResourceView* const* ppShaderResourceViews) { + D3D10DeviceLock lock = LockContext(); + + SetShaderResources( + m_state.vs.shaderResources, + StartSlot, NumViews, + ppShaderResourceViews); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::VSSetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D11SamplerState* const* ppSamplers) { + D3D10DeviceLock lock = LockContext(); + + SetSamplers( + m_state.vs.samplers, + StartSlot, NumSamplers, + ppSamplers); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::VSGetShader( + ID3D11VertexShader** ppVertexShader, + ID3D11ClassInstance** ppClassInstances, + UINT* pNumClassInstances) { + D3D10DeviceLock lock = LockContext(); + + if (ppVertexShader != nullptr) + *ppVertexShader = m_state.vs.shader.ref(); + + if (pNumClassInstances != nullptr) + *pNumClassInstances = 0; + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::VSGetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer** ppConstantBuffers) { + D3D10DeviceLock lock = LockContext(); + + GetConstantBuffers( + m_state.vs.constantBuffers, + StartSlot, NumBuffers, + ppConstantBuffers, + nullptr, nullptr); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::VSGetConstantBuffers1( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer** ppConstantBuffers, + UINT* pFirstConstant, + UINT* pNumConstants) { + D3D10DeviceLock lock = LockContext(); + + GetConstantBuffers( + m_state.vs.constantBuffers, + StartSlot, NumBuffers, + ppConstantBuffers, + pFirstConstant, + pNumConstants); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::VSGetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D11ShaderResourceView** ppShaderResourceViews) { + D3D10DeviceLock lock = LockContext(); + + GetShaderResources(m_state.vs.shaderResources, + StartSlot, NumViews, ppShaderResourceViews); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::VSGetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D11SamplerState** ppSamplers) { + D3D10DeviceLock lock = LockContext(); + + GetSamplers(m_state.vs.samplers, + StartSlot, NumSamplers, ppSamplers); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::HSSetShader( + ID3D11HullShader* pHullShader, + ID3D11ClassInstance* const* ppClassInstances, + UINT NumClassInstances) { + D3D10DeviceLock lock = LockContext(); + + auto shader = static_cast(pHullShader); + + if (NumClassInstances != 0) + Logger::err("D3D11: Class instances not supported"); + + if (m_state.hs.shader != shader) { + m_state.hs.shader = shader; + + BindShader(GetCommonShader(shader)); + } + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::HSSetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D11ShaderResourceView* const* ppShaderResourceViews) { + D3D10DeviceLock lock = LockContext(); + + SetShaderResources( + m_state.hs.shaderResources, + StartSlot, NumViews, + ppShaderResourceViews); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::HSSetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer* const* ppConstantBuffers) { + D3D10DeviceLock lock = LockContext(); + + SetConstantBuffers( + m_state.hs.constantBuffers, + StartSlot, NumBuffers, + ppConstantBuffers); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::HSSetConstantBuffers1( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer* const* ppConstantBuffers, + const UINT* pFirstConstant, + const UINT* pNumConstants) { + D3D10DeviceLock lock = LockContext(); + + SetConstantBuffers1( + m_state.hs.constantBuffers, + StartSlot, NumBuffers, + ppConstantBuffers, + pFirstConstant, + pNumConstants); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::HSSetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D11SamplerState* const* ppSamplers) { + D3D10DeviceLock lock = LockContext(); + + SetSamplers( + m_state.hs.samplers, + StartSlot, NumSamplers, + ppSamplers); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::HSGetShader( + ID3D11HullShader** ppHullShader, + ID3D11ClassInstance** ppClassInstances, + UINT* pNumClassInstances) { + D3D10DeviceLock lock = LockContext(); + + if (ppHullShader != nullptr) + *ppHullShader = m_state.hs.shader.ref(); + + if (pNumClassInstances != nullptr) + *pNumClassInstances = 0; + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::HSGetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer** ppConstantBuffers) { + D3D10DeviceLock lock = LockContext(); + + GetConstantBuffers( + m_state.hs.constantBuffers, + StartSlot, NumBuffers, + ppConstantBuffers, + nullptr, nullptr); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::HSGetConstantBuffers1( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer** ppConstantBuffers, + UINT* pFirstConstant, + UINT* pNumConstants) { + D3D10DeviceLock lock = LockContext(); + + GetConstantBuffers( + m_state.hs.constantBuffers, + StartSlot, NumBuffers, + ppConstantBuffers, + pFirstConstant, + pNumConstants); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::HSGetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D11ShaderResourceView** ppShaderResourceViews) { + D3D10DeviceLock lock = LockContext(); + + GetShaderResources(m_state.hs.shaderResources, + StartSlot, NumViews, ppShaderResourceViews); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::HSGetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D11SamplerState** ppSamplers) { + D3D10DeviceLock lock = LockContext(); + + GetSamplers(m_state.hs.samplers, + StartSlot, NumSamplers, ppSamplers); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::DSSetShader( + ID3D11DomainShader* pDomainShader, + ID3D11ClassInstance* const* ppClassInstances, + UINT NumClassInstances) { + D3D10DeviceLock lock = LockContext(); + + auto shader = static_cast(pDomainShader); + + if (NumClassInstances != 0) + Logger::err("D3D11: Class instances not supported"); + + if (m_state.ds.shader != shader) { + m_state.ds.shader = shader; + + BindShader(GetCommonShader(shader)); + } + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::DSSetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D11ShaderResourceView* const* ppShaderResourceViews) { + D3D10DeviceLock lock = LockContext(); + + SetShaderResources( + m_state.ds.shaderResources, + StartSlot, NumViews, + ppShaderResourceViews); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::DSSetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer* const* ppConstantBuffers) { + D3D10DeviceLock lock = LockContext(); + + SetConstantBuffers( + m_state.ds.constantBuffers, + StartSlot, NumBuffers, + ppConstantBuffers); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::DSSetConstantBuffers1( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer* const* ppConstantBuffers, + const UINT* pFirstConstant, + const UINT* pNumConstants) { + D3D10DeviceLock lock = LockContext(); + + SetConstantBuffers1( + m_state.ds.constantBuffers, + StartSlot, NumBuffers, + ppConstantBuffers, + pFirstConstant, + pNumConstants); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::DSSetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D11SamplerState* const* ppSamplers) { + D3D10DeviceLock lock = LockContext(); + + SetSamplers( + m_state.ds.samplers, + StartSlot, NumSamplers, + ppSamplers); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::DSGetShader( + ID3D11DomainShader** ppDomainShader, + ID3D11ClassInstance** ppClassInstances, + UINT* pNumClassInstances) { + D3D10DeviceLock lock = LockContext(); + + if (ppDomainShader != nullptr) + *ppDomainShader = m_state.ds.shader.ref(); + + if (pNumClassInstances != nullptr) + *pNumClassInstances = 0; + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::DSGetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer** ppConstantBuffers) { + D3D10DeviceLock lock = LockContext(); + + GetConstantBuffers( + m_state.ds.constantBuffers, + StartSlot, NumBuffers, + ppConstantBuffers, + nullptr, nullptr); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::DSGetConstantBuffers1( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer** ppConstantBuffers, + UINT* pFirstConstant, + UINT* pNumConstants) { + D3D10DeviceLock lock = LockContext(); + + GetConstantBuffers( + m_state.ds.constantBuffers, + StartSlot, NumBuffers, + ppConstantBuffers, + pFirstConstant, + pNumConstants); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::DSGetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D11ShaderResourceView** ppShaderResourceViews) { + D3D10DeviceLock lock = LockContext(); + + GetShaderResources(m_state.ds.shaderResources, + StartSlot, NumViews, ppShaderResourceViews); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::DSGetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D11SamplerState** ppSamplers) { + D3D10DeviceLock lock = LockContext(); + + GetSamplers(m_state.ds.samplers, + StartSlot, NumSamplers, ppSamplers); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::GSSetShader( + ID3D11GeometryShader* pShader, + ID3D11ClassInstance* const* ppClassInstances, + UINT NumClassInstances) { + D3D10DeviceLock lock = LockContext(); + + auto shader = static_cast(pShader); + + if (NumClassInstances != 0) + Logger::err("D3D11: Class instances not supported"); + + if (m_state.gs.shader != shader) { + m_state.gs.shader = shader; + + BindShader(GetCommonShader(shader)); + } + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::GSSetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer* const* ppConstantBuffers) { + D3D10DeviceLock lock = LockContext(); + + SetConstantBuffers( + m_state.gs.constantBuffers, + StartSlot, NumBuffers, + ppConstantBuffers); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::GSSetConstantBuffers1( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer* const* ppConstantBuffers, + const UINT* pFirstConstant, + const UINT* pNumConstants) { + D3D10DeviceLock lock = LockContext(); + + SetConstantBuffers1( + m_state.gs.constantBuffers, + StartSlot, NumBuffers, + ppConstantBuffers, + pFirstConstant, + pNumConstants); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::GSSetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D11ShaderResourceView* const* ppShaderResourceViews) { + D3D10DeviceLock lock = LockContext(); + + SetShaderResources( + m_state.gs.shaderResources, + StartSlot, NumViews, + ppShaderResourceViews); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::GSSetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D11SamplerState* const* ppSamplers) { + D3D10DeviceLock lock = LockContext(); + + SetSamplers( + m_state.gs.samplers, + StartSlot, NumSamplers, + ppSamplers); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::GSGetShader( + ID3D11GeometryShader** ppGeometryShader, + ID3D11ClassInstance** ppClassInstances, + UINT* pNumClassInstances) { + D3D10DeviceLock lock = LockContext(); + + if (ppGeometryShader != nullptr) + *ppGeometryShader = m_state.gs.shader.ref(); + + if (pNumClassInstances != nullptr) + *pNumClassInstances = 0; + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::GSGetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer** ppConstantBuffers) { + D3D10DeviceLock lock = LockContext(); + + GetConstantBuffers( + m_state.gs.constantBuffers, + StartSlot, NumBuffers, + ppConstantBuffers, + nullptr, nullptr); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::GSGetConstantBuffers1( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer** ppConstantBuffers, + UINT* pFirstConstant, + UINT* pNumConstants) { + D3D10DeviceLock lock = LockContext(); + + GetConstantBuffers( + m_state.gs.constantBuffers, + StartSlot, NumBuffers, + ppConstantBuffers, + pFirstConstant, + pNumConstants); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::GSGetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D11ShaderResourceView** ppShaderResourceViews) { + D3D10DeviceLock lock = LockContext(); + + GetShaderResources(m_state.gs.shaderResources, + StartSlot, NumViews, ppShaderResourceViews); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::GSGetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D11SamplerState** ppSamplers) { + D3D10DeviceLock lock = LockContext(); + + GetSamplers(m_state.gs.samplers, + StartSlot, NumSamplers, ppSamplers); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::PSSetShader( + ID3D11PixelShader* pPixelShader, + ID3D11ClassInstance* const* ppClassInstances, + UINT NumClassInstances) { + D3D10DeviceLock lock = LockContext(); + + auto shader = static_cast(pPixelShader); + + if (NumClassInstances != 0) + Logger::err("D3D11: Class instances not supported"); + + if (m_state.ps.shader != shader) { + m_state.ps.shader = shader; + + BindShader(GetCommonShader(shader)); + } + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::PSSetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer* const* ppConstantBuffers) { + D3D10DeviceLock lock = LockContext(); + + SetConstantBuffers( + m_state.ps.constantBuffers, + StartSlot, NumBuffers, + ppConstantBuffers); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::PSSetConstantBuffers1( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer* const* ppConstantBuffers, + const UINT* pFirstConstant, + const UINT* pNumConstants) { + D3D10DeviceLock lock = LockContext(); + + SetConstantBuffers1( + m_state.ps.constantBuffers, + StartSlot, NumBuffers, + ppConstantBuffers, + pFirstConstant, + pNumConstants); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::PSSetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D11ShaderResourceView* const* ppShaderResourceViews) { + D3D10DeviceLock lock = LockContext(); + + SetShaderResources( + m_state.ps.shaderResources, + StartSlot, NumViews, + ppShaderResourceViews); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::PSSetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D11SamplerState* const* ppSamplers) { + D3D10DeviceLock lock = LockContext(); + + SetSamplers( + m_state.ps.samplers, + StartSlot, NumSamplers, + ppSamplers); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::PSGetShader( + ID3D11PixelShader** ppPixelShader, + ID3D11ClassInstance** ppClassInstances, + UINT* pNumClassInstances) { + D3D10DeviceLock lock = LockContext(); + + if (ppPixelShader != nullptr) + *ppPixelShader = m_state.ps.shader.ref(); + + if (pNumClassInstances != nullptr) + *pNumClassInstances = 0; + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::PSGetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer** ppConstantBuffers) { + D3D10DeviceLock lock = LockContext(); + + GetConstantBuffers( + m_state.ps.constantBuffers, + StartSlot, NumBuffers, + ppConstantBuffers, + nullptr, nullptr); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::PSGetConstantBuffers1( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer** ppConstantBuffers, + UINT* pFirstConstant, + UINT* pNumConstants) { + D3D10DeviceLock lock = LockContext(); + + GetConstantBuffers( + m_state.ps.constantBuffers, + StartSlot, NumBuffers, + ppConstantBuffers, + pFirstConstant, + pNumConstants); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::PSGetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D11ShaderResourceView** ppShaderResourceViews) { + D3D10DeviceLock lock = LockContext(); + + GetShaderResources(m_state.ps.shaderResources, + StartSlot, NumViews, ppShaderResourceViews); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::PSGetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D11SamplerState** ppSamplers) { + D3D10DeviceLock lock = LockContext(); + + GetSamplers(m_state.ps.samplers, + StartSlot, NumSamplers, ppSamplers); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::CSSetShader( + ID3D11ComputeShader* pComputeShader, + ID3D11ClassInstance* const* ppClassInstances, + UINT NumClassInstances) { + D3D10DeviceLock lock = LockContext(); + + auto shader = static_cast(pComputeShader); + + if (NumClassInstances != 0) + Logger::err("D3D11: Class instances not supported"); + + if (m_state.cs.shader != shader) { + m_state.cs.shader = shader; + + BindShader(GetCommonShader(shader)); + } + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::CSSetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer* const* ppConstantBuffers) { + D3D10DeviceLock lock = LockContext(); + + SetConstantBuffers( + m_state.cs.constantBuffers, + StartSlot, NumBuffers, + ppConstantBuffers); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::CSSetConstantBuffers1( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer* const* ppConstantBuffers, + const UINT* pFirstConstant, + const UINT* pNumConstants) { + D3D10DeviceLock lock = LockContext(); + + SetConstantBuffers1( + m_state.cs.constantBuffers, + StartSlot, NumBuffers, + ppConstantBuffers, + pFirstConstant, + pNumConstants); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::CSSetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D11ShaderResourceView* const* ppShaderResourceViews) { + D3D10DeviceLock lock = LockContext(); + + SetShaderResources( + m_state.cs.shaderResources, + StartSlot, NumViews, + ppShaderResourceViews); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::CSSetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D11SamplerState* const* ppSamplers) { + D3D10DeviceLock lock = LockContext(); + + SetSamplers( + m_state.cs.samplers, + StartSlot, NumSamplers, + ppSamplers); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::CSSetUnorderedAccessViews( + UINT StartSlot, + UINT NumUAVs, + ID3D11UnorderedAccessView* const* ppUnorderedAccessViews, + const UINT* pUAVInitialCounts) { + D3D10DeviceLock lock = LockContext(); + + if (TestRtvUavHazards(0, nullptr, NumUAVs, ppUnorderedAccessViews)) + return; + + // Unbind previously bound conflicting UAVs + uint32_t uavSlotId = computeUavBinding (DxbcProgramType::ComputeShader, 0); + uint32_t ctrSlotId = computeUavCounterBinding(DxbcProgramType::ComputeShader, 0); + + int32_t uavId = m_state.cs.uavMask.findNext(0); + + while (uavId >= 0) { + if (uint32_t(uavId) < StartSlot || uint32_t(uavId) >= StartSlot + NumUAVs) { + for (uint32_t i = 0; i < NumUAVs; i++) { + auto uav = static_cast(ppUnorderedAccessViews[i]); + + if (CheckViewOverlap(uav, m_state.cs.unorderedAccessViews[uavId].ptr())) { + m_state.cs.unorderedAccessViews[uavId] = nullptr; + m_state.cs.uavMask.clr(uavId); + + BindUnorderedAccessView( + uavSlotId + uavId, nullptr, + ctrSlotId + uavId, ~0u); + } + } + + uavId = m_state.cs.uavMask.findNext(uavId + 1); + } else { + uavId = m_state.cs.uavMask.findNext(StartSlot + NumUAVs); + } + } + + // Actually bind the given UAVs + for (uint32_t i = 0; i < NumUAVs; i++) { + auto uav = static_cast(ppUnorderedAccessViews[i]); + auto ctr = pUAVInitialCounts ? pUAVInitialCounts[i] : ~0u; + + if (m_state.cs.unorderedAccessViews[StartSlot + i] != uav || ctr != ~0u) { + m_state.cs.unorderedAccessViews[StartSlot + i] = uav; + m_state.cs.uavMask.set(StartSlot + i, uav != nullptr); + + BindUnorderedAccessView( + uavSlotId + StartSlot + i, uav, + ctrSlotId + StartSlot + i, ctr); + + ResolveCsSrvHazards(uav); + } + } + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::CSGetShader( + ID3D11ComputeShader** ppComputeShader, + ID3D11ClassInstance** ppClassInstances, + UINT* pNumClassInstances) { + D3D10DeviceLock lock = LockContext(); + + if (ppComputeShader != nullptr) + *ppComputeShader = m_state.cs.shader.ref(); + + if (pNumClassInstances != nullptr) + *pNumClassInstances = 0; + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::CSGetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer** ppConstantBuffers) { + D3D10DeviceLock lock = LockContext(); + + GetConstantBuffers( + m_state.cs.constantBuffers, + StartSlot, NumBuffers, + ppConstantBuffers, + nullptr, nullptr); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::CSGetConstantBuffers1( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer** ppConstantBuffers, + UINT* pFirstConstant, + UINT* pNumConstants) { + D3D10DeviceLock lock = LockContext(); + + GetConstantBuffers( + m_state.cs.constantBuffers, + StartSlot, NumBuffers, + ppConstantBuffers, + pFirstConstant, + pNumConstants); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::CSGetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D11ShaderResourceView** ppShaderResourceViews) { + D3D10DeviceLock lock = LockContext(); + + GetShaderResources(m_state.cs.shaderResources, + StartSlot, NumViews, ppShaderResourceViews); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::CSGetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D11SamplerState** ppSamplers) { + D3D10DeviceLock lock = LockContext(); + + GetSamplers(m_state.cs.samplers, + StartSlot, NumSamplers, ppSamplers); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::CSGetUnorderedAccessViews( + UINT StartSlot, + UINT NumUAVs, + ID3D11UnorderedAccessView** ppUnorderedAccessViews) { + D3D10DeviceLock lock = LockContext(); + + for (uint32_t i = 0; i < NumUAVs; i++) { + ppUnorderedAccessViews[i] = StartSlot + i < m_state.cs.unorderedAccessViews.size() + ? m_state.cs.unorderedAccessViews[StartSlot + i].ref() + : nullptr; + } + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::OMSetRenderTargets( + UINT NumViews, + ID3D11RenderTargetView* const* ppRenderTargetViews, + ID3D11DepthStencilView* pDepthStencilView) { + OMSetRenderTargetsAndUnorderedAccessViews( + NumViews, ppRenderTargetViews, pDepthStencilView, + NumViews, 0, nullptr, nullptr); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::OMSetRenderTargetsAndUnorderedAccessViews( + UINT NumRTVs, + ID3D11RenderTargetView* const* ppRenderTargetViews, + ID3D11DepthStencilView* pDepthStencilView, + UINT UAVStartSlot, + UINT NumUAVs, + ID3D11UnorderedAccessView* const* ppUnorderedAccessViews, + const UINT* pUAVInitialCounts) { + D3D10DeviceLock lock = LockContext(); + + if (TestRtvUavHazards(NumRTVs, ppRenderTargetViews, NumUAVs, ppUnorderedAccessViews)) + return; + + bool needsUpdate = false; + + if (likely(NumRTVs != D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL)) { + // Native D3D11 does not change the render targets if + // the parameters passed to this method are invalid. + if (!ValidateRenderTargets(NumRTVs, ppRenderTargetViews, pDepthStencilView)) + return; + + for (uint32_t i = 0; i < m_state.om.renderTargetViews.size(); i++) { + auto rtv = i < NumRTVs + ? static_cast(ppRenderTargetViews[i]) + : nullptr; + + if (m_state.om.renderTargetViews[i] != rtv) { + m_state.om.renderTargetViews[i] = rtv; + needsUpdate = true; + ResolveOmSrvHazards(rtv); + + if (NumUAVs == D3D11_KEEP_UNORDERED_ACCESS_VIEWS) + ResolveOmUavHazards(rtv); + } + } + + auto dsv = static_cast(pDepthStencilView); + + if (m_state.om.depthStencilView != dsv) { + m_state.om.depthStencilView = dsv; + needsUpdate = true; + ResolveOmSrvHazards(dsv); + } + + m_state.om.maxRtv = NumRTVs; + } + + if (unlikely(NumUAVs || m_state.om.maxUav)) { + uint32_t uavSlotId = computeUavBinding (DxbcProgramType::PixelShader, 0); + uint32_t ctrSlotId = computeUavCounterBinding(DxbcProgramType::PixelShader, 0); + + if (likely(NumUAVs != D3D11_KEEP_UNORDERED_ACCESS_VIEWS)) { + uint32_t newMaxUav = NumUAVs ? UAVStartSlot + NumUAVs : 0; + uint32_t oldMaxUav = std::exchange(m_state.om.maxUav, newMaxUav); + + for (uint32_t i = 0; i < std::max(oldMaxUav, newMaxUav); i++) { + D3D11UnorderedAccessView* uav = nullptr; + uint32_t ctr = ~0u; + + if (i >= UAVStartSlot && i < UAVStartSlot + NumUAVs) { + uav = static_cast(ppUnorderedAccessViews[i - UAVStartSlot]); + ctr = pUAVInitialCounts ? pUAVInitialCounts[i - UAVStartSlot] : ~0u; + } + + if (m_state.ps.unorderedAccessViews[i] != uav || ctr != ~0u) { + m_state.ps.unorderedAccessViews[i] = uav; + + BindUnorderedAccessView( + uavSlotId + i, uav, + ctrSlotId + i, ctr); + + ResolveOmSrvHazards(uav); + + if (NumRTVs == D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL) + needsUpdate |= ResolveOmRtvHazards(uav); + } + } + } + } + + if (needsUpdate) + BindFramebuffer(); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::OMSetBlendState( + ID3D11BlendState* pBlendState, + const FLOAT BlendFactor[4], + UINT SampleMask) { + D3D10DeviceLock lock = LockContext(); + + auto blendState = static_cast(pBlendState); + + if (m_state.om.cbState != blendState + || m_state.om.sampleMask != SampleMask) { + m_state.om.cbState = blendState; + m_state.om.sampleMask = SampleMask; + + ApplyBlendState(); + } + + if (BlendFactor != nullptr) { + for (uint32_t i = 0; i < 4; i++) + m_state.om.blendFactor[i] = BlendFactor[i]; + + ApplyBlendFactor(); + } + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::OMSetDepthStencilState( + ID3D11DepthStencilState* pDepthStencilState, + UINT StencilRef) { + D3D10DeviceLock lock = LockContext(); + + auto depthStencilState = static_cast(pDepthStencilState); + + if (m_state.om.dsState != depthStencilState) { + m_state.om.dsState = depthStencilState; + ApplyDepthStencilState(); + } + + if (m_state.om.stencilRef != StencilRef) { + m_state.om.stencilRef = StencilRef; + ApplyStencilRef(); + } + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::OMGetRenderTargets( + UINT NumViews, + ID3D11RenderTargetView** ppRenderTargetViews, + ID3D11DepthStencilView** ppDepthStencilView) { + D3D10DeviceLock lock = LockContext(); + + if (ppRenderTargetViews != nullptr) { + for (UINT i = 0; i < NumViews; i++) { + ppRenderTargetViews[i] = i < m_state.om.renderTargetViews.size() + ? m_state.om.renderTargetViews[i].ref() + : nullptr; + } + } + + if (ppDepthStencilView != nullptr) + *ppDepthStencilView = m_state.om.depthStencilView.ref(); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::OMGetRenderTargetsAndUnorderedAccessViews( + UINT NumRTVs, + ID3D11RenderTargetView** ppRenderTargetViews, + ID3D11DepthStencilView** ppDepthStencilView, + UINT UAVStartSlot, + UINT NumUAVs, + ID3D11UnorderedAccessView** ppUnorderedAccessViews) { + OMGetRenderTargets(NumRTVs, ppRenderTargetViews, ppDepthStencilView); + + D3D10DeviceLock lock = LockContext(); + + if (ppUnorderedAccessViews != nullptr) { + for (UINT i = 0; i < NumUAVs; i++) { + ppUnorderedAccessViews[i] = UAVStartSlot + i < m_state.ps.unorderedAccessViews.size() + ? m_state.ps.unorderedAccessViews[UAVStartSlot + i].ref() + : nullptr; + } + } + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::OMGetBlendState( + ID3D11BlendState** ppBlendState, + FLOAT BlendFactor[4], + UINT* pSampleMask) { + D3D10DeviceLock lock = LockContext(); + + if (ppBlendState != nullptr) + *ppBlendState = ref(m_state.om.cbState); + + if (BlendFactor != nullptr) + std::memcpy(BlendFactor, m_state.om.blendFactor, sizeof(FLOAT) * 4); + + if (pSampleMask != nullptr) + *pSampleMask = m_state.om.sampleMask; + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::OMGetDepthStencilState( + ID3D11DepthStencilState** ppDepthStencilState, + UINT* pStencilRef) { + D3D10DeviceLock lock = LockContext(); + + if (ppDepthStencilState != nullptr) + *ppDepthStencilState = ref(m_state.om.dsState); + + if (pStencilRef != nullptr) + *pStencilRef = m_state.om.stencilRef; + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::RSSetState(ID3D11RasterizerState* pRasterizerState) { + D3D10DeviceLock lock = LockContext(); + + auto rasterizerState = static_cast(pRasterizerState); + + bool currScissorEnable = m_state.rs.state != nullptr + ? m_state.rs.state->Desc()->ScissorEnable + : false; + + bool nextScissorEnable = rasterizerState != nullptr + ? rasterizerState->Desc()->ScissorEnable + : false; + + if (m_state.rs.state != rasterizerState) { + m_state.rs.state = rasterizerState; + + // In D3D11, the rasterizer state defines whether the + // scissor test is enabled, so we have to update the + // scissor rectangles as well. + ApplyRasterizerState(); + + if (currScissorEnable != nextScissorEnable) + ApplyViewportState(); + } + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::RSSetViewports( + UINT NumViewports, + const D3D11_VIEWPORT* pViewports) { + D3D10DeviceLock lock = LockContext(); + + if (unlikely(NumViewports > m_state.rs.viewports.size())) + return; + + bool dirty = m_state.rs.numViewports != NumViewports; + m_state.rs.numViewports = NumViewports; + + for (uint32_t i = 0; i < NumViewports; i++) { + const D3D11_VIEWPORT& vp = m_state.rs.viewports[i]; + + dirty |= vp.TopLeftX != pViewports[i].TopLeftX + || vp.TopLeftY != pViewports[i].TopLeftY + || vp.Width != pViewports[i].Width + || vp.Height != pViewports[i].Height + || vp.MinDepth != pViewports[i].MinDepth + || vp.MaxDepth != pViewports[i].MaxDepth; + + m_state.rs.viewports[i] = pViewports[i]; + } + + if (dirty) + ApplyViewportState(); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::RSSetScissorRects( + UINT NumRects, + const D3D11_RECT* pRects) { + D3D10DeviceLock lock = LockContext(); + + if (unlikely(NumRects > m_state.rs.scissors.size())) + return; + + bool dirty = m_state.rs.numScissors != NumRects; + m_state.rs.numScissors = NumRects; + + for (uint32_t i = 0; i < NumRects; i++) { + if (pRects[i].bottom >= pRects[i].top + && pRects[i].right >= pRects[i].left) { + const D3D11_RECT& sr = m_state.rs.scissors[i]; + + dirty |= sr.top != pRects[i].top + || sr.left != pRects[i].left + || sr.bottom != pRects[i].bottom + || sr.right != pRects[i].right; + + m_state.rs.scissors[i] = pRects[i]; + } + } + + if (m_state.rs.state != nullptr && dirty) { + D3D11_RASTERIZER_DESC rsDesc; + m_state.rs.state->GetDesc(&rsDesc); + + if (rsDesc.ScissorEnable) + ApplyViewportState(); + } + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::RSGetState(ID3D11RasterizerState** ppRasterizerState) { + D3D10DeviceLock lock = LockContext(); + + if (ppRasterizerState != nullptr) + *ppRasterizerState = ref(m_state.rs.state); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::RSGetViewports( + UINT* pNumViewports, + D3D11_VIEWPORT* pViewports) { + D3D10DeviceLock lock = LockContext(); + uint32_t numWritten = m_state.rs.numViewports; + + if (pViewports) { + numWritten = std::min(numWritten, *pNumViewports); + + for (uint32_t i = 0; i < *pNumViewports; i++) { + if (i < m_state.rs.numViewports) { + pViewports[i] = m_state.rs.viewports[i]; + } else { + pViewports[i].TopLeftX = 0.0f; + pViewports[i].TopLeftY = 0.0f; + pViewports[i].Width = 0.0f; + pViewports[i].Height = 0.0f; + pViewports[i].MinDepth = 0.0f; + pViewports[i].MaxDepth = 0.0f; + } + } + } + + *pNumViewports = numWritten; + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::RSGetScissorRects( + UINT* pNumRects, + D3D11_RECT* pRects) { + D3D10DeviceLock lock = LockContext(); + uint32_t numWritten = m_state.rs.numScissors; + + if (pRects) { + numWritten = std::min(numWritten, *pNumRects); + + for (uint32_t i = 0; i < *pNumRects; i++) { + if (i < m_state.rs.numScissors) { + pRects[i] = m_state.rs.scissors[i]; + } else { + pRects[i].left = 0; + pRects[i].top = 0; + pRects[i].right = 0; + pRects[i].bottom = 0; + } + } + } + + *pNumRects = m_state.rs.numScissors; + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::SOSetTargets( + UINT NumBuffers, + ID3D11Buffer* const* ppSOTargets, + const UINT* pOffsets) { + D3D10DeviceLock lock = LockContext(); + + for (uint32_t i = 0; i < NumBuffers; i++) { + D3D11Buffer* buffer = static_cast(ppSOTargets[i]); + UINT offset = pOffsets != nullptr ? pOffsets[i] : 0; + + m_state.so.targets[i].buffer = buffer; + m_state.so.targets[i].offset = offset; + } + + for (uint32_t i = NumBuffers; i < D3D11_SO_BUFFER_SLOT_COUNT; i++) { + m_state.so.targets[i].buffer = nullptr; + m_state.so.targets[i].offset = 0; + } + + for (uint32_t i = 0; i < D3D11_SO_BUFFER_SLOT_COUNT; i++) { + BindXfbBuffer(i, + m_state.so.targets[i].buffer.ptr(), + m_state.so.targets[i].offset); + } + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::SOGetTargets( + UINT NumBuffers, + ID3D11Buffer** ppSOTargets) { + D3D10DeviceLock lock = LockContext(); + + for (uint32_t i = 0; i < NumBuffers; i++) { + ppSOTargets[i] = i < m_state.so.targets.size() + ? m_state.so.targets[i].buffer.ref() + : nullptr; + } + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::SOGetTargetsWithOffsets( + UINT NumBuffers, + ID3D11Buffer** ppSOTargets, + UINT* pOffsets) { + D3D10DeviceLock lock = LockContext(); + + for (uint32_t i = 0; i < NumBuffers; i++) { + const bool inRange = i < m_state.so.targets.size(); + + if (ppSOTargets != nullptr) { + ppSOTargets[i] = inRange + ? m_state.so.targets[i].buffer.ref() + : nullptr; + } + + if (pOffsets != nullptr) { + pOffsets[i] = inRange + ? m_state.so.targets[i].offset + : 0u; + } + } + } + + + BOOL STDMETHODCALLTYPE D3D11DeviceContext::IsAnnotationEnabled() { + return m_device->instance()->extensions().extDebugUtils; + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::SetMarkerInt( + LPCWSTR pLabel, + INT Data) { + // Not implemented in the backend, ignore + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::BeginEventInt( + LPCWSTR pLabel, + INT Data) { + // Not implemented in the backend, ignore + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::EndEvent() { + // Not implemented in the backend, ignore + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::GetHardwareProtectionState( + BOOL* pHwProtectionEnable) { + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::err("D3D11DeviceContext::GetHardwareProtectionState: Not implemented"); + + if (pHwProtectionEnable) + *pHwProtectionEnable = FALSE; + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::SetHardwareProtectionState( + BOOL HwProtectionEnable) { + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::err("D3D11DeviceContext::SetHardwareProtectionState: Not implemented"); + } + + + void STDMETHODCALLTYPE D3D11DeviceContext::TransitionSurfaceLayout( + IDXGIVkInteropSurface* pSurface, + const VkImageSubresourceRange* pSubresources, + VkImageLayout OldLayout, + VkImageLayout NewLayout) { + D3D10DeviceLock lock = LockContext(); + + // Get the underlying D3D11 resource + Com resource; + + pSurface->QueryInterface(__uuidof(ID3D11Resource), + reinterpret_cast(&resource)); + + // Get the texture from that resource + D3D11CommonTexture* texture = GetCommonTexture(resource.ptr()); + + EmitCs([ + cImage = texture->GetImage(), + cSubresources = *pSubresources, + cOldLayout = OldLayout, + cNewLayout = NewLayout + ] (DxvkContext* ctx) { + ctx->transformImage( + cImage, cSubresources, + cOldLayout, cNewLayout); + }); + } + + + void D3D11DeviceContext::ApplyInputLayout() { + auto inputLayout = m_state.ia.inputLayout.prvRef(); + + if (likely(inputLayout != nullptr)) { + EmitCs([ + cInputLayout = std::move(inputLayout) + ] (DxvkContext* ctx) { + cInputLayout->BindToContext(ctx); + }); + } else { + EmitCs([] (DxvkContext* ctx) { + ctx->setInputLayout(0, nullptr, 0, nullptr); + }); + } + } + + + void D3D11DeviceContext::ApplyPrimitiveTopology() { + D3D11_PRIMITIVE_TOPOLOGY topology = m_state.ia.primitiveTopology; + DxvkInputAssemblyState iaState = { }; + + if (topology <= D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ) { + static const std::array s_iaStates = {{ + { VK_PRIMITIVE_TOPOLOGY_MAX_ENUM, VK_FALSE, 0 }, + { VK_PRIMITIVE_TOPOLOGY_POINT_LIST, VK_FALSE, 0 }, + { VK_PRIMITIVE_TOPOLOGY_LINE_LIST, VK_FALSE, 0 }, + { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, VK_TRUE, 0 }, + { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, VK_FALSE, 0 }, + { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, VK_TRUE, 0 }, + { }, { }, { }, { }, // Random gap that exists for no reason + { VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY, VK_FALSE, 0 }, + { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY, VK_TRUE, 0 }, + { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY, VK_FALSE, 0 }, + { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY, VK_TRUE, 0 }, + }}; + + iaState = s_iaStates[uint32_t(topology)]; + } else if (topology >= D3D11_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + && topology <= D3D11_PRIMITIVE_TOPOLOGY_32_CONTROL_POINT_PATCHLIST) { + // The number of control points per patch can be inferred from the enum value in D3D11 + uint32_t vertexCount = uint32_t(topology - D3D11_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + 1); + iaState = { VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, VK_FALSE, vertexCount }; + } + + EmitCs([iaState] (DxvkContext* ctx) { + ctx->setInputAssemblyState(iaState); + }); + } + + + void D3D11DeviceContext::ApplyBlendState() { + if (m_state.om.cbState != nullptr) { + EmitCs([ + cBlendState = m_state.om.cbState, + cSampleMask = m_state.om.sampleMask + ] (DxvkContext* ctx) { + cBlendState->BindToContext(ctx, cSampleMask); + }); + } else { + EmitCs([ + cSampleMask = m_state.om.sampleMask + ] (DxvkContext* ctx) { + DxvkBlendMode cbState; + DxvkLogicOpState loState; + DxvkMultisampleState msState; + InitDefaultBlendState(&cbState, &loState, &msState, cSampleMask); + + for (uint32_t i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) + ctx->setBlendMode(i, cbState); + + ctx->setLogicOpState(loState); + ctx->setMultisampleState(msState); + }); + } + } + + + void D3D11DeviceContext::ApplyBlendFactor() { + EmitCs([ + cBlendConstants = DxvkBlendConstants { + m_state.om.blendFactor[0], m_state.om.blendFactor[1], + m_state.om.blendFactor[2], m_state.om.blendFactor[3] } + ] (DxvkContext* ctx) { + ctx->setBlendConstants(cBlendConstants); + }); + } + + + void D3D11DeviceContext::ApplyDepthStencilState() { + if (m_state.om.dsState != nullptr) { + EmitCs([ + cDepthStencilState = m_state.om.dsState + ] (DxvkContext* ctx) { + cDepthStencilState->BindToContext(ctx); + }); + } else { + EmitCs([] (DxvkContext* ctx) { + DxvkDepthStencilState dsState; + InitDefaultDepthStencilState(&dsState); + + ctx->setDepthStencilState(dsState); + }); + } + } + + + void D3D11DeviceContext::ApplyStencilRef() { + EmitCs([ + cStencilRef = m_state.om.stencilRef + ] (DxvkContext* ctx) { + ctx->setStencilReference(cStencilRef); + }); + } + + + void D3D11DeviceContext::ApplyRasterizerState() { + if (m_state.rs.state != nullptr) { + EmitCs([ + cRasterizerState = m_state.rs.state + ] (DxvkContext* ctx) { + cRasterizerState->BindToContext(ctx); + }); + } else { + EmitCs([] (DxvkContext* ctx) { + DxvkRasterizerState rsState; + InitDefaultRasterizerState(&rsState); + + ctx->setRasterizerState(rsState); + }); + } + } + + + void D3D11DeviceContext::ApplyViewportState() { + std::array viewports; + std::array scissors; + + // The backend can't handle a viewport count of zero, + // so we should at least specify one empty viewport + uint32_t viewportCount = m_state.rs.numViewports; + + if (unlikely(!viewportCount)) { + viewportCount = 1; + viewports[0] = VkViewport(); + scissors [0] = VkRect2D(); + } + + // D3D11's coordinate system has its origin in the bottom left, + // but the viewport coordinates are aligned to the top-left + // corner so we can get away with flipping the viewport. + for (uint32_t i = 0; i < m_state.rs.numViewports; i++) { + const D3D11_VIEWPORT& vp = m_state.rs.viewports[i]; + + viewports[i] = VkViewport { + vp.TopLeftX, vp.Height + vp.TopLeftY, + vp.Width, -vp.Height, + vp.MinDepth, vp.MaxDepth, + }; + } + + // Scissor rectangles. Vulkan does not provide an easy way + // to disable the scissor test, so we'll have to set scissor + // rects that are at least as large as the framebuffer. + bool enableScissorTest = false; + + if (m_state.rs.state != nullptr) { + D3D11_RASTERIZER_DESC rsDesc; + m_state.rs.state->GetDesc(&rsDesc); + enableScissorTest = rsDesc.ScissorEnable; + } + + for (uint32_t i = 0; i < m_state.rs.numViewports; i++) { + if (!enableScissorTest) { + scissors[i] = VkRect2D { + VkOffset2D { 0, 0 }, + VkExtent2D { + D3D11_VIEWPORT_BOUNDS_MAX, + D3D11_VIEWPORT_BOUNDS_MAX } }; + } else if (i >= m_state.rs.numScissors) { + scissors[i] = VkRect2D { + VkOffset2D { 0, 0 }, + VkExtent2D { 0, 0 } }; + } else { + D3D11_RECT sr = m_state.rs.scissors[i]; + + VkOffset2D srPosA; + srPosA.x = std::max(0, sr.left); + srPosA.y = std::max(0, sr.top); + + VkOffset2D srPosB; + srPosB.x = std::max(srPosA.x, sr.right); + srPosB.y = std::max(srPosA.y, sr.bottom); + + VkExtent2D srSize; + srSize.width = uint32_t(srPosB.x - srPosA.x); + srSize.height = uint32_t(srPosB.y - srPosA.y); + + scissors[i] = VkRect2D { srPosA, srSize }; + } + } + + if (likely(viewportCount == 1)) { + EmitCs([ + cViewport = viewports[0], + cScissor = scissors[0] + ] (DxvkContext* ctx) { + ctx->setViewports(1, + &cViewport, + &cScissor); + }); + } else { + EmitCs([ + cViewportCount = viewportCount, + cViewports = viewports, + cScissors = scissors + ] (DxvkContext* ctx) { + ctx->setViewports( + cViewportCount, + cViewports.data(), + cScissors.data()); + }); + } + } + + + template + void D3D11DeviceContext::BindShader( + const D3D11CommonShader* pShaderModule) { + // Bind the shader and the ICB at once + EmitCs([ + cSlice = pShaderModule != nullptr + && pShaderModule->GetIcb() != nullptr + ? DxvkBufferSlice(pShaderModule->GetIcb()) + : DxvkBufferSlice(), + cShader = pShaderModule != nullptr + ? pShaderModule->GetShader() + : nullptr + ] (DxvkContext* ctx) { + VkShaderStageFlagBits stage = GetShaderStage(ShaderStage); + + uint32_t slotId = computeConstantBufferBinding(ShaderStage, + D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT); + + ctx->bindShader (stage, cShader); + ctx->bindResourceBuffer(slotId, cSlice); + }); + } + + + void D3D11DeviceContext::BindFramebuffer() { + DxvkRenderTargets attachments; + + // D3D11 doesn't have the concept of a framebuffer object, + // so we'll just create a new one every time the render + // target bindings are updated. Set up the attachments. + for (UINT i = 0; i < m_state.om.renderTargetViews.size(); i++) { + if (m_state.om.renderTargetViews[i] != nullptr) { + attachments.color[i] = { + m_state.om.renderTargetViews[i]->GetImageView(), + m_state.om.renderTargetViews[i]->GetRenderLayout() }; + } + } + + if (m_state.om.depthStencilView != nullptr) { + attachments.depth = { + m_state.om.depthStencilView->GetImageView(), + m_state.om.depthStencilView->GetRenderLayout() }; + } + + // Create and bind the framebuffer object to the context + EmitCs([ + cAttachments = std::move(attachments) + ] (DxvkContext* ctx) { + ctx->bindRenderTargets(cAttachments); + }); + } + + + void D3D11DeviceContext::BindDrawBuffers( + D3D11Buffer* pBufferForArgs, + D3D11Buffer* pBufferForCount) { + EmitCs([ + cArgBuffer = pBufferForArgs ? pBufferForArgs->GetBufferSlice() : DxvkBufferSlice(), + cCntBuffer = pBufferForCount ? pBufferForCount->GetBufferSlice() : DxvkBufferSlice() + ] (DxvkContext* ctx) { + ctx->bindDrawBuffers(cArgBuffer, cCntBuffer); + }); + } + + + void D3D11DeviceContext::BindVertexBuffer( + UINT Slot, + D3D11Buffer* pBuffer, + UINT Offset, + UINT Stride) { + if (likely(pBuffer != nullptr)) { + EmitCs([ + cSlotId = Slot, + cBufferSlice = pBuffer->GetBufferSlice(Offset), + cStride = Stride + ] (DxvkContext* ctx) { + ctx->bindVertexBuffer(cSlotId, cBufferSlice, cStride); + }); + } else { + EmitCs([ + cSlotId = Slot + ] (DxvkContext* ctx) { + ctx->bindVertexBuffer(cSlotId, DxvkBufferSlice(), 0); + }); + } + } + + + void D3D11DeviceContext::BindIndexBuffer( + D3D11Buffer* pBuffer, + UINT Offset, + DXGI_FORMAT Format) { + VkIndexType indexType = Format == DXGI_FORMAT_R16_UINT + ? VK_INDEX_TYPE_UINT16 + : VK_INDEX_TYPE_UINT32; + + EmitCs([ + cBufferSlice = pBuffer != nullptr ? pBuffer->GetBufferSlice(Offset) : DxvkBufferSlice(), + cIndexType = indexType + ] (DxvkContext* ctx) { + ctx->bindIndexBuffer(cBufferSlice, cIndexType); + }); + } + + + void D3D11DeviceContext::BindXfbBuffer( + UINT Slot, + D3D11Buffer* pBuffer, + UINT Offset) { + DxvkBufferSlice bufferSlice; + DxvkBufferSlice counterSlice; + + if (pBuffer != nullptr) { + bufferSlice = pBuffer->GetBufferSlice(); + counterSlice = pBuffer->GetSOCounter(); + } + + EmitCs([ + cSlotId = Slot, + cOffset = Offset, + cBufferSlice = bufferSlice, + cCounterSlice = counterSlice + ] (DxvkContext* ctx) { + if (cCounterSlice.defined() && cOffset != ~0u) { + ctx->updateBuffer( + cCounterSlice.buffer(), + cCounterSlice.offset(), + sizeof(cOffset), + &cOffset); + } + + ctx->bindXfbBuffer(cSlotId, cBufferSlice, cCounterSlice); + }); + } + + + void D3D11DeviceContext::BindConstantBuffer( + UINT Slot, + D3D11Buffer* pBuffer, + UINT Offset, + UINT Length) { + EmitCs([ + cSlotId = Slot, + cBufferSlice = Length ? pBuffer->GetBufferSlice(16 * Offset, 16 * Length) : DxvkBufferSlice() + ] (DxvkContext* ctx) { + ctx->bindResourceBuffer(cSlotId, cBufferSlice); + }); + } + + + void D3D11DeviceContext::BindSampler( + UINT Slot, + D3D11SamplerState* pSampler) { + EmitCs([ + cSlotId = Slot, + cSampler = pSampler != nullptr ? pSampler->GetDXVKSampler() : nullptr + ] (DxvkContext* ctx) { + ctx->bindResourceSampler(cSlotId, cSampler); + }); + } + + + void D3D11DeviceContext::BindShaderResource( + UINT Slot, + D3D11ShaderResourceView* pResource) { + EmitCs([ + cSlotId = Slot, + cImageView = pResource != nullptr ? pResource->GetImageView() : nullptr, + cBufferView = pResource != nullptr ? pResource->GetBufferView() : nullptr + ] (DxvkContext* ctx) { + ctx->bindResourceView(cSlotId, cImageView, cBufferView); + }); + } + + + void D3D11DeviceContext::BindUnorderedAccessView( + UINT UavSlot, + D3D11UnorderedAccessView* pUav, + UINT CtrSlot, + UINT Counter) { + EmitCs([ + cUavSlotId = UavSlot, + cCtrSlotId = CtrSlot, + cImageView = pUav != nullptr ? pUav->GetImageView() : nullptr, + cBufferView = pUav != nullptr ? pUav->GetBufferView() : nullptr, + cCounterSlice = pUav != nullptr ? pUav->GetCounterSlice() : DxvkBufferSlice(), + cCounterValue = Counter + ] (DxvkContext* ctx) { + if (cCounterSlice.defined() && cCounterValue != ~0u) { + ctx->updateBuffer( + cCounterSlice.buffer(), + cCounterSlice.offset(), + sizeof(uint32_t), + &cCounterValue); + } + + ctx->bindResourceView (cUavSlotId, cImageView, cBufferView); + ctx->bindResourceBuffer (cCtrSlotId, cCounterSlice); + }); + } + + + void D3D11DeviceContext::CopyBuffer( + D3D11Buffer* pDstBuffer, + VkDeviceSize DstOffset, + D3D11Buffer* pSrcBuffer, + VkDeviceSize SrcOffset, + VkDeviceSize ByteCount) { + // Clamp copy region to prevent out-of-bounds access + VkDeviceSize dstLength = pDstBuffer->Desc()->ByteWidth; + VkDeviceSize srcLength = pSrcBuffer->Desc()->ByteWidth; + + if (SrcOffset >= srcLength || DstOffset >= dstLength || !ByteCount) + return; + + ByteCount = std::min(dstLength - DstOffset, ByteCount); + ByteCount = std::min(srcLength - SrcOffset, ByteCount); + + EmitCs([ + cDstBuffer = pDstBuffer->GetBufferSlice(DstOffset, ByteCount), + cSrcBuffer = pSrcBuffer->GetBufferSlice(SrcOffset, ByteCount) + ] (DxvkContext* ctx) { + if (cDstBuffer.buffer() != cSrcBuffer.buffer()) { + ctx->copyBuffer( + cDstBuffer.buffer(), + cDstBuffer.offset(), + cSrcBuffer.buffer(), + cSrcBuffer.offset(), + cSrcBuffer.length()); + } else { + ctx->copyBufferRegion( + cDstBuffer.buffer(), + cDstBuffer.offset(), + cSrcBuffer.offset(), + cSrcBuffer.length()); + } + }); + + if (pDstBuffer->HasSequenceNumber()) + TrackBufferSequenceNumber(pDstBuffer); + if (pSrcBuffer->HasSequenceNumber()) + TrackBufferSequenceNumber(pSrcBuffer); + } + + + void D3D11DeviceContext::CopyImage( + D3D11CommonTexture* pDstTexture, + const VkImageSubresourceLayers* pDstLayers, + VkOffset3D DstOffset, + D3D11CommonTexture* pSrcTexture, + const VkImageSubresourceLayers* pSrcLayers, + VkOffset3D SrcOffset, + VkExtent3D SrcExtent) { + // Image formats must be size-compatible + auto dstFormatInfo = imageFormatInfo(pDstTexture->GetPackedFormat()); + auto srcFormatInfo = imageFormatInfo(pSrcTexture->GetPackedFormat()); + + if (dstFormatInfo->elementSize != srcFormatInfo->elementSize) { + Logger::err("D3D11: CopyImage: Incompatible texel size"); + return; + } + + // Sample counts must match + if (pDstTexture->Desc()->SampleDesc.Count != pSrcTexture->Desc()->SampleDesc.Count) { + Logger::err("D3D11: CopyImage: Incompatible sample count"); + return; + } + + // Obviously, the copy region must not be empty + VkExtent3D dstMipExtent = pDstTexture->MipLevelExtent(pDstLayers->mipLevel); + VkExtent3D srcMipExtent = pSrcTexture->MipLevelExtent(pSrcLayers->mipLevel); + + if (uint32_t(DstOffset.x) >= dstMipExtent.width + || uint32_t(DstOffset.y) >= dstMipExtent.height + || uint32_t(DstOffset.z) >= dstMipExtent.depth) + return; + + if (uint32_t(SrcOffset.x) >= srcMipExtent.width + || uint32_t(SrcOffset.y) >= srcMipExtent.height + || uint32_t(SrcOffset.z) >= srcMipExtent.depth) + return; + + // Don't perform the copy if the offsets aren't block-aligned + if (!util::isBlockAligned(SrcOffset, srcFormatInfo->blockSize) + || !util::isBlockAligned(DstOffset, dstFormatInfo->blockSize)) { + Logger::err(str::format("D3D11: CopyImage: Unaligned block offset")); + return; + } + + // Clamp the image region in order to avoid out-of-bounds access + VkExtent3D blockCount = util::computeBlockCount(SrcExtent, srcFormatInfo->blockSize); + VkExtent3D dstBlockCount = util::computeMaxBlockCount(DstOffset, dstMipExtent, dstFormatInfo->blockSize); + VkExtent3D srcBlockCount = util::computeMaxBlockCount(SrcOffset, srcMipExtent, srcFormatInfo->blockSize); + + blockCount = util::minExtent3D(blockCount, dstBlockCount); + blockCount = util::minExtent3D(blockCount, srcBlockCount); + + SrcExtent = util::computeBlockExtent(blockCount, srcFormatInfo->blockSize); + SrcExtent = util::snapExtent3D(SrcOffset, SrcExtent, srcMipExtent); + + if (!SrcExtent.width || !SrcExtent.height || !SrcExtent.depth) + return; + + // While copying between 2D and 3D images is allowed in CopySubresourceRegion, + // copying more than one slice at a time is not suppoted. Layer counts are 1. + if ((pDstTexture->GetVkImageType() == VK_IMAGE_TYPE_3D) + != (pSrcTexture->GetVkImageType() == VK_IMAGE_TYPE_3D)) + SrcExtent.depth = 1; + + // Certain types of copies require us to pass the destination extent to + // the backend. This may be different when copying between compressed + // and uncompressed image formats. + VkExtent3D dstExtent = util::computeBlockExtent(blockCount, dstFormatInfo->blockSize); + dstExtent = util::snapExtent3D(DstOffset, dstExtent, dstMipExtent); + + // It is possible for any of the given images to be a staging image with + // no actual image, so we need to account for all possibilities here. + bool dstIsImage = pDstTexture->GetMapMode() != D3D11_COMMON_TEXTURE_MAP_MODE_STAGING; + bool srcIsImage = pSrcTexture->GetMapMode() != D3D11_COMMON_TEXTURE_MAP_MODE_STAGING; + + if (dstIsImage && srcIsImage) { + EmitCs([ + cDstImage = pDstTexture->GetImage(), + cSrcImage = pSrcTexture->GetImage(), + cDstLayers = *pDstLayers, + cSrcLayers = *pSrcLayers, + cDstOffset = DstOffset, + cSrcOffset = SrcOffset, + cExtent = SrcExtent + ] (DxvkContext* ctx) { + // CopyResource can only copy between different images, and + // CopySubresourceRegion can only copy data from one single + // subresource at a time, so this check is safe. + if (cDstImage != cSrcImage || cDstLayers != cSrcLayers) { + ctx->copyImage( + cDstImage, cDstLayers, cDstOffset, + cSrcImage, cSrcLayers, cSrcOffset, + cExtent); + } else { + ctx->copyImageRegion( + cDstImage, cDstLayers, cDstOffset, + cSrcOffset, cExtent); + } + }); + } else { + // Since each subresource uses a dedicated buffer, we are going + // to need one call per subresource for staging resource copies + for (uint32_t i = 0; i < pDstLayers->layerCount; i++) { + uint32_t dstSubresource = D3D11CalcSubresource(pDstLayers->mipLevel, pDstLayers->baseArrayLayer + i, pDstTexture->Desc()->MipLevels); + uint32_t srcSubresource = D3D11CalcSubresource(pSrcLayers->mipLevel, pSrcLayers->baseArrayLayer + i, pSrcTexture->Desc()->MipLevels); + + // For multi-plane image data stored in a buffer, the backend + // assumes that the second plane immediately follows the first + // plane in memory, which is only true if we copy the full image. + uint32_t planeCount = 1; + + if (dstFormatInfo->flags.test(DxvkFormatFlag::MultiPlane)) { + bool needsSeparateCopies = !dstIsImage && !srcIsImage; + + if (!dstIsImage) + needsSeparateCopies |= pDstTexture->MipLevelExtent(pDstLayers->mipLevel) != SrcExtent; + if (!srcIsImage) + needsSeparateCopies |= pSrcTexture->MipLevelExtent(pSrcLayers->mipLevel) != SrcExtent; + + if (needsSeparateCopies) + planeCount = vk::getPlaneCount(srcFormatInfo->aspectMask); + } + + for (uint32_t j = 0; j < planeCount; j++) { + VkImageAspectFlags dstAspectMask = dstFormatInfo->aspectMask; + VkImageAspectFlags srcAspectMask = srcFormatInfo->aspectMask; + + if (planeCount > 1) { + dstAspectMask = vk::getPlaneAspect(j); + srcAspectMask = dstAspectMask; + } + + if (dstIsImage) { + VkImageSubresourceLayers dstLayer = { dstAspectMask, + pDstLayers->mipLevel, pDstLayers->baseArrayLayer + i, 1 }; + + EmitCs([ + cDstImage = pDstTexture->GetImage(), + cDstLayers = dstLayer, + cDstOffset = DstOffset, + cDstExtent = dstExtent, + cSrcBuffer = pSrcTexture->GetMappedBuffer(srcSubresource), + cSrcLayout = pSrcTexture->GetSubresourceLayout(srcAspectMask, srcSubresource), + cSrcOffset = pSrcTexture->ComputeMappedOffset(srcSubresource, j, SrcOffset), + cSrcCoord = SrcOffset, + cSrcExtent = srcMipExtent, + cSrcFormat = pSrcTexture->GetPackedFormat() + ] (DxvkContext* ctx) { + if (cDstLayers.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { + ctx->copyBufferToImage(cDstImage, cDstLayers, cDstOffset, cDstExtent, + cSrcBuffer, cSrcOffset, cSrcLayout.RowPitch, cSrcLayout.DepthPitch); + } else { + ctx->copyPackedBufferToDepthStencilImage(cDstImage, cDstLayers, + VkOffset2D { cDstOffset.x, cDstOffset.y }, + VkExtent2D { cDstExtent.width, cDstExtent.height }, + cSrcBuffer, cSrcLayout.Offset, + VkOffset2D { cSrcCoord.x, cSrcCoord.y }, + VkExtent2D { cSrcExtent.width, cSrcExtent.height }, + cSrcFormat); + } + }); + } else if (srcIsImage) { + VkImageSubresourceLayers srcLayer = { srcAspectMask, + pSrcLayers->mipLevel, pSrcLayers->baseArrayLayer + i, 1 }; + + EmitCs([ + cSrcImage = pSrcTexture->GetImage(), + cSrcLayers = srcLayer, + cSrcOffset = SrcOffset, + cSrcExtent = SrcExtent, + cDstBuffer = pDstTexture->GetMappedBuffer(dstSubresource), + cDstLayout = pDstTexture->GetSubresourceLayout(dstAspectMask, dstSubresource), + cDstOffset = pDstTexture->ComputeMappedOffset(dstSubresource, j, DstOffset), + cDstCoord = DstOffset, + cDstExtent = dstMipExtent, + cDstFormat = pDstTexture->GetPackedFormat() + ] (DxvkContext* ctx) { + if (cSrcLayers.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { + ctx->copyImageToBuffer(cDstBuffer, cDstOffset, cDstLayout.RowPitch, + cDstLayout.DepthPitch, cSrcImage, cSrcLayers, cSrcOffset, cSrcExtent); + } else { + ctx->copyDepthStencilImageToPackedBuffer(cDstBuffer, cDstLayout.Offset, + VkOffset2D { cDstCoord.x, cDstCoord.y }, + VkExtent2D { cDstExtent.width, cDstExtent.height }, + cSrcImage, cSrcLayers, + VkOffset2D { cSrcOffset.x, cSrcOffset.y }, + VkExtent2D { cSrcExtent.width, cSrcExtent.height }, + cDstFormat); + } + }); + } else { + // The backend is not aware of image metadata in this case, + // so we need to handle image planes and block sizes here + VkDeviceSize elementSize = dstFormatInfo->elementSize; + VkExtent3D dstBlockSize = dstFormatInfo->blockSize; + VkExtent3D srcBlockSize = srcFormatInfo->blockSize; + VkExtent3D planeBlockSize = { 1u, 1u, 1u }; + + if (planeCount > 1) { + auto plane = &dstFormatInfo->planes[j]; + dstBlockSize.width *= plane->blockSize.width; + dstBlockSize.height *= plane->blockSize.height; + srcBlockSize.width *= plane->blockSize.width; + srcBlockSize.height *= plane->blockSize.height; + + planeBlockSize.width = plane->blockSize.width; + planeBlockSize.height = plane->blockSize.height; + elementSize = plane->elementSize; + } + + EmitCs([ + cPixelSize = elementSize, + cSrcBuffer = pSrcTexture->GetMappedBuffer(srcSubresource), + cSrcStart = pSrcTexture->GetSubresourceLayout(srcAspectMask, srcSubresource).Offset, + cSrcOffset = util::computeBlockOffset(SrcOffset, srcBlockSize), + cSrcSize = util::computeBlockCount(srcMipExtent, srcBlockSize), + cDstBuffer = pDstTexture->GetMappedBuffer(dstSubresource), + cDstStart = pDstTexture->GetSubresourceLayout(dstAspectMask, dstSubresource).Offset, + cDstOffset = util::computeBlockOffset(DstOffset, dstBlockSize), + cDstSize = util::computeBlockCount(dstMipExtent, dstBlockSize), + cExtent = util::computeBlockCount(blockCount, planeBlockSize) + ] (DxvkContext* ctx) { + ctx->copyPackedBufferImage( + cDstBuffer, cDstStart, cDstOffset, cDstSize, + cSrcBuffer, cSrcStart, cSrcOffset, cSrcSize, + cExtent, cPixelSize); + }); + } + } + } + } + + if (pDstTexture->HasSequenceNumber()) { + for (uint32_t i = 0; i < pDstLayers->layerCount; i++) { + TrackTextureSequenceNumber(pDstTexture, D3D11CalcSubresource( + pDstLayers->mipLevel, pDstLayers->baseArrayLayer + i, pDstTexture->Desc()->MipLevels)); + } + } + + if (pSrcTexture->HasSequenceNumber()) { + for (uint32_t i = 0; i < pSrcLayers->layerCount; i++) { + TrackTextureSequenceNumber(pSrcTexture, D3D11CalcSubresource( + pSrcLayers->mipLevel, pSrcLayers->baseArrayLayer + i, pSrcTexture->Desc()->MipLevels)); + } + } + } + + + void D3D11DeviceContext::DiscardBuffer( + ID3D11Resource* pResource) { + auto buffer = static_cast(pResource); + + if (buffer->GetMapMode() != D3D11_COMMON_BUFFER_MAP_MODE_NONE) { + D3D11_MAPPED_SUBRESOURCE sr; + + Map(pResource, 0, D3D11_MAP_WRITE_DISCARD, 0, &sr); + Unmap(pResource, 0); + } + } + + + void D3D11DeviceContext::DiscardTexture( + ID3D11Resource* pResource, + UINT Subresource) { + auto texture = GetCommonTexture(pResource); + + if (texture->GetMapMode() != D3D11_COMMON_TEXTURE_MAP_MODE_NONE) { + D3D11_MAPPED_SUBRESOURCE sr; + + Map(pResource, Subresource, D3D11_MAP_WRITE_DISCARD, 0, &sr); + Unmap(pResource, Subresource); + } + } + + + void D3D11DeviceContext::UpdateBuffer( + D3D11Buffer* pDstBuffer, + UINT Offset, + UINT Length, + const void* pSrcData) { + DxvkBufferSlice bufferSlice = pDstBuffer->GetBufferSlice(Offset, Length); + + if (Length <= 1024 && !(Offset & 0x3) && !(Length & 0x3)) { + // The backend has special code paths for small buffer updates, + // however both offset and size must be aligned to four bytes. + DxvkDataSlice dataSlice = AllocUpdateBufferSlice(Length); + std::memcpy(dataSlice.ptr(), pSrcData, Length); + + EmitCs([ + cDataBuffer = std::move(dataSlice), + cBufferSlice = std::move(bufferSlice) + ] (DxvkContext* ctx) { + ctx->updateBuffer( + cBufferSlice.buffer(), + cBufferSlice.offset(), + cBufferSlice.length(), + cDataBuffer.ptr()); + }); + } else { + // Otherwise, to avoid large data copies on the CS thread, + // write directly to a staging buffer and dispatch a copy + DxvkBufferSlice stagingSlice = AllocStagingBuffer(Length); + std::memcpy(stagingSlice.mapPtr(0), pSrcData, Length); + + EmitCs([ + cStagingSlice = std::move(stagingSlice), + cBufferSlice = std::move(bufferSlice) + ] (DxvkContext* ctx) { + ctx->copyBuffer( + cBufferSlice.buffer(), + cBufferSlice.offset(), + cStagingSlice.buffer(), + cStagingSlice.offset(), + cBufferSlice.length()); + }); + } + + if (pDstBuffer->HasSequenceNumber()) + TrackBufferSequenceNumber(pDstBuffer); + } + + + void D3D11DeviceContext::UpdateTexture( + D3D11CommonTexture* pDstTexture, + UINT DstSubresource, + const D3D11_BOX* pDstBox, + const void* pSrcData, + UINT SrcRowPitch, + UINT SrcDepthPitch) { + if (DstSubresource >= pDstTexture->CountSubresources()) + return; + + VkFormat packedFormat = pDstTexture->GetPackedFormat(); + + auto formatInfo = imageFormatInfo(packedFormat); + auto subresource = pDstTexture->GetSubresourceFromIndex( + formatInfo->aspectMask, DstSubresource); + + VkExtent3D mipExtent = pDstTexture->MipLevelExtent(subresource.mipLevel); + + VkOffset3D offset = { 0, 0, 0 }; + VkExtent3D extent = mipExtent; + + if (pDstBox != nullptr) { + if (pDstBox->left >= pDstBox->right + || pDstBox->top >= pDstBox->bottom + || pDstBox->front >= pDstBox->back) + return; // no-op, but legal + + offset.x = pDstBox->left; + offset.y = pDstBox->top; + offset.z = pDstBox->front; + + extent.width = pDstBox->right - pDstBox->left; + extent.height = pDstBox->bottom - pDstBox->top; + extent.depth = pDstBox->back - pDstBox->front; + } + + if (!util::isBlockAligned(offset, extent, formatInfo->blockSize, mipExtent)) { + Logger::err("D3D11: UpdateSubresource1: Unaligned region"); + return; + } + + auto stagingSlice = AllocStagingBuffer(util::computeImageDataSize(packedFormat, extent)); + + util::packImageData(stagingSlice.mapPtr(0), + pSrcData, SrcRowPitch, SrcDepthPitch, 0, 0, + pDstTexture->GetVkImageType(), extent, 1, + formatInfo, formatInfo->aspectMask); + + UpdateImage(pDstTexture, &subresource, + offset, extent, std::move(stagingSlice)); + } + + + void D3D11DeviceContext::UpdateImage( + D3D11CommonTexture* pDstTexture, + const VkImageSubresource* pDstSubresource, + VkOffset3D DstOffset, + VkExtent3D DstExtent, + DxvkBufferSlice StagingBuffer) { + bool dstIsImage = pDstTexture->GetMapMode() != D3D11_COMMON_TEXTURE_MAP_MODE_STAGING; + + uint32_t dstSubresource = D3D11CalcSubresource(pDstSubresource->mipLevel, + pDstSubresource->arrayLayer, pDstTexture->Desc()->MipLevels); + + if (dstIsImage) { + EmitCs([ + cDstImage = pDstTexture->GetImage(), + cDstLayers = vk::makeSubresourceLayers(*pDstSubresource), + cDstOffset = DstOffset, + cDstExtent = DstExtent, + cStagingSlice = std::move(StagingBuffer), + cPackedFormat = pDstTexture->GetPackedFormat() + ] (DxvkContext* ctx) { + if (cDstLayers.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { + ctx->copyBufferToImage(cDstImage, + cDstLayers, cDstOffset, cDstExtent, + cStagingSlice.buffer(), + cStagingSlice.offset(), 0, 0); + } else { + ctx->copyPackedBufferToDepthStencilImage(cDstImage, cDstLayers, + VkOffset2D { cDstOffset.x, cDstOffset.y }, + VkExtent2D { cDstExtent.width, cDstExtent.height }, + cStagingSlice.buffer(), + cStagingSlice.offset(), + VkOffset2D { 0, 0 }, + VkExtent2D { cDstExtent.width, cDstExtent.height }, + cPackedFormat); + } + }); + } else { + // If the destination image is backed only by a buffer, we need to use + // the packed buffer copy function which does not know about planes and + // format metadata, so deal with it manually here. + VkExtent3D dstMipExtent = pDstTexture->MipLevelExtent(pDstSubresource->mipLevel); + + auto dstFormat = pDstTexture->GetPackedFormat(); + auto dstFormatInfo = imageFormatInfo(dstFormat); + + uint32_t planeCount = 1; + + if (dstFormatInfo->flags.test(DxvkFormatFlag::MultiPlane)) + planeCount = vk::getPlaneCount(dstFormatInfo->aspectMask); + + // The source data isn't stored in an image so we'll also need to + // track the offset for that while iterating over the planes. + VkDeviceSize srcPlaneOffset = 0; + + for (uint32_t i = 0; i < planeCount; i++) { + VkImageAspectFlags dstAspectMask = dstFormatInfo->aspectMask; + VkDeviceSize elementSize = dstFormatInfo->elementSize; + VkExtent3D blockSize = dstFormatInfo->blockSize; + + if (dstFormatInfo->flags.test(DxvkFormatFlag::MultiPlane)) { + dstAspectMask = vk::getPlaneAspect(i); + + auto plane = &dstFormatInfo->planes[i]; + blockSize.width *= plane->blockSize.width; + blockSize.height *= plane->blockSize.height; + elementSize = plane->elementSize; + } + + VkExtent3D blockCount = util::computeBlockCount(DstExtent, blockSize); + + EmitCs([ + cDstBuffer = pDstTexture->GetMappedBuffer(dstSubresource), + cDstStart = pDstTexture->GetSubresourceLayout(dstAspectMask, dstSubresource).Offset, + cDstOffset = util::computeBlockOffset(DstOffset, blockSize), + cDstSize = util::computeBlockCount(dstMipExtent, blockSize), + cDstExtent = blockCount, + cSrcBuffer = StagingBuffer.buffer(), + cSrcStart = StagingBuffer.offset() + srcPlaneOffset, + cPixelSize = elementSize + ] (DxvkContext* ctx) { + ctx->copyPackedBufferImage( + cDstBuffer, cDstStart, cDstOffset, cDstSize, + cSrcBuffer, cSrcStart, VkOffset3D(), cDstExtent, + cDstExtent, cPixelSize); + }); + + srcPlaneOffset += util::flattenImageExtent(blockCount) * elementSize; + } + } + + if (pDstTexture->HasSequenceNumber()) + TrackTextureSequenceNumber(pDstTexture, dstSubresource); + } + + + void D3D11DeviceContext::SetDrawBuffers( + ID3D11Buffer* pBufferForArgs, + ID3D11Buffer* pBufferForCount) { + auto argBuffer = static_cast(pBufferForArgs); + auto cntBuffer = static_cast(pBufferForCount); + + if (m_state.id.argBuffer != argBuffer + || m_state.id.cntBuffer != cntBuffer) { + m_state.id.argBuffer = argBuffer; + m_state.id.cntBuffer = cntBuffer; + + BindDrawBuffers(argBuffer, cntBuffer); + } + } + + + template + void D3D11DeviceContext::SetConstantBuffers( + D3D11ConstantBufferBindings& Bindings, + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer* const* ppConstantBuffers) { + uint32_t slotId = computeConstantBufferBinding(ShaderStage, StartSlot); + + for (uint32_t i = 0; i < NumBuffers; i++) { + auto newBuffer = static_cast(ppConstantBuffers[i]); + + UINT constantCount = 0; + + if (likely(newBuffer != nullptr)) + constantCount = std::min(newBuffer->Desc()->ByteWidth / 16, UINT(D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT)); + + if (Bindings[StartSlot + i].buffer != newBuffer + || Bindings[StartSlot + i].constantCount != constantCount) { + Bindings[StartSlot + i].buffer = newBuffer; + Bindings[StartSlot + i].constantOffset = 0; + Bindings[StartSlot + i].constantCount = constantCount; + Bindings[StartSlot + i].constantBound = constantCount; + + BindConstantBuffer(slotId + i, newBuffer, 0, constantCount); + } + } + } + + + template + void D3D11DeviceContext::SetConstantBuffers1( + D3D11ConstantBufferBindings& Bindings, + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer* const* ppConstantBuffers, + const UINT* pFirstConstant, + const UINT* pNumConstants) { + uint32_t slotId = computeConstantBufferBinding(ShaderStage, StartSlot); + + for (uint32_t i = 0; i < NumBuffers; i++) { + auto newBuffer = static_cast(ppConstantBuffers[i]); + + UINT constantOffset; + UINT constantCount; + UINT constantBound; + + if (likely(newBuffer != nullptr)) { + UINT bufferConstantsCount = newBuffer->Desc()->ByteWidth / 16; + constantBound = std::min(bufferConstantsCount, UINT(D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT)); + + if (likely(pFirstConstant && pNumConstants)) { + constantOffset = pFirstConstant[i]; + constantCount = pNumConstants [i]; + + if (unlikely(constantCount > D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT)) + continue; + + constantBound = (constantOffset + constantCount > bufferConstantsCount) + ? bufferConstantsCount - std::min(constantOffset, bufferConstantsCount) + : constantCount; + } else { + constantOffset = 0; + constantCount = constantBound; + } + } else { + constantOffset = 0; + constantCount = 0; + constantBound = 0; + } + + bool needsUpdate = Bindings[StartSlot + i].buffer != newBuffer; + + if (needsUpdate) + Bindings[StartSlot + i].buffer = newBuffer; + + needsUpdate |= Bindings[StartSlot + i].constantOffset != constantOffset + || Bindings[StartSlot + i].constantCount != constantCount; + + if (needsUpdate) { + Bindings[StartSlot + i].constantOffset = constantOffset; + Bindings[StartSlot + i].constantCount = constantCount; + Bindings[StartSlot + i].constantBound = constantBound; + + BindConstantBuffer(slotId + i, newBuffer, constantOffset, constantBound); + } + } + } + + + template + void D3D11DeviceContext::SetSamplers( + D3D11SamplerBindings& Bindings, + UINT StartSlot, + UINT NumSamplers, + ID3D11SamplerState* const* ppSamplers) { + uint32_t slotId = computeSamplerBinding(ShaderStage, StartSlot); + + for (uint32_t i = 0; i < NumSamplers; i++) { + auto sampler = static_cast(ppSamplers[i]); + + if (Bindings[StartSlot + i] != sampler) { + Bindings[StartSlot + i] = sampler; + BindSampler(slotId + i, sampler); + } + } + } + + + template + void D3D11DeviceContext::SetShaderResources( + D3D11ShaderResourceBindings& Bindings, + UINT StartSlot, + UINT NumResources, + ID3D11ShaderResourceView* const* ppResources) { + uint32_t slotId = computeSrvBinding(ShaderStage, StartSlot); + + for (uint32_t i = 0; i < NumResources; i++) { + auto resView = static_cast(ppResources[i]); + + if (Bindings.views[StartSlot + i] != resView) { + if (unlikely(resView && resView->TestHazards())) { + if (TestSrvHazards(resView)) + resView = nullptr; + + // Only set if necessary, but don't reset it on every + // bind as this would be more expensive than a few + // redundant checks in OMSetRenderTargets and friends. + Bindings.hazardous.set(StartSlot + i, resView); + } + + Bindings.views[StartSlot + i] = resView; + BindShaderResource(slotId + i, resView); + } + } + } + + + void D3D11DeviceContext::GetConstantBuffers( + const D3D11ConstantBufferBindings& Bindings, + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer** ppConstantBuffers, + UINT* pFirstConstant, + UINT* pNumConstants) { + for (uint32_t i = 0; i < NumBuffers; i++) { + const bool inRange = StartSlot + i < Bindings.size(); + + if (ppConstantBuffers != nullptr) { + ppConstantBuffers[i] = inRange + ? Bindings[StartSlot + i].buffer.ref() + : nullptr; + } + + if (pFirstConstant != nullptr) { + pFirstConstant[i] = inRange + ? Bindings[StartSlot + i].constantOffset + : 0u; + } + + if (pNumConstants != nullptr) { + pNumConstants[i] = inRange + ? Bindings[StartSlot + i].constantCount + : 0u; + } + } + } + + + void D3D11DeviceContext::GetShaderResources( + const D3D11ShaderResourceBindings& Bindings, + UINT StartSlot, + UINT NumViews, + ID3D11ShaderResourceView** ppShaderResourceViews) { + for (uint32_t i = 0; i < NumViews; i++) { + ppShaderResourceViews[i] = StartSlot + i < Bindings.views.size() + ? Bindings.views[StartSlot + i].ref() + : nullptr; + } + } + + + void D3D11DeviceContext::GetSamplers( + const D3D11SamplerBindings& Bindings, + UINT StartSlot, + UINT NumSamplers, + ID3D11SamplerState** ppSamplers) { + for (uint32_t i = 0; i < NumSamplers; i++) { + ppSamplers[i] = StartSlot + i < Bindings.size() + ? ref(Bindings[StartSlot + i]) + : nullptr; + } + } + + + void D3D11DeviceContext::ResetState() { + EmitCs([] (DxvkContext* ctx) { + // Reset render targets + ctx->bindRenderTargets(DxvkRenderTargets()); + + // Reset vertex input state + ctx->setInputLayout(0, nullptr, 0, nullptr); + + // Reset render states + DxvkInputAssemblyState iaState; + InitDefaultPrimitiveTopology(&iaState); + + DxvkDepthStencilState dsState; + InitDefaultDepthStencilState(&dsState); + + DxvkRasterizerState rsState; + InitDefaultRasterizerState(&rsState); + + DxvkBlendMode cbState; + DxvkLogicOpState loState; + DxvkMultisampleState msState; + InitDefaultBlendState(&cbState, &loState, &msState, D3D11_DEFAULT_SAMPLE_MASK); + + ctx->setInputAssemblyState(iaState); + ctx->setDepthStencilState(dsState); + ctx->setRasterizerState(rsState); + ctx->setLogicOpState(loState); + ctx->setMultisampleState(msState); + + for (uint32_t i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) + ctx->setBlendMode(i, cbState); + + // Reset dynamic states + ctx->setBlendConstants(DxvkBlendConstants { 1.0f, 1.0f, 1.0f, 1.0f }); + ctx->setStencilReference(D3D11_DEFAULT_STENCIL_REFERENCE); + + // Reset viewports + auto viewport = VkViewport(); + auto scissor = VkRect2D(); + + ctx->setViewports(1, &viewport, &scissor); + + // Unbind indirect draw buffer + ctx->bindDrawBuffers(DxvkBufferSlice(), DxvkBufferSlice()); + + // Unbind index and vertex buffers + ctx->bindIndexBuffer(DxvkBufferSlice(), VK_INDEX_TYPE_UINT32); + + for (uint32_t i = 0; i < D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; i++) + ctx->bindVertexBuffer(i, DxvkBufferSlice(), 0); + + // Unbind transform feedback buffers + for (uint32_t i = 0; i < D3D11_SO_BUFFER_SLOT_COUNT; i++) + ctx->bindXfbBuffer(i, DxvkBufferSlice(), DxvkBufferSlice()); + + // Unbind per-shader stage resources + for (uint32_t i = 0; i < 6; i++) { + auto programType = DxbcProgramType(i); + ctx->bindShader(GetShaderStage(programType), nullptr); + + // Unbind constant buffers, including the shader's ICB + auto cbSlotId = computeConstantBufferBinding(programType, 0); + + for (uint32_t j = 0; j <= D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; j++) + ctx->bindResourceBuffer(cbSlotId + j, DxvkBufferSlice()); + + // Unbind shader resource views + auto srvSlotId = computeSrvBinding(programType, 0); + + for (uint32_t j = 0; j < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; j++) + ctx->bindResourceView(srvSlotId + j, nullptr, nullptr); + + // Unbind texture samplers + auto samplerSlotId = computeSamplerBinding(programType, 0); + + for (uint32_t j = 0; j < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; j++) + ctx->bindResourceSampler(samplerSlotId + j, nullptr); + + // Unbind UAVs for supported stages + if (programType == DxbcProgramType::PixelShader + || programType == DxbcProgramType::ComputeShader) { + auto uavSlotId = computeUavBinding(programType, 0); + auto ctrSlotId = computeUavCounterBinding(programType, 0); + + for (uint32_t j = 0; j < D3D11_1_UAV_SLOT_COUNT; j++) { + ctx->bindResourceView (uavSlotId, nullptr, nullptr); + ctx->bindResourceBuffer (ctrSlotId, DxvkBufferSlice()); + } + } + } + }); + } + + + void D3D11DeviceContext::RestoreState() { + BindFramebuffer(); + + BindShader (GetCommonShader(m_state.vs.shader.ptr())); + BindShader (GetCommonShader(m_state.hs.shader.ptr())); + BindShader (GetCommonShader(m_state.ds.shader.ptr())); + BindShader (GetCommonShader(m_state.gs.shader.ptr())); + BindShader (GetCommonShader(m_state.ps.shader.ptr())); + BindShader (GetCommonShader(m_state.cs.shader.ptr())); + + ApplyInputLayout(); + ApplyPrimitiveTopology(); + ApplyBlendState(); + ApplyBlendFactor(); + ApplyDepthStencilState(); + ApplyStencilRef(); + ApplyRasterizerState(); + ApplyViewportState(); + + BindDrawBuffers( + m_state.id.argBuffer.ptr(), + m_state.id.cntBuffer.ptr()); + + BindIndexBuffer( + m_state.ia.indexBuffer.buffer.ptr(), + m_state.ia.indexBuffer.offset, + m_state.ia.indexBuffer.format); + + for (uint32_t i = 0; i < m_state.ia.vertexBuffers.size(); i++) { + BindVertexBuffer(i, + m_state.ia.vertexBuffers[i].buffer.ptr(), + m_state.ia.vertexBuffers[i].offset, + m_state.ia.vertexBuffers[i].stride); + } + + for (uint32_t i = 0; i < m_state.so.targets.size(); i++) + BindXfbBuffer(i, m_state.so.targets[i].buffer.ptr(), ~0u); + + RestoreConstantBuffers (m_state.vs.constantBuffers); + RestoreConstantBuffers (m_state.hs.constantBuffers); + RestoreConstantBuffers (m_state.ds.constantBuffers); + RestoreConstantBuffers (m_state.gs.constantBuffers); + RestoreConstantBuffers (m_state.ps.constantBuffers); + RestoreConstantBuffers (m_state.cs.constantBuffers); + + RestoreSamplers (m_state.vs.samplers); + RestoreSamplers (m_state.hs.samplers); + RestoreSamplers (m_state.ds.samplers); + RestoreSamplers(m_state.gs.samplers); + RestoreSamplers (m_state.ps.samplers); + RestoreSamplers (m_state.cs.samplers); + + RestoreShaderResources (m_state.vs.shaderResources); + RestoreShaderResources (m_state.hs.shaderResources); + RestoreShaderResources (m_state.ds.shaderResources); + RestoreShaderResources (m_state.gs.shaderResources); + RestoreShaderResources (m_state.ps.shaderResources); + RestoreShaderResources (m_state.cs.shaderResources); + + RestoreUnorderedAccessViews (m_state.ps.unorderedAccessViews); + RestoreUnorderedAccessViews (m_state.cs.unorderedAccessViews); + } + + + template + void D3D11DeviceContext::RestoreConstantBuffers( + D3D11ConstantBufferBindings& Bindings) { + uint32_t slotId = computeConstantBufferBinding(Stage, 0); + + for (uint32_t i = 0; i < Bindings.size(); i++) { + BindConstantBuffer(slotId + i, Bindings[i].buffer.ptr(), + Bindings[i].constantOffset, Bindings[i].constantBound); + } + } + + + template + void D3D11DeviceContext::RestoreSamplers( + D3D11SamplerBindings& Bindings) { + uint32_t slotId = computeSamplerBinding(Stage, 0); + + for (uint32_t i = 0; i < Bindings.size(); i++) + BindSampler(slotId + i, Bindings[i]); + } + + + template + void D3D11DeviceContext::RestoreShaderResources( + D3D11ShaderResourceBindings& Bindings) { + uint32_t slotId = computeSrvBinding(Stage, 0); + + for (uint32_t i = 0; i < Bindings.views.size(); i++) + BindShaderResource(slotId + i, Bindings.views[i].ptr()); + } + + + template + void D3D11DeviceContext::RestoreUnorderedAccessViews( + D3D11UnorderedAccessBindings& Bindings) { + uint32_t uavSlotId = computeUavBinding (Stage, 0); + uint32_t ctrSlotId = computeUavCounterBinding(Stage, 0); + + for (uint32_t i = 0; i < Bindings.size(); i++) { + BindUnorderedAccessView( + uavSlotId + i, + Bindings[i].ptr(), + ctrSlotId + i, ~0u); + } + } + + + bool D3D11DeviceContext::TestRtvUavHazards( + UINT NumRTVs, + ID3D11RenderTargetView* const* ppRTVs, + UINT NumUAVs, + ID3D11UnorderedAccessView* const* ppUAVs) { + if (NumRTVs == D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL) NumRTVs = 0; + if (NumUAVs == D3D11_KEEP_UNORDERED_ACCESS_VIEWS) NumUAVs = 0; + + for (uint32_t i = 0; i < NumRTVs; i++) { + auto rtv = static_cast(ppRTVs[i]); + + if (!rtv) + continue; + + for (uint32_t j = 0; j < i; j++) { + if (CheckViewOverlap(rtv, static_cast(ppRTVs[j]))) + return true; + } + + if (rtv->HasBindFlag(D3D11_BIND_UNORDERED_ACCESS)) { + for (uint32_t j = 0; j < NumUAVs; j++) { + if (CheckViewOverlap(rtv, static_cast(ppUAVs[j]))) + return true; + } + } + } + + for (uint32_t i = 0; i < NumUAVs; i++) { + auto uav = static_cast(ppUAVs[i]); + + if (!uav) + continue; + + for (uint32_t j = 0; j < i; j++) { + if (CheckViewOverlap(uav, static_cast(ppUAVs[j]))) + return true; + } + } + + return false; + } + + + template + bool D3D11DeviceContext::TestSrvHazards( + D3D11ShaderResourceView* pView) { + bool hazard = false; + + if (ShaderStage == DxbcProgramType::ComputeShader) { + int32_t uav = m_state.cs.uavMask.findNext(0); + + while (uav >= 0 && !hazard) { + hazard = CheckViewOverlap(pView, m_state.cs.unorderedAccessViews[uav].ptr()); + uav = m_state.cs.uavMask.findNext(uav + 1); + } + } else { + hazard = CheckViewOverlap(pView, m_state.om.depthStencilView.ptr()); + + for (uint32_t i = 0; !hazard && i < m_state.om.maxRtv; i++) + hazard = CheckViewOverlap(pView, m_state.om.renderTargetViews[i].ptr()); + + for (uint32_t i = 0; !hazard && i < m_state.om.maxUav; i++) + hazard = CheckViewOverlap(pView, m_state.ps.unorderedAccessViews[i].ptr()); + } + + return hazard; + } + + + template + void D3D11DeviceContext::ResolveSrvHazards( + T* pView, + D3D11ShaderResourceBindings& Bindings) { + uint32_t slotId = computeSrvBinding(ShaderStage, 0); + int32_t srvId = Bindings.hazardous.findNext(0); + + while (srvId >= 0) { + auto srv = Bindings.views[srvId].ptr(); + + if (likely(srv && srv->TestHazards())) { + bool hazard = CheckViewOverlap(pView, srv); + + if (unlikely(hazard)) { + Bindings.views[srvId] = nullptr; + Bindings.hazardous.clr(srvId); + + BindShaderResource(slotId + srvId, nullptr); + } + } else { + // Avoid further redundant iterations + Bindings.hazardous.clr(srvId); + } + + srvId = Bindings.hazardous.findNext(srvId + 1); + } + } + + + template + void D3D11DeviceContext::ResolveCsSrvHazards( + T* pView) { + if (!pView) return; + ResolveSrvHazards (pView, m_state.cs.shaderResources); + } + + + template + void D3D11DeviceContext::ResolveOmSrvHazards( + T* pView) { + if (!pView) return; + ResolveSrvHazards (pView, m_state.vs.shaderResources); + ResolveSrvHazards (pView, m_state.hs.shaderResources); + ResolveSrvHazards (pView, m_state.ds.shaderResources); + ResolveSrvHazards (pView, m_state.gs.shaderResources); + ResolveSrvHazards (pView, m_state.ps.shaderResources); + } + + + bool D3D11DeviceContext::ResolveOmRtvHazards( + D3D11UnorderedAccessView* pView) { + if (!pView || !pView->HasBindFlag(D3D11_BIND_RENDER_TARGET)) + return false; + + bool hazard = false; + + if (CheckViewOverlap(pView, m_state.om.depthStencilView.ptr())) { + m_state.om.depthStencilView = nullptr; + hazard = true; + } + + for (uint32_t i = 0; i < m_state.om.maxRtv; i++) { + if (CheckViewOverlap(pView, m_state.om.renderTargetViews[i].ptr())) { + m_state.om.renderTargetViews[i] = nullptr; + hazard = true; + } + } + + return hazard; + } + + + void D3D11DeviceContext::ResolveOmUavHazards( + D3D11RenderTargetView* pView) { + if (!pView || !pView->HasBindFlag(D3D11_BIND_UNORDERED_ACCESS)) + return; + + uint32_t uavSlotId = computeUavBinding (DxbcProgramType::PixelShader, 0); + uint32_t ctrSlotId = computeUavCounterBinding(DxbcProgramType::PixelShader, 0); + + for (uint32_t i = 0; i < m_state.om.maxUav; i++) { + if (CheckViewOverlap(pView, m_state.ps.unorderedAccessViews[i].ptr())) { + m_state.ps.unorderedAccessViews[i] = nullptr; + + BindUnorderedAccessView( + uavSlotId + i, nullptr, + ctrSlotId + i, ~0u); + } + } + } + + + bool D3D11DeviceContext::ValidateRenderTargets( + UINT NumViews, + ID3D11RenderTargetView* const* ppRenderTargetViews, + ID3D11DepthStencilView* pDepthStencilView) { + Rc refView; + + VkExtent3D dsvExtent = { 0u, 0u, 0u }; + VkExtent3D rtvExtent = { 0u, 0u, 0u }; + + if (pDepthStencilView != nullptr) { + refView = static_cast( + pDepthStencilView)->GetImageView(); + dsvExtent = refView->mipLevelExtent(0); + } + + for (uint32_t i = 0; i < NumViews; i++) { + if (ppRenderTargetViews[i] != nullptr) { + auto curView = static_cast( + ppRenderTargetViews[i])->GetImageView(); + + if (!rtvExtent.width) + rtvExtent = curView->mipLevelExtent(0); + + if (refView != nullptr) { + // Render target views must all have the same sample count, + // layer count, and type. The size can mismatch under certain + // conditions, the D3D11 documentation is wrong here. + if (curView->info().type != refView->info().type + || curView->info().numLayers != refView->info().numLayers) + return false; + + if (curView->imageInfo().sampleCount + != refView->imageInfo().sampleCount) + return false; + + // Color targets must all be the same size + VkExtent3D curExtent = curView->mipLevelExtent(0); + + if (curExtent.width != rtvExtent.width + || curExtent.height != rtvExtent.height) + return false; + } else { + // Set reference view. All remaining views + // must be compatible to the reference view. + refView = curView; + } + } + } + + // Based on testing, the depth-stencil target is allowed + // to be larger than all color targets, but not smaller + if (rtvExtent.width && dsvExtent.width) { + if (rtvExtent.width > dsvExtent.width + || rtvExtent.height > dsvExtent.height) + return false; + } + + return true; + } + + + VkClearValue D3D11DeviceContext::ConvertColorValue( + const FLOAT Color[4], + const DxvkFormatInfo* pFormatInfo) { + VkClearValue result; + + if (pFormatInfo->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) { + for (uint32_t i = 0; i < 4; i++) { + if (pFormatInfo->flags.test(DxvkFormatFlag::SampledUInt)) + result.color.uint32[i] = uint32_t(std::max(0.0f, Color[i])); + else if (pFormatInfo->flags.test(DxvkFormatFlag::SampledSInt)) + result.color.int32[i] = int32_t(Color[i]); + else + result.color.float32[i] = Color[i]; + } + } else { + result.depthStencil.depth = Color[0]; + result.depthStencil.stencil = 0; + } + + return result; + } + + + DxvkDataSlice D3D11DeviceContext::AllocUpdateBufferSlice(size_t Size) { + constexpr size_t UpdateBufferSize = 1 * 1024 * 1024; + + if (Size >= UpdateBufferSize) { + Rc buffer = new DxvkDataBuffer(Size); + return buffer->alloc(Size); + } else { + if (m_updateBuffer == nullptr) + m_updateBuffer = new DxvkDataBuffer(UpdateBufferSize); + + DxvkDataSlice slice = m_updateBuffer->alloc(Size); + + if (slice.ptr() == nullptr) { + m_updateBuffer = new DxvkDataBuffer(UpdateBufferSize); + slice = m_updateBuffer->alloc(Size); + } + + return slice; + } + } + + + DxvkBufferSlice D3D11DeviceContext::AllocStagingBuffer( + VkDeviceSize Size) { + return m_staging.alloc(256, Size); + } + + + void D3D11DeviceContext::ResetStagingBuffer() { + m_staging.reset(); + } + + + DxvkCsChunkRef D3D11DeviceContext::AllocCsChunk() { + return m_parent->AllocCsChunk(m_csFlags); + } + + + void D3D11DeviceContext::InitDefaultPrimitiveTopology( + DxvkInputAssemblyState* pIaState) { + pIaState->primitiveTopology = VK_PRIMITIVE_TOPOLOGY_MAX_ENUM; + pIaState->primitiveRestart = VK_FALSE; + pIaState->patchVertexCount = 0; + } + + + void D3D11DeviceContext::InitDefaultRasterizerState( + DxvkRasterizerState* pRsState) { + pRsState->polygonMode = VK_POLYGON_MODE_FILL; + pRsState->cullMode = VK_CULL_MODE_BACK_BIT; + pRsState->frontFace = VK_FRONT_FACE_CLOCKWISE; + pRsState->depthClipEnable = VK_TRUE; + pRsState->depthBiasEnable = VK_FALSE; + pRsState->conservativeMode = VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT; + pRsState->sampleCount = 0; + } + + + void D3D11DeviceContext::InitDefaultDepthStencilState( + DxvkDepthStencilState* pDsState) { + VkStencilOpState stencilOp; + stencilOp.failOp = VK_STENCIL_OP_KEEP; + stencilOp.passOp = VK_STENCIL_OP_KEEP; + stencilOp.depthFailOp = VK_STENCIL_OP_KEEP; + stencilOp.compareOp = VK_COMPARE_OP_ALWAYS; + stencilOp.compareMask = D3D11_DEFAULT_STENCIL_READ_MASK; + stencilOp.writeMask = D3D11_DEFAULT_STENCIL_WRITE_MASK; + stencilOp.reference = 0; + + pDsState->enableDepthTest = VK_TRUE; + pDsState->enableDepthWrite = VK_TRUE; + pDsState->enableStencilTest = VK_FALSE; + pDsState->depthCompareOp = VK_COMPARE_OP_LESS; + pDsState->stencilOpFront = stencilOp; + pDsState->stencilOpBack = stencilOp; + } + + + void D3D11DeviceContext::InitDefaultBlendState( + DxvkBlendMode* pCbState, + DxvkLogicOpState* pLoState, + DxvkMultisampleState* pMsState, + UINT SampleMask) { + pCbState->enableBlending = VK_FALSE; + pCbState->colorSrcFactor = VK_BLEND_FACTOR_ONE; + pCbState->colorDstFactor = VK_BLEND_FACTOR_ZERO; + pCbState->colorBlendOp = VK_BLEND_OP_ADD; + pCbState->alphaSrcFactor = VK_BLEND_FACTOR_ONE; + pCbState->alphaDstFactor = VK_BLEND_FACTOR_ZERO; + pCbState->alphaBlendOp = VK_BLEND_OP_ADD; + pCbState->writeMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT + | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + + pLoState->enableLogicOp = VK_FALSE; + pLoState->logicOp = VK_LOGIC_OP_NO_OP; + + pMsState->sampleMask = SampleMask; + pMsState->enableAlphaToCoverage = VK_FALSE; + } + + + void D3D11DeviceContext::TrackResourceSequenceNumber( + ID3D11Resource* pResource) { + if (!pResource) + return; + + D3D11CommonTexture* texture = GetCommonTexture(pResource); + + if (texture) { + if (texture->HasSequenceNumber()) { + for (uint32_t i = 0; i < texture->CountSubresources(); i++) + TrackTextureSequenceNumber(texture, i); + } + } else { + D3D11Buffer* buffer = static_cast(pResource); + + if (buffer->HasSequenceNumber()) + TrackBufferSequenceNumber(buffer); + } + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_context.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_context.h new file mode 100644 index 00000000000..3bd60a57809 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_context.h @@ -0,0 +1,1089 @@ +#pragma once + +#include "../dxvk/dxvk_adapter.h" +#include "../dxvk/dxvk_cs.h" +#include "../dxvk/dxvk_device.h" +#include "../dxvk/dxvk_staging.h" + +#include "../d3d10/d3d10_multithread.h" + +#include "d3d11_annotation.h" +#include "d3d11_cmd.h" +#include "d3d11_context_ext.h" +#include "d3d11_context_state.h" +#include "d3d11_device_child.h" +#include "d3d11_texture.h" + +namespace dxvk { + + class D3D11Device; + + class D3D11DeviceContext : public D3D11DeviceChild { + friend class D3D11DeviceContextExt; + // Needed in order to call EmitCs for pushing markers + friend class D3D11UserDefinedAnnotation; + + constexpr static VkDeviceSize StagingBufferSize = 4ull << 20; + public: + + D3D11DeviceContext( + D3D11Device* pParent, + const Rc& Device, + DxvkCsChunkFlags CsFlags); + ~D3D11DeviceContext(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + void STDMETHODCALLTYPE DiscardResource(ID3D11Resource *pResource); + + void STDMETHODCALLTYPE DiscardView(ID3D11View* pResourceView); + + void STDMETHODCALLTYPE DiscardView1( + ID3D11View* pResourceView, + const D3D11_RECT* pRects, + UINT NumRects); + + void STDMETHODCALLTYPE ClearState(); + + void STDMETHODCALLTYPE SetPredication( + ID3D11Predicate* pPredicate, + BOOL PredicateValue); + + void STDMETHODCALLTYPE GetPredication( + ID3D11Predicate** ppPredicate, + BOOL* pPredicateValue); + + void STDMETHODCALLTYPE CopySubresourceRegion( + ID3D11Resource* pDstResource, + UINT DstSubresource, + UINT DstX, + UINT DstY, + UINT DstZ, + ID3D11Resource* pSrcResource, + UINT SrcSubresource, + const D3D11_BOX* pSrcBox); + + void STDMETHODCALLTYPE CopySubresourceRegion1( + ID3D11Resource* pDstResource, + UINT DstSubresource, + UINT DstX, + UINT DstY, + UINT DstZ, + ID3D11Resource* pSrcResource, + UINT SrcSubresource, + const D3D11_BOX* pSrcBox, + UINT CopyFlags); + + void STDMETHODCALLTYPE CopyResource( + ID3D11Resource* pDstResource, + ID3D11Resource* pSrcResource); + + void STDMETHODCALLTYPE CopyStructureCount( + ID3D11Buffer* pDstBuffer, + UINT DstAlignedByteOffset, + ID3D11UnorderedAccessView* pSrcView); + + void STDMETHODCALLTYPE CopyTiles( + ID3D11Resource* pTiledResource, + const D3D11_TILED_RESOURCE_COORDINATE* pTileRegionStartCoordinate, + const D3D11_TILE_REGION_SIZE* pTileRegionSize, + ID3D11Buffer* pBuffer, + UINT64 BufferStartOffsetInBytes, + UINT Flags); + + HRESULT STDMETHODCALLTYPE CopyTileMappings( + ID3D11Resource* pDestTiledResource, + const D3D11_TILED_RESOURCE_COORDINATE* pDestRegionStartCoordinate, + ID3D11Resource* pSourceTiledResource, + const D3D11_TILED_RESOURCE_COORDINATE* pSourceRegionStartCoordinate, + const D3D11_TILE_REGION_SIZE* pTileRegionSize, + UINT Flags); + + HRESULT STDMETHODCALLTYPE ResizeTilePool( + ID3D11Buffer* pTilePool, + UINT64 NewSizeInBytes); + + void STDMETHODCALLTYPE TiledResourceBarrier( + ID3D11DeviceChild* pTiledResourceOrViewAccessBeforeBarrier, + ID3D11DeviceChild* pTiledResourceOrViewAccessAfterBarrier); + + void STDMETHODCALLTYPE ClearRenderTargetView( + ID3D11RenderTargetView* pRenderTargetView, + const FLOAT ColorRGBA[4]); + + void STDMETHODCALLTYPE ClearUnorderedAccessViewUint( + ID3D11UnorderedAccessView* pUnorderedAccessView, + const UINT Values[4]); + + void STDMETHODCALLTYPE ClearUnorderedAccessViewFloat( + ID3D11UnorderedAccessView* pUnorderedAccessView, + const FLOAT Values[4]); + + void STDMETHODCALLTYPE ClearDepthStencilView( + ID3D11DepthStencilView* pDepthStencilView, + UINT ClearFlags, + FLOAT Depth, + UINT8 Stencil); + + void STDMETHODCALLTYPE ClearView( + ID3D11View *pView, + const FLOAT Color[4], + const D3D11_RECT *pRect, + UINT NumRects); + + void STDMETHODCALLTYPE GenerateMips( + ID3D11ShaderResourceView* pShaderResourceView); + + HRESULT STDMETHODCALLTYPE UpdateTileMappings( + ID3D11Resource* pTiledResource, + UINT NumTiledResourceRegions, + const D3D11_TILED_RESOURCE_COORDINATE* pTiledResourceRegionStartCoordinates, + const D3D11_TILE_REGION_SIZE* pTiledResourceRegionSizes, + ID3D11Buffer* pTilePool, + UINT NumRanges, + const UINT* pRangeFlags, + const UINT* pTilePoolStartOffsets, + const UINT* pRangeTileCounts, + UINT Flags); + + void STDMETHODCALLTYPE UpdateTiles( + ID3D11Resource* pDestTiledResource, + const D3D11_TILED_RESOURCE_COORDINATE* pDestTileRegionStartCoordinate, + const D3D11_TILE_REGION_SIZE* pDestTileRegionSize, + const void* pSourceTileData, + UINT Flags); + + void STDMETHODCALLTYPE SetResourceMinLOD( + ID3D11Resource* pResource, + FLOAT MinLOD); + + FLOAT STDMETHODCALLTYPE GetResourceMinLOD( + ID3D11Resource* pResource); + + void STDMETHODCALLTYPE ResolveSubresource( + ID3D11Resource* pDstResource, + UINT DstSubresource, + ID3D11Resource* pSrcResource, + UINT SrcSubresource, + DXGI_FORMAT Format); + + void STDMETHODCALLTYPE DrawAuto(); + + void STDMETHODCALLTYPE Draw( + UINT VertexCount, + UINT StartVertexLocation); + + void STDMETHODCALLTYPE DrawIndexed( + UINT IndexCount, + UINT StartIndexLocation, + INT BaseVertexLocation); + + void STDMETHODCALLTYPE DrawInstanced( + UINT VertexCountPerInstance, + UINT InstanceCount, + UINT StartVertexLocation, + UINT StartInstanceLocation); + + void STDMETHODCALLTYPE DrawIndexedInstanced( + UINT IndexCountPerInstance, + UINT InstanceCount, + UINT StartIndexLocation, + INT BaseVertexLocation, + UINT StartInstanceLocation); + + void STDMETHODCALLTYPE DrawIndexedInstancedIndirect( + ID3D11Buffer* pBufferForArgs, + UINT AlignedByteOffsetForArgs); + + void STDMETHODCALLTYPE DrawInstancedIndirect( + ID3D11Buffer* pBufferForArgs, + UINT AlignedByteOffsetForArgs); + + void STDMETHODCALLTYPE Dispatch( + UINT ThreadGroupCountX, + UINT ThreadGroupCountY, + UINT ThreadGroupCountZ); + + void STDMETHODCALLTYPE DispatchIndirect( + ID3D11Buffer* pBufferForArgs, + UINT AlignedByteOffsetForArgs); + + void STDMETHODCALLTYPE IASetInputLayout( + ID3D11InputLayout* pInputLayout); + + void STDMETHODCALLTYPE IASetPrimitiveTopology( + D3D11_PRIMITIVE_TOPOLOGY Topology); + + void STDMETHODCALLTYPE IASetVertexBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer* const* ppVertexBuffers, + const UINT* pStrides, + const UINT* pOffsets); + + void STDMETHODCALLTYPE IASetIndexBuffer( + ID3D11Buffer* pIndexBuffer, + DXGI_FORMAT Format, + UINT Offset); + + void STDMETHODCALLTYPE IAGetInputLayout( + ID3D11InputLayout** ppInputLayout); + + void STDMETHODCALLTYPE IAGetPrimitiveTopology( + D3D11_PRIMITIVE_TOPOLOGY* pTopology); + + void STDMETHODCALLTYPE IAGetVertexBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer** ppVertexBuffers, + UINT* pStrides, + UINT* pOffsets); + + void STDMETHODCALLTYPE IAGetIndexBuffer( + ID3D11Buffer** ppIndexBuffer, + DXGI_FORMAT* pFormat, + UINT* pOffset); + + void STDMETHODCALLTYPE VSSetShader( + ID3D11VertexShader* pVertexShader, + ID3D11ClassInstance* const* ppClassInstances, + UINT NumClassInstances); + + void STDMETHODCALLTYPE VSSetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer* const* ppConstantBuffers); + + void STDMETHODCALLTYPE VSSetConstantBuffers1( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer* const* ppConstantBuffers, + const UINT* pFirstConstant, + const UINT* pNumConstants); + + void STDMETHODCALLTYPE VSSetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D11ShaderResourceView* const* ppShaderResourceViews); + + void STDMETHODCALLTYPE VSSetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D11SamplerState* const* ppSamplers); + + void STDMETHODCALLTYPE VSGetShader( + ID3D11VertexShader** ppVertexShader, + ID3D11ClassInstance** ppClassInstances, + UINT* pNumClassInstances); + + void STDMETHODCALLTYPE VSGetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer** ppConstantBuffers); + + void STDMETHODCALLTYPE VSGetConstantBuffers1( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer** ppConstantBuffers, + UINT* pFirstConstant, + UINT* pNumConstants); + + void STDMETHODCALLTYPE VSGetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D11ShaderResourceView** ppShaderResourceViews); + + void STDMETHODCALLTYPE VSGetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D11SamplerState** ppSamplers); + + void STDMETHODCALLTYPE HSSetShader( + ID3D11HullShader* pHullShader, + ID3D11ClassInstance* const* ppClassInstances, + UINT NumClassInstances); + + void STDMETHODCALLTYPE HSSetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D11ShaderResourceView* const* ppShaderResourceViews); + + void STDMETHODCALLTYPE HSSetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer* const* ppConstantBuffers); + + void STDMETHODCALLTYPE HSSetConstantBuffers1( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer* const* ppConstantBuffers, + const UINT* pFirstConstant, + const UINT* pNumConstants); + + void STDMETHODCALLTYPE HSSetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D11SamplerState* const* ppSamplers); + + void STDMETHODCALLTYPE HSGetShader( + ID3D11HullShader** ppHullShader, + ID3D11ClassInstance** ppClassInstances, + UINT* pNumClassInstances); + + void STDMETHODCALLTYPE HSGetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer** ppConstantBuffers); + + void STDMETHODCALLTYPE HSGetConstantBuffers1( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer** ppConstantBuffers, + UINT* pFirstConstant, + UINT* pNumConstants); + + void STDMETHODCALLTYPE HSGetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D11ShaderResourceView** ppShaderResourceViews); + + void STDMETHODCALLTYPE HSGetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D11SamplerState** ppSamplers); + + void STDMETHODCALLTYPE DSSetShader( + ID3D11DomainShader* pDomainShader, + ID3D11ClassInstance* const* ppClassInstances, + UINT NumClassInstances); + + void STDMETHODCALLTYPE DSSetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D11ShaderResourceView* const* ppShaderResourceViews); + + void STDMETHODCALLTYPE DSSetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer* const* ppConstantBuffers); + + void STDMETHODCALLTYPE DSSetConstantBuffers1( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer* const* ppConstantBuffers, + const UINT* pFirstConstant, + const UINT* pNumConstants); + + void STDMETHODCALLTYPE DSSetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D11SamplerState* const* ppSamplers); + + void STDMETHODCALLTYPE DSGetShader( + ID3D11DomainShader** ppDomainShader, + ID3D11ClassInstance** ppClassInstances, + UINT* pNumClassInstances); + + void STDMETHODCALLTYPE DSGetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer** ppConstantBuffers); + + void STDMETHODCALLTYPE DSGetConstantBuffers1( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer** ppConstantBuffers, + UINT* pFirstConstant, + UINT* pNumConstants); + + void STDMETHODCALLTYPE DSGetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D11ShaderResourceView** ppShaderResourceViews); + + void STDMETHODCALLTYPE DSGetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D11SamplerState** ppSamplers); + + void STDMETHODCALLTYPE GSSetShader( + ID3D11GeometryShader* pShader, + ID3D11ClassInstance* const* ppClassInstances, + UINT NumClassInstances); + + void STDMETHODCALLTYPE GSSetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer* const* ppConstantBuffers); + + void STDMETHODCALLTYPE GSSetConstantBuffers1( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer* const* ppConstantBuffers, + const UINT* pFirstConstant, + const UINT* pNumConstants); + + void STDMETHODCALLTYPE GSSetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D11ShaderResourceView* const* ppShaderResourceViews); + + void STDMETHODCALLTYPE GSSetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D11SamplerState* const* ppSamplers); + + void STDMETHODCALLTYPE GSGetShader( + ID3D11GeometryShader** ppGeometryShader, + ID3D11ClassInstance** ppClassInstances, + UINT* pNumClassInstances); + + void STDMETHODCALLTYPE GSGetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer** ppConstantBuffers); + + void STDMETHODCALLTYPE GSGetConstantBuffers1( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer** ppConstantBuffers, + UINT* pFirstConstant, + UINT* pNumConstants); + + void STDMETHODCALLTYPE GSGetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D11ShaderResourceView** ppShaderResourceViews); + + void STDMETHODCALLTYPE GSGetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D11SamplerState** ppSamplers); + + void STDMETHODCALLTYPE PSSetShader( + ID3D11PixelShader* pPixelShader, + ID3D11ClassInstance* const* ppClassInstances, + UINT NumClassInstances); + + void STDMETHODCALLTYPE PSSetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer* const* ppConstantBuffers); + + void STDMETHODCALLTYPE PSSetConstantBuffers1( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer* const* ppConstantBuffers, + const UINT* pFirstConstant, + const UINT* pNumConstants); + + void STDMETHODCALLTYPE PSSetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D11ShaderResourceView* const* ppShaderResourceViews); + + void STDMETHODCALLTYPE PSSetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D11SamplerState* const* ppSamplers); + + void STDMETHODCALLTYPE PSGetShader( + ID3D11PixelShader** ppPixelShader, + ID3D11ClassInstance** ppClassInstances, + UINT* pNumClassInstances); + + void STDMETHODCALLTYPE PSGetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer** ppConstantBuffers); + + void STDMETHODCALLTYPE PSGetConstantBuffers1( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer** ppConstantBuffers, + UINT* pFirstConstant, + UINT* pNumConstants); + + void STDMETHODCALLTYPE PSGetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D11ShaderResourceView** ppShaderResourceViews); + + void STDMETHODCALLTYPE PSGetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D11SamplerState** ppSamplers); + + void STDMETHODCALLTYPE CSSetShader( + ID3D11ComputeShader* pComputeShader, + ID3D11ClassInstance* const* ppClassInstances, + UINT NumClassInstances); + + void STDMETHODCALLTYPE CSSetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer* const* ppConstantBuffers); + + void STDMETHODCALLTYPE CSSetConstantBuffers1( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer* const* ppConstantBuffers, + const UINT* pFirstConstant, + const UINT* pNumConstants); + + void STDMETHODCALLTYPE CSSetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D11ShaderResourceView* const* ppShaderResourceViews); + + void STDMETHODCALLTYPE CSSetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D11SamplerState* const* ppSamplers); + + void STDMETHODCALLTYPE CSSetUnorderedAccessViews( + UINT StartSlot, + UINT NumUAVs, + ID3D11UnorderedAccessView* const* ppUnorderedAccessViews, + const UINT* pUAVInitialCounts); + + void STDMETHODCALLTYPE CSGetShader( + ID3D11ComputeShader** ppComputeShader, + ID3D11ClassInstance** ppClassInstances, + UINT* pNumClassInstances); + + void STDMETHODCALLTYPE CSGetConstantBuffers( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer** ppConstantBuffers); + + void STDMETHODCALLTYPE CSGetConstantBuffers1( + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer** ppConstantBuffers, + UINT* pFirstConstant, + UINT* pNumConstants); + + void STDMETHODCALLTYPE CSGetShaderResources( + UINT StartSlot, + UINT NumViews, + ID3D11ShaderResourceView** ppShaderResourceViews); + + void STDMETHODCALLTYPE CSGetSamplers( + UINT StartSlot, + UINT NumSamplers, + ID3D11SamplerState** ppSamplers); + + void STDMETHODCALLTYPE CSGetUnorderedAccessViews( + UINT StartSlot, + UINT NumUAVs, + ID3D11UnorderedAccessView** ppUnorderedAccessViews); + + void STDMETHODCALLTYPE OMSetRenderTargets( + UINT NumViews, + ID3D11RenderTargetView* const* ppRenderTargetViews, + ID3D11DepthStencilView* pDepthStencilView); + + void STDMETHODCALLTYPE OMSetRenderTargetsAndUnorderedAccessViews( + UINT NumRTVs, + ID3D11RenderTargetView* const* ppRenderTargetViews, + ID3D11DepthStencilView* pDepthStencilView, + UINT UAVStartSlot, + UINT NumUAVs, + ID3D11UnorderedAccessView* const* ppUnorderedAccessViews, + const UINT* pUAVInitialCounts); + + void STDMETHODCALLTYPE OMSetBlendState( + ID3D11BlendState* pBlendState, + const FLOAT BlendFactor[4], + UINT SampleMask); + + void STDMETHODCALLTYPE OMSetDepthStencilState( + ID3D11DepthStencilState* pDepthStencilState, + UINT StencilRef); + + void STDMETHODCALLTYPE OMGetRenderTargets( + UINT NumViews, + ID3D11RenderTargetView** ppRenderTargetViews, + ID3D11DepthStencilView** ppDepthStencilView); + + void STDMETHODCALLTYPE OMGetRenderTargetsAndUnorderedAccessViews( + UINT NumRTVs, + ID3D11RenderTargetView** ppRenderTargetViews, + ID3D11DepthStencilView** ppDepthStencilView, + UINT UAVStartSlot, + UINT NumUAVs, + ID3D11UnorderedAccessView** ppUnorderedAccessViews); + + void STDMETHODCALLTYPE OMGetBlendState( + ID3D11BlendState** ppBlendState, + FLOAT BlendFactor[4], + UINT* pSampleMask); + + void STDMETHODCALLTYPE OMGetDepthStencilState( + ID3D11DepthStencilState** ppDepthStencilState, + UINT* pStencilRef); + + void STDMETHODCALLTYPE RSSetState( + ID3D11RasterizerState* pRasterizerState); + + void STDMETHODCALLTYPE RSSetViewports( + UINT NumViewports, + const D3D11_VIEWPORT* pViewports); + + void STDMETHODCALLTYPE RSSetScissorRects( + UINT NumRects, + const D3D11_RECT* pRects); + + void STDMETHODCALLTYPE RSGetState( + ID3D11RasterizerState** ppRasterizerState); + + void STDMETHODCALLTYPE RSGetViewports( + UINT* pNumViewports, + D3D11_VIEWPORT* pViewports); + + void STDMETHODCALLTYPE RSGetScissorRects( + UINT* pNumRects, + D3D11_RECT* pRects); + + void STDMETHODCALLTYPE SOSetTargets( + UINT NumBuffers, + ID3D11Buffer* const* ppSOTargets, + const UINT* pOffsets); + + void STDMETHODCALLTYPE SOGetTargets( + UINT NumBuffers, + ID3D11Buffer** ppSOTargets); + + void STDMETHODCALLTYPE SOGetTargetsWithOffsets( + UINT NumBuffers, + ID3D11Buffer** ppSOTargets, + UINT* pOffsets); + + BOOL STDMETHODCALLTYPE IsAnnotationEnabled(); + + void STDMETHODCALLTYPE SetMarkerInt( + LPCWSTR pLabel, + INT Data); + + void STDMETHODCALLTYPE BeginEventInt( + LPCWSTR pLabel, + INT Data); + + void STDMETHODCALLTYPE EndEvent(); + + void STDMETHODCALLTYPE GetHardwareProtectionState( + BOOL* pHwProtectionEnable); + + void STDMETHODCALLTYPE SetHardwareProtectionState( + BOOL HwProtectionEnable); + + void STDMETHODCALLTYPE TransitionSurfaceLayout( + IDXGIVkInteropSurface* pSurface, + const VkImageSubresourceRange* pSubresources, + VkImageLayout OldLayout, + VkImageLayout NewLayout); + + D3D10DeviceLock LockContext() { + return m_multithread.AcquireLock(); + } + + protected: + + D3D11DeviceContextExt m_contextExt; + D3D10Multithread m_multithread; + + Rc m_device; + Rc m_updateBuffer; + + DxvkStagingBuffer m_staging; + + //has to be declared after m_device, as compiler initialize in order of declaration in the class + D3D11UserDefinedAnnotation m_annotation; + + DxvkCsChunkFlags m_csFlags; + DxvkCsChunkRef m_csChunk; + + D3D11ContextState m_state; + D3D11CmdData* m_cmdData; + + void ApplyInputLayout(); + + void ApplyPrimitiveTopology(); + + void ApplyBlendState(); + + void ApplyBlendFactor(); + + void ApplyDepthStencilState(); + + void ApplyStencilRef(); + + void ApplyRasterizerState(); + + void ApplyViewportState(); + + template + void BindShader( + const D3D11CommonShader* pShaderModule); + + void BindFramebuffer(); + + void BindDrawBuffers( + D3D11Buffer* pBufferForArgs, + D3D11Buffer* pBufferForCount); + + void BindVertexBuffer( + UINT Slot, + D3D11Buffer* pBuffer, + UINT Offset, + UINT Stride); + + void BindIndexBuffer( + D3D11Buffer* pBuffer, + UINT Offset, + DXGI_FORMAT Format); + + void BindXfbBuffer( + UINT Slot, + D3D11Buffer* pBuffer, + UINT Offset); + + void BindConstantBuffer( + UINT Slot, + D3D11Buffer* pBuffer, + UINT Offset, + UINT Length); + + void BindSampler( + UINT Slot, + D3D11SamplerState* pSampler); + + void BindShaderResource( + UINT Slot, + D3D11ShaderResourceView* pResource); + + void BindUnorderedAccessView( + UINT UavSlot, + D3D11UnorderedAccessView* pUav, + UINT CtrSlot, + UINT Counter); + + void CopyBuffer( + D3D11Buffer* pDstBuffer, + VkDeviceSize DstOffset, + D3D11Buffer* pSrcBuffer, + VkDeviceSize SrcOffset, + VkDeviceSize ByteCount); + + void CopyImage( + D3D11CommonTexture* pDstTexture, + const VkImageSubresourceLayers* pDstLayers, + VkOffset3D DstOffset, + D3D11CommonTexture* pSrcTexture, + const VkImageSubresourceLayers* pSrcLayers, + VkOffset3D SrcOffset, + VkExtent3D SrcExtent); + + void DiscardBuffer( + ID3D11Resource* pResource); + + void DiscardTexture( + ID3D11Resource* pResource, + UINT Subresource); + + template + static void UpdateResource( + ContextType* pContext, + ID3D11Resource* pDstResource, + UINT DstSubresource, + const D3D11_BOX* pDstBox, + const void* pSrcData, + UINT SrcRowPitch, + UINT SrcDepthPitch, + UINT CopyFlags) { + D3D10DeviceLock lock = pContext->LockContext(); + + if (!pDstResource) + return; + + // We need a different code path for buffers + D3D11_RESOURCE_DIMENSION resourceType; + pDstResource->GetType(&resourceType); + + if (likely(resourceType == D3D11_RESOURCE_DIMENSION_BUFFER)) { + const auto bufferResource = static_cast(pDstResource); + uint64_t bufferSize = bufferResource->Desc()->ByteWidth; + + // Provide a fast path for mapped buffer updates since some + // games use UpdateSubresource to update constant buffers. + if (likely(bufferResource->GetMapMode() == D3D11_COMMON_BUFFER_MAP_MODE_DIRECT) && likely(!pDstBox)) { + pContext->UpdateMappedBuffer(bufferResource, 0, bufferSize, pSrcData, 0); + return; + } + + // Validate buffer range to update + uint64_t offset = 0; + uint64_t length = bufferSize; + + if (pDstBox) { + offset = pDstBox->left; + length = pDstBox->right - offset; + } + + if (unlikely(offset + length > bufferSize)) + return; + + // Still try to be fast if a box is provided but we update the full buffer + if (likely(bufferResource->GetMapMode() == D3D11_COMMON_BUFFER_MAP_MODE_DIRECT)) { + CopyFlags &= D3D11_COPY_DISCARD | D3D11_COPY_NO_OVERWRITE; + + if (likely(length == bufferSize) || unlikely(CopyFlags != 0)) { + pContext->UpdateMappedBuffer(bufferResource, offset, length, pSrcData, CopyFlags); + return; + } + } + + // Otherwise we can't really do anything fancy, so just do a GPU copy + pContext->UpdateBuffer(bufferResource, offset, length, pSrcData); + } else { + D3D11CommonTexture* textureResource = GetCommonTexture(pDstResource); + + pContext->UpdateTexture(textureResource, + DstSubresource, pDstBox, pSrcData, SrcRowPitch, SrcDepthPitch); + } + } + + void UpdateBuffer( + D3D11Buffer* pDstBuffer, + UINT Offset, + UINT Length, + const void* pSrcData); + + void UpdateTexture( + D3D11CommonTexture* pDstTexture, + UINT DstSubresource, + const D3D11_BOX* pDstBox, + const void* pSrcData, + UINT SrcRowPitch, + UINT SrcDepthPitch); + + void UpdateImage( + D3D11CommonTexture* pDstTexture, + const VkImageSubresource* pDstSubresource, + VkOffset3D DstOffset, + VkExtent3D DstExtent, + DxvkBufferSlice StagingBuffer); + + void SetDrawBuffers( + ID3D11Buffer* pBufferForArgs, + ID3D11Buffer* pBufferForCount); + + template + void SetConstantBuffers( + D3D11ConstantBufferBindings& Bindings, + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer* const* ppConstantBuffers); + + template + void SetConstantBuffers1( + D3D11ConstantBufferBindings& Bindings, + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer* const* ppConstantBuffers, + const UINT* pFirstConstant, + const UINT* pNumConstants); + + template + void SetSamplers( + D3D11SamplerBindings& Bindings, + UINT StartSlot, + UINT NumSamplers, + ID3D11SamplerState* const* ppSamplers); + + template + void SetShaderResources( + D3D11ShaderResourceBindings& Bindings, + UINT StartSlot, + UINT NumResources, + ID3D11ShaderResourceView* const* ppResources); + + void GetConstantBuffers( + const D3D11ConstantBufferBindings& Bindings, + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer** ppConstantBuffers, + UINT* pFirstConstant, + UINT* pNumConstants); + + void GetShaderResources( + const D3D11ShaderResourceBindings& Bindings, + UINT StartSlot, + UINT NumViews, + ID3D11ShaderResourceView** ppShaderResourceViews); + + void GetSamplers( + const D3D11SamplerBindings& Bindings, + UINT StartSlot, + UINT NumSamplers, + ID3D11SamplerState** ppSamplers); + + void ResetState(); + + void RestoreState(); + + template + void RestoreConstantBuffers( + D3D11ConstantBufferBindings& Bindings); + + template + void RestoreSamplers( + D3D11SamplerBindings& Bindings); + + template + void RestoreShaderResources( + D3D11ShaderResourceBindings& Bindings); + + template + void RestoreUnorderedAccessViews( + D3D11UnorderedAccessBindings& Bindings); + + bool TestRtvUavHazards( + UINT NumRTVs, + ID3D11RenderTargetView* const* ppRTVs, + UINT NumUAVs, + ID3D11UnorderedAccessView* const* ppUAVs); + + template + bool TestSrvHazards( + D3D11ShaderResourceView* pView); + + template + void ResolveSrvHazards( + T* pView, + D3D11ShaderResourceBindings& Bindings); + + template + void ResolveCsSrvHazards( + T* pView); + + template + void ResolveOmSrvHazards( + T* pView); + + bool ResolveOmRtvHazards( + D3D11UnorderedAccessView* pView); + + void ResolveOmUavHazards( + D3D11RenderTargetView* pView); + + bool ValidateRenderTargets( + UINT NumViews, + ID3D11RenderTargetView* const* ppRenderTargetViews, + ID3D11DepthStencilView* pDepthStencilView); + + VkClearValue ConvertColorValue( + const FLOAT Color[4], + const DxvkFormatInfo* pFormatInfo); + + DxvkDataSlice AllocUpdateBufferSlice(size_t Size); + + DxvkBufferSlice AllocStagingBuffer( + VkDeviceSize Size); + + void ResetStagingBuffer(); + + DxvkCsChunkRef AllocCsChunk(); + + static void InitDefaultPrimitiveTopology( + DxvkInputAssemblyState* pIaState); + + static void InitDefaultRasterizerState( + DxvkRasterizerState* pRsState); + + static void InitDefaultDepthStencilState( + DxvkDepthStencilState* pDsState); + + static void InitDefaultBlendState( + DxvkBlendMode* pCbState, + DxvkLogicOpState* pLoState, + DxvkMultisampleState* pMsState, + UINT SampleMask); + + template + const D3D11CommonShader* GetCommonShader(T* pShader) const { + return pShader != nullptr ? pShader->GetCommonShader() : nullptr; + } + + static uint32_t GetIndirectCommandStride(const D3D11CmdDrawIndirectData* cmdData, uint32_t offset, uint32_t minStride) { + if (likely(cmdData->stride)) + return cmdData->offset + cmdData->count * cmdData->stride == offset ? cmdData->stride : 0; + + uint32_t stride = offset - cmdData->offset; + return stride >= minStride && stride <= 32 ? stride : 0; + } + + static bool ValidateDrawBufferSize(ID3D11Buffer* pBuffer, UINT Offset, UINT Size) { + UINT bufferSize = 0; + + if (likely(pBuffer != nullptr)) + bufferSize = static_cast(pBuffer)->Desc()->ByteWidth; + + return bufferSize >= Offset + Size; + } + + template + void EmitCs(Cmd&& command) { + m_cmdData = nullptr; + + if (unlikely(!m_csChunk->push(command))) { + EmitCsChunk(std::move(m_csChunk)); + + m_csChunk = AllocCsChunk(); + m_csChunk->push(command); + } + } + + template + M* EmitCsCmd(Cmd&& command, Args&&... args) { + M* data = m_csChunk->pushCmd( + command, std::forward(args)...); + + if (unlikely(!data)) { + EmitCsChunk(std::move(m_csChunk)); + + m_csChunk = AllocCsChunk(); + data = m_csChunk->pushCmd( + command, std::forward(args)...); + } + + m_cmdData = data; + return data; + } + + void FlushCsChunk() { + if (likely(!m_csChunk->empty())) { + EmitCsChunk(std::move(m_csChunk)); + m_csChunk = AllocCsChunk(); + m_cmdData = nullptr; + } + } + + void TrackResourceSequenceNumber( + ID3D11Resource* pResource); + + virtual void EmitCsChunk(DxvkCsChunkRef&& chunk) = 0; + + virtual void TrackTextureSequenceNumber( + D3D11CommonTexture* pResource, + UINT Subresource) = 0; + + virtual void TrackBufferSequenceNumber( + D3D11Buffer* pResource) = 0; + + }; + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_context_def.cpp b/utils/dxvk-1.10.3/src/d3d11/d3d11_context_def.cpp new file mode 100644 index 00000000000..552cfcc8152 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_context_def.cpp @@ -0,0 +1,461 @@ +#include "d3d11_context_def.h" +#include "d3d11_device.h" + +namespace dxvk { + + D3D11DeferredContext::D3D11DeferredContext( + D3D11Device* pParent, + const Rc& Device, + UINT ContextFlags) + : D3D11DeviceContext(pParent, Device, GetCsChunkFlags(pParent)), + m_contextFlags(ContextFlags), + m_commandList (CreateCommandList()) { + ClearState(); + } + + + D3D11_DEVICE_CONTEXT_TYPE STDMETHODCALLTYPE D3D11DeferredContext::GetType() { + return D3D11_DEVICE_CONTEXT_DEFERRED; + } + + + UINT STDMETHODCALLTYPE D3D11DeferredContext::GetContextFlags() { + return m_contextFlags; + } + + + HRESULT STDMETHODCALLTYPE D3D11DeferredContext::GetData( + ID3D11Asynchronous* pAsync, + void* pData, + UINT DataSize, + UINT GetDataFlags) { + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::warn("D3D11: GetData called on a deferred context"); + + return DXGI_ERROR_INVALID_CALL; + } + + + void STDMETHODCALLTYPE D3D11DeferredContext::Begin( + ID3D11Asynchronous* pAsync) { + D3D10DeviceLock lock = LockContext(); + + if (unlikely(!pAsync)) + return; + + Com query(static_cast(pAsync)); + + if (unlikely(!query->IsScoped())) + return; + + auto entry = std::find( + m_queriesBegun.begin(), + m_queriesBegun.end(), query); + + if (unlikely(entry != m_queriesBegun.end())) + return; + + EmitCs([cQuery = query] + (DxvkContext* ctx) { + cQuery->Begin(ctx); + }); + + m_queriesBegun.push_back(std::move(query)); + } + + + void STDMETHODCALLTYPE D3D11DeferredContext::End( + ID3D11Asynchronous* pAsync) { + D3D10DeviceLock lock = LockContext(); + + if (unlikely(!pAsync)) + return; + + Com query(static_cast(pAsync)); + + if (query->IsScoped()) { + auto entry = std::find( + m_queriesBegun.begin(), + m_queriesBegun.end(), query); + + if (likely(entry != m_queriesBegun.end())) { + m_queriesBegun.erase(entry); + } else { + EmitCs([cQuery = query] + (DxvkContext* ctx) { + cQuery->Begin(ctx); + }); + } + } + + m_commandList->AddQuery(query.ptr()); + + EmitCs([cQuery = std::move(query)] + (DxvkContext* ctx) { + cQuery->End(ctx); + }); + } + + + void STDMETHODCALLTYPE D3D11DeferredContext::Flush() { + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::warn("D3D11: Flush called on a deferred context"); + } + + + void STDMETHODCALLTYPE D3D11DeferredContext::Flush1( + D3D11_CONTEXT_TYPE ContextType, + HANDLE hEvent) { + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::warn("D3D11: Flush1 called on a deferred context"); + } + + + HRESULT STDMETHODCALLTYPE D3D11DeferredContext::Signal( + ID3D11Fence* pFence, + UINT64 Value) { + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::warn("D3D11: Signal called on a deferred context"); + + return DXGI_ERROR_INVALID_CALL; + } + + + HRESULT STDMETHODCALLTYPE D3D11DeferredContext::Wait( + ID3D11Fence* pFence, + UINT64 Value) { + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::warn("D3D11: Wait called on a deferred context"); + + return DXGI_ERROR_INVALID_CALL; + } + + + void STDMETHODCALLTYPE D3D11DeferredContext::ExecuteCommandList( + ID3D11CommandList* pCommandList, + BOOL RestoreContextState) { + D3D10DeviceLock lock = LockContext(); + + FlushCsChunk(); + + static_cast(pCommandList)->EmitToCommandList(m_commandList.ptr()); + + if (RestoreContextState) + RestoreState(); + else + ClearState(); + } + + + HRESULT STDMETHODCALLTYPE D3D11DeferredContext::FinishCommandList( + BOOL RestoreDeferredContextState, + ID3D11CommandList **ppCommandList) { + D3D10DeviceLock lock = LockContext(); + + FinalizeQueries(); + FlushCsChunk(); + + if (ppCommandList != nullptr) + *ppCommandList = m_commandList.ref(); + m_commandList = CreateCommandList(); + + if (RestoreDeferredContextState) + RestoreState(); + else + ClearState(); + + m_mappedResources.clear(); + ResetStagingBuffer(); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11DeferredContext::Map( + ID3D11Resource* pResource, + UINT Subresource, + D3D11_MAP MapType, + UINT MapFlags, + D3D11_MAPPED_SUBRESOURCE* pMappedResource) { + D3D10DeviceLock lock = LockContext(); + + if (unlikely(!pResource || !pMappedResource)) + return E_INVALIDARG; + + if (MapType == D3D11_MAP_WRITE_DISCARD) { + D3D11_RESOURCE_DIMENSION resourceDim; + pResource->GetType(&resourceDim); + + D3D11_MAPPED_SUBRESOURCE mapInfo; + HRESULT status = resourceDim == D3D11_RESOURCE_DIMENSION_BUFFER + ? MapBuffer(pResource, &mapInfo) + : MapImage (pResource, Subresource, &mapInfo); + + if (unlikely(FAILED(status))) { + *pMappedResource = D3D11_MAPPED_SUBRESOURCE(); + return status; + } + + AddMapEntry(pResource, Subresource, resourceDim, mapInfo); + *pMappedResource = mapInfo; + return S_OK; + } else if (MapType == D3D11_MAP_WRITE_NO_OVERWRITE) { + // The resource must be mapped with D3D11_MAP_WRITE_DISCARD + // before it can be mapped with D3D11_MAP_WRITE_NO_OVERWRITE. + auto entry = FindMapEntry(pResource, Subresource); + + if (unlikely(!entry)) { + *pMappedResource = D3D11_MAPPED_SUBRESOURCE(); + return E_INVALIDARG; + } + + // Return same memory region as earlier + *pMappedResource = entry->MapInfo; + return S_OK; + } else { + // Not allowed on deferred contexts + *pMappedResource = D3D11_MAPPED_SUBRESOURCE(); + return E_INVALIDARG; + } + } + + + void STDMETHODCALLTYPE D3D11DeferredContext::Unmap( + ID3D11Resource* pResource, + UINT Subresource) { + // No-op, updates are committed in Map + } + + + void STDMETHODCALLTYPE D3D11DeferredContext::UpdateSubresource( + ID3D11Resource* pDstResource, + UINT DstSubresource, + const D3D11_BOX* pDstBox, + const void* pSrcData, + UINT SrcRowPitch, + UINT SrcDepthPitch) { + UpdateResource(this, pDstResource, + DstSubresource, pDstBox, pSrcData, SrcRowPitch, SrcDepthPitch, 0); + } + + + void STDMETHODCALLTYPE D3D11DeferredContext::UpdateSubresource1( + ID3D11Resource* pDstResource, + UINT DstSubresource, + const D3D11_BOX* pDstBox, + const void* pSrcData, + UINT SrcRowPitch, + UINT SrcDepthPitch, + UINT CopyFlags) { + UpdateResource(this, pDstResource, + DstSubresource, pDstBox, pSrcData, SrcRowPitch, SrcDepthPitch, CopyFlags); + } + + + void STDMETHODCALLTYPE D3D11DeferredContext::SwapDeviceContextState( + ID3DDeviceContextState* pState, + ID3DDeviceContextState** ppPreviousState) { + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::warn("D3D11: SwapDeviceContextState called on a deferred context"); + } + + + HRESULT D3D11DeferredContext::MapBuffer( + ID3D11Resource* pResource, + D3D11_MAPPED_SUBRESOURCE* pMappedResource) { + D3D11Buffer* pBuffer = static_cast(pResource); + + if (unlikely(pBuffer->GetMapMode() == D3D11_COMMON_BUFFER_MAP_MODE_NONE)) { + Logger::err("D3D11: Cannot map a device-local buffer"); + return E_INVALIDARG; + } + + pMappedResource->RowPitch = pBuffer->Desc()->ByteWidth; + pMappedResource->DepthPitch = pBuffer->Desc()->ByteWidth; + + if (likely(m_csFlags.test(DxvkCsChunkFlag::SingleUse))) { + // For resources that cannot be written by the GPU, + // we may write to the buffer resource directly and + // just swap in the buffer slice as needed. + auto bufferSlice = pBuffer->AllocSlice(); + pMappedResource->pData = bufferSlice.mapPtr; + + EmitCs([ + cDstBuffer = pBuffer->GetBuffer(), + cPhysSlice = bufferSlice + ] (DxvkContext* ctx) { + ctx->invalidateBuffer(cDstBuffer, cPhysSlice); + }); + } else { + // For GPU-writable resources, we need a data slice + // to perform the update operation at execution time. + auto dataSlice = AllocUpdateBufferSlice(pBuffer->Desc()->ByteWidth); + pMappedResource->pData = dataSlice.ptr(); + + EmitCs([ + cDstBuffer = pBuffer->GetBuffer(), + cDataSlice = dataSlice + ] (DxvkContext* ctx) { + DxvkBufferSliceHandle slice = cDstBuffer->allocSlice(); + std::memcpy(slice.mapPtr, cDataSlice.ptr(), cDataSlice.length()); + ctx->invalidateBuffer(cDstBuffer, slice); + }); + } + + return S_OK; + } + + + HRESULT D3D11DeferredContext::MapImage( + ID3D11Resource* pResource, + UINT Subresource, + D3D11_MAPPED_SUBRESOURCE* pMappedResource) { + D3D11CommonTexture* pTexture = GetCommonTexture(pResource); + + if (unlikely(pTexture->GetMapMode() == D3D11_COMMON_TEXTURE_MAP_MODE_NONE)) { + Logger::err("D3D11: Cannot map a device-local image"); + return E_INVALIDARG; + } + + if (unlikely(Subresource >= pTexture->CountSubresources())) + return E_INVALIDARG; + + VkFormat packedFormat = pTexture->GetPackedFormat(); + + auto formatInfo = imageFormatInfo(packedFormat); + auto subresource = pTexture->GetSubresourceFromIndex( + formatInfo->aspectMask, Subresource); + + VkExtent3D levelExtent = pTexture->MipLevelExtent(subresource.mipLevel); + + auto layout = pTexture->GetSubresourceLayout(formatInfo->aspectMask, Subresource); + auto dataSlice = AllocStagingBuffer(util::computeImageDataSize(packedFormat, levelExtent)); + + pMappedResource->RowPitch = layout.RowPitch; + pMappedResource->DepthPitch = layout.DepthPitch; + pMappedResource->pData = dataSlice.mapPtr(0); + + UpdateImage(pTexture, &subresource, + VkOffset3D { 0, 0, 0 }, levelExtent, + std::move(dataSlice)); + return S_OK; + } + + + void D3D11DeferredContext::UpdateMappedBuffer( + D3D11Buffer* pDstBuffer, + UINT Offset, + UINT Length, + const void* pSrcData, + UINT CopyFlags) { + void* mapPtr = nullptr; + + if (unlikely(CopyFlags == D3D11_COPY_NO_OVERWRITE)) { + auto entry = FindMapEntry(pDstBuffer, 0); + + if (entry) + mapPtr = entry->MapInfo.pData; + } + + if (likely(!mapPtr)) { + // The caller validates the map mode, so we can + // safely ignore the MapBuffer return value here + D3D11_MAPPED_SUBRESOURCE mapInfo; + MapBuffer(pDstBuffer, &mapInfo); + AddMapEntry(pDstBuffer, 0, D3D11_RESOURCE_DIMENSION_BUFFER, mapInfo); + mapPtr = mapInfo.pData; + } + + std::memcpy(reinterpret_cast(mapPtr) + Offset, pSrcData, Length); + } + + + void D3D11DeferredContext::FinalizeQueries() { + for (auto& query : m_queriesBegun) { + m_commandList->AddQuery(query.ptr()); + + EmitCs([cQuery = std::move(query)] + (DxvkContext* ctx) { + cQuery->End(ctx); + }); + } + + m_queriesBegun.clear(); + } + + + Com D3D11DeferredContext::CreateCommandList() { + return new D3D11CommandList(m_parent, m_contextFlags); + } + + + void D3D11DeferredContext::EmitCsChunk(DxvkCsChunkRef&& chunk) { + m_commandList->AddChunk(std::move(chunk)); + } + + + void D3D11DeferredContext::TrackTextureSequenceNumber( + D3D11CommonTexture* pResource, + UINT Subresource) { + m_commandList->TrackResourceUsage( + pResource->GetInterface(), + pResource->GetDimension(), + Subresource); + } + + + void D3D11DeferredContext::TrackBufferSequenceNumber( + D3D11Buffer* pResource) { + m_commandList->TrackResourceUsage( + pResource, D3D11_RESOURCE_DIMENSION_BUFFER, 0); + } + + + D3D11DeferredContextMapEntry* D3D11DeferredContext::FindMapEntry( + ID3D11Resource* pResource, + UINT Subresource) { + // Recently mapped resources as well as entries with + // up-to-date map infos will be located at the end + // of the resource array, so scan in reverse order. + size_t size = m_mappedResources.size(); + + for (size_t i = 1; i <= size; i++) { + auto entry = &m_mappedResources[size - i]; + + if (entry->Resource.Get() == pResource + && entry->Resource.GetSubresource() == Subresource) + return entry; + } + + return nullptr; + } + + void D3D11DeferredContext::AddMapEntry( + ID3D11Resource* pResource, + UINT Subresource, + D3D11_RESOURCE_DIMENSION ResourceType, + const D3D11_MAPPED_SUBRESOURCE& MapInfo) { + m_mappedResources.emplace_back(pResource, + Subresource, ResourceType, MapInfo); + } + + + DxvkCsChunkFlags D3D11DeferredContext::GetCsChunkFlags( + D3D11Device* pDevice) { + return pDevice->GetOptions()->dcSingleUseMode + ? DxvkCsChunkFlags(DxvkCsChunkFlag::SingleUse) + : DxvkCsChunkFlags(); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_context_def.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_context_def.h new file mode 100644 index 00000000000..c5fe49c9d7d --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_context_def.h @@ -0,0 +1,164 @@ +#pragma once + +#include "d3d11_buffer.h" +#include "d3d11_cmdlist.h" +#include "d3d11_context.h" +#include "d3d11_texture.h" + +#include + +namespace dxvk { + + struct D3D11DeferredContextMapEntry { + D3D11DeferredContextMapEntry() { } + D3D11DeferredContextMapEntry( + ID3D11Resource* pResource, + UINT Subresource, + D3D11_RESOURCE_DIMENSION ResourceType, + const D3D11_MAPPED_SUBRESOURCE& MappedResource) + : Resource(pResource, Subresource, ResourceType), + MapInfo(MappedResource) { } + + D3D11ResourceRef Resource; + D3D11_MAPPED_SUBRESOURCE MapInfo; + }; + + class D3D11DeferredContext : public D3D11DeviceContext { + friend class D3D11DeviceContext; + public: + + D3D11DeferredContext( + D3D11Device* pParent, + const Rc& Device, + UINT ContextFlags); + + D3D11_DEVICE_CONTEXT_TYPE STDMETHODCALLTYPE GetType(); + + UINT STDMETHODCALLTYPE GetContextFlags(); + + HRESULT STDMETHODCALLTYPE GetData( + ID3D11Asynchronous* pAsync, + void* pData, + UINT DataSize, + UINT GetDataFlags); + + void STDMETHODCALLTYPE Begin( + ID3D11Asynchronous* pAsync); + + void STDMETHODCALLTYPE End( + ID3D11Asynchronous* pAsync); + + void STDMETHODCALLTYPE Flush(); + + void STDMETHODCALLTYPE Flush1( + D3D11_CONTEXT_TYPE ContextType, + HANDLE hEvent); + + HRESULT STDMETHODCALLTYPE Signal( + ID3D11Fence* pFence, + UINT64 Value); + + HRESULT STDMETHODCALLTYPE Wait( + ID3D11Fence* pFence, + UINT64 Value); + + void STDMETHODCALLTYPE ExecuteCommandList( + ID3D11CommandList* pCommandList, + BOOL RestoreContextState); + + HRESULT STDMETHODCALLTYPE FinishCommandList( + BOOL RestoreDeferredContextState, + ID3D11CommandList** ppCommandList); + + HRESULT STDMETHODCALLTYPE Map( + ID3D11Resource* pResource, + UINT Subresource, + D3D11_MAP MapType, + UINT MapFlags, + D3D11_MAPPED_SUBRESOURCE* pMappedResource); + + void STDMETHODCALLTYPE Unmap( + ID3D11Resource* pResource, + UINT Subresource); + + void STDMETHODCALLTYPE UpdateSubresource( + ID3D11Resource* pDstResource, + UINT DstSubresource, + const D3D11_BOX* pDstBox, + const void* pSrcData, + UINT SrcRowPitch, + UINT SrcDepthPitch); + + void STDMETHODCALLTYPE UpdateSubresource1( + ID3D11Resource* pDstResource, + UINT DstSubresource, + const D3D11_BOX* pDstBox, + const void* pSrcData, + UINT SrcRowPitch, + UINT SrcDepthPitch, + UINT CopyFlags); + + void STDMETHODCALLTYPE SwapDeviceContextState( + ID3DDeviceContextState* pState, + ID3DDeviceContextState** ppPreviousState); + + private: + + const UINT m_contextFlags; + + // Command list that we're recording + Com m_commandList; + + // Info about currently mapped (sub)resources. Using a vector + // here is reasonable since there will usually only be a small + // number of mapped resources per command list. + std::vector m_mappedResources; + + // Begun and ended queries, will also be stored in command list + std::vector> m_queriesBegun; + + HRESULT MapBuffer( + ID3D11Resource* pResource, + D3D11_MAPPED_SUBRESOURCE* pMappedResource); + + HRESULT MapImage( + ID3D11Resource* pResource, + UINT Subresource, + D3D11_MAPPED_SUBRESOURCE* pMappedResource); + + void UpdateMappedBuffer( + D3D11Buffer* pDstBuffer, + UINT Offset, + UINT Length, + const void* pSrcData, + UINT CopyFlags); + + void FinalizeQueries(); + + Com CreateCommandList(); + + void EmitCsChunk(DxvkCsChunkRef&& chunk); + + void TrackTextureSequenceNumber( + D3D11CommonTexture* pResource, + UINT Subresource); + + void TrackBufferSequenceNumber( + D3D11Buffer* pResource); + + D3D11DeferredContextMapEntry* FindMapEntry( + ID3D11Resource* pResource, + UINT Subresource); + + void AddMapEntry( + ID3D11Resource* pResource, + UINT Subresource, + D3D11_RESOURCE_DIMENSION ResourceType, + const D3D11_MAPPED_SUBRESOURCE& MapInfo); + + static DxvkCsChunkFlags GetCsChunkFlags( + D3D11Device* pDevice); + + }; + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_context_ext.cpp b/utils/dxvk-1.10.3/src/d3d11/d3d11_context_ext.cpp new file mode 100644 index 00000000000..ecd41e832e1 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_context_ext.cpp @@ -0,0 +1,205 @@ +#include +#include +#include + +#include "d3d11_device.h" +#include "d3d11_context.h" +#include "d3d11_cuda.h" + +#include "../util/log/log.h" + +namespace dxvk { + + D3D11DeviceContextExt::D3D11DeviceContextExt( + D3D11DeviceContext* pContext) + : m_ctx(pContext) { + + } + + + ULONG STDMETHODCALLTYPE D3D11DeviceContextExt::AddRef() { + return m_ctx->AddRef(); + } + + + ULONG STDMETHODCALLTYPE D3D11DeviceContextExt::Release() { + return m_ctx->Release(); + } + + + HRESULT STDMETHODCALLTYPE D3D11DeviceContextExt::QueryInterface( + REFIID riid, + void** ppvObject) { + return m_ctx->QueryInterface(riid, ppvObject); + } + + + void STDMETHODCALLTYPE D3D11DeviceContextExt::MultiDrawIndirect( + UINT DrawCount, + ID3D11Buffer* pBufferForArgs, + UINT ByteOffsetForArgs, + UINT ByteStrideForArgs) { + D3D10DeviceLock lock = m_ctx->LockContext(); + m_ctx->SetDrawBuffers(pBufferForArgs, nullptr); + + m_ctx->EmitCs([ + cCount = DrawCount, + cOffset = ByteOffsetForArgs, + cStride = ByteStrideForArgs + ] (DxvkContext* ctx) { + ctx->drawIndirect(cOffset, cCount, cStride); + }); + } + + + void STDMETHODCALLTYPE D3D11DeviceContextExt::MultiDrawIndexedIndirect( + UINT DrawCount, + ID3D11Buffer* pBufferForArgs, + UINT ByteOffsetForArgs, + UINT ByteStrideForArgs) { + D3D10DeviceLock lock = m_ctx->LockContext(); + m_ctx->SetDrawBuffers(pBufferForArgs, nullptr); + + m_ctx->EmitCs([ + cCount = DrawCount, + cOffset = ByteOffsetForArgs, + cStride = ByteStrideForArgs + ] (DxvkContext* ctx) { + ctx->drawIndexedIndirect(cOffset, cCount, cStride); + }); + } + + + void STDMETHODCALLTYPE D3D11DeviceContextExt::MultiDrawIndirectCount( + UINT MaxDrawCount, + ID3D11Buffer* pBufferForCount, + UINT ByteOffsetForCount, + ID3D11Buffer* pBufferForArgs, + UINT ByteOffsetForArgs, + UINT ByteStrideForArgs) { + D3D10DeviceLock lock = m_ctx->LockContext(); + m_ctx->SetDrawBuffers(pBufferForArgs, pBufferForCount); + + m_ctx->EmitCs([ + cMaxCount = MaxDrawCount, + cArgOffset = ByteOffsetForArgs, + cCntOffset = ByteOffsetForCount, + cStride = ByteStrideForArgs + ] (DxvkContext* ctx) { + ctx->drawIndirectCount(cArgOffset, cCntOffset, cMaxCount, cStride); + }); + } + + + void STDMETHODCALLTYPE D3D11DeviceContextExt::MultiDrawIndexedIndirectCount( + UINT MaxDrawCount, + ID3D11Buffer* pBufferForCount, + UINT ByteOffsetForCount, + ID3D11Buffer* pBufferForArgs, + UINT ByteOffsetForArgs, + UINT ByteStrideForArgs) { + D3D10DeviceLock lock = m_ctx->LockContext(); + m_ctx->SetDrawBuffers(pBufferForArgs, pBufferForCount); + + m_ctx->EmitCs([ + cMaxCount = MaxDrawCount, + cArgOffset = ByteOffsetForArgs, + cCntOffset = ByteOffsetForCount, + cStride = ByteStrideForArgs + ] (DxvkContext* ctx) { + ctx->drawIndexedIndirectCount(cArgOffset, cCntOffset, cMaxCount, cStride); + }); + } + + + void STDMETHODCALLTYPE D3D11DeviceContextExt::SetDepthBoundsTest( + BOOL Enable, + FLOAT MinDepthBounds, + FLOAT MaxDepthBounds) { + D3D10DeviceLock lock = m_ctx->LockContext(); + + DxvkDepthBounds db; + db.enableDepthBounds = Enable; + db.minDepthBounds = MinDepthBounds; + db.maxDepthBounds = MaxDepthBounds; + + m_ctx->EmitCs([cDepthBounds = db] (DxvkContext* ctx) { + ctx->setDepthBounds(cDepthBounds); + }); + } + + + void STDMETHODCALLTYPE D3D11DeviceContextExt::SetBarrierControl( + UINT ControlFlags) { + D3D10DeviceLock lock = m_ctx->LockContext(); + DxvkBarrierControlFlags flags; + + if (ControlFlags & D3D11_VK_BARRIER_CONTROL_IGNORE_WRITE_AFTER_WRITE) + flags.set(DxvkBarrierControl::IgnoreWriteAfterWrite); + + if (ControlFlags & D3D11_VK_BARRIER_CONTROL_IGNORE_GRAPHICS_UAV) + flags.set(DxvkBarrierControl::IgnoreGraphicsBarriers); + + m_ctx->EmitCs([cFlags = flags] (DxvkContext* ctx) { + ctx->setBarrierControl(cFlags); + }); + } + + + bool STDMETHODCALLTYPE D3D11DeviceContextExt::LaunchCubinShaderNVX(IUnknown* hShader, uint32_t GridX, uint32_t GridY, uint32_t GridZ, + const void* pParams, uint32_t ParamSize, void* const* pReadResources, uint32_t NumReadResources, void* const* pWriteResources, uint32_t NumWriteResources) { + D3D10DeviceLock lock = m_ctx->LockContext(); + + CubinShaderWrapper* cubinShader = static_cast(hShader); + CubinShaderLaunchInfo launchInfo; + + const uint32_t maxResources = NumReadResources + NumWriteResources; + launchInfo.buffers.reserve(maxResources); + launchInfo.images.reserve(maxResources); + + for (uint32_t i = 0; i < NumReadResources; i++) + launchInfo.insertResource(static_cast(pReadResources[i]), DxvkAccess::Read); + + for (uint32_t i = 0; i < NumWriteResources; i++) + launchInfo.insertResource(static_cast(pWriteResources[i]), DxvkAccess::Write); + + launchInfo.paramSize = ParamSize; + launchInfo.params.resize(launchInfo.paramSize); + std::memcpy(launchInfo.params.data(), pParams, ParamSize); + + launchInfo.cuLaunchConfig[0] = reinterpret_cast(0x01); // CU_LAUNCH_PARAM_BUFFER_POINTER + launchInfo.cuLaunchConfig[1] = launchInfo.params.data(); + launchInfo.cuLaunchConfig[2] = reinterpret_cast(0x02); // CU_LAUNCH_PARAM_BUFFER_SIZE + launchInfo.cuLaunchConfig[3] = &launchInfo.paramSize; // yes, this actually requires a pointer to a size_t containing the parameter size + launchInfo.cuLaunchConfig[4] = reinterpret_cast(0x00); // CU_LAUNCH_PARAM_END + + launchInfo.nvxLaunchInfo.function = cubinShader->cuFunction(); + launchInfo.nvxLaunchInfo.gridDimX = GridX; + launchInfo.nvxLaunchInfo.gridDimY = GridY; + launchInfo.nvxLaunchInfo.gridDimZ = GridZ; + launchInfo.nvxLaunchInfo.blockDimX = cubinShader->blockDim().width; + launchInfo.nvxLaunchInfo.blockDimY = cubinShader->blockDim().height; + launchInfo.nvxLaunchInfo.blockDimZ = cubinShader->blockDim().depth; + launchInfo.nvxLaunchInfo.sharedMemBytes = 0; + launchInfo.nvxLaunchInfo.paramCount = 0; + launchInfo.nvxLaunchInfo.pParams = nullptr; + launchInfo.nvxLaunchInfo.extraCount = 1; + launchInfo.nvxLaunchInfo.pExtras = launchInfo.cuLaunchConfig.data(); + + launchInfo.shader = cubinShader; + + /* Need to capture by value in case this gets called from a deferred context */ + m_ctx->EmitCs([cLaunchInfo = std::move(launchInfo)] (DxvkContext* ctx) { + ctx->launchCuKernelNVX(cLaunchInfo.nvxLaunchInfo, cLaunchInfo.buffers, cLaunchInfo.images); + }); + + // Track resource usage as necessary + for (uint32_t i = 0; i < NumReadResources; i++) + m_ctx->TrackResourceSequenceNumber(static_cast(pReadResources[i])); + + for (uint32_t i = 0; i < NumWriteResources; i++) + m_ctx->TrackResourceSequenceNumber(static_cast(pWriteResources[i])); + + return true; + } +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_context_ext.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_context_ext.h new file mode 100644 index 00000000000..2109a0deaa4 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_context_ext.h @@ -0,0 +1,78 @@ +#pragma once + +#include "d3d11_interfaces.h" + +namespace dxvk { + + class D3D11DeviceContext; + + class D3D11DeviceContextExt : public ID3D11VkExtContext1 { + + public: + + D3D11DeviceContextExt( + D3D11DeviceContext* pContext); + + ULONG STDMETHODCALLTYPE AddRef(); + + ULONG STDMETHODCALLTYPE Release(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + void STDMETHODCALLTYPE MultiDrawIndirect( + UINT DrawCount, + ID3D11Buffer* pBufferForArgs, + UINT ByteOffsetForArgs, + UINT ByteStrideForArgs); + + void STDMETHODCALLTYPE MultiDrawIndexedIndirect( + UINT DrawCount, + ID3D11Buffer* pBufferForArgs, + UINT ByteOffsetForArgs, + UINT ByteStrideForArgs); + + void STDMETHODCALLTYPE MultiDrawIndirectCount( + UINT MaxDrawCount, + ID3D11Buffer* pBufferForCount, + UINT ByteOffsetForCount, + ID3D11Buffer* pBufferForArgs, + UINT ByteOffsetForArgs, + UINT ByteStrideForArgs); + + void STDMETHODCALLTYPE MultiDrawIndexedIndirectCount( + UINT MaxDrawCount, + ID3D11Buffer* pBufferForCount, + UINT ByteOffsetForCount, + ID3D11Buffer* pBufferForArgs, + UINT ByteOffsetForArgs, + UINT ByteStrideForArgs); + + void STDMETHODCALLTYPE SetDepthBoundsTest( + BOOL Enable, + FLOAT MinDepthBounds, + FLOAT MaxDepthBounds); + + void STDMETHODCALLTYPE SetBarrierControl( + UINT ControlFlags); + + bool STDMETHODCALLTYPE LaunchCubinShaderNVX( + IUnknown* hShader, + uint32_t GridX, + uint32_t GridY, + uint32_t GridZ, + const void* pParams, + uint32_t paramSize, + void* const* pReadResources, + uint32_t NumReadResources, + void* const* pWriteResources, + uint32_t NumWriteResources); + + private: + + D3D11DeviceContext* m_ctx; + + }; + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_context_imm.cpp b/utils/dxvk-1.10.3/src/d3d11/d3d11_context_imm.cpp new file mode 100644 index 00000000000..adde00aeef8 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_context_imm.cpp @@ -0,0 +1,823 @@ +#include "d3d11_cmdlist.h" +#include "d3d11_context_imm.h" +#include "d3d11_device.h" +#include "d3d11_fence.h" +#include "d3d11_texture.h" + +constexpr static uint32_t MinFlushIntervalUs = 750; +constexpr static uint32_t IncFlushIntervalUs = 250; +constexpr static uint32_t MaxPendingSubmits = 6; + +namespace dxvk { + + D3D11ImmediateContext::D3D11ImmediateContext( + D3D11Device* pParent, + const Rc& Device) + : D3D11DeviceContext(pParent, Device, DxvkCsChunkFlag::SingleUse), + m_csThread(Device, Device->createContext()), + m_maxImplicitDiscardSize(pParent->GetOptions()->maxImplicitDiscardSize), + m_videoContext(this, Device) { + EmitCs([ + cDevice = m_device, + cRelaxedBarriers = pParent->GetOptions()->relaxedBarriers, + cIgnoreGraphicsBarriers = pParent->GetOptions()->ignoreGraphicsBarriers + ] (DxvkContext* ctx) { + ctx->beginRecording(cDevice->createCommandList()); + + DxvkBarrierControlFlags barrierControl; + + if (cRelaxedBarriers) + barrierControl.set(DxvkBarrierControl::IgnoreWriteAfterWrite); + + if (cIgnoreGraphicsBarriers) + barrierControl.set(DxvkBarrierControl::IgnoreGraphicsBarriers); + + ctx->setBarrierControl(barrierControl); + }); + + ClearState(); + } + + + D3D11ImmediateContext::~D3D11ImmediateContext() { + Flush(); + SynchronizeCsThread(DxvkCsThread::SynchronizeAll); + SynchronizeDevice(); + } + + + HRESULT STDMETHODCALLTYPE D3D11ImmediateContext::QueryInterface(REFIID riid, void** ppvObject) { + if (riid == __uuidof(ID3D11VideoContext)) { + *ppvObject = ref(&m_videoContext); + return S_OK; + } + + return D3D11DeviceContext::QueryInterface(riid, ppvObject); + } + + + D3D11_DEVICE_CONTEXT_TYPE STDMETHODCALLTYPE D3D11ImmediateContext::GetType() { + return D3D11_DEVICE_CONTEXT_IMMEDIATE; + } + + + UINT STDMETHODCALLTYPE D3D11ImmediateContext::GetContextFlags() { + return 0; + } + + + HRESULT STDMETHODCALLTYPE D3D11ImmediateContext::GetData( + ID3D11Asynchronous* pAsync, + void* pData, + UINT DataSize, + UINT GetDataFlags) { + if (!pAsync || (DataSize && !pData)) + return E_INVALIDARG; + + // Check whether the data size is actually correct + if (DataSize && DataSize != pAsync->GetDataSize()) + return E_INVALIDARG; + + // Passing a non-null pData is actually allowed if + // DataSize is 0, but we should ignore that pointer + pData = DataSize ? pData : nullptr; + + // Get query status directly from the query object + auto query = static_cast(pAsync); + HRESULT hr = query->GetData(pData, GetDataFlags); + + // If we're likely going to spin on the asynchronous object, + // flush the context so that we're keeping the GPU busy. + if (hr == S_FALSE) { + // Don't mark the event query as stalling if the app does + // not intend to spin on it. This reduces flushes on End. + if (!(GetDataFlags & D3D11_ASYNC_GETDATA_DONOTFLUSH)) + query->NotifyStall(); + + // Ignore the DONOTFLUSH flag here as some games will spin + // on queries without ever flushing the context otherwise. + FlushImplicit(FALSE); + } + + return hr; + } + + + void STDMETHODCALLTYPE D3D11ImmediateContext::Begin(ID3D11Asynchronous* pAsync) { + D3D10DeviceLock lock = LockContext(); + + if (unlikely(!pAsync)) + return; + + auto query = static_cast(pAsync); + + if (unlikely(!query->DoBegin())) + return; + + EmitCs([cQuery = Com(query)] + (DxvkContext* ctx) { + cQuery->Begin(ctx); + }); + } + + + void STDMETHODCALLTYPE D3D11ImmediateContext::End(ID3D11Asynchronous* pAsync) { + D3D10DeviceLock lock = LockContext(); + + if (unlikely(!pAsync)) + return; + + auto query = static_cast(pAsync); + + if (unlikely(!query->DoEnd())) { + EmitCs([cQuery = Com(query)] + (DxvkContext* ctx) { + cQuery->Begin(ctx); + }); + } + + EmitCs([cQuery = Com(query)] + (DxvkContext* ctx) { + cQuery->End(ctx); + }); + + if (unlikely(query->TrackStalls())) { + query->NotifyEnd(); + + if (query->IsStalling()) + Flush(); + else if (query->IsEvent()) + FlushImplicit(TRUE); + } + } + + + void STDMETHODCALLTYPE D3D11ImmediateContext::Flush() { + Flush1(D3D11_CONTEXT_TYPE_ALL, nullptr); + } + + + void STDMETHODCALLTYPE D3D11ImmediateContext::Flush1( + D3D11_CONTEXT_TYPE ContextType, + HANDLE hEvent) { + m_parent->FlushInitContext(); + + if (hEvent) + SignalEvent(hEvent); + + D3D10DeviceLock lock = LockContext(); + + if (m_csIsBusy || !m_csChunk->empty()) { + // Add commands to flush the threaded + // context, then flush the command list + EmitCs([] (DxvkContext* ctx) { + ctx->flushCommandList(); + }); + + FlushCsChunk(); + + // Reset flush timer used for implicit flushes + m_lastFlush = dxvk::high_resolution_clock::now(); + m_csIsBusy = false; + } + } + + + HRESULT STDMETHODCALLTYPE D3D11ImmediateContext::Signal( + ID3D11Fence* pFence, + UINT64 Value) { + auto fence = static_cast(pFence); + + if (!fence) + return E_INVALIDARG; + + EmitCs([ + cFence = fence->GetFence(), + cValue = Value + ] (DxvkContext* ctx) { + ctx->signalFence(cFence, cValue); + }); + + Flush(); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11ImmediateContext::Wait( + ID3D11Fence* pFence, + UINT64 Value) { + auto fence = static_cast(pFence); + + if (!fence) + return E_INVALIDARG; + + Flush(); + + EmitCs([ + cFence = fence->GetFence(), + cValue = Value + ] (DxvkContext* ctx) { + ctx->waitFence(cFence, cValue); + }); + + return S_OK; + } + + + void STDMETHODCALLTYPE D3D11ImmediateContext::ExecuteCommandList( + ID3D11CommandList* pCommandList, + BOOL RestoreContextState) { + D3D10DeviceLock lock = LockContext(); + + auto commandList = static_cast(pCommandList); + + // Flush any outstanding commands so that + // we don't mess up the execution order + FlushCsChunk(); + + // As an optimization, flush everything if the + // number of pending draw calls is high enough. + FlushImplicit(FALSE); + + // Dispatch command list to the CS thread and + // restore the immediate context's state + uint64_t csSeqNum = commandList->EmitToCsThread(&m_csThread); + m_csSeqNum = std::max(m_csSeqNum, csSeqNum); + + if (RestoreContextState) + RestoreState(); + else + ClearState(); + + // Mark CS thread as busy so that subsequent + // flush operations get executed correctly. + m_csIsBusy = true; + } + + + HRESULT STDMETHODCALLTYPE D3D11ImmediateContext::FinishCommandList( + BOOL RestoreDeferredContextState, + ID3D11CommandList **ppCommandList) { + InitReturnPtr(ppCommandList); + + Logger::err("D3D11: FinishCommandList called on immediate context"); + return DXGI_ERROR_INVALID_CALL; + } + + + HRESULT STDMETHODCALLTYPE D3D11ImmediateContext::Map( + ID3D11Resource* pResource, + UINT Subresource, + D3D11_MAP MapType, + UINT MapFlags, + D3D11_MAPPED_SUBRESOURCE* pMappedResource) { + D3D10DeviceLock lock = LockContext(); + + if (unlikely(!pResource)) + return E_INVALIDARG; + + D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN; + pResource->GetType(&resourceDim); + + HRESULT hr; + + if (likely(resourceDim == D3D11_RESOURCE_DIMENSION_BUFFER)) { + hr = MapBuffer( + static_cast(pResource), + MapType, MapFlags, pMappedResource); + } else { + hr = MapImage( + GetCommonTexture(pResource), + Subresource, MapType, MapFlags, + pMappedResource); + } + + if (unlikely(FAILED(hr))) + *pMappedResource = D3D11_MAPPED_SUBRESOURCE(); + + return hr; + } + + + void STDMETHODCALLTYPE D3D11ImmediateContext::Unmap( + ID3D11Resource* pResource, + UINT Subresource) { + // Since it is very uncommon for images to be mapped compared + // to buffers, we count the currently mapped images in order + // to avoid a virtual method call in the common case. + if (unlikely(m_mappedImageCount > 0)) { + D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN; + pResource->GetType(&resourceDim); + + if (resourceDim != D3D11_RESOURCE_DIMENSION_BUFFER) { + D3D10DeviceLock lock = LockContext(); + UnmapImage(GetCommonTexture(pResource), Subresource); + } + } + } + + void STDMETHODCALLTYPE D3D11ImmediateContext::UpdateSubresource( + ID3D11Resource* pDstResource, + UINT DstSubresource, + const D3D11_BOX* pDstBox, + const void* pSrcData, + UINT SrcRowPitch, + UINT SrcDepthPitch) { + UpdateResource(this, pDstResource, + DstSubresource, pDstBox, pSrcData, SrcRowPitch, SrcDepthPitch, 0); + } + + + void STDMETHODCALLTYPE D3D11ImmediateContext::UpdateSubresource1( + ID3D11Resource* pDstResource, + UINT DstSubresource, + const D3D11_BOX* pDstBox, + const void* pSrcData, + UINT SrcRowPitch, + UINT SrcDepthPitch, + UINT CopyFlags) { + UpdateResource(this, pDstResource, + DstSubresource, pDstBox, pSrcData, SrcRowPitch, SrcDepthPitch, CopyFlags); + } + + + void STDMETHODCALLTYPE D3D11ImmediateContext::OMSetRenderTargets( + UINT NumViews, + ID3D11RenderTargetView* const* ppRenderTargetViews, + ID3D11DepthStencilView* pDepthStencilView) { + FlushImplicit(TRUE); + + D3D11DeviceContext::OMSetRenderTargets( + NumViews, ppRenderTargetViews, pDepthStencilView); + } + + + void STDMETHODCALLTYPE D3D11ImmediateContext::OMSetRenderTargetsAndUnorderedAccessViews( + UINT NumRTVs, + ID3D11RenderTargetView* const* ppRenderTargetViews, + ID3D11DepthStencilView* pDepthStencilView, + UINT UAVStartSlot, + UINT NumUAVs, + ID3D11UnorderedAccessView* const* ppUnorderedAccessViews, + const UINT* pUAVInitialCounts) { + FlushImplicit(TRUE); + + D3D11DeviceContext::OMSetRenderTargetsAndUnorderedAccessViews( + NumRTVs, ppRenderTargetViews, pDepthStencilView, + UAVStartSlot, NumUAVs, ppUnorderedAccessViews, + pUAVInitialCounts); + } + + + HRESULT D3D11ImmediateContext::MapBuffer( + D3D11Buffer* pResource, + D3D11_MAP MapType, + UINT MapFlags, + D3D11_MAPPED_SUBRESOURCE* pMappedResource) { + if (unlikely(!pMappedResource)) + return E_INVALIDARG; + + if (unlikely(pResource->GetMapMode() == D3D11_COMMON_BUFFER_MAP_MODE_NONE)) { + Logger::err("D3D11: Cannot map a device-local buffer"); + return E_INVALIDARG; + } + + VkDeviceSize bufferSize = pResource->Desc()->ByteWidth; + + if (likely(MapType == D3D11_MAP_WRITE_DISCARD)) { + // Allocate a new backing slice for the buffer and set + // it as the 'new' mapped slice. This assumes that the + // only way to invalidate a buffer is by mapping it. + auto physSlice = pResource->DiscardSlice(); + pMappedResource->pData = physSlice.mapPtr; + pMappedResource->RowPitch = bufferSize; + pMappedResource->DepthPitch = bufferSize; + + EmitCs([ + cBuffer = pResource->GetBuffer(), + cBufferSlice = physSlice + ] (DxvkContext* ctx) { + ctx->invalidateBuffer(cBuffer, cBufferSlice); + }); + + return S_OK; + } else if (likely(MapType == D3D11_MAP_WRITE_NO_OVERWRITE)) { + // Put this on a fast path without any extra checks since it's + // a somewhat desired method to partially update large buffers + DxvkBufferSliceHandle physSlice = pResource->GetMappedSlice(); + pMappedResource->pData = physSlice.mapPtr; + pMappedResource->RowPitch = bufferSize; + pMappedResource->DepthPitch = bufferSize; + return S_OK; + } else { + // Quantum Break likes using MAP_WRITE on resources which would force + // us to synchronize with the GPU multiple times per frame. In those + // situations, if there are no pending GPU writes to the resource, we + // can promote it to MAP_WRITE_DISCARD, but preserve the data by doing + // a CPU copy from the previous buffer slice, to avoid the sync point. + bool doInvalidatePreserve = false; + + auto buffer = pResource->GetBuffer(); + auto sequenceNumber = pResource->GetSequenceNumber(); + + if (MapType != D3D11_MAP_READ && !MapFlags && bufferSize <= m_maxImplicitDiscardSize) { + SynchronizeCsThread(sequenceNumber); + + bool hasWoAccess = buffer->isInUse(DxvkAccess::Write); + bool hasRwAccess = buffer->isInUse(DxvkAccess::Read); + + if (hasRwAccess && !hasWoAccess) { + // Uncached reads can be so slow that a GPU sync may actually be faster + doInvalidatePreserve = buffer->memFlags() & VK_MEMORY_PROPERTY_HOST_CACHED_BIT; + } + } + + if (doInvalidatePreserve) { + FlushImplicit(TRUE); + + auto prevSlice = pResource->GetMappedSlice(); + auto physSlice = pResource->DiscardSlice(); + + EmitCs([ + cBuffer = std::move(buffer), + cBufferSlice = physSlice + ] (DxvkContext* ctx) { + ctx->invalidateBuffer(cBuffer, cBufferSlice); + }); + + std::memcpy(physSlice.mapPtr, prevSlice.mapPtr, physSlice.length); + pMappedResource->pData = physSlice.mapPtr; + pMappedResource->RowPitch = bufferSize; + pMappedResource->DepthPitch = bufferSize; + return S_OK; + } else { + if (!WaitForResource(buffer, sequenceNumber, MapType, MapFlags)) + return DXGI_ERROR_WAS_STILL_DRAWING; + + DxvkBufferSliceHandle physSlice = pResource->GetMappedSlice(); + pMappedResource->pData = physSlice.mapPtr; + pMappedResource->RowPitch = bufferSize; + pMappedResource->DepthPitch = bufferSize; + return S_OK; + } + } + } + + + HRESULT D3D11ImmediateContext::MapImage( + D3D11CommonTexture* pResource, + UINT Subresource, + D3D11_MAP MapType, + UINT MapFlags, + D3D11_MAPPED_SUBRESOURCE* pMappedResource) { + const Rc mappedImage = pResource->GetImage(); + const Rc mappedBuffer = pResource->GetMappedBuffer(Subresource); + + auto mapMode = pResource->GetMapMode(); + + if (unlikely(mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_NONE)) { + Logger::err("D3D11: Cannot map a device-local image"); + return E_INVALIDARG; + } + + if (unlikely(Subresource >= pResource->CountSubresources())) + return E_INVALIDARG; + + if (likely(pMappedResource != nullptr)) { + // Resources with an unknown memory layout cannot return a pointer + if (pResource->Desc()->Usage == D3D11_USAGE_DEFAULT + && pResource->Desc()->TextureLayout == D3D11_TEXTURE_LAYOUT_UNDEFINED) + return E_INVALIDARG; + } else { + if (pResource->Desc()->Usage != D3D11_USAGE_DEFAULT) + return E_INVALIDARG; + } + + VkFormat packedFormat = m_parent->LookupPackedFormat( + pResource->Desc()->Format, pResource->GetFormatMode()).Format; + + uint64_t sequenceNumber = pResource->GetSequenceNumber(Subresource); + + auto formatInfo = imageFormatInfo(packedFormat); + void* mapPtr; + + if (mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT) { + // Wait for the resource to become available. We do not + // support image renaming, so stall on DISCARD instead. + if (MapType == D3D11_MAP_WRITE_DISCARD) + MapFlags &= ~D3D11_MAP_FLAG_DO_NOT_WAIT; + + if (MapType != D3D11_MAP_WRITE_NO_OVERWRITE) { + if (!WaitForResource(mappedImage, sequenceNumber, MapType, MapFlags)) + return DXGI_ERROR_WAS_STILL_DRAWING; + } + + // Query the subresource's memory layout and hope that + // the application respects the returned pitch values. + mapPtr = mappedImage->mapPtr(0); + } else { + constexpr uint32_t DoInvalidate = (1u << 0); + constexpr uint32_t DoPreserve = (1u << 1); + constexpr uint32_t DoWait = (1u << 2); + uint32_t doFlags; + + if (MapType == D3D11_MAP_READ) { + // Reads will not change the image content, so we only need + // to wait for the GPU to finish writing to the mapped buffer. + doFlags = DoWait; + } else if (MapType == D3D11_MAP_WRITE_DISCARD) { + doFlags = DoInvalidate; + + // If we know for sure that the mapped buffer is currently not + // in use by the GPU, we don't have to allocate a new slice. + if (m_csThread.lastSequenceNumber() >= sequenceNumber && !mappedBuffer->isInUse(DxvkAccess::Read)) + doFlags = 0; + } else if (mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_STAGING && (MapFlags & D3D11_MAP_FLAG_DO_NOT_WAIT)) { + // Always respect DO_NOT_WAIT for mapped staging images + doFlags = DoWait; + } else if (MapType != D3D11_MAP_WRITE_NO_OVERWRITE || mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER) { + // Need to synchronize thread to determine pending GPU accesses + SynchronizeCsThread(sequenceNumber); + + // Don't implicitly discard large buffers or buffers of images with + // multiple subresources, as that is likely to cause memory issues. + VkDeviceSize bufferSize = pResource->GetMappedSlice(Subresource).length; + + if (bufferSize >= m_maxImplicitDiscardSize || pResource->CountSubresources() > 1) { + // Don't check access flags, WaitForResource will return + // early anyway if the resource is currently in use + doFlags = DoWait; + } else if (mappedBuffer->isInUse(DxvkAccess::Write)) { + // There are pending GPU writes, need to wait for those + doFlags = DoWait; + } else if (mappedBuffer->isInUse(DxvkAccess::Read)) { + // All pending GPU accesses are reads, so the buffer data + // is still current, and we can prevent GPU synchronization + // by creating a new slice with an exact copy of the data. + doFlags = DoInvalidate | DoPreserve; + } else { + // There are no pending accesses, so we don't need to wait + doFlags = 0; + } + } else { + // No need to synchronize staging resources with NO_OVERWRITE + // since the buffer will be used directly. + doFlags = 0; + } + + if (doFlags & DoInvalidate) { + FlushImplicit(TRUE); + + DxvkBufferSliceHandle prevSlice = pResource->GetMappedSlice(Subresource); + DxvkBufferSliceHandle physSlice = pResource->DiscardSlice(Subresource); + + EmitCs([ + cImageBuffer = mappedBuffer, + cBufferSlice = physSlice + ] (DxvkContext* ctx) { + ctx->invalidateBuffer(cImageBuffer, cBufferSlice); + }); + + if (doFlags & DoPreserve) + std::memcpy(physSlice.mapPtr, prevSlice.mapPtr, physSlice.length); + + mapPtr = physSlice.mapPtr; + } else { + if (doFlags & DoWait) { + // We cannot respect DO_NOT_WAIT for buffer-mapped resources since + // our internal copies need to be transparent to the application. + if (mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER) + MapFlags &= ~D3D11_MAP_FLAG_DO_NOT_WAIT; + + // Wait for mapped buffer to become available + if (!WaitForResource(mappedBuffer, sequenceNumber, MapType, MapFlags)) + return DXGI_ERROR_WAS_STILL_DRAWING; + } + + mapPtr = pResource->GetMappedSlice(Subresource).mapPtr; + } + } + + // Mark the given subresource as mapped + pResource->SetMapType(Subresource, MapType); + + if (pMappedResource) { + auto layout = pResource->GetSubresourceLayout(formatInfo->aspectMask, Subresource); + pMappedResource->pData = reinterpret_cast(mapPtr) + layout.Offset; + pMappedResource->RowPitch = layout.RowPitch; + pMappedResource->DepthPitch = layout.DepthPitch; + } + + m_mappedImageCount += 1; + return S_OK; + } + + + void D3D11ImmediateContext::UnmapImage( + D3D11CommonTexture* pResource, + UINT Subresource) { + D3D11_MAP mapType = pResource->GetMapType(Subresource); + pResource->SetMapType(Subresource, D3D11_MAP(~0u)); + + if (mapType == D3D11_MAP(~0u)) + return; + + // Decrement mapped image counter only after making sure + // the given subresource is actually mapped right now + m_mappedImageCount -= 1; + + if ((mapType != D3D11_MAP_READ) && + (pResource->GetMapMode() == D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER)) { + // Now that data has been written into the buffer, + // we need to copy its contents into the image + VkImageAspectFlags aspectMask = imageFormatInfo(pResource->GetPackedFormat())->aspectMask; + VkImageSubresource subresource = pResource->GetSubresourceFromIndex(aspectMask, Subresource); + + UpdateImage(pResource, &subresource, VkOffset3D { 0, 0, 0 }, + pResource->MipLevelExtent(subresource.mipLevel), + DxvkBufferSlice(pResource->GetMappedBuffer(Subresource))); + } + } + + + void D3D11ImmediateContext::UpdateMappedBuffer( + D3D11Buffer* pDstBuffer, + UINT Offset, + UINT Length, + const void* pSrcData, + UINT CopyFlags) { + DxvkBufferSliceHandle slice; + + if (likely(CopyFlags != D3D11_COPY_NO_OVERWRITE)) { + slice = pDstBuffer->DiscardSlice(); + + EmitCs([ + cBuffer = pDstBuffer->GetBuffer(), + cBufferSlice = slice + ] (DxvkContext* ctx) { + ctx->invalidateBuffer(cBuffer, cBufferSlice); + }); + } else { + slice = pDstBuffer->GetMappedSlice(); + } + + std::memcpy(reinterpret_cast(slice.mapPtr) + Offset, pSrcData, Length); + } + + + void STDMETHODCALLTYPE D3D11ImmediateContext::SwapDeviceContextState( + ID3DDeviceContextState* pState, + ID3DDeviceContextState** ppPreviousState) { + InitReturnPtr(ppPreviousState); + + if (!pState) + return; + + Com oldState = std::move(m_stateObject); + Com newState = static_cast(pState); + + if (oldState == nullptr) + oldState = new D3D11DeviceContextState(m_parent); + + if (ppPreviousState) + *ppPreviousState = oldState.ref(); + + m_stateObject = newState; + + oldState->SetState(m_state); + newState->GetState(m_state); + + RestoreState(); + } + + + void D3D11ImmediateContext::SynchronizeCsThread(uint64_t SequenceNumber) { + D3D10DeviceLock lock = LockContext(); + + // Dispatch current chunk so that all commands + // recorded prior to this function will be run + if (SequenceNumber > m_csSeqNum) + FlushCsChunk(); + + m_csThread.synchronize(SequenceNumber); + } + + + void D3D11ImmediateContext::SynchronizeDevice() { + m_device->waitForIdle(); + } + + + bool D3D11ImmediateContext::WaitForResource( + const Rc& Resource, + uint64_t SequenceNumber, + D3D11_MAP MapType, + UINT MapFlags) { + // Determine access type to wait for based on map mode + DxvkAccess access = MapType == D3D11_MAP_READ + ? DxvkAccess::Write + : DxvkAccess::Read; + + // Wait for any CS chunk using the resource to execute, since + // otherwise we cannot accurately determine if the resource is + // actually being used by the GPU right now. + bool isInUse = Resource->isInUse(access); + + if (!isInUse) { + SynchronizeCsThread(SequenceNumber); + isInUse = Resource->isInUse(access); + } + + if (MapFlags & D3D11_MAP_FLAG_DO_NOT_WAIT) { + if (isInUse) { + // We don't have to wait, but misbehaving games may + // still try to spin on `Map` until the resource is + // idle, so we should flush pending commands + FlushImplicit(FALSE); + return false; + } + } else { + if (isInUse) { + // Make sure pending commands using the resource get + // executed on the the GPU if we have to wait for it + Flush(); + SynchronizeCsThread(SequenceNumber); + + m_device->waitForResource(Resource, access); + } + } + + return true; + } + + + void D3D11ImmediateContext::EmitCsChunk(DxvkCsChunkRef&& chunk) { + m_csSeqNum = m_csThread.dispatchChunk(std::move(chunk)); + m_csIsBusy = true; + } + + + void D3D11ImmediateContext::TrackTextureSequenceNumber( + D3D11CommonTexture* pResource, + UINT Subresource) { + uint64_t sequenceNumber = GetCurrentSequenceNumber(); + pResource->TrackSequenceNumber(Subresource, sequenceNumber); + + FlushImplicit(TRUE); + } + + + void D3D11ImmediateContext::TrackBufferSequenceNumber( + D3D11Buffer* pResource) { + uint64_t sequenceNumber = GetCurrentSequenceNumber(); + pResource->TrackSequenceNumber(sequenceNumber); + + FlushImplicit(TRUE); + } + + + uint64_t D3D11ImmediateContext::GetCurrentSequenceNumber() { + // We do not flush empty chunks, so if we are tracking a resource + // immediately after a flush, we need to use the sequence number + // of the previously submitted chunk to prevent deadlocks. + return m_csChunk->empty() ? m_csSeqNum : m_csSeqNum + 1; + } + + + void D3D11ImmediateContext::FlushImplicit(BOOL StrongHint) { + // Flush only if the GPU is about to go idle, in + // order to keep the number of submissions low. + uint32_t pending = m_device->pendingSubmissions(); + + if (StrongHint || pending <= MaxPendingSubmits) { + auto now = dxvk::high_resolution_clock::now(); + + uint32_t delay = MinFlushIntervalUs + + IncFlushIntervalUs * pending; + + // Prevent flushing too often in short intervals. + if (now - m_lastFlush >= std::chrono::microseconds(delay)) + Flush(); + } + } + + + void D3D11ImmediateContext::SignalEvent(HANDLE hEvent) { + uint64_t value = ++m_eventCount; + + if (m_eventSignal == nullptr) + m_eventSignal = new sync::CallbackFence(); + + m_eventSignal->setCallback(value, [hEvent] { + SetEvent(hEvent); + }); + + EmitCs([ + cSignal = m_eventSignal, + cValue = value + ] (DxvkContext* ctx) { + ctx->signal(cSignal, cValue); + }); + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_context_imm.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_context_imm.h new file mode 100644 index 00000000000..9a5ba21f518 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_context_imm.h @@ -0,0 +1,185 @@ +#pragma once + +#include "../util/util_time.h" + +#include "../util/sync/sync_signal.h" + +#include "d3d11_context.h" +#include "d3d11_state_object.h" +#include "d3d11_video.h" + +namespace dxvk { + + class D3D11Buffer; + class D3D11CommonTexture; + + class D3D11ImmediateContext : public D3D11DeviceContext { + friend class D3D11SwapChain; + friend class D3D11VideoContext; + friend class D3D11DeviceContext; + public: + + D3D11ImmediateContext( + D3D11Device* pParent, + const Rc& Device); + ~D3D11ImmediateContext(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + D3D11_DEVICE_CONTEXT_TYPE STDMETHODCALLTYPE GetType(); + + UINT STDMETHODCALLTYPE GetContextFlags(); + + HRESULT STDMETHODCALLTYPE GetData( + ID3D11Asynchronous* pAsync, + void* pData, + UINT DataSize, + UINT GetDataFlags); + + void STDMETHODCALLTYPE Begin( + ID3D11Asynchronous* pAsync); + + void STDMETHODCALLTYPE End( + ID3D11Asynchronous* pAsync); + + void STDMETHODCALLTYPE Flush(); + + void STDMETHODCALLTYPE Flush1( + D3D11_CONTEXT_TYPE ContextType, + HANDLE hEvent); + + HRESULT STDMETHODCALLTYPE Signal( + ID3D11Fence* pFence, + UINT64 Value); + + HRESULT STDMETHODCALLTYPE Wait( + ID3D11Fence* pFence, + UINT64 Value); + + void STDMETHODCALLTYPE ExecuteCommandList( + ID3D11CommandList* pCommandList, + BOOL RestoreContextState); + + HRESULT STDMETHODCALLTYPE FinishCommandList( + BOOL RestoreDeferredContextState, + ID3D11CommandList **ppCommandList); + + HRESULT STDMETHODCALLTYPE Map( + ID3D11Resource* pResource, + UINT Subresource, + D3D11_MAP MapType, + UINT MapFlags, + D3D11_MAPPED_SUBRESOURCE* pMappedResource); + + void STDMETHODCALLTYPE Unmap( + ID3D11Resource* pResource, + UINT Subresource); + + void STDMETHODCALLTYPE UpdateSubresource( + ID3D11Resource* pDstResource, + UINT DstSubresource, + const D3D11_BOX* pDstBox, + const void* pSrcData, + UINT SrcRowPitch, + UINT SrcDepthPitch); + + void STDMETHODCALLTYPE UpdateSubresource1( + ID3D11Resource* pDstResource, + UINT DstSubresource, + const D3D11_BOX* pDstBox, + const void* pSrcData, + UINT SrcRowPitch, + UINT SrcDepthPitch, + UINT CopyFlags); + + void STDMETHODCALLTYPE OMSetRenderTargets( + UINT NumViews, + ID3D11RenderTargetView* const* ppRenderTargetViews, + ID3D11DepthStencilView* pDepthStencilView); + + void STDMETHODCALLTYPE OMSetRenderTargetsAndUnorderedAccessViews( + UINT NumRTVs, + ID3D11RenderTargetView* const* ppRenderTargetViews, + ID3D11DepthStencilView* pDepthStencilView, + UINT UAVStartSlot, + UINT NumUAVs, + ID3D11UnorderedAccessView* const* ppUnorderedAccessViews, + const UINT* pUAVInitialCounts); + + void STDMETHODCALLTYPE SwapDeviceContextState( + ID3DDeviceContextState* pState, + ID3DDeviceContextState** ppPreviousState); + + void SynchronizeCsThread( + uint64_t SequenceNumber); + + private: + + DxvkCsThread m_csThread; + uint64_t m_csSeqNum = 0ull; + bool m_csIsBusy = false; + + Rc m_eventSignal; + uint64_t m_eventCount = 0ull; + uint32_t m_mappedImageCount = 0u; + + VkDeviceSize m_maxImplicitDiscardSize = 0ull; + + dxvk::high_resolution_clock::time_point m_lastFlush + = dxvk::high_resolution_clock::now(); + + D3D11VideoContext m_videoContext; + Com m_stateObject; + + HRESULT MapBuffer( + D3D11Buffer* pResource, + D3D11_MAP MapType, + UINT MapFlags, + D3D11_MAPPED_SUBRESOURCE* pMappedResource); + + HRESULT MapImage( + D3D11CommonTexture* pResource, + UINT Subresource, + D3D11_MAP MapType, + UINT MapFlags, + D3D11_MAPPED_SUBRESOURCE* pMappedResource); + + void UnmapImage( + D3D11CommonTexture* pResource, + UINT Subresource); + + void UpdateMappedBuffer( + D3D11Buffer* pDstBuffer, + UINT Offset, + UINT Length, + const void* pSrcData, + UINT CopyFlags); + + void SynchronizeDevice(); + + bool WaitForResource( + const Rc& Resource, + uint64_t SequenceNumber, + D3D11_MAP MapType, + UINT MapFlags); + + void EmitCsChunk(DxvkCsChunkRef&& chunk); + + void TrackTextureSequenceNumber( + D3D11CommonTexture* pResource, + UINT Subresource); + + void TrackBufferSequenceNumber( + D3D11Buffer* pResource); + + uint64_t GetCurrentSequenceNumber(); + + void FlushImplicit(BOOL StrongHint); + + void SignalEvent(HANDLE hEvent); + + }; + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_context_state.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_context_state.h new file mode 100644 index 00000000000..eca2a3c9d94 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_context_state.h @@ -0,0 +1,187 @@ +#pragma once + +#include + +#include "d3d11_buffer.h" +#include "d3d11_input_layout.h" +#include "d3d11_query.h" +#include "d3d11_sampler.h" +#include "d3d11_shader.h" +#include "d3d11_state.h" +#include "d3d11_view_dsv.h" +#include "d3d11_view_rtv.h" +#include "d3d11_view_srv.h" +#include "d3d11_view_uav.h" + +namespace dxvk { + + struct D3D11ConstantBufferBinding { + Com buffer = nullptr; + UINT constantOffset = 0; + UINT constantCount = 0; + UINT constantBound = 0; + }; + + using D3D11ConstantBufferBindings = std::array< + D3D11ConstantBufferBinding, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT>; + + + using D3D11SamplerBindings = std::array< + D3D11SamplerState*, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT>; + + + struct D3D11ShaderResourceBindings { + std::array, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT> views = { }; + DxvkBindingSet hazardous = { }; + }; + + + using D3D11UnorderedAccessBindings = std::array< + Com, D3D11_1_UAV_SLOT_COUNT>; + + + struct D3D11ContextStateVS { + Com shader = nullptr; + D3D11ConstantBufferBindings constantBuffers = { }; + D3D11SamplerBindings samplers = { }; + D3D11ShaderResourceBindings shaderResources = { }; + }; + + + struct D3D11ContextStateHS { + Com shader = nullptr; + D3D11ConstantBufferBindings constantBuffers = { }; + D3D11SamplerBindings samplers = { }; + D3D11ShaderResourceBindings shaderResources = { }; + }; + + + struct D3D11ContextStateDS { + Com shader = nullptr; + D3D11ConstantBufferBindings constantBuffers = { }; + D3D11SamplerBindings samplers = { }; + D3D11ShaderResourceBindings shaderResources = { }; + }; + + + struct D3D11ContextStateGS { + Com shader = nullptr; + D3D11ConstantBufferBindings constantBuffers = { }; + D3D11SamplerBindings samplers = { }; + D3D11ShaderResourceBindings shaderResources = { }; + }; + + + struct D3D11ContextStatePS { + Com shader = nullptr; + D3D11ConstantBufferBindings constantBuffers = { }; + D3D11SamplerBindings samplers = { }; + D3D11ShaderResourceBindings shaderResources = { }; + D3D11UnorderedAccessBindings unorderedAccessViews = { }; + }; + + + struct D3D11ContextStateCS { + Com shader = nullptr; + D3D11ConstantBufferBindings constantBuffers = { }; + D3D11SamplerBindings samplers = { }; + D3D11ShaderResourceBindings shaderResources = { }; + D3D11UnorderedAccessBindings unorderedAccessViews = { }; + + DxvkBindingSet uavMask = { }; + }; + + + struct D3D11VertexBufferBinding { + Com buffer = nullptr; + UINT offset = 0; + UINT stride = 0; + }; + + + struct D3D11IndexBufferBinding { + Com buffer = nullptr; + UINT offset = 0; + DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN; + }; + + + struct D3D11ContextStateID { + Com argBuffer = nullptr; + Com cntBuffer = nullptr; + }; + + + struct D3D11ContextStateIA { + Com inputLayout = nullptr; + D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED; + + std::array vertexBuffers = { }; + D3D11IndexBufferBinding indexBuffer = { }; + }; + + + struct D3D11ContextStateOM { + std::array, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT> renderTargetViews = { }; + Com depthStencilView = { }; + + D3D11BlendState* cbState = nullptr; + D3D11DepthStencilState* dsState = nullptr; + + FLOAT blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + UINT sampleMask = 0xFFFFFFFFu; + UINT stencilRef = 0u; + + UINT maxRtv = 0u; + UINT maxUav = 0u; + }; + + + struct D3D11ContextStateRS { + uint32_t numViewports = 0; + uint32_t numScissors = 0; + + std::array viewports = { }; + std::array scissors = { }; + + D3D11RasterizerState* state = nullptr; + }; + + + struct D3D11ContextSoTarget { + Com buffer = nullptr; + UINT offset = 0; + }; + + + struct D3D11ContextStateSO { + std::array targets = { }; + }; + + + struct D3D11ContextStatePR { + Com predicateObject = nullptr; + BOOL predicateValue = FALSE; + }; + + + /** + * \brief Context state + */ + struct D3D11ContextState { + D3D11ContextStateCS cs; + D3D11ContextStateDS ds; + D3D11ContextStateGS gs; + D3D11ContextStateHS hs; + D3D11ContextStatePS ps; + D3D11ContextStateVS vs; + + D3D11ContextStateID id; + D3D11ContextStateIA ia; + D3D11ContextStateOM om; + D3D11ContextStateRS rs; + D3D11ContextStateSO so; + D3D11ContextStatePR pr; + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_cuda.cpp b/utils/dxvk-1.10.3/src/d3d11/d3d11_cuda.cpp new file mode 100644 index 00000000000..4a31d347a29 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_cuda.cpp @@ -0,0 +1,51 @@ +#include "d3d11_cuda.h" + +namespace dxvk { + + CubinShaderWrapper::CubinShaderWrapper(const Rc& dxvkDevice, VkCuModuleNVX cuModule, VkCuFunctionNVX cuFunction, VkExtent3D blockDim) + : m_dxvkDevice(dxvkDevice), m_module(cuModule), m_function(cuFunction), m_blockDim(blockDim) { }; + + + CubinShaderWrapper::~CubinShaderWrapper() { + VkDevice vkDevice = m_dxvkDevice->handle(); + m_dxvkDevice->vkd()->vkDestroyCuFunctionNVX(vkDevice, m_function, nullptr); + m_dxvkDevice->vkd()->vkDestroyCuModuleNVX(vkDevice, m_module, nullptr); + }; + + + HRESULT STDMETHODCALLTYPE CubinShaderWrapper::QueryInterface(REFIID riid, void **ppvObject) { + if (riid == __uuidof(IUnknown)) { + *ppvObject = ref(this); + return S_OK; + } + + Logger::warn("CubinShaderWrapper::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + void CubinShaderLaunchInfo::insertResource(ID3D11Resource* pResource, DxvkAccessFlags access) { + auto img = GetCommonTexture(pResource); + auto buf = GetCommonBuffer(pResource); + + if (img) + insertUniqueResource(images, img->GetImage(), access); + if (buf) + insertUniqueResource(buffers, buf->GetBuffer(), access); + } + + + template + void CubinShaderLaunchInfo::insertUniqueResource(std::vector>& list, const T& resource, DxvkAccessFlags access) { + for (auto& entry : list) { + if (entry.first == resource) { + entry.second.set(access); + return; + } + } + + list.push_back({ resource, access }); + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_cuda.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_cuda.h new file mode 100644 index 00000000000..a9fcdf4b31e --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_cuda.h @@ -0,0 +1,83 @@ +#pragma once + +#include +#include + +#include "../dxvk/dxvk_resource.h" + +#include "../util/com/com_guid.h" +#include "../util/com/com_object.h" + +#include "d3d11_buffer.h" +#include "d3d11_texture.h" + +namespace dxvk { + + class CubinShaderWrapper : public ComObject { + + public: + + CubinShaderWrapper(const Rc& dxvkDevice, VkCuModuleNVX cuModule, VkCuFunctionNVX cuFunction, VkExtent3D blockDim); + ~CubinShaderWrapper(); + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject); + + VkCuModuleNVX cuModule() const { + return m_module; + } + + VkCuFunctionNVX cuFunction() const { + return m_function; + } + + VkExtent3D blockDim() const { + return m_blockDim; + } + + private: + + Rc m_dxvkDevice; + VkCuModuleNVX m_module; + VkCuFunctionNVX m_function; + VkExtent3D m_blockDim; + + }; + + + struct CubinShaderLaunchInfo { + + CubinShaderLaunchInfo() = default; + + CubinShaderLaunchInfo(CubinShaderLaunchInfo&& other) { + shader = std::move(other.shader); + params = std::move(other.params); + paramSize = std::move(other.paramSize); + nvxLaunchInfo = std::move(other.nvxLaunchInfo); + cuLaunchConfig = other.cuLaunchConfig; + buffers = std::move(other.buffers); + images = std::move(other.images); + other.cuLaunchConfig[1] = nullptr; + other.cuLaunchConfig[3] = nullptr; + other.nvxLaunchInfo.pExtras = nullptr; + // fix-up internally-pointing pointers + cuLaunchConfig[1] = params.data(); + cuLaunchConfig[3] = ¶mSize; + nvxLaunchInfo.pExtras = cuLaunchConfig.data(); + } + + Com shader; + std::vector params; + size_t paramSize; + VkCuLaunchInfoNVX nvxLaunchInfo = { VK_STRUCTURE_TYPE_CU_LAUNCH_INFO_NVX }; + std::array cuLaunchConfig; + + std::vector, DxvkAccessFlags>> buffers; + std::vector, DxvkAccessFlags>> images; + + void insertResource(ID3D11Resource* pResource, DxvkAccessFlags access); + + template + static void insertUniqueResource(std::vector>& list, const T& resource, DxvkAccessFlags access); + }; + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_depth_stencil.cpp b/utils/dxvk-1.10.3/src/d3d11/d3d11_depth_stencil.cpp new file mode 100644 index 00000000000..b095e5eac4b --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_depth_stencil.cpp @@ -0,0 +1,166 @@ +#include "d3d11_depth_stencil.h" +#include "d3d11_device.h" + +namespace dxvk { + + D3D11DepthStencilState::D3D11DepthStencilState( + D3D11Device* device, + const D3D11_DEPTH_STENCIL_DESC& desc) + : D3D11StateObject(device), + m_desc(desc), m_d3d10(this) { + m_state.enableDepthTest = desc.DepthEnable; + m_state.enableDepthWrite = desc.DepthWriteMask == D3D11_DEPTH_WRITE_MASK_ALL; + m_state.enableStencilTest = desc.StencilEnable; + m_state.depthCompareOp = DecodeCompareOp(desc.DepthFunc); + m_state.stencilOpFront = DecodeStencilOpState(desc.FrontFace, desc); + m_state.stencilOpBack = DecodeStencilOpState(desc.BackFace, desc); + } + + + D3D11DepthStencilState::~D3D11DepthStencilState() { + + } + + + HRESULT STDMETHODCALLTYPE D3D11DepthStencilState::QueryInterface(REFIID riid, void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(ID3D11DeviceChild) + || riid == __uuidof(ID3D11DepthStencilState)) { + *ppvObject = ref(this); + return S_OK; + } + + if (riid == __uuidof(ID3D10DeviceChild) + || riid == __uuidof(ID3D10DepthStencilState)) { + *ppvObject = ref(this); + return S_OK; + } + + Logger::warn("D3D11DepthStencilState::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + void STDMETHODCALLTYPE D3D11DepthStencilState::GetDesc(D3D11_DEPTH_STENCIL_DESC* pDesc) { + *pDesc = m_desc; + } + + + void D3D11DepthStencilState::BindToContext(const Rc& ctx) { + ctx->setDepthStencilState(m_state); + } + + + HRESULT D3D11DepthStencilState::NormalizeDesc(D3D11_DEPTH_STENCIL_DESC* pDesc) { + if (pDesc->DepthEnable) { + pDesc->DepthEnable = TRUE; + + if (!ValidateDepthFunc(pDesc->DepthFunc)) + return E_INVALIDARG; + } else { + pDesc->DepthFunc = D3D11_COMPARISON_LESS; + pDesc->DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; + } + + if (!ValidateDepthWriteMask(pDesc->DepthWriteMask)) + return E_INVALIDARG; + + if (pDesc->StencilEnable) { + pDesc->StencilEnable = TRUE; + + if (!ValidateStencilFunc(pDesc->FrontFace.StencilFunc) + || !ValidateStencilOp(pDesc->FrontFace.StencilFailOp) + || !ValidateStencilOp(pDesc->FrontFace.StencilDepthFailOp) + || !ValidateStencilOp(pDesc->FrontFace.StencilPassOp)) + return E_INVALIDARG; + + if (!ValidateStencilFunc(pDesc->BackFace.StencilFunc) + || !ValidateStencilOp(pDesc->BackFace.StencilFailOp) + || !ValidateStencilOp(pDesc->BackFace.StencilDepthFailOp) + || !ValidateStencilOp(pDesc->BackFace.StencilPassOp)) + return E_INVALIDARG; + } else { + D3D11_DEPTH_STENCILOP_DESC stencilOp; + stencilOp.StencilFailOp = D3D11_STENCIL_OP_KEEP; + stencilOp.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; + stencilOp.StencilPassOp = D3D11_STENCIL_OP_KEEP; + stencilOp.StencilFunc = D3D11_COMPARISON_ALWAYS; + + pDesc->FrontFace = stencilOp; + pDesc->BackFace = stencilOp; + pDesc->StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK; + pDesc->StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK; + } + + return S_OK; + } + + + VkStencilOpState D3D11DepthStencilState::DecodeStencilOpState( + const D3D11_DEPTH_STENCILOP_DESC& StencilDesc, + const D3D11_DEPTH_STENCIL_DESC& Desc) const { + VkStencilOpState result; + result.failOp = VK_STENCIL_OP_KEEP; + result.passOp = VK_STENCIL_OP_KEEP; + result.depthFailOp = VK_STENCIL_OP_KEEP; + result.compareOp = VK_COMPARE_OP_ALWAYS; + result.compareMask = Desc.StencilReadMask; + result.writeMask = Desc.StencilWriteMask; + result.reference = 0; + + if (Desc.StencilEnable) { + result.failOp = DecodeStencilOp(StencilDesc.StencilFailOp); + result.passOp = DecodeStencilOp(StencilDesc.StencilPassOp); + result.depthFailOp = DecodeStencilOp(StencilDesc.StencilDepthFailOp); + result.compareOp = DecodeCompareOp(StencilDesc.StencilFunc); + } + + return result; + } + + + VkStencilOp D3D11DepthStencilState::DecodeStencilOp(D3D11_STENCIL_OP Op) const { + switch (Op) { + case D3D11_STENCIL_OP_KEEP: return VK_STENCIL_OP_KEEP; + case D3D11_STENCIL_OP_ZERO: return VK_STENCIL_OP_ZERO; + case D3D11_STENCIL_OP_REPLACE: return VK_STENCIL_OP_REPLACE; + case D3D11_STENCIL_OP_INCR_SAT: return VK_STENCIL_OP_INCREMENT_AND_CLAMP; + case D3D11_STENCIL_OP_DECR_SAT: return VK_STENCIL_OP_DECREMENT_AND_CLAMP; + case D3D11_STENCIL_OP_INVERT: return VK_STENCIL_OP_INVERT; + case D3D11_STENCIL_OP_INCR: return VK_STENCIL_OP_INCREMENT_AND_WRAP; + case D3D11_STENCIL_OP_DECR: return VK_STENCIL_OP_DECREMENT_AND_WRAP; + default: return VK_STENCIL_OP_KEEP; + } + } + + + bool D3D11DepthStencilState::ValidateDepthFunc(D3D11_COMPARISON_FUNC Comparison) { + return Comparison >= D3D11_COMPARISON_NEVER + && Comparison <= D3D11_COMPARISON_ALWAYS; + } + + + bool D3D11DepthStencilState::ValidateStencilFunc(D3D11_COMPARISON_FUNC Comparison) { + return Comparison >= D3D11_COMPARISON_NEVER + && Comparison <= D3D11_COMPARISON_ALWAYS; + } + + + bool D3D11DepthStencilState::ValidateStencilOp(D3D11_STENCIL_OP StencilOp) { + return StencilOp >= D3D11_STENCIL_OP_KEEP + && StencilOp <= D3D11_STENCIL_OP_DECR; + } + + + bool D3D11DepthStencilState::ValidateDepthWriteMask(D3D11_DEPTH_WRITE_MASK Mask) { + return Mask == D3D11_DEPTH_WRITE_MASK_ZERO + || Mask == D3D11_DEPTH_WRITE_MASK_ALL; + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_depth_stencil.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_depth_stencil.h new file mode 100644 index 00000000000..6311259f42e --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_depth_stencil.h @@ -0,0 +1,68 @@ +#pragma once + +#include "../dxvk/dxvk_device.h" + +#include "../d3d10/d3d10_depth_stencil.h" + +#include "d3d11_device_child.h" +#include "d3d11_util.h" + +namespace dxvk { + + class D3D11Device; + + class D3D11DepthStencilState : public D3D11StateObject { + + public: + + using DescType = D3D11_DEPTH_STENCIL_DESC; + + D3D11DepthStencilState( + D3D11Device* device, + const D3D11_DEPTH_STENCIL_DESC& desc); + ~D3D11DepthStencilState(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject) final; + + void STDMETHODCALLTYPE GetDesc( + D3D11_DEPTH_STENCIL_DESC* pDesc) final; + + void BindToContext( + const Rc& ctx); + + D3D10DepthStencilState* GetD3D10Iface() { + return &m_d3d10; + } + + static HRESULT NormalizeDesc( + D3D11_DEPTH_STENCIL_DESC* pDesc); + + private: + + D3D11_DEPTH_STENCIL_DESC m_desc; + DxvkDepthStencilState m_state; + D3D10DepthStencilState m_d3d10; + + VkStencilOpState DecodeStencilOpState( + const D3D11_DEPTH_STENCILOP_DESC& StencilDesc, + const D3D11_DEPTH_STENCIL_DESC& Desc) const; + + VkStencilOp DecodeStencilOp( + D3D11_STENCIL_OP Op) const; + + static bool ValidateDepthFunc( + D3D11_COMPARISON_FUNC Comparison); + + static bool ValidateStencilFunc( + D3D11_COMPARISON_FUNC Comparison); + + static bool ValidateStencilOp( + D3D11_STENCIL_OP StencilOp); + + static bool ValidateDepthWriteMask( + D3D11_DEPTH_WRITE_MASK Mask); + }; + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_device.cpp b/utils/dxvk-1.10.3/src/d3d11/d3d11_device.cpp new file mode 100644 index 00000000000..3dcad9baf88 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_device.cpp @@ -0,0 +1,3496 @@ +#include +#include + +#include "../dxgi/dxgi_monitor.h" +#include "../dxgi/dxgi_swapchain.h" + +#include "../dxvk/dxvk_adapter.h" +#include "../dxvk/dxvk_instance.h" + +#include "d3d11_buffer.h" +#include "d3d11_class_linkage.h" +#include "d3d11_context_def.h" +#include "d3d11_context_imm.h" +#include "d3d11_device.h" +#include "d3d11_fence.h" +#include "d3d11_input_layout.h" +#include "d3d11_interop.h" +#include "d3d11_query.h" +#include "d3d11_resource.h" +#include "d3d11_sampler.h" +#include "d3d11_shader.h" +#include "d3d11_state_object.h" +#include "d3d11_swapchain.h" +#include "d3d11_texture.h" +#include "d3d11_video.h" + +#include "../util/util_shared_res.h" + +namespace dxvk { + + constexpr uint32_t D3D11DXGIDevice::DefaultFrameLatency; + + + + D3D11Device::D3D11Device( + D3D11DXGIDevice* pContainer, + D3D_FEATURE_LEVEL FeatureLevel, + UINT FeatureFlags) + : m_container (pContainer), + m_featureLevel (FeatureLevel), + m_featureFlags (FeatureFlags), + m_dxvkDevice (pContainer->GetDXVKDevice()), + m_dxvkAdapter (m_dxvkDevice->adapter()), + m_d3d11Formats (m_dxvkAdapter), + m_d3d11Options (m_dxvkDevice->instance()->config(), m_dxvkDevice), + m_dxbcOptions (m_dxvkDevice, m_d3d11Options) { + m_initializer = new D3D11Initializer(this); + m_context = new D3D11ImmediateContext(this, m_dxvkDevice); + m_d3d10Device = new D3D10Device(this, m_context.ptr()); + } + + + D3D11Device::~D3D11Device() { + delete m_d3d10Device; + m_context = nullptr; + delete m_initializer; + } + + + ULONG STDMETHODCALLTYPE D3D11Device::AddRef() { + return m_container->AddRef(); + } + + + ULONG STDMETHODCALLTYPE D3D11Device::Release() { + return m_container->Release(); + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::QueryInterface(REFIID riid, void** ppvObject) { + return m_container->QueryInterface(riid, ppvObject); + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreateBuffer( + const D3D11_BUFFER_DESC* pDesc, + const D3D11_SUBRESOURCE_DATA* pInitialData, + ID3D11Buffer** ppBuffer) { + InitReturnPtr(ppBuffer); + + if (!pDesc) + return E_INVALIDARG; + + D3D11_BUFFER_DESC desc = *pDesc; + HRESULT hr = D3D11Buffer::NormalizeBufferProperties(&desc); + + if (FAILED(hr)) + return hr; + + if (!ppBuffer) + return S_FALSE; + + try { + const Com buffer = new D3D11Buffer(this, &desc); + m_initializer->InitBuffer(buffer.ptr(), pInitialData); + *ppBuffer = buffer.ref(); + return S_OK; + } catch (const DxvkError& e) { + Logger::err(e.message()); + return E_INVALIDARG; + } + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreateTexture1D( + const D3D11_TEXTURE1D_DESC* pDesc, + const D3D11_SUBRESOURCE_DATA* pInitialData, + ID3D11Texture1D** ppTexture1D) { + InitReturnPtr(ppTexture1D); + + if (!pDesc) + return E_INVALIDARG; + + D3D11_COMMON_TEXTURE_DESC desc; + desc.Width = pDesc->Width; + desc.Height = 1; + desc.Depth = 1; + desc.MipLevels = pDesc->MipLevels; + desc.ArraySize = pDesc->ArraySize; + desc.Format = pDesc->Format; + desc.SampleDesc = DXGI_SAMPLE_DESC { 1, 0 }; + desc.Usage = pDesc->Usage; + desc.BindFlags = pDesc->BindFlags; + desc.CPUAccessFlags = pDesc->CPUAccessFlags; + desc.MiscFlags = pDesc->MiscFlags; + desc.TextureLayout = D3D11_TEXTURE_LAYOUT_UNDEFINED; + + HRESULT hr = D3D11CommonTexture::NormalizeTextureProperties(&desc); + + if (FAILED(hr)) + return hr; + + if (!ppTexture1D) + return S_FALSE; + + try { + const Com texture = new D3D11Texture1D(this, &desc); + m_initializer->InitTexture(texture->GetCommonTexture(), pInitialData); + *ppTexture1D = texture.ref(); + return S_OK; + } catch (const DxvkError& e) { + Logger::err(e.message()); + return E_INVALIDARG; + } + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreateTexture2D( + const D3D11_TEXTURE2D_DESC* pDesc, + const D3D11_SUBRESOURCE_DATA* pInitialData, + ID3D11Texture2D** ppTexture2D) { + InitReturnPtr(ppTexture2D); + + if (!pDesc) + return E_INVALIDARG; + + D3D11_TEXTURE2D_DESC1 desc; + desc.Width = pDesc->Width; + desc.Height = pDesc->Height; + desc.MipLevels = pDesc->MipLevels; + desc.ArraySize = pDesc->ArraySize; + desc.Format = pDesc->Format; + desc.SampleDesc = pDesc->SampleDesc; + desc.Usage = pDesc->Usage; + desc.BindFlags = pDesc->BindFlags; + desc.CPUAccessFlags = pDesc->CPUAccessFlags; + desc.MiscFlags = pDesc->MiscFlags; + desc.TextureLayout = D3D11_TEXTURE_LAYOUT_UNDEFINED; + + ID3D11Texture2D1* texture2D = nullptr; + HRESULT hr = CreateTexture2D1(&desc, pInitialData, ppTexture2D ? &texture2D : nullptr); + + if (hr != S_OK) + return hr; + + *ppTexture2D = texture2D; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreateTexture2D1( + const D3D11_TEXTURE2D_DESC1* pDesc, + const D3D11_SUBRESOURCE_DATA* pInitialData, + ID3D11Texture2D1** ppTexture2D) { + InitReturnPtr(ppTexture2D); + + if (!pDesc) + return E_INVALIDARG; + + D3D11_COMMON_TEXTURE_DESC desc; + desc.Width = pDesc->Width; + desc.Height = pDesc->Height; + desc.Depth = 1; + desc.MipLevels = pDesc->MipLevels; + desc.ArraySize = pDesc->ArraySize; + desc.Format = pDesc->Format; + desc.SampleDesc = pDesc->SampleDesc; + desc.Usage = pDesc->Usage; + desc.BindFlags = pDesc->BindFlags; + desc.CPUAccessFlags = pDesc->CPUAccessFlags; + desc.MiscFlags = pDesc->MiscFlags; + desc.TextureLayout = pDesc->TextureLayout; + + HRESULT hr = D3D11CommonTexture::NormalizeTextureProperties(&desc); + + if (FAILED(hr)) + return hr; + + if (!ppTexture2D) + return S_FALSE; + + try { + Com texture = new D3D11Texture2D(this, &desc, nullptr); + m_initializer->InitTexture(texture->GetCommonTexture(), pInitialData); + *ppTexture2D = texture.ref(); + return S_OK; + } catch (const DxvkError& e) { + Logger::err(e.message()); + return E_INVALIDARG; + } + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreateTexture3D( + const D3D11_TEXTURE3D_DESC* pDesc, + const D3D11_SUBRESOURCE_DATA* pInitialData, + ID3D11Texture3D** ppTexture3D) { + InitReturnPtr(ppTexture3D); + + if (!pDesc) + return E_INVALIDARG; + + D3D11_TEXTURE3D_DESC1 desc; + desc.Width = pDesc->Width; + desc.Height = pDesc->Height; + desc.Depth = pDesc->Depth; + desc.MipLevels = pDesc->MipLevels; + desc.Format = pDesc->Format; + desc.Usage = pDesc->Usage; + desc.BindFlags = pDesc->BindFlags; + desc.CPUAccessFlags = pDesc->CPUAccessFlags; + desc.MiscFlags = pDesc->MiscFlags; + desc.TextureLayout = D3D11_TEXTURE_LAYOUT_UNDEFINED; + + ID3D11Texture3D1* texture3D = nullptr; + HRESULT hr = CreateTexture3D1(&desc, pInitialData, ppTexture3D ? &texture3D : nullptr); + + if (hr != S_OK) + return hr; + + *ppTexture3D = texture3D; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreateTexture3D1( + const D3D11_TEXTURE3D_DESC1* pDesc, + const D3D11_SUBRESOURCE_DATA* pInitialData, + ID3D11Texture3D1** ppTexture3D) { + InitReturnPtr(ppTexture3D); + + if (!pDesc) + return E_INVALIDARG; + + D3D11_COMMON_TEXTURE_DESC desc; + desc.Width = pDesc->Width; + desc.Height = pDesc->Height; + desc.Depth = pDesc->Depth; + desc.MipLevels = pDesc->MipLevels; + desc.ArraySize = 1; + desc.Format = pDesc->Format; + desc.SampleDesc = DXGI_SAMPLE_DESC { 1, 0 }; + desc.Usage = pDesc->Usage; + desc.BindFlags = pDesc->BindFlags; + desc.CPUAccessFlags = pDesc->CPUAccessFlags; + desc.MiscFlags = pDesc->MiscFlags; + desc.TextureLayout = pDesc->TextureLayout; + + HRESULT hr = D3D11CommonTexture::NormalizeTextureProperties(&desc); + + if (FAILED(hr)) + return hr; + + if (!ppTexture3D) + return S_FALSE; + + try { + Com texture = new D3D11Texture3D(this, &desc); + m_initializer->InitTexture(texture->GetCommonTexture(), pInitialData); + *ppTexture3D = texture.ref(); + return S_OK; + } catch (const DxvkError& e) { + Logger::err(e.message()); + return E_INVALIDARG; + } + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreateShaderResourceView( + ID3D11Resource* pResource, + const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc, + ID3D11ShaderResourceView** ppSRView) { + InitReturnPtr(ppSRView); + + uint32_t plane = GetViewPlaneIndex(pResource, pDesc ? pDesc->Format : DXGI_FORMAT_UNKNOWN); + + D3D11_SHADER_RESOURCE_VIEW_DESC1 desc = pDesc + ? D3D11ShaderResourceView::PromoteDesc(pDesc, plane) + : D3D11_SHADER_RESOURCE_VIEW_DESC1(); + + ID3D11ShaderResourceView1* view = nullptr; + + HRESULT hr = CreateShaderResourceView1(pResource, + pDesc ? &desc : nullptr, + ppSRView ? &view : nullptr); + + if (hr != S_OK) + return hr; + + *ppSRView = view; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreateShaderResourceView1( + ID3D11Resource* pResource, + const D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc, + ID3D11ShaderResourceView1** ppSRView) { + InitReturnPtr(ppSRView); + + if (!pResource) + return E_INVALIDARG; + + D3D11_COMMON_RESOURCE_DESC resourceDesc; + GetCommonResourceDesc(pResource, &resourceDesc); + + // The description is optional. If omitted, we'll create + // a view that covers all subresources of the image. + D3D11_SHADER_RESOURCE_VIEW_DESC1 desc; + + if (!pDesc) { + if (FAILED(D3D11ShaderResourceView::GetDescFromResource(pResource, &desc))) + return E_INVALIDARG; + } else { + desc = *pDesc; + + if (FAILED(D3D11ShaderResourceView::NormalizeDesc(pResource, &desc))) + return E_INVALIDARG; + } + + uint32_t plane = D3D11ShaderResourceView::GetPlaneSlice(&desc); + + if (!CheckResourceViewCompatibility(pResource, D3D11_BIND_SHADER_RESOURCE, desc.Format, plane)) { + Logger::err(str::format("D3D11: Cannot create shader resource view:", + "\n Resource type: ", resourceDesc.Dim, + "\n Resource usage: ", resourceDesc.BindFlags, + "\n Resource format: ", resourceDesc.Format, + "\n View format: ", desc.Format, + "\n View plane: ", plane)); + return E_INVALIDARG; + } + + if (!ppSRView) + return S_FALSE; + + try { + *ppSRView = ref(new D3D11ShaderResourceView(this, pResource, &desc)); + return S_OK; + } catch (const DxvkError& e) { + Logger::err(e.message()); + return E_INVALIDARG; + } + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreateUnorderedAccessView( + ID3D11Resource* pResource, + const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc, + ID3D11UnorderedAccessView** ppUAView) { + InitReturnPtr(ppUAView); + + uint32_t plane = GetViewPlaneIndex(pResource, pDesc ? pDesc->Format : DXGI_FORMAT_UNKNOWN); + + D3D11_UNORDERED_ACCESS_VIEW_DESC1 desc = pDesc + ? D3D11UnorderedAccessView::PromoteDesc(pDesc, plane) + : D3D11_UNORDERED_ACCESS_VIEW_DESC1(); + + ID3D11UnorderedAccessView1* view = nullptr; + + HRESULT hr = CreateUnorderedAccessView1(pResource, + pDesc ? &desc : nullptr, + ppUAView ? &view : nullptr); + + if (hr != S_OK) + return hr; + + *ppUAView = view; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreateUnorderedAccessView1( + ID3D11Resource* pResource, + const D3D11_UNORDERED_ACCESS_VIEW_DESC1* pDesc, + ID3D11UnorderedAccessView1** ppUAView) { + InitReturnPtr(ppUAView); + + if (!pResource) + return E_INVALIDARG; + + D3D11_COMMON_RESOURCE_DESC resourceDesc; + GetCommonResourceDesc(pResource, &resourceDesc); + + // The description is optional. If omitted, we'll create + // a view that covers all subresources of the image. + D3D11_UNORDERED_ACCESS_VIEW_DESC1 desc; + + if (!pDesc) { + if (FAILED(D3D11UnorderedAccessView::GetDescFromResource(pResource, &desc))) + return E_INVALIDARG; + } else { + desc = *pDesc; + + if (FAILED(D3D11UnorderedAccessView::NormalizeDesc(pResource, &desc))) + return E_INVALIDARG; + } + + uint32_t plane = D3D11UnorderedAccessView::GetPlaneSlice(&desc); + + if (!CheckResourceViewCompatibility(pResource, D3D11_BIND_UNORDERED_ACCESS, desc.Format, plane)) { + Logger::err(str::format("D3D11: Cannot create unordered access view:", + "\n Resource type: ", resourceDesc.Dim, + "\n Resource usage: ", resourceDesc.BindFlags, + "\n Resource format: ", resourceDesc.Format, + "\n View format: ", desc.Format, + "\n View plane: ", plane)); + return E_INVALIDARG; + } + + if (!ppUAView) + return S_FALSE; + + try { + auto uav = new D3D11UnorderedAccessView(this, pResource, &desc); + m_initializer->InitUavCounter(uav); + *ppUAView = ref(uav); + return S_OK; + } catch (const DxvkError& e) { + Logger::err(e.message()); + return E_INVALIDARG; + } + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreateRenderTargetView( + ID3D11Resource* pResource, + const D3D11_RENDER_TARGET_VIEW_DESC* pDesc, + ID3D11RenderTargetView** ppRTView) { + InitReturnPtr(ppRTView); + + uint32_t plane = GetViewPlaneIndex(pResource, pDesc ? pDesc->Format : DXGI_FORMAT_UNKNOWN); + + D3D11_RENDER_TARGET_VIEW_DESC1 desc = pDesc + ? D3D11RenderTargetView::PromoteDesc(pDesc, plane) + : D3D11_RENDER_TARGET_VIEW_DESC1(); + + ID3D11RenderTargetView1* view = nullptr; + + HRESULT hr = CreateRenderTargetView1(pResource, + pDesc ? &desc : nullptr, + ppRTView ? &view : nullptr); + + if (hr != S_OK) + return hr; + + *ppRTView = view; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreateRenderTargetView1( + ID3D11Resource* pResource, + const D3D11_RENDER_TARGET_VIEW_DESC1* pDesc, + ID3D11RenderTargetView1** ppRTView) { + InitReturnPtr(ppRTView); + + if (!pResource) + return E_INVALIDARG; + + // DXVK only supports render target views for image resources + D3D11_COMMON_RESOURCE_DESC resourceDesc; + GetCommonResourceDesc(pResource, &resourceDesc); + + if (resourceDesc.Dim == D3D11_RESOURCE_DIMENSION_BUFFER) { + Logger::warn("D3D11: Cannot create render target view for a buffer"); + return S_OK; // It is required to run Battlefield 3 and Battlefield 4. + } + + // The view description is optional. If not defined, it + // will use the resource's format and all array layers. + D3D11_RENDER_TARGET_VIEW_DESC1 desc; + + if (!pDesc) { + if (FAILED(D3D11RenderTargetView::GetDescFromResource(pResource, &desc))) + return E_INVALIDARG; + } else { + desc = *pDesc; + + if (FAILED(D3D11RenderTargetView::NormalizeDesc(pResource, &desc))) + return E_INVALIDARG; + } + + uint32_t plane = D3D11RenderTargetView::GetPlaneSlice(&desc); + + if (!CheckResourceViewCompatibility(pResource, D3D11_BIND_RENDER_TARGET, desc.Format, plane)) { + Logger::err(str::format("D3D11: Cannot create render target view:", + "\n Resource type: ", resourceDesc.Dim, + "\n Resource usage: ", resourceDesc.BindFlags, + "\n Resource format: ", resourceDesc.Format, + "\n View format: ", desc.Format, + "\n View plane: ", plane)); + return E_INVALIDARG; + } + + if (!ppRTView) + return S_FALSE; + + try { + *ppRTView = ref(new D3D11RenderTargetView(this, pResource, &desc)); + return S_OK; + } catch (const DxvkError& e) { + Logger::err(e.message()); + return E_INVALIDARG; + } + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreateDepthStencilView( + ID3D11Resource* pResource, + const D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc, + ID3D11DepthStencilView** ppDepthStencilView) { + InitReturnPtr(ppDepthStencilView); + + if (pResource == nullptr) + return E_INVALIDARG; + + D3D11_COMMON_RESOURCE_DESC resourceDesc; + GetCommonResourceDesc(pResource, &resourceDesc); + + // The view description is optional. If not defined, it + // will use the resource's format and all array layers. + D3D11_DEPTH_STENCIL_VIEW_DESC desc; + + if (pDesc == nullptr) { + if (FAILED(D3D11DepthStencilView::GetDescFromResource(pResource, &desc))) + return E_INVALIDARG; + } else { + desc = *pDesc; + + if (FAILED(D3D11DepthStencilView::NormalizeDesc(pResource, &desc))) + return E_INVALIDARG; + } + + if (!CheckResourceViewCompatibility(pResource, D3D11_BIND_DEPTH_STENCIL, desc.Format, 0)) { + Logger::err(str::format("D3D11: Cannot create depth-stencil view:", + "\n Resource type: ", resourceDesc.Dim, + "\n Resource usage: ", resourceDesc.BindFlags, + "\n Resource format: ", resourceDesc.Format, + "\n View format: ", desc.Format)); + return E_INVALIDARG; + } + + if (ppDepthStencilView == nullptr) + return S_FALSE; + + try { + *ppDepthStencilView = ref(new D3D11DepthStencilView(this, pResource, &desc)); + return S_OK; + } catch (const DxvkError& e) { + Logger::err(e.message()); + return E_INVALIDARG; + } + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreateInputLayout( + const D3D11_INPUT_ELEMENT_DESC* pInputElementDescs, + UINT NumElements, + const void* pShaderBytecodeWithInputSignature, + SIZE_T BytecodeLength, + ID3D11InputLayout** ppInputLayout) { + InitReturnPtr(ppInputLayout); + + if (pInputElementDescs == nullptr) + return E_INVALIDARG; + + try { + DxbcReader dxbcReader(reinterpret_cast( + pShaderBytecodeWithInputSignature), BytecodeLength); + DxbcModule dxbcModule(dxbcReader); + + const Rc inputSignature = dxbcModule.isgn(); + + uint32_t attrMask = 0; + uint32_t bindMask = 0; + + std::array attrList; + std::array bindList; + + for (uint32_t i = 0; i < NumElements; i++) { + const DxbcSgnEntry* entry = inputSignature->find( + pInputElementDescs[i].SemanticName, + pInputElementDescs[i].SemanticIndex, 0); + + if (entry == nullptr) { + Logger::debug(str::format( + "D3D11Device: No such vertex shader semantic: ", + pInputElementDescs[i].SemanticName, + pInputElementDescs[i].SemanticIndex)); + } + + // Create vertex input attribute description + DxvkVertexAttribute attrib; + attrib.location = entry != nullptr ? entry->registerId : 0; + attrib.binding = pInputElementDescs[i].InputSlot; + attrib.format = LookupFormat(pInputElementDescs[i].Format, DXGI_VK_FORMAT_MODE_COLOR).Format; + attrib.offset = pInputElementDescs[i].AlignedByteOffset; + + // The application may choose to let the implementation + // generate the exact vertex layout. In that case we'll + // pack attributes on the same binding in the order they + // are declared, aligning each attribute to four bytes. + const DxvkFormatInfo* formatInfo = imageFormatInfo(attrib.format); + VkDeviceSize alignment = std::min(formatInfo->elementSize, 4); + + if (attrib.offset == D3D11_APPEND_ALIGNED_ELEMENT) { + attrib.offset = 0; + + for (uint32_t j = 1; j <= i; j++) { + const DxvkVertexAttribute& prev = attrList.at(i - j); + + if (prev.binding == attrib.binding) { + attrib.offset = align(prev.offset + imageFormatInfo(prev.format)->elementSize, alignment); + break; + } + } + } else if (attrib.offset & (alignment - 1)) + return E_INVALIDARG; + + attrList.at(i) = attrib; + + // Create vertex input binding description. The + // stride is dynamic state in D3D11 and will be + // set by D3D11DeviceContext::IASetVertexBuffers. + DxvkVertexBinding binding; + binding.binding = pInputElementDescs[i].InputSlot; + binding.fetchRate = pInputElementDescs[i].InstanceDataStepRate; + binding.inputRate = pInputElementDescs[i].InputSlotClass == D3D11_INPUT_PER_INSTANCE_DATA + ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX; + + // Check if the binding was already defined. If so, the + // parameters must be identical (namely, the input rate). + bool bindingDefined = false; + + for (uint32_t j = 0; j < i; j++) { + uint32_t bindingId = attrList.at(j).binding; + + if (binding.binding == bindingId) { + bindingDefined = true; + + if (binding.inputRate != bindList.at(bindingId).inputRate) { + Logger::err(str::format( + "D3D11Device: Conflicting input rate for binding ", + binding.binding)); + return E_INVALIDARG; + } + } + } + + if (!bindingDefined) + bindList.at(binding.binding) = binding; + + if (entry != nullptr) { + attrMask |= 1u << i; + bindMask |= 1u << binding.binding; + } + } + + // Compact the attribute and binding lists to filter + // out attributes and bindings not used by the shader + uint32_t attrCount = CompactSparseList(attrList.data(), attrMask); + uint32_t bindCount = CompactSparseList(bindList.data(), bindMask); + + // Check if there are any semantics defined in the + // shader that are not included in the current input + // layout. + for (auto i = inputSignature->begin(); i != inputSignature->end(); i++) { + bool found = i->systemValue != DxbcSystemValue::None; + + for (uint32_t j = 0; j < attrCount && !found; j++) + found = attrList.at(j).location == i->registerId; + + if (!found) { + Logger::warn(str::format( + "D3D11Device: Vertex input '", + i->semanticName, i->semanticIndex, + "' not defined by input layout")); + } + } + + // Create the actual input layout object + // if the application requests it. + if (ppInputLayout != nullptr) { + *ppInputLayout = ref( + new D3D11InputLayout(this, + attrCount, attrList.data(), + bindCount, bindList.data())); + } + + return S_OK; + } catch (const DxvkError& e) { + Logger::err(e.message()); + return E_INVALIDARG; + } + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreateVertexShader( + const void* pShaderBytecode, + SIZE_T BytecodeLength, + ID3D11ClassLinkage* pClassLinkage, + ID3D11VertexShader** ppVertexShader) { + InitReturnPtr(ppVertexShader); + D3D11CommonShader module; + + DxbcModuleInfo moduleInfo; + moduleInfo.options = m_dxbcOptions; + moduleInfo.tess = nullptr; + moduleInfo.xfb = nullptr; + + Sha1Hash hash = Sha1Hash::compute( + pShaderBytecode, BytecodeLength); + + HRESULT hr = CreateShaderModule(&module, + DxvkShaderKey(VK_SHADER_STAGE_VERTEX_BIT, hash), + pShaderBytecode, BytecodeLength, pClassLinkage, + &moduleInfo); + + if (FAILED(hr)) + return hr; + + if (!ppVertexShader) + return S_FALSE; + + *ppVertexShader = ref(new D3D11VertexShader(this, module)); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreateGeometryShader( + const void* pShaderBytecode, + SIZE_T BytecodeLength, + ID3D11ClassLinkage* pClassLinkage, + ID3D11GeometryShader** ppGeometryShader) { + InitReturnPtr(ppGeometryShader); + D3D11CommonShader module; + + DxbcModuleInfo moduleInfo; + moduleInfo.options = m_dxbcOptions; + moduleInfo.tess = nullptr; + moduleInfo.xfb = nullptr; + + Sha1Hash hash = Sha1Hash::compute( + pShaderBytecode, BytecodeLength); + + HRESULT hr = CreateShaderModule(&module, + DxvkShaderKey(VK_SHADER_STAGE_GEOMETRY_BIT, hash), + pShaderBytecode, BytecodeLength, pClassLinkage, + &moduleInfo); + + if (FAILED(hr)) + return hr; + + if (!ppGeometryShader) + return S_FALSE; + + *ppGeometryShader = ref(new D3D11GeometryShader(this, module)); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreateGeometryShaderWithStreamOutput( + const void* pShaderBytecode, + SIZE_T BytecodeLength, + const D3D11_SO_DECLARATION_ENTRY* pSODeclaration, + UINT NumEntries, + const UINT* pBufferStrides, + UINT NumStrides, + UINT RasterizedStream, + ID3D11ClassLinkage* pClassLinkage, + ID3D11GeometryShader** ppGeometryShader) { + InitReturnPtr(ppGeometryShader); + D3D11CommonShader module; + + if (!m_dxvkDevice->features().extTransformFeedback.transformFeedback) + return DXGI_ERROR_INVALID_CALL; + + // Zero-init some counterss so that we can increment + // them while walking over the stream output entries + DxbcXfbInfo xfb = { }; + + for (uint32_t i = 0; i < NumEntries; i++) { + const D3D11_SO_DECLARATION_ENTRY* so = &pSODeclaration[i]; + + if (so->OutputSlot >= D3D11_SO_BUFFER_SLOT_COUNT) + return E_INVALIDARG; + + if (so->SemanticName != nullptr) { + if (so->Stream >= D3D11_SO_BUFFER_SLOT_COUNT + || so->StartComponent >= 4 + || so->ComponentCount < 1 + || so->ComponentCount > 4) + return E_INVALIDARG; + + DxbcXfbEntry* entry = &xfb.entries[xfb.entryCount++]; + entry->semanticName = so->SemanticName; + entry->semanticIndex = so->SemanticIndex; + entry->componentIndex = so->StartComponent; + entry->componentCount = so->ComponentCount; + entry->streamId = so->Stream; + entry->bufferId = so->OutputSlot; + entry->offset = xfb.strides[so->OutputSlot]; + } + + xfb.strides[so->OutputSlot] += so->ComponentCount * sizeof(uint32_t); + } + + // If necessary, override the buffer strides + for (uint32_t i = 0; i < NumStrides; i++) + xfb.strides[i] = pBufferStrides[i]; + + // Set stream to rasterize, if any + xfb.rasterizedStream = -1; + + if (RasterizedStream != D3D11_SO_NO_RASTERIZED_STREAM) + Logger::err("D3D11: CreateGeometryShaderWithStreamOutput: Rasterized stream not supported"); + + // Compute hash from both the xfb info and the source + // code, because both influence the generated code + DxbcXfbInfo hashXfb = xfb; + + std::vector chunks = {{ + { pShaderBytecode, BytecodeLength }, + { &hashXfb, sizeof(hashXfb) }, + }}; + + for (uint32_t i = 0; i < hashXfb.entryCount; i++) { + const char* semantic = hashXfb.entries[i].semanticName; + + if (semantic) { + chunks.push_back({ semantic, std::strlen(semantic) }); + hashXfb.entries[i].semanticName = nullptr; + } + } + + Sha1Hash hash = Sha1Hash::compute(chunks.size(), chunks.data()); + + // Create the actual shader module + DxbcModuleInfo moduleInfo; + moduleInfo.options = m_dxbcOptions; + moduleInfo.tess = nullptr; + moduleInfo.xfb = &xfb; + + HRESULT hr = CreateShaderModule(&module, + DxvkShaderKey(VK_SHADER_STAGE_GEOMETRY_BIT, hash), + pShaderBytecode, BytecodeLength, pClassLinkage, + &moduleInfo); + + if (FAILED(hr)) + return E_INVALIDARG; + + if (!ppGeometryShader) + return S_FALSE; + + *ppGeometryShader = ref(new D3D11GeometryShader(this, module)); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreatePixelShader( + const void* pShaderBytecode, + SIZE_T BytecodeLength, + ID3D11ClassLinkage* pClassLinkage, + ID3D11PixelShader** ppPixelShader) { + InitReturnPtr(ppPixelShader); + D3D11CommonShader module; + + DxbcModuleInfo moduleInfo; + moduleInfo.options = m_dxbcOptions; + moduleInfo.tess = nullptr; + moduleInfo.xfb = nullptr; + + Sha1Hash hash = Sha1Hash::compute( + pShaderBytecode, BytecodeLength); + + + HRESULT hr = CreateShaderModule(&module, + DxvkShaderKey(VK_SHADER_STAGE_FRAGMENT_BIT, hash), + pShaderBytecode, BytecodeLength, pClassLinkage, + &moduleInfo); + + if (FAILED(hr)) + return hr; + + if (!ppPixelShader) + return S_FALSE; + + *ppPixelShader = ref(new D3D11PixelShader(this, module)); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreateHullShader( + const void* pShaderBytecode, + SIZE_T BytecodeLength, + ID3D11ClassLinkage* pClassLinkage, + ID3D11HullShader** ppHullShader) { + InitReturnPtr(ppHullShader); + D3D11CommonShader module; + + DxbcTessInfo tessInfo; + tessInfo.maxTessFactor = float(m_d3d11Options.maxTessFactor); + + DxbcModuleInfo moduleInfo; + moduleInfo.options = m_dxbcOptions; + moduleInfo.tess = nullptr; + moduleInfo.xfb = nullptr; + + if (tessInfo.maxTessFactor >= 8.0f) + moduleInfo.tess = &tessInfo; + + Sha1Hash hash = Sha1Hash::compute( + pShaderBytecode, BytecodeLength); + + HRESULT hr = CreateShaderModule(&module, + DxvkShaderKey(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, hash), + pShaderBytecode, BytecodeLength, pClassLinkage, &moduleInfo); + + if (FAILED(hr)) + return hr; + + if (!ppHullShader) + return S_FALSE; + + *ppHullShader = ref(new D3D11HullShader(this, module)); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreateDomainShader( + const void* pShaderBytecode, + SIZE_T BytecodeLength, + ID3D11ClassLinkage* pClassLinkage, + ID3D11DomainShader** ppDomainShader) { + InitReturnPtr(ppDomainShader); + D3D11CommonShader module; + + DxbcModuleInfo moduleInfo; + moduleInfo.options = m_dxbcOptions; + moduleInfo.tess = nullptr; + moduleInfo.xfb = nullptr; + + Sha1Hash hash = Sha1Hash::compute( + pShaderBytecode, BytecodeLength); + + HRESULT hr = CreateShaderModule(&module, + DxvkShaderKey(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, hash), + pShaderBytecode, BytecodeLength, pClassLinkage, &moduleInfo); + + if (FAILED(hr)) + return hr; + + if (ppDomainShader == nullptr) + return S_FALSE; + + *ppDomainShader = ref(new D3D11DomainShader(this, module)); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreateComputeShader( + const void* pShaderBytecode, + SIZE_T BytecodeLength, + ID3D11ClassLinkage* pClassLinkage, + ID3D11ComputeShader** ppComputeShader) { + InitReturnPtr(ppComputeShader); + D3D11CommonShader module; + + DxbcModuleInfo moduleInfo; + moduleInfo.options = m_dxbcOptions; + moduleInfo.tess = nullptr; + moduleInfo.xfb = nullptr; + + Sha1Hash hash = Sha1Hash::compute( + pShaderBytecode, BytecodeLength); + + HRESULT hr = CreateShaderModule(&module, + DxvkShaderKey(VK_SHADER_STAGE_COMPUTE_BIT, hash), + pShaderBytecode, BytecodeLength, pClassLinkage, + &moduleInfo); + + if (FAILED(hr)) + return hr; + + if (!ppComputeShader) + return S_FALSE; + + *ppComputeShader = ref(new D3D11ComputeShader(this, module)); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreateClassLinkage(ID3D11ClassLinkage** ppLinkage) { + *ppLinkage = ref(new D3D11ClassLinkage(this)); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreateBlendState( + const D3D11_BLEND_DESC* pBlendStateDesc, + ID3D11BlendState** ppBlendState) { + InitReturnPtr(ppBlendState); + + if (!pBlendStateDesc) + return E_INVALIDARG; + + D3D11_BLEND_DESC1 desc = D3D11BlendState::PromoteDesc(pBlendStateDesc); + + if (FAILED(D3D11BlendState::NormalizeDesc(&desc))) + return E_INVALIDARG; + + if (ppBlendState != nullptr) { + *ppBlendState = m_bsStateObjects.Create(this, desc); + return S_OK; + } return S_FALSE; + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreateBlendState1( + const D3D11_BLEND_DESC1* pBlendStateDesc, + ID3D11BlendState1** ppBlendState) { + InitReturnPtr(ppBlendState); + + if (!pBlendStateDesc) + return E_INVALIDARG; + + D3D11_BLEND_DESC1 desc = *pBlendStateDesc; + + if (FAILED(D3D11BlendState::NormalizeDesc(&desc))) + return E_INVALIDARG; + + if (ppBlendState != nullptr) { + *ppBlendState = m_bsStateObjects.Create(this, desc); + return S_OK; + } return S_FALSE; + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreateDepthStencilState( + const D3D11_DEPTH_STENCIL_DESC* pDepthStencilDesc, + ID3D11DepthStencilState** ppDepthStencilState) { + InitReturnPtr(ppDepthStencilState); + + if (!pDepthStencilDesc) + return E_INVALIDARG; + + D3D11_DEPTH_STENCIL_DESC desc = *pDepthStencilDesc; + + if (FAILED(D3D11DepthStencilState::NormalizeDesc(&desc))) + return E_INVALIDARG; + + if (ppDepthStencilState != nullptr) { + *ppDepthStencilState = m_dsStateObjects.Create(this, desc); + return S_OK; + } return S_FALSE; + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreateRasterizerState( + const D3D11_RASTERIZER_DESC* pRasterizerDesc, + ID3D11RasterizerState** ppRasterizerState) { + InitReturnPtr(ppRasterizerState); + + if (!pRasterizerDesc) + return E_INVALIDARG; + + D3D11_RASTERIZER_DESC2 desc = D3D11RasterizerState::PromoteDesc(pRasterizerDesc); + + if (FAILED(D3D11RasterizerState::NormalizeDesc(&desc))) + return E_INVALIDARG; + + if (!ppRasterizerState) + return S_FALSE; + + *ppRasterizerState = m_rsStateObjects.Create(this, desc); + return S_OK; + } + + + HRESULT D3D11Device::CreateRasterizerState1( + const D3D11_RASTERIZER_DESC1* pRasterizerDesc, + ID3D11RasterizerState1** ppRasterizerState) { + InitReturnPtr(ppRasterizerState); + + if (!pRasterizerDesc) + return E_INVALIDARG; + + D3D11_RASTERIZER_DESC2 desc = D3D11RasterizerState::PromoteDesc(pRasterizerDesc); + + if (FAILED(D3D11RasterizerState::NormalizeDesc(&desc))) + return E_INVALIDARG; + + if (!ppRasterizerState) + return S_FALSE; + + *ppRasterizerState = m_rsStateObjects.Create(this, desc); + return S_OK; + } + + + HRESULT D3D11Device::CreateRasterizerState2( + const D3D11_RASTERIZER_DESC2* pRasterizerDesc, + ID3D11RasterizerState2** ppRasterizerState) { + InitReturnPtr(ppRasterizerState); + + if (!pRasterizerDesc) + return E_INVALIDARG; + + D3D11_RASTERIZER_DESC2 desc = *pRasterizerDesc; + + if (FAILED(D3D11RasterizerState::NormalizeDesc(&desc))) + return E_INVALIDARG; + + if (desc.ConservativeRaster != D3D11_CONSERVATIVE_RASTERIZATION_MODE_OFF + && !m_dxvkDevice->extensions().extConservativeRasterization) + return E_INVALIDARG; + + if (!ppRasterizerState) + return S_FALSE; + + *ppRasterizerState = m_rsStateObjects.Create(this, desc); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreateSamplerState( + const D3D11_SAMPLER_DESC* pSamplerDesc, + ID3D11SamplerState** ppSamplerState) { + InitReturnPtr(ppSamplerState); + + if (pSamplerDesc == nullptr) + return E_INVALIDARG; + + D3D11_SAMPLER_DESC desc = *pSamplerDesc; + + if (FAILED(D3D11SamplerState::NormalizeDesc(&desc))) + return E_INVALIDARG; + + if (ppSamplerState == nullptr) + return S_FALSE; + + try { + *ppSamplerState = m_samplerObjects.Create(this, desc); + return S_OK; + } catch (const DxvkError& e) { + Logger::err(e.message()); + return E_INVALIDARG; + } + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreateQuery( + const D3D11_QUERY_DESC* pQueryDesc, + ID3D11Query** ppQuery) { + InitReturnPtr(ppQuery); + + if (!pQueryDesc) + return E_INVALIDARG; + + D3D11_QUERY_DESC1 desc; + desc.Query = pQueryDesc->Query; + desc.MiscFlags = pQueryDesc->MiscFlags; + desc.ContextType = D3D11_CONTEXT_TYPE_ALL; + + ID3D11Query1* query = nullptr; + HRESULT hr = CreateQuery1(&desc, ppQuery ? &query : nullptr); + + if (hr != S_OK) + return hr; + + *ppQuery = query; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreateQuery1( + const D3D11_QUERY_DESC1* pQueryDesc, + ID3D11Query1** ppQuery) { + InitReturnPtr(ppQuery); + + if (!pQueryDesc) + return E_INVALIDARG; + + HRESULT hr = D3D11Query::ValidateDesc(pQueryDesc); + + if (FAILED(hr)) + return hr; + + if (!ppQuery) + return S_FALSE; + + try { + *ppQuery = ref(new D3D11Query(this, *pQueryDesc)); + return S_OK; + } catch (const DxvkError& e) { + Logger::err(e.message()); + return E_INVALIDARG; + } + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreatePredicate( + const D3D11_QUERY_DESC* pPredicateDesc, + ID3D11Predicate** ppPredicate) { + InitReturnPtr(ppPredicate); + + if (!pPredicateDesc) + return E_INVALIDARG; + + D3D11_QUERY_DESC1 desc; + desc.Query = pPredicateDesc->Query; + desc.MiscFlags = pPredicateDesc->MiscFlags; + desc.ContextType = D3D11_CONTEXT_TYPE_ALL; + + if (desc.Query != D3D11_QUERY_OCCLUSION_PREDICATE) { + Logger::warn(str::format("D3D11: Unhandled predicate type: ", pPredicateDesc->Query)); + return E_INVALIDARG; + } + + if (!ppPredicate) + return S_FALSE; + + try { + *ppPredicate = D3D11Query::AsPredicate( + ref(new D3D11Query(this, desc))); + return S_OK; + } catch (const DxvkError& e) { + Logger::err(e.message()); + return E_INVALIDARG; + } + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreateCounter( + const D3D11_COUNTER_DESC* pCounterDesc, + ID3D11Counter** ppCounter) { + InitReturnPtr(ppCounter); + + Logger::err(str::format("D3D11: Unsupported counter: ", pCounterDesc->Counter)); + return E_INVALIDARG; + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreateDeferredContext( + UINT ContextFlags, + ID3D11DeviceContext** ppDeferredContext) { + *ppDeferredContext = ref(new D3D11DeferredContext(this, m_dxvkDevice, ContextFlags)); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreateDeferredContext1( + UINT ContextFlags, + ID3D11DeviceContext1** ppDeferredContext) { + *ppDeferredContext = ref(new D3D11DeferredContext(this, m_dxvkDevice, ContextFlags)); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreateDeferredContext2( + UINT ContextFlags, + ID3D11DeviceContext2** ppDeferredContext) { + *ppDeferredContext = ref(new D3D11DeferredContext(this, m_dxvkDevice, ContextFlags)); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreateDeferredContext3( + UINT ContextFlags, + ID3D11DeviceContext3** ppDeferredContext) { + *ppDeferredContext = ref(new D3D11DeferredContext(this, m_dxvkDevice, ContextFlags)); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreateDeviceContextState( + UINT Flags, + const D3D_FEATURE_LEVEL* pFeatureLevels, + UINT FeatureLevels, + UINT SDKVersion, + REFIID EmulatedInterface, + D3D_FEATURE_LEVEL* pChosenFeatureLevel, + ID3DDeviceContextState** ppContextState) { + InitReturnPtr(ppContextState); + + if (!pFeatureLevels || FeatureLevels == 0) + return E_INVALIDARG; + + if (EmulatedInterface != __uuidof(ID3D10Device) + && EmulatedInterface != __uuidof(ID3D10Device1) + && EmulatedInterface != __uuidof(ID3D11Device) + && EmulatedInterface != __uuidof(ID3D11Device1)) + return E_INVALIDARG; + + UINT flId; + for (flId = 0; flId < FeatureLevels; flId++) { + if (CheckFeatureLevelSupport(m_dxvkDevice->instance(), m_dxvkAdapter, pFeatureLevels[flId])) + break; + } + + if (flId == FeatureLevels) + return E_INVALIDARG; + + if (pFeatureLevels[flId] > m_featureLevel) + m_featureLevel = pFeatureLevels[flId]; + + if (pChosenFeatureLevel) + *pChosenFeatureLevel = pFeatureLevels[flId]; + + if (!ppContextState) + return S_FALSE; + + *ppContextState = ref(new D3D11DeviceContextState(this)); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CreateFence( + UINT64 InitialValue, + D3D11_FENCE_FLAG Flags, + REFIID riid, + void** ppFence) { + InitReturnPtr(ppFence); + + try { + Com fence = new D3D11Fence(this, InitialValue, Flags, INVALID_HANDLE_VALUE); + return fence->QueryInterface(riid, ppFence); + } catch (const DxvkError& e) { + Logger::err(e.message()); + return E_FAIL; + } + } + + + void STDMETHODCALLTYPE D3D11Device::ReadFromSubresource( + void* pDstData, + UINT DstRowPitch, + UINT DstDepthPitch, + ID3D11Resource* pSrcResource, + UINT SrcSubresource, + const D3D11_BOX* pSrcBox) { + CopySubresourceData( + pDstData, DstRowPitch, DstDepthPitch, + pSrcResource, SrcSubresource, pSrcBox); + } + + + void STDMETHODCALLTYPE D3D11Device::WriteToSubresource( + ID3D11Resource* pDstResource, + UINT DstSubresource, + const D3D11_BOX* pDstBox, + const void* pSrcData, + UINT SrcRowPitch, + UINT SrcDepthPitch) { + CopySubresourceData( + pSrcData, SrcRowPitch, SrcRowPitch, + pDstResource, DstSubresource, pDstBox); + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::OpenSharedResource( + HANDLE hResource, + REFIID ReturnedInterface, + void** ppResource) { + return OpenSharedResourceGeneric( + hResource, ReturnedInterface, ppResource); + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::OpenSharedResource1( + HANDLE hResource, + REFIID ReturnedInterface, + void** ppResource) { + return OpenSharedResourceGeneric( + hResource, ReturnedInterface, ppResource); + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::OpenSharedResourceByName( + LPCWSTR lpName, + DWORD dwDesiredAccess, + REFIID returnedInterface, + void** ppResource) { + InitReturnPtr(ppResource); + + Logger::err("D3D11Device::OpenSharedResourceByName: Not implemented"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::OpenSharedFence( + HANDLE hFence, + REFIID ReturnedInterface, + void** ppFence) { + InitReturnPtr(ppFence); + + if (ppFence == nullptr) + return S_FALSE; + + try { + Com fence = new D3D11Fence(this, 0, D3D11_FENCE_FLAG_SHARED, hFence); + return fence->QueryInterface(ReturnedInterface, ppFence); + } catch (const DxvkError& e) { + Logger::err(e.message()); + return E_FAIL; + } + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CheckFormatSupport( + DXGI_FORMAT Format, + UINT* pFormatSupport) { + return GetFormatSupportFlags(Format, pFormatSupport, nullptr); + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CheckMultisampleQualityLevels( + DXGI_FORMAT Format, + UINT SampleCount, + UINT* pNumQualityLevels) { + return CheckMultisampleQualityLevels1(Format, SampleCount, 0, pNumQualityLevels); + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CheckMultisampleQualityLevels1( + DXGI_FORMAT Format, + UINT SampleCount, + UINT Flags, + UINT* pNumQualityLevels) { + // There are many error conditions, so we'll just assume + // that we will fail and return a non-zero value in case + // the device does actually support the format. + if (!pNumQualityLevels) + return E_INVALIDARG; + + // We don't support tiled resources, but it's unclear what + // we are supposed to return in this case. Be conservative. + if (Flags) { + *pNumQualityLevels = 0; + return E_FAIL; + } + + // For some reason, we can query DXGI_FORMAT_UNKNOWN + if (Format == DXGI_FORMAT_UNKNOWN) { + *pNumQualityLevels = SampleCount == 1 ? 1 : 0; + return SampleCount ? S_OK : E_FAIL; + } + + // All other unknown formats should result in an error return. + VkFormat format = LookupFormat(Format, DXGI_VK_FORMAT_MODE_ANY).Format; + + if (format == VK_FORMAT_UNDEFINED) + return E_INVALIDARG; + + // Zero-init now, leave value undefined otherwise. + // This does actually match native D3D11 behaviour. + *pNumQualityLevels = 0; + + // Non-power of two sample counts are not supported, but querying + // support for them is legal, so we return zero quality levels. + VkSampleCountFlagBits sampleCountFlag = VK_SAMPLE_COUNT_1_BIT; + + if (FAILED(DecodeSampleCount(SampleCount, &sampleCountFlag))) + return SampleCount && SampleCount <= 32 ? S_OK : E_FAIL; + + // Check if the device supports the given combination of format + // and sample count. D3D exposes the opaque concept of quality + // levels to the application, we'll just define one such level. + VkImageFormatProperties formatProps; + + VkResult status = m_dxvkAdapter->imageFormatProperties( + format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, + VK_IMAGE_USAGE_SAMPLED_BIT, 0, formatProps); + + if ((status == VK_SUCCESS) && (formatProps.sampleCounts & sampleCountFlag)) + *pNumQualityLevels = 1; + return S_OK; + } + + + void STDMETHODCALLTYPE D3D11Device::CheckCounterInfo(D3D11_COUNTER_INFO* pCounterInfo) { + // We basically don't support counters + pCounterInfo->LastDeviceDependentCounter = D3D11_COUNTER(0); + pCounterInfo->NumSimultaneousCounters = 0; + pCounterInfo->NumDetectableParallelUnits = 0; + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CheckCounter( + const D3D11_COUNTER_DESC* pDesc, + D3D11_COUNTER_TYPE* pType, + UINT* pActiveCounters, + LPSTR szName, + UINT* pNameLength, + LPSTR szUnits, + UINT* pUnitsLength, + LPSTR szDescription, + UINT* pDescriptionLength) { + Logger::err("D3D11: Counters not supported"); + return E_INVALIDARG; + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::CheckFeatureSupport( + D3D11_FEATURE Feature, + void* pFeatureSupportData, + UINT FeatureSupportDataSize) { + switch (Feature) { + case D3D11_FEATURE_THREADING: { + auto info = static_cast(pFeatureSupportData); + + if (FeatureSupportDataSize != sizeof(*info)) + return E_INVALIDARG; + + // We report native support for command lists here so that we do not actually + // have to re-implement the UpdateSubresource bug from the D3D11 runtime, see + // https://msdn.microsoft.com/en-us/library/windows/desktop/ff476486(v=vs.85).aspx) + info->DriverConcurrentCreates = TRUE; + info->DriverCommandLists = TRUE; + } return S_OK; + + case D3D11_FEATURE_DOUBLES: { + auto info = static_cast(pFeatureSupportData); + + if (FeatureSupportDataSize != sizeof(*info)) + return E_INVALIDARG; + + info->DoublePrecisionFloatShaderOps = m_dxvkDevice->features().core.features.shaderFloat64 + && m_dxvkDevice->features().core.features.shaderInt64; + } return S_OK; + + case D3D11_FEATURE_FORMAT_SUPPORT: { + auto info = static_cast(pFeatureSupportData); + + if (FeatureSupportDataSize != sizeof(*info)) + return E_INVALIDARG; + + return GetFormatSupportFlags(info->InFormat, &info->OutFormatSupport, nullptr); + } return S_OK; + + case D3D11_FEATURE_FORMAT_SUPPORT2: { + auto info = static_cast(pFeatureSupportData); + + if (FeatureSupportDataSize != sizeof(*info)) + return E_INVALIDARG; + + return GetFormatSupportFlags(info->InFormat, nullptr, &info->OutFormatSupport2); + } return S_OK; + + case D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS: { + auto info = static_cast(pFeatureSupportData); + + if (FeatureSupportDataSize != sizeof(*info)) + return E_INVALIDARG; + + info->ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x = TRUE; + } return S_OK; + + case D3D11_FEATURE_D3D11_OPTIONS: { + auto info = static_cast(pFeatureSupportData); + + if (FeatureSupportDataSize != sizeof(*info)) + return E_INVALIDARG; + + // https://msdn.microsoft.com/en-us/library/windows/desktop/hh404457(v=vs.85).aspx + const auto& features = m_dxvkDevice->features(); + + info->OutputMergerLogicOp = features.core.features.logicOp; + info->UAVOnlyRenderingForcedSampleCount = features.core.features.variableMultisampleRate; + info->DiscardAPIsSeenByDriver = TRUE; + info->FlagsForUpdateAndCopySeenByDriver = TRUE; + info->ClearView = TRUE; + info->CopyWithOverlap = TRUE; + info->ConstantBufferPartialUpdate = TRUE; + info->ConstantBufferOffsetting = TRUE; + info->MapNoOverwriteOnDynamicConstantBuffer = TRUE; + info->MapNoOverwriteOnDynamicBufferSRV = TRUE; + info->MultisampleRTVWithForcedSampleCountOne = TRUE; /* not really */ + info->SAD4ShaderInstructions = TRUE; + info->ExtendedDoublesShaderInstructions = TRUE; + info->ExtendedResourceSharing = TRUE; /* not really */ + } return S_OK; + + case D3D11_FEATURE_ARCHITECTURE_INFO: { + auto info = static_cast(pFeatureSupportData); + + if (FeatureSupportDataSize != sizeof(*info)) + return E_INVALIDARG; + + info->TileBasedDeferredRenderer = FALSE; + } return S_OK; + + case D3D11_FEATURE_D3D9_OPTIONS: { + auto info = static_cast(pFeatureSupportData); + + if (FeatureSupportDataSize != sizeof(*info)) + return E_INVALIDARG; + + info->FullNonPow2TextureSupport = TRUE; + } return S_OK; + + case D3D11_FEATURE_SHADER_MIN_PRECISION_SUPPORT: { + auto info = static_cast(pFeatureSupportData); + + if (FeatureSupportDataSize != sizeof(*info)) + return E_INVALIDARG; + + // Report that we only support full 32-bit operations + info->PixelShaderMinPrecision = 0; + info->AllOtherShaderStagesMinPrecision = 0; + } return S_OK; + + case D3D11_FEATURE_D3D9_SHADOW_SUPPORT: { + auto info = static_cast(pFeatureSupportData); + + if (FeatureSupportDataSize != sizeof(*info)) + return E_INVALIDARG; + + info->SupportsDepthAsTextureWithLessEqualComparisonFilter = TRUE; + } return S_OK; + + case D3D11_FEATURE_D3D11_OPTIONS1: { + auto info = static_cast(pFeatureSupportData); + + if (FeatureSupportDataSize != sizeof(*info)) + return E_INVALIDARG; + + // Min/Max filtering requires Tiled Resources Tier 2 for some reason, + // so we cannot support it even though Vulkan exposes this feature + info->TiledResourcesTier = D3D11_TILED_RESOURCES_NOT_SUPPORTED; + info->MinMaxFiltering = FALSE; + info->ClearViewAlsoSupportsDepthOnlyFormats = TRUE; + info->MapOnDefaultBuffers = TRUE; + } return S_OK; + + case D3D11_FEATURE_D3D9_SIMPLE_INSTANCING_SUPPORT: { + auto info = static_cast(pFeatureSupportData); + + if (FeatureSupportDataSize != sizeof(*info)) + return E_INVALIDARG; + + info->SimpleInstancingSupported = TRUE; + } return S_OK; + + case D3D11_FEATURE_MARKER_SUPPORT: { + auto info = static_cast(pFeatureSupportData); + + if (FeatureSupportDataSize != sizeof(*info)) + return E_INVALIDARG; + + info->Profile = FALSE; + } return S_OK; + + case D3D11_FEATURE_D3D9_OPTIONS1: { + auto info = static_cast(pFeatureSupportData); + + if (FeatureSupportDataSize != sizeof(*info)) + return E_INVALIDARG; + + info->FullNonPow2TextureSupported = TRUE; + info->DepthAsTextureWithLessEqualComparisonFilterSupported = TRUE; + info->SimpleInstancingSupported = TRUE; + info->TextureCubeFaceRenderTargetWithNonCubeDepthStencilSupported = TRUE; + } return S_OK; + + case D3D11_FEATURE_D3D11_OPTIONS2: { + auto info = static_cast(pFeatureSupportData); + + if (FeatureSupportDataSize != sizeof(*info)) + return E_INVALIDARG; + + const auto& extensions = m_dxvkDevice->extensions(); + const auto& features = m_dxvkDevice->features(); + + info->PSSpecifiedStencilRefSupported = extensions.extShaderStencilExport; + info->TypedUAVLoadAdditionalFormats = features.core.features.shaderStorageImageReadWithoutFormat; + info->ROVsSupported = FALSE; + info->ConservativeRasterizationTier = D3D11_CONSERVATIVE_RASTERIZATION_NOT_SUPPORTED; + info->MapOnDefaultTextures = TRUE; + info->TiledResourcesTier = D3D11_TILED_RESOURCES_NOT_SUPPORTED; + info->StandardSwizzle = FALSE; + info->UnifiedMemoryArchitecture = m_dxvkDevice->isUnifiedMemoryArchitecture(); + + if (m_dxvkDevice->extensions().extConservativeRasterization) { + // We don't have a way to query uncertainty regions, so just check degenerate triangle behaviour + info->ConservativeRasterizationTier = m_dxvkDevice->properties().extConservativeRasterization.degenerateTrianglesRasterized + ? D3D11_CONSERVATIVE_RASTERIZATION_TIER_2 : D3D11_CONSERVATIVE_RASTERIZATION_TIER_1; + } + } return S_OK; + + case D3D11_FEATURE_D3D11_OPTIONS3: { + if (FeatureSupportDataSize != sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS3)) + return E_INVALIDARG; + + const auto& extensions = m_dxvkDevice->extensions(); + + auto info = static_cast(pFeatureSupportData); + info->VPAndRTArrayIndexFromAnyShaderFeedingRasterizer = extensions.extShaderViewportIndexLayer; + } return S_OK; + + case D3D11_FEATURE_GPU_VIRTUAL_ADDRESS_SUPPORT: { + auto info = static_cast(pFeatureSupportData); + + if (FeatureSupportDataSize != sizeof(*info)) + return E_INVALIDARG; + + // These numbers are not accurate, but it should not have any effect on D3D11 apps + info->MaxGPUVirtualAddressBitsPerResource = 32; + info->MaxGPUVirtualAddressBitsPerProcess = 40; + } return S_OK; + + case D3D11_FEATURE_D3D11_OPTIONS4: { + auto info = static_cast(pFeatureSupportData); + + if (FeatureSupportDataSize != sizeof(*info)) + return E_INVALIDARG; + + info->ExtendedNV12SharedTextureSupported = FALSE; + } return S_OK; + + default: + Logger::err(str::format("D3D11Device: CheckFeatureSupport: Unknown feature: ", Feature)); + return E_INVALIDARG; + } + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::GetPrivateData( + REFGUID guid, UINT* pDataSize, void* pData) { + return m_container->GetPrivateData(guid, pDataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::SetPrivateData( + REFGUID guid, UINT DataSize, const void* pData) { + return m_container->SetPrivateData(guid, DataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::SetPrivateDataInterface( + REFGUID guid, const IUnknown* pData) { + return m_container->SetPrivateDataInterface(guid, pData); + } + + + D3D_FEATURE_LEVEL STDMETHODCALLTYPE D3D11Device::GetFeatureLevel() { + return m_featureLevel; + } + + + UINT STDMETHODCALLTYPE D3D11Device::GetCreationFlags() { + return m_featureFlags; + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::GetDeviceRemovedReason() { + VkResult status = m_dxvkDevice->getDeviceStatus(); + + switch (status) { + case VK_SUCCESS: return S_OK; + default: return DXGI_ERROR_DEVICE_RESET; + } + } + + + void STDMETHODCALLTYPE D3D11Device::GetImmediateContext(ID3D11DeviceContext** ppImmediateContext) { + *ppImmediateContext = m_context.ref(); + } + + + void STDMETHODCALLTYPE D3D11Device::GetImmediateContext1(ID3D11DeviceContext1** ppImmediateContext) { + *ppImmediateContext = m_context.ref(); + } + + + void STDMETHODCALLTYPE D3D11Device::GetImmediateContext2(ID3D11DeviceContext2** ppImmediateContext) { + *ppImmediateContext = m_context.ref(); + } + + + void STDMETHODCALLTYPE D3D11Device::GetImmediateContext3(ID3D11DeviceContext3** ppImmediateContext) { + *ppImmediateContext = m_context.ref(); + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::SetExceptionMode(UINT RaiseFlags) { + Logger::err("D3D11Device::SetExceptionMode: Not implemented"); + return E_NOTIMPL; + } + + + UINT STDMETHODCALLTYPE D3D11Device::GetExceptionMode() { + Logger::err("D3D11Device::GetExceptionMode: Not implemented"); + return 0; + } + + + void STDMETHODCALLTYPE D3D11Device::GetResourceTiling( + ID3D11Resource* pTiledResource, + UINT* pNumTilesForEntireResource, + D3D11_PACKED_MIP_DESC* pPackedMipDesc, + D3D11_TILE_SHAPE* pStandardTileShapeForNonPackedMips, + UINT* pNumSubresourceTilings, + UINT FirstSubresourceTilingToGet, + D3D11_SUBRESOURCE_TILING* pSubresourceTilingsForNonPackedMips) { + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::err("D3D11Device::GetResourceTiling: Tiled resources not supported"); + + if (pNumTilesForEntireResource) + *pNumTilesForEntireResource = 0; + + if (pPackedMipDesc) + *pPackedMipDesc = D3D11_PACKED_MIP_DESC(); + + if (pStandardTileShapeForNonPackedMips) + *pStandardTileShapeForNonPackedMips = D3D11_TILE_SHAPE(); + + if (pNumSubresourceTilings) { + if (pSubresourceTilingsForNonPackedMips) { + for (uint32_t i = 0; i < *pNumSubresourceTilings; i++) + pSubresourceTilingsForNonPackedMips[i] = D3D11_SUBRESOURCE_TILING(); + } + + *pNumSubresourceTilings = 0; + } + } + + + HRESULT STDMETHODCALLTYPE D3D11Device::RegisterDeviceRemovedEvent( + HANDLE hEvent, + DWORD* pdwCookie) { + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::err("D3D11Device::RegisterDeviceRemovedEvent: Not implemented"); + + return E_NOTIMPL; + } + + + void STDMETHODCALLTYPE D3D11Device::UnregisterDeviceRemoved( + DWORD dwCookie) { + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::err("D3D11Device::UnregisterDeviceRemovedEvent: Not implemented"); + } + + + DXGI_VK_FORMAT_INFO D3D11Device::LookupFormat( + DXGI_FORMAT Format, + DXGI_VK_FORMAT_MODE Mode) const { + return m_d3d11Formats.GetFormatInfo(Format, Mode); + } + + + DXGI_VK_FORMAT_INFO D3D11Device::LookupPackedFormat( + DXGI_FORMAT Format, + DXGI_VK_FORMAT_MODE Mode) const { + return m_d3d11Formats.GetPackedFormatInfo(Format, Mode); + } + + + DXGI_VK_FORMAT_FAMILY D3D11Device::LookupFamily( + DXGI_FORMAT Format, + DXGI_VK_FORMAT_MODE Mode) const { + return m_d3d11Formats.GetFormatFamily(Format, Mode); + } + + + void D3D11Device::FlushInitContext() { + m_initializer->Flush(); + } + + + bool D3D11Device::CheckFeatureLevelSupport( + const Rc& instance, + const Rc& adapter, + D3D_FEATURE_LEVEL featureLevel) { + if (featureLevel > GetMaxFeatureLevel(instance)) + return false; + + // Check whether all features are supported + const DxvkDeviceFeatures features + = GetDeviceFeatures(adapter, featureLevel); + + if (!adapter->checkFeatureSupport(features)) + return false; + + // TODO also check for required limits + return true; + } + + + DxvkDeviceFeatures D3D11Device::GetDeviceFeatures( + const Rc& adapter, + D3D_FEATURE_LEVEL featureLevel) { + DxvkDeviceFeatures supported = adapter->features(); + DxvkDeviceFeatures enabled = {}; + + enabled.core.features.geometryShader = VK_TRUE; + enabled.core.features.robustBufferAccess = VK_TRUE; + enabled.core.features.shaderStorageImageWriteWithoutFormat = VK_TRUE; + enabled.core.features.depthBounds = supported.core.features.depthBounds; + + enabled.shaderDrawParameters.shaderDrawParameters = VK_TRUE; + + enabled.khrTimelineSemaphore.timelineSemaphore = supported.khrTimelineSemaphore.timelineSemaphore; + + enabled.extMemoryPriority.memoryPriority = supported.extMemoryPriority.memoryPriority; + + enabled.extRobustness2.robustBufferAccess2 = supported.extRobustness2.robustBufferAccess2; + enabled.extRobustness2.robustImageAccess2 = supported.extRobustness2.robustImageAccess2; + enabled.extRobustness2.nullDescriptor = supported.extRobustness2.nullDescriptor; + + enabled.extShaderDemoteToHelperInvocation.shaderDemoteToHelperInvocation = supported.extShaderDemoteToHelperInvocation.shaderDemoteToHelperInvocation; + + enabled.extVertexAttributeDivisor.vertexAttributeInstanceRateDivisor = supported.extVertexAttributeDivisor.vertexAttributeInstanceRateDivisor; + enabled.extVertexAttributeDivisor.vertexAttributeInstanceRateZeroDivisor = supported.extVertexAttributeDivisor.vertexAttributeInstanceRateZeroDivisor; + + if (supported.extCustomBorderColor.customBorderColorWithoutFormat) { + enabled.extCustomBorderColor.customBorderColors = VK_TRUE; + enabled.extCustomBorderColor.customBorderColorWithoutFormat = VK_TRUE; + } + + if (featureLevel >= D3D_FEATURE_LEVEL_9_1) { + enabled.core.features.depthClamp = VK_TRUE; + enabled.core.features.depthBiasClamp = VK_TRUE; + enabled.core.features.fillModeNonSolid = VK_TRUE; + enabled.core.features.pipelineStatisticsQuery = supported.core.features.pipelineStatisticsQuery; + enabled.core.features.sampleRateShading = VK_TRUE; + enabled.core.features.samplerAnisotropy = supported.core.features.samplerAnisotropy; + enabled.core.features.shaderClipDistance = VK_TRUE; + enabled.core.features.shaderCullDistance = VK_TRUE; + enabled.core.features.textureCompressionBC = VK_TRUE; + enabled.extDepthClipEnable.depthClipEnable = supported.extDepthClipEnable.depthClipEnable; + enabled.extHostQueryReset.hostQueryReset = VK_TRUE; + } + + if (featureLevel >= D3D_FEATURE_LEVEL_9_2) { + enabled.core.features.occlusionQueryPrecise = VK_TRUE; + } + + if (featureLevel >= D3D_FEATURE_LEVEL_9_3) { + enabled.core.features.independentBlend = VK_TRUE; + enabled.core.features.multiViewport = VK_TRUE; + } + + if (featureLevel >= D3D_FEATURE_LEVEL_10_0) { + enabled.core.features.fullDrawIndexUint32 = VK_TRUE; + enabled.core.features.logicOp = supported.core.features.logicOp; + enabled.core.features.shaderImageGatherExtended = VK_TRUE; + enabled.core.features.variableMultisampleRate = supported.core.features.variableMultisampleRate; + enabled.extTransformFeedback.transformFeedback = VK_TRUE; + enabled.extTransformFeedback.geometryStreams = VK_TRUE; + } + + if (featureLevel >= D3D_FEATURE_LEVEL_10_1) { + enabled.core.features.dualSrcBlend = VK_TRUE; + enabled.core.features.imageCubeArray = VK_TRUE; + } + + if (featureLevel >= D3D_FEATURE_LEVEL_11_0) { + enabled.core.features.drawIndirectFirstInstance = VK_TRUE; + enabled.core.features.fragmentStoresAndAtomics = VK_TRUE; + enabled.core.features.multiDrawIndirect = VK_TRUE; + enabled.core.features.shaderFloat64 = supported.core.features.shaderFloat64; + enabled.core.features.shaderInt64 = supported.core.features.shaderInt64; + enabled.core.features.shaderStorageImageReadWithoutFormat = supported.core.features.shaderStorageImageReadWithoutFormat; + enabled.core.features.tessellationShader = VK_TRUE; + } + + if (featureLevel >= D3D_FEATURE_LEVEL_11_1) { + enabled.core.features.logicOp = VK_TRUE; + enabled.core.features.variableMultisampleRate = VK_TRUE; + enabled.core.features.vertexPipelineStoresAndAtomics = VK_TRUE; + } + + return enabled; + } + + + HRESULT D3D11Device::CreateShaderModule( + D3D11CommonShader* pShaderModule, + DxvkShaderKey ShaderKey, + const void* pShaderBytecode, + size_t BytecodeLength, + ID3D11ClassLinkage* pClassLinkage, + const DxbcModuleInfo* pModuleInfo) { + if (pClassLinkage != nullptr) + Logger::warn("D3D11Device::CreateShaderModule: Class linkage not supported"); + + D3D11CommonShader commonShader; + + HRESULT hr = m_shaderModules.GetShaderModule(this, + &ShaderKey, pModuleInfo, pShaderBytecode, BytecodeLength, + &commonShader); + + if (FAILED(hr)) + return hr; + + auto shader = commonShader.GetShader(); + + if (shader->flags().test(DxvkShaderFlag::ExportsStencilRef) + && !m_dxvkDevice->extensions().extShaderStencilExport) + return E_INVALIDARG; + + if (shader->flags().test(DxvkShaderFlag::ExportsViewportIndexLayerFromVertexStage) + && !m_dxvkDevice->extensions().extShaderViewportIndexLayer) + return E_INVALIDARG; + + *pShaderModule = std::move(commonShader); + return S_OK; + } + + + HRESULT D3D11Device::GetFormatSupportFlags(DXGI_FORMAT Format, UINT* pFlags1, UINT* pFlags2) const { + const DXGI_VK_FORMAT_INFO fmtMapping = LookupFormat(Format, DXGI_VK_FORMAT_MODE_ANY); + + // Reset output flags preemptively + if (pFlags1 != nullptr) *pFlags1 = 0; + if (pFlags2 != nullptr) *pFlags2 = 0; + + // Unsupported or invalid format + if (Format != DXGI_FORMAT_UNKNOWN && fmtMapping.Format == VK_FORMAT_UNDEFINED) + return E_FAIL; + + // Query Vulkan format properties and supported features for it + const DxvkFormatInfo* fmtProperties = imageFormatInfo(fmtMapping.Format); + + VkFormatProperties fmtSupport = fmtMapping.Format != VK_FORMAT_UNDEFINED + ? m_dxvkAdapter->formatProperties(fmtMapping.Format) + : VkFormatProperties(); + + VkFormatFeatureFlags bufFeatures = fmtSupport.bufferFeatures; + VkFormatFeatureFlags imgFeatures = fmtSupport.optimalTilingFeatures | fmtSupport.linearTilingFeatures; + + // For multi-plane images, we want to check available view formats as well + if (fmtProperties->flags.test(DxvkFormatFlag::MultiPlane)) { + const VkFormatFeatureFlags featureMask + = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT + | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT + | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT + | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT + | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT; + + DXGI_VK_FORMAT_FAMILY formatFamily = LookupFamily(Format, DXGI_VK_FORMAT_MODE_ANY); + + for (uint32_t i = 0; i < formatFamily.FormatCount; i++) { + VkFormatProperties viewFmtSupport = m_dxvkAdapter->formatProperties(formatFamily.Formats[i]); + imgFeatures |= (viewFmtSupport.optimalTilingFeatures | viewFmtSupport.linearTilingFeatures) & featureMask; + } + } + + UINT flags1 = 0; + UINT flags2 = 0; + + // Format can be used for shader resource views with buffers + if (bufFeatures & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT + || Format == DXGI_FORMAT_UNKNOWN) + flags1 |= D3D11_FORMAT_SUPPORT_BUFFER; + + // Format can be used for vertex data + if (bufFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) + flags1 |= D3D11_FORMAT_SUPPORT_IA_VERTEX_BUFFER; + + // Format can be used for index data. Only + // these two formats are supported by D3D11. + if (Format == DXGI_FORMAT_R16_UINT + || Format == DXGI_FORMAT_R32_UINT) + flags1 |= D3D11_FORMAT_SUPPORT_IA_INDEX_BUFFER; + + // These formats are technically irrelevant since + // SO buffers are passed in as raw buffers and not + // as views, but the feature flag exists regardless + if (Format == DXGI_FORMAT_R32_FLOAT + || Format == DXGI_FORMAT_R32_UINT + || Format == DXGI_FORMAT_R32_SINT + || Format == DXGI_FORMAT_R32G32_FLOAT + || Format == DXGI_FORMAT_R32G32_UINT + || Format == DXGI_FORMAT_R32G32_SINT + || Format == DXGI_FORMAT_R32G32B32_FLOAT + || Format == DXGI_FORMAT_R32G32B32_UINT + || Format == DXGI_FORMAT_R32G32B32_SINT + || Format == DXGI_FORMAT_R32G32B32A32_FLOAT + || Format == DXGI_FORMAT_R32G32B32A32_UINT + || Format == DXGI_FORMAT_R32G32B32A32_SINT) + flags1 |= D3D11_FORMAT_SUPPORT_SO_BUFFER; + + if (imgFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT + || imgFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) { + const VkFormat depthFormat = LookupFormat(Format, DXGI_VK_FORMAT_MODE_DEPTH).Format; + + if (GetImageTypeSupport(fmtMapping.Format, VK_IMAGE_TYPE_1D)) flags1 |= D3D11_FORMAT_SUPPORT_TEXTURE1D; + if (GetImageTypeSupport(fmtMapping.Format, VK_IMAGE_TYPE_2D)) flags1 |= D3D11_FORMAT_SUPPORT_TEXTURE2D; + if (GetImageTypeSupport(fmtMapping.Format, VK_IMAGE_TYPE_3D)) flags1 |= D3D11_FORMAT_SUPPORT_TEXTURE3D; + + flags1 |= D3D11_FORMAT_SUPPORT_MIP + | D3D11_FORMAT_SUPPORT_CAST_WITHIN_BIT_LAYOUT; + + // Format can be read + if (imgFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) { + flags1 |= D3D11_FORMAT_SUPPORT_TEXTURECUBE + | D3D11_FORMAT_SUPPORT_SHADER_LOAD + | D3D11_FORMAT_SUPPORT_SHADER_GATHER + | D3D11_FORMAT_SUPPORT_SHADER_SAMPLE + | D3D11_FORMAT_SUPPORT_VIDEO_PROCESSOR_INPUT; + + if (depthFormat != VK_FORMAT_UNDEFINED) { + flags1 |= D3D11_FORMAT_SUPPORT_SHADER_GATHER_COMPARISON + | D3D11_FORMAT_SUPPORT_SHADER_SAMPLE_COMPARISON; + } + } + + // Format is a color format that can be used for rendering + if (imgFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) { + flags1 |= D3D11_FORMAT_SUPPORT_RENDER_TARGET + | D3D11_FORMAT_SUPPORT_MIP_AUTOGEN + | D3D11_FORMAT_SUPPORT_VIDEO_PROCESSOR_OUTPUT; + + if (m_dxvkDevice->features().core.features.logicOp) + flags2 |= D3D11_FORMAT_SUPPORT2_OUTPUT_MERGER_LOGIC_OP; + } + + // Format supports blending when used for rendering + if (imgFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT) + flags1 |= D3D11_FORMAT_SUPPORT_BLENDABLE; + + // Format is a depth-stencil format that can be used for rendering + if (imgFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) + flags1 |= D3D11_FORMAT_SUPPORT_DEPTH_STENCIL; + + // FIXME implement properly. This would require a VkSurface. + if (Format == DXGI_FORMAT_R8G8B8A8_UNORM + || Format == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB + || Format == DXGI_FORMAT_B8G8R8A8_UNORM + || Format == DXGI_FORMAT_B8G8R8A8_UNORM_SRGB + || Format == DXGI_FORMAT_R16G16B16A16_FLOAT + || Format == DXGI_FORMAT_R10G10B10A2_UNORM + || Format == DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM) + flags1 |= D3D11_FORMAT_SUPPORT_DISPLAY; + + // Query multisample support for this format + VkImageFormatProperties imgFmtProperties; + + VkResult status = m_dxvkAdapter->imageFormatProperties(fmtMapping.Format, + VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, + (fmtProperties->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) + ? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT + : VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, + 0, imgFmtProperties); + + if (status == VK_SUCCESS && imgFmtProperties.sampleCounts > VK_SAMPLE_COUNT_1_BIT) { + flags1 |= D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET + | D3D11_FORMAT_SUPPORT_MULTISAMPLE_RESOLVE + | D3D11_FORMAT_SUPPORT_MULTISAMPLE_LOAD; + } + } + + // Format can be used for storage images or storage texel buffers + if ((bufFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT) + && (imgFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)) { + flags1 |= D3D11_FORMAT_SUPPORT_TYPED_UNORDERED_ACCESS_VIEW; + flags2 |= D3D11_FORMAT_SUPPORT2_UAV_TYPED_STORE; + + if (m_dxvkDevice->features().core.features.shaderStorageImageReadWithoutFormat + || Format == DXGI_FORMAT_R32_UINT + || Format == DXGI_FORMAT_R32_SINT + || Format == DXGI_FORMAT_R32_FLOAT) + flags2 |= D3D11_FORMAT_SUPPORT2_UAV_TYPED_LOAD; + + if (Format == DXGI_FORMAT_R32_UINT + || Format == DXGI_FORMAT_R32_SINT) { + flags2 |= D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_ADD + | D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_BITWISE_OPS + | D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_COMPARE_STORE_OR_COMPARE_EXCHANGE + | D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_EXCHANGE; + } + + if (Format == DXGI_FORMAT_R32_SINT) + flags2 |= D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_SIGNED_MIN_OR_MAX; + + if (Format == DXGI_FORMAT_R32_UINT) + flags2 |= D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_UNSIGNED_MIN_OR_MAX; + } + + // Mark everyting as CPU lockable + if (flags1 | flags2) + flags1 |= D3D11_FORMAT_SUPPORT_CPU_LOCKABLE; + + // Write back format support flags + if (pFlags1 != nullptr) *pFlags1 = flags1; + if (pFlags2 != nullptr) *pFlags2 = flags2; + return (pFlags1 && flags1) || (pFlags2 && flags2) ? S_OK : E_FAIL; + } + + + BOOL D3D11Device::GetImageTypeSupport(VkFormat Format, VkImageType Type) const { + VkImageFormatProperties props; + + VkResult status = m_dxvkAdapter->imageFormatProperties( + Format, Type, VK_IMAGE_TILING_OPTIMAL, + VK_IMAGE_USAGE_SAMPLED_BIT, 0, props); + + if (status != VK_SUCCESS) { + status = m_dxvkAdapter->imageFormatProperties( + Format, Type, VK_IMAGE_TILING_LINEAR, + VK_IMAGE_USAGE_SAMPLED_BIT, 0, props); + } + + return status == VK_SUCCESS; + } + + + uint32_t D3D11Device::GetViewPlaneIndex( + ID3D11Resource* pResource, + DXGI_FORMAT ViewFormat) { + auto texture = GetCommonTexture(pResource); + + if (!texture) + return 0; + + uint32_t planeCount = texture->GetPlaneCount(); + + if (planeCount == 1) + return 0; + + auto formatMode = texture->GetFormatMode(); + auto formatFamily = LookupFamily(texture->Desc()->Format, formatMode); + auto viewFormat = LookupFormat(ViewFormat, formatMode); + + for (uint32_t i = 0; i < formatFamily.FormatCount; i++) { + if (formatFamily.Formats[i] == viewFormat.Format) + return i % planeCount; + } + + return ~0u; + } + + + template + HRESULT D3D11Device::OpenSharedResourceGeneric( + HANDLE hResource, + REFIID ReturnedInterface, + void** ppResource) { + InitReturnPtr(ppResource); + + if (ppResource == nullptr) + return S_FALSE; + + HANDLE ntHandle = IsKmtHandle ? openKmtHandle(hResource) : hResource; + + if (ntHandle == INVALID_HANDLE_VALUE) { + Logger::warn(str::format("D3D11Device::OpenSharedResourceGeneric: Handle not found: ", hResource)); + return E_INVALIDARG; + } + + DxvkSharedTextureMetadata metadata; + bool ret = getSharedMetadata(ntHandle, &metadata, sizeof(metadata), NULL); + + if (IsKmtHandle) + ::CloseHandle(ntHandle); + + if (!ret) { + Logger::warn("D3D11Device::OpenSharedResourceGeneric: Failed to get shared resource info for a texture"); + return E_INVALIDARG; + } + + D3D11_COMMON_TEXTURE_DESC d3d11Desc; + d3d11Desc.Width = metadata.Width; + d3d11Desc.Height = metadata.Height; + d3d11Desc.Depth = 1, + d3d11Desc.MipLevels = metadata.MipLevels; + d3d11Desc.ArraySize = metadata.ArraySize; + d3d11Desc.Format = metadata.Format; + d3d11Desc.SampleDesc = metadata.SampleDesc; + d3d11Desc.Usage = metadata.Usage; + d3d11Desc.BindFlags = metadata.BindFlags; + d3d11Desc.CPUAccessFlags = metadata.CPUAccessFlags; + d3d11Desc.MiscFlags = metadata.MiscFlags; + d3d11Desc.TextureLayout = metadata.TextureLayout; + + // Only 2D textures may be shared + try { + const Com texture = new D3D11Texture2D(this, &d3d11Desc, hResource); + texture->QueryInterface(ReturnedInterface, ppResource); + return S_OK; + } + catch (const DxvkError& e) { + Logger::err(e.message()); + return E_INVALIDARG; + } + } + + + template + void D3D11Device::CopySubresourceData( + Void* pData, + UINT RowPitch, + UINT DepthPitch, + ID3D11Resource* pResource, + UINT Subresource, + const D3D11_BOX* pBox) { + auto texture = GetCommonTexture(pResource); + + if (!texture) + return; + + // Validate texture state and skip invalid calls + if (texture->Desc()->Usage != D3D11_USAGE_DEFAULT + || texture->GetMapMode() == D3D11_COMMON_TEXTURE_MAP_MODE_NONE + || texture->CountSubresources() <= Subresource + || texture->GetMapType(Subresource) == D3D11_MAP(~0u)) + return; + + // Retrieve image format information + VkFormat packedFormat = LookupPackedFormat( + texture->Desc()->Format, + texture->GetFormatMode()).Format; + + auto formatInfo = imageFormatInfo(packedFormat); + + // Validate box against subresource dimensions + Rc image = texture->GetImage(); + + auto subresource = texture->GetSubresourceFromIndex( + formatInfo->aspectMask, Subresource); + + VkOffset3D offset = { 0, 0, 0 }; + VkExtent3D extent = image->mipLevelExtent(subresource.mipLevel); + + if (pBox) { + if (pBox->left >= pBox->right + || pBox->top >= pBox->bottom + || pBox->front >= pBox->back) + return; // legal, but no-op + + if (pBox->right > extent.width + || pBox->bottom > extent.height + || pBox->back > extent.depth) + return; // out of bounds + + offset = VkOffset3D { + int32_t(pBox->left), + int32_t(pBox->top), + int32_t(pBox->front) }; + + extent = VkExtent3D { + pBox->right - pBox->left, + pBox->bottom - pBox->top, + pBox->back - pBox->front }; + } + + // We can only operate on full blocks of compressed images + offset = util::computeBlockOffset(offset, formatInfo->blockSize); + extent = util::computeBlockCount(extent, formatInfo->blockSize); + + // Determine the memory layout of the image data + D3D11_MAPPED_SUBRESOURCE subresourceData = { }; + + if (texture->GetMapMode() == D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT) { + VkSubresourceLayout layout = image->querySubresourceLayout(subresource); + subresourceData.pData = image->mapPtr(layout.offset); + subresourceData.RowPitch = layout.rowPitch; + subresourceData.DepthPitch = layout.depthPitch; + } else { + subresourceData.pData = texture->GetMappedBuffer(Subresource)->mapPtr(0); + subresourceData.RowPitch = formatInfo->elementSize * extent.width; + subresourceData.DepthPitch = formatInfo->elementSize * extent.width * extent.height; + } + + if constexpr (std::is_const::value) { + // WriteToSubresource + auto src = reinterpret_cast(pData); + auto dst = reinterpret_cast< char*>(subresourceData.pData); + + for (uint32_t z = 0; z < extent.depth; z++) { + for (uint32_t y = 0; y < extent.height; y++) { + std::memcpy( + dst + (offset.z + z) * subresourceData.DepthPitch + + (offset.y + y) * subresourceData.RowPitch + + (offset.x) * formatInfo->elementSize, + src + z * DepthPitch + + y * RowPitch, + formatInfo->elementSize * extent.width); + } + } + } else { + // ReadFromSubresource + auto src = reinterpret_cast(subresourceData.pData); + auto dst = reinterpret_cast< char*>(pData); + + for (uint32_t z = 0; z < extent.depth; z++) { + for (uint32_t y = 0; y < extent.height; y++) { + std::memcpy( + dst + z * DepthPitch + + y * RowPitch, + src + (offset.z + z) * subresourceData.DepthPitch + + (offset.y + y) * subresourceData.RowPitch + + (offset.x) * formatInfo->elementSize, + formatInfo->elementSize * extent.width); + } + } + } + } + + + D3D_FEATURE_LEVEL D3D11Device::GetMaxFeatureLevel(const Rc& pInstance) { + static const std::array, 9> s_featureLevels = {{ + { "12_1", D3D_FEATURE_LEVEL_12_1 }, + { "12_0", D3D_FEATURE_LEVEL_12_0 }, + { "11_1", D3D_FEATURE_LEVEL_11_1 }, + { "11_0", D3D_FEATURE_LEVEL_11_0 }, + { "10_1", D3D_FEATURE_LEVEL_10_1 }, + { "10_0", D3D_FEATURE_LEVEL_10_0 }, + { "9_3", D3D_FEATURE_LEVEL_9_3 }, + { "9_2", D3D_FEATURE_LEVEL_9_2 }, + { "9_1", D3D_FEATURE_LEVEL_9_1 }, + }}; + + const std::string maxLevel = pInstance->config() + .getOption("d3d11.maxFeatureLevel"); + + auto entry = std::find_if(s_featureLevels.begin(), s_featureLevels.end(), + [&] (const std::pair& pair) { + return pair.first == maxLevel; + }); + + return entry != s_featureLevels.end() + ? entry->second + : D3D_FEATURE_LEVEL_11_1; + } + + + + + D3D11DeviceExt::D3D11DeviceExt( + D3D11DXGIDevice* pContainer, + D3D11Device* pDevice) + : m_container(pContainer), m_device(pDevice) { + + } + + + ULONG STDMETHODCALLTYPE D3D11DeviceExt::AddRef() { + return m_container->AddRef(); + } + + + ULONG STDMETHODCALLTYPE D3D11DeviceExt::Release() { + return m_container->Release(); + } + + + HRESULT STDMETHODCALLTYPE D3D11DeviceExt::QueryInterface( + REFIID riid, + void** ppvObject) { + return m_container->QueryInterface(riid, ppvObject); + } + + + BOOL STDMETHODCALLTYPE D3D11DeviceExt::GetExtensionSupport( + D3D11_VK_EXTENSION Extension) { + const auto& deviceFeatures = m_device->GetDXVKDevice()->features(); + const auto& deviceExtensions = m_device->GetDXVKDevice()->extensions(); + + switch (Extension) { + case D3D11_VK_EXT_BARRIER_CONTROL: + return true; + + case D3D11_VK_EXT_MULTI_DRAW_INDIRECT: + return deviceFeatures.core.features.multiDrawIndirect; + + case D3D11_VK_EXT_MULTI_DRAW_INDIRECT_COUNT: + return deviceFeatures.core.features.multiDrawIndirect + && deviceExtensions.khrDrawIndirectCount; + + case D3D11_VK_EXT_DEPTH_BOUNDS: + return deviceFeatures.core.features.depthBounds; + + case D3D11_VK_NVX_IMAGE_VIEW_HANDLE: + return deviceExtensions.nvxImageViewHandle; + + case D3D11_VK_NVX_BINARY_IMPORT: + return deviceExtensions.nvxBinaryImport + && deviceExtensions.khrBufferDeviceAddress; + + default: + return false; + } + } + + + bool STDMETHODCALLTYPE D3D11DeviceExt::GetCudaTextureObjectNVX(uint32_t srvDriverHandle, uint32_t samplerDriverHandle, uint32_t* pCudaTextureHandle) { + ID3D11ShaderResourceView* srv = HandleToSrvNVX(srvDriverHandle); + + if (!srv) { + Logger::warn(str::format("GetCudaTextureObjectNVX() failure - srv handle wasn't found: ", srvDriverHandle)); + return false; + } + + ID3D11SamplerState* samplerState = HandleToSamplerNVX(samplerDriverHandle); + + if (!samplerState) { + Logger::warn(str::format("GetCudaTextureObjectNVX() failure - sampler handle wasn't found: ", samplerDriverHandle)); + return false; + } + + D3D11SamplerState* pSS = static_cast(samplerState); + Rc pDSS = pSS->GetDXVKSampler(); + VkSampler vkSampler = pDSS->handle(); + + D3D11ShaderResourceView* pSRV = static_cast(srv); + Rc pIV = pSRV->GetImageView(); + VkImageView vkImageView = pIV->handle(); + + VkImageViewHandleInfoNVX imageViewHandleInfo = {VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX}; + imageViewHandleInfo.imageView = vkImageView; + imageViewHandleInfo.sampler = vkSampler; + imageViewHandleInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + + // note: there's no implicit lifetime management here; it's up to the + // app to keep the sampler and SRV alive as long as it wants to use this + // derived handle. + VkDevice vkDevice = m_device->GetDXVKDevice()->handle(); + *pCudaTextureHandle = m_device->GetDXVKDevice()->vkd()->vkGetImageViewHandleNVX(vkDevice, &imageViewHandleInfo); + + if (!*pCudaTextureHandle) { + Logger::warn("GetCudaTextureObjectNVX() handle==0 - failed"); + return false; + } + + return true; + } + + + bool STDMETHODCALLTYPE D3D11DeviceExt::CreateCubinComputeShaderWithNameNVX(const void* pCubin, uint32_t size, + uint32_t blockX, uint32_t blockY, uint32_t blockZ, const char* pShaderName, IUnknown** phShader) { + Rc dxvkDevice = m_device->GetDXVKDevice(); + VkDevice vkDevice = dxvkDevice->handle(); + + VkCuModuleCreateInfoNVX moduleCreateInfo = { VK_STRUCTURE_TYPE_CU_MODULE_CREATE_INFO_NVX }; + moduleCreateInfo.pData = pCubin; + moduleCreateInfo.dataSize = size; + + VkCuModuleNVX cuModule; + VkCuFunctionNVX cuFunction; + VkResult result; + + if ((result = dxvkDevice->vkd()->vkCreateCuModuleNVX(vkDevice, &moduleCreateInfo, nullptr, &cuModule))) { + Logger::warn(str::format("CreateCubinComputeShaderWithNameNVX() - failure to create module - result=", result, " pcubindata=", pCubin, " cubinsize=", size)); + return false; // failure + } + + VkCuFunctionCreateInfoNVX functionCreateInfo = { VK_STRUCTURE_TYPE_CU_FUNCTION_CREATE_INFO_NVX }; + functionCreateInfo.module = cuModule; + functionCreateInfo.pName = pShaderName; + + if ((result = dxvkDevice->vkd()->vkCreateCuFunctionNVX(vkDevice, &functionCreateInfo, nullptr, &cuFunction))) { + dxvkDevice->vkd()->vkDestroyCuModuleNVX(vkDevice, cuModule, nullptr); + Logger::warn(str::format("CreateCubinComputeShaderWithNameNVX() - failure to create function - result=", result)); + return false; + } + + *phShader = ref(new CubinShaderWrapper(dxvkDevice, + cuModule, cuFunction, { blockX, blockY, blockZ })); + return true; + } + + + bool STDMETHODCALLTYPE D3D11DeviceExt::GetResourceHandleGPUVirtualAddressAndSizeNVX(void* hObject, uint64_t* gpuVAStart, uint64_t* gpuVASize) { + // The hObject 'opaque driver handle' is really just a straight cast + // of the corresponding ID3D11Resource* in dxvk/dxvknvapi + ID3D11Resource* pResource = static_cast(hObject); + + D3D11_COMMON_RESOURCE_DESC resourceDesc; + if (FAILED(GetCommonResourceDesc(pResource, &resourceDesc))) { + Logger::warn("GetResourceHandleGPUVirtualAddressAndSize() - GetCommonResourceDesc() failed"); + return false; + } + + switch (resourceDesc.Dim) { + case D3D11_RESOURCE_DIMENSION_BUFFER: + case D3D11_RESOURCE_DIMENSION_TEXTURE2D: + // okay - we can deal with those two dimensions + break; + case D3D11_RESOURCE_DIMENSION_TEXTURE1D: + case D3D11_RESOURCE_DIMENSION_TEXTURE3D: + case D3D11_RESOURCE_DIMENSION_UNKNOWN: + default: + Logger::warn(str::format("GetResourceHandleGPUVirtualAddressAndSize(?) - failure - unsupported dimension: ", resourceDesc.Dim)); + return false; + } + + Rc dxvkDevice = m_device->GetDXVKDevice(); + VkDevice vkDevice = dxvkDevice->handle(); + + if (resourceDesc.Dim == D3D11_RESOURCE_DIMENSION_TEXTURE2D) { + D3D11CommonTexture *texture = GetCommonTexture(pResource); + Rc dxvkImage = texture->GetImage(); + if (0 == (dxvkImage->info().usage & (VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT))) { + Logger::warn(str::format("GetResourceHandleGPUVirtualAddressAndSize(res=", pResource,") image info missing required usage bit(s); can't be used for vkGetImageViewHandleNVX - failure")); + return false; + } + + // The d3d11 nvapi provides us a texture but vulkan only lets us get the GPU address from an imageview. So, make a private imageview and get the address from that... + + D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDesc; + + const D3D11_COMMON_TEXTURE_DESC *texDesc = texture->Desc(); + if (texDesc->ArraySize != 1) { + Logger::debug(str::format("GetResourceHandleGPUVirtualAddressAndSize(?) - unexpected array size: ", texDesc->ArraySize)); + } + resourceViewDesc.Format = texDesc->Format; + resourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + resourceViewDesc.Texture2D.MostDetailedMip = 0; + resourceViewDesc.Texture2D.MipLevels = texDesc->MipLevels; + + Com pNewSRV; + HRESULT hr = m_device->CreateShaderResourceView(pResource, &resourceViewDesc, &pNewSRV); + if (FAILED(hr)) { + Logger::warn("GetResourceHandleGPUVirtualAddressAndSize() - private CreateShaderResourceView() failed"); + return false; + } + + Rc dxvkImageView = static_cast(pNewSRV.ptr())->GetImageView(); + VkImageView vkImageView = dxvkImageView->handle(); + + VkImageViewAddressPropertiesNVX imageViewAddressProperties = {VK_STRUCTURE_TYPE_IMAGE_VIEW_ADDRESS_PROPERTIES_NVX}; + + VkResult res = dxvkDevice->vkd()->vkGetImageViewAddressNVX(vkDevice, vkImageView, &imageViewAddressProperties); + if (res != VK_SUCCESS) { + Logger::warn(str::format("GetResourceHandleGPUVirtualAddressAndSize(): vkGetImageViewAddressNVX() result is failure: ", res)); + return false; + } + + *gpuVAStart = imageViewAddressProperties.deviceAddress; + *gpuVASize = imageViewAddressProperties.size; + } + else if (resourceDesc.Dim == D3D11_RESOURCE_DIMENSION_BUFFER) { + D3D11Buffer *buffer = GetCommonBuffer(pResource); + const DxvkBufferSliceHandle bufSliceHandle = buffer->GetBuffer()->getSliceHandle(); + VkBuffer vkBuffer = bufSliceHandle.handle; + + VkBufferDeviceAddressInfoKHR bdaInfo = { VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_KHR }; + bdaInfo.buffer = vkBuffer; + VkDeviceAddress bufAddr = dxvkDevice->vkd()->vkGetBufferDeviceAddressKHR(vkDevice, &bdaInfo); + *gpuVAStart = uint64_t(bufAddr) + bufSliceHandle.offset; + *gpuVASize = bufSliceHandle.length; + } + + if (!*gpuVAStart) + Logger::warn("GetResourceHandleGPUVirtualAddressAndSize() addr==0 - unexpected"); // ... but not explicitly a failure; continue + + return true; + } + + + bool STDMETHODCALLTYPE D3D11DeviceExt::CreateUnorderedAccessViewAndGetDriverHandleNVX(ID3D11Resource* pResource, const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc, ID3D11UnorderedAccessView** ppUAV, uint32_t* pDriverHandle) { + D3D11_COMMON_RESOURCE_DESC resourceDesc; + if (!SUCCEEDED(GetCommonResourceDesc(pResource, &resourceDesc))) { + Logger::warn("CreateUnorderedAccessViewAndGetDriverHandleNVX() - GetCommonResourceDesc() failed"); + return false; + } + if (resourceDesc.Dim != D3D11_RESOURCE_DIMENSION_TEXTURE2D) { + Logger::warn(str::format("CreateUnorderedAccessViewAndGetDriverHandleNVX() - failure - unsupported dimension: ", resourceDesc.Dim)); + return false; + } + + auto texture = GetCommonTexture(pResource); + Rc dxvkImage = texture->GetImage(); + if (0 == (dxvkImage->info().usage & (VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT))) { + Logger::warn(str::format("CreateUnorderedAccessViewAndGetDriverHandleNVX(res=", pResource, ") image info missing required usage bit(s); can't be used for vkGetImageViewHandleNVX - failure")); + return false; + } + + if (!SUCCEEDED(m_device->CreateUnorderedAccessView(pResource, pDesc, ppUAV))) { + return false; + } + + D3D11UnorderedAccessView *pUAV = static_cast(*ppUAV); + Rc dxvkDevice = m_device->GetDXVKDevice(); + VkDevice vkDevice = dxvkDevice->handle(); + + VkImageViewHandleInfoNVX imageViewHandleInfo = {VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX}; + Rc dxvkImageView = pUAV->GetImageView(); + VkImageView vkImageView = dxvkImageView->handle(); + + imageViewHandleInfo.imageView = vkImageView; + imageViewHandleInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + + *pDriverHandle = dxvkDevice->vkd()->vkGetImageViewHandleNVX(vkDevice, &imageViewHandleInfo); + + if (!*pDriverHandle) { + Logger::warn("CreateUnorderedAccessViewAndGetDriverHandleNVX() handle==0 - failure"); + pUAV->Release(); + return false; + } + + return true; + } + + + bool STDMETHODCALLTYPE D3D11DeviceExt::CreateShaderResourceViewAndGetDriverHandleNVX(ID3D11Resource* pResource, const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc, ID3D11ShaderResourceView** ppSRV, uint32_t* pDriverHandle) { + D3D11_COMMON_RESOURCE_DESC resourceDesc; + if (!SUCCEEDED(GetCommonResourceDesc(pResource, &resourceDesc))) { + Logger::warn("CreateShaderResourceViewAndGetDriverHandleNVX() - GetCommonResourceDesc() failed"); + return false; + } + if (resourceDesc.Dim != D3D11_RESOURCE_DIMENSION_TEXTURE2D) { + Logger::warn(str::format("CreateShaderResourceViewAndGetDriverHandleNVX() - failure - unsupported dimension: ", resourceDesc.Dim)); + return false; + } + + auto texture = GetCommonTexture(pResource); + Rc dxvkImage = texture->GetImage(); + if (0 == (dxvkImage->info().usage & (VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT))) { + Logger::warn(str::format("CreateShaderResourceViewAndGetDriverHandleNVX(res=", pResource, ") image info missing required usage bit(s); can't be used for vkGetImageViewHandleNVX - failure")); + return false; + } + + if (!SUCCEEDED(m_device->CreateShaderResourceView(pResource, pDesc, ppSRV))) { + return false; + } + + D3D11ShaderResourceView* pSRV = static_cast(*ppSRV); + Rc dxvkDevice = m_device->GetDXVKDevice(); + VkDevice vkDevice = dxvkDevice->handle(); + + VkImageViewHandleInfoNVX imageViewHandleInfo = {VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX}; + Rc dxvkImageView = pSRV->GetImageView(); + VkImageView vkImageView = dxvkImageView->handle(); + + imageViewHandleInfo.imageView = vkImageView; + imageViewHandleInfo.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + + *pDriverHandle = dxvkDevice->vkd()->vkGetImageViewHandleNVX(vkDevice, &imageViewHandleInfo); + + if (!*pDriverHandle) { + Logger::warn("CreateShaderResourceViewAndGetDriverHandleNVX() handle==0 - failure"); + pSRV->Release(); + return false; + } + + // will need to look-up resource from uint32 handle later + AddSrvAndHandleNVX(*ppSRV, *pDriverHandle); + return true; + } + + + bool STDMETHODCALLTYPE D3D11DeviceExt::CreateSamplerStateAndGetDriverHandleNVX(const D3D11_SAMPLER_DESC* pSamplerDesc, ID3D11SamplerState** ppSamplerState, uint32_t* pDriverHandle) { + if (!SUCCEEDED(m_device->CreateSamplerState(pSamplerDesc, ppSamplerState))) { + return false; + } + + // for our purposes the actual value doesn't matter, only its uniqueness + static std::atomic s_seqNum = 0; + *pDriverHandle = ++s_seqNum; + + // will need to look-up sampler from uint32 handle later + AddSamplerAndHandleNVX(*ppSamplerState, *pDriverHandle); + return true; + } + + + void D3D11DeviceExt::AddSamplerAndHandleNVX(ID3D11SamplerState* pSampler, uint32_t Handle) { + std::lock_guard lock(m_mapLock); + m_samplerHandleToPtr[Handle] = pSampler; + } + + + ID3D11SamplerState* D3D11DeviceExt::HandleToSamplerNVX(uint32_t Handle) { + std::lock_guard lock(m_mapLock); + auto got = m_samplerHandleToPtr.find(Handle); + + if (got == m_samplerHandleToPtr.end()) + return nullptr; + + return static_cast(got->second); + } + + + void D3D11DeviceExt::AddSrvAndHandleNVX(ID3D11ShaderResourceView* pSrv, uint32_t Handle) { + std::lock_guard lock(m_mapLock); + m_srvHandleToPtr[Handle] = pSrv; + } + + + ID3D11ShaderResourceView* D3D11DeviceExt::HandleToSrvNVX(uint32_t Handle) { + std::lock_guard lock(m_mapLock); + auto got = m_srvHandleToPtr.find(Handle); + + if (got == m_srvHandleToPtr.end()) + return nullptr; + + return static_cast(got->second); + } + + + + + + D3D11VideoDevice::D3D11VideoDevice( + D3D11DXGIDevice* pContainer, + D3D11Device* pDevice) + : m_container(pContainer), m_device(pDevice) { + + } + + + D3D11VideoDevice::~D3D11VideoDevice() { + + } + + + ULONG STDMETHODCALLTYPE D3D11VideoDevice::AddRef() { + return m_container->AddRef(); + } + + + ULONG STDMETHODCALLTYPE D3D11VideoDevice::Release() { + return m_container->Release(); + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoDevice::QueryInterface( + REFIID riid, + void** ppvObject) { + return m_container->QueryInterface(riid, ppvObject); + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoDevice::CreateVideoDecoder( + const D3D11_VIDEO_DECODER_DESC* pVideoDesc, + const D3D11_VIDEO_DECODER_CONFIG* pConfig, + ID3D11VideoDecoder** ppDecoder) { + Logger::err("D3D11VideoDevice::CreateVideoDecoder: Stub"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoDevice::CreateVideoProcessor( + ID3D11VideoProcessorEnumerator* pEnum, + UINT RateConversionIndex, + ID3D11VideoProcessor** ppVideoProcessor) { + try { + auto enumerator = static_cast(pEnum); + *ppVideoProcessor = ref(new D3D11VideoProcessor(m_device, enumerator, RateConversionIndex)); + return S_OK; + } catch (const DxvkError& e) { + Logger::err(e.message()); + return E_FAIL; + } + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoDevice::CreateAuthenticatedChannel( + D3D11_AUTHENTICATED_CHANNEL_TYPE ChannelType, + ID3D11AuthenticatedChannel** ppAuthenticatedChannel) { + Logger::err("D3D11VideoDevice::CreateAuthenticatedChannel: Stub"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoDevice::CreateCryptoSession( + const GUID* pCryptoType, + const GUID* pDecoderProfile, + const GUID* pKeyExchangeType, + ID3D11CryptoSession** ppCryptoSession) { + Logger::err("D3D11VideoDevice::CreateCryptoSession: Stub"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoDevice::CreateVideoDecoderOutputView( + ID3D11Resource* pResource, + const D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC* pDesc, + ID3D11VideoDecoderOutputView** ppVDOVView) { + Logger::err("D3D11VideoDevice::CreateVideoDecoderOutputView: Stub"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoDevice::CreateVideoProcessorInputView( + ID3D11Resource* pResource, + ID3D11VideoProcessorEnumerator* pEnum, + const D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC* pDesc, + ID3D11VideoProcessorInputView** ppVPIView) { + try { + *ppVPIView = ref(new D3D11VideoProcessorInputView(m_device, pResource, *pDesc)); + return S_OK; + } catch (const DxvkError& e) { + Logger::err(e.message()); + return E_FAIL; + } + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoDevice::CreateVideoProcessorOutputView( + ID3D11Resource* pResource, + ID3D11VideoProcessorEnumerator* pEnum, + const D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC* pDesc, + ID3D11VideoProcessorOutputView** ppVPOView) { + try { + *ppVPOView = ref(new D3D11VideoProcessorOutputView(m_device, pResource, *pDesc)); + return S_OK; + } catch (const DxvkError& e) { + Logger::err(e.message()); + return E_FAIL; + } + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoDevice::CreateVideoProcessorEnumerator( + const D3D11_VIDEO_PROCESSOR_CONTENT_DESC* pDesc, + ID3D11VideoProcessorEnumerator** ppEnum) { + try { + *ppEnum = ref(new D3D11VideoProcessorEnumerator(m_device, *pDesc)); + return S_OK; + } catch (const DxvkError& e) { + Logger::err(e.message()); + return E_FAIL; + } + } + + + UINT STDMETHODCALLTYPE D3D11VideoDevice::GetVideoDecoderProfileCount() { + Logger::err("D3D11VideoDevice::GetVideoDecoderProfileCount: Stub"); + return 0; + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoDevice::GetVideoDecoderProfile( + UINT Index, + GUID* pDecoderProfile) { + Logger::err("D3D11VideoDevice::GetVideoDecoderProfile: Stub"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoDevice::CheckVideoDecoderFormat( + const GUID* pDecoderProfile, + DXGI_FORMAT Format, + BOOL* pSupported) { + Logger::err("D3D11VideoDevice::CheckVideoDecoderFormat: Stub"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoDevice::GetVideoDecoderConfigCount( + const D3D11_VIDEO_DECODER_DESC* pDesc, + UINT* pCount) { + Logger::err("D3D11VideoDevice::GetVideoDecoderConfigCount: Stub"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoDevice::GetVideoDecoderConfig( + const D3D11_VIDEO_DECODER_DESC* pDesc, + UINT Index, + D3D11_VIDEO_DECODER_CONFIG* pConfig) { + Logger::err("D3D11VideoDevice::GetVideoDecoderConfig: Stub"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoDevice::GetContentProtectionCaps( + const GUID* pCryptoType, + const GUID* pDecoderProfile, + D3D11_VIDEO_CONTENT_PROTECTION_CAPS* pCaps) { + Logger::err("D3D11VideoDevice::GetContentProtectionCaps: Stub"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoDevice::CheckCryptoKeyExchange( + const GUID* pCryptoType, + const GUID* pDecoderProfile, + UINT Index, + GUID* pKeyExchangeType) { + Logger::err("D3D11VideoDevice::CheckCryptoKeyExchange: Stub"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoDevice::SetPrivateData( + REFGUID Name, + UINT DataSize, + const void* pData) { + return m_container->SetPrivateData(Name, DataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoDevice::SetPrivateDataInterface( + REFGUID Name, + const IUnknown* pData) { + return m_container->SetPrivateDataInterface(Name, pData); + } + + + + + WineDXGISwapChainFactory::WineDXGISwapChainFactory( + D3D11DXGIDevice* pContainer, + D3D11Device* pDevice) + : m_container(pContainer), m_device(pDevice) { + + } + + + ULONG STDMETHODCALLTYPE WineDXGISwapChainFactory::AddRef() { + return m_device->AddRef(); + } + + + ULONG STDMETHODCALLTYPE WineDXGISwapChainFactory::Release() { + return m_device->Release(); + } + + + HRESULT STDMETHODCALLTYPE WineDXGISwapChainFactory::QueryInterface( + REFIID riid, + void** ppvObject) { + return m_device->QueryInterface(riid, ppvObject); + } + + + HRESULT STDMETHODCALLTYPE WineDXGISwapChainFactory::CreateSwapChainForHwnd( + IDXGIFactory* pFactory, + HWND hWnd, + const DXGI_SWAP_CHAIN_DESC1* pDesc, + const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc, + IDXGIOutput* pRestrictToOutput, + IDXGISwapChain1** ppSwapChain) { + InitReturnPtr(ppSwapChain); + + if (!ppSwapChain || !pDesc || !hWnd) + return DXGI_ERROR_INVALID_CALL; + + // Make sure the back buffer size is not zero + DXGI_SWAP_CHAIN_DESC1 desc = *pDesc; + + GetWindowClientSize(hWnd, + desc.Width ? nullptr : &desc.Width, + desc.Height ? nullptr : &desc.Height); + + // If necessary, set up a default set of + // fullscreen parameters for the swap chain + DXGI_SWAP_CHAIN_FULLSCREEN_DESC fsDesc; + + if (pFullscreenDesc) { + fsDesc = *pFullscreenDesc; + } else { + fsDesc.RefreshRate = { 0, 0 }; + fsDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; + fsDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + fsDesc.Windowed = TRUE; + } + + try { + // Create presenter for the device + Com presenter = new D3D11SwapChain( + m_container, m_device, hWnd, &desc); + + // Create the actual swap chain + *ppSwapChain = ref(new DxgiSwapChain( + pFactory, presenter.ptr(), hWnd, &desc, &fsDesc)); + return S_OK; + } catch (const DxvkError& e) { + Logger::err(e.message()); + return E_INVALIDARG; + } + } + + + + DXGIDXVKDevice::DXGIDXVKDevice(D3D11DXGIDevice* pContainer) + : m_container(pContainer), m_apiVersion(11) { + + } + + + ULONG STDMETHODCALLTYPE DXGIDXVKDevice::AddRef() { + return m_container->AddRef(); + } + + + ULONG STDMETHODCALLTYPE DXGIDXVKDevice::Release() { + return m_container->Release(); + } + + + HRESULT STDMETHODCALLTYPE DXGIDXVKDevice::QueryInterface( + REFIID riid, + void** ppvObject) { + return m_container->QueryInterface(riid, ppvObject); + } + + + void STDMETHODCALLTYPE DXGIDXVKDevice::SetAPIVersion( + UINT Version) { + m_apiVersion = Version; + } + + + UINT STDMETHODCALLTYPE DXGIDXVKDevice::GetAPIVersion() { + return m_apiVersion; + } + + + + + D3D11DXGIDevice::D3D11DXGIDevice( + IDXGIAdapter* pAdapter, + const Rc& pDxvkInstance, + const Rc& pDxvkAdapter, + D3D_FEATURE_LEVEL FeatureLevel, + UINT FeatureFlags) + : m_dxgiAdapter (pAdapter), + m_dxvkInstance (pDxvkInstance), + m_dxvkAdapter (pDxvkAdapter), + m_dxvkDevice (CreateDevice(FeatureLevel)), + m_d3d11Device (this, FeatureLevel, FeatureFlags), + m_d3d11DeviceExt(this, &m_d3d11Device), + m_d3d11Interop (this, &m_d3d11Device), + m_d3d11Video (this, &m_d3d11Device), + m_metaDevice (this), + m_wineFactory (this, &m_d3d11Device) { + + } + + + D3D11DXGIDevice::~D3D11DXGIDevice() { + + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::QueryInterface(REFIID riid, void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(IDXGIObject) + || riid == __uuidof(IDXGIDevice) + || riid == __uuidof(IDXGIDevice1) + || riid == __uuidof(IDXGIDevice2) + || riid == __uuidof(IDXGIDevice3) + || riid == __uuidof(IDXGIDevice4)) { + *ppvObject = ref(this); + return S_OK; + } + + if (riid == __uuidof(IDXGIVkInteropDevice) + || riid == __uuidof(IDXGIVkInteropDevice1)) { + *ppvObject = ref(&m_d3d11Interop); + return S_OK; + } + + if (riid == __uuidof(ID3D10Device) + || riid == __uuidof(ID3D10Device1)) { + *ppvObject = ref(m_d3d11Device.GetD3D10Interface()); + return S_OK; + } + + if (riid == __uuidof(ID3D11Device) + || riid == __uuidof(ID3D11Device1) + || riid == __uuidof(ID3D11Device2) + || riid == __uuidof(ID3D11Device3) + || riid == __uuidof(ID3D11Device4) + || riid == __uuidof(ID3D11Device5)) { + *ppvObject = ref(&m_d3d11Device); + return S_OK; + } + + if (riid == __uuidof(ID3D11VkExtDevice) + || riid == __uuidof(ID3D11VkExtDevice1)) { + *ppvObject = ref(&m_d3d11DeviceExt); + return S_OK; + } + + if (riid == __uuidof(IDXGIDXVKDevice)) { + *ppvObject = ref(&m_metaDevice); + return S_OK; + } + + if (riid == __uuidof(IWineDXGISwapChainFactory)) { + *ppvObject = ref(&m_wineFactory); + return S_OK; + } + + if (riid == __uuidof(ID3D11VideoDevice)) { + *ppvObject = ref(&m_d3d11Video); + return S_OK; + } + + if (riid == __uuidof(ID3D10Multithread)) { + Com context; + m_d3d11Device.GetImmediateContext(&context); + return context->QueryInterface(riid, ppvObject); + } + + if (riid == __uuidof(ID3D11Debug)) + return E_NOINTERFACE; + + // Undocumented interfaces that are queried by some games + if (riid == GUID{0xd56e2a4c,0x5127,0x8437,{0x65,0x8a,0x98,0xc5,0xbb,0x78,0x94,0x98}}) + return E_NOINTERFACE; + + Logger::warn("D3D11DXGIDevice::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::GetParent( + REFIID riid, + void** ppParent) { + return m_dxgiAdapter->QueryInterface(riid, ppParent); + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::CreateSurface( + const DXGI_SURFACE_DESC* pDesc, + UINT NumSurfaces, + DXGI_USAGE Usage, + const DXGI_SHARED_RESOURCE* pSharedResource, + IDXGISurface** ppSurface) { + if (!pDesc || (NumSurfaces && !ppSurface)) + return E_INVALIDARG; + + D3D11_TEXTURE2D_DESC desc; + desc.Width = pDesc->Width; + desc.Height = pDesc->Height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = pDesc->Format; + desc.SampleDesc = pDesc->SampleDesc; + desc.BindFlags = 0; + desc.MiscFlags = 0; + + // Handle bind flags + if (Usage & DXGI_USAGE_RENDER_TARGET_OUTPUT) + desc.BindFlags |= D3D11_BIND_RENDER_TARGET; + + if (Usage & DXGI_USAGE_SHADER_INPUT) + desc.BindFlags |= D3D11_BIND_SHADER_RESOURCE; + + if (Usage & DXGI_USAGE_UNORDERED_ACCESS) + desc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS; + + // Handle CPU access flags + switch (Usage & DXGI_CPU_ACCESS_FIELD) { + case DXGI_CPU_ACCESS_NONE: + desc.Usage = D3D11_USAGE_DEFAULT; + desc.CPUAccessFlags = 0; + break; + + case DXGI_CPU_ACCESS_DYNAMIC: + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + break; + + case DXGI_CPU_ACCESS_READ_WRITE: + case DXGI_CPU_ACCESS_SCRATCH: + desc.Usage = D3D11_USAGE_STAGING; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + break; + + default: + return E_INVALIDARG; + } + + // Restrictions and limitations of CreateSurface are not + // well-documented, so we'll be a lenient on validation. + HRESULT hr = m_d3d11Device.CreateTexture2D(&desc, nullptr, nullptr); + + if (FAILED(hr)) + return hr; + + // We don't support shared resources + if (NumSurfaces && pSharedResource) + Logger::err("D3D11: CreateSurface: Shared surfaces not supported"); + + // Try to create the given number of surfaces + uint32_t surfacesCreated = 0; + hr = S_OK; + + for (uint32_t i = 0; i < NumSurfaces; i++) { + Com texture; + + hr = m_d3d11Device.CreateTexture2D(&desc, nullptr, &texture); + + if (SUCCEEDED(hr)) { + hr = texture->QueryInterface(__uuidof(IDXGISurface), + reinterpret_cast(&ppSurface[i])); + surfacesCreated = i + 1; + } + + if (FAILED(hr)) + break; + } + + // Don't leak surfaces if we failed to create one + if (FAILED(hr)) { + for (uint32_t i = 0; i < surfacesCreated; i++) + ppSurface[i]->Release(); + } + + return hr; + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::GetAdapter( + IDXGIAdapter** pAdapter) { + if (pAdapter == nullptr) + return DXGI_ERROR_INVALID_CALL; + + *pAdapter = m_dxgiAdapter.ref(); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::GetGPUThreadPriority( + INT* pPriority) { + *pPriority = 0; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::QueryResourceResidency( + IUnknown* const* ppResources, + DXGI_RESIDENCY* pResidencyStatus, + UINT NumResources) { + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::err("D3D11DXGIDevice::QueryResourceResidency: Stub"); + + if (!ppResources || !pResidencyStatus) + return E_INVALIDARG; + + for (uint32_t i = 0; i < NumResources; i++) + pResidencyStatus[i] = DXGI_RESIDENCY_FULLY_RESIDENT; + + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::SetGPUThreadPriority( + INT Priority) { + if (Priority < -7 || Priority > 7) + return E_INVALIDARG; + + Logger::err("DXGI: SetGPUThreadPriority: Ignoring"); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::GetMaximumFrameLatency( + UINT* pMaxLatency) { + if (!pMaxLatency) + return DXGI_ERROR_INVALID_CALL; + + *pMaxLatency = m_frameLatency; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::SetMaximumFrameLatency( + UINT MaxLatency) { + if (MaxLatency == 0) + MaxLatency = DefaultFrameLatency; + + if (MaxLatency > DXGI_MAX_SWAP_CHAIN_BUFFERS) + return DXGI_ERROR_INVALID_CALL; + + m_frameLatency = MaxLatency; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::OfferResources( + UINT NumResources, + IDXGIResource* const* ppResources, + DXGI_OFFER_RESOURCE_PRIORITY Priority) { + return OfferResources1(NumResources, ppResources, Priority, 0); + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::OfferResources1( + UINT NumResources, + IDXGIResource* const* ppResources, + DXGI_OFFER_RESOURCE_PRIORITY Priority, + UINT Flags) { + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::warn("D3D11DXGIDevice::OfferResources1: Stub"); + + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::ReclaimResources( + UINT NumResources, + IDXGIResource* const* ppResources, + BOOL* pDiscarded) { + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::warn("D3D11DXGIDevice::ReclaimResources: Stub"); + + if (pDiscarded) + *pDiscarded = false; + + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::ReclaimResources1( + UINT NumResources, + IDXGIResource* const* ppResources, + DXGI_RECLAIM_RESOURCE_RESULTS* pResults) { + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::warn("D3D11DXGIDevice::ReclaimResources1: Stub"); + + if (pResults) { + for (uint32_t i = 0; i < NumResources; i++) + pResults[i] = DXGI_RECLAIM_RESOURCE_RESULT_OK; + } + + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::EnqueueSetEvent(HANDLE hEvent) { + Logger::err("D3D11DXGIDevice::EnqueueSetEvent: Not implemented"); + return DXGI_ERROR_UNSUPPORTED; + } + + + void STDMETHODCALLTYPE D3D11DXGIDevice::Trim() { + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::warn("D3D11DXGIDevice::Trim: Stub"); + } + + + Rc STDMETHODCALLTYPE D3D11DXGIDevice::GetDXVKDevice() { + return m_dxvkDevice; + } + + + Rc D3D11DXGIDevice::CreateDevice(D3D_FEATURE_LEVEL FeatureLevel) { + DxvkDeviceFeatures deviceFeatures = D3D11Device::GetDeviceFeatures(m_dxvkAdapter, FeatureLevel); + return m_dxvkAdapter->createDevice(m_dxvkInstance, deviceFeatures); + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_device.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_device.h new file mode 100644 index 00000000000..5a99bd62a13 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_device.h @@ -0,0 +1,863 @@ +#pragma once + +#include +#include + +#include "../dxbc/dxbc_options.h" + +#include "../dxgi/dxgi_object.h" +#include "../dxgi/dxgi_interfaces.h" + +#include "../dxvk/dxvk_cs.h" + +#include "../d3d10/d3d10_device.h" + +#include "../util/com/com_private_data.h" + +#include "d3d11_cmdlist.h" +#include "d3d11_cuda.h" +#include "d3d11_initializer.h" +#include "d3d11_interfaces.h" +#include "d3d11_interop.h" +#include "d3d11_options.h" +#include "d3d11_shader.h" +#include "d3d11_state.h" +#include "d3d11_util.h" + +namespace dxvk { + class DxgiAdapter; + + class D3D11Buffer; + class D3D11CommonShader; + class D3D11CommonTexture; + class D3D11Counter; + class D3D11DeviceContext; + class D3D11DXGIDevice; + class D3D11ImmediateContext; + class D3D11Predicate; + class D3D11Query; + class D3D11Texture1D; + class D3D11Texture2D; + class D3D11Texture3D; + + /** + * \brief D3D11 device implementation + * + * Implements the ID3D11Device interfaces + * as part of a \ref D3D11DeviceContainer. + */ + class D3D11Device final : public ID3D11Device5 { + /// Maximum number of resource init commands per command buffer + constexpr static uint64_t InitCommandThreshold = 50; + public: + + D3D11Device( + D3D11DXGIDevice* pContainer, + D3D_FEATURE_LEVEL FeatureLevel, + UINT FeatureFlags); + + ~D3D11Device(); + + ULONG STDMETHODCALLTYPE AddRef(); + + ULONG STDMETHODCALLTYPE Release(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + HRESULT STDMETHODCALLTYPE CreateBuffer( + const D3D11_BUFFER_DESC* pDesc, + const D3D11_SUBRESOURCE_DATA* pInitialData, + ID3D11Buffer** ppBuffer); + + HRESULT STDMETHODCALLTYPE CreateTexture1D( + const D3D11_TEXTURE1D_DESC* pDesc, + const D3D11_SUBRESOURCE_DATA* pInitialData, + ID3D11Texture1D** ppTexture1D); + + HRESULT STDMETHODCALLTYPE CreateTexture2D( + const D3D11_TEXTURE2D_DESC* pDesc, + const D3D11_SUBRESOURCE_DATA* pInitialData, + ID3D11Texture2D** ppTexture2D); + + HRESULT STDMETHODCALLTYPE CreateTexture2D1( + const D3D11_TEXTURE2D_DESC1* pDesc, + const D3D11_SUBRESOURCE_DATA* pInitialData, + ID3D11Texture2D1** ppTexture2D); + + HRESULT STDMETHODCALLTYPE CreateTexture3D( + const D3D11_TEXTURE3D_DESC* pDesc, + const D3D11_SUBRESOURCE_DATA* pInitialData, + ID3D11Texture3D** ppTexture3D); + + HRESULT STDMETHODCALLTYPE CreateTexture3D1( + const D3D11_TEXTURE3D_DESC1* pDesc, + const D3D11_SUBRESOURCE_DATA* pInitialData, + ID3D11Texture3D1** ppTexture3D); + + HRESULT STDMETHODCALLTYPE CreateShaderResourceView( + ID3D11Resource* pResource, + const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc, + ID3D11ShaderResourceView** ppSRView); + + HRESULT STDMETHODCALLTYPE CreateShaderResourceView1( + ID3D11Resource* pResource, + const D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc, + ID3D11ShaderResourceView1** ppSRView); + + HRESULT STDMETHODCALLTYPE CreateUnorderedAccessView( + ID3D11Resource* pResource, + const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc, + ID3D11UnorderedAccessView** ppUAView); + + HRESULT STDMETHODCALLTYPE CreateUnorderedAccessView1( + ID3D11Resource* pResource, + const D3D11_UNORDERED_ACCESS_VIEW_DESC1* pDesc, + ID3D11UnorderedAccessView1** ppUAView); + + HRESULT STDMETHODCALLTYPE CreateRenderTargetView( + ID3D11Resource* pResource, + const D3D11_RENDER_TARGET_VIEW_DESC* pDesc, + ID3D11RenderTargetView** ppRTView); + + HRESULT STDMETHODCALLTYPE CreateRenderTargetView1( + ID3D11Resource* pResource, + const D3D11_RENDER_TARGET_VIEW_DESC1* pDesc, + ID3D11RenderTargetView1** ppRTView); + + HRESULT STDMETHODCALLTYPE CreateDepthStencilView( + ID3D11Resource* pResource, + const D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc, + ID3D11DepthStencilView** ppDepthStencilView); + + HRESULT STDMETHODCALLTYPE CreateInputLayout( + const D3D11_INPUT_ELEMENT_DESC* pInputElementDescs, + UINT NumElements, + const void* pShaderBytecodeWithInputSignature, + SIZE_T BytecodeLength, + ID3D11InputLayout** ppInputLayout); + + HRESULT STDMETHODCALLTYPE CreateVertexShader( + const void* pShaderBytecode, + SIZE_T BytecodeLength, + ID3D11ClassLinkage* pClassLinkage, + ID3D11VertexShader** ppVertexShader); + + HRESULT STDMETHODCALLTYPE CreateGeometryShader( + const void* pShaderBytecode, + SIZE_T BytecodeLength, + ID3D11ClassLinkage* pClassLinkage, + ID3D11GeometryShader** ppGeometryShader); + + HRESULT STDMETHODCALLTYPE CreateGeometryShaderWithStreamOutput( + const void* pShaderBytecode, + SIZE_T BytecodeLength, + const D3D11_SO_DECLARATION_ENTRY* pSODeclaration, + UINT NumEntries, + const UINT* pBufferStrides, + UINT NumStrides, + UINT RasterizedStream, + ID3D11ClassLinkage* pClassLinkage, + ID3D11GeometryShader** ppGeometryShader); + + HRESULT STDMETHODCALLTYPE CreatePixelShader( + const void* pShaderBytecode, + SIZE_T BytecodeLength, + ID3D11ClassLinkage* pClassLinkage, + ID3D11PixelShader** ppPixelShader); + + HRESULT STDMETHODCALLTYPE CreateHullShader( + const void* pShaderBytecode, + SIZE_T BytecodeLength, + ID3D11ClassLinkage* pClassLinkage, + ID3D11HullShader** ppHullShader); + + HRESULT STDMETHODCALLTYPE CreateDomainShader( + const void* pShaderBytecode, + SIZE_T BytecodeLength, + ID3D11ClassLinkage* pClassLinkage, + ID3D11DomainShader** ppDomainShader); + + HRESULT STDMETHODCALLTYPE CreateComputeShader( + const void* pShaderBytecode, + SIZE_T BytecodeLength, + ID3D11ClassLinkage* pClassLinkage, + ID3D11ComputeShader** ppComputeShader); + + HRESULT STDMETHODCALLTYPE CreateClassLinkage( + ID3D11ClassLinkage** ppLinkage); + + HRESULT STDMETHODCALLTYPE CreateBlendState( + const D3D11_BLEND_DESC* pBlendStateDesc, + ID3D11BlendState** ppBlendState); + + HRESULT STDMETHODCALLTYPE CreateBlendState1( + const D3D11_BLEND_DESC1* pBlendStateDesc, + ID3D11BlendState1** ppBlendState); + + HRESULT STDMETHODCALLTYPE CreateDepthStencilState( + const D3D11_DEPTH_STENCIL_DESC* pDepthStencilDesc, + ID3D11DepthStencilState** ppDepthStencilState); + + HRESULT STDMETHODCALLTYPE CreateRasterizerState( + const D3D11_RASTERIZER_DESC* pRasterizerDesc, + ID3D11RasterizerState** ppRasterizerState); + + HRESULT STDMETHODCALLTYPE CreateRasterizerState1( + const D3D11_RASTERIZER_DESC1* pRasterizerDesc, + ID3D11RasterizerState1** ppRasterizerState); + + HRESULT STDMETHODCALLTYPE CreateRasterizerState2( + const D3D11_RASTERIZER_DESC2* pRasterizerDesc, + ID3D11RasterizerState2** ppRasterizerState); + + HRESULT STDMETHODCALLTYPE CreateSamplerState( + const D3D11_SAMPLER_DESC* pSamplerDesc, + ID3D11SamplerState** ppSamplerState); + + HRESULT STDMETHODCALLTYPE CreateQuery( + const D3D11_QUERY_DESC* pQueryDesc, + ID3D11Query** ppQuery); + + HRESULT STDMETHODCALLTYPE CreateQuery1( + const D3D11_QUERY_DESC1* pQueryDesc, + ID3D11Query1** ppQuery); + + HRESULT STDMETHODCALLTYPE CreatePredicate( + const D3D11_QUERY_DESC* pPredicateDesc, + ID3D11Predicate** ppPredicate); + + HRESULT STDMETHODCALLTYPE CreateCounter( + const D3D11_COUNTER_DESC* pCounterDesc, + ID3D11Counter** ppCounter); + + HRESULT STDMETHODCALLTYPE CreateDeferredContext( + UINT ContextFlags, + ID3D11DeviceContext** ppDeferredContext); + + HRESULT STDMETHODCALLTYPE CreateDeferredContext1( + UINT ContextFlags, + ID3D11DeviceContext1** ppDeferredContext); + + HRESULT STDMETHODCALLTYPE CreateDeferredContext2( + UINT ContextFlags, + ID3D11DeviceContext2** ppDeferredContext); + + HRESULT STDMETHODCALLTYPE CreateDeferredContext3( + UINT ContextFlags, + ID3D11DeviceContext3** ppDeferredContext); + + HRESULT STDMETHODCALLTYPE CreateDeviceContextState( + UINT Flags, + const D3D_FEATURE_LEVEL* pFeatureLevels, + UINT FeatureLevels, + UINT SDKVersion, + REFIID EmulatedInterface, + D3D_FEATURE_LEVEL* pChosenFeatureLevel, + ID3DDeviceContextState** ppContextState); + + HRESULT STDMETHODCALLTYPE CreateFence( + UINT64 InitialValue, + D3D11_FENCE_FLAG Flags, + REFIID riid, + void** ppFence); + + void STDMETHODCALLTYPE ReadFromSubresource( + void* pDstData, + UINT DstRowPitch, + UINT DstDepthPitch, + ID3D11Resource* pSrcResource, + UINT SrcSubresource, + const D3D11_BOX* pSrcBox); + + void STDMETHODCALLTYPE WriteToSubresource( + ID3D11Resource* pDstResource, + UINT DstSubresource, + const D3D11_BOX* pDstBox, + const void* pSrcData, + UINT SrcRowPitch, + UINT SrcDepthPitch); + + HRESULT STDMETHODCALLTYPE OpenSharedResource( + HANDLE hResource, + REFIID ReturnedInterface, + void** ppResource); + + HRESULT STDMETHODCALLTYPE OpenSharedResource1( + HANDLE hResource, + REFIID returnedInterface, + void** ppResource); + + HRESULT STDMETHODCALLTYPE OpenSharedResourceByName( + LPCWSTR lpName, + DWORD dwDesiredAccess, + REFIID returnedInterface, + void** ppResource); + + HRESULT STDMETHODCALLTYPE OpenSharedFence( + HANDLE hFence, + REFIID ReturnedInterface, + void** ppFence); + + HRESULT STDMETHODCALLTYPE CheckFormatSupport( + DXGI_FORMAT Format, + UINT* pFormatSupport); + + HRESULT STDMETHODCALLTYPE CheckMultisampleQualityLevels( + DXGI_FORMAT Format, + UINT SampleCount, + UINT* pNumQualityLevels); + + HRESULT STDMETHODCALLTYPE CheckMultisampleQualityLevels1( + DXGI_FORMAT Format, + UINT SampleCount, + UINT Flags, + UINT* pNumQualityLevels); + + void STDMETHODCALLTYPE CheckCounterInfo( + D3D11_COUNTER_INFO* pCounterInfo); + + HRESULT STDMETHODCALLTYPE CheckCounter( + const D3D11_COUNTER_DESC* pDesc, + D3D11_COUNTER_TYPE* pType, + UINT* pActiveCounters, + LPSTR szName, + UINT* pNameLength, + LPSTR szUnits, + UINT* pUnitsLength, + LPSTR szDescription, + UINT* pDescriptionLength); + + HRESULT STDMETHODCALLTYPE CheckFeatureSupport( + D3D11_FEATURE Feature, + void* pFeatureSupportData, + UINT FeatureSupportDataSize); + + HRESULT STDMETHODCALLTYPE GetPrivateData( + REFGUID Name, + UINT *pDataSize, + void *pData); + + HRESULT STDMETHODCALLTYPE SetPrivateData( + REFGUID Name, + UINT DataSize, + const void *pData); + + HRESULT STDMETHODCALLTYPE SetPrivateDataInterface( + REFGUID Name, + const IUnknown *pUnknown); + + D3D_FEATURE_LEVEL STDMETHODCALLTYPE GetFeatureLevel(); + + UINT STDMETHODCALLTYPE GetCreationFlags(); + + HRESULT STDMETHODCALLTYPE GetDeviceRemovedReason(); + + void STDMETHODCALLTYPE GetImmediateContext( + ID3D11DeviceContext** ppImmediateContext); + + void STDMETHODCALLTYPE GetImmediateContext1( + ID3D11DeviceContext1** ppImmediateContext); + + void STDMETHODCALLTYPE GetImmediateContext2( + ID3D11DeviceContext2** ppImmediateContext); + + void STDMETHODCALLTYPE GetImmediateContext3( + ID3D11DeviceContext3** ppImmediateContext); + + HRESULT STDMETHODCALLTYPE SetExceptionMode(UINT RaiseFlags); + + UINT STDMETHODCALLTYPE GetExceptionMode(); + + void STDMETHODCALLTYPE GetResourceTiling( + ID3D11Resource* pTiledResource, + UINT* pNumTilesForEntireResource, + D3D11_PACKED_MIP_DESC* pPackedMipDesc, + D3D11_TILE_SHAPE* pStandardTileShapeForNonPackedMips, + UINT* pNumSubresourceTilings, + UINT FirstSubresourceTilingToGet, + D3D11_SUBRESOURCE_TILING* pSubresourceTilingsForNonPackedMips); + + HRESULT STDMETHODCALLTYPE RegisterDeviceRemovedEvent( + HANDLE hEvent, + DWORD* pdwCookie); + + void STDMETHODCALLTYPE UnregisterDeviceRemoved( + DWORD dwCookie); + + Rc GetDXVKDevice() { + return m_dxvkDevice; + } + + void FlushInitContext(); + + VkPipelineStageFlags GetEnabledShaderStages() const { + return m_dxvkDevice->getShaderPipelineStages(); + } + + DXGI_VK_FORMAT_INFO LookupFormat( + DXGI_FORMAT Format, + DXGI_VK_FORMAT_MODE Mode) const; + + DXGI_VK_FORMAT_INFO LookupPackedFormat( + DXGI_FORMAT Format, + DXGI_VK_FORMAT_MODE Mode) const; + + DXGI_VK_FORMAT_FAMILY LookupFamily( + DXGI_FORMAT Format, + DXGI_VK_FORMAT_MODE Mode) const; + + DxvkCsChunkRef AllocCsChunk(DxvkCsChunkFlags flags) { + DxvkCsChunk* chunk = m_csChunkPool.allocChunk(flags); + return DxvkCsChunkRef(chunk, &m_csChunkPool); + } + + const D3D11Options* GetOptions() const { + return &m_d3d11Options; + } + + D3D10Device* GetD3D10Interface() const { + return m_d3d10Device; + } + + static bool CheckFeatureLevelSupport( + const Rc& instance, + const Rc& adapter, + D3D_FEATURE_LEVEL featureLevel); + + static DxvkDeviceFeatures GetDeviceFeatures( + const Rc& adapter, + D3D_FEATURE_LEVEL featureLevel); + + private: + + IDXGIObject* m_container; + + D3D_FEATURE_LEVEL m_featureLevel; + UINT m_featureFlags; + + const Rc m_dxvkDevice; + const Rc m_dxvkAdapter; + + const DXGIVkFormatTable m_d3d11Formats; + const D3D11Options m_d3d11Options; + const DxbcOptions m_dxbcOptions; + + DxvkCsChunkPool m_csChunkPool; + + D3D11Initializer* m_initializer = nullptr; + D3D10Device* m_d3d10Device = nullptr; + Com m_context; + + D3D11StateObjectSet m_bsStateObjects; + D3D11StateObjectSet m_dsStateObjects; + D3D11StateObjectSet m_rsStateObjects; + D3D11StateObjectSet m_samplerObjects; + D3D11ShaderModuleSet m_shaderModules; + + HRESULT CreateShaderModule( + D3D11CommonShader* pShaderModule, + DxvkShaderKey ShaderKey, + const void* pShaderBytecode, + size_t BytecodeLength, + ID3D11ClassLinkage* pClassLinkage, + const DxbcModuleInfo* pModuleInfo); + + HRESULT GetFormatSupportFlags( + DXGI_FORMAT Format, + UINT* pFlags1, + UINT* pFlags2) const; + + BOOL GetImageTypeSupport( + VkFormat Format, + VkImageType Type) const; + + template + HRESULT OpenSharedResourceGeneric( + HANDLE hResource, + REFIID ReturnedInterface, + void** ppResource); + + uint32_t GetViewPlaneIndex( + ID3D11Resource* pResource, + DXGI_FORMAT ViewFormat); + + template + void CopySubresourceData( + Void* pData, + UINT RowPitch, + UINT DepthPitch, + ID3D11Resource* pResource, + UINT Subresource, + const D3D11_BOX* pBox); + + static D3D_FEATURE_LEVEL GetMaxFeatureLevel( + const Rc& pInstance); + + }; + + + /** + * \brief Extended D3D11 device + */ + class D3D11DeviceExt : public ID3D11VkExtDevice1 { + + public: + + D3D11DeviceExt( + D3D11DXGIDevice* pContainer, + D3D11Device* pDevice); + + ULONG STDMETHODCALLTYPE AddRef(); + + ULONG STDMETHODCALLTYPE Release(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + BOOL STDMETHODCALLTYPE GetExtensionSupport( + D3D11_VK_EXTENSION Extension); + + bool STDMETHODCALLTYPE GetCudaTextureObjectNVX( + uint32_t srvDriverHandle, + uint32_t samplerDriverHandle, + uint32_t* pCudaTextureHandle); + + bool STDMETHODCALLTYPE CreateCubinComputeShaderWithNameNVX( + const void* pCubin, + uint32_t size, + uint32_t blockX, + uint32_t blockY, + uint32_t blockZ, + const char* pShaderName, + IUnknown** phShader); + + bool STDMETHODCALLTYPE GetResourceHandleGPUVirtualAddressAndSizeNVX( + void* hObject, + uint64_t* gpuVAStart, + uint64_t* gpuVASize); + + bool STDMETHODCALLTYPE CreateUnorderedAccessViewAndGetDriverHandleNVX( + ID3D11Resource* pResource, + const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc, + ID3D11UnorderedAccessView** ppUAV, + uint32_t* pDriverHandle); + + bool STDMETHODCALLTYPE CreateShaderResourceViewAndGetDriverHandleNVX( + ID3D11Resource* pResource, + const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc, + ID3D11ShaderResourceView** ppSRV, + uint32_t* pDriverHandle); + + bool STDMETHODCALLTYPE CreateSamplerStateAndGetDriverHandleNVX( + const D3D11_SAMPLER_DESC* pSamplerDesc, + ID3D11SamplerState** ppSamplerState, + uint32_t* pDriverHandle); + + private: + + D3D11DXGIDevice* m_container; + D3D11Device* m_device; + + void AddSamplerAndHandleNVX( + ID3D11SamplerState* pSampler, + uint32_t Handle); + + ID3D11SamplerState* HandleToSamplerNVX( + uint32_t Handle); + + void AddSrvAndHandleNVX( + ID3D11ShaderResourceView* pSrv, + uint32_t Handle); + + ID3D11ShaderResourceView* HandleToSrvNVX( + uint32_t Handle); + + dxvk::mutex m_mapLock; + std::unordered_map m_samplerHandleToPtr; + std::unordered_map m_srvHandleToPtr; + }; + + + /** + * \brief D3D11 video device + */ + class D3D11VideoDevice : public ID3D11VideoDevice { + + public: + + D3D11VideoDevice( + D3D11DXGIDevice* pContainer, + D3D11Device* pDevice); + + ~D3D11VideoDevice(); + + ULONG STDMETHODCALLTYPE AddRef(); + + ULONG STDMETHODCALLTYPE Release(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + HRESULT STDMETHODCALLTYPE CreateVideoDecoder( + const D3D11_VIDEO_DECODER_DESC* pVideoDesc, + const D3D11_VIDEO_DECODER_CONFIG* pConfig, + ID3D11VideoDecoder** ppDecoder); + + HRESULT STDMETHODCALLTYPE CreateVideoProcessor( + ID3D11VideoProcessorEnumerator* pEnum, + UINT RateConversionIndex, + ID3D11VideoProcessor** ppVideoProcessor); + + HRESULT STDMETHODCALLTYPE CreateAuthenticatedChannel( + D3D11_AUTHENTICATED_CHANNEL_TYPE ChannelType, + ID3D11AuthenticatedChannel** ppAuthenticatedChannel); + + HRESULT STDMETHODCALLTYPE CreateCryptoSession( + const GUID* pCryptoType, + const GUID* pDecoderProfile, + const GUID* pKeyExchangeType, + ID3D11CryptoSession** ppCryptoSession); + + HRESULT STDMETHODCALLTYPE CreateVideoDecoderOutputView( + ID3D11Resource* pResource, + const D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC* pDesc, + ID3D11VideoDecoderOutputView** ppVDOVView); + + HRESULT STDMETHODCALLTYPE CreateVideoProcessorInputView( + ID3D11Resource* pResource, + ID3D11VideoProcessorEnumerator* pEnum, + const D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC* pDesc, + ID3D11VideoProcessorInputView** ppVPIView); + + HRESULT STDMETHODCALLTYPE CreateVideoProcessorOutputView( + ID3D11Resource* pResource, + ID3D11VideoProcessorEnumerator* pEnum, + const D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC* pDesc, + ID3D11VideoProcessorOutputView** ppVPOView); + + HRESULT STDMETHODCALLTYPE CreateVideoProcessorEnumerator( + const D3D11_VIDEO_PROCESSOR_CONTENT_DESC* pDesc, + ID3D11VideoProcessorEnumerator** ppEnum); + + UINT STDMETHODCALLTYPE GetVideoDecoderProfileCount(); + + HRESULT STDMETHODCALLTYPE GetVideoDecoderProfile( + UINT Index, + GUID* pDecoderProfile); + + HRESULT STDMETHODCALLTYPE CheckVideoDecoderFormat( + const GUID* pDecoderProfile, + DXGI_FORMAT Format, + BOOL* pSupported); + + HRESULT STDMETHODCALLTYPE GetVideoDecoderConfigCount( + const D3D11_VIDEO_DECODER_DESC* pDesc, + UINT* pCount); + + HRESULT STDMETHODCALLTYPE GetVideoDecoderConfig( + const D3D11_VIDEO_DECODER_DESC* pDesc, + UINT Index, + D3D11_VIDEO_DECODER_CONFIG* pConfig); + + HRESULT STDMETHODCALLTYPE GetContentProtectionCaps( + const GUID* pCryptoType, + const GUID* pDecoderProfile, + D3D11_VIDEO_CONTENT_PROTECTION_CAPS* pCaps); + + HRESULT STDMETHODCALLTYPE CheckCryptoKeyExchange( + const GUID* pCryptoType, + const GUID* pDecoderProfile, + UINT Index, + GUID* pKeyExchangeType); + + HRESULT STDMETHODCALLTYPE SetPrivateData( + REFGUID Name, + UINT DataSize, + const void* pData); + + HRESULT STDMETHODCALLTYPE SetPrivateDataInterface( + REFGUID Name, + const IUnknown* pData); + + private: + + D3D11DXGIDevice* m_container; + D3D11Device* m_device; + + }; + + + /** + * \brief DXGI swap chain factory + */ + class WineDXGISwapChainFactory : public IWineDXGISwapChainFactory { + + public: + + WineDXGISwapChainFactory( + D3D11DXGIDevice* pContainer, + D3D11Device* pDevice); + + ULONG STDMETHODCALLTYPE AddRef(); + + ULONG STDMETHODCALLTYPE Release(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + HRESULT STDMETHODCALLTYPE CreateSwapChainForHwnd( + IDXGIFactory* pFactory, + HWND hWnd, + const DXGI_SWAP_CHAIN_DESC1* pDesc, + const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc, + IDXGIOutput* pRestrictToOutput, + IDXGISwapChain1** ppSwapChain); + + private: + + D3D11DXGIDevice* m_container; + D3D11Device* m_device; + + }; + + + /** + * \brief D3D11 device metadata shenanigans + */ + class DXGIDXVKDevice : public IDXGIDXVKDevice { + + public: + + DXGIDXVKDevice(D3D11DXGIDevice* pContainer); + + ULONG STDMETHODCALLTYPE AddRef(); + + ULONG STDMETHODCALLTYPE Release(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + void STDMETHODCALLTYPE SetAPIVersion( + UINT Version); + + UINT STDMETHODCALLTYPE GetAPIVersion(); + + private: + + D3D11DXGIDevice* m_container; + UINT m_apiVersion; + + }; + + + /** + * \brief D3D11 device container + * + * Stores all the objects that contribute to the D3D11 + * device implementation, including the DXGI device. + */ + class D3D11DXGIDevice : public DxgiObject { + constexpr static uint32_t DefaultFrameLatency = 3; + public: + + D3D11DXGIDevice( + IDXGIAdapter* pAdapter, + const Rc& pDxvkInstance, + const Rc& pDxvkAdapter, + D3D_FEATURE_LEVEL FeatureLevel, + UINT FeatureFlags); + + ~D3D11DXGIDevice(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + HRESULT STDMETHODCALLTYPE GetParent( + REFIID riid, + void** ppParent); + + HRESULT STDMETHODCALLTYPE CreateSurface( + const DXGI_SURFACE_DESC* pDesc, + UINT NumSurfaces, + DXGI_USAGE Usage, + const DXGI_SHARED_RESOURCE* pSharedResource, + IDXGISurface** ppSurface) final; + + HRESULT STDMETHODCALLTYPE GetAdapter( + IDXGIAdapter** pAdapter) final; + + HRESULT STDMETHODCALLTYPE GetGPUThreadPriority( + INT* pPriority) final; + + HRESULT STDMETHODCALLTYPE QueryResourceResidency( + IUnknown* const* ppResources, + DXGI_RESIDENCY* pResidencyStatus, + UINT NumResources) final; + + HRESULT STDMETHODCALLTYPE SetGPUThreadPriority( + INT Priority) final; + + HRESULT STDMETHODCALLTYPE GetMaximumFrameLatency( + UINT* pMaxLatency) final; + + HRESULT STDMETHODCALLTYPE SetMaximumFrameLatency( + UINT MaxLatency) final; + + HRESULT STDMETHODCALLTYPE OfferResources( + UINT NumResources, + IDXGIResource* const* ppResources, + DXGI_OFFER_RESOURCE_PRIORITY Priority) final; + + HRESULT STDMETHODCALLTYPE OfferResources1( + UINT NumResources, + IDXGIResource* const* ppResources, + DXGI_OFFER_RESOURCE_PRIORITY Priority, + UINT Flags) final; + + HRESULT STDMETHODCALLTYPE ReclaimResources( + UINT NumResources, + IDXGIResource* const* ppResources, + BOOL* pDiscarded) final; + + HRESULT STDMETHODCALLTYPE ReclaimResources1( + UINT NumResources, + IDXGIResource* const* ppResources, + DXGI_RECLAIM_RESOURCE_RESULTS* pResults) final; + + HRESULT STDMETHODCALLTYPE EnqueueSetEvent( + HANDLE hEvent) final; + + void STDMETHODCALLTYPE Trim() final; + + Rc STDMETHODCALLTYPE GetDXVKDevice(); + + private: + + Com m_dxgiAdapter; + + Rc m_dxvkInstance; + Rc m_dxvkAdapter; + Rc m_dxvkDevice; + + D3D11Device m_d3d11Device; + D3D11DeviceExt m_d3d11DeviceExt; + D3D11VkInterop m_d3d11Interop; + D3D11VideoDevice m_d3d11Video; + DXGIDXVKDevice m_metaDevice; + + WineDXGISwapChainFactory m_wineFactory; + + uint32_t m_frameLatency = DefaultFrameLatency; + + Rc CreateDevice(D3D_FEATURE_LEVEL FeatureLevel); + + }; + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_device_child.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_device_child.h new file mode 100644 index 00000000000..60eff07afd8 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_device_child.h @@ -0,0 +1,130 @@ +#pragma once + +#include "d3d11_include.h" + +#include "../util/com/com_private_data.h" + +namespace dxvk { + + class D3D11Device; + + template + class D3D11DeviceObject : public Base { + + public: + + D3D11DeviceObject(D3D11Device* pDevice) + : m_parent(pDevice) { + + } + + HRESULT STDMETHODCALLTYPE GetPrivateData( + REFGUID guid, + UINT *pDataSize, + void *pData) final { + return m_privateData.getData( + guid, pDataSize, pData); + } + + HRESULT STDMETHODCALLTYPE SetPrivateData( + REFGUID guid, + UINT DataSize, + const void *pData) final { + return m_privateData.setData( + guid, DataSize, pData); + } + + HRESULT STDMETHODCALLTYPE SetPrivateDataInterface( + REFGUID guid, + const IUnknown *pUnknown) final { + return m_privateData.setInterface( + guid, pUnknown); + } + + void STDMETHODCALLTYPE GetDevice( + ID3D11Device** ppDevice) final { + *ppDevice = ref(GetParentInterface()); + } + + protected: + + ID3D11Device* GetParentInterface() const { + // We don't know the definition of ID3D11Device + // here, because D3D11Device includes this file. + return reinterpret_cast(m_parent); + } + + D3D11Device* const m_parent; + + private: + + ComPrivateData m_privateData; + + }; + + + template + class D3D11DeviceChild : public D3D11DeviceObject> { + + public: + + D3D11DeviceChild(D3D11Device* pDevice) + : D3D11DeviceObject>(pDevice) { + + } + + ULONG STDMETHODCALLTYPE AddRef() { + uint32_t refCount = this->m_refCount++; + if (unlikely(!refCount)) { + this->AddRefPrivate(); + this->GetParentInterface()->AddRef(); + } + + return refCount + 1; + } + + ULONG STDMETHODCALLTYPE Release() { + uint32_t refCount = --this->m_refCount; + if (unlikely(!refCount)) { + auto* parent = this->GetParentInterface(); + this->ReleasePrivate(); + parent->Release(); + } + return refCount; + } + + }; + + template + class D3D11StateObject : public D3D11DeviceObject { + + public: + + D3D11StateObject(D3D11Device* pDevice) + : D3D11DeviceObject(pDevice) { + + } + + ULONG STDMETHODCALLTYPE AddRef() { + uint32_t refCount = this->m_refCount++; + if (unlikely(!refCount)) + this->GetParentInterface()->AddRef(); + + return refCount + 1; + } + + ULONG STDMETHODCALLTYPE Release() { + uint32_t refCount = --this->m_refCount; + if (unlikely(!refCount)) + this->GetParentInterface()->Release(); + + return refCount; + } + + private: + + std::atomic m_refCount = { 0u }; + + }; + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_enums.cpp b/utils/dxvk-1.10.3/src/d3d11/d3d11_enums.cpp new file mode 100644 index 00000000000..24af0276c81 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_enums.cpp @@ -0,0 +1,16 @@ +#include "d3d11_enums.h" + +std::ostream& operator << (std::ostream& os, D3D_FEATURE_LEVEL e) { + switch (e) { + ENUM_NAME(D3D_FEATURE_LEVEL_9_1); + ENUM_NAME(D3D_FEATURE_LEVEL_9_2); + ENUM_NAME(D3D_FEATURE_LEVEL_9_3); + ENUM_NAME(D3D_FEATURE_LEVEL_10_0); + ENUM_NAME(D3D_FEATURE_LEVEL_10_1); + ENUM_NAME(D3D_FEATURE_LEVEL_11_0); + ENUM_NAME(D3D_FEATURE_LEVEL_11_1); + ENUM_NAME(D3D_FEATURE_LEVEL_12_0); + ENUM_NAME(D3D_FEATURE_LEVEL_12_1); + ENUM_DEFAULT(e); + } +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_enums.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_enums.h new file mode 100644 index 00000000000..d67d0cddc0c --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_enums.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +#include "d3d11_include.h" + +std::ostream& operator << (std::ostream& os, D3D_FEATURE_LEVEL e); \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_fence.cpp b/utils/dxvk-1.10.3/src/d3d11/d3d11_fence.cpp new file mode 100644 index 00000000000..e3c7688b2d6 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_fence.cpp @@ -0,0 +1,101 @@ +#include "d3d11_fence.h" +#include "d3d11_device.h" + +namespace dxvk { + + D3D11Fence::D3D11Fence( + D3D11Device* pDevice, + UINT64 InitialValue, + D3D11_FENCE_FLAG Flags, + HANDLE hFence) + : D3D11DeviceChild(pDevice) { + DxvkFenceCreateInfo fenceInfo; + fenceInfo.initialValue = InitialValue; + m_flags = Flags; + + if (Flags & D3D11_FENCE_FLAG_SHARED) { + fenceInfo.sharedType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D11_FENCE_BIT; + if (hFence == nullptr) + hFence = INVALID_HANDLE_VALUE; + fenceInfo.sharedHandle = hFence; + } + + if (Flags & ~D3D11_FENCE_FLAG_SHARED) + Logger::err(str::format("Fence flags 0x", std::hex, Flags, " not supported")); + + m_fence = pDevice->GetDXVKDevice()->createFence(fenceInfo); + } + + + D3D11Fence::~D3D11Fence() { + + } + + + HRESULT STDMETHODCALLTYPE D3D11Fence::QueryInterface( + REFIID riid, + void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(ID3D11DeviceChild) + || riid == __uuidof(ID3D11Fence)) { + *ppvObject = ref(this); + return S_OK; + } + + Logger::warn("D3D11Fence: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + HRESULT STDMETHODCALLTYPE D3D11Fence::CreateSharedHandle( + const SECURITY_ATTRIBUTES* pAttributes, + DWORD dwAccess, + LPCWSTR lpName, + HANDLE* pHandle) { + if (!(m_flags & D3D11_FENCE_FLAG_SHARED)) + return E_INVALIDARG; + + if (pAttributes) + Logger::warn(str::format("CreateSharedHandle: attributes ", pAttributes, " not handled")); + if (dwAccess) + Logger::warn(str::format("CreateSharedHandle: access ", dwAccess, " not handled")); + if (lpName) + Logger::warn(str::format("CreateSharedHandle: name ", dxvk::str::fromws(lpName), " not handled")); + + HANDLE sharedHandle = m_fence->sharedHandle(); + if (sharedHandle == INVALID_HANDLE_VALUE) + return E_INVALIDARG; + + *pHandle = sharedHandle; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11Fence::SetEventOnCompletion( + UINT64 Value, + HANDLE hEvent) { + // TODO in case of rewinds, the stored value may be higher. + // For shared fences, calling vkWaitSemaphores here could alleviate the issue. + + m_fence->enqueueWait(Value, [hEvent] { + SetEvent(hEvent); + }); + + return S_OK; + } + + + UINT64 STDMETHODCALLTYPE D3D11Fence::GetCompletedValue() { + // TODO in the case of rewinds, the stored value may be higher. + // For shared fences, calling vkGetSemaphoreCounterValue here could alleviate the issue. + + return m_fence->getValue(); + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_fence.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_fence.h new file mode 100644 index 00000000000..99d42a9431c --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_fence.h @@ -0,0 +1,49 @@ +#pragma once + +#include "../dxvk/dxvk_fence.h" +#include "../dxvk/dxvk_gpu_query.h" + +#include "d3d11_device_child.h" + +namespace dxvk { + + class D3D11Fence : public D3D11DeviceChild { + + public: + + D3D11Fence( + D3D11Device* pDevice, + UINT64 InitialValue, + D3D11_FENCE_FLAG Flags, + HANDLE hFence); + + ~D3D11Fence(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + HRESULT STDMETHODCALLTYPE CreateSharedHandle( + const SECURITY_ATTRIBUTES* pAttributes, + DWORD dwAccess, + LPCWSTR lpName, + HANDLE* pHandle); + + HRESULT STDMETHODCALLTYPE SetEventOnCompletion( + UINT64 Value, + HANDLE hEvent); + + UINT64 STDMETHODCALLTYPE GetCompletedValue(); + + Rc GetFence() const { + return m_fence; + } + + private: + + Rc m_fence; + D3D11_FENCE_FLAG m_flags; + + }; + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_gdi.cpp b/utils/dxvk-1.10.3/src/d3d11/d3d11_gdi.cpp new file mode 100644 index 00000000000..0958886eca9 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_gdi.cpp @@ -0,0 +1,206 @@ +#include "d3d11_context.h" +#include "d3d11_device.h" +#include "d3d11_gdi.h" + +#include "../util/util_gdi.h" + +namespace dxvk { + + D3D11GDISurface::D3D11GDISurface( + ID3D11Resource* pResource, + UINT Subresource) + : m_resource (pResource), + m_subresource (Subresource), + m_readback (nullptr), + m_hdc (nullptr), + m_hbitmap (nullptr), + m_acquired (false) { + // Allocate memory for the bitmap + auto tex = GetCommonTexture(m_resource)->Desc(); + m_data.resize(tex->Width * tex->Height); + + // Create GDI DC + D3DKMT_CREATEDCFROMMEMORY desc; + desc.pMemory = m_data.data(); + desc.Format = D3DFMT_A8R8G8B8; + desc.Width = tex->Width; + desc.Height = tex->Height; + desc.Pitch = tex->Width * sizeof(uint32_t); + desc.hDeviceDc = CreateCompatibleDC(nullptr); + desc.pColorTable = nullptr; + desc.hDc = nullptr; + desc.hBitmap = nullptr; + + if (D3DKMTCreateDCFromMemory(&desc)) + Logger::err(str::format("D3D11: Failed to create GDI DC")); + + m_hdc = desc.hDc; + m_hbitmap = desc.hBitmap; + } + + + D3D11GDISurface::~D3D11GDISurface() { + if (m_readback) + m_readback->Release(); + + D3DKMT_DESTROYDCFROMMEMORY desc; + desc.hDC = m_hdc; + desc.hBitmap = m_hbitmap; + D3DKMTDestroyDCFromMemory(&desc); + } + + + HRESULT D3D11GDISurface::Acquire(BOOL Discard, HDC* phdc) { + if (!phdc) + return E_INVALIDARG; + + *phdc = nullptr; + + if (m_acquired) + return DXGI_ERROR_INVALID_CALL; + + if (!Discard) { + // Create a staging resource that we can map + if (!m_readback && FAILED(CreateReadbackResource())) { + Logger::err("D3D11: Failed to create GDI readback resource"); + return E_FAIL; + } + + // Copy subresource to staging image + Com device; + Com context; + + m_resource->GetDevice(&device); + device->GetImmediateContext(&context); + + context->CopySubresourceRegion(m_readback, 0, + 0, 0, 0, m_resource, m_subresource, nullptr); + + // Copy staging image to DC memory + auto tex = GetCommonTexture(m_resource)->Desc(); + auto rowData = reinterpret_cast(m_data.data()); + auto rowLength = sizeof(uint32_t) * tex->Width; + + D3D11_MAPPED_SUBRESOURCE sr; + context->Map(m_readback, 0, D3D11_MAP_READ, 0, &sr); + + for (uint32_t i = 0; i < tex->Height; i++) { + std::memcpy(rowData + rowLength * i, + reinterpret_cast(sr.pData) + sr.RowPitch * i, + rowLength); + } + + context->Unmap(m_readback, 0); + } + + m_acquired = true; + *phdc = m_hdc; + return S_OK; + } + + + HRESULT D3D11GDISurface::Release(const RECT* pDirtyRect) { + if (!m_acquired) + return DXGI_ERROR_INVALID_CALL; + + Com device; + Com context; + + m_resource->GetDevice(&device); + device->GetImmediateContext(&context); + + // Commit changes made to the DC + auto tex = GetCommonTexture(m_resource)->Desc(); + + RECT rect; + + if (pDirtyRect) { + rect.left = std::max(pDirtyRect->left, 0); + rect.top = std::max(pDirtyRect->top, 0); + rect.right = std::min(pDirtyRect->right, tex->Width); + rect.bottom = std::min(pDirtyRect->bottom, tex->Height); + } else { + rect.left = 0; + rect.top = 0; + rect.right = tex->Width; + rect.bottom = tex->Height; + } + + if (rect.left < rect.right && rect.top < rect.bottom) { + D3D11_BOX box; + box.left = rect.left; + box.top = rect.top; + box.front = 0; + box.right = rect.right; + box.bottom = rect.bottom; + box.back = 1; + + context->UpdateSubresource(m_resource, m_subresource, + &box, m_data.data() + rect.left, + sizeof(uint32_t) * tex->Width, + sizeof(uint32_t) * tex->Width * tex->Height); + } + + m_acquired = false; + return S_OK; + } + + + HRESULT D3D11GDISurface::CreateReadbackResource() { + auto tex = GetCommonTexture(m_resource); + + Com device; + Com context; + + m_resource->GetDevice(&device); + device->GetImmediateContext(&context); + + D3D11_RESOURCE_DIMENSION dim = { }; + m_resource->GetType(&dim); + + VkImageSubresource sr = tex->GetSubresourceFromIndex( + VK_IMAGE_ASPECT_COLOR_BIT, m_subresource); + + switch (dim) { + case D3D11_RESOURCE_DIMENSION_TEXTURE1D: { + D3D11_TEXTURE1D_DESC desc; + desc.Width = std::max(tex->Desc()->Width >> sr.mipLevel, 1); + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = tex->Desc()->Format; + desc.Usage = D3D11_USAGE_STAGING; + desc.BindFlags = 0; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + desc.MiscFlags = 0; + + ID3D11Texture1D* tex1D = nullptr; + HRESULT hr = device->CreateTexture1D(&desc, nullptr, &tex1D); + m_readback = tex1D; + return hr; + } break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE2D: { + D3D11_TEXTURE2D_DESC desc; + desc.Width = std::max(tex->Desc()->Width >> sr.mipLevel, 1); + desc.Height = std::max(tex->Desc()->Height >> sr.mipLevel, 1); + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = tex->Desc()->Format; + desc.SampleDesc= { 1, 0 }; + desc.Usage = D3D11_USAGE_STAGING; + desc.BindFlags = 0; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + desc.MiscFlags = 0; + + ID3D11Texture2D* tex2D = nullptr; + HRESULT hr = device->CreateTexture2D(&desc, nullptr, &tex2D); + m_readback = tex2D; + return hr; + } break; + + default: + return E_INVALIDARG; + } + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_gdi.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_gdi.h new file mode 100644 index 00000000000..a2656c0a99b --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_gdi.h @@ -0,0 +1,41 @@ +#pragma once + +#include + +#include "d3d11_include.h" + +namespace dxvk { + + class D3D11GDISurface { + + public: + + D3D11GDISurface( + ID3D11Resource* pResource, + UINT Subresource); + + ~D3D11GDISurface(); + + HRESULT Acquire( + BOOL Discard, + HDC* phdc); + + HRESULT Release( + const RECT* pDirtyRect); + + private: + + ID3D11Resource* m_resource; + uint32_t m_subresource; + ID3D11Resource* m_readback; + HDC m_hdc; + HANDLE m_hbitmap; + bool m_acquired; + + std::vector m_data; + + HRESULT CreateReadbackResource(); + + }; + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_include.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_include.h new file mode 100644 index 00000000000..1598088af6a --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_include.h @@ -0,0 +1,46 @@ +#pragma once + +#include "../dxgi/dxgi_include.h" + +#include + +// This is not defined in the mingw headers +#ifndef D3D11_1_UAV_SLOT_COUNT +#define D3D11_1_UAV_SLOT_COUNT 64 +#endif + +#ifndef D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL +#define D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL 0xFFFFFFFF +#endif + +#ifndef D3D11_KEEP_UNORDERED_ACCESS_VIEWS +#define D3D11_KEEP_UNORDERED_ACCESS_VIEWS 0xFFFFFFFF +#endif + +#define D3D11_DXVK_USE_REMAINING_LAYERS 0xFFFFFFFF +#define D3D11_DXVK_USE_REMAINING_LEVELS 0xFFFFFFFF + +// Most of these were copied from d3d11.h +// For some strange reason, we cannot use the structures +// directly, although others from the same header work. +// Some structures are missing from the mingw headers. +#ifndef _MSC_VER +#if !defined(__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 9 +typedef enum D3D11_FORMAT_SUPPORT2 { + D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_ADD = 0x1, + D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_BITWISE_OPS = 0x2, + D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_COMPARE_STORE_OR_COMPARE_EXCHANGE = 0x4, + D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_EXCHANGE = 0x8, + D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_SIGNED_MIN_OR_MAX = 0x10, + D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_UNSIGNED_MIN_OR_MAX = 0x20, + D3D11_FORMAT_SUPPORT2_UAV_TYPED_LOAD = 0x40, + D3D11_FORMAT_SUPPORT2_UAV_TYPED_STORE = 0x80, + D3D11_FORMAT_SUPPORT2_OUTPUT_MERGER_LOGIC_OP = 0x100, + D3D11_FORMAT_SUPPORT2_TILED = 0x200, + D3D11_FORMAT_SUPPORT2_SHAREABLE = 0x400, + D3D11_FORMAT_SUPPORT2_MULTIPLANE_OVERLAY = 0x4000 +} D3D11_FORMAT_SUPPORT2; +#define D3D11_RESOURCE_MISC_TILE_POOL (0x20000) +#define D3D11_RESOURCE_MISC_TILED (0x40000) +#endif // !defined(__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 9 +#endif // _MSC_VER diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_initializer.cpp b/utils/dxvk-1.10.3/src/d3d11/d3d11_initializer.cpp new file mode 100644 index 00000000000..863c453e717 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_initializer.cpp @@ -0,0 +1,270 @@ +#include + +#include "d3d11_device.h" +#include "d3d11_initializer.h" + +namespace dxvk { + + D3D11Initializer::D3D11Initializer( + D3D11Device* pParent) + : m_parent(pParent), + m_device(pParent->GetDXVKDevice()), + m_context(m_device->createContext()) { + m_context->beginRecording( + m_device->createCommandList()); + } + + + D3D11Initializer::~D3D11Initializer() { + + } + + + void D3D11Initializer::Flush() { + std::lock_guard lock(m_mutex); + + if (m_transferCommands != 0) + FlushInternal(); + } + + void D3D11Initializer::InitBuffer( + D3D11Buffer* pBuffer, + const D3D11_SUBRESOURCE_DATA* pInitialData) { + VkMemoryPropertyFlags memFlags = pBuffer->GetBuffer()->memFlags(); + + (memFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) + ? InitHostVisibleBuffer(pBuffer, pInitialData) + : InitDeviceLocalBuffer(pBuffer, pInitialData); + } + + + void D3D11Initializer::InitTexture( + D3D11CommonTexture* pTexture, + const D3D11_SUBRESOURCE_DATA* pInitialData) { + (pTexture->GetMapMode() == D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT) + ? InitHostVisibleTexture(pTexture, pInitialData) + : InitDeviceLocalTexture(pTexture, pInitialData); + } + + + void D3D11Initializer::InitUavCounter( + D3D11UnorderedAccessView* pUav) { + auto counterBuffer = pUav->GetCounterSlice(); + + if (!counterBuffer.defined()) + return; + + std::lock_guard lock(m_mutex); + m_transferCommands += 1; + + const uint32_t zero = 0; + m_context->updateBuffer( + counterBuffer.buffer(), + 0, sizeof(zero), &zero); + + FlushImplicit(); + } + + + void D3D11Initializer::InitDeviceLocalBuffer( + D3D11Buffer* pBuffer, + const D3D11_SUBRESOURCE_DATA* pInitialData) { + std::lock_guard lock(m_mutex); + + DxvkBufferSlice bufferSlice = pBuffer->GetBufferSlice(); + + if (pInitialData != nullptr && pInitialData->pSysMem != nullptr) { + m_transferMemory += bufferSlice.length(); + m_transferCommands += 1; + + m_context->uploadBuffer( + bufferSlice.buffer(), + pInitialData->pSysMem); + } else { + m_transferCommands += 1; + + m_context->initBuffer( + bufferSlice.buffer()); + } + + FlushImplicit(); + } + + + void D3D11Initializer::InitHostVisibleBuffer( + D3D11Buffer* pBuffer, + const D3D11_SUBRESOURCE_DATA* pInitialData) { + // If the buffer is mapped, we can write data directly + // to the mapped memory region instead of doing it on + // the GPU. Same goes for zero-initialization. + DxvkBufferSlice bufferSlice = pBuffer->GetBufferSlice(); + + if (pInitialData != nullptr && pInitialData->pSysMem != nullptr) { + std::memcpy( + bufferSlice.mapPtr(0), + pInitialData->pSysMem, + bufferSlice.length()); + } else { + std::memset( + bufferSlice.mapPtr(0), 0, + bufferSlice.length()); + } + } + + + void D3D11Initializer::InitDeviceLocalTexture( + D3D11CommonTexture* pTexture, + const D3D11_SUBRESOURCE_DATA* pInitialData) { + std::lock_guard lock(m_mutex); + + Rc image = pTexture->GetImage(); + + auto mapMode = pTexture->GetMapMode(); + auto desc = pTexture->Desc(); + + VkFormat packedFormat = m_parent->LookupPackedFormat(desc->Format, pTexture->GetFormatMode()).Format; + auto formatInfo = imageFormatInfo(packedFormat); + + if (pInitialData != nullptr && pInitialData->pSysMem != nullptr) { + // pInitialData is an array that stores an entry for + // every single subresource. Since we will define all + // subresources, this counts as initialization. + for (uint32_t layer = 0; layer < desc->ArraySize; layer++) { + for (uint32_t level = 0; level < desc->MipLevels; level++) { + const uint32_t id = D3D11CalcSubresource( + level, layer, desc->MipLevels); + + VkOffset3D mipLevelOffset = { 0, 0, 0 }; + VkExtent3D mipLevelExtent = pTexture->MipLevelExtent(level); + + if (mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_STAGING) { + m_transferCommands += 1; + m_transferMemory += pTexture->GetSubresourceLayout(formatInfo->aspectMask, id).Size; + + VkImageSubresourceLayers subresourceLayers; + subresourceLayers.aspectMask = formatInfo->aspectMask; + subresourceLayers.mipLevel = level; + subresourceLayers.baseArrayLayer = layer; + subresourceLayers.layerCount = 1; + + if (formatInfo->aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { + m_context->uploadImage( + image, subresourceLayers, + pInitialData[id].pSysMem, + pInitialData[id].SysMemPitch, + pInitialData[id].SysMemSlicePitch); + } else { + m_context->updateDepthStencilImage( + image, subresourceLayers, + VkOffset2D { mipLevelOffset.x, mipLevelOffset.y }, + VkExtent2D { mipLevelExtent.width, mipLevelExtent.height }, + pInitialData[id].pSysMem, + pInitialData[id].SysMemPitch, + pInitialData[id].SysMemSlicePitch, + packedFormat); + } + } + + if (mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_NONE) { + util::packImageData(pTexture->GetMappedBuffer(id)->mapPtr(0), + pInitialData[id].pSysMem, pInitialData[id].SysMemPitch, pInitialData[id].SysMemSlicePitch, + 0, 0, pTexture->GetVkImageType(), mipLevelExtent, 1, formatInfo, formatInfo->aspectMask); + } + } + } + } else { + if (mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_STAGING) { + m_transferCommands += 1; + + // While the Microsoft docs state that resource contents are + // undefined if no initial data is provided, some applications + // expect a resource to be pre-cleared. + VkImageSubresourceRange subresources; + subresources.aspectMask = formatInfo->aspectMask; + subresources.baseMipLevel = 0; + subresources.levelCount = desc->MipLevels; + subresources.baseArrayLayer = 0; + subresources.layerCount = desc->ArraySize; + + m_context->initImage(image, subresources, VK_IMAGE_LAYOUT_UNDEFINED); + } + + if (mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_NONE) { + for (uint32_t i = 0; i < pTexture->CountSubresources(); i++) { + auto buffer = pTexture->GetMappedBuffer(i); + std::memset(buffer->mapPtr(0), 0, buffer->info().size); + } + } + } + + FlushImplicit(); + } + + + void D3D11Initializer::InitHostVisibleTexture( + D3D11CommonTexture* pTexture, + const D3D11_SUBRESOURCE_DATA* pInitialData) { + Rc image = pTexture->GetImage(); + + for (uint32_t layer = 0; layer < image->info().numLayers; layer++) { + for (uint32_t level = 0; level < image->info().mipLevels; level++) { + VkImageSubresource subresource; + subresource.aspectMask = image->formatInfo()->aspectMask; + subresource.mipLevel = level; + subresource.arrayLayer = layer; + + VkExtent3D blockCount = util::computeBlockCount( + image->mipLevelExtent(level), + image->formatInfo()->blockSize); + + VkSubresourceLayout layout = image->querySubresourceLayout(subresource); + + auto initialData = pInitialData + ? &pInitialData[D3D11CalcSubresource(level, layer, image->info().mipLevels)] + : nullptr; + + for (uint32_t z = 0; z < blockCount.depth; z++) { + for (uint32_t y = 0; y < blockCount.height; y++) { + auto size = blockCount.width * image->formatInfo()->elementSize; + auto dst = image->mapPtr(layout.offset + y * layout.rowPitch + z * layout.depthPitch); + + if (initialData) { + auto src = reinterpret_cast(initialData->pSysMem) + + y * initialData->SysMemPitch + + z * initialData->SysMemSlicePitch; + std::memcpy(dst, src, size); + } else { + std::memset(dst, 0, size); + } + } + } + } + } + + // Initialize the image on the GPU + std::lock_guard lock(m_mutex); + + VkImageSubresourceRange subresources = image->getAvailableSubresources(); + + m_context->initImage(image, subresources, VK_IMAGE_LAYOUT_PREINITIALIZED); + + m_transferCommands += 1; + FlushImplicit(); + } + + + void D3D11Initializer::FlushImplicit() { + if (m_transferCommands > MaxTransferCommands + || m_transferMemory > MaxTransferMemory) + FlushInternal(); + } + + + void D3D11Initializer::FlushInternal() { + m_context->flushCommandList(); + + m_transferCommands = 0; + m_transferMemory = 0; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_initializer.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_initializer.h new file mode 100644 index 00000000000..8c96babda06 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_initializer.h @@ -0,0 +1,73 @@ +#pragma once + +#include "d3d11_buffer.h" +#include "d3d11_texture.h" + +namespace dxvk { + + class D3D11Device; + + /** + * \brief Resource initialization context + * + * Manages a context which is used for resource + * initialization. This includes initialization + * with application-defined data, as well as + * zero-initialization for buffers and images. + */ + class D3D11Initializer { + constexpr static size_t MaxTransferMemory = 32 * 1024 * 1024; + constexpr static size_t MaxTransferCommands = 512; + public: + + D3D11Initializer( + D3D11Device* pParent); + + ~D3D11Initializer(); + + void Flush(); + + void InitBuffer( + D3D11Buffer* pBuffer, + const D3D11_SUBRESOURCE_DATA* pInitialData); + + void InitTexture( + D3D11CommonTexture* pTexture, + const D3D11_SUBRESOURCE_DATA* pInitialData); + + void InitUavCounter( + D3D11UnorderedAccessView* pUav); + + private: + + dxvk::mutex m_mutex; + + D3D11Device* m_parent; + Rc m_device; + Rc m_context; + + size_t m_transferCommands = 0; + size_t m_transferMemory = 0; + + void InitDeviceLocalBuffer( + D3D11Buffer* pBuffer, + const D3D11_SUBRESOURCE_DATA* pInitialData); + + void InitHostVisibleBuffer( + D3D11Buffer* pBuffer, + const D3D11_SUBRESOURCE_DATA* pInitialData); + + void InitDeviceLocalTexture( + D3D11CommonTexture* pTexture, + const D3D11_SUBRESOURCE_DATA* pInitialData); + + void InitHostVisibleTexture( + D3D11CommonTexture* pTexture, + const D3D11_SUBRESOURCE_DATA* pInitialData); + + void FlushImplicit(); + void FlushInternal(); + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_input_layout.cpp b/utils/dxvk-1.10.3/src/d3d11/d3d11_input_layout.cpp new file mode 100644 index 00000000000..abf3d125b9a --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_input_layout.cpp @@ -0,0 +1,84 @@ +#include "d3d11_device.h" +#include "d3d11_input_layout.h" + +namespace dxvk { + + D3D11InputLayout::D3D11InputLayout( + D3D11Device* pDevice, + uint32_t numAttributes, + const DxvkVertexAttribute* pAttributes, + uint32_t numBindings, + const DxvkVertexBinding* pBindings) + : D3D11DeviceChild(pDevice), + m_d3d10(this) { + m_attributes.resize(numAttributes); + m_bindings.resize(numBindings); + + for (uint32_t i = 0; i < numAttributes; i++) + m_attributes.at(i) = pAttributes[i]; + + for (uint32_t i = 0; i < numBindings; i++) + m_bindings.at(i) = pBindings[i]; + } + + + D3D11InputLayout::~D3D11InputLayout() { + + } + + + HRESULT STDMETHODCALLTYPE D3D11InputLayout::QueryInterface(REFIID riid, void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(ID3D11DeviceChild) + || riid == __uuidof(ID3D11InputLayout)) { + *ppvObject = ref(this); + return S_OK; + } + + if (riid == __uuidof(ID3D10DeviceChild) + || riid == __uuidof(ID3D10InputLayout)) { + *ppvObject = ref(&m_d3d10); + return S_OK; + } + + Logger::warn("D3D11InputLayout::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + void D3D11InputLayout::BindToContext(const Rc& ctx) { + ctx->setInputLayout( + m_attributes.size(), + m_attributes.data(), + m_bindings.size(), + m_bindings.data()); + } + + + bool D3D11InputLayout::Compare(const D3D11InputLayout* pOther) const { + bool eq = m_attributes.size() == pOther->m_attributes.size() + && m_bindings.size() == pOther->m_bindings.size(); + + for (uint32_t i = 0; eq && i < m_attributes.size(); i++) { + eq &= m_attributes[i].location == pOther->m_attributes[i].location + && m_attributes[i].binding == pOther->m_attributes[i].binding + && m_attributes[i].format == pOther->m_attributes[i].format + && m_attributes[i].offset == pOther->m_attributes[i].offset; + } + + for (uint32_t i = 0; eq && i < m_bindings.size(); i++) { + eq &= m_bindings[i].binding == pOther->m_bindings[i].binding + && m_bindings[i].fetchRate == pOther->m_bindings[i].fetchRate + && m_bindings[i].inputRate == pOther->m_bindings[i].inputRate; + } + + return eq; + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_input_layout.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_input_layout.h new file mode 100644 index 00000000000..8e472e2ebeb --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_input_layout.h @@ -0,0 +1,47 @@ +#pragma once + +#include "d3d11_device_child.h" + +#include "../d3d10/d3d10_input_layout.h" + +namespace dxvk { + + class D3D11Device; + + class D3D11InputLayout : public D3D11DeviceChild { + + public: + + D3D11InputLayout( + D3D11Device* pDevice, + uint32_t numAttributes, + const DxvkVertexAttribute* pAttributes, + uint32_t numBindings, + const DxvkVertexBinding* pBindings); + + ~D3D11InputLayout(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject) final; + + void BindToContext( + const Rc& ctx); + + bool Compare( + const D3D11InputLayout* pOther) const; + + D3D10InputLayout* GetD3D10Iface() { + return &m_d3d10; + } + + private: + + std::vector m_attributes; + std::vector m_bindings; + + D3D10InputLayout m_d3d10; + + }; + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_interfaces.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_interfaces.h new file mode 100644 index 00000000000..3b0629bbd9e --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_interfaces.h @@ -0,0 +1,176 @@ +#pragma once + +#include "../dxgi/dxgi_interfaces.h" + +#include "d3d11_include.h" + +/** + * \brief D3D11 extension + * + * Lists D3D11 extensions supported by DXVK. + */ +enum D3D11_VK_EXTENSION : uint32_t { + D3D11_VK_EXT_MULTI_DRAW_INDIRECT = 0, + D3D11_VK_EXT_MULTI_DRAW_INDIRECT_COUNT = 1, + D3D11_VK_EXT_DEPTH_BOUNDS = 2, + D3D11_VK_EXT_BARRIER_CONTROL = 3, + D3D11_VK_NVX_BINARY_IMPORT = 4, + D3D11_VK_NVX_IMAGE_VIEW_HANDLE = 5, +}; + + +/** + * \brief Barrier control flags + */ +enum D3D11_VK_BARRIER_CONTROL : uint32_t { + D3D11_VK_BARRIER_CONTROL_IGNORE_WRITE_AFTER_WRITE = 1 << 0, + D3D11_VK_BARRIER_CONTROL_IGNORE_GRAPHICS_UAV = 1 << 1, +}; + + +/** + * \brief Extended D3D11 device + * + * Introduces a method to check for extension support. + */ +MIDL_INTERFACE("8a6e3c42-f74c-45b7-8265-a231b677ca17") +ID3D11VkExtDevice : public IUnknown { + /** + * \brief Checks whether an extension is supported + * + * \param [in] Extension The extension to check + * \returns \c TRUE if the extension is supported + */ + virtual BOOL STDMETHODCALLTYPE GetExtensionSupport( + D3D11_VK_EXTENSION Extension) = 0; + +}; + + +/** + * \brief Extended extended D3D11 device + * + * Introduces methods to get virtual addresses and driver + * handles for resources, and create and destroy objects + * for D3D11-Cuda interop. + */ +MIDL_INTERFACE("cfcf64ef-9586-46d0-bca4-97cf2ca61b06") +ID3D11VkExtDevice1 : public ID3D11VkExtDevice { + + virtual bool STDMETHODCALLTYPE GetResourceHandleGPUVirtualAddressAndSizeNVX( + void* hObject, + uint64_t* gpuVAStart, + uint64_t* gpuVASize) = 0; + + virtual bool STDMETHODCALLTYPE CreateUnorderedAccessViewAndGetDriverHandleNVX( + ID3D11Resource* pResource, + const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc, + ID3D11UnorderedAccessView** ppUAV, + uint32_t* pDriverHandle) = 0; + + virtual bool STDMETHODCALLTYPE CreateShaderResourceViewAndGetDriverHandleNVX( + ID3D11Resource* pResource, + const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc, + ID3D11ShaderResourceView** ppSRV, + uint32_t* pDriverHandle) = 0; + + virtual bool STDMETHODCALLTYPE CreateSamplerStateAndGetDriverHandleNVX( + const D3D11_SAMPLER_DESC* pSamplerDesc, + ID3D11SamplerState** ppSamplerState, + uint32_t* pDriverHandle) = 0; + + virtual bool STDMETHODCALLTYPE CreateCubinComputeShaderWithNameNVX( + const void* pCubin, + uint32_t size, + uint32_t blockX, + uint32_t blockY, + uint32_t blockZ, + const char* pShaderName, + IUnknown** phShader) = 0; + + virtual bool STDMETHODCALLTYPE GetCudaTextureObjectNVX( + uint32_t srvDriverHandle, + uint32_t samplerDriverHandle, + uint32_t* pCudaTextureHandle) = 0; +}; + + +/** + * \brief Extended D3D11 context + * + * Provides functionality for various D3D11 + * extensions. + */ +MIDL_INTERFACE("fd0bca13-5cb6-4c3a-987e-4750de2ca791") +ID3D11VkExtContext : public IUnknown { + virtual void STDMETHODCALLTYPE MultiDrawIndirect( + UINT DrawCount, + ID3D11Buffer* pBufferForArgs, + UINT ByteOffsetForArgs, + UINT ByteStrideForArgs) = 0; + + virtual void STDMETHODCALLTYPE MultiDrawIndexedIndirect( + UINT DrawCount, + ID3D11Buffer* pBufferForArgs, + UINT ByteOffsetForArgs, + UINT ByteStrideForArgs) = 0; + + virtual void STDMETHODCALLTYPE MultiDrawIndirectCount( + UINT MaxDrawCount, + ID3D11Buffer* pBufferForCount, + UINT ByteOffsetForCount, + ID3D11Buffer* pBufferForArgs, + UINT ByteOffsetForArgs, + UINT ByteStrideForArgs) = 0; + + virtual void STDMETHODCALLTYPE MultiDrawIndexedIndirectCount( + UINT MaxDrawCount, + ID3D11Buffer* pBufferForCount, + UINT ByteOffsetForCount, + ID3D11Buffer* pBufferForArgs, + UINT ByteOffsetForArgs, + UINT ByteStrideForArgs) = 0; + + virtual void STDMETHODCALLTYPE SetDepthBoundsTest( + BOOL Enable, + FLOAT MinDepthBounds, + FLOAT MaxDepthBounds) = 0; + + virtual void STDMETHODCALLTYPE SetBarrierControl( + UINT ControlFlags) = 0; +}; + + +/** + * \brief Extended extended D3D11 context + * + * Provides functionality to launch a Cuda kernel + */ +MIDL_INTERFACE("874b09b2-ae0b-41d8-8476-5f3b7a0e879d") +ID3D11VkExtContext1 : public ID3D11VkExtContext { + + virtual bool STDMETHODCALLTYPE LaunchCubinShaderNVX( + IUnknown* hShader, + uint32_t gridX, + uint32_t gridY, + uint32_t gridZ, + const void* pParams, + uint32_t paramSize, + void* const* pReadResources, + uint32_t numReadResources, + void* const* pWriteResources, + uint32_t numWriteResources) = 0; +}; + + +#ifdef _MSC_VER +struct __declspec(uuid("8a6e3c42-f74c-45b7-8265-a231b677ca17")) ID3D11VkExtDevice; +struct __declspec(uuid("cfcf64ef-9586-46d0-bca4-97cf2ca61b06")) ID3D11VkExtDevice1; +struct __declspec(uuid("fd0bca13-5cb6-4c3a-987e-4750de2ca791")) ID3D11VkExtContext; +struct __declspec(uuid("874b09b2-ae0b-41d8-8476-5f3b7a0e879d")) ID3D11VkExtContext1; +#else +__CRT_UUID_DECL(ID3D11VkExtDevice, 0x8a6e3c42,0xf74c,0x45b7,0x82,0x65,0xa2,0x31,0xb6,0x77,0xca,0x17); +__CRT_UUID_DECL(ID3D11VkExtDevice1, 0xcfcf64ef,0x9586,0x46d0,0xbc,0xa4,0x97,0xcf,0x2c,0xa6,0x1b,0x06); +__CRT_UUID_DECL(ID3D11VkExtContext, 0xfd0bca13,0x5cb6,0x4c3a,0x98,0x7e,0x47,0x50,0xde,0x2c,0xa7,0x91); +__CRT_UUID_DECL(ID3D11VkExtContext1, 0x874b09b2,0xae0b,0x41d8,0x84,0x76,0x5f,0x3b,0x7a,0x0e,0x87,0x9d); +#endif diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_interop.cpp b/utils/dxvk-1.10.3/src/d3d11/d3d11_interop.cpp new file mode 100644 index 00000000000..8fa50288b6f --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_interop.cpp @@ -0,0 +1,166 @@ +#include "d3d11_context_imm.h" +#include "d3d11_interop.h" +#include "d3d11_device.h" + +#include "../dxvk/dxvk_adapter.h" +#include "../dxvk/dxvk_device.h" +#include "../dxvk/dxvk_instance.h" + +namespace dxvk { + + D3D11VkInterop::D3D11VkInterop( + IDXGIObject* pContainer, + D3D11Device* pDevice) + : m_container (pContainer), + m_device (pDevice) { } + + + D3D11VkInterop::~D3D11VkInterop() { + + } + + + ULONG STDMETHODCALLTYPE D3D11VkInterop::AddRef() { + return m_container->AddRef(); + } + + + ULONG STDMETHODCALLTYPE D3D11VkInterop::Release() { + return m_container->Release(); + } + + + HRESULT STDMETHODCALLTYPE D3D11VkInterop::QueryInterface( + REFIID riid, + void** ppvObject) { + return m_container->QueryInterface(riid, ppvObject); + } + + + void STDMETHODCALLTYPE D3D11VkInterop::GetVulkanHandles( + VkInstance* pInstance, + VkPhysicalDevice* pPhysDev, + VkDevice* pDevice) { + auto device = m_device->GetDXVKDevice(); + auto adapter = device->adapter(); + auto instance = device->instance(); + + if (pDevice != nullptr) + *pDevice = device->handle(); + + if (pPhysDev != nullptr) + *pPhysDev = adapter->handle(); + + if (pInstance != nullptr) + *pInstance = instance->handle(); + } + + + void STDMETHODCALLTYPE D3D11VkInterop::GetSubmissionQueue( + VkQueue* pQueue, + uint32_t* pQueueFamilyIndex) { + auto device = static_cast(m_device)->GetDXVKDevice(); + DxvkDeviceQueue queue = device->queues().graphics; + + if (pQueue != nullptr) + *pQueue = queue.queueHandle; + + if (pQueueFamilyIndex != nullptr) + *pQueueFamilyIndex = queue.queueFamily; + } + + + void STDMETHODCALLTYPE D3D11VkInterop::TransitionSurfaceLayout( + IDXGIVkInteropSurface* pSurface, + const VkImageSubresourceRange* pSubresources, + VkImageLayout OldLayout, + VkImageLayout NewLayout) { + Com deviceContext = nullptr; + m_device->GetImmediateContext(&deviceContext); + + auto immediateContext = static_cast(deviceContext.ptr()); + + immediateContext->TransitionSurfaceLayout( + pSurface, pSubresources, OldLayout, NewLayout); + } + + + void STDMETHODCALLTYPE D3D11VkInterop::FlushRenderingCommands() { + Com deviceContext = nullptr; + m_device->GetImmediateContext(&deviceContext); + + auto immediateContext = static_cast(deviceContext.ptr()); + immediateContext->Flush(); + immediateContext->SynchronizeCsThread(DxvkCsThread::SynchronizeAll); + } + + + void STDMETHODCALLTYPE D3D11VkInterop::LockSubmissionQueue() { + m_device->GetDXVKDevice()->lockSubmission(); + } + + + void STDMETHODCALLTYPE D3D11VkInterop::ReleaseSubmissionQueue() { + m_device->GetDXVKDevice()->unlockSubmission(); + } + + + void STDMETHODCALLTYPE D3D11VkInterop::GetSubmissionQueue1( + VkQueue* pQueue, + uint32_t* pQueueIndex, + uint32_t* pQueueFamilyIndex) { + auto device = static_cast(m_device)->GetDXVKDevice(); + DxvkDeviceQueue queue = device->queues().graphics; + + if (pQueue != nullptr) + *pQueue = queue.queueHandle; + + if (pQueueIndex != nullptr) + *pQueueIndex = queue.queueIndex; + + if (pQueueFamilyIndex != nullptr) + *pQueueFamilyIndex = queue.queueFamily; + } + + HRESULT STDMETHODCALLTYPE D3D11VkInterop::CreateTexture2DFromVkImage( + const D3D11_TEXTURE2D_DESC1 *pDesc, + VkImage vkImage, + ID3D11Texture2D **ppTexture2D) { + + InitReturnPtr(ppTexture2D); + + if (!pDesc) + return E_INVALIDARG; + + D3D11_COMMON_TEXTURE_DESC desc; + desc.Width = pDesc->Width; + desc.Height = pDesc->Height; + desc.Depth = 1; + desc.MipLevels = pDesc->MipLevels; + desc.ArraySize = pDesc->ArraySize; + desc.Format = pDesc->Format; + desc.SampleDesc = pDesc->SampleDesc; + desc.Usage = pDesc->Usage; + desc.BindFlags = pDesc->BindFlags; + desc.CPUAccessFlags = pDesc->CPUAccessFlags; + desc.MiscFlags = pDesc->MiscFlags; + desc.TextureLayout = pDesc->TextureLayout; + + HRESULT hr = D3D11CommonTexture::NormalizeTextureProperties(&desc); + + if (FAILED(hr)) + return hr; + + if (!ppTexture2D) + return S_FALSE; + + try { + Com texture = new D3D11Texture2D(m_device, &desc, 0, vkImage); + *ppTexture2D = texture.ref(); + return S_OK; + } catch (const DxvkError& e) { + Logger::err(e.message()); + return E_INVALIDARG; + } + } +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_interop.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_interop.h new file mode 100644 index 00000000000..48ee4c3bb22 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_interop.h @@ -0,0 +1,67 @@ +#pragma once + +#include "../dxgi/dxgi_interfaces.h" + +#include "d3d11_include.h" + +namespace dxvk { + + class D3D11Device; + + class D3D11VkInterop : public ComObject { + + public: + + D3D11VkInterop( + IDXGIObject* pContainer, + D3D11Device* pDevice); + + ~D3D11VkInterop(); + + ULONG STDMETHODCALLTYPE AddRef(); + + ULONG STDMETHODCALLTYPE Release(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + void STDMETHODCALLTYPE GetVulkanHandles( + VkInstance* pInstance, + VkPhysicalDevice* pPhysDev, + VkDevice* pDevice); + + void STDMETHODCALLTYPE GetSubmissionQueue( + VkQueue* pQueue, + uint32_t* pQueueFamilyIndex); + + void STDMETHODCALLTYPE TransitionSurfaceLayout( + IDXGIVkInteropSurface* pSurface, + const VkImageSubresourceRange* pSubresources, + VkImageLayout OldLayout, + VkImageLayout NewLayout); + + void STDMETHODCALLTYPE FlushRenderingCommands(); + + void STDMETHODCALLTYPE LockSubmissionQueue(); + + void STDMETHODCALLTYPE ReleaseSubmissionQueue(); + + void STDMETHODCALLTYPE GetSubmissionQueue1( + VkQueue* pQueue, + uint32_t* pQueueIndex, + uint32_t* pQueueFamilyIndex); + + HRESULT STDMETHODCALLTYPE CreateTexture2DFromVkImage( + const D3D11_TEXTURE2D_DESC1* pDesc, + VkImage vkImage, + ID3D11Texture2D** ppTexture2D); + + private: + + IDXGIObject* m_container; + D3D11Device* m_device; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_main.cpp b/utils/dxvk-1.10.3/src/d3d11/d3d11_main.cpp new file mode 100644 index 00000000000..d80d5dec495 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_main.cpp @@ -0,0 +1,265 @@ +#include + +#include "../dxgi/dxgi_adapter.h" + +#include "../dxvk/dxvk_instance.h" + +#include "d3d11_device.h" +#include "d3d11_enums.h" +#include "d3d11_interop.h" + +namespace dxvk { + Logger Logger::s_instance("d3d11.log"); +} + +extern "C" { + using namespace dxvk; + + DLLEXPORT HRESULT __stdcall D3D11CoreCreateDevice( + IDXGIFactory* pFactory, + IDXGIAdapter* pAdapter, + UINT Flags, + const D3D_FEATURE_LEVEL* pFeatureLevels, + UINT FeatureLevels, + ID3D11Device** ppDevice) { + InitReturnPtr(ppDevice); + + Rc dxvkAdapter; + Rc dxvkInstance; + + Com dxgiVkAdapter; + + // Try to find the corresponding Vulkan device for the DXGI adapter + if (SUCCEEDED(pAdapter->QueryInterface(__uuidof(IDXGIDXVKAdapter), reinterpret_cast(&dxgiVkAdapter)))) { + dxvkAdapter = dxgiVkAdapter->GetDXVKAdapter(); + dxvkInstance = dxgiVkAdapter->GetDXVKInstance(); + } else { + Logger::warn("D3D11CoreCreateDevice: Adapter is not a DXVK adapter"); + DXGI_ADAPTER_DESC desc; + pAdapter->GetDesc(&desc); + + dxvkInstance = new DxvkInstance(); + dxvkAdapter = dxvkInstance->findAdapterByLuid(&desc.AdapterLuid); + + if (dxvkAdapter == nullptr) + dxvkAdapter = dxvkInstance->findAdapterByDeviceId(desc.VendorId, desc.DeviceId); + + if (dxvkAdapter == nullptr) + dxvkAdapter = dxvkInstance->enumAdapters(0); + + if (dxvkAdapter == nullptr) + return E_FAIL; + } + + // Feature levels to probe if the + // application does not specify any. + std::array defaultFeatureLevels = { + D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3, + D3D_FEATURE_LEVEL_9_2, D3D_FEATURE_LEVEL_9_1, + }; + + if (pFeatureLevels == nullptr || FeatureLevels == 0) { + pFeatureLevels = defaultFeatureLevels.data(); + FeatureLevels = defaultFeatureLevels.size(); + } + + // Find the highest feature level supported by the device. + // This works because the feature level array is ordered. + UINT flId; + + for (flId = 0 ; flId < FeatureLevels; flId++) { + Logger::info(str::format("D3D11CoreCreateDevice: Probing ", pFeatureLevels[flId])); + + if (D3D11Device::CheckFeatureLevelSupport(dxvkInstance, dxvkAdapter, pFeatureLevels[flId])) + break; + } + + if (flId == FeatureLevels) { + Logger::err("D3D11CoreCreateDevice: Requested feature level not supported"); + return E_INVALIDARG; + } + + // Try to create the device with the given parameters. + const D3D_FEATURE_LEVEL fl = pFeatureLevels[flId]; + + try { + Logger::info(str::format("D3D11CoreCreateDevice: Using feature level ", fl)); + Com device = new D3D11DXGIDevice( + pAdapter, dxvkInstance, dxvkAdapter, fl, Flags); + + return device->QueryInterface( + __uuidof(ID3D11Device), + reinterpret_cast(ppDevice)); + } catch (const DxvkError& e) { + Logger::err("D3D11CoreCreateDevice: Failed to create D3D11 device"); + return E_FAIL; + } + } + + + static HRESULT D3D11InternalCreateDeviceAndSwapChain( + IDXGIAdapter* pAdapter, + D3D_DRIVER_TYPE DriverType, + HMODULE Software, + UINT Flags, + const D3D_FEATURE_LEVEL* pFeatureLevels, + UINT FeatureLevels, + UINT SDKVersion, + const DXGI_SWAP_CHAIN_DESC* pSwapChainDesc, + IDXGISwapChain** ppSwapChain, + ID3D11Device** ppDevice, + D3D_FEATURE_LEVEL* pFeatureLevel, + ID3D11DeviceContext** ppImmediateContext) { + InitReturnPtr(ppDevice); + InitReturnPtr(ppSwapChain); + InitReturnPtr(ppImmediateContext); + + if (pFeatureLevel) + *pFeatureLevel = D3D_FEATURE_LEVEL(0); + + HRESULT hr; + + Com dxgiFactory = nullptr; + Com dxgiAdapter = pAdapter; + Com device = nullptr; + + if (ppSwapChain && !pSwapChainDesc) + return E_INVALIDARG; + + if (!pAdapter) { + // We'll treat everything as hardware, even if the + // Vulkan device is actually a software device. + if (DriverType != D3D_DRIVER_TYPE_HARDWARE) + Logger::warn("D3D11CreateDevice: Unsupported driver type"); + + // We'll use the first adapter returned by a DXGI factory + hr = CreateDXGIFactory1(__uuidof(IDXGIFactory), reinterpret_cast(&dxgiFactory)); + + if (FAILED(hr)) { + Logger::err("D3D11CreateDevice: Failed to create a DXGI factory"); + return hr; + } + + hr = dxgiFactory->EnumAdapters(0, &dxgiAdapter); + + if (FAILED(hr)) { + Logger::err("D3D11CreateDevice: No default adapter available"); + return hr; + } + } else { + // We should be able to query the DXGI factory from the adapter + if (FAILED(dxgiAdapter->GetParent(__uuidof(IDXGIFactory), reinterpret_cast(&dxgiFactory)))) { + Logger::err("D3D11CreateDevice: Failed to query DXGI factory from DXGI adapter"); + return E_INVALIDARG; + } + + // In theory we could ignore these, but the Microsoft docs explicitly + // state that we need to return E_INVALIDARG in case the arguments are + // invalid. Both the driver type and software parameter can only be + // set if the adapter itself is unspecified. + // See: https://msdn.microsoft.com/en-us/library/windows/desktop/ff476082(v=vs.85).aspx + if (DriverType != D3D_DRIVER_TYPE_UNKNOWN || Software) + return E_INVALIDARG; + } + + // Create the actual device + hr = D3D11CoreCreateDevice( + dxgiFactory.ptr(), dxgiAdapter.ptr(), + Flags, pFeatureLevels, FeatureLevels, + &device); + + if (FAILED(hr)) + return hr; + + // Create the swap chain, if requested + if (ppSwapChain) { + DXGI_SWAP_CHAIN_DESC desc = *pSwapChainDesc; + hr = dxgiFactory->CreateSwapChain(device.ptr(), &desc, ppSwapChain); + + if (FAILED(hr)) { + Logger::err("D3D11CreateDevice: Failed to create swap chain"); + return hr; + } + } + + // Write back whatever info the application requested + if (pFeatureLevel) + *pFeatureLevel = device->GetFeatureLevel(); + + if (ppDevice) + *ppDevice = device.ref(); + + if (ppImmediateContext) + device->GetImmediateContext(ppImmediateContext); + + // If we were unable to write back the device and the + // swap chain, the application has no way of working + // with the device so we should report S_FALSE here. + if (!ppDevice && !ppImmediateContext && !ppSwapChain) + return S_FALSE; + + return S_OK; + } + + + DLLEXPORT HRESULT __stdcall D3D11CreateDevice( + IDXGIAdapter* pAdapter, + D3D_DRIVER_TYPE DriverType, + HMODULE Software, + UINT Flags, + const D3D_FEATURE_LEVEL* pFeatureLevels, + UINT FeatureLevels, + UINT SDKVersion, + ID3D11Device** ppDevice, + D3D_FEATURE_LEVEL* pFeatureLevel, + ID3D11DeviceContext** ppImmediateContext) { + return D3D11InternalCreateDeviceAndSwapChain( + pAdapter, DriverType, Software, Flags, + pFeatureLevels, FeatureLevels, SDKVersion, + nullptr, nullptr, + ppDevice, pFeatureLevel, ppImmediateContext); + } + + + DLLEXPORT HRESULT __stdcall D3D11CreateDeviceAndSwapChain( + IDXGIAdapter* pAdapter, + D3D_DRIVER_TYPE DriverType, + HMODULE Software, + UINT Flags, + const D3D_FEATURE_LEVEL* pFeatureLevels, + UINT FeatureLevels, + UINT SDKVersion, + const DXGI_SWAP_CHAIN_DESC* pSwapChainDesc, + IDXGISwapChain** ppSwapChain, + ID3D11Device** ppDevice, + D3D_FEATURE_LEVEL* pFeatureLevel, + ID3D11DeviceContext** ppImmediateContext) { + return D3D11InternalCreateDeviceAndSwapChain( + pAdapter, DriverType, Software, Flags, + pFeatureLevels, FeatureLevels, SDKVersion, + pSwapChainDesc, ppSwapChain, + ppDevice, pFeatureLevel, ppImmediateContext); + } + + + DLLEXPORT HRESULT __stdcall D3D11On12CreateDevice( + IUnknown* pDevice, + UINT Flags, + const D3D_FEATURE_LEVEL* pFeatureLevels, + UINT FeatureLevels, + IUnknown* const* ppCommandQueues, + UINT NumQueues, + UINT NodeMask, + ID3D11Device** ppDevice, + ID3D11DeviceContext** ppImmediateContext, + D3D_FEATURE_LEVEL* pChosenFeatureLevel) { + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::err("D3D11On12CreateDevice: Not implemented"); + + return E_NOTIMPL; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_options.cpp b/utils/dxvk-1.10.3/src/d3d11/d3d11_options.cpp new file mode 100644 index 00000000000..e78c51981d5 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_options.cpp @@ -0,0 +1,64 @@ +#include + +#include "d3d11_options.h" + +namespace dxvk { + + D3D11Options::D3D11Options(const Config& config, const Rc& device) { + const DxvkDeviceInfo& devInfo = device->properties(); + + this->dcSingleUseMode = config.getOption("d3d11.dcSingleUseMode", true); + this->enableRtOutputNanFixup = config.getOption("d3d11.enableRtOutputNanFixup", false); + this->zeroInitWorkgroupMemory = config.getOption("d3d11.zeroInitWorkgroupMemory", false); + this->forceTgsmBarriers = config.getOption("d3d11.forceTgsmBarriers", false); + this->relaxedBarriers = config.getOption("d3d11.relaxedBarriers", false); + this->ignoreGraphicsBarriers = config.getOption("d3d11.ignoreGraphicsBarriers", false); + this->maxTessFactor = config.getOption("d3d11.maxTessFactor", 0); + this->samplerAnisotropy = config.getOption("d3d11.samplerAnisotropy", -1); + this->invariantPosition = config.getOption("d3d11.invariantPosition", true); + this->floatControls = config.getOption("d3d11.floatControls", true); + this->disableMsaa = config.getOption("d3d11.disableMsaa", false); + this->deferSurfaceCreation = config.getOption("dxgi.deferSurfaceCreation", false); + this->numBackBuffers = config.getOption("dxgi.numBackBuffers", 0); + this->maxFrameLatency = config.getOption("dxgi.maxFrameLatency", 0); + this->maxFrameRate = config.getOption("dxgi.maxFrameRate", 0); + this->syncInterval = config.getOption("dxgi.syncInterval", -1); + this->tearFree = config.getOption("dxgi.tearFree", Tristate::Auto); + + int32_t maxImplicitDiscardSize = config.getOption("d3d11.maxImplicitDiscardSize", 256); + this->maxImplicitDiscardSize = maxImplicitDiscardSize >= 0 + ? VkDeviceSize(maxImplicitDiscardSize) << 10 + : VkDeviceSize(~0ull); + + int32_t maxDynamicImageBufferSize = config.getOption("d3d11.maxDynamicImageBufferSize", -1); + this->maxDynamicImageBufferSize = maxDynamicImageBufferSize >= 0 + ? VkDeviceSize(maxDynamicImageBufferSize) << 10 + : VkDeviceSize(~0ull); + + this->constantBufferRangeCheck = config.getOption("d3d11.constantBufferRangeCheck", false) + && DxvkGpuVendor(devInfo.core.properties.vendorID) != DxvkGpuVendor::Amd; + + auto cachedDynamicResources = config.getOption("d3d11.cachedDynamicResources", std::string()); + + if (::GetModuleHandle("dxgitrace.dll")) { + // apitrace reads back all mapped resources on the CPU, so + // allocating everything in cached memory is necessary to + // achieve acceptable performance + this->cachedDynamicResources = ~0u; + } else { + this->cachedDynamicResources = 0u; + + for (char c : cachedDynamicResources) { + switch (c) { + case 'c': this->cachedDynamicResources |= D3D11_BIND_CONSTANT_BUFFER; break; + case 'v': this->cachedDynamicResources |= D3D11_BIND_VERTEX_BUFFER; break; + case 'i': this->cachedDynamicResources |= D3D11_BIND_INDEX_BUFFER; break; + case 'r': this->cachedDynamicResources |= D3D11_BIND_SHADER_RESOURCE; break; + case 'a': this->cachedDynamicResources = ~0u; break; + default: Logger::warn(str::format("Unknown flag for d3d11.cachedDynamicResources option: ", c)); + } + } + } + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_options.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_options.h new file mode 100644 index 00000000000..99353b30280 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_options.h @@ -0,0 +1,116 @@ +#pragma once + +#include "../util/config/config.h" + +#include "../dxgi/dxgi_options.h" + +#include "../dxvk/dxvk_device.h" + +#include "d3d11_include.h" + +namespace dxvk { + + struct D3D11Options { + D3D11Options(const Config& config, const Rc& device); + + /// Enables speed hack for mapping on deferred contexts + /// + /// This can substantially speed up some games, but may + /// cause issues if the game submits command lists more + /// than once. + bool dcSingleUseMode; + + /// Enables workaround to replace NaN render target + /// outputs with zero + bool enableRtOutputNanFixup; + + /// Enables out-of-bounds access check for constant + /// buffers. Workaround for a few broken games that + /// access random data inside their shaders. + bool constantBufferRangeCheck; + + /// Zero-initialize workgroup memory + /// + /// Workargound for games that don't initialize + /// TGSM in compute shaders before reading it. + bool zeroInitWorkgroupMemory; + + /// Force thread-group shared memory barriers + /// + /// Workaround for compute shaders that read and + /// write from the same shared memory location + /// without explicit synchronization. + bool forceTgsmBarriers; + + /// Use relaxed memory barriers + /// + /// May improve performance in some games, + /// but might also cause rendering issues. + bool relaxedBarriers; + + /// Ignore graphics barriers + /// + /// May improve performance in some games, + /// but might also cause rendering issues. + bool ignoreGraphicsBarriers; + + /// Maximum tessellation factor. + /// + /// Limits tessellation factors in tessellation + /// control shaders. Values from 8 to 64 are + /// supported, other values will be ignored. + int32_t maxTessFactor; + + /// Anisotropic filter override + /// + /// Enforces anisotropic filtering with the + /// given anisotropy value for all samplers. + int32_t samplerAnisotropy; + + /// Declare vertex positions in shaders as invariant + bool invariantPosition; + + /// Enable float control bits + bool floatControls; + + /// Back buffer count for the Vulkan swap chain. + /// Overrides DXGI_SWAP_CHAIN_DESC::BufferCount. + int32_t numBackBuffers; + + /// Sync interval. Overrides the value + /// passed to IDXGISwapChain::Present. + int32_t syncInterval; + + /// Tear-free mode if vsync is disabled + /// Tearing mode if vsync is enabled + Tristate tearFree; + + /// Override maximum frame latency if the app specifies + /// a higher value. May help with frame timing issues. + int32_t maxFrameLatency; + + /// Limit frame rate + int32_t maxFrameRate; + + /// Limit discardable resource size + VkDeviceSize maxImplicitDiscardSize; + + /// Limit size of buffer-mapped images + VkDeviceSize maxDynamicImageBufferSize; + + /// Defer surface creation until first present call. This + /// fixes issues with games that create multiple swap chains + /// for a single window that may interfere with each other. + bool deferSurfaceCreation; + + /// Forces the sample count of all textures to be 1, and + /// performs the required shader and resolve fixups. + bool disableMsaa; + + /// Dynamic resources with the given bind flags will be allocated + /// in cached system memory. Enabled automatically when recording + /// an api trace. + uint32_t cachedDynamicResources; + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_query.cpp b/utils/dxvk-1.10.3/src/d3d11/d3d11_query.cpp new file mode 100644 index 00000000000..b7145739fbd --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_query.cpp @@ -0,0 +1,352 @@ +#include "d3d11_device.h" +#include "d3d11_query.h" + +namespace dxvk { + + D3D11Query::D3D11Query( + D3D11Device* device, + const D3D11_QUERY_DESC1& desc) + : D3D11DeviceChild(device), + m_desc(desc), + m_state(D3D11_VK_QUERY_INITIAL), + m_d3d10(this) { + Rc dxvkDevice = m_parent->GetDXVKDevice(); + + switch (m_desc.Query) { + case D3D11_QUERY_EVENT: + m_event[0] = dxvkDevice->createGpuEvent(); + break; + + case D3D11_QUERY_OCCLUSION: + m_query[0] = dxvkDevice->createGpuQuery( + VK_QUERY_TYPE_OCCLUSION, + VK_QUERY_CONTROL_PRECISE_BIT, 0); + break; + + case D3D11_QUERY_OCCLUSION_PREDICATE: + m_query[0] = dxvkDevice->createGpuQuery( + VK_QUERY_TYPE_OCCLUSION, 0, 0); + break; + + case D3D11_QUERY_TIMESTAMP: + m_query[0] = dxvkDevice->createGpuQuery( + VK_QUERY_TYPE_TIMESTAMP, 0, 0); + break; + + case D3D11_QUERY_TIMESTAMP_DISJOINT: + for (uint32_t i = 0; i < 2; i++) { + m_query[i] = dxvkDevice->createGpuQuery( + VK_QUERY_TYPE_TIMESTAMP, 0, 0); + } + break; + + case D3D11_QUERY_PIPELINE_STATISTICS: + m_query[0] = dxvkDevice->createGpuQuery( + VK_QUERY_TYPE_PIPELINE_STATISTICS, 0, 0); + break; + + case D3D11_QUERY_SO_STATISTICS: + case D3D11_QUERY_SO_STATISTICS_STREAM0: + case D3D11_QUERY_SO_OVERFLOW_PREDICATE: + case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM0: + // FIXME it is technically incorrect to map + // SO_OVERFLOW_PREDICATE to the first stream, + // but this is good enough for D3D10 behaviour + m_query[0] = dxvkDevice->createGpuQuery( + VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT, 0, 0); + break; + + case D3D11_QUERY_SO_STATISTICS_STREAM1: + case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM1: + m_query[0] = dxvkDevice->createGpuQuery( + VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT, 0, 1); + break; + + case D3D11_QUERY_SO_STATISTICS_STREAM2: + case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM2: + m_query[0] = dxvkDevice->createGpuQuery( + VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT, 0, 2); + break; + + case D3D11_QUERY_SO_STATISTICS_STREAM3: + case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM3: + m_query[0] = dxvkDevice->createGpuQuery( + VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT, 0, 3); + break; + + default: + throw DxvkError(str::format("D3D11: Unhandled query type: ", desc.Query)); + } + } + + + D3D11Query::~D3D11Query() { + + } + + + HRESULT STDMETHODCALLTYPE D3D11Query::QueryInterface(REFIID riid, void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(ID3D11DeviceChild) + || riid == __uuidof(ID3D11Asynchronous) + || riid == __uuidof(ID3D11Query) + || riid == __uuidof(ID3D11Query1)) { + *ppvObject = ref(this); + return S_OK; + } + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(ID3D10DeviceChild) + || riid == __uuidof(ID3D10Asynchronous) + || riid == __uuidof(ID3D10Query)) { + *ppvObject = ref(&m_d3d10); + return S_OK; + } + + if (m_desc.Query == D3D11_QUERY_OCCLUSION_PREDICATE) { + if (riid == __uuidof(ID3D11Predicate)) { + *ppvObject = AsPredicate(ref(this)); + return S_OK; + } + + if (riid == __uuidof(ID3D10Predicate)) { + *ppvObject = ref(&m_d3d10); + return S_OK; + } + } + + Logger::warn("D3D11Query: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + UINT STDMETHODCALLTYPE D3D11Query::GetDataSize() { + switch (m_desc.Query) { + case D3D11_QUERY_EVENT: + return sizeof(BOOL); + + case D3D11_QUERY_OCCLUSION: + return sizeof(UINT64); + + case D3D11_QUERY_TIMESTAMP: + return sizeof(UINT64); + + case D3D11_QUERY_TIMESTAMP_DISJOINT: + return sizeof(D3D11_QUERY_DATA_TIMESTAMP_DISJOINT); + + case D3D11_QUERY_PIPELINE_STATISTICS: + return sizeof(D3D11_QUERY_DATA_PIPELINE_STATISTICS); + + case D3D11_QUERY_OCCLUSION_PREDICATE: + return sizeof(BOOL); + + case D3D11_QUERY_SO_STATISTICS: + case D3D11_QUERY_SO_STATISTICS_STREAM0: + case D3D11_QUERY_SO_STATISTICS_STREAM1: + case D3D11_QUERY_SO_STATISTICS_STREAM2: + case D3D11_QUERY_SO_STATISTICS_STREAM3: + return sizeof(D3D11_QUERY_DATA_SO_STATISTICS); + + case D3D11_QUERY_SO_OVERFLOW_PREDICATE: + case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM0: + case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM1: + case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM2: + case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM3: + return sizeof(BOOL); + } + + Logger::err("D3D11Query: Failed to query data size"); + return 0; + } + + + void STDMETHODCALLTYPE D3D11Query::GetDesc(D3D11_QUERY_DESC* pDesc) { + pDesc->Query = m_desc.Query; + pDesc->MiscFlags = m_desc.MiscFlags; + } + + + void STDMETHODCALLTYPE D3D11Query::GetDesc1(D3D11_QUERY_DESC1* pDesc) { + *pDesc = m_desc; + } + + + void D3D11Query::Begin(DxvkContext* ctx) { + switch (m_desc.Query) { + case D3D11_QUERY_EVENT: + case D3D11_QUERY_TIMESTAMP: + break; + + case D3D11_QUERY_TIMESTAMP_DISJOINT: + ctx->writeTimestamp(m_query[1]); + break; + + default: + ctx->beginQuery(m_query[0]); + } + } + + + void D3D11Query::End(DxvkContext* ctx) { + switch (m_desc.Query) { + case D3D11_QUERY_EVENT: + ctx->signalGpuEvent(m_event[0]); + break; + + case D3D11_QUERY_TIMESTAMP: + case D3D11_QUERY_TIMESTAMP_DISJOINT: + ctx->writeTimestamp(m_query[0]); + break; + + default: + ctx->endQuery(m_query[0]); + } + + m_resetCtr.fetch_sub(1, std::memory_order_release); + } + + + bool STDMETHODCALLTYPE D3D11Query::DoBegin() { + if (!IsScoped() || m_state == D3D11_VK_QUERY_BEGUN) + return false; + + m_state = D3D11_VK_QUERY_BEGUN; + return true; + } + + bool STDMETHODCALLTYPE D3D11Query::DoEnd() { + // Apparently the D3D11 runtime implicitly begins the query + // if it is in the wrong state at the time End is called, so + // let the caller react to it instead of just failing here. + bool result = m_state == D3D11_VK_QUERY_BEGUN || !IsScoped(); + + m_state = D3D11_VK_QUERY_ENDED; + m_resetCtr.fetch_add(1, std::memory_order_acquire); + return result; + } + + + HRESULT STDMETHODCALLTYPE D3D11Query::GetData( + void* pData, + UINT GetDataFlags) { + if (m_state != D3D11_VK_QUERY_ENDED) + return DXGI_ERROR_INVALID_CALL; + + if (m_resetCtr != 0u) + return S_FALSE; + + if (m_desc.Query == D3D11_QUERY_EVENT) { + DxvkGpuEventStatus status = m_event[0]->test(); + + if (status == DxvkGpuEventStatus::Invalid) + return DXGI_ERROR_INVALID_CALL; + + bool signaled = status == DxvkGpuEventStatus::Signaled; + + if (pData != nullptr) + *static_cast(pData) = signaled; + + return signaled ? S_OK : S_FALSE; + } else { + std::array queryData = { }; + + for (uint32_t i = 0; i < MaxGpuQueries && m_query[i] != nullptr; i++) { + DxvkGpuQueryStatus status = m_query[i]->getData(queryData[i]); + + if (status == DxvkGpuQueryStatus::Invalid + || status == DxvkGpuQueryStatus::Failed) + return DXGI_ERROR_INVALID_CALL; + + if (status == DxvkGpuQueryStatus::Pending) + return S_FALSE; + } + + if (pData == nullptr) + return S_OK; + + switch (m_desc.Query) { + case D3D11_QUERY_OCCLUSION: + *static_cast(pData) = queryData[0].occlusion.samplesPassed; + return S_OK; + + case D3D11_QUERY_OCCLUSION_PREDICATE: + *static_cast(pData) = queryData[0].occlusion.samplesPassed != 0; + return S_OK; + + case D3D11_QUERY_TIMESTAMP: + *static_cast(pData) = queryData[0].timestamp.time; + return S_OK; + + case D3D11_QUERY_TIMESTAMP_DISJOINT: { + auto data = static_cast(pData); + data->Frequency = GetTimestampQueryFrequency(); + data->Disjoint = queryData[0].timestamp.time < queryData[1].timestamp.time; + } return S_OK; + + case D3D11_QUERY_PIPELINE_STATISTICS: { + auto data = static_cast(pData); + data->IAVertices = queryData[0].statistic.iaVertices; + data->IAPrimitives = queryData[0].statistic.iaPrimitives; + data->VSInvocations = queryData[0].statistic.vsInvocations; + data->GSInvocations = queryData[0].statistic.gsInvocations; + data->GSPrimitives = queryData[0].statistic.gsPrimitives; + data->CInvocations = queryData[0].statistic.clipInvocations; + data->CPrimitives = queryData[0].statistic.clipPrimitives; + data->PSInvocations = queryData[0].statistic.fsInvocations; + data->HSInvocations = queryData[0].statistic.tcsPatches; + data->DSInvocations = queryData[0].statistic.tesInvocations; + data->CSInvocations = queryData[0].statistic.csInvocations; + } return S_OK; + + case D3D11_QUERY_SO_STATISTICS: + case D3D11_QUERY_SO_STATISTICS_STREAM0: + case D3D11_QUERY_SO_STATISTICS_STREAM1: + case D3D11_QUERY_SO_STATISTICS_STREAM2: + case D3D11_QUERY_SO_STATISTICS_STREAM3: { + auto data = static_cast(pData); + data->NumPrimitivesWritten = queryData[0].xfbStream.primitivesWritten; + data->PrimitivesStorageNeeded = queryData[0].xfbStream.primitivesNeeded; + } return S_OK; + + case D3D11_QUERY_SO_OVERFLOW_PREDICATE: + case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM0: + case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM1: + case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM2: + case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM3: { + auto data = static_cast(pData); + *data = queryData[0].xfbStream.primitivesNeeded + > queryData[0].xfbStream.primitivesWritten; + } return S_OK; + + default: + Logger::err(str::format("D3D11: Unhandled query type in GetData: ", m_desc.Query)); + return E_INVALIDARG; + } + } + } + + + UINT64 D3D11Query::GetTimestampQueryFrequency() const { + Rc device = m_parent->GetDXVKDevice(); + Rc adapter = device->adapter(); + + VkPhysicalDeviceLimits limits = adapter->deviceProperties().limits; + return uint64_t(1'000'000'000.0f / limits.timestampPeriod); + } + + + HRESULT D3D11Query::ValidateDesc(const D3D11_QUERY_DESC1* pDesc) { + if (pDesc->Query >= D3D11_QUERY_PIPELINE_STATISTICS + && pDesc->ContextType > D3D11_CONTEXT_TYPE_3D) + return E_INVALIDARG; + + return S_OK; + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_query.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_query.h new file mode 100644 index 00000000000..a1853cfcae7 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_query.h @@ -0,0 +1,120 @@ +#pragma once + +#include "../dxvk/dxvk_gpu_event.h" +#include "../dxvk/dxvk_gpu_query.h" + +#include "../d3d10/d3d10_query.h" + +#include "d3d11_device_child.h" + +namespace dxvk { + + enum D3D11_VK_QUERY_STATE : uint32_t { + D3D11_VK_QUERY_INITIAL, + D3D11_VK_QUERY_BEGUN, + D3D11_VK_QUERY_ENDED, + }; + + class D3D11Query : public D3D11DeviceChild { + constexpr static uint32_t MaxGpuQueries = 2; + constexpr static uint32_t MaxGpuEvents = 1; + public: + + D3D11Query( + D3D11Device* device, + const D3D11_QUERY_DESC1& desc); + + ~D3D11Query(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject) final; + + UINT STDMETHODCALLTYPE GetDataSize(); + + void STDMETHODCALLTYPE GetDesc(D3D11_QUERY_DESC* pDesc) final; + + void STDMETHODCALLTYPE GetDesc1(D3D11_QUERY_DESC1* pDesc) final; + + void Begin(DxvkContext* ctx); + + void End(DxvkContext* ctx); + + bool STDMETHODCALLTYPE DoBegin(); + + bool STDMETHODCALLTYPE DoEnd(); + + HRESULT STDMETHODCALLTYPE GetData( + void* pData, + UINT GetDataFlags); + + void DoDeferredEnd() { + m_state = D3D11_VK_QUERY_ENDED; + m_resetCtr.fetch_add(1, std::memory_order_acquire); + } + + bool IsScoped() const { + return m_desc.Query != D3D11_QUERY_EVENT + && m_desc.Query != D3D11_QUERY_TIMESTAMP; + } + + bool IsEvent() const { + return m_desc.Query == D3D11_QUERY_EVENT; + } + + bool TrackStalls() const { + return m_desc.Query == D3D11_QUERY_EVENT + || m_desc.Query == D3D11_QUERY_TIMESTAMP + || m_desc.Query == D3D11_QUERY_TIMESTAMP_DISJOINT; + } + + bool IsStalling() const { + return m_stallFlag; + } + + void NotifyEnd() { + m_stallMask <<= 1; + } + + void NotifyStall() { + m_stallMask |= 1; + m_stallFlag |= bit::popcnt(m_stallMask) >= 16; + } + + D3D10Query* GetD3D10Iface() { + return &m_d3d10; + } + + static HRESULT ValidateDesc(const D3D11_QUERY_DESC1* pDesc); + + static ID3D11Predicate* AsPredicate(ID3D11Query* pQuery) { + // ID3D11Predicate and ID3D11Query have the same vtable. This + // saves us some headache in all query-related functions. + return static_cast(pQuery); + } + + static D3D11Query* FromPredicate(ID3D11Predicate* pPredicate) { + return static_cast(static_cast(pPredicate)); + } + + private: + + D3D11_QUERY_DESC1 m_desc; + + D3D11_VK_QUERY_STATE m_state; + + std::array, MaxGpuQueries> m_query; + std::array, MaxGpuEvents> m_event; + + D3D10Query m_d3d10; + + uint32_t m_stallMask = 0; + bool m_stallFlag = false; + + std::atomic m_resetCtr = { 0u }; + + UINT64 GetTimestampQueryFrequency() const; + + }; + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_rasterizer.cpp b/utils/dxvk-1.10.3/src/d3d11/d3d11_rasterizer.cpp new file mode 100644 index 00000000000..6d70847e4be --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_rasterizer.cpp @@ -0,0 +1,195 @@ +#include "d3d11_device.h" +#include "d3d11_rasterizer.h" + +namespace dxvk { + + D3D11RasterizerState::D3D11RasterizerState( + D3D11Device* device, + const D3D11_RASTERIZER_DESC2& desc) + : D3D11StateObject(device), + m_desc(desc), m_d3d10(this) { + // Polygon mode. Determines whether the rasterizer fills + // a polygon or renders lines connecting the vertices. + switch (desc.FillMode) { + default: + case D3D11_FILL_SOLID: m_state.polygonMode = VK_POLYGON_MODE_FILL; break; + case D3D11_FILL_WIREFRAME: m_state.polygonMode = VK_POLYGON_MODE_LINE; break; + } + + // Face culling properties. The rasterizer may discard + // polygons that are facing towards or away from the + // viewer, depending on the options below. + switch (desc.CullMode) { + default: + case D3D11_CULL_NONE: m_state.cullMode = VK_CULL_MODE_NONE; break; + case D3D11_CULL_FRONT: m_state.cullMode = VK_CULL_MODE_FRONT_BIT; break; + case D3D11_CULL_BACK: m_state.cullMode = VK_CULL_MODE_BACK_BIT; break; + } + + m_state.frontFace = desc.FrontCounterClockwise + ? VK_FRONT_FACE_COUNTER_CLOCKWISE + : VK_FRONT_FACE_CLOCKWISE; + + // In the backend we treat depth bias as a dynamic state because + // some games like to put random/uninitialized numbers here, but + // we do not need to enable it in case the parameters are both 0. + m_state.depthBiasEnable = desc.DepthBias != 0 || desc.SlopeScaledDepthBias != 0.0f; + m_state.depthClipEnable = desc.DepthClipEnable; + m_state.conservativeMode = DecodeConservativeRasterizationMode(desc.ConservativeRaster); + m_state.sampleCount = VkSampleCountFlags(desc.ForcedSampleCount); + + m_depthBias.depthBiasConstant = float(desc.DepthBias); + m_depthBias.depthBiasSlope = desc.SlopeScaledDepthBias; + m_depthBias.depthBiasClamp = desc.DepthBiasClamp; + + if (desc.AntialiasedLineEnable) + Logger::err("D3D11RasterizerState: Antialiased lines not supported"); + } + + + D3D11RasterizerState::~D3D11RasterizerState() { + + } + + + HRESULT STDMETHODCALLTYPE D3D11RasterizerState::QueryInterface(REFIID riid, void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(ID3D11DeviceChild) + || riid == __uuidof(ID3D11RasterizerState) + || riid == __uuidof(ID3D11RasterizerState1) + || riid == __uuidof(ID3D11RasterizerState2)) { + *ppvObject = ref(this); + return S_OK; + } + + if (riid == __uuidof(ID3D10DeviceChild) + || riid == __uuidof(ID3D10RasterizerState)) { + *ppvObject = ref(&m_d3d10); + return S_OK; + } + + Logger::warn("D3D11RasterizerState::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + void STDMETHODCALLTYPE D3D11RasterizerState::GetDesc(D3D11_RASTERIZER_DESC* pDesc) { + pDesc->FillMode = m_desc.FillMode; + pDesc->CullMode = m_desc.CullMode; + pDesc->FrontCounterClockwise = m_desc.FrontCounterClockwise; + pDesc->DepthBias = m_desc.DepthBias; + pDesc->DepthBiasClamp = m_desc.DepthBiasClamp; + pDesc->SlopeScaledDepthBias = m_desc.SlopeScaledDepthBias; + pDesc->DepthClipEnable = m_desc.DepthClipEnable; + pDesc->ScissorEnable = m_desc.ScissorEnable; + pDesc->MultisampleEnable = m_desc.MultisampleEnable; + pDesc->AntialiasedLineEnable = m_desc.AntialiasedLineEnable; + } + + + void STDMETHODCALLTYPE D3D11RasterizerState::GetDesc1(D3D11_RASTERIZER_DESC1* pDesc) { + pDesc->FillMode = m_desc.FillMode; + pDesc->CullMode = m_desc.CullMode; + pDesc->FrontCounterClockwise = m_desc.FrontCounterClockwise; + pDesc->DepthBias = m_desc.DepthBias; + pDesc->DepthBiasClamp = m_desc.DepthBiasClamp; + pDesc->SlopeScaledDepthBias = m_desc.SlopeScaledDepthBias; + pDesc->DepthClipEnable = m_desc.DepthClipEnable; + pDesc->ScissorEnable = m_desc.ScissorEnable; + pDesc->MultisampleEnable = m_desc.MultisampleEnable; + pDesc->AntialiasedLineEnable = m_desc.AntialiasedLineEnable; + pDesc->ForcedSampleCount = m_desc.ForcedSampleCount; + } + + + void STDMETHODCALLTYPE D3D11RasterizerState::GetDesc2(D3D11_RASTERIZER_DESC2* pDesc) { + *pDesc = m_desc; + } + + + void D3D11RasterizerState::BindToContext(const Rc& ctx) { + ctx->setRasterizerState(m_state); + + if (m_state.depthBiasEnable) + ctx->setDepthBias(m_depthBias); + } + + + D3D11_RASTERIZER_DESC2 D3D11RasterizerState::PromoteDesc( + const D3D11_RASTERIZER_DESC* pSrcDesc) { + D3D11_RASTERIZER_DESC2 dstDesc; + dstDesc.FillMode = pSrcDesc->FillMode; + dstDesc.CullMode = pSrcDesc->CullMode; + dstDesc.FrontCounterClockwise = pSrcDesc->FrontCounterClockwise; + dstDesc.DepthBias = pSrcDesc->DepthBias; + dstDesc.DepthBiasClamp = pSrcDesc->DepthBiasClamp; + dstDesc.SlopeScaledDepthBias = pSrcDesc->SlopeScaledDepthBias; + dstDesc.DepthClipEnable = pSrcDesc->DepthClipEnable; + dstDesc.ScissorEnable = pSrcDesc->ScissorEnable; + dstDesc.MultisampleEnable = pSrcDesc->MultisampleEnable; + dstDesc.AntialiasedLineEnable = pSrcDesc->AntialiasedLineEnable; + dstDesc.ForcedSampleCount = 0; + dstDesc.ConservativeRaster = D3D11_CONSERVATIVE_RASTERIZATION_MODE_OFF; + return dstDesc; + } + + + D3D11_RASTERIZER_DESC2 D3D11RasterizerState::PromoteDesc( + const D3D11_RASTERIZER_DESC1* pSrcDesc) { + D3D11_RASTERIZER_DESC2 dstDesc; + dstDesc.FillMode = pSrcDesc->FillMode; + dstDesc.CullMode = pSrcDesc->CullMode; + dstDesc.FrontCounterClockwise = pSrcDesc->FrontCounterClockwise; + dstDesc.DepthBias = pSrcDesc->DepthBias; + dstDesc.DepthBiasClamp = pSrcDesc->DepthBiasClamp; + dstDesc.SlopeScaledDepthBias = pSrcDesc->SlopeScaledDepthBias; + dstDesc.DepthClipEnable = pSrcDesc->DepthClipEnable; + dstDesc.ScissorEnable = pSrcDesc->ScissorEnable; + dstDesc.MultisampleEnable = pSrcDesc->MultisampleEnable; + dstDesc.AntialiasedLineEnable = pSrcDesc->AntialiasedLineEnable; + dstDesc.ForcedSampleCount = 0; + dstDesc.ConservativeRaster = D3D11_CONSERVATIVE_RASTERIZATION_MODE_OFF; + return dstDesc; + } + + + HRESULT D3D11RasterizerState::NormalizeDesc( + D3D11_RASTERIZER_DESC2* pDesc) { + if (pDesc->FillMode < D3D11_FILL_WIREFRAME + || pDesc->FillMode > D3D11_FILL_SOLID) + return E_INVALIDARG; + + if (pDesc->CullMode < D3D11_CULL_NONE + || pDesc->CullMode > D3D11_CULL_BACK) + return E_INVALIDARG; + + if (pDesc->FrontCounterClockwise) + pDesc->FrontCounterClockwise = TRUE; + + if (pDesc->DepthClipEnable) + pDesc->DepthClipEnable = TRUE; + + if (pDesc->ScissorEnable) + pDesc->ScissorEnable = TRUE; + + if (pDesc->MultisampleEnable) + pDesc->MultisampleEnable = TRUE; + + if (pDesc->AntialiasedLineEnable) + pDesc->AntialiasedLineEnable = TRUE; + + if (pDesc->ForcedSampleCount != 0) { + if (FAILED(DecodeSampleCount(pDesc->ForcedSampleCount, nullptr))) + return E_INVALIDARG; + } + + return S_OK; + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_rasterizer.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_rasterizer.h new file mode 100644 index 00000000000..7b542f2ca9a --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_rasterizer.h @@ -0,0 +1,66 @@ +#pragma once + +#include "../dxvk/dxvk_device.h" + +#include "../d3d10/d3d10_rasterizer.h" + +#include "d3d11_device_child.h" + +namespace dxvk { + + class D3D11Device; + + class D3D11RasterizerState : public D3D11StateObject { + + public: + + using DescType = D3D11_RASTERIZER_DESC2; + + D3D11RasterizerState( + D3D11Device* device, + const D3D11_RASTERIZER_DESC2& desc); + ~D3D11RasterizerState(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject) final; + + void STDMETHODCALLTYPE GetDesc( + D3D11_RASTERIZER_DESC* pDesc) final; + + void STDMETHODCALLTYPE GetDesc1( + D3D11_RASTERIZER_DESC1* pDesc) final; + + void STDMETHODCALLTYPE GetDesc2( + D3D11_RASTERIZER_DESC2* pDesc) final; + + const D3D11_RASTERIZER_DESC2* Desc() const { + return &m_desc; + } + + void BindToContext( + const Rc& ctx); + + D3D10RasterizerState* GetD3D10Iface() { + return &m_d3d10; + } + + static D3D11_RASTERIZER_DESC2 PromoteDesc( + const D3D11_RASTERIZER_DESC* pDesc); + + static D3D11_RASTERIZER_DESC2 PromoteDesc( + const D3D11_RASTERIZER_DESC1* pDesc); + + static HRESULT NormalizeDesc( + D3D11_RASTERIZER_DESC2* pDesc); + + private: + + D3D11_RASTERIZER_DESC2 m_desc; + DxvkRasterizerState m_state; + DxvkDepthBias m_depthBias; + D3D10RasterizerState m_d3d10; + + }; + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_resource.cpp b/utils/dxvk-1.10.3/src/d3d11/d3d11_resource.cpp new file mode 100644 index 00000000000..ab8aabe40aa --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_resource.cpp @@ -0,0 +1,263 @@ +#include "d3d11_buffer.h" +#include "d3d11_texture.h" +#include "d3d11_resource.h" + +#include "../util/util_shared_res.h" + +namespace dxvk { + + D3D11DXGIResource::D3D11DXGIResource( + ID3D11Resource* pResource) + : m_resource(pResource) { + + } + + + D3D11DXGIResource::~D3D11DXGIResource() { + + } + + + ULONG STDMETHODCALLTYPE D3D11DXGIResource::AddRef() { + return m_resource->AddRef(); + } + + + ULONG STDMETHODCALLTYPE D3D11DXGIResource::Release() { + return m_resource->Release(); + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIResource::QueryInterface( + REFIID riid, + void** ppvObject) { + return m_resource->QueryInterface(riid, ppvObject); + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIResource::GetPrivateData( + REFGUID Name, + UINT* pDataSize, + void* pData) { + return m_resource->GetPrivateData(Name, pDataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIResource::SetPrivateData( + REFGUID Name, + UINT DataSize, + const void* pData) { + return m_resource->SetPrivateData(Name, DataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIResource::SetPrivateDataInterface( + REFGUID Name, + const IUnknown* pUnknown) { + return m_resource->SetPrivateDataInterface(Name, pUnknown); + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIResource::GetParent( + REFIID riid, + void** ppParent) { + return GetDevice(riid, ppParent); + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIResource::GetDevice( + REFIID riid, + void** ppDevice) { + Com device; + m_resource->GetDevice(&device); + return device->QueryInterface(riid, ppDevice); + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIResource::GetEvictionPriority( + UINT* pEvictionPriority) { + *pEvictionPriority = m_resource->GetEvictionPriority(); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIResource::GetSharedHandle( + HANDLE* pSharedHandle) { + auto texture = GetCommonTexture(m_resource); + if (texture == nullptr || pSharedHandle == nullptr || !(texture->Desc()->MiscFlags & D3D11_RESOURCE_MISC_SHARED)) + return E_INVALIDARG; + + HANDLE kmtHandle = texture->GetImage()->sharedHandle(); + + if (kmtHandle == INVALID_HANDLE_VALUE) + return E_INVALIDARG; + + *pSharedHandle = kmtHandle; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIResource::GetUsage( + DXGI_USAGE* pUsage) { + D3D11_COMMON_RESOURCE_DESC desc; + + HRESULT hr = GetCommonResourceDesc(m_resource, &desc); + + if (FAILED(hr)) + return hr; + + DXGI_USAGE usage = desc.DxgiUsage; + + switch (desc.Usage) { + case D3D11_USAGE_IMMUTABLE: usage |= DXGI_CPU_ACCESS_NONE; break; + case D3D11_USAGE_DEFAULT: usage |= DXGI_CPU_ACCESS_NONE; break; + case D3D11_USAGE_DYNAMIC: usage |= DXGI_CPU_ACCESS_DYNAMIC; break; + case D3D11_USAGE_STAGING: usage |= DXGI_CPU_ACCESS_READ_WRITE; break; + } + + // TODO add flags for swap chain back buffers + if (desc.BindFlags & (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_CONSTANT_BUFFER)) + usage |= DXGI_USAGE_SHADER_INPUT; + + if (desc.BindFlags & D3D11_BIND_RENDER_TARGET) + usage |= DXGI_USAGE_RENDER_TARGET_OUTPUT; + + if (desc.BindFlags & D3D11_BIND_UNORDERED_ACCESS) + usage |= DXGI_USAGE_UNORDERED_ACCESS; + + *pUsage = usage; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIResource::SetEvictionPriority( + UINT EvictionPriority) { + m_resource->SetEvictionPriority(EvictionPriority); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIResource::CreateSharedHandle( + const SECURITY_ATTRIBUTES* pAttributes, + DWORD dwAccess, + LPCWSTR lpName, + HANDLE* pHandle) { + auto texture = GetCommonTexture(m_resource); + if (texture == nullptr || pHandle == nullptr || + !(texture->Desc()->MiscFlags & (D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX | D3D11_RESOURCE_MISC_SHARED_NTHANDLE))) + return E_INVALIDARG; + + if (lpName) + Logger::warn("Naming shared resources not supported"); + + HANDLE handle = texture->GetImage()->sharedHandle(); + + if (handle == INVALID_HANDLE_VALUE) + return E_INVALIDARG; + + if (texture->Desc()->MiscFlags & D3D11_RESOURCE_MISC_SHARED) + handle = openKmtHandle( handle ); + + *pHandle = handle; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGIResource::CreateSubresourceSurface( + UINT index, + IDXGISurface2** ppSurface) { + InitReturnPtr(ppSurface); + Logger::err("D3D11DXGIResource::CreateSubresourceSurface: Stub"); + return E_NOTIMPL; + } + + + HRESULT GetCommonResourceDesc( + ID3D11Resource* pResource, + D3D11_COMMON_RESOURCE_DESC* pDesc) { + auto buffer = GetCommonBuffer (pResource); + auto texture = GetCommonTexture(pResource); + + if (buffer != nullptr) { + pDesc->Dim = D3D11_RESOURCE_DIMENSION_BUFFER; + pDesc->Format = DXGI_FORMAT_UNKNOWN; + pDesc->Usage = buffer->Desc()->Usage; + pDesc->BindFlags = buffer->Desc()->BindFlags; + pDesc->CPUAccessFlags = buffer->Desc()->CPUAccessFlags; + pDesc->MiscFlags = buffer->Desc()->MiscFlags; + pDesc->DxgiUsage = 0; + return S_OK; + } else if (texture != nullptr) { + pResource->GetType(&pDesc->Dim); + pDesc->Format = texture->Desc()->Format; + pDesc->Usage = texture->Desc()->Usage; + pDesc->BindFlags = texture->Desc()->BindFlags; + pDesc->CPUAccessFlags = texture->Desc()->CPUAccessFlags; + pDesc->MiscFlags = texture->Desc()->MiscFlags; + pDesc->DxgiUsage = texture->GetDxgiUsage(); + return S_OK; + } else { + pDesc->Dim = D3D11_RESOURCE_DIMENSION_UNKNOWN; + pDesc->Format = DXGI_FORMAT_UNKNOWN; + pDesc->Usage = D3D11_USAGE_DEFAULT; + pDesc->BindFlags = 0; + pDesc->CPUAccessFlags = 0; + pDesc->MiscFlags = 0; + pDesc->DxgiUsage = 0; + return E_INVALIDARG; + } + } + + + BOOL CheckResourceViewCompatibility( + ID3D11Resource* pResource, + UINT BindFlags, + DXGI_FORMAT Format, + UINT Plane) { + auto texture = GetCommonTexture(pResource); + auto buffer = GetCommonBuffer (pResource); + + return texture != nullptr + ? texture->CheckViewCompatibility(BindFlags, Format, Plane) + : buffer ->CheckViewCompatibility(BindFlags, Format); + } + + + HRESULT ResourceAddRefPrivate(ID3D11Resource* pResource, D3D11_RESOURCE_DIMENSION Type) { + switch (Type) { + case D3D11_RESOURCE_DIMENSION_BUFFER: static_cast (pResource)->AddRefPrivate(); return S_OK; + case D3D11_RESOURCE_DIMENSION_TEXTURE1D: static_cast(pResource)->AddRefPrivate(); return S_OK; + case D3D11_RESOURCE_DIMENSION_TEXTURE2D: static_cast(pResource)->AddRefPrivate(); return S_OK; + case D3D11_RESOURCE_DIMENSION_TEXTURE3D: static_cast(pResource)->AddRefPrivate(); return S_OK; + default: return E_INVALIDARG; + } + } + + + HRESULT ResourceAddRefPrivate(ID3D11Resource* pResource) { + D3D11_RESOURCE_DIMENSION dim; + pResource->GetType(&dim); + + return ResourceAddRefPrivate(pResource, dim); + } + + + HRESULT ResourceReleasePrivate(ID3D11Resource* pResource, D3D11_RESOURCE_DIMENSION Type) { + switch (Type) { + case D3D11_RESOURCE_DIMENSION_BUFFER: static_cast (pResource)->ReleasePrivate(); return S_OK; + case D3D11_RESOURCE_DIMENSION_TEXTURE1D: static_cast(pResource)->ReleasePrivate(); return S_OK; + case D3D11_RESOURCE_DIMENSION_TEXTURE2D: static_cast(pResource)->ReleasePrivate(); return S_OK; + case D3D11_RESOURCE_DIMENSION_TEXTURE3D: static_cast(pResource)->ReleasePrivate(); return S_OK; + default: return E_INVALIDARG; + } + } + + + HRESULT ResourceReleasePrivate(ID3D11Resource* pResource) { + D3D11_RESOURCE_DIMENSION dim; + pResource->GetType(&dim); + + return ResourceReleasePrivate(pResource, dim); + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_resource.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_resource.h new file mode 100644 index 00000000000..0fd29f48dfa --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_resource.h @@ -0,0 +1,255 @@ +#pragma once + +#include "d3d11_include.h" + +namespace dxvk { + + /** + * \brief Common resource description + * + * Stores the usage and bind flags of a resource + * Can be used to quickly determine whether it is + * legal to create a view for a given resource. + */ + struct D3D11_COMMON_RESOURCE_DESC { + D3D11_RESOURCE_DIMENSION Dim; + DXGI_FORMAT Format; + D3D11_USAGE Usage; + UINT BindFlags; + UINT CPUAccessFlags; + UINT MiscFlags; + UINT DxgiUsage; + }; + + + /** + * \brief IDXGIResource implementation for D3D11 resources + */ + class D3D11DXGIResource : public IDXGIResource1 { + + public: + + D3D11DXGIResource( + ID3D11Resource* pResource); + + ~D3D11DXGIResource(); + + ULONG STDMETHODCALLTYPE AddRef(); + + ULONG STDMETHODCALLTYPE Release(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + HRESULT STDMETHODCALLTYPE GetPrivateData( + REFGUID Name, + UINT* pDataSize, + void* pData); + + HRESULT STDMETHODCALLTYPE SetPrivateData( + REFGUID Name, + UINT DataSize, + const void* pData); + + HRESULT STDMETHODCALLTYPE SetPrivateDataInterface( + REFGUID Name, + const IUnknown* pUnknown); + + HRESULT STDMETHODCALLTYPE GetParent( + REFIID riid, + void** ppParent); + + HRESULT STDMETHODCALLTYPE GetDevice( + REFIID riid, + void** ppDevice); + + HRESULT STDMETHODCALLTYPE GetEvictionPriority( + UINT* pEvictionPriority); + + HRESULT STDMETHODCALLTYPE GetSharedHandle( + HANDLE* pSharedHandle); + + HRESULT STDMETHODCALLTYPE GetUsage( + DXGI_USAGE* pUsage); + + HRESULT STDMETHODCALLTYPE SetEvictionPriority( + UINT EvictionPriority); + + HRESULT STDMETHODCALLTYPE CreateSharedHandle( + const SECURITY_ATTRIBUTES* pAttributes, + DWORD dwAccess, + LPCWSTR lpName, + HANDLE* pHandle); + + HRESULT STDMETHODCALLTYPE CreateSubresourceSurface( + UINT index, + IDXGISurface2** ppSurface); + + private: + + ID3D11Resource* m_resource; + + }; + + + /** + * \brief Queries common resource description + * + * \param [in] pResource The resource to query + * \param [out] pDesc Resource description + * \returns \c S_OK on success, or \c E_INVALIDARG + */ + HRESULT GetCommonResourceDesc( + ID3D11Resource* pResource, + D3D11_COMMON_RESOURCE_DESC* pDesc); + + /** + * \brief Checks whether a format can be used to view a resource + * + * Depending on whether the resource is a buffer or a + * texture, certain restrictions apply on which formats + * can be used to view the resource. + * \param [in] pResource The resource to check + * \param [in] BindFlags Bind flags required for the view + * \param [in] Format The desired view format + * \param [in] Plane Plane slice for planar formats + * \returns \c true if the format is compatible + */ + BOOL CheckResourceViewCompatibility( + ID3D11Resource* pResource, + UINT BindFlags, + DXGI_FORMAT Format, + UINT Plane); + + /** + * \brief Increments private reference count of a resource + * + * Helper method that figures out the exact type of + * the resource and calls its \c AddRefPrivate method. + * \param [in] pResource The resource to reference + * \param [in] Type Resource type + * \returns \c S_OK, or \c E_INVALIDARG for an invalid resource + */ + HRESULT ResourceAddRefPrivate( + ID3D11Resource* pResource, + D3D11_RESOURCE_DIMENSION Type); + + HRESULT ResourceAddRefPrivate( + ID3D11Resource* pResource); + + /** + * \brief Decrements private reference count of a resource + * + * Helper method that figures out the exact type of + * the resource and calls its \c ReleasePrivate method. + * \param [in] pResource The resource to reference + * \param [in] Type Resource type + * \returns \c S_OK, or \c E_INVALIDARG for an invalid resource + */ + HRESULT ResourceReleasePrivate( + ID3D11Resource* pResource, + D3D11_RESOURCE_DIMENSION Type); + + HRESULT ResourceReleasePrivate( + ID3D11Resource* pResource); + + /** + * \brief Typed private resource pointer + * + * Stores a resource and its type, in order to avoid + * unnecessary GetType calls. Also optionally stores + * a subresource index to avoid struct padding. + */ + class D3D11ResourceRef { + + public: + + D3D11ResourceRef() + : m_type(D3D11_RESOURCE_DIMENSION_UNKNOWN), + m_subresource(0), m_resource(nullptr) { } + + D3D11ResourceRef(ID3D11Resource* pResource) + : D3D11ResourceRef(pResource, 0) { } + + D3D11ResourceRef(ID3D11Resource* pResource, UINT Subresource) + : m_type(D3D11_RESOURCE_DIMENSION_UNKNOWN), + m_subresource(Subresource), m_resource(pResource) { + if (m_resource) { + m_resource->GetType(&m_type); + ResourceAddRefPrivate(m_resource, m_type); + } + } + + D3D11ResourceRef(ID3D11Resource* pResource, UINT Subresource, D3D11_RESOURCE_DIMENSION Type) + : m_type(Type), m_subresource(Subresource), m_resource(pResource) { + if (m_resource) + ResourceAddRefPrivate(m_resource, m_type); + } + + D3D11ResourceRef(D3D11ResourceRef&& other) + : m_type(other.m_type), m_subresource(other.m_subresource), m_resource(other.m_resource) { + other.m_type = D3D11_RESOURCE_DIMENSION_UNKNOWN; + other.m_subresource = 0; + other.m_resource = nullptr; + } + + D3D11ResourceRef(const D3D11ResourceRef& other) + : m_type(other.m_type), m_subresource(other.m_subresource), m_resource(other.m_resource) { + if (m_resource) + ResourceAddRefPrivate(m_resource, m_type); + } + + ~D3D11ResourceRef() { + if (m_resource) + ResourceReleasePrivate(m_resource, m_type); + } + + D3D11ResourceRef& operator = (D3D11ResourceRef&& other) { + if (m_resource) + ResourceReleasePrivate(m_resource, m_type); + + m_type = other.m_type; + m_subresource = other.m_subresource; + m_resource = other.m_resource; + + other.m_type = D3D11_RESOURCE_DIMENSION_UNKNOWN; + other.m_subresource = 0; + other.m_resource = nullptr; + return *this; + } + + D3D11ResourceRef& operator = (const D3D11ResourceRef& other) { + if (other.m_resource) + ResourceAddRefPrivate(other.m_resource, other.m_type); + + if (m_resource) + ResourceReleasePrivate(m_resource, m_type); + + m_type = other.m_type; + m_subresource = other.m_subresource; + m_resource = other.m_resource; + return *this; + } + + D3D11_RESOURCE_DIMENSION GetType() const { + return m_type; + } + + UINT GetSubresource() const { + return m_subresource; + } + + ID3D11Resource* Get() const { + return m_resource; + } + + private: + + D3D11_RESOURCE_DIMENSION m_type; + UINT m_subresource; + ID3D11Resource* m_resource; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_sampler.cpp b/utils/dxvk-1.10.3/src/d3d11/d3d11_sampler.cpp new file mode 100644 index 00000000000..e3e54cf393f --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_sampler.cpp @@ -0,0 +1,148 @@ +#include "d3d11_device.h" +#include "d3d11_sampler.h" +#include "d3d11_util.h" + +namespace dxvk { + + D3D11SamplerState::D3D11SamplerState( + D3D11Device* device, + const D3D11_SAMPLER_DESC& desc) + : D3D11StateObject(device), + m_desc(desc), m_d3d10(this) { + DxvkSamplerCreateInfo info; + + // While D3D11_FILTER is technically an enum, its value bits + // can be used to decode the filter properties more efficiently. + const uint32_t filterBits = uint32_t(desc.Filter); + info.magFilter = (filterBits & 0x04) ? VK_FILTER_LINEAR : VK_FILTER_NEAREST; + info.minFilter = (filterBits & 0x10) ? VK_FILTER_LINEAR : VK_FILTER_NEAREST; + + // Set up the remaining properties, which are + // stored directly in the sampler description + info.mipmapMode = (filterBits & 0x01) ? VK_SAMPLER_MIPMAP_MODE_LINEAR : VK_SAMPLER_MIPMAP_MODE_NEAREST; + info.mipmapLodBias = desc.MipLODBias; + info.mipmapLodMin = desc.MinLOD; + info.mipmapLodMax = desc.MaxLOD; + + info.useAnisotropy = (filterBits & 0x40) ? VK_TRUE : VK_FALSE; + info.maxAnisotropy = float(desc.MaxAnisotropy); + + info.addressModeU = DecodeAddressMode(desc.AddressU); + info.addressModeV = DecodeAddressMode(desc.AddressV); + info.addressModeW = DecodeAddressMode(desc.AddressW); + + info.compareToDepth = (filterBits & 0x80) ? VK_TRUE : VK_FALSE; + info.compareOp = DecodeCompareOp(desc.ComparisonFunc); + + for (uint32_t i = 0; i < 4; i++) + info.borderColor.float32[i] = desc.BorderColor[i]; + + info.usePixelCoord = VK_FALSE; // Not supported in D3D11 + info.nonSeamless = VK_FALSE; + + // Make sure to use a valid anisotropy value + if (desc.MaxAnisotropy < 1) info.maxAnisotropy = 1.0f; + if (desc.MaxAnisotropy > 16) info.maxAnisotropy = 16.0f; + + // Enforce anisotropy specified in the device options + int32_t samplerAnisotropyOption = device->GetOptions()->samplerAnisotropy; + + if (samplerAnisotropyOption >= 0 && info.minFilter == VK_FILTER_LINEAR) { + info.useAnisotropy = samplerAnisotropyOption > 0; + info.maxAnisotropy = float(samplerAnisotropyOption); + } + + m_sampler = device->GetDXVKDevice()->createSampler(info); + } + + + D3D11SamplerState::~D3D11SamplerState() { + + } + + + HRESULT STDMETHODCALLTYPE D3D11SamplerState::QueryInterface(REFIID riid, void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(ID3D11DeviceChild) + || riid == __uuidof(ID3D11SamplerState)) { + *ppvObject = ref(this); + return S_OK; + } + + if (riid == __uuidof(ID3D10DeviceChild) + || riid == __uuidof(ID3D10SamplerState)) { + *ppvObject = ref(&m_d3d10); + return S_OK; + } + + Logger::warn("D3D11SamplerState::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + void STDMETHODCALLTYPE D3D11SamplerState::GetDesc(D3D11_SAMPLER_DESC* pDesc) { + *pDesc = m_desc; + } + + + HRESULT D3D11SamplerState::NormalizeDesc(D3D11_SAMPLER_DESC* pDesc) { + const uint32_t filterBits = uint32_t(pDesc->Filter); + + if (filterBits & 0xFFFFFF2A) { + Logger::err(str::format( + "D3D11SamplerState: Unhandled filter: ", filterBits)); + return E_INVALIDARG; + } + + if (pDesc->MaxAnisotropy < 0 + || pDesc->MaxAnisotropy > 16) { + return E_INVALIDARG; + } else if ((filterBits & 0x40) == 0 /* not anisotropic */) { + // Reset anisotropy if it is not used + pDesc->MaxAnisotropy = 0; + } + + if (filterBits & 0x80 /* compare-to-depth */) { + if (!ValidateComparisonFunc(pDesc->ComparisonFunc)) + return E_INVALIDARG; + } else { + // Reset compare func if it is not used + pDesc->ComparisonFunc = D3D11_COMPARISON_NEVER; + } + + if (!ValidateAddressMode(pDesc->AddressU) + || !ValidateAddressMode(pDesc->AddressV) + || !ValidateAddressMode(pDesc->AddressW)) + return E_INVALIDARG; + + // Clear BorderColor to 0 if none of the address + // modes are D3D11_TEXTURE_ADDRESS_BORDER + if (pDesc->AddressU != D3D11_TEXTURE_ADDRESS_BORDER + && pDesc->AddressV != D3D11_TEXTURE_ADDRESS_BORDER + && pDesc->AddressW != D3D11_TEXTURE_ADDRESS_BORDER) { + for (int i = 0; i < 4; i++) + pDesc->BorderColor[i] = 0.0f; + } + + return S_OK; + } + + + bool D3D11SamplerState::ValidateAddressMode(D3D11_TEXTURE_ADDRESS_MODE Mode) { + return Mode >= D3D11_TEXTURE_ADDRESS_WRAP + && Mode <= D3D11_TEXTURE_ADDRESS_MIRROR_ONCE; + } + + + bool D3D11SamplerState::ValidateComparisonFunc(D3D11_COMPARISON_FUNC Comparison) { + return Comparison >= D3D11_COMPARISON_NEVER + && Comparison <= D3D11_COMPARISON_ALWAYS; + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_sampler.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_sampler.h new file mode 100644 index 00000000000..57fa139b4f3 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_sampler.h @@ -0,0 +1,58 @@ +#pragma once + +#include "../dxvk/dxvk_device.h" + +#include "../d3d10/d3d10_sampler.h" + +#include "d3d11_device_child.h" + +namespace dxvk { + + class D3D11Device; + + class D3D11SamplerState : public D3D11StateObject { + + public: + + using DescType = D3D11_SAMPLER_DESC; + + D3D11SamplerState( + D3D11Device* device, + const D3D11_SAMPLER_DESC& desc); + ~D3D11SamplerState(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject) final; + + void STDMETHODCALLTYPE GetDesc( + D3D11_SAMPLER_DESC* pDesc) final; + + Rc GetDXVKSampler() const { + return m_sampler; + } + + D3D10SamplerState* GetD3D10Iface() { + return &m_d3d10; + } + + static HRESULT NormalizeDesc( + D3D11_SAMPLER_DESC* pDesc); + + private: + + D3D11_SAMPLER_DESC m_desc; + Rc m_sampler; + D3D10SamplerState m_d3d10; + + std::atomic m_refCount = { 0u }; + + static bool ValidateAddressMode( + D3D11_TEXTURE_ADDRESS_MODE Mode); + + static bool ValidateComparisonFunc( + D3D11_COMPARISON_FUNC Comparison); + + }; + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_shader.cpp b/utils/dxvk-1.10.3/src/d3d11/d3d11_shader.cpp new file mode 100644 index 00000000000..800bdea8d22 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_shader.cpp @@ -0,0 +1,128 @@ +#include "d3d11_device.h" +#include "d3d11_shader.h" + +namespace dxvk { + + D3D11CommonShader:: D3D11CommonShader() { } + D3D11CommonShader::~D3D11CommonShader() { } + + + D3D11CommonShader::D3D11CommonShader( + D3D11Device* pDevice, + const DxvkShaderKey* pShaderKey, + const DxbcModuleInfo* pDxbcModuleInfo, + const void* pShaderBytecode, + size_t BytecodeLength) { + const std::string name = pShaderKey->toString(); + Logger::debug(str::format("Compiling shader ", name)); + + DxbcReader reader( + reinterpret_cast(pShaderBytecode), + BytecodeLength); + + DxbcModule module(reader); + + // If requested by the user, dump both the raw DXBC + // shader and the compiled SPIR-V module to a file. + const std::string dumpPath = env::getEnvVar("DXVK_SHADER_DUMP_PATH"); + + if (dumpPath.size() != 0) { + reader.store(std::ofstream(str::tows(str::format(dumpPath, "/", name, ".dxbc").c_str()).c_str(), + std::ios_base::binary | std::ios_base::trunc)); + } + + // Decide whether we need to create a pass-through + // geometry shader for vertex shader stream output + bool passthroughShader = pDxbcModuleInfo->xfb != nullptr + && (module.programInfo().type() == DxbcProgramType::VertexShader + || module.programInfo().type() == DxbcProgramType::DomainShader); + + if (module.programInfo().shaderStage() != pShaderKey->type() && !passthroughShader) + throw DxvkError("Mismatching shader type."); + + m_shader = passthroughShader + ? module.compilePassthroughShader(*pDxbcModuleInfo, name) + : module.compile (*pDxbcModuleInfo, name); + m_shader->setShaderKey(*pShaderKey); + + if (dumpPath.size() != 0) { + std::ofstream dumpStream( + str::tows(str::format(dumpPath, "/", name, ".spv").c_str()).c_str(), + std::ios_base::binary | std::ios_base::trunc); + + m_shader->dump(dumpStream); + } + + // Create shader constant buffer if necessary + const DxvkShaderCreateInfo& shaderInfo = m_shader->info(); + + if (shaderInfo.uniformSize) { + DxvkBufferCreateInfo info; + info.size = shaderInfo.uniformSize; + info.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; + info.stages = util::pipelineStages(shaderInfo.stage); + info.access = VK_ACCESS_UNIFORM_READ_BIT; + + VkMemoryPropertyFlags memFlags + = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT + | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT + | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + + m_buffer = pDevice->GetDXVKDevice()->createBuffer(info, memFlags); + std::memcpy(m_buffer->mapPtr(0), shaderInfo.uniformData, shaderInfo.uniformSize); + } + + pDevice->GetDXVKDevice()->registerShader(m_shader); + } + + + D3D11ShaderModuleSet:: D3D11ShaderModuleSet() { } + D3D11ShaderModuleSet::~D3D11ShaderModuleSet() { } + + + HRESULT D3D11ShaderModuleSet::GetShaderModule( + D3D11Device* pDevice, + const DxvkShaderKey* pShaderKey, + const DxbcModuleInfo* pDxbcModuleInfo, + const void* pShaderBytecode, + size_t BytecodeLength, + D3D11CommonShader* pShader) { + // Use the shader's unique key for the lookup + { std::unique_lock lock(m_mutex); + + auto entry = m_modules.find(*pShaderKey); + if (entry != m_modules.end()) { + *pShader = entry->second; + return S_OK; + } + } + + // This shader has not been compiled yet, so we have to create a + // new module. This takes a while, so we won't lock the structure. + D3D11CommonShader module; + + try { + module = D3D11CommonShader(pDevice, pShaderKey, + pDxbcModuleInfo, pShaderBytecode, BytecodeLength); + } catch (const DxvkError& e) { + Logger::err(e.message()); + return E_INVALIDARG; + } + + // Insert the new module into the lookup table. If another thread + // has compiled the same shader in the meantime, we should return + // that object instead and discard the newly created module. + { std::unique_lock lock(m_mutex); + + auto status = m_modules.insert({ *pShaderKey, module }); + if (!status.second) { + *pShader = status.first->second; + return S_OK; + } + } + + *pShader = std::move(module); + return S_OK; + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_shader.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_shader.h new file mode 100644 index 00000000000..3ab16854ed3 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_shader.h @@ -0,0 +1,158 @@ +#pragma once + +#include +#include + +#include "../dxbc/dxbc_module.h" +#include "../dxvk/dxvk_device.h" + +#include "../d3d10/d3d10_shader.h" + +#include "../util/sha1/sha1_util.h" + +#include "../util/util_env.h" + +#include "d3d11_device_child.h" +#include "d3d11_interfaces.h" + +namespace dxvk { + + class D3D11Device; + + /** + * \brief Common shader object + * + * Stores the compiled SPIR-V shader and the SHA-1 + * hash of the original DXBC shader, which can be + * used to identify the shader. + */ + class D3D11CommonShader { + + public: + + D3D11CommonShader(); + D3D11CommonShader( + D3D11Device* pDevice, + const DxvkShaderKey* pShaderKey, + const DxbcModuleInfo* pDxbcModuleInfo, + const void* pShaderBytecode, + size_t BytecodeLength); + ~D3D11CommonShader(); + + Rc GetShader() const { + return m_shader; + } + + Rc GetIcb() const { + return m_buffer; + } + + std::string GetName() const { + return m_shader->debugName(); + } + + private: + + Rc m_shader; + Rc m_buffer; + + }; + + + /** + * \brief Common shader interface + * + * Implements methods for all D3D11*Shader + * interfaces and stores the actual shader + * module object. + */ + template + class D3D11Shader : public D3D11DeviceChild { + using D3D10ShaderClass = D3D10Shader; + public: + + D3D11Shader(D3D11Device* device, const D3D11CommonShader& shader) + : D3D11DeviceChild(device), + m_shader(shader), m_d3d10(this) { } + + ~D3D11Shader() { } + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) final { + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(ID3D11DeviceChild) + || riid == __uuidof(D3D11Interface)) { + *ppvObject = ref(this); + return S_OK; + } + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(ID3D10DeviceChild) + || riid == __uuidof(D3D10Interface)) { + *ppvObject = ref(&m_d3d10); + return S_OK; + } + + Logger::warn("D3D11Shader::QueryInterface: Unknown interface query"); + return E_NOINTERFACE; + } + + const D3D11CommonShader* GetCommonShader() const { + return &m_shader; + } + + D3D10ShaderClass* GetD3D10Iface() { + return &m_d3d10; + } + + private: + + D3D11CommonShader m_shader; + D3D10ShaderClass m_d3d10; + + }; + + using D3D11VertexShader = D3D11Shader; + using D3D11HullShader = D3D11Shader; + using D3D11DomainShader = D3D11Shader; + using D3D11GeometryShader = D3D11Shader; + using D3D11PixelShader = D3D11Shader; + using D3D11ComputeShader = D3D11Shader; + + + /** + * \brief Shader module set + * + * Some applications may compile the same shader multiple + * times, so we should cache the resulting shader modules + * and reuse them rather than creating new ones. This + * class is thread-safe. + */ + class D3D11ShaderModuleSet { + + public: + + D3D11ShaderModuleSet(); + ~D3D11ShaderModuleSet(); + + HRESULT GetShaderModule( + D3D11Device* pDevice, + const DxvkShaderKey* pShaderKey, + const DxbcModuleInfo* pDxbcModuleInfo, + const void* pShaderBytecode, + size_t BytecodeLength, + D3D11CommonShader* pShader); + + private: + + dxvk::mutex m_mutex; + + std::unordered_map< + DxvkShaderKey, + D3D11CommonShader, + DxvkHash, DxvkEq> m_modules; + + }; + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_state.cpp b/utils/dxvk-1.10.3/src/d3d11/d3d11_state.cpp new file mode 100644 index 00000000000..161566c023a --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_state.cpp @@ -0,0 +1,199 @@ +#include "d3d11_state.h" + +namespace dxvk { + + size_t D3D11StateDescHash::operator () ( + const D3D11_BLEND_DESC1& desc) const { + DxvkHashState hash; + hash.add(desc.AlphaToCoverageEnable); + hash.add(desc.IndependentBlendEnable); + + // Render targets 1 to 7 are ignored and may contain + // undefined data if independent blend is disabled + const uint32_t usedRenderTargets = desc.IndependentBlendEnable ? 8 : 1; + + for (uint32_t i = 0; i < usedRenderTargets; i++) + hash.add(this->operator () (desc.RenderTarget[i])); + + return hash; + } + + + size_t D3D11StateDescHash::operator () ( + const D3D11_DEPTH_STENCILOP_DESC& desc) const { + DxvkHashState hash; + hash.add(desc.StencilFunc); + hash.add(desc.StencilDepthFailOp); + hash.add(desc.StencilPassOp); + hash.add(desc.StencilFailOp); + return hash; + } + + + size_t D3D11StateDescHash::operator () ( + const D3D11_DEPTH_STENCIL_DESC& desc) const { + DxvkHashState hash; + hash.add(desc.DepthEnable); + hash.add(desc.DepthWriteMask); + hash.add(desc.DepthFunc); + hash.add(desc.StencilEnable); + hash.add(desc.StencilReadMask); + hash.add(desc.StencilWriteMask); + hash.add(this->operator () (desc.FrontFace)); + hash.add(this->operator () (desc.BackFace)); + return hash; + } + + + size_t D3D11StateDescHash::operator () ( + const D3D11_RASTERIZER_DESC2& desc) const { + std::hash fhash; + + DxvkHashState hash; + hash.add(desc.FillMode); + hash.add(desc.CullMode); + hash.add(desc.FrontCounterClockwise); + hash.add(desc.DepthBias); + hash.add(fhash(desc.SlopeScaledDepthBias)); + hash.add(fhash(desc.DepthBiasClamp)); + hash.add(desc.DepthClipEnable); + hash.add(desc.ScissorEnable); + hash.add(desc.MultisampleEnable); + hash.add(desc.AntialiasedLineEnable); + hash.add(desc.ForcedSampleCount); + hash.add(desc.ConservativeRaster); + return hash; + } + + + size_t D3D11StateDescHash::operator () ( + const D3D11_RENDER_TARGET_BLEND_DESC1& desc) const { + DxvkHashState hash; + hash.add(desc.BlendEnable); + hash.add(desc.LogicOpEnable); + hash.add(desc.SrcBlend); + hash.add(desc.DestBlend); + hash.add(desc.BlendOp); + hash.add(desc.SrcBlendAlpha); + hash.add(desc.DestBlendAlpha); + hash.add(desc.BlendOpAlpha); + hash.add(desc.LogicOp); + hash.add(desc.RenderTargetWriteMask); + return hash; + } + + + size_t D3D11StateDescHash::operator () ( + const D3D11_SAMPLER_DESC& desc) const { + std::hash fhash; + + DxvkHashState hash; + hash.add(desc.Filter); + hash.add(desc.AddressU); + hash.add(desc.AddressV); + hash.add(desc.AddressW); + hash.add(fhash(desc.MipLODBias)); + hash.add(desc.MaxAnisotropy); + hash.add(desc.ComparisonFunc); + for (uint32_t i = 0; i < 4; i++) + hash.add(fhash(desc.BorderColor[i])); + hash.add(fhash(desc.MinLOD)); + hash.add(fhash(desc.MaxLOD)); + return hash; + } + + + bool D3D11StateDescEqual::operator () ( + const D3D11_BLEND_DESC1& a, + const D3D11_BLEND_DESC1& b) const { + bool eq = a.AlphaToCoverageEnable == b.AlphaToCoverageEnable + && a.IndependentBlendEnable == b.IndependentBlendEnable; + + // Render targets 1 to 7 are ignored and may contain + // undefined data if independent blend is disabled + const uint32_t usedRenderTargets = a.IndependentBlendEnable ? 8 : 1; + + for (uint32_t i = 0; eq && (i < usedRenderTargets); i++) + eq &= this->operator () (a.RenderTarget[i], b.RenderTarget[i]); + + return eq; + } + + + bool D3D11StateDescEqual::operator () ( + const D3D11_DEPTH_STENCILOP_DESC& a, + const D3D11_DEPTH_STENCILOP_DESC& b) const { + return a.StencilFunc == b.StencilFunc + && a.StencilDepthFailOp == b.StencilDepthFailOp + && a.StencilPassOp == b.StencilPassOp + && a.StencilFailOp == b.StencilFailOp; + } + + + bool D3D11StateDescEqual::operator () ( + const D3D11_DEPTH_STENCIL_DESC& a, + const D3D11_DEPTH_STENCIL_DESC& b) const { + return a.DepthEnable == b.DepthEnable + && a.DepthWriteMask == b.DepthWriteMask + && a.DepthFunc == b.DepthFunc + && a.StencilEnable == b.StencilEnable + && a.StencilReadMask == b.StencilReadMask + && a.StencilWriteMask == b.StencilWriteMask + && this->operator () (a.FrontFace, b.FrontFace) + && this->operator () (a.BackFace, b.BackFace); + } + + + bool D3D11StateDescEqual::operator () ( + const D3D11_RASTERIZER_DESC2& a, + const D3D11_RASTERIZER_DESC2& b) const { + return a.FillMode == b.FillMode + && a.CullMode == b.CullMode + && a.FrontCounterClockwise == b.FrontCounterClockwise + && a.DepthBias == b.DepthBias + && a.SlopeScaledDepthBias == b.SlopeScaledDepthBias + && a.DepthBiasClamp == b.DepthBiasClamp + && a.DepthClipEnable == b.DepthClipEnable + && a.ScissorEnable == b.ScissorEnable + && a.MultisampleEnable == b.MultisampleEnable + && a.AntialiasedLineEnable == b.AntialiasedLineEnable + && a.ForcedSampleCount == b.ForcedSampleCount + && a.ConservativeRaster == b.ConservativeRaster; + } + + + bool D3D11StateDescEqual::operator () ( + const D3D11_RENDER_TARGET_BLEND_DESC1& a, + const D3D11_RENDER_TARGET_BLEND_DESC1& b) const { + return a.BlendEnable == b.BlendEnable + && a.LogicOpEnable == b.LogicOpEnable + && a.SrcBlend == b.SrcBlend + && a.DestBlend == b.DestBlend + && a.BlendOp == b.BlendOp + && a.SrcBlendAlpha == b.SrcBlendAlpha + && a.DestBlendAlpha == b.DestBlendAlpha + && a.BlendOpAlpha == b.BlendOpAlpha + && a.LogicOp == b.LogicOp + && a.RenderTargetWriteMask == b.RenderTargetWriteMask; + } + + + bool D3D11StateDescEqual::operator () ( + const D3D11_SAMPLER_DESC& a, + const D3D11_SAMPLER_DESC& b) const { + return a.Filter == b.Filter + && a.AddressU == b.AddressU + && a.AddressV == b.AddressV + && a.AddressW == b.AddressW + && a.MipLODBias == b.MipLODBias + && a.MaxAnisotropy == b.MaxAnisotropy + && a.ComparisonFunc == b.ComparisonFunc + && a.BorderColor[0] == b.BorderColor[0] + && a.BorderColor[1] == b.BorderColor[1] + && a.BorderColor[2] == b.BorderColor[2] + && a.BorderColor[3] == b.BorderColor[3] + && a.MinLOD == b.MinLOD + && a.MaxLOD == b.MaxLOD; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_state.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_state.h new file mode 100644 index 00000000000..e807d1ad334 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_state.h @@ -0,0 +1,79 @@ +#pragma once + +#include + +#include "d3d11_blend.h" +#include "d3d11_depth_stencil.h" +#include "d3d11_rasterizer.h" +#include "d3d11_sampler.h" + +namespace dxvk { + + class D3D11Device; + + struct D3D11StateDescHash { + size_t operator () (const D3D11_BLEND_DESC1& desc) const; + size_t operator () (const D3D11_DEPTH_STENCILOP_DESC& desc) const; + size_t operator () (const D3D11_DEPTH_STENCIL_DESC& desc) const; + size_t operator () (const D3D11_RASTERIZER_DESC2& desc) const; + size_t operator () (const D3D11_RENDER_TARGET_BLEND_DESC1& desc) const; + size_t operator () (const D3D11_SAMPLER_DESC& desc) const; + }; + + + struct D3D11StateDescEqual { + bool operator () (const D3D11_BLEND_DESC1& a, const D3D11_BLEND_DESC1& b) const; + bool operator () (const D3D11_DEPTH_STENCILOP_DESC& a, const D3D11_DEPTH_STENCILOP_DESC& b) const; + bool operator () (const D3D11_DEPTH_STENCIL_DESC& a, const D3D11_DEPTH_STENCIL_DESC& b) const; + bool operator () (const D3D11_RASTERIZER_DESC2& a, const D3D11_RASTERIZER_DESC2& b) const; + bool operator () (const D3D11_RENDER_TARGET_BLEND_DESC1& a, const D3D11_RENDER_TARGET_BLEND_DESC1& b) const; + bool operator () (const D3D11_SAMPLER_DESC& a, const D3D11_SAMPLER_DESC& b) const; + }; + + + /** + * \brief Unique state object set + * + * When creating state objects, D3D11 first checks if + * an object with the same description already exists + * and returns it if that is the case. This class + * implements that behaviour. + */ + template + class D3D11StateObjectSet { + using DescType = typename T::DescType; + public: + + /** + * \brief Retrieves a state object + * + * Returns an object with the same description or + * creates a new one if no such object exists. + * \param [in] device The calling D3D11 device + * \param [in] desc State object description + * \returns Pointer to the state object + */ + T* Create(D3D11Device* device, const DescType& desc) { + std::lock_guard lock(m_mutex); + + auto entry = m_objects.find(desc); + + if (entry != m_objects.end()) + return ref(&entry->second); + + auto result = m_objects.emplace( + std::piecewise_construct, + std::tuple(desc), + std::tuple(device, desc)); + return ref(&result.first->second); + } + + private: + + dxvk::mutex m_mutex; + std::unordered_map m_objects; + + }; + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_state_object.cpp b/utils/dxvk-1.10.3/src/d3d11/d3d11_state_object.cpp new file mode 100644 index 00000000000..33cc8a33f3d --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_state_object.cpp @@ -0,0 +1,37 @@ +#include "d3d11_state_object.h" + +namespace dxvk { + + D3D11DeviceContextState::D3D11DeviceContextState( + D3D11Device* pDevice) + : D3D11DeviceChild(pDevice) { + + } + + + D3D11DeviceContextState::~D3D11DeviceContextState() { + + } + + + HRESULT STDMETHODCALLTYPE D3D11DeviceContextState::QueryInterface( + REFIID riid, + void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(ID3D11DeviceChild) + || riid == __uuidof(ID3DDeviceContextState)) { + *ppvObject = ref(this); + return S_OK; + } + + Logger::warn("D3D11DeviceContextState::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_state_object.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_state_object.h new file mode 100644 index 00000000000..775a0951c11 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_state_object.h @@ -0,0 +1,44 @@ +#pragma once + +#include "d3d11_device.h" +#include "d3d11_context_state.h" +#include "d3d11_device_child.h" + +namespace dxvk { + + /** + * \brief Device context state implementation + * + * This is an opaque interface in D3D11, and we only + * implement the state block-like functionality, not + * the methods to disable certain context and device + * interfaces based on the emulated device IID. + */ + class D3D11DeviceContextState : public D3D11DeviceChild { + + public: + + D3D11DeviceContextState( + D3D11Device* pDevice); + + ~D3D11DeviceContextState(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + void SetState(const D3D11ContextState& State) { + m_state = State; + } + + void GetState(D3D11ContextState& State) const { + State = m_state; + } + + private: + + D3D11ContextState m_state; + + }; + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_swapchain.cpp b/utils/dxvk-1.10.3/src/d3d11/d3d11_swapchain.cpp new file mode 100644 index 00000000000..56c51a7b856 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_swapchain.cpp @@ -0,0 +1,657 @@ +#include "d3d11_context_imm.h" +#include "d3d11_device.h" +#include "d3d11_swapchain.h" + +namespace dxvk { + + static uint16_t MapGammaControlPoint(float x) { + if (x < 0.0f) x = 0.0f; + if (x > 1.0f) x = 1.0f; + return uint16_t(65535.0f * x); + } + + + D3D11SwapChain::D3D11SwapChain( + D3D11DXGIDevice* pContainer, + D3D11Device* pDevice, + HWND hWnd, + const DXGI_SWAP_CHAIN_DESC1* pDesc) + : m_dxgiDevice(pContainer), + m_parent (pDevice), + m_window (hWnd), + m_desc (*pDesc), + m_device (pDevice->GetDXVKDevice()), + m_context (m_device->createContext()), + m_frameLatencyCap(pDevice->GetOptions()->maxFrameLatency) { + CreateFrameLatencyEvent(); + + if (!pDevice->GetOptions()->deferSurfaceCreation) + CreatePresenter(); + + CreateBackBuffer(); + CreateBlitter(); + CreateHud(); + } + + + D3D11SwapChain::~D3D11SwapChain() { + m_device->waitForSubmission(&m_presentStatus); + m_device->waitForIdle(); + + DestroyFrameLatencyEvent(); + } + + + HRESULT STDMETHODCALLTYPE D3D11SwapChain::QueryInterface( + REFIID riid, + void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + InitReturnPtr(ppvObject); + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(IDXGIVkSwapChain)) { + *ppvObject = ref(this); + return S_OK; + } + + Logger::warn("D3D11SwapChain::QueryInterface: Unknown interface query"); + return E_NOINTERFACE; + } + + + HRESULT STDMETHODCALLTYPE D3D11SwapChain::GetDesc( + DXGI_SWAP_CHAIN_DESC1* pDesc) { + *pDesc = m_desc; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11SwapChain::GetAdapter( + REFIID riid, + void** ppvObject) { + return m_dxgiDevice->GetParent(riid, ppvObject); + } + + + HRESULT STDMETHODCALLTYPE D3D11SwapChain::GetDevice( + REFIID riid, + void** ppDevice) { + return m_dxgiDevice->QueryInterface(riid, ppDevice); + } + + + HRESULT STDMETHODCALLTYPE D3D11SwapChain::GetImage( + UINT BufferId, + REFIID riid, + void** ppBuffer) { + InitReturnPtr(ppBuffer); + + if (BufferId > 0) { + Logger::err("D3D11: GetImage: BufferId > 0 not supported"); + return DXGI_ERROR_UNSUPPORTED; + } + + return m_backBuffer->QueryInterface(riid, ppBuffer); + } + + + UINT STDMETHODCALLTYPE D3D11SwapChain::GetImageIndex() { + return 0; + } + + + UINT STDMETHODCALLTYPE D3D11SwapChain::GetFrameLatency() { + return m_frameLatency; + } + + + HANDLE STDMETHODCALLTYPE D3D11SwapChain::GetFrameLatencyEvent() { + return m_frameLatencyEvent; + } + + + HRESULT STDMETHODCALLTYPE D3D11SwapChain::ChangeProperties( + const DXGI_SWAP_CHAIN_DESC1* pDesc) { + + m_dirty |= m_desc.Format != pDesc->Format + || m_desc.Width != pDesc->Width + || m_desc.Height != pDesc->Height + || m_desc.BufferCount != pDesc->BufferCount + || m_desc.Flags != pDesc->Flags; + + m_desc = *pDesc; + CreateBackBuffer(); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11SwapChain::SetPresentRegion( + const RECT* pRegion) { + // TODO implement + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE D3D11SwapChain::SetGammaControl( + UINT NumControlPoints, + const DXGI_RGB* pControlPoints) { + bool isIdentity = true; + + if (NumControlPoints > 1) { + std::array cp; + + if (NumControlPoints > cp.size()) + return E_INVALIDARG; + + for (uint32_t i = 0; i < NumControlPoints; i++) { + uint16_t identity = MapGammaControlPoint(float(i) / float(NumControlPoints - 1)); + + cp[i].r = MapGammaControlPoint(pControlPoints[i].Red); + cp[i].g = MapGammaControlPoint(pControlPoints[i].Green); + cp[i].b = MapGammaControlPoint(pControlPoints[i].Blue); + cp[i].a = 0; + + isIdentity &= cp[i].r == identity + && cp[i].g == identity + && cp[i].b == identity; + } + + if (!isIdentity) + m_blitter->setGammaRamp(NumControlPoints, cp.data()); + } + + if (isIdentity) + m_blitter->setGammaRamp(0, nullptr); + + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11SwapChain::SetFrameLatency( + UINT MaxLatency) { + if (MaxLatency == 0 || MaxLatency > DXGI_MAX_SWAP_CHAIN_BUFFERS) + return DXGI_ERROR_INVALID_CALL; + + if (m_frameLatencyEvent) { + // Windows DXGI does not seem to handle the case where the new maximum + // latency is less than the current value, and some games relying on + // this behaviour will hang if we attempt to decrement the semaphore. + // Thus, only increment the semaphore as necessary. + if (MaxLatency > m_frameLatency) + ReleaseSemaphore(m_frameLatencyEvent, MaxLatency - m_frameLatency, nullptr); + } + + m_frameLatency = MaxLatency; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11SwapChain::Present( + UINT SyncInterval, + UINT PresentFlags, + const DXGI_PRESENT_PARAMETERS* pPresentParameters) { + auto options = m_parent->GetOptions(); + + if (options->syncInterval >= 0) + SyncInterval = options->syncInterval; + + if (!(PresentFlags & DXGI_PRESENT_TEST)) { + bool vsync = SyncInterval != 0; + + m_dirty |= vsync != m_vsync; + m_vsync = vsync; + } + + if (m_presenter == nullptr) + CreatePresenter(); + + HRESULT hr = S_OK; + + if (!m_presenter->hasSwapChain()) { + RecreateSwapChain(m_vsync); + m_dirty = false; + } + + if (!m_presenter->hasSwapChain()) + hr = DXGI_STATUS_OCCLUDED; + + if (m_device->getDeviceStatus() != VK_SUCCESS) + hr = DXGI_ERROR_DEVICE_RESET; + + if ((PresentFlags & DXGI_PRESENT_TEST) || hr != S_OK) + return hr; + + if (std::exchange(m_dirty, false)) + RecreateSwapChain(m_vsync); + + try { + PresentImage(SyncInterval); + } catch (const DxvkError& e) { + Logger::err(e.message()); + hr = E_FAIL; + } + + return hr; + } + + + void STDMETHODCALLTYPE D3D11SwapChain::NotifyModeChange( + BOOL Windowed, + const DXGI_MODE_DESC* pDisplayMode) { + if (Windowed || !pDisplayMode) { + // Display modes aren't meaningful in windowed mode + m_displayRefreshRate = 0.0; + } else { + DXGI_RATIONAL rate = pDisplayMode->RefreshRate; + m_displayRefreshRate = double(rate.Numerator) / double(rate.Denominator); + } + + if (m_presenter != nullptr) + m_presenter->setFrameRateLimiterRefreshRate(m_displayRefreshRate); + } + + + HRESULT D3D11SwapChain::PresentImage(UINT SyncInterval) { + Com deviceContext = nullptr; + m_parent->GetImmediateContext(&deviceContext); + + // Flush pending rendering commands before + auto immediateContext = static_cast(deviceContext.ptr()); + immediateContext->Flush(); + + // Bump our frame id. + ++m_frameId; + + for (uint32_t i = 0; i < SyncInterval || i < 1; i++) { + SynchronizePresent(); + + if (!m_presenter->hasSwapChain()) + return DXGI_STATUS_OCCLUDED; + + // Presentation semaphores and WSI swap chain image + vk::PresenterInfo info = m_presenter->info(); + vk::PresenterSync sync; + + uint32_t imageIndex = 0; + + VkResult status = m_presenter->acquireNextImage(sync, imageIndex); + + while (status != VK_SUCCESS && status != VK_SUBOPTIMAL_KHR) { + RecreateSwapChain(m_vsync); + + if (!m_presenter->hasSwapChain()) + return DXGI_STATUS_OCCLUDED; + + info = m_presenter->info(); + status = m_presenter->acquireNextImage(sync, imageIndex); + } + + // Resolve back buffer if it is multisampled. We + // only have to do it only for the first frame. + m_context->beginRecording( + m_device->createCommandList()); + + m_blitter->presentImage(m_context.ptr(), + m_imageViews.at(imageIndex), VkRect2D(), + m_swapImageView, VkRect2D()); + + if (m_hud != nullptr) + m_hud->render(m_context, info.format, info.imageExtent); + + if (i + 1 >= SyncInterval) + m_context->signal(m_frameLatencySignal, m_frameId); + + SubmitPresent(immediateContext, sync, i); + } + + SyncFrameLatency(); + return S_OK; + } + + + void D3D11SwapChain::SubmitPresent( + D3D11ImmediateContext* pContext, + const vk::PresenterSync& Sync, + uint32_t FrameId) { + auto lock = pContext->LockContext(); + + // Present from CS thread so that we don't + // have to synchronize with it first. + m_presentStatus.result = VK_NOT_READY; + + pContext->EmitCs([this, + cFrameId = FrameId, + cSync = Sync, + cHud = m_hud, + cCommandList = m_context->endRecording() + ] (DxvkContext* ctx) { + m_device->submitCommandList(cCommandList, + cSync.acquire, cSync.present); + + if (cHud != nullptr && !cFrameId) + cHud->update(); + + m_device->presentImage(m_presenter, &m_presentStatus); + }); + + pContext->FlushCsChunk(); + } + + + void D3D11SwapChain::SynchronizePresent() { + // Recreate swap chain if the previous present call failed + VkResult status = m_device->waitForSubmission(&m_presentStatus); + + if (status != VK_SUCCESS) + RecreateSwapChain(m_vsync); + } + + + void D3D11SwapChain::RecreateSwapChain(BOOL Vsync) { + // Ensure that we can safely destroy the swap chain + m_device->waitForSubmission(&m_presentStatus); + m_device->waitForIdle(); + + m_presentStatus.result = VK_SUCCESS; + + vk::PresenterDesc presenterDesc; + presenterDesc.imageExtent = { m_desc.Width, m_desc.Height }; + presenterDesc.imageCount = PickImageCount(m_desc.BufferCount + 1); + presenterDesc.numFormats = PickFormats(m_desc.Format, presenterDesc.formats); + presenterDesc.numPresentModes = PickPresentModes(Vsync, presenterDesc.presentModes); + presenterDesc.fullScreenExclusive = PickFullscreenMode(); + + if (m_presenter->recreateSwapChain(presenterDesc) != VK_SUCCESS) + throw DxvkError("D3D11SwapChain: Failed to recreate swap chain"); + + CreateRenderTargetViews(); + } + + + void D3D11SwapChain::CreateFrameLatencyEvent() { + m_frameLatencySignal = new sync::CallbackFence(m_frameId); + + if (m_desc.Flags & DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT) + m_frameLatencyEvent = CreateSemaphore(nullptr, m_frameLatency, DXGI_MAX_SWAP_CHAIN_BUFFERS, nullptr); + } + + + void D3D11SwapChain::CreatePresenter() { + DxvkDeviceQueue graphicsQueue = m_device->queues().graphics; + + vk::PresenterDevice presenterDevice; + presenterDevice.queueFamily = graphicsQueue.queueFamily; + presenterDevice.queue = graphicsQueue.queueHandle; + presenterDevice.adapter = m_device->adapter()->handle(); + presenterDevice.features.fullScreenExclusive = m_device->extensions().extFullScreenExclusive; + + vk::PresenterDesc presenterDesc; + presenterDesc.imageExtent = { m_desc.Width, m_desc.Height }; + presenterDesc.imageCount = PickImageCount(m_desc.BufferCount + 1); + presenterDesc.numFormats = PickFormats(m_desc.Format, presenterDesc.formats); + presenterDesc.numPresentModes = PickPresentModes(false, presenterDesc.presentModes); + presenterDesc.fullScreenExclusive = PickFullscreenMode(); + + m_presenter = new vk::Presenter(m_window, + m_device->adapter()->vki(), + m_device->vkd(), + presenterDevice, + presenterDesc); + + m_presenter->setFrameRateLimit(m_parent->GetOptions()->maxFrameRate); + m_presenter->setFrameRateLimiterRefreshRate(m_displayRefreshRate); + + CreateRenderTargetViews(); + } + + + void D3D11SwapChain::CreateRenderTargetViews() { + vk::PresenterInfo info = m_presenter->info(); + + m_imageViews.clear(); + m_imageViews.resize(info.imageCount); + + DxvkImageCreateInfo imageInfo; + imageInfo.type = VK_IMAGE_TYPE_2D; + imageInfo.format = info.format.format; + imageInfo.flags = 0; + imageInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT; + imageInfo.extent = { info.imageExtent.width, info.imageExtent.height, 1 }; + imageInfo.numLayers = 1; + imageInfo.mipLevels = 1; + imageInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + imageInfo.stages = 0; + imageInfo.access = 0; + imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; + imageInfo.layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + imageInfo.shared = VK_TRUE; + + DxvkImageViewCreateInfo viewInfo; + viewInfo.type = VK_IMAGE_VIEW_TYPE_2D; + viewInfo.format = info.format.format; + viewInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + viewInfo.aspect = VK_IMAGE_ASPECT_COLOR_BIT; + viewInfo.minLevel = 0; + viewInfo.numLevels = 1; + viewInfo.minLayer = 0; + viewInfo.numLayers = 1; + + for (uint32_t i = 0; i < info.imageCount; i++) { + VkImage imageHandle = m_presenter->getImage(i).image; + + Rc image = new DxvkImage( + m_device.ptr(), imageInfo, imageHandle); + + m_imageViews[i] = new DxvkImageView( + m_device->vkd(), image, viewInfo); + } + } + + + void D3D11SwapChain::CreateBackBuffer() { + // Explicitly destroy current swap image before + // creating a new one to free up resources + m_swapImage = nullptr; + m_swapImageView = nullptr; + m_backBuffer = nullptr; + + // Create new back buffer + D3D11_COMMON_TEXTURE_DESC desc; + desc.Width = std::max(m_desc.Width, 1u); + desc.Height = std::max(m_desc.Height, 1u); + desc.Depth = 1; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = m_desc.Format; + desc.SampleDesc = m_desc.SampleDesc; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = 0; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + desc.TextureLayout = D3D11_TEXTURE_LAYOUT_UNDEFINED; + + if (m_desc.BufferUsage & DXGI_USAGE_RENDER_TARGET_OUTPUT) + desc.BindFlags |= D3D11_BIND_RENDER_TARGET; + + if (m_desc.BufferUsage & DXGI_USAGE_SHADER_INPUT) + desc.BindFlags |= D3D11_BIND_SHADER_RESOURCE; + + if (m_desc.BufferUsage & DXGI_USAGE_UNORDERED_ACCESS) + desc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS; + + if (m_desc.Flags & DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE) + desc.MiscFlags |= D3D11_RESOURCE_MISC_GDI_COMPATIBLE; + + DXGI_USAGE dxgiUsage = DXGI_USAGE_BACK_BUFFER; + + if (m_desc.SwapEffect == DXGI_SWAP_EFFECT_DISCARD + || m_desc.SwapEffect == DXGI_SWAP_EFFECT_FLIP_DISCARD) + dxgiUsage |= DXGI_USAGE_DISCARD_ON_PRESENT; + + m_backBuffer = new D3D11Texture2D(m_parent, this, &desc, dxgiUsage); + m_swapImage = GetCommonTexture(m_backBuffer.ptr())->GetImage(); + + // Create an image view that allows the + // image to be bound as a shader resource. + DxvkImageViewCreateInfo viewInfo; + viewInfo.type = VK_IMAGE_VIEW_TYPE_2D; + viewInfo.format = m_swapImage->info().format; + viewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT; + viewInfo.aspect = VK_IMAGE_ASPECT_COLOR_BIT; + viewInfo.minLevel = 0; + viewInfo.numLevels = 1; + viewInfo.minLayer = 0; + viewInfo.numLayers = 1; + m_swapImageView = m_device->createImageView(m_swapImage, viewInfo); + + // Initialize the image so that we can use it. Clearing + // to black prevents garbled output for the first frame. + VkImageSubresourceRange subresources; + subresources.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + subresources.baseMipLevel = 0; + subresources.levelCount = 1; + subresources.baseArrayLayer = 0; + subresources.layerCount = 1; + + m_context->beginRecording( + m_device->createCommandList()); + + m_context->initImage(m_swapImage, + subresources, VK_IMAGE_LAYOUT_UNDEFINED); + + m_device->submitCommandList( + m_context->endRecording(), + VK_NULL_HANDLE, + VK_NULL_HANDLE); + } + + + void D3D11SwapChain::CreateBlitter() { + m_blitter = new DxvkSwapchainBlitter(m_device); + } + + + void D3D11SwapChain::CreateHud() { + m_hud = hud::Hud::createHud(m_device); + + if (m_hud != nullptr) + m_hud->addItem("api", 1, GetApiName()); + } + + + void D3D11SwapChain::DestroyFrameLatencyEvent() { + CloseHandle(m_frameLatencyEvent); + } + + + void D3D11SwapChain::SyncFrameLatency() { + // Wait for the sync event so that we respect the maximum frame latency + m_frameLatencySignal->wait(m_frameId - GetActualFrameLatency()); + + if (m_frameLatencyEvent) { + m_frameLatencySignal->setCallback(m_frameId, [cFrameLatencyEvent = m_frameLatencyEvent] () { + ReleaseSemaphore(cFrameLatencyEvent, 1, nullptr); + }); + } + } + + + uint32_t D3D11SwapChain::GetActualFrameLatency() { + uint32_t maxFrameLatency = m_frameLatency; + + if (!(m_desc.Flags & DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT)) + m_dxgiDevice->GetMaximumFrameLatency(&maxFrameLatency); + + if (m_frameLatencyCap) + maxFrameLatency = std::min(maxFrameLatency, m_frameLatencyCap); + + maxFrameLatency = std::min(maxFrameLatency, m_desc.BufferCount + 1); + return maxFrameLatency; + } + + + uint32_t D3D11SwapChain::PickFormats( + DXGI_FORMAT Format, + VkSurfaceFormatKHR* pDstFormats) { + uint32_t n = 0; + + switch (Format) { + default: + Logger::warn(str::format("D3D11SwapChain: Unexpected format: ", m_desc.Format)); + [[fallthrough]]; + + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_B8G8R8A8_UNORM: { + pDstFormats[n++] = { VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }; + pDstFormats[n++] = { VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }; + } break; + + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: { + pDstFormats[n++] = { VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }; + pDstFormats[n++] = { VK_FORMAT_B8G8R8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }; + } break; + + case DXGI_FORMAT_R10G10B10A2_UNORM: { + pDstFormats[n++] = { VK_FORMAT_A2B10G10R10_UNORM_PACK32, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }; + pDstFormats[n++] = { VK_FORMAT_A2R10G10B10_UNORM_PACK32, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }; + } break; + + case DXGI_FORMAT_R16G16B16A16_FLOAT: { + pDstFormats[n++] = { VK_FORMAT_R16G16B16A16_SFLOAT, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }; + } break; + } + + return n; + } + + + uint32_t D3D11SwapChain::PickPresentModes( + BOOL Vsync, + VkPresentModeKHR* pDstModes) { + uint32_t n = 0; + + if (Vsync) { + if (m_parent->GetOptions()->tearFree == Tristate::False) + pDstModes[n++] = VK_PRESENT_MODE_FIFO_RELAXED_KHR; + pDstModes[n++] = VK_PRESENT_MODE_FIFO_KHR; + } else { + if (m_parent->GetOptions()->tearFree != Tristate::True) + pDstModes[n++] = VK_PRESENT_MODE_IMMEDIATE_KHR; + pDstModes[n++] = VK_PRESENT_MODE_MAILBOX_KHR; + } + + return n; + } + + + uint32_t D3D11SwapChain::PickImageCount( + UINT Preferred) { + int32_t option = m_parent->GetOptions()->numBackBuffers; + return option > 0 ? uint32_t(option) : uint32_t(Preferred); + } + + + VkFullScreenExclusiveEXT D3D11SwapChain::PickFullscreenMode() { + return m_desc.Flags & DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH + ? VK_FULL_SCREEN_EXCLUSIVE_ALLOWED_EXT + : VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT; + } + + + std::string D3D11SwapChain::GetApiName() const { + Com device; + m_parent->QueryInterface(__uuidof(IDXGIDXVKDevice), reinterpret_cast(&device)); + + uint32_t apiVersion = device->GetAPIVersion(); + uint32_t featureLevel = m_parent->GetFeatureLevel(); + + uint32_t flHi = (featureLevel >> 12); + uint32_t flLo = (featureLevel >> 8) & 0x7; + + return str::format("D3D", apiVersion, " FL", flHi, "_", flLo); + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_swapchain.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_swapchain.h new file mode 100644 index 00000000000..f4debea1485 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_swapchain.h @@ -0,0 +1,164 @@ +#pragma once + +#include "d3d11_texture.h" + +#include "../dxvk/hud/dxvk_hud.h" + +#include "../dxvk/dxvk_swapchain_blitter.h" + +#include "../util/sync/sync_signal.h" + +namespace dxvk { + + class D3D11Device; + class D3D11DXGIDevice; + + class D3D11SwapChain : public ComObject { + constexpr static uint32_t DefaultFrameLatency = 1; + public: + + D3D11SwapChain( + D3D11DXGIDevice* pContainer, + D3D11Device* pDevice, + HWND hWnd, + const DXGI_SWAP_CHAIN_DESC1* pDesc); + + ~D3D11SwapChain(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + HRESULT STDMETHODCALLTYPE GetDesc( + DXGI_SWAP_CHAIN_DESC1* pDesc); + + HRESULT STDMETHODCALLTYPE GetAdapter( + REFIID riid, + void** ppvObject); + + HRESULT STDMETHODCALLTYPE GetDevice( + REFIID riid, + void** ppDevice); + + HRESULT STDMETHODCALLTYPE GetImage( + UINT BufferId, + REFIID riid, + void** ppBuffer); + + UINT STDMETHODCALLTYPE GetImageIndex(); + + UINT STDMETHODCALLTYPE GetFrameLatency(); + + HANDLE STDMETHODCALLTYPE GetFrameLatencyEvent(); + + HRESULT STDMETHODCALLTYPE ChangeProperties( + const DXGI_SWAP_CHAIN_DESC1* pDesc); + + HRESULT STDMETHODCALLTYPE SetPresentRegion( + const RECT* pRegion); + + HRESULT STDMETHODCALLTYPE SetGammaControl( + UINT NumControlPoints, + const DXGI_RGB* pControlPoints); + + HRESULT STDMETHODCALLTYPE SetFrameLatency( + UINT MaxLatency); + + HRESULT STDMETHODCALLTYPE Present( + UINT SyncInterval, + UINT PresentFlags, + const DXGI_PRESENT_PARAMETERS* pPresentParameters); + + void STDMETHODCALLTYPE NotifyModeChange( + BOOL Windowed, + const DXGI_MODE_DESC* pDisplayMode); + + private: + + enum BindingIds : uint32_t { + Image = 0, + Gamma = 1, + }; + + Com m_dxgiDevice; + + D3D11Device* m_parent; + HWND m_window; + + DXGI_SWAP_CHAIN_DESC1 m_desc; + + Rc m_device; + Rc m_context; + + Rc m_presenter; + + Rc m_swapImage; + Rc m_swapImageView; + Rc m_blitter; + + Rc m_hud; + + Com m_backBuffer; + DxvkSubmitStatus m_presentStatus; + + std::vector> m_imageViews; + + uint64_t m_frameId = DXGI_MAX_SWAP_CHAIN_BUFFERS; + uint32_t m_frameLatency = DefaultFrameLatency; + uint32_t m_frameLatencyCap = 0; + HANDLE m_frameLatencyEvent = nullptr; + Rc m_frameLatencySignal; + + bool m_dirty = true; + bool m_vsync = true; + + double m_displayRefreshRate = 0.0; + + HRESULT PresentImage(UINT SyncInterval); + + void SubmitPresent( + D3D11ImmediateContext* pContext, + const vk::PresenterSync& Sync, + uint32_t FrameId); + + void SynchronizePresent(); + + void RecreateSwapChain( + BOOL Vsync); + + void CreateFrameLatencyEvent(); + + void CreatePresenter(); + + void CreateRenderTargetViews(); + + void CreateBackBuffer(); + + void CreateBlitter(); + + void CreateHud(); + + void DestroyFrameLatencyEvent(); + + void SyncFrameLatency(); + + uint32_t GetActualFrameLatency(); + + uint32_t PickFormats( + DXGI_FORMAT Format, + VkSurfaceFormatKHR* pDstFormats); + + uint32_t PickPresentModes( + BOOL Vsync, + VkPresentModeKHR* pDstModes); + + uint32_t PickImageCount( + UINT Preferred); + + VkFullScreenExclusiveEXT PickFullscreenMode(); + + std::string GetApiName() const; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_texture.cpp b/utils/dxvk-1.10.3/src/d3d11/d3d11_texture.cpp new file mode 100644 index 00000000000..08b6351d690 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_texture.cpp @@ -0,0 +1,1379 @@ +#include "d3d11_device.h" +#include "d3d11_gdi.h" +#include "d3d11_texture.h" + +#include "../util/util_shared_res.h" + +namespace dxvk { + + D3D11CommonTexture::D3D11CommonTexture( + ID3D11Resource* pInterface, + D3D11Device* pDevice, + const D3D11_COMMON_TEXTURE_DESC* pDesc, + D3D11_RESOURCE_DIMENSION Dimension, + DXGI_USAGE DxgiUsage, + VkImage vkImage, + HANDLE hSharedHandle) + : m_interface(pInterface), m_device(pDevice), m_dimension(Dimension), m_desc(*pDesc), m_dxgiUsage(DxgiUsage) { + DXGI_VK_FORMAT_MODE formatMode = GetFormatMode(); + DXGI_VK_FORMAT_INFO formatInfo = m_device->LookupFormat(m_desc.Format, formatMode); + DXGI_VK_FORMAT_FAMILY formatFamily = m_device->LookupFamily(m_desc.Format, formatMode); + DXGI_VK_FORMAT_INFO formatPacked = m_device->LookupPackedFormat(m_desc.Format, formatMode); + m_packedFormat = formatPacked.Format; + + DxvkImageCreateInfo imageInfo; + imageInfo.type = GetVkImageType(); + imageInfo.format = formatInfo.Format; + imageInfo.flags = 0; + imageInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT; + imageInfo.extent.width = m_desc.Width; + imageInfo.extent.height = m_desc.Height; + imageInfo.extent.depth = m_desc.Depth; + imageInfo.numLayers = m_desc.ArraySize; + imageInfo.mipLevels = m_desc.MipLevels; + imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + imageInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT; + imageInfo.access = VK_ACCESS_TRANSFER_READ_BIT + | VK_ACCESS_TRANSFER_WRITE_BIT; + imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; + imageInfo.layout = VK_IMAGE_LAYOUT_GENERAL; + imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + imageInfo.shared = vkImage != VK_NULL_HANDLE; + + // Normalise hSharedhandle to INVALID_HANDLE_VALUE to allow passing in nullptr + if (hSharedHandle == nullptr) + hSharedHandle = INVALID_HANDLE_VALUE; + + if (m_desc.MiscFlags & (D3D11_RESOURCE_MISC_SHARED|D3D11_RESOURCE_MISC_SHARED_NTHANDLE)) { + if (m_desc.MiscFlags & D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX) + Logger::warn("D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX: not supported."); + + imageInfo.shared = true; + imageInfo.sharing.mode = hSharedHandle == INVALID_HANDLE_VALUE ? DxvkSharedHandleMode::Export : DxvkSharedHandleMode::Import; + imageInfo.sharing.type = m_desc.MiscFlags & D3D11_RESOURCE_MISC_SHARED_NTHANDLE + ? VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT + : VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT; + imageInfo.sharing.handle = hSharedHandle; + } + + if (!pDevice->GetOptions()->disableMsaa) + DecodeSampleCount(m_desc.SampleDesc.Count, &imageInfo.sampleCount); + + if ((m_desc.BindFlags & D3D11_BIND_UNORDERED_ACCESS) && IsR32UavCompatibleFormat(m_desc.Format)) { + formatFamily.Add(formatInfo.Format); + formatFamily.Add(VK_FORMAT_R32_SFLOAT); + formatFamily.Add(VK_FORMAT_R32_UINT); + formatFamily.Add(VK_FORMAT_R32_SINT); + } + + // The image must be marked as mutable if it can be reinterpreted + // by a view with a different format. Depth-stencil formats cannot + // be reinterpreted in Vulkan, so we'll ignore those. + auto formatProperties = imageFormatInfo(formatInfo.Format); + + bool isMutable = formatFamily.FormatCount > 1; + bool isMultiPlane = (formatProperties->aspectMask & VK_IMAGE_ASPECT_PLANE_0_BIT) != 0; + bool isColorFormat = (formatProperties->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) != 0; + + if (isMutable && (isColorFormat || isMultiPlane)) { + imageInfo.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; + imageInfo.viewFormatCount = formatFamily.FormatCount; + imageInfo.viewFormats = formatFamily.Formats; + } + + // Adjust image flags based on the corresponding D3D flags + if (m_desc.BindFlags & D3D11_BIND_SHADER_RESOURCE) { + imageInfo.usage |= VK_IMAGE_USAGE_SAMPLED_BIT; + imageInfo.stages |= pDevice->GetEnabledShaderStages(); + imageInfo.access |= VK_ACCESS_SHADER_READ_BIT; + } + + if (m_desc.BindFlags & D3D11_BIND_RENDER_TARGET) { + imageInfo.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + imageInfo.stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + imageInfo.access |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT + | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + } + + if (m_desc.BindFlags & D3D11_BIND_DEPTH_STENCIL) { + imageInfo.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + imageInfo.stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT + | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + imageInfo.access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT + | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + } + + if (m_desc.BindFlags & D3D11_BIND_UNORDERED_ACCESS) { + imageInfo.usage |= VK_IMAGE_USAGE_STORAGE_BIT; + imageInfo.stages |= pDevice->GetEnabledShaderStages(); + imageInfo.access |= VK_ACCESS_SHADER_READ_BIT + | VK_ACCESS_SHADER_WRITE_BIT; + + // UAVs are not supported for sRGB formats on most drivers, + // but we can still create linear views for the image + if (formatProperties->flags.test(DxvkFormatFlag::ColorSpaceSrgb)) + imageInfo.flags |= VK_IMAGE_CREATE_EXTENDED_USAGE_BIT; + } + + // Multi-plane formats need views to be created with color formats, and + // may not report all relevant usage flags as supported on their own. + // Also, enable sampled bit to enable use with video processor APIs. + if (isMultiPlane) { + imageInfo.usage |= VK_IMAGE_USAGE_SAMPLED_BIT; + imageInfo.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT + | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT; + } + + // Access pattern for meta-resolve operations + if (imageInfo.sampleCount != VK_SAMPLE_COUNT_1_BIT && isColorFormat) { + imageInfo.usage |= VK_IMAGE_USAGE_SAMPLED_BIT; + imageInfo.stages |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + imageInfo.access |= VK_ACCESS_SHADER_READ_BIT; + } + + if (m_desc.MiscFlags & D3D11_RESOURCE_MISC_TEXTURECUBE) + imageInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; + + if (Dimension == D3D11_RESOURCE_DIMENSION_TEXTURE3D && + (m_desc.BindFlags & D3D11_BIND_RENDER_TARGET)) + imageInfo.flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT; + + // Swap chain back buffers need to be shader readable + if (DxgiUsage & DXGI_USAGE_BACK_BUFFER) { + imageInfo.usage |= VK_IMAGE_USAGE_SAMPLED_BIT; + imageInfo.stages |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + imageInfo.access |= VK_ACCESS_SHADER_READ_BIT; + imageInfo.shared = VK_TRUE; + } + + // Some image formats (i.e. the R32G32B32 ones) are + // only supported with linear tiling on most GPUs + if (!CheckImageSupport(&imageInfo, VK_IMAGE_TILING_OPTIMAL)) + imageInfo.tiling = VK_IMAGE_TILING_LINEAR; + + // Determine map mode based on our findings + m_mapMode = DetermineMapMode(&imageInfo); + + // If the image is mapped directly to host memory, we need + // to enable linear tiling, and DXVK needs to be aware that + // the image can be accessed by the host. + if (m_mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT) { + imageInfo.tiling = VK_IMAGE_TILING_LINEAR; + imageInfo.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; + } + + // If necessary, create the mapped linear buffer + if (m_mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_NONE) { + for (uint32_t i = 0; i < m_desc.ArraySize; i++) { + for (uint32_t j = 0; j < m_desc.MipLevels; j++) { + if (m_mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT) + m_buffers.push_back(CreateMappedBuffer(j)); + + m_mapInfo.push_back({ D3D11_MAP(~0u), 0ull }); + } + } + } + + // Skip image creation if possible + if (m_mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_STAGING) + return; + + // We must keep LINEAR images in GENERAL layout, but we + // can choose a better layout for the image based on how + // it is going to be used by the game. + if (imageInfo.tiling == VK_IMAGE_TILING_OPTIMAL && !isMultiPlane && imageInfo.sharing.mode == DxvkSharedHandleMode::None) + imageInfo.layout = OptimizeLayout(imageInfo.usage); + + // For some formats, we need to enable sampled and/or + // render target capabilities if available, but these + // should in no way affect the default image layout + imageInfo.usage |= EnableMetaCopyUsage(imageInfo.format, imageInfo.tiling); + imageInfo.usage |= EnableMetaPackUsage(imageInfo.format, m_desc.CPUAccessFlags); + + // Check if we can actually create the image + if (!CheckImageSupport(&imageInfo, imageInfo.tiling)) { + throw DxvkError(str::format( + "D3D11: Cannot create texture:", + "\n Format: ", m_desc.Format, + "\n Extent: ", m_desc.Width, + "x", m_desc.Height, + "x", m_desc.Depth, + "\n Samples: ", m_desc.SampleDesc.Count, + "\n Layers: ", m_desc.ArraySize, + "\n Levels: ", m_desc.MipLevels, + "\n Usage: ", std::hex, m_desc.BindFlags, + "\n Flags: ", std::hex, m_desc.MiscFlags)); + } + + // Create the image on a host-visible memory type + // in case it is going to be mapped directly. + VkMemoryPropertyFlags memoryProperties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + + if (m_mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT) + memoryProperties = GetMemoryFlags(); + + if (vkImage == VK_NULL_HANDLE) + m_image = m_device->GetDXVKDevice()->createImage(imageInfo, memoryProperties); + else + m_image = m_device->GetDXVKDevice()->createImageFromVkImage(imageInfo, vkImage); + + if (imageInfo.sharing.mode == DxvkSharedHandleMode::Export) + ExportImageInfo(); + } + + + D3D11CommonTexture::~D3D11CommonTexture() { + + } + + + VkDeviceSize D3D11CommonTexture::ComputeMappedOffset(UINT Subresource, UINT Plane, VkOffset3D Offset) const { + auto packedFormatInfo = imageFormatInfo(m_packedFormat); + + VkImageAspectFlags aspectMask = packedFormatInfo->aspectMask; + VkDeviceSize elementSize = packedFormatInfo->elementSize; + + if (packedFormatInfo->flags.test(DxvkFormatFlag::MultiPlane)) { + auto plane = &packedFormatInfo->planes[Plane]; + elementSize = plane->elementSize; + Offset.x /= plane->blockSize.width; + Offset.y /= plane->blockSize.height; + aspectMask = vk::getPlaneAspect(Plane); + } + + auto layout = GetSubresourceLayout(aspectMask, Subresource); + auto blockOffset = util::computeBlockOffset(Offset, packedFormatInfo->blockSize); + + return VkDeviceSize(blockOffset.z) * layout.DepthPitch + + VkDeviceSize(blockOffset.y) * layout.RowPitch + + VkDeviceSize(blockOffset.x) * elementSize + + VkDeviceSize(layout.Offset); + } + + + VkImageSubresource D3D11CommonTexture::GetSubresourceFromIndex( + VkImageAspectFlags Aspect, + UINT Subresource) const { + VkImageSubresource result; + result.aspectMask = Aspect; + result.mipLevel = Subresource % m_desc.MipLevels; + result.arrayLayer = Subresource / m_desc.MipLevels; + return result; + } + + + D3D11_COMMON_TEXTURE_SUBRESOURCE_LAYOUT D3D11CommonTexture::GetSubresourceLayout( + VkImageAspectFlags AspectMask, + UINT Subresource) const { + VkImageSubresource subresource = GetSubresourceFromIndex(AspectMask, Subresource); + D3D11_COMMON_TEXTURE_SUBRESOURCE_LAYOUT layout = { }; + + switch (m_mapMode) { + case D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT: { + auto vkLayout = m_image->querySubresourceLayout(subresource); + layout.Offset = vkLayout.offset; + layout.Size = vkLayout.size; + layout.RowPitch = vkLayout.rowPitch; + layout.DepthPitch = vkLayout.depthPitch; + } break; + + case D3D11_COMMON_TEXTURE_MAP_MODE_NONE: + case D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER: + case D3D11_COMMON_TEXTURE_MAP_MODE_STAGING: { + auto packedFormatInfo = imageFormatInfo(m_packedFormat); + + VkImageAspectFlags aspects = packedFormatInfo->aspectMask; + VkExtent3D mipExtent = MipLevelExtent(subresource.mipLevel); + + while (aspects) { + auto aspect = vk::getNextAspect(aspects); + auto extent = mipExtent; + auto elementSize = packedFormatInfo->elementSize; + + if (packedFormatInfo->flags.test(DxvkFormatFlag::MultiPlane)) { + auto plane = &packedFormatInfo->planes[vk::getPlaneIndex(aspect)]; + extent.width /= plane->blockSize.width; + extent.height /= plane->blockSize.height; + elementSize = plane->elementSize; + } + + auto blockCount = util::computeBlockCount(extent, packedFormatInfo->blockSize); + + if (!layout.RowPitch) { + layout.RowPitch = elementSize * blockCount.width; + layout.DepthPitch = elementSize * blockCount.width * blockCount.height; + } + + VkDeviceSize size = elementSize * blockCount.width * blockCount.height * blockCount.depth; + + if (aspect & AspectMask) + layout.Size += size; + else if (!layout.Size) + layout.Offset += size; + } + } break; + } + + // D3D wants us to return the total subresource size in some instances + if (m_dimension < D3D11_RESOURCE_DIMENSION_TEXTURE2D) layout.RowPitch = layout.Size; + if (m_dimension < D3D11_RESOURCE_DIMENSION_TEXTURE3D) layout.DepthPitch = layout.Size; + return layout; + } + + + DXGI_VK_FORMAT_MODE D3D11CommonTexture::GetFormatMode() const { + if (m_desc.BindFlags & D3D11_BIND_RENDER_TARGET) + return DXGI_VK_FORMAT_MODE_COLOR; + + if (m_desc.BindFlags & D3D11_BIND_DEPTH_STENCIL) + return DXGI_VK_FORMAT_MODE_DEPTH; + + return DXGI_VK_FORMAT_MODE_ANY; + } + + + uint32_t D3D11CommonTexture::GetPlaneCount() const { + return vk::getPlaneCount(m_image->formatInfo()->aspectMask); + } + + + bool D3D11CommonTexture::CheckViewCompatibility(UINT BindFlags, DXGI_FORMAT Format, UINT Plane) const { + const DxvkImageCreateInfo& imageInfo = m_image->info(); + + // Check whether the given bind flags are supported + if ((m_desc.BindFlags & BindFlags) != BindFlags) + return false; + + // Check whether the view format is compatible + DXGI_VK_FORMAT_MODE formatMode = GetFormatMode(); + DXGI_VK_FORMAT_INFO viewFormat = m_device->LookupFormat(Format, formatMode); + DXGI_VK_FORMAT_INFO baseFormat = m_device->LookupFormat(m_desc.Format, formatMode); + + // Check whether the plane index is valid for the given format + uint32_t planeCount = GetPlaneCount(); + + if (Plane >= planeCount) + return false; + + if (imageInfo.flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) { + // Check whether the given combination of image + // view type and view format is actually supported + VkFormatFeatureFlags features = GetImageFormatFeatures(BindFlags); + + if (!CheckFormatFeatureSupport(viewFormat.Format, features)) + return false; + + // Using the image format itself is supported for non-planar formats + if (viewFormat.Format == baseFormat.Format && planeCount == 1) + return true; + + // If there is a list of compatible formats, the view format must be + // included in that list. For planar formats, the list is laid out in + // such a way that the n-th format is supported for the n-th plane. + for (size_t i = Plane; i < imageInfo.viewFormatCount; i += planeCount) { + if (imageInfo.viewFormats[i] == viewFormat.Format) { + return true; + } + } + + // Otherwise, all bit-compatible formats can be used. + if (imageInfo.viewFormatCount == 0 && planeCount == 1) { + auto baseFormatInfo = imageFormatInfo(baseFormat.Format); + auto viewFormatInfo = imageFormatInfo(viewFormat.Format); + + return baseFormatInfo->aspectMask == viewFormatInfo->aspectMask + && baseFormatInfo->elementSize == viewFormatInfo->elementSize; + } + + return false; + } else { + // For non-mutable images, the view format + // must be identical to the image format. + return viewFormat.Format == baseFormat.Format && planeCount == 1; + } + } + + + HRESULT D3D11CommonTexture::NormalizeTextureProperties(D3D11_COMMON_TEXTURE_DESC* pDesc) { + if (pDesc->Width == 0 || pDesc->Height == 0 || pDesc->Depth == 0 || pDesc->ArraySize == 0) + return E_INVALIDARG; + + if (FAILED(DecodeSampleCount(pDesc->SampleDesc.Count, nullptr))) + return E_INVALIDARG; + + if ((pDesc->MiscFlags & D3D11_RESOURCE_MISC_GDI_COMPATIBLE) + && (pDesc->Usage == D3D11_USAGE_STAGING + || (pDesc->Format != DXGI_FORMAT_B8G8R8A8_TYPELESS + && pDesc->Format != DXGI_FORMAT_B8G8R8A8_UNORM + && pDesc->Format != DXGI_FORMAT_B8G8R8A8_UNORM_SRGB))) + return E_INVALIDARG; + + if ((pDesc->MiscFlags & D3D11_RESOURCE_MISC_GENERATE_MIPS) + && (pDesc->BindFlags & (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET)) + != (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET)) + return E_INVALIDARG; + + // TILE_POOL is invalid, but we don't support TILED either + if (pDesc->MiscFlags & (D3D11_RESOURCE_MISC_TILE_POOL | D3D11_RESOURCE_MISC_TILED)) + return E_INVALIDARG; + + // Use the maximum possible mip level count if the supplied + // mip level count is either unspecified (0) or invalid + const uint32_t maxMipLevelCount = (pDesc->SampleDesc.Count <= 1) + ? util::computeMipLevelCount({ pDesc->Width, pDesc->Height, pDesc->Depth }) + : 1u; + + if (pDesc->MipLevels == 0 || pDesc->MipLevels > maxMipLevelCount) + pDesc->MipLevels = maxMipLevelCount; + + // Row-major is only supported for textures with one single + // subresource and one sample and cannot have bind flags. + if (pDesc->TextureLayout == D3D11_TEXTURE_LAYOUT_ROW_MAJOR + && (pDesc->MipLevels != 1 || pDesc->SampleDesc.Count != 1 || pDesc->BindFlags)) + return E_INVALIDARG; + + // Standard swizzle is unsupported + if (pDesc->TextureLayout == D3D11_TEXTURE_LAYOUT_64K_STANDARD_SWIZZLE) + return E_INVALIDARG; + + return S_OK; + } + + + BOOL D3D11CommonTexture::CheckImageSupport( + const DxvkImageCreateInfo* pImageInfo, + VkImageTiling Tiling) const { + const Rc adapter = m_device->GetDXVKDevice()->adapter(); + + VkImageUsageFlags usage = pImageInfo->usage; + + if (pImageInfo->flags & VK_IMAGE_CREATE_EXTENDED_USAGE_BIT) + usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; + + VkImageFormatProperties formatProps = { }; + VkResult status = adapter->imageFormatProperties( + pImageInfo->format, pImageInfo->type, Tiling, + usage, pImageInfo->flags, formatProps); + + if (status != VK_SUCCESS) + return FALSE; + + return (pImageInfo->extent.width <= formatProps.maxExtent.width) + && (pImageInfo->extent.height <= formatProps.maxExtent.height) + && (pImageInfo->extent.depth <= formatProps.maxExtent.depth) + && (pImageInfo->numLayers <= formatProps.maxArrayLayers) + && (pImageInfo->mipLevels <= formatProps.maxMipLevels) + && (pImageInfo->sampleCount & formatProps.sampleCounts); + } + + + BOOL D3D11CommonTexture::CheckFormatFeatureSupport( + VkFormat Format, + VkFormatFeatureFlags Features) const { + VkFormatProperties properties = m_device->GetDXVKDevice()->adapter()->formatProperties(Format); + + return (properties.linearTilingFeatures & Features) == Features + || (properties.optimalTilingFeatures & Features) == Features; + } + + + VkImageUsageFlags D3D11CommonTexture::EnableMetaCopyUsage( + VkFormat Format, + VkImageTiling Tiling) const { + VkFormatFeatureFlags requestedFeatures = 0; + + if (Format == VK_FORMAT_D16_UNORM || Format == VK_FORMAT_D32_SFLOAT) { + requestedFeatures |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT + | VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT; + } + + if (Format == VK_FORMAT_R16_UNORM || Format == VK_FORMAT_R32_SFLOAT) { + requestedFeatures |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT + | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT; + } + + if (Format == VK_FORMAT_D32_SFLOAT_S8_UINT || Format == VK_FORMAT_D24_UNORM_S8_UINT) + requestedFeatures |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT; + + if (requestedFeatures == 0) + return 0; + + // Enable usage flags for all supported and requested features + VkFormatProperties properties = m_device->GetDXVKDevice()->adapter()->formatProperties(Format); + + requestedFeatures &= Tiling == VK_IMAGE_TILING_OPTIMAL + ? properties.optimalTilingFeatures + : properties.linearTilingFeatures; + + VkImageUsageFlags requestedUsage = 0; + + if (requestedFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) + requestedUsage |= VK_IMAGE_USAGE_SAMPLED_BIT; + + if (requestedFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) + requestedUsage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + + if (requestedFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) + requestedUsage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + + return requestedUsage; + } + + + VkImageUsageFlags D3D11CommonTexture::EnableMetaPackUsage( + VkFormat Format, + UINT CpuAccess) const { + if ((CpuAccess & D3D11_CPU_ACCESS_READ) == 0) + return 0; + + const auto dsMask = VK_IMAGE_ASPECT_DEPTH_BIT + | VK_IMAGE_ASPECT_STENCIL_BIT; + + auto formatInfo = imageFormatInfo(Format); + + return formatInfo->aspectMask == dsMask + ? VK_IMAGE_USAGE_SAMPLED_BIT + : 0; + } + + + VkMemoryPropertyFlags D3D11CommonTexture::GetMemoryFlags() const { + VkMemoryPropertyFlags memoryFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT + | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + + bool useCached = (m_device->GetOptions()->cachedDynamicResources == ~0u) + || (m_device->GetOptions()->cachedDynamicResources & m_desc.BindFlags); + + if (m_desc.Usage == D3D11_USAGE_STAGING || useCached) + memoryFlags |= VK_MEMORY_PROPERTY_HOST_CACHED_BIT; + else if (m_desc.Usage == D3D11_USAGE_DEFAULT || m_desc.BindFlags) + memoryFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + + return memoryFlags; + } + + + D3D11_COMMON_TEXTURE_MAP_MODE D3D11CommonTexture::DetermineMapMode( + const DxvkImageCreateInfo* pImageInfo) const { + // Don't map an image unless the application requests it + if (!m_desc.CPUAccessFlags) + return D3D11_COMMON_TEXTURE_MAP_MODE_NONE; + + // If the resource cannot be used in the actual rendering pipeline, we + // do not need to create an actual image and can instead implement copy + // functions as buffer-to-image and image-to-buffer copies. + if (!m_desc.BindFlags && m_desc.Usage != D3D11_USAGE_DEFAULT) + return D3D11_COMMON_TEXTURE_MAP_MODE_STAGING; + + // Depth-stencil formats in D3D11 can be mapped and follow special + // packing rules, so we need to copy that data into a buffer first + if (GetPackedDepthStencilFormat(m_desc.Format)) + return D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER; + + // Multi-plane images have a special memory layout in D3D11 + if (imageFormatInfo(pImageInfo->format)->flags.test(DxvkFormatFlag::MultiPlane)) + return D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER; + + // If we can't use linear tiling for this image, we have to use a buffer + if (!this->CheckImageSupport(pImageInfo, VK_IMAGE_TILING_LINEAR)) + return D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER; + + // If supported and requested, create a linear image. Default images + // can be used for resolves and other operations regardless of bind + // flags, so we need to use a proper image for those. + if (m_desc.TextureLayout == D3D11_TEXTURE_LAYOUT_ROW_MAJOR + || m_desc.Usage == D3D11_USAGE_DEFAULT) + return D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT; + + // The overhead of frequently uploading large dynamic images may outweigh + // the benefit of linear tiling, so use a linear image in those cases. + VkDeviceSize threshold = m_device->GetOptions()->maxDynamicImageBufferSize; + VkDeviceSize size = util::computeImageDataSize(pImageInfo->format, pImageInfo->extent); + + if (size > threshold) + return D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT; + + // Dynamic images that can be sampled by a shader should generally go + // through a buffer to allow optimal tiling and to avoid running into + // bugs where games ignore the pitch when mapping the image. + return D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER; + } + + + void D3D11CommonTexture::ExportImageInfo() { + HANDLE hSharedHandle; + + if (m_desc.MiscFlags & D3D11_RESOURCE_MISC_SHARED) + hSharedHandle = openKmtHandle( m_image->sharedHandle() ); + else + hSharedHandle = m_image->sharedHandle(); + + DxvkSharedTextureMetadata metadata; + + metadata.Width = m_desc.Width; + metadata.Height = m_desc.Height; + metadata.MipLevels = m_desc.MipLevels; + metadata.ArraySize = m_desc.ArraySize; + metadata.Format = m_desc.Format; + metadata.SampleDesc = m_desc.SampleDesc; + metadata.Usage = m_desc.Usage; + metadata.BindFlags = m_desc.BindFlags; + metadata.CPUAccessFlags = m_desc.CPUAccessFlags; + metadata.MiscFlags = m_desc.MiscFlags; + metadata.TextureLayout = m_desc.TextureLayout; + + if (hSharedHandle == INVALID_HANDLE_VALUE || !setSharedMetadata(hSharedHandle, &metadata, sizeof(metadata))) { + Logger::warn("D3D11: Failed to write shared resource info for a texture"); + } + + if (hSharedHandle != INVALID_HANDLE_VALUE) + CloseHandle(hSharedHandle); + } + + + BOOL D3D11CommonTexture::IsR32UavCompatibleFormat( + DXGI_FORMAT Format) { + return Format == DXGI_FORMAT_R8G8B8A8_TYPELESS + || Format == DXGI_FORMAT_B8G8R8A8_TYPELESS + || Format == DXGI_FORMAT_B8G8R8X8_TYPELESS + || Format == DXGI_FORMAT_R10G10B10A2_TYPELESS + || Format == DXGI_FORMAT_R16G16_TYPELESS + || Format == DXGI_FORMAT_R32_TYPELESS; + } + + + D3D11CommonTexture::MappedBuffer D3D11CommonTexture::CreateMappedBuffer(UINT MipLevel) const { + const DxvkFormatInfo* formatInfo = imageFormatInfo( + m_device->LookupPackedFormat(m_desc.Format, GetFormatMode()).Format); + + DxvkBufferCreateInfo info; + info.size = GetSubresourceLayout(formatInfo->aspectMask, MipLevel).Size; + info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT + | VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT + | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT + | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT; + info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT + | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; + info.access = VK_ACCESS_TRANSFER_READ_BIT + | VK_ACCESS_TRANSFER_WRITE_BIT + | VK_ACCESS_SHADER_READ_BIT + | VK_ACCESS_SHADER_WRITE_BIT; + + VkMemoryPropertyFlags memType = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT + | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + + bool useCached = m_device->GetOptions()->cachedDynamicResources == ~0u; + + if (m_desc.Usage == D3D11_USAGE_STAGING || useCached) + memType |= VK_MEMORY_PROPERTY_HOST_CACHED_BIT; + + MappedBuffer result; + result.buffer = m_device->GetDXVKDevice()->createBuffer(info, memType); + result.slice = result.buffer->getSliceHandle(); + return result; + } + + + VkImageType D3D11CommonTexture::GetImageTypeFromResourceDim(D3D11_RESOURCE_DIMENSION Dimension) { + switch (Dimension) { + case D3D11_RESOURCE_DIMENSION_TEXTURE1D: return VK_IMAGE_TYPE_1D; + case D3D11_RESOURCE_DIMENSION_TEXTURE2D: return VK_IMAGE_TYPE_2D; + case D3D11_RESOURCE_DIMENSION_TEXTURE3D: return VK_IMAGE_TYPE_3D; + default: throw DxvkError("D3D11CommonTexture: Unhandled resource dimension"); + } + } + + + VkImageLayout D3D11CommonTexture::OptimizeLayout(VkImageUsageFlags Usage) { + const VkImageUsageFlags usageFlags = Usage; + + // Filter out unnecessary flags. Transfer operations + // are handled by the backend in a transparent manner. + Usage &= ~(VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_TRANSFER_SRC_BIT); + + // If the image is used only as an attachment, we never + // have to transform the image back to a different layout + if (Usage == VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) + return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + if (Usage == VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) + return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + Usage &= ~(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT + | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); + + // If the image is used for reading but not as a storage + // image, we can optimize the image for texture access + if (Usage == VK_IMAGE_USAGE_SAMPLED_BIT) { + return usageFlags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT + ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL + : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + } + + // Otherwise, we have to stick with the default layout + return VK_IMAGE_LAYOUT_GENERAL; + } + + + + + D3D11DXGISurface::D3D11DXGISurface( + ID3D11Resource* pResource, + D3D11CommonTexture* pTexture) + : m_resource (pResource), + m_texture (pTexture), + m_gdiSurface(nullptr) { + if (pTexture->Desc()->MiscFlags & D3D11_RESOURCE_MISC_GDI_COMPATIBLE) + m_gdiSurface = new D3D11GDISurface(m_resource, 0); + } + + + D3D11DXGISurface::~D3D11DXGISurface() { + if (m_gdiSurface) + delete m_gdiSurface; + } + + + ULONG STDMETHODCALLTYPE D3D11DXGISurface::AddRef() { + return m_resource->AddRef(); + } + + + ULONG STDMETHODCALLTYPE D3D11DXGISurface::Release() { + return m_resource->Release(); + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGISurface::QueryInterface( + REFIID riid, + void** ppvObject) { + return m_resource->QueryInterface(riid, ppvObject); + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGISurface::GetPrivateData( + REFGUID Name, + UINT* pDataSize, + void* pData) { + return m_resource->GetPrivateData(Name, pDataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGISurface::SetPrivateData( + REFGUID Name, + UINT DataSize, + const void* pData) { + return m_resource->SetPrivateData(Name, DataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGISurface::SetPrivateDataInterface( + REFGUID Name, + const IUnknown* pUnknown) { + return m_resource->SetPrivateDataInterface(Name, pUnknown); + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGISurface::GetParent( + REFIID riid, + void** ppParent) { + return GetDevice(riid, ppParent); + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGISurface::GetDevice( + REFIID riid, + void** ppDevice) { + Com device; + m_resource->GetDevice(&device); + return device->QueryInterface(riid, ppDevice); + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGISurface::GetDesc( + DXGI_SURFACE_DESC* pDesc) { + if (!pDesc) + return DXGI_ERROR_INVALID_CALL; + + auto desc = m_texture->Desc(); + pDesc->Width = desc->Width; + pDesc->Height = desc->Height; + pDesc->Format = desc->Format; + pDesc->SampleDesc = desc->SampleDesc; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGISurface::Map( + DXGI_MAPPED_RECT* pLockedRect, + UINT MapFlags) { + Com device; + Com context; + + m_resource->GetDevice(&device); + device->GetImmediateContext(&context); + + if (pLockedRect) { + pLockedRect->Pitch = 0; + pLockedRect->pBits = nullptr; + } + + D3D11_MAP mapType; + + if (MapFlags & (DXGI_MAP_READ | DXGI_MAP_WRITE)) + mapType = D3D11_MAP_READ_WRITE; + else if (MapFlags & DXGI_MAP_READ) + mapType = D3D11_MAP_READ; + else if (MapFlags & (DXGI_MAP_WRITE | DXGI_MAP_DISCARD)) + mapType = D3D11_MAP_WRITE_DISCARD; + else if (MapFlags & DXGI_MAP_WRITE) + mapType = D3D11_MAP_WRITE; + else + return DXGI_ERROR_INVALID_CALL; + + D3D11_MAPPED_SUBRESOURCE sr; + HRESULT hr = context->Map(m_resource, 0, + mapType, 0, pLockedRect ? &sr : nullptr); + + if (hr != S_OK) + return hr; + + pLockedRect->Pitch = sr.RowPitch; + pLockedRect->pBits = reinterpret_cast(sr.pData); + return hr; + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGISurface::Unmap() { + Com device; + Com context; + + m_resource->GetDevice(&device); + device->GetImmediateContext(&context); + + context->Unmap(m_resource, 0); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGISurface::GetDC( + BOOL Discard, + HDC* phdc) { + if (!m_gdiSurface) + return DXGI_ERROR_INVALID_CALL; + + return m_gdiSurface->Acquire(Discard, phdc); + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGISurface::ReleaseDC( + RECT* pDirtyRect) { + if (!m_gdiSurface) + return DXGI_ERROR_INVALID_CALL; + + return m_gdiSurface->Release(pDirtyRect); + } + + + HRESULT STDMETHODCALLTYPE D3D11DXGISurface::GetResource( + REFIID riid, + void** ppParentResource, + UINT* pSubresourceIndex) { + HRESULT hr = m_resource->QueryInterface(riid, ppParentResource); + if (pSubresourceIndex) + *pSubresourceIndex = 0; + return hr; + } + + + bool D3D11DXGISurface::isSurfaceCompatible() const { + auto desc = m_texture->Desc(); + + return desc->ArraySize == 1 + && desc->MipLevels == 1; + } + + + + + D3D11VkInteropSurface::D3D11VkInteropSurface( + ID3D11Resource* pResource, + D3D11CommonTexture* pTexture) + : m_resource(pResource), + m_texture (pTexture) { + + } + + + D3D11VkInteropSurface::~D3D11VkInteropSurface() { + + } + + + ULONG STDMETHODCALLTYPE D3D11VkInteropSurface::AddRef() { + return m_resource->AddRef(); + } + + + ULONG STDMETHODCALLTYPE D3D11VkInteropSurface::Release() { + return m_resource->Release(); + } + + + HRESULT STDMETHODCALLTYPE D3D11VkInteropSurface::QueryInterface( + REFIID riid, + void** ppvObject) { + return m_resource->QueryInterface(riid, ppvObject); + } + + + HRESULT STDMETHODCALLTYPE D3D11VkInteropSurface::GetDevice( + IDXGIVkInteropDevice** ppDevice) { + Com device; + m_resource->GetDevice(&device); + + return device->QueryInterface( + __uuidof(IDXGIVkInteropDevice), + reinterpret_cast(ppDevice)); + } + + + HRESULT STDMETHODCALLTYPE D3D11VkInteropSurface::GetVulkanImageInfo( + VkImage* pHandle, + VkImageLayout* pLayout, + VkImageCreateInfo* pInfo) { + const Rc image = m_texture->GetImage(); + const DxvkImageCreateInfo& info = image->info(); + + if (pHandle != nullptr) + *pHandle = image->handle(); + + if (pLayout != nullptr) + *pLayout = info.layout; + + if (pInfo != nullptr) { + // We currently don't support any extended structures + if (pInfo->sType != VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO + || pInfo->pNext != nullptr) + return E_INVALIDARG; + + pInfo->flags = 0; + pInfo->imageType = info.type; + pInfo->format = info.format; + pInfo->extent = info.extent; + pInfo->mipLevels = info.mipLevels; + pInfo->arrayLayers = info.numLayers; + pInfo->samples = info.sampleCount; + pInfo->tiling = info.tiling; + pInfo->usage = info.usage; + pInfo->sharingMode = VK_SHARING_MODE_EXCLUSIVE; + pInfo->queueFamilyIndexCount = 0; + pInfo->initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + } + + return S_OK; + } + + + /////////////////////////////////////////// + // D 3 D 1 1 T E X T U R E 1 D + D3D11Texture1D::D3D11Texture1D( + D3D11Device* pDevice, + const D3D11_COMMON_TEXTURE_DESC* pDesc) + : D3D11DeviceChild(pDevice), + m_texture (this, pDevice, pDesc, D3D11_RESOURCE_DIMENSION_TEXTURE1D, 0, VK_NULL_HANDLE, nullptr), + m_interop (this, &m_texture), + m_surface (this, &m_texture), + m_resource(this), + m_d3d10 (this) { + + } + + + D3D11Texture1D::~D3D11Texture1D() { + + } + + + HRESULT STDMETHODCALLTYPE D3D11Texture1D::QueryInterface(REFIID riid, void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(ID3D11DeviceChild) + || riid == __uuidof(ID3D11Resource) + || riid == __uuidof(ID3D11Texture1D)) { + *ppvObject = ref(this); + return S_OK; + } + + if (riid == __uuidof(ID3D10DeviceChild) + || riid == __uuidof(ID3D10Resource) + || riid == __uuidof(ID3D10Texture1D)) { + *ppvObject = ref(&m_d3d10); + return S_OK; + } + + if (m_surface.isSurfaceCompatible() + && (riid == __uuidof(IDXGISurface) + || riid == __uuidof(IDXGISurface1) + || riid == __uuidof(IDXGISurface2))) { + *ppvObject = ref(&m_surface); + return S_OK; + } + + if (riid == __uuidof(IDXGIObject) + || riid == __uuidof(IDXGIDeviceSubObject) + || riid == __uuidof(IDXGIResource) + || riid == __uuidof(IDXGIResource1)) { + *ppvObject = ref(&m_resource); + return S_OK; + } + + if (riid == __uuidof(IDXGIVkInteropSurface)) { + *ppvObject = ref(&m_interop); + return S_OK; + } + + Logger::warn("D3D11Texture1D::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + void STDMETHODCALLTYPE D3D11Texture1D::GetType(D3D11_RESOURCE_DIMENSION *pResourceDimension) { + *pResourceDimension = D3D11_RESOURCE_DIMENSION_TEXTURE1D; + } + + + UINT STDMETHODCALLTYPE D3D11Texture1D::GetEvictionPriority() { + return DXGI_RESOURCE_PRIORITY_NORMAL; + } + + + void STDMETHODCALLTYPE D3D11Texture1D::SetEvictionPriority(UINT EvictionPriority) { + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::warn("D3D11Texture1D::SetEvictionPriority: Stub"); + } + + + void STDMETHODCALLTYPE D3D11Texture1D::GetDesc(D3D11_TEXTURE1D_DESC *pDesc) { + pDesc->Width = m_texture.Desc()->Width; + pDesc->MipLevels = m_texture.Desc()->MipLevels; + pDesc->ArraySize = m_texture.Desc()->ArraySize; + pDesc->Format = m_texture.Desc()->Format; + pDesc->Usage = m_texture.Desc()->Usage; + pDesc->BindFlags = m_texture.Desc()->BindFlags; + pDesc->CPUAccessFlags = m_texture.Desc()->CPUAccessFlags; + pDesc->MiscFlags = m_texture.Desc()->MiscFlags; + } + + + /////////////////////////////////////////// + // D 3 D 1 1 T E X T U R E 2 D + D3D11Texture2D::D3D11Texture2D( + D3D11Device* pDevice, + const D3D11_COMMON_TEXTURE_DESC* pDesc, + HANDLE hSharedHandle) + : D3D11DeviceChild(pDevice), + m_texture (this, pDevice, pDesc, D3D11_RESOURCE_DIMENSION_TEXTURE2D, 0, VK_NULL_HANDLE, hSharedHandle), + m_interop (this, &m_texture), + m_surface (this, &m_texture), + m_resource (this), + m_d3d10 (this), + m_swapChain (nullptr) { + } + + + D3D11Texture2D::D3D11Texture2D( + D3D11Device* pDevice, + const D3D11_COMMON_TEXTURE_DESC* pDesc, + DXGI_USAGE DxgiUsage, + VkImage vkImage) + : D3D11DeviceChild(pDevice), + m_texture (this, pDevice, pDesc, D3D11_RESOURCE_DIMENSION_TEXTURE2D, DxgiUsage, vkImage, nullptr), + m_interop (this, &m_texture), + m_surface (this, &m_texture), + m_resource (this), + m_d3d10 (this), + m_swapChain (nullptr) { + + } + + + D3D11Texture2D::D3D11Texture2D( + D3D11Device* pDevice, + IUnknown* pSwapChain, + const D3D11_COMMON_TEXTURE_DESC* pDesc, + DXGI_USAGE DxgiUsage) + : D3D11DeviceChild(pDevice), + m_texture (this, pDevice, pDesc, D3D11_RESOURCE_DIMENSION_TEXTURE2D, DxgiUsage, VK_NULL_HANDLE, nullptr), + m_interop (this, &m_texture), + m_surface (this, &m_texture), + m_resource (this), + m_d3d10 (this), + m_swapChain (pSwapChain) { + + } + + + D3D11Texture2D::~D3D11Texture2D() { + + } + + + ULONG STDMETHODCALLTYPE D3D11Texture2D::AddRef() { + uint32_t refCount = m_refCount++; + + if (unlikely(!refCount)) { + if (m_swapChain) + m_swapChain->AddRef(); + + AddRefPrivate(); + } + + return refCount + 1; + } + + + ULONG STDMETHODCALLTYPE D3D11Texture2D::Release() { + uint32_t refCount = --m_refCount; + + if (unlikely(!refCount)) { + if (m_swapChain) + m_swapChain->Release(); + + ReleasePrivate(); + } + + return refCount; + } + + + HRESULT STDMETHODCALLTYPE D3D11Texture2D::QueryInterface(REFIID riid, void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(ID3D11DeviceChild) + || riid == __uuidof(ID3D11Resource) + || riid == __uuidof(ID3D11Texture2D) + || riid == __uuidof(ID3D11Texture2D1)) { + *ppvObject = ref(this); + return S_OK; + } + + if (riid == __uuidof(ID3D10DeviceChild) + || riid == __uuidof(ID3D10Resource) + || riid == __uuidof(ID3D10Texture2D)) { + *ppvObject = ref(&m_d3d10); + return S_OK; + } + + if (m_surface.isSurfaceCompatible() + && (riid == __uuidof(IDXGISurface) + || riid == __uuidof(IDXGISurface1) + || riid == __uuidof(IDXGISurface2))) { + *ppvObject = ref(&m_surface); + return S_OK; + } + + if (riid == __uuidof(IDXGIObject) + || riid == __uuidof(IDXGIDeviceSubObject) + || riid == __uuidof(IDXGIResource) + || riid == __uuidof(IDXGIResource1)) { + *ppvObject = ref(&m_resource); + return S_OK; + } + + if (riid == __uuidof(IDXGIVkInteropSurface)) { + *ppvObject = ref(&m_interop); + return S_OK; + } + + Logger::warn("D3D11Texture2D::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + void STDMETHODCALLTYPE D3D11Texture2D::GetType(D3D11_RESOURCE_DIMENSION *pResourceDimension) { + *pResourceDimension = D3D11_RESOURCE_DIMENSION_TEXTURE2D; + } + + + UINT STDMETHODCALLTYPE D3D11Texture2D::GetEvictionPriority() { + return DXGI_RESOURCE_PRIORITY_NORMAL; + } + + + void STDMETHODCALLTYPE D3D11Texture2D::SetEvictionPriority(UINT EvictionPriority) { + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::warn("D3D11Texture2D::SetEvictionPriority: Stub"); + } + + + void STDMETHODCALLTYPE D3D11Texture2D::GetDesc(D3D11_TEXTURE2D_DESC* pDesc) { + pDesc->Width = m_texture.Desc()->Width; + pDesc->Height = m_texture.Desc()->Height; + pDesc->MipLevels = m_texture.Desc()->MipLevels; + pDesc->ArraySize = m_texture.Desc()->ArraySize; + pDesc->Format = m_texture.Desc()->Format; + pDesc->SampleDesc = m_texture.Desc()->SampleDesc; + pDesc->Usage = m_texture.Desc()->Usage; + pDesc->BindFlags = m_texture.Desc()->BindFlags; + pDesc->CPUAccessFlags = m_texture.Desc()->CPUAccessFlags; + pDesc->MiscFlags = m_texture.Desc()->MiscFlags; + } + + + void STDMETHODCALLTYPE D3D11Texture2D::GetDesc1(D3D11_TEXTURE2D_DESC1* pDesc) { + pDesc->Width = m_texture.Desc()->Width; + pDesc->Height = m_texture.Desc()->Height; + pDesc->MipLevels = m_texture.Desc()->MipLevels; + pDesc->ArraySize = m_texture.Desc()->ArraySize; + pDesc->Format = m_texture.Desc()->Format; + pDesc->SampleDesc = m_texture.Desc()->SampleDesc; + pDesc->Usage = m_texture.Desc()->Usage; + pDesc->BindFlags = m_texture.Desc()->BindFlags; + pDesc->CPUAccessFlags = m_texture.Desc()->CPUAccessFlags; + pDesc->MiscFlags = m_texture.Desc()->MiscFlags; + pDesc->TextureLayout = m_texture.Desc()->TextureLayout; + } + + + /////////////////////////////////////////// + // D 3 D 1 1 T E X T U R E 3 D + D3D11Texture3D::D3D11Texture3D( + D3D11Device* pDevice, + const D3D11_COMMON_TEXTURE_DESC* pDesc) + : D3D11DeviceChild(pDevice), + m_texture (this, pDevice, pDesc, D3D11_RESOURCE_DIMENSION_TEXTURE3D, 0, VK_NULL_HANDLE, nullptr), + m_interop (this, &m_texture), + m_resource(this), + m_d3d10 (this) { + + } + + + D3D11Texture3D::~D3D11Texture3D() { + + } + + + HRESULT STDMETHODCALLTYPE D3D11Texture3D::QueryInterface(REFIID riid, void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(ID3D11DeviceChild) + || riid == __uuidof(ID3D11Resource) + || riid == __uuidof(ID3D11Texture3D) + || riid == __uuidof(ID3D11Texture3D1)) { + *ppvObject = ref(this); + return S_OK; + } + + if (riid == __uuidof(ID3D10DeviceChild) + || riid == __uuidof(ID3D10Resource) + || riid == __uuidof(ID3D10Texture3D)) { + *ppvObject = ref(&m_d3d10); + return S_OK; + } + + if (riid == __uuidof(IDXGIObject) + || riid == __uuidof(IDXGIDeviceSubObject) + || riid == __uuidof(IDXGIResource) + || riid == __uuidof(IDXGIResource1)) { + *ppvObject = ref(&m_resource); + return S_OK; + } + + if (riid == __uuidof(IDXGIVkInteropSurface)) { + *ppvObject = ref(&m_interop); + return S_OK; + } + + Logger::warn("D3D11Texture3D::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + void STDMETHODCALLTYPE D3D11Texture3D::GetType(D3D11_RESOURCE_DIMENSION *pResourceDimension) { + *pResourceDimension = D3D11_RESOURCE_DIMENSION_TEXTURE3D; + } + + + UINT STDMETHODCALLTYPE D3D11Texture3D::GetEvictionPriority() { + return DXGI_RESOURCE_PRIORITY_NORMAL; + } + + + void STDMETHODCALLTYPE D3D11Texture3D::SetEvictionPriority(UINT EvictionPriority) { + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::warn("D3D11Texture3D::SetEvictionPriority: Stub"); + } + + + void STDMETHODCALLTYPE D3D11Texture3D::GetDesc(D3D11_TEXTURE3D_DESC* pDesc) { + pDesc->Width = m_texture.Desc()->Width; + pDesc->Height = m_texture.Desc()->Height; + pDesc->Depth = m_texture.Desc()->Depth; + pDesc->MipLevels = m_texture.Desc()->MipLevels; + pDesc->Format = m_texture.Desc()->Format; + pDesc->Usage = m_texture.Desc()->Usage; + pDesc->BindFlags = m_texture.Desc()->BindFlags; + pDesc->CPUAccessFlags = m_texture.Desc()->CPUAccessFlags; + pDesc->MiscFlags = m_texture.Desc()->MiscFlags; + } + + + void STDMETHODCALLTYPE D3D11Texture3D::GetDesc1(D3D11_TEXTURE3D_DESC1* pDesc) { + pDesc->Width = m_texture.Desc()->Width; + pDesc->Height = m_texture.Desc()->Height; + pDesc->Depth = m_texture.Desc()->Depth; + pDesc->MipLevels = m_texture.Desc()->MipLevels; + pDesc->Format = m_texture.Desc()->Format; + pDesc->Usage = m_texture.Desc()->Usage; + pDesc->BindFlags = m_texture.Desc()->BindFlags; + pDesc->CPUAccessFlags = m_texture.Desc()->CPUAccessFlags; + pDesc->MiscFlags = m_texture.Desc()->MiscFlags; + } + + + D3D11CommonTexture* GetCommonTexture(ID3D11Resource* pResource) { + D3D11_RESOURCE_DIMENSION dimension = D3D11_RESOURCE_DIMENSION_UNKNOWN; + pResource->GetType(&dimension); + + switch (dimension) { + case D3D11_RESOURCE_DIMENSION_TEXTURE1D: + return static_cast(pResource)->GetCommonTexture(); + + case D3D11_RESOURCE_DIMENSION_TEXTURE2D: + return static_cast(pResource)->GetCommonTexture(); + + case D3D11_RESOURCE_DIMENSION_TEXTURE3D: + return static_cast(pResource)->GetCommonTexture(); + + default: + return nullptr; + } + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_texture.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_texture.h new file mode 100644 index 00000000000..2db2bc0c0d7 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_texture.h @@ -0,0 +1,721 @@ +#pragma once + +#include "../dxvk/dxvk_cs.h" +#include "../dxvk/dxvk_device.h" + +#include "../d3d10/d3d10_texture.h" + +#include "d3d11_device_child.h" +#include "d3d11_interfaces.h" +#include "d3d11_resource.h" + +namespace dxvk { + + class D3D11Device; + class D3D11GDISurface; + + /** + * \brief Image memory mapping mode + * + * Determines how exactly \c Map will + * behave when mapping an image. + */ + enum D3D11_COMMON_TEXTURE_MAP_MODE { + D3D11_COMMON_TEXTURE_MAP_MODE_NONE, ///< Not mapped + D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER, ///< Mapped through buffer + D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT, ///< Directly mapped to host mem + D3D11_COMMON_TEXTURE_MAP_MODE_STAGING, ///< Buffer only, no image + }; + + + /** + * \brief Common texture description + * + * Contains all members that can be + * defined for 1D, 2D and 3D textures. + */ + struct D3D11_COMMON_TEXTURE_DESC { + UINT Width; + UINT Height; + UINT Depth; + UINT MipLevels; + UINT ArraySize; + DXGI_FORMAT Format; + DXGI_SAMPLE_DESC SampleDesc; + D3D11_USAGE Usage; + UINT BindFlags; + UINT CPUAccessFlags; + UINT MiscFlags; + D3D11_TEXTURE_LAYOUT TextureLayout; + }; + + + /** + * \brief Packed subresource layout + */ + struct D3D11_COMMON_TEXTURE_SUBRESOURCE_LAYOUT { + UINT64 Offset; + UINT64 Size; + UINT RowPitch; + UINT DepthPitch; + }; + + + /** + * \brief D3D11 common texture object + * + * This class implements common texture methods and + * aims to work around the issue that there are three + * different interfaces for basically the same thing. + */ + class D3D11CommonTexture { + + public: + + D3D11CommonTexture( + ID3D11Resource* pInterface, + D3D11Device* pDevice, + const D3D11_COMMON_TEXTURE_DESC* pDesc, + D3D11_RESOURCE_DIMENSION Dimension, + DXGI_USAGE DxgiUsage, + VkImage vkImage, + HANDLE hSharedHandle); + + ~D3D11CommonTexture(); + + /** + * \brief Retrieves resource interface + * \returns Resource interface + */ + ID3D11Resource* GetInterface() const { + return m_interface; + } + + /** + * \brief Texture properties + * + * The returned data can be used to fill in + * \c D3D11_TEXTURE2D_DESC and similar structs. + * \returns Pointer to texture description + */ + const D3D11_COMMON_TEXTURE_DESC* Desc() const { + return &m_desc; + } + + /** + * \brief Retrieves D3D11 texture type + * \returns D3D11 resource dimension + */ + D3D11_RESOURCE_DIMENSION GetDimension() const { + return m_dimension; + } + + /** + * \brief Retrieves Vulkan image type + * + * Returns the image type based on the D3D11 resource + * dimension. Also works if there is no actual image. + * \returns Vulkan image type + */ + VkImageType GetVkImageType() const { + return GetImageTypeFromResourceDim(m_dimension); + } + + /** + * \brief Computes extent of a given mip level + * + * This also works for staging resources that have no image. + * \param [in] Level Mip level to compute the size of + */ + VkExtent3D MipLevelExtent(uint32_t Level) const { + return util::computeMipLevelExtent( + VkExtent3D { m_desc.Width, m_desc.Height, m_desc.Depth }, Level); + } + + /** + * \brief Special DXGI usage flags + * + * Flags that are set in addition to the bind + * flags. Zero for application-created textures. + * \returns DXGI usage flags + */ + DXGI_USAGE GetDxgiUsage() const { + return m_dxgiUsage; + } + + /** + * \brief Counts number of subresources + * \returns Number of subresources + */ + UINT CountSubresources() const { + return m_desc.ArraySize * m_desc.MipLevels; + } + + /** + * \brief Map mode + * \returns Map mode + */ + D3D11_COMMON_TEXTURE_MAP_MODE GetMapMode() const { + return m_mapMode; + } + + /** + * \brief Map type of a given subresource + * + * \param [in] Subresource Subresource index + * \returns Current map mode of that subresource + */ + D3D11_MAP GetMapType(UINT Subresource) const { + return Subresource < m_mapInfo.size() + ? D3D11_MAP(m_mapInfo[Subresource].mapType) + : D3D11_MAP(~0u); + } + + /** + * \brief Sets map type for a given subresource + * + * \param [in] Subresource The subresource + * \param [in] MapType The map type + */ + void SetMapType(UINT Subresource, D3D11_MAP MapType) { + if (Subresource < m_mapInfo.size()) + m_mapInfo[Subresource].mapType = MapType; + } + + /** + * \brief The DXVK image + * \returns The DXVK image + */ + Rc GetImage() const { + return m_image; + } + + /** + * \brief Mapped subresource buffer + * + * \param [in] Subresource Subresource index + * \returns Mapped subresource buffer + */ + Rc GetMappedBuffer(UINT Subresource) const { + return Subresource < m_buffers.size() + ? m_buffers[Subresource].buffer + : Rc(); + } + + /** + * \brief Discards mapped buffer slice for a given subresource + * + * \param [in] Subresource Subresource to discard + * \returns Newly allocated mapped buffer slice + */ + DxvkBufferSliceHandle DiscardSlice(UINT Subresource) { + if (Subresource < m_buffers.size()) { + DxvkBufferSliceHandle slice = m_buffers[Subresource].buffer->allocSlice(); + m_buffers[Subresource].slice = slice; + return slice; + } else { + return DxvkBufferSliceHandle(); + } + } + + /** + * \brief Retrieves mapped buffer slice for a given subresource + * + * \param [in] Subresource Subresource index to query + * \returns Currently mapped buffer slice + */ + DxvkBufferSliceHandle GetMappedSlice(UINT Subresource) const { + return Subresource < m_buffers.size() + ? m_buffers[Subresource].slice + : DxvkBufferSliceHandle(); + } + + /** + * \brief Returns underlying packed Vulkan format + * + * This works even for staging resources that have no image. + * Note that for depth-stencil resources, the returned format + * may be different from the image format on some systems. + * \returns Packed Vulkan format + */ + VkFormat GetPackedFormat() const { + return m_packedFormat; + } + + /** + * \brief Checks whether the resource is eligible for tracking + * + * Mapped resources with no bind flags can be tracked so that + * mapping them will not necessarily cause a CS thread sync. + * \returns \c true if tracking is supported for this resource + */ + bool HasSequenceNumber() const { + if (m_mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_NONE) + return false; + + // For buffer-mapped images we only need to track copies to + // and from that buffer, so we can safely ignore bind flags + if (m_mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER) + return true; + + // Otherwise we can only do accurate tracking if the + // image cannot be used in the rendering pipeline. + return m_desc.BindFlags == 0; + } + + /** + * \brief Tracks sequence number for a given subresource + * + * Stores which CS chunk the resource was last used on. + * \param [in] Subresource Subresource index + * \param [in] Seq Sequence number + */ + void TrackSequenceNumber(UINT Subresource, uint64_t Seq) { + if (Subresource < m_mapInfo.size()) + m_mapInfo[Subresource].seq = Seq; + } + + /** + * \brief Queries sequence number for a given subresource + * + * Returns which CS chunk the resource was last used on. + * \param [in] Subresource Subresource index + * \returns Sequence number for the given subresource + */ + uint64_t GetSequenceNumber(UINT Subresource) { + if (HasSequenceNumber()) { + return Subresource < m_buffers.size() + ? m_mapInfo[Subresource].seq + : 0ull; + } else { + return DxvkCsThread::SynchronizeAll; + } + } + + /** + * \brief Computes pixel offset into mapped buffer + * + * \param [in] Subresource Subresource index + * \param [in] Subresource Plane index + * \param [in] Offset Pixel coordinate to compute offset for + * \returns Offset into mapped subresource buffer, in pixels + */ + VkDeviceSize ComputeMappedOffset(UINT Subresource, UINT Plane, VkOffset3D Offset) const; + + /** + * \brief Computes subresource from the subresource index + * + * Used by some functions that operate on only + * one subresource, such as \c UpdateSubresource. + * \param [in] Aspect The image aspect + * \param [in] Subresource Subresource index + * \returns The Vulkan image subresource + */ + VkImageSubresource GetSubresourceFromIndex( + VkImageAspectFlags Aspect, + UINT Subresource) const; + + /** + * \brief Computes subresource layout for the given subresource + * + * \param [in] AspectMask The image aspect + * \param [in] Subresource Subresource index + * \returns Memory layout of the mapped subresource + */ + D3D11_COMMON_TEXTURE_SUBRESOURCE_LAYOUT GetSubresourceLayout( + VkImageAspectFlags AspectMask, + UINT Subresource) const; + + /** + * \brief Format mode + * + * Determines whether the image is going to + * be used as a color image or a depth image. + * \returns Format mode + */ + DXGI_VK_FORMAT_MODE GetFormatMode() const; + + /** + * \brief Computes plane count + * + * For non-planar formats, the plane count will be 1. + * \returns Image plane count + */ + uint32_t GetPlaneCount() const; + + /** + * \brief Checks whether a view can be created for this textue + * + * View formats are only compatible if they are either identical + * or from the same family of typeless formats, where the resource + * format must be typeless and the view format must be typed. This + * will also check whether the required bind flags are supported. + * \param [in] BindFlags Bind flags for the view + * \param [in] Format The desired view format + * \param [in] Plane Plane slice for planar formats + * \returns \c true if the format is compatible + */ + bool CheckViewCompatibility( + UINT BindFlags, + DXGI_FORMAT Format, + UINT Plane) const; + + /** + * \brief Normalizes and validates texture description + * + * Fills in undefined values and validates the texture + * parameters. Any error returned by this method should + * be forwarded to the application. + * \param [in,out] pDesc Texture description + * \returns \c S_OK if the parameters are valid + */ + static HRESULT NormalizeTextureProperties( + D3D11_COMMON_TEXTURE_DESC* pDesc); + + private: + + struct MappedBuffer { + Rc buffer; + DxvkBufferSliceHandle slice; + }; + + struct MappedInfo { + D3D11_MAP mapType; + uint64_t seq; + }; + + ID3D11Resource* m_interface; + D3D11Device* m_device; + D3D11_RESOURCE_DIMENSION m_dimension; + D3D11_COMMON_TEXTURE_DESC m_desc; + D3D11_COMMON_TEXTURE_MAP_MODE m_mapMode; + DXGI_USAGE m_dxgiUsage; + VkFormat m_packedFormat; + + Rc m_image; + std::vector m_buffers; + std::vector m_mapInfo; + + MappedBuffer CreateMappedBuffer( + UINT MipLevel) const; + + BOOL CheckImageSupport( + const DxvkImageCreateInfo* pImageInfo, + VkImageTiling Tiling) const; + + BOOL CheckFormatFeatureSupport( + VkFormat Format, + VkFormatFeatureFlags Features) const; + + VkImageUsageFlags EnableMetaCopyUsage( + VkFormat Format, + VkImageTiling Tiling) const; + + VkImageUsageFlags EnableMetaPackUsage( + VkFormat Format, + UINT CpuAccess) const; + + VkMemoryPropertyFlags GetMemoryFlags() const; + + D3D11_COMMON_TEXTURE_MAP_MODE DetermineMapMode( + const DxvkImageCreateInfo* pImageInfo) const; + + void ExportImageInfo(); + + static BOOL IsR32UavCompatibleFormat( + DXGI_FORMAT Format); + + static VkImageType GetImageTypeFromResourceDim( + D3D11_RESOURCE_DIMENSION Dimension); + + static VkImageLayout OptimizeLayout( + VkImageUsageFlags Usage); + }; + + + /** + * \brief IDXGISurface implementation for D3D11 textures + * + * Provides an implementation for 2D textures that + * have only one array layer and one mip level. + */ + class D3D11DXGISurface : public IDXGISurface2 { + + public: + + D3D11DXGISurface( + ID3D11Resource* pResource, + D3D11CommonTexture* pTexture); + + ~D3D11DXGISurface(); + + ULONG STDMETHODCALLTYPE AddRef(); + + ULONG STDMETHODCALLTYPE Release(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + HRESULT STDMETHODCALLTYPE GetPrivateData( + REFGUID Name, + UINT* pDataSize, + void* pData); + + HRESULT STDMETHODCALLTYPE SetPrivateData( + REFGUID Name, + UINT DataSize, + const void* pData); + + HRESULT STDMETHODCALLTYPE SetPrivateDataInterface( + REFGUID Name, + const IUnknown* pUnknown); + + HRESULT STDMETHODCALLTYPE GetParent( + REFIID riid, + void** ppParent); + + HRESULT STDMETHODCALLTYPE GetDevice( + REFIID riid, + void** ppDevice); + + HRESULT STDMETHODCALLTYPE GetDesc( + DXGI_SURFACE_DESC* pDesc); + + HRESULT STDMETHODCALLTYPE Map( + DXGI_MAPPED_RECT* pLockedRect, + UINT MapFlags); + + HRESULT STDMETHODCALLTYPE Unmap(); + + HRESULT STDMETHODCALLTYPE GetDC( + BOOL Discard, + HDC* phdc); + + HRESULT STDMETHODCALLTYPE ReleaseDC( + RECT* pDirtyRect); + + HRESULT STDMETHODCALLTYPE GetResource( + REFIID riid, + void** ppParentResource, + UINT* pSubresourceIndex); + + bool isSurfaceCompatible() const; + + private: + + ID3D11Resource* m_resource; + D3D11CommonTexture* m_texture; + D3D11GDISurface* m_gdiSurface; + + }; + + + /** + * \brief Common texture interop class + * + * Provides access to the underlying Vulkan + * texture to external Vulkan libraries. + */ + class D3D11VkInteropSurface : public IDXGIVkInteropSurface { + + public: + + D3D11VkInteropSurface( + ID3D11Resource* pResource, + D3D11CommonTexture* pTexture); + + ~D3D11VkInteropSurface(); + + ULONG STDMETHODCALLTYPE AddRef(); + + ULONG STDMETHODCALLTYPE Release(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + HRESULT STDMETHODCALLTYPE GetDevice( + IDXGIVkInteropDevice** ppDevice); + + HRESULT STDMETHODCALLTYPE GetVulkanImageInfo( + VkImage* pHandle, + VkImageLayout* pLayout, + VkImageCreateInfo* pInfo); + + private: + + ID3D11Resource* m_resource; + D3D11CommonTexture* m_texture; + + }; + + + /////////////////////////////////////////// + // D 3 D 1 1 T E X T U R E 1 D + class D3D11Texture1D : public D3D11DeviceChild { + + public: + + D3D11Texture1D( + D3D11Device* pDevice, + const D3D11_COMMON_TEXTURE_DESC* pDesc); + + ~D3D11Texture1D(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject) final; + + void STDMETHODCALLTYPE GetType( + D3D11_RESOURCE_DIMENSION *pResourceDimension) final; + + UINT STDMETHODCALLTYPE GetEvictionPriority() final; + + void STDMETHODCALLTYPE SetEvictionPriority(UINT EvictionPriority) final; + + void STDMETHODCALLTYPE GetDesc( + D3D11_TEXTURE1D_DESC *pDesc) final; + + D3D11CommonTexture* GetCommonTexture() { + return &m_texture; + } + + D3D10Texture1D* GetD3D10Iface() { + return &m_d3d10; + } + + private: + + D3D11CommonTexture m_texture; + D3D11VkInteropSurface m_interop; + D3D11DXGISurface m_surface; + D3D11DXGIResource m_resource; + D3D10Texture1D m_d3d10; + + }; + + + /////////////////////////////////////////// + // D 3 D 1 1 T E X T U R E 2 D + class D3D11Texture2D : public D3D11DeviceChild { + + public: + + D3D11Texture2D( + D3D11Device* pDevice, + const D3D11_COMMON_TEXTURE_DESC* pDesc, + HANDLE hSharedHandle); + + D3D11Texture2D( + D3D11Device* pDevice, + const D3D11_COMMON_TEXTURE_DESC* pDesc, + DXGI_USAGE DxgiUsage, + VkImage vkImage); + + D3D11Texture2D( + D3D11Device* pDevice, + IUnknown* pSwapChain, + const D3D11_COMMON_TEXTURE_DESC* pDesc, + DXGI_USAGE DxgiUsage); + + ~D3D11Texture2D(); + + ULONG STDMETHODCALLTYPE AddRef(); + + ULONG STDMETHODCALLTYPE Release(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject) final; + + void STDMETHODCALLTYPE GetType( + D3D11_RESOURCE_DIMENSION *pResourceDimension) final; + + UINT STDMETHODCALLTYPE GetEvictionPriority() final; + + void STDMETHODCALLTYPE SetEvictionPriority(UINT EvictionPriority) final; + + void STDMETHODCALLTYPE GetDesc( + D3D11_TEXTURE2D_DESC* pDesc) final; + + void STDMETHODCALLTYPE GetDesc1( + D3D11_TEXTURE2D_DESC1* pDesc) final; + + D3D11CommonTexture* GetCommonTexture() { + return &m_texture; + } + + D3D10Texture2D* GetD3D10Iface() { + return &m_d3d10; + } + + private: + + D3D11CommonTexture m_texture; + D3D11VkInteropSurface m_interop; + D3D11DXGISurface m_surface; + D3D11DXGIResource m_resource; + D3D10Texture2D m_d3d10; + IUnknown* m_swapChain; + + }; + + + /////////////////////////////////////////// + // D 3 D 1 1 T E X T U R E 3 D + class D3D11Texture3D : public D3D11DeviceChild { + + public: + + D3D11Texture3D( + D3D11Device* pDevice, + const D3D11_COMMON_TEXTURE_DESC* pDesc); + + ~D3D11Texture3D(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject) final; + + void STDMETHODCALLTYPE GetType( + D3D11_RESOURCE_DIMENSION *pResourceDimension) final; + + UINT STDMETHODCALLTYPE GetEvictionPriority() final; + + void STDMETHODCALLTYPE SetEvictionPriority(UINT EvictionPriority) final; + + void STDMETHODCALLTYPE GetDesc( + D3D11_TEXTURE3D_DESC* pDesc) final; + + void STDMETHODCALLTYPE GetDesc1( + D3D11_TEXTURE3D_DESC1* pDesc) final; + + D3D11CommonTexture* GetCommonTexture() { + return &m_texture; + } + + D3D10Texture3D* GetD3D10Iface() { + return &m_d3d10; + } + + private: + + D3D11CommonTexture m_texture; + D3D11VkInteropSurface m_interop; + D3D11DXGIResource m_resource; + D3D10Texture3D m_d3d10; + + }; + + + /** + * \brief Retrieves texture from resource pointer + * + * \param [in] pResource The resource to query + * \returns Pointer to texture info, or \c nullptr + */ + D3D11CommonTexture* GetCommonTexture( + ID3D11Resource* pResource); + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_util.cpp b/utils/dxvk-1.10.3/src/d3d11/d3d11_util.cpp new file mode 100644 index 00000000000..d4448c54f62 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_util.cpp @@ -0,0 +1,141 @@ +#include "d3d11_util.h" + +namespace dxvk { + + HRESULT DecodeSampleCount(UINT Count, VkSampleCountFlagBits* pCount) { + VkSampleCountFlagBits flag; + + switch (Count) { + case 1: flag = VK_SAMPLE_COUNT_1_BIT; break; + case 2: flag = VK_SAMPLE_COUNT_2_BIT; break; + case 4: flag = VK_SAMPLE_COUNT_4_BIT; break; + case 8: flag = VK_SAMPLE_COUNT_8_BIT; break; + case 16: flag = VK_SAMPLE_COUNT_16_BIT; break; + default: return E_INVALIDARG; + } + + if (pCount != nullptr) { + *pCount = flag; + return S_OK; + } return S_FALSE; + } + + + VkSamplerAddressMode DecodeAddressMode( + D3D11_TEXTURE_ADDRESS_MODE mode) { + switch (mode) { + case D3D11_TEXTURE_ADDRESS_WRAP: + return VK_SAMPLER_ADDRESS_MODE_REPEAT; + + case D3D11_TEXTURE_ADDRESS_MIRROR: + return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT; + + case D3D11_TEXTURE_ADDRESS_CLAMP: + return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + + case D3D11_TEXTURE_ADDRESS_BORDER: + return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; + + case D3D11_TEXTURE_ADDRESS_MIRROR_ONCE: + return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE; + + default: + Logger::err(str::format("D3D11: Unsupported address mode: ", mode)); + return VK_SAMPLER_ADDRESS_MODE_REPEAT; + } + } + + + VkCompareOp DecodeCompareOp(D3D11_COMPARISON_FUNC Mode) { + switch (Mode) { + case D3D11_COMPARISON_NEVER: return VK_COMPARE_OP_NEVER; + case D3D11_COMPARISON_LESS: return VK_COMPARE_OP_LESS; + case D3D11_COMPARISON_EQUAL: return VK_COMPARE_OP_EQUAL; + case D3D11_COMPARISON_LESS_EQUAL: return VK_COMPARE_OP_LESS_OR_EQUAL; + case D3D11_COMPARISON_GREATER: return VK_COMPARE_OP_GREATER; + case D3D11_COMPARISON_NOT_EQUAL: return VK_COMPARE_OP_NOT_EQUAL; + case D3D11_COMPARISON_GREATER_EQUAL: return VK_COMPARE_OP_GREATER_OR_EQUAL; + case D3D11_COMPARISON_ALWAYS: return VK_COMPARE_OP_ALWAYS; + } + + if (Mode != 0) // prevent log spamming when apps use ZeroMemory + Logger::err(str::format("D3D11: Unsupported compare op: ", Mode)); + return VK_COMPARE_OP_NEVER; + } + + + VkConservativeRasterizationModeEXT DecodeConservativeRasterizationMode( + D3D11_CONSERVATIVE_RASTERIZATION_MODE Mode) { + switch (Mode) { + case D3D11_CONSERVATIVE_RASTERIZATION_MODE_OFF: + return VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT; + case D3D11_CONSERVATIVE_RASTERIZATION_MODE_ON: + return VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT; + } + + Logger::err(str::format("D3D11: Unsupported conservative raster mode: ", Mode)); + return VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT; + } + + + VkShaderStageFlagBits GetShaderStage(DxbcProgramType ProgramType) { + switch (ProgramType) { + case DxbcProgramType::VertexShader: return VK_SHADER_STAGE_VERTEX_BIT; + case DxbcProgramType::HullShader: return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; + case DxbcProgramType::DomainShader: return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; + case DxbcProgramType::GeometryShader: return VK_SHADER_STAGE_GEOMETRY_BIT; + case DxbcProgramType::PixelShader: return VK_SHADER_STAGE_FRAGMENT_BIT; + case DxbcProgramType::ComputeShader: return VK_SHADER_STAGE_COMPUTE_BIT; + default: return VkShaderStageFlagBits(0); + } + } + + + VkFormatFeatureFlags GetBufferFormatFeatures(UINT BindFlags) { + VkFormatFeatureFlags features = 0; + + if (BindFlags & D3D11_BIND_SHADER_RESOURCE) + features |= VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT; + if (BindFlags & D3D11_BIND_UNORDERED_ACCESS) + features |= VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT; + + return features; + } + + + VkFormatFeatureFlags GetImageFormatFeatures(UINT BindFlags) { + VkFormatFeatureFlags features = 0; + + if (BindFlags & D3D11_BIND_DEPTH_STENCIL) + features |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT; + if (BindFlags & D3D11_BIND_RENDER_TARGET) + features |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT; + if (BindFlags & D3D11_BIND_SHADER_RESOURCE) + features |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT; + if (BindFlags & D3D11_BIND_UNORDERED_ACCESS) + features |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT; + + return features; + } + + + VkFormat GetPackedDepthStencilFormat(DXGI_FORMAT Format) { + switch (Format) { + case DXGI_FORMAT_R24G8_TYPELESS: + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + case DXGI_FORMAT_D24_UNORM_S8_UINT: + return VK_FORMAT_D24_UNORM_S8_UINT; + + case DXGI_FORMAT_R32G8X24_TYPELESS: + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + return VK_FORMAT_D32_SFLOAT_S8_UINT; + + default: + return VK_FORMAT_UNDEFINED; + } + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_util.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_util.h new file mode 100644 index 00000000000..749dc8bed02 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_util.h @@ -0,0 +1,46 @@ +#pragma once + +#include "../dxvk/dxvk_device.h" + +#include "../dxbc/dxbc_util.h" + +#include "d3d11_include.h" + +namespace dxvk { + + template + UINT CompactSparseList(T* pData, UINT Mask) { + uint32_t count = 0; + + for (uint32_t id : bit::BitMask(Mask)) + pData[count++] = pData[id]; + + return count; + } + + HRESULT DecodeSampleCount( + UINT Count, + VkSampleCountFlagBits* pCount); + + VkSamplerAddressMode DecodeAddressMode( + D3D11_TEXTURE_ADDRESS_MODE mode); + + VkCompareOp DecodeCompareOp( + D3D11_COMPARISON_FUNC Mode); + + VkConservativeRasterizationModeEXT DecodeConservativeRasterizationMode( + D3D11_CONSERVATIVE_RASTERIZATION_MODE Mode); + + VkShaderStageFlagBits GetShaderStage( + DxbcProgramType ProgramType); + + VkFormatFeatureFlags GetBufferFormatFeatures( + UINT BindFlags); + + VkFormatFeatureFlags GetImageFormatFeatures( + UINT BindFlags); + + VkFormat GetPackedDepthStencilFormat( + DXGI_FORMAT Format); + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_video.cpp b/utils/dxvk-1.10.3/src/d3d11/d3d11_video.cpp new file mode 100644 index 00000000000..92bacdcaec8 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_video.cpp @@ -0,0 +1,1305 @@ +#include + +#include "d3d11_context.h" +#include "d3d11_context_imm.h" +#include "d3d11_video.h" + +#include +#include + +namespace dxvk { + + D3D11VideoProcessorEnumerator::D3D11VideoProcessorEnumerator( + D3D11Device* pDevice, + const D3D11_VIDEO_PROCESSOR_CONTENT_DESC& Desc) + : D3D11DeviceChild(pDevice), + m_desc(Desc) { + + } + + + D3D11VideoProcessorEnumerator::~D3D11VideoProcessorEnumerator() { + + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoProcessorEnumerator::QueryInterface( + REFIID riid, + void** ppvObject) { + if (riid == __uuidof(IUnknown) + || riid == __uuidof(ID3D11DeviceChild) + || riid == __uuidof(ID3D11VideoProcessorEnumerator)) { + *ppvObject = ref(this); + return S_OK; + } + + Logger::warn("D3D11VideoProcessorEnumerator::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoProcessorEnumerator::GetVideoProcessorContentDesc( + D3D11_VIDEO_PROCESSOR_CONTENT_DESC* pContentDesc) { + *pContentDesc = m_desc; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoProcessorEnumerator::CheckVideoProcessorFormat( + DXGI_FORMAT Format, + UINT* pFlags) { + Logger::err("D3D11VideoProcessorEnumerator::CheckVideoProcessorFormat: Stub"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoProcessorEnumerator::GetVideoProcessorCaps( + D3D11_VIDEO_PROCESSOR_CAPS* pCaps) { + Logger::err("D3D11VideoProcessorEnumerator::GetVideoProcessorCaps: Stub"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoProcessorEnumerator::GetVideoProcessorRateConversionCaps( + UINT TypeIndex, + D3D11_VIDEO_PROCESSOR_RATE_CONVERSION_CAPS* pCaps) { + Logger::err("D3D11VideoProcessorEnumerator::GetVideoProcessorRateConversionCaps: Stub"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoProcessorEnumerator::GetVideoProcessorCustomRate( + UINT TypeIndex, + UINT CustomRateIndex, + D3D11_VIDEO_PROCESSOR_CUSTOM_RATE* pRate) { + Logger::err("D3D11VideoProcessorEnumerator::GetVideoProcessorCustomRate: Stub"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoProcessorEnumerator::GetVideoProcessorFilterRange( + D3D11_VIDEO_PROCESSOR_FILTER Filter, + D3D11_VIDEO_PROCESSOR_FILTER_RANGE* pRange) { + Logger::err("D3D11VideoProcessorEnumerator::GetVideoProcessorFilterRange: Stub"); + return E_NOTIMPL; + } + + + + + D3D11VideoProcessor::D3D11VideoProcessor( + D3D11Device* pDevice, + D3D11VideoProcessorEnumerator* pEnumerator, + UINT RateConversionIndex) + : D3D11DeviceChild(pDevice), + m_enumerator(pEnumerator), m_rateConversionIndex(RateConversionIndex) { + + } + + + D3D11VideoProcessor::~D3D11VideoProcessor() { + + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoProcessor::QueryInterface( + REFIID riid, + void** ppvObject) { + if (riid == __uuidof(IUnknown) + || riid == __uuidof(ID3D11DeviceChild) + || riid == __uuidof(ID3D11VideoProcessor)) { + *ppvObject = ref(this); + return S_OK; + } + + Logger::warn("D3D11VideoProcessor::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + void STDMETHODCALLTYPE D3D11VideoProcessor::GetContentDesc( + D3D11_VIDEO_PROCESSOR_CONTENT_DESC *pDesc) { + m_enumerator->GetVideoProcessorContentDesc(pDesc); + } + + + void STDMETHODCALLTYPE D3D11VideoProcessor::GetRateConversionCaps( + D3D11_VIDEO_PROCESSOR_RATE_CONVERSION_CAPS *pCaps) { + m_enumerator->GetVideoProcessorRateConversionCaps(m_rateConversionIndex, pCaps); + } + + + + + D3D11VideoProcessorInputView::D3D11VideoProcessorInputView( + D3D11Device* pDevice, + ID3D11Resource* pResource, + const D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC& Desc) + : D3D11DeviceChild(pDevice), + m_resource(pResource), m_desc(Desc) { + D3D11_COMMON_RESOURCE_DESC resourceDesc = { }; + GetCommonResourceDesc(pResource, &resourceDesc); + + Rc dxvkImage = GetCommonTexture(pResource)->GetImage(); + + if (!(dxvkImage->info().usage & VK_IMAGE_USAGE_SAMPLED_BIT)) { + DxvkImageCreateInfo info = dxvkImage->info(); + info.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT; + info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + info.access = VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT; + info.tiling = VK_IMAGE_TILING_OPTIMAL; + info.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + info.shared = VK_FALSE; + dxvkImage = m_copy = pDevice->GetDXVKDevice()->createImage(info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + } + + DXGI_VK_FORMAT_INFO formatInfo = pDevice->LookupFormat(resourceDesc.Format, DXGI_VK_FORMAT_MODE_COLOR); + DXGI_VK_FORMAT_FAMILY formatFamily = pDevice->LookupFamily(resourceDesc.Format, DXGI_VK_FORMAT_MODE_COLOR); + + VkImageAspectFlags aspectMask = imageFormatInfo(formatInfo.Format)->aspectMask; + + DxvkImageViewCreateInfo viewInfo; + viewInfo.format = formatInfo.Format; + viewInfo.swizzle = formatInfo.Swizzle; + viewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT; + + switch (m_desc.ViewDimension) { + case D3D11_VPIV_DIMENSION_TEXTURE2D: + viewInfo.type = VK_IMAGE_VIEW_TYPE_2D; + viewInfo.minLevel = m_desc.Texture2D.MipSlice; + viewInfo.numLevels = 1; + viewInfo.minLayer = 0; + viewInfo.numLayers = 1; + break; + + case D3D11_RTV_DIMENSION_UNKNOWN: + throw DxvkError("Invalid view dimension"); + } + + m_subresources.aspectMask = aspectMask; + m_subresources.baseArrayLayer = viewInfo.minLayer; + m_subresources.layerCount = viewInfo.numLayers; + m_subresources.mipLevel = viewInfo.minLevel; + + for (uint32_t i = 0; aspectMask && i < m_views.size(); i++) { + viewInfo.aspect = vk::getNextAspect(aspectMask); + + if (viewInfo.aspect != VK_IMAGE_ASPECT_COLOR_BIT) + viewInfo.format = formatFamily.Formats[i]; + + m_views[i] = pDevice->GetDXVKDevice()->createImageView(dxvkImage, viewInfo); + } + + m_isYCbCr = IsYCbCrFormat(resourceDesc.Format); + } + + + D3D11VideoProcessorInputView::~D3D11VideoProcessorInputView() { + + } + + + bool D3D11VideoProcessorInputView::IsYCbCrFormat(DXGI_FORMAT Format) { + static const std::array s_formats = {{ + DXGI_FORMAT_NV12, + DXGI_FORMAT_YUY2, + DXGI_FORMAT_AYUV, + }}; + + return std::find(s_formats.begin(), s_formats.end(), Format) != s_formats.end(); + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoProcessorInputView::QueryInterface( + REFIID riid, + void** ppvObject) { + if (riid == __uuidof(IUnknown) + || riid == __uuidof(ID3D11DeviceChild) + || riid == __uuidof(ID3D11View) + || riid == __uuidof(ID3D11VideoProcessorInputView)) { + *ppvObject = ref(this); + return S_OK; + } + + Logger::warn("D3D11VideoProcessorInputView::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + void STDMETHODCALLTYPE D3D11VideoProcessorInputView::GetResource( + ID3D11Resource** ppResource) { + *ppResource = m_resource.ref(); + } + + + void STDMETHODCALLTYPE D3D11VideoProcessorInputView::GetDesc( + D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC* pDesc) { + *pDesc = m_desc; + } + + + + D3D11VideoProcessorOutputView::D3D11VideoProcessorOutputView( + D3D11Device* pDevice, + ID3D11Resource* pResource, + const D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC& Desc) + : D3D11DeviceChild(pDevice), + m_resource(pResource), m_desc(Desc) { + D3D11_COMMON_RESOURCE_DESC resourceDesc = { }; + GetCommonResourceDesc(pResource, &resourceDesc); + + DXGI_VK_FORMAT_INFO formatInfo = pDevice->LookupFormat( + resourceDesc.Format, DXGI_VK_FORMAT_MODE_COLOR); + + DxvkImageViewCreateInfo viewInfo; + viewInfo.format = formatInfo.Format; + viewInfo.aspect = imageFormatInfo(viewInfo.format)->aspectMask; + viewInfo.swizzle = formatInfo.Swizzle; + viewInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + + switch (m_desc.ViewDimension) { + case D3D11_VPOV_DIMENSION_TEXTURE2D: + viewInfo.type = VK_IMAGE_VIEW_TYPE_2D; + viewInfo.minLevel = m_desc.Texture2D.MipSlice; + viewInfo.numLevels = 1; + viewInfo.minLayer = 0; + viewInfo.numLayers = 1; + break; + + case D3D11_VPOV_DIMENSION_TEXTURE2DARRAY: + viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; + viewInfo.minLevel = m_desc.Texture2DArray.MipSlice; + viewInfo.numLevels = 1; + viewInfo.minLayer = m_desc.Texture2DArray.FirstArraySlice; + viewInfo.numLayers = m_desc.Texture2DArray.ArraySize; + break; + + case D3D11_RTV_DIMENSION_UNKNOWN: + throw DxvkError("Invalid view dimension"); + } + + m_view = pDevice->GetDXVKDevice()->createImageView( + GetCommonTexture(pResource)->GetImage(), viewInfo); + } + + + D3D11VideoProcessorOutputView::~D3D11VideoProcessorOutputView() { + + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoProcessorOutputView::QueryInterface( + REFIID riid, + void** ppvObject) { + if (riid == __uuidof(IUnknown) + || riid == __uuidof(ID3D11DeviceChild) + || riid == __uuidof(ID3D11View) + || riid == __uuidof(ID3D11VideoProcessorOutputView)) { + *ppvObject = ref(this); + return S_OK; + } + + Logger::warn("D3D11VideoProcessorOutputView::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + void STDMETHODCALLTYPE D3D11VideoProcessorOutputView::GetResource( + ID3D11Resource** ppResource) { + *ppResource = m_resource.ref(); + } + + + void STDMETHODCALLTYPE D3D11VideoProcessorOutputView::GetDesc( + D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC* pDesc) { + *pDesc = m_desc; + } + + + + D3D11VideoContext::D3D11VideoContext( + D3D11ImmediateContext* pContext, + const Rc& Device) + : m_ctx(pContext) { + SpirvCodeBuffer vsCode(d3d11_video_blit_vert); + SpirvCodeBuffer fsCode(d3d11_video_blit_frag); + + const std::array fsResourceSlots = {{ + { 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC }, + { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, + { 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, VK_IMAGE_VIEW_TYPE_2D }, + { 3, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, VK_IMAGE_VIEW_TYPE_2D }, + }}; + + DxvkShaderCreateInfo vsInfo; + vsInfo.stage = VK_SHADER_STAGE_VERTEX_BIT; + vsInfo.outputMask = 0x1; + m_vs = new DxvkShader(vsInfo, std::move(vsCode)); + + DxvkShaderCreateInfo fsInfo; + fsInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT; + fsInfo.resourceSlotCount = fsResourceSlots.size(); + fsInfo.resourceSlots = fsResourceSlots.data(); + fsInfo.inputMask = 0x1; + fsInfo.outputMask = 0x1; + m_fs = new DxvkShader(fsInfo, std::move(fsCode)); + + DxvkSamplerCreateInfo samplerInfo; + samplerInfo.magFilter = VK_FILTER_LINEAR; + samplerInfo.minFilter = VK_FILTER_LINEAR; + samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; + samplerInfo.mipmapLodBias = 0.0f; + samplerInfo.mipmapLodMin = 0.0f; + samplerInfo.mipmapLodMax = 0.0f; + samplerInfo.useAnisotropy = VK_FALSE; + samplerInfo.maxAnisotropy = 1.0f; + samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerInfo.compareToDepth = VK_FALSE; + samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS; + samplerInfo.borderColor = VkClearColorValue(); + samplerInfo.usePixelCoord = VK_FALSE; + samplerInfo.nonSeamless = VK_FALSE; + m_sampler = Device->createSampler(samplerInfo); + + DxvkBufferCreateInfo bufferInfo; + bufferInfo.size = sizeof(UboData); + bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; + bufferInfo.stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + bufferInfo.access = VK_ACCESS_UNIFORM_READ_BIT; + m_ubo = Device->createBuffer(bufferInfo, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + } + + + D3D11VideoContext::~D3D11VideoContext() { + + } + + + ULONG STDMETHODCALLTYPE D3D11VideoContext::AddRef() { + return m_ctx->AddRef(); + } + + + ULONG STDMETHODCALLTYPE D3D11VideoContext::Release() { + return m_ctx->Release(); + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoContext::QueryInterface( + REFIID riid, + void** ppvObject) { + return m_ctx->QueryInterface(riid, ppvObject); + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoContext::GetPrivateData( + REFGUID Name, + UINT* pDataSize, + void* pData) { + return m_ctx->GetPrivateData(Name, pDataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoContext::SetPrivateData( + REFGUID Name, + UINT DataSize, + const void* pData) { + return m_ctx->SetPrivateData(Name, DataSize, pData); + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoContext::SetPrivateDataInterface( + REFGUID Name, + const IUnknown* pUnknown) { + return m_ctx->SetPrivateDataInterface(Name, pUnknown); + } + + + void STDMETHODCALLTYPE D3D11VideoContext::GetDevice( + ID3D11Device** ppDevice) { + return m_ctx->GetDevice(ppDevice); + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoContext::GetDecoderBuffer( + ID3D11VideoDecoder* pDecoder, + D3D11_VIDEO_DECODER_BUFFER_TYPE Type, + UINT* BufferSize, + void** ppBuffer) { + Logger::err("D3D11VideoContext::GetDecoderBuffer: Stub"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoContext::ReleaseDecoderBuffer( + ID3D11VideoDecoder* pDecoder, + D3D11_VIDEO_DECODER_BUFFER_TYPE Type) { + Logger::err("D3D11VideoContext::ReleaseDecoderBuffer: Stub"); + return E_NOTIMPL; + } + + HRESULT STDMETHODCALLTYPE D3D11VideoContext::DecoderBeginFrame( + ID3D11VideoDecoder* pDecoder, + ID3D11VideoDecoderOutputView* pView, + UINT KeySize, + const void* pKey) { + Logger::err("D3D11VideoContext::DecoderBeginFrame: Stub"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoContext::DecoderEndFrame( + ID3D11VideoDecoder* pDecoder) { + Logger::err("D3D11VideoContext::DecoderEndFrame: Stub"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoContext::SubmitDecoderBuffers( + ID3D11VideoDecoder* pDecoder, + UINT BufferCount, + const D3D11_VIDEO_DECODER_BUFFER_DESC* pBufferDescs) { + Logger::err("D3D11VideoContext::SubmitDecoderBuffers: Stub"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoContext::DecoderExtension( + ID3D11VideoDecoder* pDecoder, + const D3D11_VIDEO_DECODER_EXTENSION* pExtension) { + Logger::err("D3D11VideoContext::DecoderExtension: Stub"); + return E_NOTIMPL; + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetOutputTargetRect( + ID3D11VideoProcessor* pVideoProcessor, + BOOL Enable, + const RECT* pRect) { + D3D10DeviceLock lock = m_ctx->LockContext(); + + auto state = static_cast(pVideoProcessor)->GetState(); + state->outputTargetRectEnabled = Enable; + + if (Enable) + state->outputTargetRect = *pRect; + + static bool errorShown = false; + + if (!std::exchange(errorShown, true)) + Logger::err("D3D11VideoContext::VideoProcessorSetOutputTargetRect: Stub."); + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetOutputBackgroundColor( + ID3D11VideoProcessor* pVideoProcessor, + BOOL YCbCr, + const D3D11_VIDEO_COLOR* pColor) { + D3D10DeviceLock lock = m_ctx->LockContext(); + + auto state = static_cast(pVideoProcessor)->GetState(); + state->outputBackgroundColorIsYCbCr = YCbCr; + state->outputBackgroundColor = *pColor; + + static bool errorShown = false; + + if (!std::exchange(errorShown, true)) + Logger::err("D3D11VideoContext::VideoProcessorSetOutputBackgroundColor: Stub"); + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetOutputColorSpace( + ID3D11VideoProcessor* pVideoProcessor, + const D3D11_VIDEO_PROCESSOR_COLOR_SPACE *pColorSpace) { + D3D10DeviceLock lock = m_ctx->LockContext(); + + auto state = static_cast(pVideoProcessor)->GetState(); + state->outputColorSpace = *pColorSpace; + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetOutputAlphaFillMode( + ID3D11VideoProcessor* pVideoProcessor, + D3D11_VIDEO_PROCESSOR_ALPHA_FILL_MODE AlphaFillMode, + UINT StreamIndex) { + Logger::err("D3D11VideoContext::VideoProcessorSetOutputAlphaFillMode: Stub"); + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetOutputConstriction( + ID3D11VideoProcessor* pVideoProcessor, + BOOL Enable, + SIZE Size) { + Logger::err("D3D11VideoContext::VideoProcessorSetOutputConstriction: Stub"); + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetOutputStereoMode( + ID3D11VideoProcessor* pVideoProcessor, + BOOL Enable) { + D3D10DeviceLock lock = m_ctx->LockContext(); + + auto state = static_cast(pVideoProcessor)->GetState(); + state->outputStereoModeEnabled = Enable; + + if (Enable) + Logger::err("D3D11VideoContext: Stereo output not supported"); + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetOutputExtension( + ID3D11VideoProcessor* pVideoProcessor, + const GUID* pExtensionGuid, + UINT DataSize, + void* pData) { + Logger::err("D3D11VideoContext::VideoProcessorSetOutputExtension: Stub"); + return E_NOTIMPL; + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamFrameFormat( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + D3D11_VIDEO_FRAME_FORMAT Format) { + D3D10DeviceLock lock = m_ctx->LockContext(); + + auto state = static_cast(pVideoProcessor)->GetStreamState(StreamIndex); + + if (!state) + return; + + state->frameFormat = Format; + + if (Format != D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE) + Logger::err(str::format("D3D11VideoContext: Unsupported frame format: ", Format)); + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamColorSpace( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + const D3D11_VIDEO_PROCESSOR_COLOR_SPACE *pColorSpace) { + D3D10DeviceLock lock = m_ctx->LockContext(); + + auto state = static_cast(pVideoProcessor)->GetStreamState(StreamIndex); + + if (!state) + return; + + state->colorSpace = *pColorSpace; + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamOutputRate( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + D3D11_VIDEO_PROCESSOR_OUTPUT_RATE Rate, + BOOL Repeat, + const DXGI_RATIONAL* CustomRate) { + Logger::err("D3D11VideoContext::VideoProcessorSetStreamOutputRate: Stub"); + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamSourceRect( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + BOOL Enable, + const RECT* pRect) { + D3D10DeviceLock lock = m_ctx->LockContext(); + + auto state = static_cast(pVideoProcessor)->GetStreamState(StreamIndex); + + if (!state) + return; + + state->srcRectEnabled = Enable; + + if (Enable) + state->srcRect = *pRect; + + static bool errorShown = false; + + if (!std::exchange(errorShown, true)) + Logger::err("D3D11VideoContext::VideoProcessorSetStreamSourceRect: Stub."); + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamDestRect( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + BOOL Enable, + const RECT* pRect) { + D3D10DeviceLock lock = m_ctx->LockContext(); + + auto state = static_cast(pVideoProcessor)->GetStreamState(StreamIndex); + + if (!state) + return; + + state->dstRectEnabled = Enable; + + if (Enable) + state->dstRect = *pRect; + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamAlpha( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + BOOL Enable, + FLOAT Alpha) { + Logger::err("D3D11VideoContext::VideoProcessorSetStreamAlpha: Stub"); + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamPalette( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + UINT EntryCount, + const UINT* pEntries) { + Logger::err("D3D11VideoContext::VideoProcessorSetStreamPalette: Stub"); + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamPixelAspectRatio( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + BOOL Enable, + const DXGI_RATIONAL* pSrcAspectRatio, + const DXGI_RATIONAL* pDstAspectRatio) { + Logger::err("D3D11VideoContext::VideoProcessorSetStreamPixelAspectRatio: Stub"); + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamLumaKey( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + BOOL Enable, + FLOAT Lower, + FLOAT Upper) { + Logger::err("D3D11VideoContext::VideoProcessorSetStreamLumaKey: Stub"); + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamStereoFormat( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + BOOL Enable, + D3D11_VIDEO_PROCESSOR_STEREO_FORMAT Format, + BOOL LeftViewFrame0, + BOOL BaseViewFrame0, + D3D11_VIDEO_PROCESSOR_STEREO_FLIP_MODE FlipMode, + int MonoOffset) { + Logger::err("D3D11VideoContext::VideoProcessorSetStreamStereoFormat: Stub"); + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamAutoProcessingMode( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + BOOL Enable) { + D3D10DeviceLock lock = m_ctx->LockContext(); + + auto state = static_cast(pVideoProcessor)->GetStreamState(StreamIndex); + + if (!state) + return; + + state->autoProcessingEnabled = Enable; + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamFilter( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + D3D11_VIDEO_PROCESSOR_FILTER Filter, + BOOL Enable, + int Level) { + Logger::err("D3D11VideoContext::VideoProcessorSetStreamFilter: Stub"); + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamExtension( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + const GUID* pExtensionGuid, + UINT DataSize, + void* pData) { + Logger::err("D3D11VideoContext::VideoProcessorSetStreamExtension: Stub"); + return E_NOTIMPL; + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamRotation( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + BOOL Enable, + D3D11_VIDEO_PROCESSOR_ROTATION Rotation) { + D3D10DeviceLock lock = m_ctx->LockContext(); + + auto state = static_cast(pVideoProcessor)->GetStreamState(StreamIndex); + + if (!state) + return; + + state->rotationEnabled = Enable; + state->rotation = Rotation; + + if (Enable && Rotation != D3D11_VIDEO_PROCESSOR_ROTATION_IDENTITY) + Logger::err(str::format("D3D11VideoContext: Unsupported rotation: ", Rotation)); + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetOutputTargetRect( + ID3D11VideoProcessor* pVideoProcessor, + BOOL* pEnabled, + RECT* pRect) { + D3D10DeviceLock lock = m_ctx->LockContext(); + + auto state = static_cast(pVideoProcessor)->GetState(); + + if (pEnabled) + *pEnabled = state->outputTargetRectEnabled; + + if (pRect) + *pRect = state->outputTargetRect; + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetOutputBackgroundColor( + ID3D11VideoProcessor* pVideoProcessor, + BOOL* pYCbCr, + D3D11_VIDEO_COLOR* pColor) { + D3D10DeviceLock lock = m_ctx->LockContext(); + + auto state = static_cast(pVideoProcessor)->GetState(); + + if (pYCbCr) + *pYCbCr = state->outputBackgroundColorIsYCbCr; + + if (pColor) + *pColor = state->outputBackgroundColor; + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetOutputColorSpace( + ID3D11VideoProcessor* pVideoProcessor, + D3D11_VIDEO_PROCESSOR_COLOR_SPACE* pColorSpace) { + D3D10DeviceLock lock = m_ctx->LockContext(); + + auto state = static_cast(pVideoProcessor)->GetState(); + + if (pColorSpace) + *pColorSpace = state->outputColorSpace; + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetOutputAlphaFillMode( + ID3D11VideoProcessor* pVideoProcessor, + D3D11_VIDEO_PROCESSOR_ALPHA_FILL_MODE* pAlphaFillMode, + UINT* pStreamIndex) { + Logger::err("D3D11VideoContext::VideoProcessorGetOutputAlphaFillMode: Stub"); + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetOutputConstriction( + ID3D11VideoProcessor* pVideoProcessor, + BOOL* pEnabled, + SIZE* pSize) { + Logger::err("D3D11VideoContext::VideoProcessorGetOutputConstriction: Stub"); + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetOutputStereoMode( + ID3D11VideoProcessor* pVideoProcessor, + BOOL* pEnabled) { + D3D10DeviceLock lock = m_ctx->LockContext(); + + auto state = static_cast(pVideoProcessor)->GetState(); + + if (pEnabled) + *pEnabled = state->outputStereoModeEnabled; + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetOutputExtension( + ID3D11VideoProcessor* pVideoProcessor, + const GUID* pExtensionGuid, + UINT DataSize, + void* pData) { + Logger::err("D3D11VideoContext::VideoProcessorGetOutputExtension: Stub"); + return E_NOTIMPL; + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamFrameFormat( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + D3D11_VIDEO_FRAME_FORMAT* pFormat) { + D3D10DeviceLock lock = m_ctx->LockContext(); + + auto state = static_cast(pVideoProcessor)->GetStreamState(StreamIndex); + + if (!state) + return; + + if (pFormat) + *pFormat = state->frameFormat; + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamColorSpace( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + D3D11_VIDEO_PROCESSOR_COLOR_SPACE* pColorSpace) { + D3D10DeviceLock lock = m_ctx->LockContext(); + + auto state = static_cast(pVideoProcessor)->GetStreamState(StreamIndex); + + if (!state) + return; + + if (pColorSpace) + *pColorSpace = state->colorSpace; + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamOutputRate( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + D3D11_VIDEO_PROCESSOR_OUTPUT_RATE* pRate, + BOOL* pRepeat, + DXGI_RATIONAL* pCustomRate) { + Logger::err("D3D11VideoContext::VideoProcessorGetStreamOutputRate: Stub"); + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamSourceRect( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + BOOL* pEnabled, + RECT* pRect) { + D3D10DeviceLock lock = m_ctx->LockContext(); + + auto state = static_cast(pVideoProcessor)->GetStreamState(StreamIndex); + + if (!state) + return; + + if (pEnabled) + *pEnabled = state->srcRectEnabled; + + if (pRect) + *pRect = state->srcRect; + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamDestRect( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + BOOL* pEnabled, + RECT* pRect) { + D3D10DeviceLock lock = m_ctx->LockContext(); + + auto state = static_cast(pVideoProcessor)->GetStreamState(StreamIndex); + + if (!state) + return; + + if (pEnabled) + *pEnabled = state->dstRectEnabled; + + if (pRect) + *pRect = state->dstRect; + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamAlpha( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + BOOL* pEnabled, + FLOAT* pAlpha) { + Logger::err("D3D11VideoContext::VideoProcessorGetStreamAlpha: Stub"); + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamPalette( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + UINT EntryCount, + UINT* pEntries) { + Logger::err("D3D11VideoContext::VideoProcessorGetStreamPalette: Stub"); + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamPixelAspectRatio( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + BOOL* pEnabled, + DXGI_RATIONAL* pSrcAspectRatio, + DXGI_RATIONAL* pDstAspectRatio) { + Logger::err("D3D11VideoContext::VideoProcessorGetStreamPixelAspectRatio: Stub"); + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamLumaKey( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + BOOL* pEnabled, + FLOAT* pLower, + FLOAT* pUpper) { + Logger::err("D3D11VideoContext::VideoProcessorGetStreamLumaKey: Stub"); + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamStereoFormat( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + BOOL* pEnabled, + D3D11_VIDEO_PROCESSOR_STEREO_FORMAT* pFormat, + BOOL* pLeftViewFrame0, + BOOL* pBaseViewFrame0, + D3D11_VIDEO_PROCESSOR_STEREO_FLIP_MODE* pFlipMode, + int* pMonoOffset) { + Logger::err("D3D11VideoContext::VideoProcessorGetStreamStereoFormat: Stub"); + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamAutoProcessingMode( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + BOOL* pEnabled) { + D3D10DeviceLock lock = m_ctx->LockContext(); + + auto state = static_cast(pVideoProcessor)->GetStreamState(StreamIndex); + + if (!state) + return; + + *pEnabled = state->autoProcessingEnabled; + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamFilter( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + D3D11_VIDEO_PROCESSOR_FILTER Filter, + BOOL* pEnabled, + int* pLevel) { + Logger::err("D3D11VideoContext::VideoProcessorGetStreamFilter: Stub"); + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamExtension( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + const GUID* pExtensionGuid, + UINT DataSize, + void* pData) { + Logger::err("D3D11VideoContext::VideoProcessorGetStreamExtension: Stub"); + return E_NOTIMPL; + } + + + void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamRotation( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + BOOL* pEnable, + D3D11_VIDEO_PROCESSOR_ROTATION* pRotation) { + D3D10DeviceLock lock = m_ctx->LockContext(); + + auto state = static_cast(pVideoProcessor)->GetStreamState(StreamIndex); + + if (!state) + return; + + if (pEnable) + *pEnable = state->rotationEnabled; + + if (pRotation) + *pRotation = state->rotation; + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorBlt( + ID3D11VideoProcessor* pVideoProcessor, + ID3D11VideoProcessorOutputView* pOutputView, + UINT FrameIdx, + UINT StreamCount, + const D3D11_VIDEO_PROCESSOR_STREAM* pStreams) { + D3D10DeviceLock lock = m_ctx->LockContext(); + + auto videoProcessor = static_cast(pVideoProcessor); + bool hasStreamsEnabled = false; + + // Resetting and restoring all context state incurs + // a lot of overhead, so only do it as necessary + for (uint32_t i = 0; i < StreamCount; i++) { + auto streamState = videoProcessor->GetStreamState(i); + + if (!pStreams[i].Enable || !streamState) + continue; + + if (!hasStreamsEnabled) { + m_ctx->ResetState(); + BindOutputView(pOutputView); + hasStreamsEnabled = true; + } + + BlitStream(streamState, &pStreams[i]); + } + + if (hasStreamsEnabled) + m_ctx->RestoreState(); + + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoContext::NegotiateCryptoSessionKeyExchange( + ID3D11CryptoSession* pSession, + UINT DataSize, + void* pData) { + Logger::err("D3D11VideoContext::NegotiateCryptoSessionKeyExchange: Stub"); + return E_NOTIMPL; + } + + + void STDMETHODCALLTYPE D3D11VideoContext::EncryptionBlt( + ID3D11CryptoSession* pSession, + ID3D11Texture2D* pSrcSurface, + ID3D11Texture2D* pDstSurface, + UINT IVSize, + void* pIV) { + Logger::err("D3D11VideoContext::EncryptionBlt: Stub"); + } + + + void STDMETHODCALLTYPE D3D11VideoContext::DecryptionBlt( + ID3D11CryptoSession* pSession, + ID3D11Texture2D* pSrcSurface, + ID3D11Texture2D* pDstSurface, + D3D11_ENCRYPTED_BLOCK_INFO* pBlockInfo, + UINT KeySize, + const void* pKey, + UINT IVSize, + void* pIV) { + Logger::err("D3D11VideoContext::DecryptionBlt: Stub"); + } + + + void STDMETHODCALLTYPE D3D11VideoContext::StartSessionKeyRefresh( + ID3D11CryptoSession* pSession, + UINT RandomNumberSize, + void* pRandomNumber) { + Logger::err("D3D11VideoContext::StartSessionKeyRefresh: Stub"); + } + + + void STDMETHODCALLTYPE D3D11VideoContext::FinishSessionKeyRefresh( + ID3D11CryptoSession* pSession) { + Logger::err("D3D11VideoContext::FinishSessionKeyRefresh: Stub"); + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoContext::GetEncryptionBltKey( + ID3D11CryptoSession* pSession, + UINT KeySize, + void* pKey) { + Logger::err("D3D11VideoContext::GetEncryptionBltKey: Stub"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoContext::NegotiateAuthenticatedChannelKeyExchange( + ID3D11AuthenticatedChannel* pChannel, + UINT DataSize, + void* pData) { + Logger::err("D3D11VideoContext::NegotiateAuthenticatedChannelKeyExchange: Stub"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoContext::QueryAuthenticatedChannel( + ID3D11AuthenticatedChannel* pChannel, + UINT InputSize, + const void* pInput, + UINT OutputSize, + void* pOutput) { + Logger::err("D3D11VideoContext::QueryAuthenticatedChannel: Stub"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE D3D11VideoContext::ConfigureAuthenticatedChannel( + ID3D11AuthenticatedChannel* pChannel, + UINT InputSize, + const void* pInput, + D3D11_AUTHENTICATED_CONFIGURE_OUTPUT* pOutput) { + Logger::err("D3D11VideoContext::ConfigureAuthenticatedChannel: Stub"); + return E_NOTIMPL; + } + + + void D3D11VideoContext::ApplyColorMatrix(float pDst[3][4], const float pSrc[3][4]) { + float result[3][4]; + + for (uint32_t i = 0; i < 3; i++) { + for (uint32_t j = 0; j < 4; j++) { + result[i][j] = pSrc[i][0] * pDst[0][j] + + pSrc[i][1] * pDst[1][j] + + pSrc[i][2] * pDst[2][j] + + pSrc[i][3] * float(j == 3); + } + } + + memcpy(pDst, &result[0][0], sizeof(result)); + } + + + void D3D11VideoContext::ApplyYCbCrMatrix(float pColorMatrix[3][4], bool UseBt709) { + static const float pretransform[3][4] = { + { 0.0f, 1.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 1.0f, -0.5f }, + { 1.0f, 0.0f, 0.0f, -0.5f }, + }; + + static const float bt601[3][4] = { + { 1.0f, 0.000000f, 1.402000f, 0.0f }, + { 1.0f, -0.344136f, -0.714136f, 0.0f }, + { 1.0f, 1.772000f, 0.000000f, 0.0f }, + }; + + static const float bt709[3][4] = { + { 1.0f, 0.000000f, 1.574800f, 0.0f }, + { 1.0f, -0.187324f, -0.468124f, 0.0f }, + { 1.0f, 1.855600f, 0.000000f, 0.0f }, + }; + + ApplyColorMatrix(pColorMatrix, pretransform); + ApplyColorMatrix(pColorMatrix, UseBt709 ? bt709 : bt601); + } + + + void D3D11VideoContext::BindOutputView( + ID3D11VideoProcessorOutputView* pOutputView) { + auto dxvkView = static_cast(pOutputView)->GetView(); + + m_ctx->EmitCs([this, cView = dxvkView] (DxvkContext* ctx) { + DxvkRenderTargets rt; + rt.color[0].view = cView; + rt.color[0].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + ctx->bindRenderTargets(rt); + ctx->bindShader(VK_SHADER_STAGE_VERTEX_BIT, m_vs); + ctx->bindShader(VK_SHADER_STAGE_FRAGMENT_BIT, m_fs); + ctx->bindResourceBuffer(0, DxvkBufferSlice(m_ubo)); + + DxvkInputAssemblyState iaState; + iaState.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + iaState.primitiveRestart = VK_FALSE; + iaState.patchVertexCount = 0; + ctx->setInputAssemblyState(iaState); + }); + + VkExtent3D viewExtent = dxvkView->mipLevelExtent(0); + m_dstExtent = { viewExtent.width, viewExtent.height }; + } + + + void D3D11VideoContext::BlitStream( + const D3D11VideoProcessorStreamState* pStreamState, + const D3D11_VIDEO_PROCESSOR_STREAM* pStream) { + if (pStream->PastFrames || pStream->FutureFrames) + Logger::err("D3D11VideoContext: Ignoring non-zero PastFrames and FutureFrames"); + + if (pStream->OutputIndex) + Logger::err("D3D11VideoContext: Ignoring non-zero OutputIndex"); + + if (pStream->InputFrameOrField) + Logger::err("D3D11VideoContext: Ignoring non-zero InputFrameOrField"); + + auto view = static_cast(pStream->pInputSurface); + + if (view->NeedsCopy()) { + m_ctx->EmitCs([ + cDstImage = view->GetShadowCopy(), + cSrcImage = view->GetImage(), + cSrcLayers = view->GetImageSubresources() + ] (DxvkContext* ctx) { + VkImageSubresourceLayers cDstLayers; + cDstLayers.aspectMask = cSrcLayers.aspectMask; + cDstLayers.baseArrayLayer = 0; + cDstLayers.layerCount = cSrcLayers.layerCount; + cDstLayers.mipLevel = cSrcLayers.mipLevel; + + ctx->copyImage( + cDstImage, cDstLayers, VkOffset3D(), + cSrcImage, cSrcLayers, VkOffset3D(), + cDstImage->info().extent); + }); + } + + m_ctx->EmitCs([this, + cStreamState = *pStreamState, + cViews = view->GetViews(), + cIsYCbCr = view->IsYCbCr() + ] (DxvkContext* ctx) { + VkViewport viewport; + viewport.x = 0.0f; + viewport.y = 0.0f; + viewport.width = float(m_dstExtent.width); + viewport.height = float(m_dstExtent.height); + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + VkRect2D scissor; + scissor.offset = { 0, 0 }; + scissor.extent = m_dstExtent; + + if (cStreamState.dstRectEnabled) { + viewport.x = float(cStreamState.dstRect.left); + viewport.y = float(cStreamState.dstRect.top); + viewport.width = float(cStreamState.dstRect.right) - viewport.x; + viewport.height = float(cStreamState.dstRect.bottom) - viewport.y; + } + + UboData uboData = { }; + uboData.colorMatrix[0][0] = 1.0f; + uboData.colorMatrix[1][1] = 1.0f; + uboData.colorMatrix[2][2] = 1.0f; + uboData.coordMatrix[0][0] = 1.0f; + uboData.coordMatrix[1][1] = 1.0f; + uboData.yMin = 0.0f; + uboData.yMax = 1.0f; + + if (cIsYCbCr) + ApplyYCbCrMatrix(uboData.colorMatrix, cStreamState.colorSpace.YCbCr_Matrix); + + if (cStreamState.colorSpace.Nominal_Range) { + uboData.yMin = 0.0627451f; + uboData.yMax = 0.9215686f; + } + + DxvkBufferSliceHandle uboSlice = m_ubo->allocSlice(); + memcpy(uboSlice.mapPtr, &uboData, sizeof(uboData)); + + ctx->invalidateBuffer(m_ubo, uboSlice); + ctx->setViewports(1, &viewport, &scissor); + ctx->bindResourceSampler(1, m_sampler); + + for (uint32_t i = 0; i < cViews.size(); i++) + ctx->bindResourceView(2 + i, cViews[i], nullptr); + + ctx->draw(3, 1, 0, 0); + }); + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_video.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_video.h new file mode 100644 index 00000000000..85979eb8f96 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_video.h @@ -0,0 +1,612 @@ +#pragma once + +#include "d3d11_device.h" + +namespace dxvk { + + static constexpr uint32_t D3D11_VK_VIDEO_STREAM_COUNT = 8; + + class D3D11VideoProcessorEnumerator : public D3D11DeviceChild { + + public: + + D3D11VideoProcessorEnumerator( + D3D11Device* pDevice, + const D3D11_VIDEO_PROCESSOR_CONTENT_DESC& Desc); + + ~D3D11VideoProcessorEnumerator(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + HRESULT STDMETHODCALLTYPE GetVideoProcessorContentDesc( + D3D11_VIDEO_PROCESSOR_CONTENT_DESC* pContentDesc); + + HRESULT STDMETHODCALLTYPE CheckVideoProcessorFormat( + DXGI_FORMAT Format, + UINT* pFlags); + + HRESULT STDMETHODCALLTYPE GetVideoProcessorCaps( + D3D11_VIDEO_PROCESSOR_CAPS* pCaps); + + HRESULT STDMETHODCALLTYPE GetVideoProcessorRateConversionCaps( + UINT TypeIndex, + D3D11_VIDEO_PROCESSOR_RATE_CONVERSION_CAPS* pCaps); + + HRESULT STDMETHODCALLTYPE GetVideoProcessorCustomRate( + UINT TypeIndex, + UINT CustomRateIndex, + D3D11_VIDEO_PROCESSOR_CUSTOM_RATE* pRate); + + HRESULT STDMETHODCALLTYPE GetVideoProcessorFilterRange( + D3D11_VIDEO_PROCESSOR_FILTER Filter, + D3D11_VIDEO_PROCESSOR_FILTER_RANGE* pRange); + + private: + + D3D11_VIDEO_PROCESSOR_CONTENT_DESC m_desc; + + }; + + + struct D3D11VideoProcessorStreamState { + BOOL autoProcessingEnabled = TRUE; + BOOL dstRectEnabled = FALSE; + BOOL srcRectEnabled = FALSE; + BOOL rotationEnabled = FALSE; + RECT dstRect = RECT(); + RECT srcRect = RECT(); + D3D11_VIDEO_FRAME_FORMAT frameFormat = D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE; + D3D11_VIDEO_PROCESSOR_ROTATION rotation = D3D11_VIDEO_PROCESSOR_ROTATION_IDENTITY; + D3D11_VIDEO_PROCESSOR_COLOR_SPACE colorSpace = D3D11_VIDEO_PROCESSOR_COLOR_SPACE(); + }; + + struct D3D11VideoProcessorState { + BOOL outputStereoModeEnabled = FALSE; + BOOL outputBackgroundColorIsYCbCr = FALSE; + BOOL outputTargetRectEnabled = FALSE; + RECT outputTargetRect = RECT(); + D3D11_VIDEO_COLOR outputBackgroundColor = D3D11_VIDEO_COLOR(); + D3D11_VIDEO_PROCESSOR_COLOR_SPACE outputColorSpace = D3D11_VIDEO_PROCESSOR_COLOR_SPACE(); + }; + + class D3D11VideoProcessor : public D3D11DeviceChild { + + public: + + D3D11VideoProcessor( + D3D11Device* pDevice, + D3D11VideoProcessorEnumerator* pEnumerator, + UINT RateConversionIndex); + + ~D3D11VideoProcessor(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + void STDMETHODCALLTYPE GetContentDesc( + D3D11_VIDEO_PROCESSOR_CONTENT_DESC *pDesc); + + void STDMETHODCALLTYPE GetRateConversionCaps( + D3D11_VIDEO_PROCESSOR_RATE_CONVERSION_CAPS *pCaps); + + D3D11VideoProcessorState* GetState() { + return &m_state; + } + + D3D11VideoProcessorStreamState* GetStreamState(UINT StreamIndex) { + return StreamIndex < D3D11_VK_VIDEO_STREAM_COUNT + ? &m_streams[StreamIndex] + : nullptr; + } + + private: + + D3D11VideoProcessorEnumerator* m_enumerator; + uint32_t m_rateConversionIndex; + D3D11VideoProcessorState m_state; + D3D11VideoProcessorStreamState m_streams[D3D11_VK_VIDEO_STREAM_COUNT]; + + }; + + + + class D3D11VideoProcessorInputView : public D3D11DeviceChild { + + public: + + D3D11VideoProcessorInputView( + D3D11Device* pDevice, + ID3D11Resource* pResource, + const D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC& Desc); + + ~D3D11VideoProcessorInputView(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + void STDMETHODCALLTYPE GetResource( + ID3D11Resource** ppResource); + + void STDMETHODCALLTYPE GetDesc( + D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC* pDesc); + + const bool IsYCbCr() const { + return m_isYCbCr; + } + + const bool NeedsCopy() const { + return m_copy != nullptr; + } + + Rc GetImage() const { + return GetCommonTexture(m_resource.ptr())->GetImage(); + } + + VkImageSubresourceLayers GetImageSubresources() const { + return m_subresources; + } + + Rc GetShadowCopy() const { + return m_copy; + } + + std::array, 2> GetViews() const { + return m_views; + } + + private: + + Com m_resource; + D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC m_desc; + VkImageSubresourceLayers m_subresources; + Rc m_copy; + std::array, 2> m_views; + bool m_isYCbCr = false; + + static bool IsYCbCrFormat(DXGI_FORMAT Format); + + }; + + + + class D3D11VideoProcessorOutputView : public D3D11DeviceChild { + + public: + + D3D11VideoProcessorOutputView( + D3D11Device* pDevice, + ID3D11Resource* pResource, + const D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC& Desc); + + ~D3D11VideoProcessorOutputView(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + void STDMETHODCALLTYPE GetResource( + ID3D11Resource** ppResource); + + void STDMETHODCALLTYPE GetDesc( + D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC* pDesc); + + Rc GetView() const { + return m_view; + } + + private: + + Com m_resource; + D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC m_desc; + Rc m_view; + + }; + + + + class D3D11VideoContext : public ID3D11VideoContext { + + public: + + D3D11VideoContext( + D3D11ImmediateContext* pContext, + const Rc& Device); + + ~D3D11VideoContext(); + + ULONG STDMETHODCALLTYPE AddRef(); + + ULONG STDMETHODCALLTYPE Release(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + HRESULT STDMETHODCALLTYPE GetPrivateData( + REFGUID Name, + UINT* pDataSize, + void* pData); + + HRESULT STDMETHODCALLTYPE SetPrivateData( + REFGUID Name, + UINT DataSize, + const void* pData); + + HRESULT STDMETHODCALLTYPE SetPrivateDataInterface( + REFGUID Name, + const IUnknown* pUnknown); + + void STDMETHODCALLTYPE GetDevice( + ID3D11Device** ppDevice); + + HRESULT STDMETHODCALLTYPE GetDecoderBuffer( + ID3D11VideoDecoder* pDecoder, + D3D11_VIDEO_DECODER_BUFFER_TYPE Type, + UINT* BufferSize, + void** ppBuffer); + + HRESULT STDMETHODCALLTYPE ReleaseDecoderBuffer( + ID3D11VideoDecoder* pDecoder, + D3D11_VIDEO_DECODER_BUFFER_TYPE Type); + + HRESULT STDMETHODCALLTYPE DecoderBeginFrame( + ID3D11VideoDecoder* pDecoder, + ID3D11VideoDecoderOutputView* pView, + UINT KeySize, + const void* pKey); + + HRESULT STDMETHODCALLTYPE DecoderEndFrame( + ID3D11VideoDecoder* pDecoder); + + HRESULT STDMETHODCALLTYPE SubmitDecoderBuffers( + ID3D11VideoDecoder* pDecoder, + UINT BufferCount, + const D3D11_VIDEO_DECODER_BUFFER_DESC* pBufferDescs); + + HRESULT STDMETHODCALLTYPE DecoderExtension( + ID3D11VideoDecoder* pDecoder, + const D3D11_VIDEO_DECODER_EXTENSION* pExtension); + + void STDMETHODCALLTYPE VideoProcessorSetOutputTargetRect( + ID3D11VideoProcessor* pVideoProcessor, + BOOL Enable, + const RECT* pRect); + + void STDMETHODCALLTYPE VideoProcessorSetOutputBackgroundColor( + ID3D11VideoProcessor* pVideoProcessor, + BOOL YCbCr, + const D3D11_VIDEO_COLOR* pColor); + + void STDMETHODCALLTYPE VideoProcessorSetOutputColorSpace( + ID3D11VideoProcessor* pVideoProcessor, + const D3D11_VIDEO_PROCESSOR_COLOR_SPACE *pColorSpace); + + void STDMETHODCALLTYPE VideoProcessorSetOutputAlphaFillMode( + ID3D11VideoProcessor* pVideoProcessor, + D3D11_VIDEO_PROCESSOR_ALPHA_FILL_MODE AlphaFillMode, + UINT StreamIndex); + + void STDMETHODCALLTYPE VideoProcessorSetOutputConstriction( + ID3D11VideoProcessor* pVideoProcessor, + BOOL Enable, + SIZE Size); + + void STDMETHODCALLTYPE VideoProcessorSetOutputStereoMode( + ID3D11VideoProcessor* pVideoProcessor, + BOOL Enable); + + HRESULT STDMETHODCALLTYPE VideoProcessorSetOutputExtension( + ID3D11VideoProcessor* pVideoProcessor, + const GUID* pExtensionGuid, + UINT DataSize, + void* pData); + + void STDMETHODCALLTYPE VideoProcessorSetStreamFrameFormat( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + D3D11_VIDEO_FRAME_FORMAT Format); + + void STDMETHODCALLTYPE VideoProcessorSetStreamColorSpace( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + const D3D11_VIDEO_PROCESSOR_COLOR_SPACE *pColorSpace); + + void STDMETHODCALLTYPE VideoProcessorSetStreamOutputRate( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + D3D11_VIDEO_PROCESSOR_OUTPUT_RATE Rate, + BOOL Repeat, + const DXGI_RATIONAL* CustomRate); + + void STDMETHODCALLTYPE VideoProcessorSetStreamSourceRect( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + BOOL Enable, + const RECT* pRect); + + void STDMETHODCALLTYPE VideoProcessorSetStreamDestRect( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + BOOL Enable, + const RECT* pRect); + + void STDMETHODCALLTYPE VideoProcessorSetStreamAlpha( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + BOOL Enable, + FLOAT Alpha); + + void STDMETHODCALLTYPE VideoProcessorSetStreamPalette( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + UINT EntryCount, + const UINT* pEntries); + + void STDMETHODCALLTYPE VideoProcessorSetStreamPixelAspectRatio( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + BOOL Enable, + const DXGI_RATIONAL* pSrcAspectRatio, + const DXGI_RATIONAL* pDstAspectRatio); + + void STDMETHODCALLTYPE VideoProcessorSetStreamLumaKey( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + BOOL Enable, + FLOAT Lower, + FLOAT Upper); + + void STDMETHODCALLTYPE VideoProcessorSetStreamStereoFormat( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + BOOL Enable, + D3D11_VIDEO_PROCESSOR_STEREO_FORMAT Format, + BOOL LeftViewFrame0, + BOOL BaseViewFrame0, + D3D11_VIDEO_PROCESSOR_STEREO_FLIP_MODE FlipMode, + int MonoOffset); + + void STDMETHODCALLTYPE VideoProcessorSetStreamAutoProcessingMode( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + BOOL Enable); + + void STDMETHODCALLTYPE VideoProcessorSetStreamFilter( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + D3D11_VIDEO_PROCESSOR_FILTER Filter, + BOOL Enable, + int Level); + + HRESULT STDMETHODCALLTYPE VideoProcessorSetStreamExtension( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + const GUID* pExtensionGuid, + UINT DataSize, + void* pData); + + void STDMETHODCALLTYPE VideoProcessorSetStreamRotation( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + BOOL Enable, + D3D11_VIDEO_PROCESSOR_ROTATION Rotation); + + void STDMETHODCALLTYPE VideoProcessorGetOutputTargetRect( + ID3D11VideoProcessor* pVideoProcessor, + BOOL* pEnabled, + RECT* pRect); + + void STDMETHODCALLTYPE VideoProcessorGetOutputBackgroundColor( + ID3D11VideoProcessor* pVideoProcessor, + BOOL* pYCbCr, + D3D11_VIDEO_COLOR* pColor); + + void STDMETHODCALLTYPE VideoProcessorGetOutputColorSpace( + ID3D11VideoProcessor* pVideoProcessor, + D3D11_VIDEO_PROCESSOR_COLOR_SPACE* pColorSpace); + + void STDMETHODCALLTYPE VideoProcessorGetOutputAlphaFillMode( + ID3D11VideoProcessor* pVideoProcessor, + D3D11_VIDEO_PROCESSOR_ALPHA_FILL_MODE* pAlphaFillMode, + UINT* pStreamIndex); + + void STDMETHODCALLTYPE VideoProcessorGetOutputConstriction( + ID3D11VideoProcessor* pVideoProcessor, + BOOL* pEnabled, + SIZE* pSize); + + void STDMETHODCALLTYPE VideoProcessorGetOutputStereoMode( + ID3D11VideoProcessor* pVideoProcessor, + BOOL* pEnabled); + + HRESULT STDMETHODCALLTYPE VideoProcessorGetOutputExtension( + ID3D11VideoProcessor* pVideoProcessor, + const GUID* pExtensionGuid, + UINT DataSize, + void* pData); + + void STDMETHODCALLTYPE VideoProcessorGetStreamFrameFormat( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + D3D11_VIDEO_FRAME_FORMAT* pFormat); + + void STDMETHODCALLTYPE VideoProcessorGetStreamColorSpace( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + D3D11_VIDEO_PROCESSOR_COLOR_SPACE* pColorSpace); + + void STDMETHODCALLTYPE VideoProcessorGetStreamOutputRate( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + D3D11_VIDEO_PROCESSOR_OUTPUT_RATE* pRate, + BOOL* pRepeat, + DXGI_RATIONAL* pCustomRate); + + void STDMETHODCALLTYPE VideoProcessorGetStreamSourceRect( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + BOOL* pEnabled, + RECT* pRect); + + void STDMETHODCALLTYPE VideoProcessorGetStreamDestRect( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + BOOL* pEnabled, + RECT* pRect); + + void STDMETHODCALLTYPE VideoProcessorGetStreamAlpha( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + BOOL* pEnabled, + FLOAT* pAlpha); + + void STDMETHODCALLTYPE VideoProcessorGetStreamPalette( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + UINT EntryCount, + UINT* pEntries); + + void STDMETHODCALLTYPE VideoProcessorGetStreamPixelAspectRatio( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + BOOL* pEnabled, + DXGI_RATIONAL* pSrcAspectRatio, + DXGI_RATIONAL* pDstAspectRatio); + + void STDMETHODCALLTYPE VideoProcessorGetStreamLumaKey( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + BOOL* pEnabled, + FLOAT* pLower, + FLOAT* pUpper); + + void STDMETHODCALLTYPE VideoProcessorGetStreamStereoFormat( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + BOOL* pEnabled, + D3D11_VIDEO_PROCESSOR_STEREO_FORMAT* pFormat, + BOOL* pLeftViewFrame0, + BOOL* pBaseViewFrame0, + D3D11_VIDEO_PROCESSOR_STEREO_FLIP_MODE* pFlipMode, + int* pMonoOffset); + + void STDMETHODCALLTYPE VideoProcessorGetStreamAutoProcessingMode( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + BOOL* pEnabled); + + void STDMETHODCALLTYPE VideoProcessorGetStreamFilter( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + D3D11_VIDEO_PROCESSOR_FILTER Filter, + BOOL* pEnabled, + int* pLevel); + + HRESULT STDMETHODCALLTYPE VideoProcessorGetStreamExtension( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + const GUID* pExtensionGuid, + UINT DataSize, + void* pData); + + void STDMETHODCALLTYPE VideoProcessorGetStreamRotation( + ID3D11VideoProcessor* pVideoProcessor, + UINT StreamIndex, + BOOL* pEnable, + D3D11_VIDEO_PROCESSOR_ROTATION* pRotation); + + HRESULT STDMETHODCALLTYPE VideoProcessorBlt( + ID3D11VideoProcessor* pVideoProcessor, + ID3D11VideoProcessorOutputView* pOutputView, + UINT FrameIdx, + UINT StreamCount, + const D3D11_VIDEO_PROCESSOR_STREAM* pStreams); + + HRESULT STDMETHODCALLTYPE NegotiateCryptoSessionKeyExchange( + ID3D11CryptoSession* pSession, + UINT DataSize, + void* pData); + + void STDMETHODCALLTYPE EncryptionBlt( + ID3D11CryptoSession* pSession, + ID3D11Texture2D* pSrcSurface, + ID3D11Texture2D* pDstSurface, + UINT IVSize, + void* pIV); + + void STDMETHODCALLTYPE DecryptionBlt( + ID3D11CryptoSession* pSession, + ID3D11Texture2D* pSrcSurface, + ID3D11Texture2D* pDstSurface, + D3D11_ENCRYPTED_BLOCK_INFO* pBlockInfo, + UINT KeySize, + const void* pKey, + UINT IVSize, + void* pIV); + + void STDMETHODCALLTYPE StartSessionKeyRefresh( + ID3D11CryptoSession* pSession, + UINT RandomNumberSize, + void* pRandomNumber); + + void STDMETHODCALLTYPE FinishSessionKeyRefresh( + ID3D11CryptoSession* pSession); + + HRESULT STDMETHODCALLTYPE GetEncryptionBltKey( + ID3D11CryptoSession* pSession, + UINT KeySize, + void* pKey); + + HRESULT STDMETHODCALLTYPE NegotiateAuthenticatedChannelKeyExchange( + ID3D11AuthenticatedChannel* pChannel, + UINT DataSize, + void* pData); + + HRESULT STDMETHODCALLTYPE QueryAuthenticatedChannel( + ID3D11AuthenticatedChannel* pChannel, + UINT InputSize, + const void* pInput, + UINT OutputSize, + void* pOutput); + + HRESULT STDMETHODCALLTYPE ConfigureAuthenticatedChannel( + ID3D11AuthenticatedChannel* pChannel, + UINT InputSize, + const void* pInput, + D3D11_AUTHENTICATED_CONFIGURE_OUTPUT* pOutput); + + private: + + struct alignas(16) UboData { + float colorMatrix[3][4]; + float coordMatrix[3][2]; + float yMin, yMax; + }; + + D3D11ImmediateContext* m_ctx; + + Rc m_sampler; + Rc m_vs; + Rc m_fs; + Rc m_ubo; + + VkExtent2D m_dstExtent = { 0u, 0u }; + + void ApplyColorMatrix(float pDst[3][4], const float pSrc[3][4]); + + void ApplyYCbCrMatrix(float pColorMatrix[3][4], bool UseBt709); + + void BindOutputView( + ID3D11VideoProcessorOutputView* pOutputView); + + void BlitStream( + const D3D11VideoProcessorStreamState* pStreamState, + const D3D11_VIDEO_PROCESSOR_STREAM* pStream); + + }; + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_view.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_view.h new file mode 100644 index 00000000000..50fcef102ce --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_view.h @@ -0,0 +1,81 @@ +#pragma once + +#include "d3d11_include.h" + +namespace dxvk { + + /** + * \brief Buffer view info + * + * Stores the byte range covered + * by a buffer view. + */ + struct D3D11_VK_BUFFER_VIEW_INFO { + VkDeviceSize Offset; + VkDeviceSize Length; + }; + + /** + * \brief Image view info + * + * Stores the subresource range + * covered by an image view. + */ + struct D3D11_VK_IMAGE_VIEW_INFO { + VkImageAspectFlags Aspects; + uint32_t MinLevel; + uint32_t MinLayer; + uint32_t NumLevels; + uint32_t NumLayers; + }; + + /** + * \brief Common view info + * + * Stores a pointer to the resource as + * well as the type-specific range that + * is affected by the view. + */ + struct D3D11_VK_VIEW_INFO { + ID3D11Resource* pResource; + D3D11_RESOURCE_DIMENSION Dimension; + UINT BindFlags; + union { + D3D11_VK_BUFFER_VIEW_INFO Buffer; + D3D11_VK_IMAGE_VIEW_INFO Image; + }; + }; + + /** + * \brief Checks whether two views overlap + * + * Overlapping views may conflict in case + * one or both views are used for writing. + * \param [in] a First view to check + * \param [in] b Second view to check + * \returns \c true if the views overlap + */ + inline bool CheckViewOverlap(const D3D11_VK_VIEW_INFO& a, const D3D11_VK_VIEW_INFO b) { + if (likely(a.pResource != b.pResource)) + return false; + + if (a.Dimension == D3D11_RESOURCE_DIMENSION_BUFFER) { + // Just check whether the buffer ranges overlap + return (a.Buffer.Offset < b.Buffer.Offset + b.Buffer.Length) + && (a.Buffer.Offset + a.Buffer.Length > b.Buffer.Offset); + } else { + // Check whether the subresource ranges overlap + return (a.Image.Aspects & b.Image.Aspects) + && (a.Image.MinLevel < b.Image.MinLevel + b.Image.NumLevels) + && (a.Image.MinLayer < b.Image.MinLayer + b.Image.NumLayers) + && (a.Image.MinLevel + a.Image.NumLevels > b.Image.MinLevel) + && (a.Image.MinLayer + a.Image.NumLayers > b.Image.MinLayer); + } + } + + template + bool CheckViewOverlap(const T1* a, const T2* b) { + return a && b && CheckViewOverlap(a->GetViewInfo(), b->GetViewInfo()); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_view_dsv.cpp b/utils/dxvk-1.10.3/src/d3d11/d3d11_view_dsv.cpp new file mode 100644 index 00000000000..f0520c64523 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_view_dsv.cpp @@ -0,0 +1,280 @@ +#include "d3d11_device.h" +#include "d3d11_buffer.h" +#include "d3d11_resource.h" +#include "d3d11_texture.h" +#include "d3d11_view_dsv.h" + +namespace dxvk { + + D3D11DepthStencilView::D3D11DepthStencilView( + D3D11Device* pDevice, + ID3D11Resource* pResource, + const D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc) + : D3D11DeviceChild(pDevice), + m_resource(pResource), m_desc(*pDesc), m_d3d10(this) { + ResourceAddRefPrivate(m_resource); + + D3D11_COMMON_RESOURCE_DESC resourceDesc; + GetCommonResourceDesc(pResource, &resourceDesc); + + DxvkImageViewCreateInfo viewInfo; + viewInfo.format = pDevice->LookupFormat(pDesc->Format, DXGI_VK_FORMAT_MODE_DEPTH).Format; + viewInfo.aspect = imageFormatInfo(viewInfo.format)->aspectMask; + viewInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + + switch (pDesc->ViewDimension) { + case D3D11_DSV_DIMENSION_TEXTURE1D: + viewInfo.type = VK_IMAGE_VIEW_TYPE_1D; + viewInfo.minLevel = pDesc->Texture1D.MipSlice; + viewInfo.numLevels = 1; + viewInfo.minLayer = 0; + viewInfo.numLayers = 1; + break; + + case D3D11_DSV_DIMENSION_TEXTURE1DARRAY: + viewInfo.type = VK_IMAGE_VIEW_TYPE_1D_ARRAY; + viewInfo.minLevel = pDesc->Texture1DArray.MipSlice; + viewInfo.numLevels = 1; + viewInfo.minLayer = pDesc->Texture1DArray.FirstArraySlice; + viewInfo.numLayers = pDesc->Texture1DArray.ArraySize; + break; + + case D3D11_DSV_DIMENSION_TEXTURE2D: + viewInfo.type = VK_IMAGE_VIEW_TYPE_2D; + viewInfo.minLevel = pDesc->Texture2D.MipSlice; + viewInfo.numLevels = 1; + viewInfo.minLayer = 0; + viewInfo.numLayers = 1; + break; + + case D3D11_DSV_DIMENSION_TEXTURE2DARRAY: + viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; + viewInfo.minLevel = pDesc->Texture2DArray.MipSlice; + viewInfo.numLevels = 1; + viewInfo.minLayer = pDesc->Texture2DArray.FirstArraySlice; + viewInfo.numLayers = pDesc->Texture2DArray.ArraySize; + break; + + case D3D11_DSV_DIMENSION_TEXTURE2DMS: + viewInfo.type = VK_IMAGE_VIEW_TYPE_2D; + viewInfo.minLevel = 0; + viewInfo.numLevels = 1; + viewInfo.minLayer = 0; + viewInfo.numLayers = 1; + break; + + case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY: + viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; + viewInfo.minLevel = 0; + viewInfo.numLevels = 1; + viewInfo.minLayer = pDesc->Texture2DMSArray.FirstArraySlice; + viewInfo.numLayers = pDesc->Texture2DMSArray.ArraySize; + break; + + default: + throw DxvkError("D3D11: Invalid view dimension for DSV"); + } + + // Normalize view type so that we won't accidentally + // bind 2D array views and 2D views at the same time + if (viewInfo.numLayers == 1) { + if (viewInfo.type == VK_IMAGE_VIEW_TYPE_1D_ARRAY) viewInfo.type = VK_IMAGE_VIEW_TYPE_1D; + if (viewInfo.type == VK_IMAGE_VIEW_TYPE_2D_ARRAY) viewInfo.type = VK_IMAGE_VIEW_TYPE_2D; + } + + // Populate view info struct + m_info.pResource = pResource; + m_info.Dimension = resourceDesc.Dim; + m_info.BindFlags = resourceDesc.BindFlags; + m_info.Image.Aspects = viewInfo.aspect; + m_info.Image.MinLevel = viewInfo.minLevel; + m_info.Image.MinLayer = viewInfo.minLayer; + m_info.Image.NumLevels = viewInfo.numLevels; + m_info.Image.NumLayers = viewInfo.numLayers; + + if (m_desc.Flags & D3D11_DSV_READ_ONLY_DEPTH) + m_info.Image.Aspects &= ~VK_IMAGE_ASPECT_DEPTH_BIT; + + if (m_desc.Flags & D3D11_DSV_READ_ONLY_STENCIL) + m_info.Image.Aspects &= ~VK_IMAGE_ASPECT_STENCIL_BIT; + + // Create the underlying image view object + m_view = pDevice->GetDXVKDevice()->createImageView( + GetCommonTexture(pResource)->GetImage(), viewInfo); + } + + + D3D11DepthStencilView::~D3D11DepthStencilView() { + ResourceReleasePrivate(m_resource); + } + + + HRESULT STDMETHODCALLTYPE D3D11DepthStencilView::QueryInterface(REFIID riid, void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(ID3D11DeviceChild) + || riid == __uuidof(ID3D11View) + || riid == __uuidof(ID3D11DepthStencilView)) { + *ppvObject = ref(this); + return S_OK; + } + + if (riid == __uuidof(ID3D10DeviceChild) + || riid == __uuidof(ID3D10View) + || riid == __uuidof(ID3D10DepthStencilView)) { + *ppvObject = ref(this); + return S_OK; + } + + Logger::warn("D3D11DepthStencilView::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + void STDMETHODCALLTYPE D3D11DepthStencilView::GetResource(ID3D11Resource** ppResource) { + *ppResource = ref(m_resource); + } + + + void STDMETHODCALLTYPE D3D11DepthStencilView::GetDesc(D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc) { + *pDesc = m_desc; + } + + + HRESULT D3D11DepthStencilView::GetDescFromResource( + ID3D11Resource* pResource, + D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc) { + D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN; + pResource->GetType(&resourceDim); + pDesc->Flags = 0; + + switch (resourceDim) { + case D3D11_RESOURCE_DIMENSION_TEXTURE1D: { + D3D11_TEXTURE1D_DESC resourceDesc; + static_cast(pResource)->GetDesc(&resourceDesc); + + pDesc->Format = resourceDesc.Format; + + if (resourceDesc.ArraySize == 1) { + pDesc->ViewDimension = D3D11_DSV_DIMENSION_TEXTURE1D; + pDesc->Texture1D.MipSlice = 0; + } else { + pDesc->ViewDimension = D3D11_DSV_DIMENSION_TEXTURE1DARRAY; + pDesc->Texture1DArray.MipSlice = 0; + pDesc->Texture1DArray.FirstArraySlice = 0; + pDesc->Texture1DArray.ArraySize = resourceDesc.ArraySize; + } + } return S_OK; + + case D3D11_RESOURCE_DIMENSION_TEXTURE2D: { + D3D11_TEXTURE2D_DESC resourceDesc; + static_cast(pResource)->GetDesc(&resourceDesc); + + pDesc->Format = resourceDesc.Format; + + if (resourceDesc.SampleDesc.Count == 1) { + if (resourceDesc.ArraySize == 1) { + pDesc->ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + pDesc->Texture2D.MipSlice = 0; + } else { + pDesc->ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; + pDesc->Texture2DArray.MipSlice = 0; + pDesc->Texture2DArray.FirstArraySlice = 0; + pDesc->Texture2DArray.ArraySize = resourceDesc.ArraySize; + } + } else { + if (resourceDesc.ArraySize == 1) { + pDesc->ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS; + } else { + pDesc->ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY; + pDesc->Texture2DMSArray.FirstArraySlice = 0; + pDesc->Texture2DMSArray.ArraySize = resourceDesc.ArraySize; + } + } + } return S_OK; + + default: + Logger::err(str::format( + "D3D11: Unsupported dimension for depth stencil view: ", + resourceDim)); + return E_INVALIDARG; + } + } + + + HRESULT D3D11DepthStencilView::NormalizeDesc( + ID3D11Resource* pResource, + D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc) { + D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN; + pResource->GetType(&resourceDim); + + DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN; + uint32_t numLayers = 0; + + switch (resourceDim) { + case D3D11_RESOURCE_DIMENSION_TEXTURE1D: { + D3D11_TEXTURE1D_DESC resourceDesc; + static_cast(pResource)->GetDesc(&resourceDesc); + + if (pDesc->ViewDimension != D3D11_DSV_DIMENSION_TEXTURE1D + && pDesc->ViewDimension != D3D11_DSV_DIMENSION_TEXTURE1DARRAY) { + Logger::err("D3D11: Incompatible view dimension for Texture1D"); + return E_INVALIDARG; + } + + format = resourceDesc.Format; + numLayers = resourceDesc.ArraySize; + } break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE2D: { + D3D11_TEXTURE2D_DESC resourceDesc; + static_cast(pResource)->GetDesc(&resourceDesc); + + if (pDesc->ViewDimension != D3D11_DSV_DIMENSION_TEXTURE2D + && pDesc->ViewDimension != D3D11_DSV_DIMENSION_TEXTURE2DARRAY + && pDesc->ViewDimension != D3D11_DSV_DIMENSION_TEXTURE2DMS + && pDesc->ViewDimension != D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY) { + Logger::err("D3D11: Incompatible view dimension for Texture2D"); + return E_INVALIDARG; + } + + format = resourceDesc.Format; + numLayers = resourceDesc.ArraySize; + } break; + + default: + return E_INVALIDARG; + } + + if (pDesc->Format == DXGI_FORMAT_UNKNOWN) + pDesc->Format = format; + + switch (pDesc->ViewDimension) { + case D3D11_DSV_DIMENSION_TEXTURE1DARRAY: + if (pDesc->Texture1DArray.ArraySize > numLayers - pDesc->Texture1DArray.FirstArraySlice) + pDesc->Texture1DArray.ArraySize = numLayers - pDesc->Texture1DArray.FirstArraySlice; + break; + + case D3D11_DSV_DIMENSION_TEXTURE2DARRAY: + if (pDesc->Texture2DArray.ArraySize > numLayers - pDesc->Texture2DArray.FirstArraySlice) + pDesc->Texture2DArray.ArraySize = numLayers - pDesc->Texture2DArray.FirstArraySlice; + break; + + case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY: + if (pDesc->Texture2DMSArray.ArraySize > numLayers - pDesc->Texture2DMSArray.FirstArraySlice) + pDesc->Texture2DMSArray.ArraySize = numLayers - pDesc->Texture2DMSArray.FirstArraySlice; + break; + + default: + break; + } + + return S_OK; + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_view_dsv.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_view_dsv.h new file mode 100644 index 00000000000..41b6fcb1a07 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_view_dsv.h @@ -0,0 +1,98 @@ +#pragma once + +#include "../dxvk/dxvk_device.h" + +#include "../d3d10/d3d10_view_dsv.h" + +#include "d3d11_device_child.h" +#include "d3d11_view.h" + +namespace dxvk { + + class D3D11Device; + + /** + * \brief Depth-stencil view + * + * Unordered access views are special in that they can + * have counters, which can be used inside shaders to + * atomically append or consume structures. + */ + class D3D11DepthStencilView : public D3D11DeviceChild { + + public: + + D3D11DepthStencilView( + D3D11Device* pDevice, + ID3D11Resource* pResource, + const D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc); + + ~D3D11DepthStencilView(); + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) final; + + void STDMETHODCALLTYPE GetResource(ID3D11Resource** ppResource) final; + + void STDMETHODCALLTYPE GetDesc(D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc) final; + + const D3D11_VK_VIEW_INFO& GetViewInfo() const { + return m_info; + } + + D3D11_RESOURCE_DIMENSION GetResourceType() const { + D3D11_RESOURCE_DIMENSION type; + m_resource->GetType(&type); + return type; + } + + Rc GetImageView() const { + return m_view; + } + + VkImageLayout GetRenderLayout() const { + if (m_view->imageInfo().tiling == VK_IMAGE_TILING_OPTIMAL) { + switch (m_desc.Flags & (D3D11_DSV_READ_ONLY_DEPTH | D3D11_DSV_READ_ONLY_STENCIL)) { + default: // case 0 + return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + case D3D11_DSV_READ_ONLY_DEPTH: + return VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR; + case D3D11_DSV_READ_ONLY_STENCIL: + return VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR; + case D3D11_DSV_READ_ONLY_DEPTH | D3D11_DSV_READ_ONLY_STENCIL: + return VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; + } + } else { + return VK_IMAGE_LAYOUT_GENERAL; + } + } + + VkImageAspectFlags GetWritableAspectMask() const { + VkImageAspectFlags mask = m_view->formatInfo()->aspectMask; + if (m_desc.Flags & D3D11_DSV_READ_ONLY_DEPTH) mask &= ~VK_IMAGE_ASPECT_DEPTH_BIT; + if (m_desc.Flags & D3D11_DSV_READ_ONLY_STENCIL) mask &= ~VK_IMAGE_ASPECT_STENCIL_BIT; + return mask; + } + + D3D10DepthStencilView* GetD3D10Iface() { + return &m_d3d10; + } + + static HRESULT GetDescFromResource( + ID3D11Resource* pResource, + D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc); + + static HRESULT NormalizeDesc( + ID3D11Resource* pResource, + D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc); + + private: + + ID3D11Resource* m_resource; + D3D11_DEPTH_STENCIL_VIEW_DESC m_desc; + D3D11_VK_VIEW_INFO m_info; + Rc m_view; + D3D10DepthStencilView m_d3d10; + + }; + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_view_rtv.cpp b/utils/dxvk-1.10.3/src/d3d11/d3d11_view_rtv.cpp new file mode 100644 index 00000000000..86460502afb --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_view_rtv.cpp @@ -0,0 +1,440 @@ +#include "d3d11_device.h" +#include "d3d11_buffer.h" +#include "d3d11_resource.h" +#include "d3d11_texture.h" +#include "d3d11_view_rtv.h" + +namespace dxvk { + + D3D11RenderTargetView::D3D11RenderTargetView( + D3D11Device* pDevice, + ID3D11Resource* pResource, + const D3D11_RENDER_TARGET_VIEW_DESC1* pDesc) + : D3D11DeviceChild(pDevice), + m_resource(pResource), m_desc(*pDesc), m_d3d10(this) { + ResourceAddRefPrivate(m_resource); + + auto texture = GetCommonTexture(pResource); + + D3D11_COMMON_RESOURCE_DESC resourceDesc; + GetCommonResourceDesc(pResource, &resourceDesc); + + DXGI_VK_FORMAT_INFO formatInfo = pDevice->LookupFormat( + pDesc->Format, DXGI_VK_FORMAT_MODE_COLOR); + + DxvkImageViewCreateInfo viewInfo; + viewInfo.format = formatInfo.Format; + viewInfo.aspect = imageFormatInfo(viewInfo.format)->aspectMask; + viewInfo.swizzle = formatInfo.Swizzle; + viewInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + + switch (pDesc->ViewDimension) { + case D3D11_RTV_DIMENSION_TEXTURE1D: + viewInfo.type = VK_IMAGE_VIEW_TYPE_1D; + viewInfo.minLevel = pDesc->Texture1D.MipSlice; + viewInfo.numLevels = 1; + viewInfo.minLayer = 0; + viewInfo.numLayers = 1; + break; + + case D3D11_RTV_DIMENSION_TEXTURE1DARRAY: + viewInfo.type = VK_IMAGE_VIEW_TYPE_1D_ARRAY; + viewInfo.minLevel = pDesc->Texture1DArray.MipSlice; + viewInfo.numLevels = 1; + viewInfo.minLayer = pDesc->Texture1DArray.FirstArraySlice; + viewInfo.numLayers = pDesc->Texture1DArray.ArraySize; + break; + + case D3D11_RTV_DIMENSION_TEXTURE2D: + viewInfo.type = VK_IMAGE_VIEW_TYPE_2D; + viewInfo.minLevel = pDesc->Texture2D.MipSlice; + viewInfo.numLevels = 1; + viewInfo.minLayer = 0; + viewInfo.numLayers = 1; + break; + + case D3D11_RTV_DIMENSION_TEXTURE2DARRAY: + viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; + viewInfo.minLevel = pDesc->Texture2DArray.MipSlice; + viewInfo.numLevels = 1; + viewInfo.minLayer = pDesc->Texture2DArray.FirstArraySlice; + viewInfo.numLayers = pDesc->Texture2DArray.ArraySize; + break; + + case D3D11_RTV_DIMENSION_TEXTURE2DMS: + viewInfo.type = VK_IMAGE_VIEW_TYPE_2D; + viewInfo.minLevel = 0; + viewInfo.numLevels = 1; + viewInfo.minLayer = 0; + viewInfo.numLayers = 1; + break; + + case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY: + viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; + viewInfo.minLevel = 0; + viewInfo.numLevels = 1; + viewInfo.minLayer = pDesc->Texture2DMSArray.FirstArraySlice; + viewInfo.numLayers = pDesc->Texture2DMSArray.ArraySize; + break; + + case D3D11_RTV_DIMENSION_TEXTURE3D: + viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; + viewInfo.minLevel = pDesc->Texture3D.MipSlice; + viewInfo.numLevels = 1; + viewInfo.minLayer = pDesc->Texture3D.FirstWSlice; + viewInfo.numLayers = pDesc->Texture3D.WSize; + break; + + default: + throw DxvkError("D3D11: Invalid view dimension for RTV"); + } + + if (texture->GetPlaneCount() > 1) + viewInfo.aspect = vk::getPlaneAspect(GetPlaneSlice(pDesc)); + + // Normalize view type so that we won't accidentally + // bind 2D array views and 2D views at the same time + if (viewInfo.numLayers == 1) { + if (viewInfo.type == VK_IMAGE_VIEW_TYPE_1D_ARRAY) viewInfo.type = VK_IMAGE_VIEW_TYPE_1D; + if (viewInfo.type == VK_IMAGE_VIEW_TYPE_2D_ARRAY) viewInfo.type = VK_IMAGE_VIEW_TYPE_2D; + } + + // Populate view info struct + m_info.pResource = pResource; + m_info.Dimension = resourceDesc.Dim; + m_info.BindFlags = resourceDesc.BindFlags; + m_info.Image.Aspects = viewInfo.aspect; + m_info.Image.MinLevel = viewInfo.minLevel; + m_info.Image.MinLayer = viewInfo.minLayer; + m_info.Image.NumLevels = viewInfo.numLevels; + m_info.Image.NumLayers = viewInfo.numLayers; + + // Create the underlying image view object + m_view = pDevice->GetDXVKDevice()->createImageView(texture->GetImage(), viewInfo); + } + + + D3D11RenderTargetView::~D3D11RenderTargetView() { + ResourceReleasePrivate(m_resource); + } + + + HRESULT STDMETHODCALLTYPE D3D11RenderTargetView::QueryInterface(REFIID riid, void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(ID3D11DeviceChild) + || riid == __uuidof(ID3D11View) + || riid == __uuidof(ID3D11RenderTargetView) + || riid == __uuidof(ID3D11RenderTargetView1)) { + *ppvObject = ref(this); + return S_OK; + } + + if (riid == __uuidof(ID3D10DeviceChild) + || riid == __uuidof(ID3D10View) + || riid == __uuidof(ID3D10RenderTargetView)) { + *ppvObject = ref(this); + return S_OK; + } + + Logger::warn("D3D11RenderTargetView::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + void STDMETHODCALLTYPE D3D11RenderTargetView::GetResource(ID3D11Resource** ppResource) { + *ppResource = ref(m_resource); + } + + + void STDMETHODCALLTYPE D3D11RenderTargetView::GetDesc(D3D11_RENDER_TARGET_VIEW_DESC* pDesc) { + pDesc->Format = m_desc.Format; + pDesc->ViewDimension = m_desc.ViewDimension; + + switch (m_desc.ViewDimension) { + case D3D11_RTV_DIMENSION_UNKNOWN: + break; + + case D3D11_RTV_DIMENSION_BUFFER: + pDesc->Buffer = m_desc.Buffer; + break; + + case D3D11_RTV_DIMENSION_TEXTURE1D: + pDesc->Texture1D = m_desc.Texture1D; + break; + + case D3D11_RTV_DIMENSION_TEXTURE1DARRAY: + pDesc->Texture1DArray = m_desc.Texture1DArray; + break; + + case D3D11_RTV_DIMENSION_TEXTURE2D: + pDesc->Texture2D.MipSlice = m_desc.Texture2D.MipSlice; + break; + + case D3D11_RTV_DIMENSION_TEXTURE2DARRAY: + pDesc->Texture2DArray.MipSlice = m_desc.Texture2DArray.MipSlice; + pDesc->Texture2DArray.FirstArraySlice = m_desc.Texture2DArray.FirstArraySlice; + pDesc->Texture2DArray.ArraySize = m_desc.Texture2DArray.ArraySize; + break; + + case D3D11_RTV_DIMENSION_TEXTURE2DMS: + pDesc->Texture2DMS = m_desc.Texture2DMS; + break; + + case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY: + pDesc->Texture2DMSArray = m_desc.Texture2DMSArray; + break; + + case D3D11_RTV_DIMENSION_TEXTURE3D: + pDesc->Texture3D = m_desc.Texture3D; + break; + } + } + + + void STDMETHODCALLTYPE D3D11RenderTargetView::GetDesc1(D3D11_RENDER_TARGET_VIEW_DESC1* pDesc) { + *pDesc = m_desc; + } + + + HRESULT D3D11RenderTargetView::GetDescFromResource( + ID3D11Resource* pResource, + D3D11_RENDER_TARGET_VIEW_DESC1* pDesc) { + D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN; + pResource->GetType(&resourceDim); + + switch (resourceDim) { + case D3D11_RESOURCE_DIMENSION_TEXTURE1D: { + D3D11_TEXTURE1D_DESC resourceDesc; + static_cast(pResource)->GetDesc(&resourceDesc); + + pDesc->Format = resourceDesc.Format; + + if (resourceDesc.ArraySize == 1) { + pDesc->ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D; + pDesc->Texture1D.MipSlice = 0; + } else { + pDesc->ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1DARRAY; + pDesc->Texture1DArray.MipSlice = 0; + pDesc->Texture1DArray.FirstArraySlice = 0; + pDesc->Texture1DArray.ArraySize = resourceDesc.ArraySize; + } + } return S_OK; + + case D3D11_RESOURCE_DIMENSION_TEXTURE2D: { + D3D11_TEXTURE2D_DESC resourceDesc; + static_cast(pResource)->GetDesc(&resourceDesc); + + pDesc->Format = resourceDesc.Format; + + if (resourceDesc.SampleDesc.Count == 1) { + if (resourceDesc.ArraySize == 1) { + pDesc->ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + pDesc->Texture2D.MipSlice = 0; + pDesc->Texture2D.PlaneSlice = 0; + } else { + pDesc->ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + pDesc->Texture2DArray.MipSlice = 0; + pDesc->Texture2DArray.FirstArraySlice = 0; + pDesc->Texture2DArray.ArraySize = resourceDesc.ArraySize; + pDesc->Texture2DArray.PlaneSlice = 0; + } + } else { + if (resourceDesc.ArraySize == 1) { + pDesc->ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS; + } else { + pDesc->ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY; + pDesc->Texture2DMSArray.FirstArraySlice = 0; + pDesc->Texture2DMSArray.ArraySize = resourceDesc.ArraySize; + } + } + } return S_OK; + + case D3D11_RESOURCE_DIMENSION_TEXTURE3D: { + D3D11_TEXTURE3D_DESC resourceDesc; + static_cast(pResource)->GetDesc(&resourceDesc); + + pDesc->Format = resourceDesc.Format; + pDesc->ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; + pDesc->Texture3D.MipSlice = 0; + pDesc->Texture3D.FirstWSlice = 0; + pDesc->Texture3D.WSize = resourceDesc.Depth; + } return S_OK; + + default: + Logger::err(str::format( + "D3D11: Unsupported dimension for render target view: ", + resourceDim)); + return E_INVALIDARG; + } + } + + + D3D11_RENDER_TARGET_VIEW_DESC1 D3D11RenderTargetView::PromoteDesc( + const D3D11_RENDER_TARGET_VIEW_DESC* pDesc, + UINT Plane) { + D3D11_RENDER_TARGET_VIEW_DESC1 dstDesc; + dstDesc.Format = pDesc->Format; + dstDesc.ViewDimension = pDesc->ViewDimension; + + switch (pDesc->ViewDimension) { + case D3D11_RTV_DIMENSION_UNKNOWN: + break; + + case D3D11_RTV_DIMENSION_BUFFER: + dstDesc.Buffer = pDesc->Buffer; + break; + + case D3D11_RTV_DIMENSION_TEXTURE1D: + dstDesc.Texture1D = pDesc->Texture1D; + break; + + case D3D11_RTV_DIMENSION_TEXTURE1DARRAY: + dstDesc.Texture1DArray = pDesc->Texture1DArray; + break; + + case D3D11_RTV_DIMENSION_TEXTURE2D: + dstDesc.Texture2D.MipSlice = pDesc->Texture2D.MipSlice; + dstDesc.Texture2D.PlaneSlice = Plane; + break; + + case D3D11_RTV_DIMENSION_TEXTURE2DARRAY: + dstDesc.Texture2DArray.MipSlice = pDesc->Texture2DArray.MipSlice; + dstDesc.Texture2DArray.FirstArraySlice = pDesc->Texture2DArray.FirstArraySlice; + dstDesc.Texture2DArray.ArraySize = pDesc->Texture2DArray.ArraySize; + dstDesc.Texture2DArray.PlaneSlice = Plane; + break; + + case D3D11_RTV_DIMENSION_TEXTURE2DMS: + dstDesc.Texture2DMS = pDesc->Texture2DMS; + break; + + case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY: + dstDesc.Texture2DMSArray = pDesc->Texture2DMSArray; + break; + + case D3D11_RTV_DIMENSION_TEXTURE3D: + dstDesc.Texture3D = pDesc->Texture3D; + break; + } + + return dstDesc; + } + + + HRESULT D3D11RenderTargetView::NormalizeDesc( + ID3D11Resource* pResource, + D3D11_RENDER_TARGET_VIEW_DESC1* pDesc) { + D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN; + pResource->GetType(&resourceDim); + + DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN; + uint32_t numLayers = 0; + + switch (resourceDim) { + case D3D11_RESOURCE_DIMENSION_BUFFER: { + if (pDesc->ViewDimension != D3D11_RTV_DIMENSION_BUFFER) { + Logger::err("D3D11: Incompatible view dimension for Buffer"); + return E_INVALIDARG; + } + } break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE1D: { + D3D11_TEXTURE1D_DESC resourceDesc; + static_cast(pResource)->GetDesc(&resourceDesc); + + if (pDesc->ViewDimension != D3D11_RTV_DIMENSION_TEXTURE1D + && pDesc->ViewDimension != D3D11_RTV_DIMENSION_TEXTURE1DARRAY) { + Logger::err("D3D11: Incompatible view dimension for Texture1D"); + return E_INVALIDARG; + } + + format = resourceDesc.Format; + numLayers = resourceDesc.ArraySize; + } break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE2D: { + D3D11_TEXTURE2D_DESC resourceDesc; + static_cast(pResource)->GetDesc(&resourceDesc); + + if (pDesc->ViewDimension != D3D11_RTV_DIMENSION_TEXTURE2D + && pDesc->ViewDimension != D3D11_RTV_DIMENSION_TEXTURE2DARRAY + && pDesc->ViewDimension != D3D11_RTV_DIMENSION_TEXTURE2DMS + && pDesc->ViewDimension != D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY) { + Logger::err("D3D11: Incompatible view dimension for Texture2D"); + return E_INVALIDARG; + } + + format = resourceDesc.Format; + numLayers = resourceDesc.ArraySize; + } break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE3D: { + D3D11_TEXTURE3D_DESC resourceDesc; + static_cast(pResource)->GetDesc(&resourceDesc); + + if (pDesc->ViewDimension != D3D11_RTV_DIMENSION_TEXTURE3D) { + Logger::err("D3D11: Incompatible view dimension for Texture3D"); + return E_INVALIDARG; + } + + format = resourceDesc.Format; + numLayers = std::max(resourceDesc.Depth >> pDesc->Texture3D.MipSlice, 1u); + } break; + + default: + return E_INVALIDARG; + } + + if (pDesc->Format == DXGI_FORMAT_UNKNOWN) + pDesc->Format = format; + + switch (pDesc->ViewDimension) { + case D3D11_RTV_DIMENSION_TEXTURE1DARRAY: + if (pDesc->Texture1DArray.ArraySize > numLayers - pDesc->Texture1DArray.FirstArraySlice) + pDesc->Texture1DArray.ArraySize = numLayers - pDesc->Texture1DArray.FirstArraySlice; + break; + + case D3D11_RTV_DIMENSION_TEXTURE2D: + break; + + case D3D11_RTV_DIMENSION_TEXTURE2DARRAY: + if (pDesc->Texture2DArray.ArraySize > numLayers - pDesc->Texture2DArray.FirstArraySlice) + pDesc->Texture2DArray.ArraySize = numLayers - pDesc->Texture2DArray.FirstArraySlice; + break; + + case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY: + if (pDesc->Texture2DMSArray.ArraySize > numLayers - pDesc->Texture2DMSArray.FirstArraySlice) + pDesc->Texture2DMSArray.ArraySize = numLayers - pDesc->Texture2DMSArray.FirstArraySlice; + break; + + case D3D11_RTV_DIMENSION_TEXTURE3D: + if (pDesc->Texture3D.WSize > numLayers - pDesc->Texture3D.FirstWSlice) + pDesc->Texture3D.WSize = numLayers - pDesc->Texture3D.FirstWSlice; + break; + + default: + break; + } + + return S_OK; + } + + + UINT D3D11RenderTargetView::GetPlaneSlice(const D3D11_RENDER_TARGET_VIEW_DESC1* pDesc) { + switch (pDesc->ViewDimension) { + case D3D11_RTV_DIMENSION_TEXTURE2D: + return pDesc->Texture2D.PlaneSlice; + case D3D11_RTV_DIMENSION_TEXTURE2DARRAY: + return pDesc->Texture2DArray.PlaneSlice; + default: + return 0; + } + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_view_rtv.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_view_rtv.h new file mode 100644 index 00000000000..080146eca4a --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_view_rtv.h @@ -0,0 +1,89 @@ +#pragma once + +#include "../dxvk/dxvk_device.h" + +#include "../d3d10/d3d10_view_rtv.h" + +#include "d3d11_device_child.h" +#include "d3d11_view.h" + +namespace dxvk { + + class D3D11Device; + + /** + * \brief Render target view + */ + class D3D11RenderTargetView : public D3D11DeviceChild { + + public: + + D3D11RenderTargetView( + D3D11Device* pDevice, + ID3D11Resource* pResource, + const D3D11_RENDER_TARGET_VIEW_DESC1* pDesc); + + ~D3D11RenderTargetView(); + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) final; + + void STDMETHODCALLTYPE GetResource(ID3D11Resource** ppResource) final; + + void STDMETHODCALLTYPE GetDesc(D3D11_RENDER_TARGET_VIEW_DESC* pDesc) final; + + void STDMETHODCALLTYPE GetDesc1(D3D11_RENDER_TARGET_VIEW_DESC1* pDesc) final; + + const D3D11_VK_VIEW_INFO& GetViewInfo() const { + return m_info; + } + + BOOL HasBindFlag(UINT Flags) const { + return m_info.BindFlags & Flags; + } + + D3D11_RESOURCE_DIMENSION GetResourceType() const { + D3D11_RESOURCE_DIMENSION type; + m_resource->GetType(&type); + return type; + } + + Rc GetImageView() const { + return m_view; + } + + VkImageLayout GetRenderLayout() const { + return m_view->imageInfo().tiling == VK_IMAGE_TILING_OPTIMAL + ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL + : VK_IMAGE_LAYOUT_GENERAL; + } + + D3D10RenderTargetView* GetD3D10Iface() { + return &m_d3d10; + } + + static HRESULT GetDescFromResource( + ID3D11Resource* pResource, + D3D11_RENDER_TARGET_VIEW_DESC1* pDesc); + + static D3D11_RENDER_TARGET_VIEW_DESC1 PromoteDesc( + const D3D11_RENDER_TARGET_VIEW_DESC* pDesc, + UINT Plane); + + static HRESULT NormalizeDesc( + ID3D11Resource* pResource, + D3D11_RENDER_TARGET_VIEW_DESC1* pDesc); + + static UINT GetPlaneSlice( + const D3D11_RENDER_TARGET_VIEW_DESC1* pDesc); + + private: + + ID3D11Resource* m_resource; + D3D11_RENDER_TARGET_VIEW_DESC1 m_desc; + D3D11_VK_VIEW_INFO m_info; + Rc m_view; + D3D10RenderTargetView m_d3d10; + + }; + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_view_srv.cpp b/utils/dxvk-1.10.3/src/d3d11/d3d11_view_srv.cpp new file mode 100644 index 00000000000..1c3d4d8dd28 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_view_srv.cpp @@ -0,0 +1,592 @@ +#include "d3d11_device.h" +#include "d3d11_buffer.h" +#include "d3d11_resource.h" +#include "d3d11_texture.h" +#include "d3d11_view_srv.h" + +namespace dxvk { + + D3D11ShaderResourceView::D3D11ShaderResourceView( + D3D11Device* pDevice, + ID3D11Resource* pResource, + const D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc) + : D3D11DeviceChild(pDevice), + m_resource(pResource), m_desc(*pDesc), m_d3d10(this) { + ResourceAddRefPrivate(m_resource); + + D3D11_COMMON_RESOURCE_DESC resourceDesc; + GetCommonResourceDesc(pResource, &resourceDesc); + + // Basic view resource info + m_info.pResource = pResource; + m_info.Dimension = resourceDesc.Dim; + m_info.BindFlags = resourceDesc.BindFlags; + + if (resourceDesc.Dim == D3D11_RESOURCE_DIMENSION_BUFFER) { + auto buffer = static_cast(pResource); + + // Move buffer description to a common struct to + // avoid having to handle the two cases separately + D3D11_BUFFEREX_SRV bufInfo; + + if (pDesc->ViewDimension == D3D11_SRV_DIMENSION_BUFFEREX) { + bufInfo.FirstElement = pDesc->BufferEx.FirstElement; + bufInfo.NumElements = pDesc->BufferEx.NumElements; + bufInfo.Flags = pDesc->BufferEx.Flags; + } else if (pDesc->ViewDimension == D3D11_SRV_DIMENSION_BUFFER) { + bufInfo.FirstElement = pDesc->Buffer.FirstElement; + bufInfo.NumElements = pDesc->Buffer.NumElements; + bufInfo.Flags = 0; + } else { + throw DxvkError("D3D11: Invalid view dimension for buffer SRV"); + } + + // Fill in buffer view info + DxvkBufferViewCreateInfo viewInfo; + + if (bufInfo.Flags & D3D11_BUFFEREX_SRV_FLAG_RAW) { + // Raw buffer view. We'll represent this as a + // uniform texel buffer with UINT32 elements. + viewInfo.format = VK_FORMAT_R32_UINT; + viewInfo.rangeOffset = sizeof(uint32_t) * bufInfo.FirstElement; + viewInfo.rangeLength = sizeof(uint32_t) * bufInfo.NumElements; + } else if (pDesc->Format == DXGI_FORMAT_UNKNOWN) { + // Structured buffer view + viewInfo.format = VK_FORMAT_R32_UINT; + viewInfo.rangeOffset = buffer->Desc()->StructureByteStride * bufInfo.FirstElement; + viewInfo.rangeLength = buffer->Desc()->StructureByteStride * bufInfo.NumElements; + } else { + viewInfo.format = pDevice->LookupFormat(pDesc->Format, DXGI_VK_FORMAT_MODE_COLOR).Format; + + const DxvkFormatInfo* formatInfo = imageFormatInfo(viewInfo.format); + viewInfo.rangeOffset = formatInfo->elementSize * bufInfo.FirstElement; + viewInfo.rangeLength = formatInfo->elementSize * bufInfo.NumElements; + } + + // Populate view info struct + m_info.Buffer.Offset = viewInfo.rangeOffset; + m_info.Buffer.Length = viewInfo.rangeLength; + + // Create underlying buffer view object + m_bufferView = pDevice->GetDXVKDevice()->createBufferView( + buffer->GetBuffer(), viewInfo); + } else { + auto texture = GetCommonTexture(pResource); + auto formatInfo = pDevice->LookupFormat(pDesc->Format, texture->GetFormatMode()); + + DxvkImageViewCreateInfo viewInfo; + viewInfo.format = formatInfo.Format; + viewInfo.aspect = formatInfo.Aspect; + viewInfo.swizzle = formatInfo.Swizzle; + viewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT; + + // Shaders expect the stencil value in the G component + if (viewInfo.aspect == VK_IMAGE_ASPECT_STENCIL_BIT) { + viewInfo.swizzle = VkComponentMapping { + VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_R, + VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO }; + } + + switch (pDesc->ViewDimension) { + case D3D11_SRV_DIMENSION_TEXTURE1D: + viewInfo.type = VK_IMAGE_VIEW_TYPE_1D; + viewInfo.minLevel = pDesc->Texture1D.MostDetailedMip; + viewInfo.numLevels = pDesc->Texture1D.MipLevels; + viewInfo.minLayer = 0; + viewInfo.numLayers = 1; + break; + + case D3D11_SRV_DIMENSION_TEXTURE1DARRAY: + viewInfo.type = VK_IMAGE_VIEW_TYPE_1D_ARRAY; + viewInfo.minLevel = pDesc->Texture1DArray.MostDetailedMip; + viewInfo.numLevels = pDesc->Texture1DArray.MipLevels; + viewInfo.minLayer = pDesc->Texture1DArray.FirstArraySlice; + viewInfo.numLayers = pDesc->Texture1DArray.ArraySize; + break; + + case D3D11_SRV_DIMENSION_TEXTURE2D: + viewInfo.type = VK_IMAGE_VIEW_TYPE_2D; + viewInfo.minLevel = pDesc->Texture2D.MostDetailedMip; + viewInfo.numLevels = pDesc->Texture2D.MipLevels; + viewInfo.minLayer = 0; + viewInfo.numLayers = 1; + break; + + case D3D11_SRV_DIMENSION_TEXTURE2DARRAY: + viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; + viewInfo.minLevel = pDesc->Texture2DArray.MostDetailedMip; + viewInfo.numLevels = pDesc->Texture2DArray.MipLevels; + viewInfo.minLayer = pDesc->Texture2DArray.FirstArraySlice; + viewInfo.numLayers = pDesc->Texture2DArray.ArraySize; + break; + + case D3D11_SRV_DIMENSION_TEXTURE2DMS: + viewInfo.type = VK_IMAGE_VIEW_TYPE_2D; + viewInfo.minLevel = 0; + viewInfo.numLevels = 1; + viewInfo.minLayer = 0; + viewInfo.numLayers = 1; + break; + + case D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY: + viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; + viewInfo.minLevel = 0; + viewInfo.numLevels = 1; + viewInfo.minLayer = pDesc->Texture2DMSArray.FirstArraySlice; + viewInfo.numLayers = pDesc->Texture2DMSArray.ArraySize; + break; + + case D3D11_SRV_DIMENSION_TEXTURE3D: + viewInfo.type = VK_IMAGE_VIEW_TYPE_3D; + viewInfo.minLevel = pDesc->Texture3D.MostDetailedMip; + viewInfo.numLevels = pDesc->Texture3D.MipLevels; + viewInfo.minLayer = 0; + viewInfo.numLayers = 1; + break; + + case D3D11_SRV_DIMENSION_TEXTURECUBE: { + const bool cubeArraysEnabled = pDevice->GetDXVKDevice()->features().core.features.imageCubeArray; + viewInfo.type = cubeArraysEnabled ? VK_IMAGE_VIEW_TYPE_CUBE_ARRAY : VK_IMAGE_VIEW_TYPE_CUBE; + viewInfo.minLevel = pDesc->TextureCube.MostDetailedMip; + viewInfo.numLevels = pDesc->TextureCube.MipLevels; + viewInfo.minLayer = 0; + viewInfo.numLayers = 6; + } break; + + case D3D11_SRV_DIMENSION_TEXTURECUBEARRAY: + viewInfo.type = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY; + viewInfo.minLevel = pDesc->TextureCubeArray.MostDetailedMip; + viewInfo.numLevels = pDesc->TextureCubeArray.MipLevels; + viewInfo.minLayer = pDesc->TextureCubeArray.First2DArrayFace; + viewInfo.numLayers = pDesc->TextureCubeArray.NumCubes * 6; + break; + + default: + throw DxvkError("D3D11: Invalid view dimension for image SRV"); + } + + if (texture->GetPlaneCount() > 1) + viewInfo.aspect = vk::getPlaneAspect(GetPlaneSlice(pDesc)); + + // Populate view info struct + m_info.Image.Aspects = viewInfo.aspect; + m_info.Image.MinLevel = viewInfo.minLevel; + m_info.Image.MinLayer = viewInfo.minLayer; + m_info.Image.NumLevels = viewInfo.numLevels; + m_info.Image.NumLayers = viewInfo.numLayers; + + // Create the underlying image view object + m_imageView = pDevice->GetDXVKDevice()->createImageView(texture->GetImage(), viewInfo); + } + } + + + D3D11ShaderResourceView::~D3D11ShaderResourceView() { + ResourceReleasePrivate(m_resource); + } + + + HRESULT STDMETHODCALLTYPE D3D11ShaderResourceView::QueryInterface(REFIID riid, void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(ID3D11DeviceChild) + || riid == __uuidof(ID3D11View) + || riid == __uuidof(ID3D11ShaderResourceView) + || riid == __uuidof(ID3D11ShaderResourceView1)) { + *ppvObject = ref(this); + return S_OK; + } + + if (riid == __uuidof(ID3D10DeviceChild) + || riid == __uuidof(ID3D10View) + || riid == __uuidof(ID3D10ShaderResourceView) + || riid == __uuidof(ID3D10ShaderResourceView1)) { + *ppvObject = ref(this); + return S_OK; + } + + Logger::warn("D3D11ShaderResourceView::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + void STDMETHODCALLTYPE D3D11ShaderResourceView::GetResource(ID3D11Resource** ppResource) { + *ppResource = ref(m_resource); + } + + + void STDMETHODCALLTYPE D3D11ShaderResourceView::GetDesc(D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc) { + pDesc->Format = m_desc.Format; + pDesc->ViewDimension = m_desc.ViewDimension; + + switch (m_desc.ViewDimension) { + case D3D11_SRV_DIMENSION_UNKNOWN: + break; + + case D3D11_SRV_DIMENSION_BUFFER: + pDesc->Buffer = m_desc.Buffer; + break; + + case D3D11_SRV_DIMENSION_TEXTURE1D: + pDesc->Texture1D = m_desc.Texture1D; + break; + + case D3D11_SRV_DIMENSION_TEXTURE1DARRAY: + pDesc->Texture1DArray = m_desc.Texture1DArray; + break; + + case D3D11_SRV_DIMENSION_TEXTURE2D: + pDesc->Texture2D.MostDetailedMip = m_desc.Texture2D.MostDetailedMip; + pDesc->Texture2D.MipLevels = m_desc.Texture2D.MipLevels; + break; + + case D3D11_SRV_DIMENSION_TEXTURE2DARRAY: + pDesc->Texture2DArray.MostDetailedMip = m_desc.Texture2DArray.MostDetailedMip; + pDesc->Texture2DArray.MipLevels = m_desc.Texture2DArray.MipLevels; + pDesc->Texture2DArray.FirstArraySlice = m_desc.Texture2DArray.FirstArraySlice; + pDesc->Texture2DArray.ArraySize = m_desc.Texture2DArray.ArraySize; + break; + + case D3D11_SRV_DIMENSION_TEXTURE2DMS: + pDesc->Texture2DMS = m_desc.Texture2DMS; + break; + + case D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY: + pDesc->Texture2DMSArray = m_desc.Texture2DMSArray; + break; + + case D3D11_SRV_DIMENSION_TEXTURE3D: + pDesc->Texture3D = m_desc.Texture3D; + break; + + case D3D11_SRV_DIMENSION_TEXTURECUBE: + pDesc->TextureCube = m_desc.TextureCube; + break; + + case D3D11_SRV_DIMENSION_TEXTURECUBEARRAY: + pDesc->TextureCubeArray = m_desc.TextureCubeArray; + break; + + case D3D11_SRV_DIMENSION_BUFFEREX: + pDesc->BufferEx = m_desc.BufferEx; + break; + } + } + + + void STDMETHODCALLTYPE D3D11ShaderResourceView::GetDesc1(D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc) { + *pDesc = m_desc; + } + + + HRESULT D3D11ShaderResourceView::GetDescFromResource( + ID3D11Resource* pResource, + D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc) { + D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN; + pResource->GetType(&resourceDim); + + switch (resourceDim) { + case D3D11_RESOURCE_DIMENSION_BUFFER: { + D3D11_BUFFER_DESC bufferDesc; + static_cast(pResource)->GetDesc(&bufferDesc); + + if (bufferDesc.MiscFlags == D3D11_RESOURCE_MISC_BUFFER_STRUCTURED) { + pDesc->Format = DXGI_FORMAT_UNKNOWN; + pDesc->ViewDimension = D3D11_SRV_DIMENSION_BUFFER; + pDesc->Buffer.FirstElement = 0; + pDesc->Buffer.NumElements = bufferDesc.ByteWidth / bufferDesc.StructureByteStride; + return S_OK; + } + } return E_INVALIDARG; + + case D3D11_RESOURCE_DIMENSION_TEXTURE1D: { + D3D11_TEXTURE1D_DESC resourceDesc; + static_cast(pResource)->GetDesc(&resourceDesc); + + pDesc->Format = resourceDesc.Format; + + if (resourceDesc.ArraySize == 1) { + pDesc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D; + pDesc->Texture1D.MostDetailedMip = 0; + pDesc->Texture1D.MipLevels = resourceDesc.MipLevels; + } else { + pDesc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY; + pDesc->Texture1DArray.MostDetailedMip = 0; + pDesc->Texture1DArray.MipLevels = resourceDesc.MipLevels; + pDesc->Texture1DArray.FirstArraySlice = 0; + pDesc->Texture1DArray.ArraySize = resourceDesc.ArraySize; + } + } return S_OK; + + case D3D11_RESOURCE_DIMENSION_TEXTURE2D: { + D3D11_TEXTURE2D_DESC resourceDesc; + static_cast(pResource)->GetDesc(&resourceDesc); + + pDesc->Format = resourceDesc.Format; + + if (resourceDesc.SampleDesc.Count == 1) { + if (resourceDesc.ArraySize == 1) { + pDesc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + pDesc->Texture2D.MostDetailedMip = 0; + pDesc->Texture2D.MipLevels = resourceDesc.MipLevels; + pDesc->Texture2D.PlaneSlice = 0; + } else { + pDesc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; + pDesc->Texture2DArray.MostDetailedMip = 0; + pDesc->Texture2DArray.MipLevels = resourceDesc.MipLevels; + pDesc->Texture2DArray.FirstArraySlice = 0; + pDesc->Texture2DArray.ArraySize = resourceDesc.ArraySize; + pDesc->Texture2DArray.PlaneSlice = 0; + } + } else { + if (resourceDesc.ArraySize == 1) { + pDesc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS; + } else { + pDesc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY; + pDesc->Texture2DMSArray.FirstArraySlice = 0; + pDesc->Texture2DMSArray.ArraySize = resourceDesc.ArraySize; + } + } + } return S_OK; + + case D3D11_RESOURCE_DIMENSION_TEXTURE3D: { + D3D11_TEXTURE3D_DESC resourceDesc; + static_cast(pResource)->GetDesc(&resourceDesc); + + pDesc->Format = resourceDesc.Format; + pDesc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D; + pDesc->Texture3D.MostDetailedMip = 0; + pDesc->Texture3D.MipLevels = resourceDesc.MipLevels; + } return S_OK; + + default: + Logger::err(str::format( + "D3D11: Unsupported dimension for shader resource view: ", + resourceDim)); + return E_INVALIDARG; + } + } + + + D3D11_SHADER_RESOURCE_VIEW_DESC1 D3D11ShaderResourceView::PromoteDesc( + const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc, + UINT Plane) { + D3D11_SHADER_RESOURCE_VIEW_DESC1 dstDesc; + dstDesc.Format = pDesc->Format; + dstDesc.ViewDimension = pDesc->ViewDimension; + + switch (pDesc->ViewDimension) { + case D3D11_SRV_DIMENSION_UNKNOWN: + break; + + case D3D11_SRV_DIMENSION_BUFFER: + dstDesc.Buffer = pDesc->Buffer; + break; + + case D3D11_SRV_DIMENSION_TEXTURE1D: + dstDesc.Texture1D = pDesc->Texture1D; + break; + + case D3D11_SRV_DIMENSION_TEXTURE1DARRAY: + dstDesc.Texture1DArray = pDesc->Texture1DArray; + break; + + case D3D11_SRV_DIMENSION_TEXTURE2D: + dstDesc.Texture2D.MostDetailedMip = pDesc->Texture2D.MostDetailedMip; + dstDesc.Texture2D.MipLevels = pDesc->Texture2D.MipLevels; + dstDesc.Texture2D.PlaneSlice = Plane; + break; + + case D3D11_SRV_DIMENSION_TEXTURE2DARRAY: + dstDesc.Texture2DArray.MostDetailedMip = pDesc->Texture2DArray.MostDetailedMip; + dstDesc.Texture2DArray.MipLevels = pDesc->Texture2DArray.MipLevels; + dstDesc.Texture2DArray.FirstArraySlice = pDesc->Texture2DArray.FirstArraySlice; + dstDesc.Texture2DArray.ArraySize = pDesc->Texture2DArray.ArraySize; + dstDesc.Texture2DArray.PlaneSlice = Plane; + break; + + case D3D11_SRV_DIMENSION_TEXTURE2DMS: + dstDesc.Texture2DMS = pDesc->Texture2DMS; + break; + + case D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY: + dstDesc.Texture2DMSArray = pDesc->Texture2DMSArray; + break; + + case D3D11_SRV_DIMENSION_TEXTURE3D: + dstDesc.Texture3D = pDesc->Texture3D; + break; + + case D3D11_SRV_DIMENSION_TEXTURECUBE: + dstDesc.TextureCube = pDesc->TextureCube; + break; + + case D3D11_SRV_DIMENSION_TEXTURECUBEARRAY: + dstDesc.TextureCubeArray = pDesc->TextureCubeArray; + break; + + case D3D11_SRV_DIMENSION_BUFFEREX: + dstDesc.BufferEx = pDesc->BufferEx; + break; + } + + return dstDesc; + } + + + HRESULT D3D11ShaderResourceView::NormalizeDesc( + ID3D11Resource* pResource, + D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc) { + D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN; + pResource->GetType(&resourceDim); + + DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN; + uint32_t mipLevels = 0; + uint32_t numLayers = 0; + + switch (resourceDim) { + case D3D11_RESOURCE_DIMENSION_BUFFER: { + if (pDesc->ViewDimension != D3D11_SRV_DIMENSION_BUFFER + && pDesc->ViewDimension != D3D11_SRV_DIMENSION_BUFFEREX) { + Logger::err("D3D11: Incompatible view dimension for Buffer"); + return E_INVALIDARG; + } + } break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE1D: { + D3D11_TEXTURE1D_DESC resourceDesc; + static_cast(pResource)->GetDesc(&resourceDesc); + + if (pDesc->ViewDimension != D3D11_SRV_DIMENSION_TEXTURE1D + && pDesc->ViewDimension != D3D11_SRV_DIMENSION_TEXTURE1DARRAY) { + Logger::err("D3D11: Incompatible view dimension for Texture1D"); + return E_INVALIDARG; + } + + format = resourceDesc.Format; + mipLevels = resourceDesc.MipLevels; + numLayers = resourceDesc.ArraySize; + } break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE2D: { + D3D11_TEXTURE2D_DESC resourceDesc; + static_cast(pResource)->GetDesc(&resourceDesc); + + if (pDesc->ViewDimension != D3D11_SRV_DIMENSION_TEXTURE2D + && pDesc->ViewDimension != D3D11_SRV_DIMENSION_TEXTURE2DARRAY + && pDesc->ViewDimension != D3D11_SRV_DIMENSION_TEXTURE2DMS + && pDesc->ViewDimension != D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY + && pDesc->ViewDimension != D3D11_SRV_DIMENSION_TEXTURECUBE + && pDesc->ViewDimension != D3D11_SRV_DIMENSION_TEXTURECUBEARRAY) { + Logger::err("D3D11: Incompatible view dimension for Texture2D"); + return E_INVALIDARG; + } + + format = resourceDesc.Format; + mipLevels = resourceDesc.MipLevels; + numLayers = resourceDesc.ArraySize; + } break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE3D: { + D3D11_TEXTURE3D_DESC resourceDesc; + static_cast(pResource)->GetDesc(&resourceDesc); + + if (pDesc->ViewDimension != D3D11_SRV_DIMENSION_TEXTURE3D) { + Logger::err("D3D11: Incompatible view dimension for Texture3D"); + return E_INVALIDARG; + } + + format = resourceDesc.Format; + mipLevels = resourceDesc.MipLevels; + numLayers = 1; + } break; + + default: + return E_INVALIDARG; + } + + if (pDesc->Format == DXGI_FORMAT_UNKNOWN) + pDesc->Format = format; + + switch (pDesc->ViewDimension) { + case D3D11_SRV_DIMENSION_BUFFER: + if (pDesc->Buffer.NumElements == 0) + return E_INVALIDARG; + break; + + case D3D11_SRV_DIMENSION_BUFFEREX: + if (pDesc->BufferEx.NumElements == 0) + return E_INVALIDARG; + break; + + case D3D11_SRV_DIMENSION_TEXTURE1D: + if (pDesc->Texture1D.MipLevels > mipLevels - pDesc->Texture1D.MostDetailedMip) + pDesc->Texture1D.MipLevels = mipLevels - pDesc->Texture1D.MostDetailedMip; + break; + + case D3D11_SRV_DIMENSION_TEXTURE1DARRAY: + if (pDesc->Texture1DArray.MipLevels > mipLevels - pDesc->Texture1DArray.MostDetailedMip) + pDesc->Texture1DArray.MipLevels = mipLevels - pDesc->Texture1DArray.MostDetailedMip; + if (pDesc->Texture1DArray.ArraySize > numLayers - pDesc->Texture1DArray.FirstArraySlice) + pDesc->Texture1DArray.ArraySize = numLayers - pDesc->Texture1DArray.FirstArraySlice; + break; + + case D3D11_SRV_DIMENSION_TEXTURE2D: + if (pDesc->Texture2D.MipLevels > mipLevels - pDesc->Texture2D.MostDetailedMip) + pDesc->Texture2D.MipLevels = mipLevels - pDesc->Texture2D.MostDetailedMip; + break; + + case D3D11_SRV_DIMENSION_TEXTURE2DARRAY: + if (pDesc->Texture2DArray.MipLevels > mipLevels - pDesc->Texture2DArray.MostDetailedMip) + pDesc->Texture2DArray.MipLevels = mipLevels - pDesc->Texture2DArray.MostDetailedMip; + if (pDesc->Texture2DArray.ArraySize > numLayers - pDesc->Texture2DArray.FirstArraySlice) + pDesc->Texture2DArray.ArraySize = numLayers - pDesc->Texture2DArray.FirstArraySlice; + break; + + case D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY: + if (pDesc->Texture2DMSArray.ArraySize > numLayers - pDesc->Texture2DMSArray.FirstArraySlice) + pDesc->Texture2DMSArray.ArraySize = numLayers - pDesc->Texture2DMSArray.FirstArraySlice; + break; + + case D3D11_SRV_DIMENSION_TEXTURECUBE: + if (pDesc->TextureCube.MipLevels > mipLevels - pDesc->TextureCube.MostDetailedMip) + pDesc->TextureCube.MipLevels = mipLevels - pDesc->TextureCube.MostDetailedMip; + break; + + case D3D11_SRV_DIMENSION_TEXTURECUBEARRAY: + if (pDesc->TextureCubeArray.MipLevels > mipLevels - pDesc->TextureCubeArray.MostDetailedMip) + pDesc->TextureCubeArray.MipLevels = mipLevels - pDesc->TextureCubeArray.MostDetailedMip; + if (pDesc->TextureCubeArray.NumCubes > (numLayers - pDesc->TextureCubeArray.First2DArrayFace) / 6) + pDesc->TextureCubeArray.NumCubes = (numLayers - pDesc->TextureCubeArray.First2DArrayFace) / 6; + break; + + case D3D11_SRV_DIMENSION_TEXTURE3D: + if (pDesc->Texture3D.MipLevels > mipLevels - pDesc->Texture3D.MostDetailedMip) + pDesc->Texture3D.MipLevels = mipLevels - pDesc->Texture3D.MostDetailedMip; + break; + + default: + break; + } + + return S_OK; + } + + + UINT D3D11ShaderResourceView::GetPlaneSlice(const D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc) { + switch (pDesc->ViewDimension) { + case D3D11_SRV_DIMENSION_TEXTURE2D: + return pDesc->Texture2D.PlaneSlice; + case D3D11_SRV_DIMENSION_TEXTURE2DARRAY: + return pDesc->Texture2DArray.PlaneSlice; + default: + return 0; + } + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_view_srv.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_view_srv.h new file mode 100644 index 00000000000..e7c5872ec7f --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_view_srv.h @@ -0,0 +1,94 @@ +#pragma once + +#include "../dxvk/dxvk_device.h" + +#include "../d3d10/d3d10_view_srv.h" + +#include "d3d11_device_child.h" +#include "d3d11_view.h" + +namespace dxvk { + + class D3D11Device; + + /** + * \brief Shader resource view + */ + class D3D11ShaderResourceView : public D3D11DeviceChild { + + public: + + D3D11ShaderResourceView( + D3D11Device* pDevice, + ID3D11Resource* pResource, + const D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc); + + ~D3D11ShaderResourceView(); + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) final; + + void STDMETHODCALLTYPE GetResource(ID3D11Resource** ppResource) final; + + void STDMETHODCALLTYPE GetDesc(D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc) final; + + void STDMETHODCALLTYPE GetDesc1(D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc) final; + + const D3D11_VK_VIEW_INFO& GetViewInfo() const { + return m_info; + } + + BOOL TestHazards() const { + return m_info.BindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_UNORDERED_ACCESS); + } + + D3D11_RESOURCE_DIMENSION GetResourceType() const { + D3D11_RESOURCE_DIMENSION type; + m_resource->GetType(&type); + return type; + } + + D3D11_COMMON_RESOURCE_DESC GetResourceDesc() const { + D3D11_COMMON_RESOURCE_DESC desc; + GetCommonResourceDesc(m_resource, &desc); + return desc; + } + + Rc GetBufferView() const { + return m_bufferView; + } + + Rc GetImageView() const { + return m_imageView; + } + + D3D10ShaderResourceView* GetD3D10Iface() { + return &m_d3d10; + } + + static HRESULT GetDescFromResource( + ID3D11Resource* pResource, + D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc); + + static D3D11_SHADER_RESOURCE_VIEW_DESC1 PromoteDesc( + const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc, + UINT Plane); + + static HRESULT NormalizeDesc( + ID3D11Resource* pResource, + D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc); + + static UINT GetPlaneSlice( + const D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc); + + private: + + ID3D11Resource* m_resource; + D3D11_SHADER_RESOURCE_VIEW_DESC1 m_desc; + D3D11_VK_VIEW_INFO m_info; + Rc m_bufferView; + Rc m_imageView; + D3D10ShaderResourceView m_d3d10; + + }; + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_view_uav.cpp b/utils/dxvk-1.10.3/src/d3d11/d3d11_view_uav.cpp new file mode 100644 index 00000000000..54f826e79e5 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_view_uav.cpp @@ -0,0 +1,447 @@ +#include "d3d11_device.h" +#include "d3d11_buffer.h" +#include "d3d11_resource.h" +#include "d3d11_texture.h" +#include "d3d11_view_uav.h" + +namespace dxvk { + + D3D11UnorderedAccessView::D3D11UnorderedAccessView( + D3D11Device* pDevice, + ID3D11Resource* pResource, + const D3D11_UNORDERED_ACCESS_VIEW_DESC1* pDesc) + : D3D11DeviceChild(pDevice), + m_resource(pResource), m_desc(*pDesc) { + ResourceAddRefPrivate(m_resource); + + D3D11_COMMON_RESOURCE_DESC resourceDesc; + GetCommonResourceDesc(pResource, &resourceDesc); + + // Basic view resource info + m_info.pResource = pResource; + m_info.Dimension = resourceDesc.Dim; + m_info.BindFlags = resourceDesc.BindFlags; + + if (resourceDesc.Dim == D3D11_RESOURCE_DIMENSION_BUFFER) { + auto buffer = static_cast(pResource); + + DxvkBufferViewCreateInfo viewInfo; + + if (pDesc->Buffer.Flags & D3D11_BUFFEREX_SRV_FLAG_RAW) { + viewInfo.format = VK_FORMAT_R32_UINT; + viewInfo.rangeOffset = sizeof(uint32_t) * pDesc->Buffer.FirstElement; + viewInfo.rangeLength = sizeof(uint32_t) * pDesc->Buffer.NumElements; + } else if (pDesc->Format == DXGI_FORMAT_UNKNOWN) { + viewInfo.format = VK_FORMAT_R32_UINT; + viewInfo.rangeOffset = buffer->Desc()->StructureByteStride * pDesc->Buffer.FirstElement; + viewInfo.rangeLength = buffer->Desc()->StructureByteStride * pDesc->Buffer.NumElements; + } else { + viewInfo.format = pDevice->LookupFormat(pDesc->Format, DXGI_VK_FORMAT_MODE_COLOR).Format; + + const DxvkFormatInfo* formatInfo = imageFormatInfo(viewInfo.format); + viewInfo.rangeOffset = formatInfo->elementSize * pDesc->Buffer.FirstElement; + viewInfo.rangeLength = formatInfo->elementSize * pDesc->Buffer.NumElements; + } + + if (pDesc->Buffer.Flags & (D3D11_BUFFER_UAV_FLAG_APPEND | D3D11_BUFFER_UAV_FLAG_COUNTER)) + m_counterBuffer = CreateCounterBuffer(); + + // Populate view info struct + m_info.Buffer.Offset = viewInfo.rangeOffset; + m_info.Buffer.Length = viewInfo.rangeLength; + + m_bufferView = pDevice->GetDXVKDevice()->createBufferView( + buffer->GetBuffer(), viewInfo); + } else { + auto texture = GetCommonTexture(pResource); + auto formatInfo = pDevice->LookupFormat(pDesc->Format, texture->GetFormatMode()); + + DxvkImageViewCreateInfo viewInfo; + viewInfo.format = formatInfo.Format; + viewInfo.aspect = formatInfo.Aspect; + viewInfo.swizzle = formatInfo.Swizzle; + viewInfo.usage = VK_IMAGE_USAGE_STORAGE_BIT; + + switch (pDesc->ViewDimension) { + case D3D11_UAV_DIMENSION_TEXTURE1D: + viewInfo.type = VK_IMAGE_VIEW_TYPE_1D; + viewInfo.minLevel = pDesc->Texture1D.MipSlice; + viewInfo.numLevels = 1; + viewInfo.minLayer = 0; + viewInfo.numLayers = 1; + break; + + case D3D11_UAV_DIMENSION_TEXTURE1DARRAY: + viewInfo.type = VK_IMAGE_VIEW_TYPE_1D_ARRAY; + viewInfo.minLevel = pDesc->Texture1DArray.MipSlice; + viewInfo.numLevels = 1; + viewInfo.minLayer = pDesc->Texture1DArray.FirstArraySlice; + viewInfo.numLayers = pDesc->Texture1DArray.ArraySize; + break; + + case D3D11_UAV_DIMENSION_TEXTURE2D: + viewInfo.type = VK_IMAGE_VIEW_TYPE_2D; + viewInfo.minLevel = pDesc->Texture2D.MipSlice; + viewInfo.numLevels = 1; + viewInfo.minLayer = 0; + viewInfo.numLayers = 1; + break; + + case D3D11_UAV_DIMENSION_TEXTURE2DARRAY: + viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; + viewInfo.minLevel = pDesc->Texture2DArray.MipSlice; + viewInfo.numLevels = 1; + viewInfo.minLayer = pDesc->Texture2DArray.FirstArraySlice; + viewInfo.numLayers = pDesc->Texture2DArray.ArraySize; + break; + + case D3D11_UAV_DIMENSION_TEXTURE3D: + // FIXME we actually have to map this to a + // 2D array view in order to support W slices + viewInfo.type = VK_IMAGE_VIEW_TYPE_3D; + viewInfo.minLevel = pDesc->Texture3D.MipSlice; + viewInfo.numLevels = 1; + viewInfo.minLayer = 0; + viewInfo.numLayers = 1; + break; + + default: + throw DxvkError("D3D11: Invalid view dimension for image UAV"); + } + + if (texture->GetPlaneCount() > 1) + viewInfo.aspect = vk::getPlaneAspect(GetPlaneSlice(pDesc)); + + // Populate view info struct + m_info.Image.Aspects = viewInfo.aspect; + m_info.Image.MinLevel = viewInfo.minLevel; + m_info.Image.MinLayer = viewInfo.minLayer; + m_info.Image.NumLevels = viewInfo.numLevels; + m_info.Image.NumLayers = viewInfo.numLayers; + + m_imageView = pDevice->GetDXVKDevice()->createImageView( + GetCommonTexture(pResource)->GetImage(), viewInfo); + } + } + + + D3D11UnorderedAccessView::~D3D11UnorderedAccessView() { + ResourceReleasePrivate(m_resource); + } + + + HRESULT STDMETHODCALLTYPE D3D11UnorderedAccessView::QueryInterface(REFIID riid, void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(ID3D11DeviceChild) + || riid == __uuidof(ID3D11View) + || riid == __uuidof(ID3D11UnorderedAccessView) + || riid == __uuidof(ID3D11UnorderedAccessView1)) { + *ppvObject = ref(this); + return S_OK; + } + + Logger::warn("D3D11UnorderedAccessView::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + void STDMETHODCALLTYPE D3D11UnorderedAccessView::GetResource(ID3D11Resource** ppResource) { + *ppResource = ref(m_resource); + } + + + void STDMETHODCALLTYPE D3D11UnorderedAccessView::GetDesc(D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc) { + pDesc->Format = m_desc.Format; + pDesc->ViewDimension = m_desc.ViewDimension; + + switch (m_desc.ViewDimension) { + case D3D11_UAV_DIMENSION_UNKNOWN: + break; + + case D3D11_UAV_DIMENSION_BUFFER: + pDesc->Buffer = m_desc.Buffer; + break; + + case D3D11_UAV_DIMENSION_TEXTURE1D: + pDesc->Texture1D = m_desc.Texture1D; + break; + + case D3D11_UAV_DIMENSION_TEXTURE1DARRAY: + pDesc->Texture1DArray = m_desc.Texture1DArray; + break; + + case D3D11_UAV_DIMENSION_TEXTURE2D: + pDesc->Texture2D.MipSlice = m_desc.Texture2D.MipSlice; + break; + + case D3D11_UAV_DIMENSION_TEXTURE2DARRAY: + pDesc->Texture2DArray.MipSlice = m_desc.Texture2DArray.MipSlice; + pDesc->Texture2DArray.FirstArraySlice = m_desc.Texture2DArray.FirstArraySlice; + pDesc->Texture2DArray.ArraySize = m_desc.Texture2DArray.ArraySize; + break; + + case D3D11_UAV_DIMENSION_TEXTURE3D: + pDesc->Texture3D = m_desc.Texture3D; + break; + } + } + + + void STDMETHODCALLTYPE D3D11UnorderedAccessView::GetDesc1(D3D11_UNORDERED_ACCESS_VIEW_DESC1* pDesc) { + *pDesc = m_desc; + } + + + HRESULT D3D11UnorderedAccessView::GetDescFromResource( + ID3D11Resource* pResource, + D3D11_UNORDERED_ACCESS_VIEW_DESC1* pDesc) { + D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN; + pResource->GetType(&resourceDim); + + switch (resourceDim) { + case D3D11_RESOURCE_DIMENSION_BUFFER: { + D3D11_BUFFER_DESC bufferDesc; + static_cast(pResource)->GetDesc(&bufferDesc); + + if (bufferDesc.MiscFlags == D3D11_RESOURCE_MISC_BUFFER_STRUCTURED) { + pDesc->Format = DXGI_FORMAT_UNKNOWN; + pDesc->ViewDimension = D3D11_UAV_DIMENSION_BUFFER; + pDesc->Buffer.FirstElement = 0; + pDesc->Buffer.NumElements = bufferDesc.ByteWidth / bufferDesc.StructureByteStride; + pDesc->Buffer.Flags = 0; + return S_OK; + } + } return E_INVALIDARG; + + case D3D11_RESOURCE_DIMENSION_TEXTURE1D: { + D3D11_TEXTURE1D_DESC resourceDesc; + static_cast(pResource)->GetDesc(&resourceDesc); + + pDesc->Format = resourceDesc.Format; + + if (resourceDesc.ArraySize == 1) { + pDesc->ViewDimension = D3D11_UAV_DIMENSION_TEXTURE1D; + pDesc->Texture1D.MipSlice = 0; + } else { + pDesc->ViewDimension = D3D11_UAV_DIMENSION_TEXTURE1DARRAY; + pDesc->Texture1DArray.MipSlice = 0; + pDesc->Texture1DArray.FirstArraySlice = 0; + pDesc->Texture1DArray.ArraySize = resourceDesc.ArraySize; + } + } return S_OK; + + case D3D11_RESOURCE_DIMENSION_TEXTURE2D: { + D3D11_TEXTURE2D_DESC resourceDesc; + static_cast(pResource)->GetDesc(&resourceDesc); + + pDesc->Format = resourceDesc.Format; + + if (resourceDesc.ArraySize == 1) { + pDesc->ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D; + pDesc->Texture2D.MipSlice = 0; + pDesc->Texture2D.PlaneSlice = 0; + } else { + pDesc->ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY; + pDesc->Texture2DArray.MipSlice = 0; + pDesc->Texture2DArray.FirstArraySlice = 0; + pDesc->Texture2DArray.ArraySize = resourceDesc.ArraySize; + pDesc->Texture2DArray.PlaneSlice = 0; + } + } return S_OK; + + case D3D11_RESOURCE_DIMENSION_TEXTURE3D: { + D3D11_TEXTURE3D_DESC resourceDesc; + static_cast(pResource)->GetDesc(&resourceDesc); + + pDesc->Format = resourceDesc.Format; + pDesc->ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D; + pDesc->Texture3D.MipSlice = 0; + pDesc->Texture3D.WSize = resourceDesc.Depth; + } return S_OK; + + default: + Logger::err(str::format( + "D3D11: Unsupported dimension for unordered access view: ", + resourceDim)); + return E_INVALIDARG; + } + } + + + D3D11_UNORDERED_ACCESS_VIEW_DESC1 D3D11UnorderedAccessView::PromoteDesc( + const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc, + UINT Plane) { + D3D11_UNORDERED_ACCESS_VIEW_DESC1 dstDesc; + dstDesc.Format = pDesc->Format; + dstDesc.ViewDimension = pDesc->ViewDimension; + + switch (pDesc->ViewDimension) { + case D3D11_UAV_DIMENSION_UNKNOWN: + break; + + case D3D11_UAV_DIMENSION_BUFFER: + dstDesc.Buffer = pDesc->Buffer; + break; + + case D3D11_UAV_DIMENSION_TEXTURE1D: + dstDesc.Texture1D = pDesc->Texture1D; + break; + + case D3D11_UAV_DIMENSION_TEXTURE1DARRAY: + dstDesc.Texture1DArray = pDesc->Texture1DArray; + break; + + case D3D11_UAV_DIMENSION_TEXTURE2D: + dstDesc.Texture2D.MipSlice = pDesc->Texture2D.MipSlice; + dstDesc.Texture2D.PlaneSlice = Plane; + break; + + case D3D11_UAV_DIMENSION_TEXTURE2DARRAY: + dstDesc.Texture2DArray.MipSlice = pDesc->Texture2DArray.MipSlice; + dstDesc.Texture2DArray.FirstArraySlice = pDesc->Texture2DArray.FirstArraySlice; + dstDesc.Texture2DArray.ArraySize = pDesc->Texture2DArray.ArraySize; + dstDesc.Texture2DArray.PlaneSlice = Plane; + break; + + case D3D11_UAV_DIMENSION_TEXTURE3D: + dstDesc.Texture3D = pDesc->Texture3D; + break; + } + + return dstDesc; + } + + + HRESULT D3D11UnorderedAccessView::NormalizeDesc( + ID3D11Resource* pResource, + D3D11_UNORDERED_ACCESS_VIEW_DESC1* pDesc) { + D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN; + pResource->GetType(&resourceDim); + + DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN; + uint32_t numLayers = 0; + + switch (resourceDim) { + case D3D11_RESOURCE_DIMENSION_BUFFER: { + if (pDesc->ViewDimension != D3D11_UAV_DIMENSION_BUFFER) { + Logger::err("D3D11: Incompatible view dimension for Buffer"); + return E_INVALIDARG; + } + } break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE1D: { + D3D11_TEXTURE1D_DESC resourceDesc; + static_cast(pResource)->GetDesc(&resourceDesc); + + if (pDesc->ViewDimension != D3D11_UAV_DIMENSION_TEXTURE1D + && pDesc->ViewDimension != D3D11_UAV_DIMENSION_TEXTURE1DARRAY) { + Logger::err("D3D11: Incompatible view dimension for Texture1D"); + return E_INVALIDARG; + } + + format = resourceDesc.Format; + numLayers = resourceDesc.ArraySize; + } break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE2D: { + D3D11_TEXTURE2D_DESC resourceDesc; + static_cast(pResource)->GetDesc(&resourceDesc); + + if (pDesc->ViewDimension != D3D11_UAV_DIMENSION_TEXTURE2D + && pDesc->ViewDimension != D3D11_UAV_DIMENSION_TEXTURE2DARRAY) { + Logger::err("D3D11: Incompatible view dimension for Texture2D"); + return E_INVALIDARG; + } + + format = resourceDesc.Format; + numLayers = resourceDesc.ArraySize; + } break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE3D: { + D3D11_TEXTURE3D_DESC resourceDesc; + static_cast(pResource)->GetDesc(&resourceDesc); + + if (pDesc->ViewDimension != D3D11_UAV_DIMENSION_TEXTURE3D) { + Logger::err("D3D11: Incompatible view dimension for Texture3D"); + return E_INVALIDARG; + } + + format = resourceDesc.Format; + numLayers = std::max(resourceDesc.Depth >> pDesc->Texture3D.MipSlice, 1u); + } break; + + default: + return E_INVALIDARG; + } + + if (pDesc->Format == DXGI_FORMAT_UNKNOWN) + pDesc->Format = format; + + switch (pDesc->ViewDimension) { + case D3D11_UAV_DIMENSION_BUFFER: + if (pDesc->Buffer.NumElements == 0) + return E_INVALIDARG; + break; + + case D3D11_UAV_DIMENSION_TEXTURE1DARRAY: + if (pDesc->Texture1DArray.ArraySize > numLayers - pDesc->Texture1DArray.FirstArraySlice) + pDesc->Texture1DArray.ArraySize = numLayers - pDesc->Texture1DArray.FirstArraySlice; + break; + + case D3D11_UAV_DIMENSION_TEXTURE2D: + break; + + case D3D11_UAV_DIMENSION_TEXTURE2DARRAY: + if (pDesc->Texture2DArray.ArraySize > numLayers - pDesc->Texture2DArray.FirstArraySlice) + pDesc->Texture2DArray.ArraySize = numLayers - pDesc->Texture2DArray.FirstArraySlice; + break; + + case D3D11_UAV_DIMENSION_TEXTURE3D: + if (pDesc->Texture3D.WSize > numLayers - pDesc->Texture3D.FirstWSlice) + pDesc->Texture3D.WSize = numLayers - pDesc->Texture3D.FirstWSlice; + break; + + default: + break; + } + + return S_OK; + } + + + UINT D3D11UnorderedAccessView::GetPlaneSlice(const D3D11_UNORDERED_ACCESS_VIEW_DESC1* pDesc) { + switch (pDesc->ViewDimension) { + case D3D11_UAV_DIMENSION_TEXTURE2D: + return pDesc->Texture2D.PlaneSlice; + case D3D11_UAV_DIMENSION_TEXTURE2DARRAY: + return pDesc->Texture2DArray.PlaneSlice; + default: + return 0; + } + } + + + Rc D3D11UnorderedAccessView::CreateCounterBuffer() { + Rc device = m_parent->GetDXVKDevice(); + + DxvkBufferCreateInfo info; + info.size = sizeof(uint32_t); + info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT + | VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT + | device->getShaderPipelineStages(); + info.access = VK_ACCESS_TRANSFER_WRITE_BIT + | VK_ACCESS_TRANSFER_READ_BIT + | VK_ACCESS_SHADER_WRITE_BIT + | VK_ACCESS_SHADER_READ_BIT; + return device->createBuffer(info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/d3d11_view_uav.h b/utils/dxvk-1.10.3/src/d3d11/d3d11_view_uav.h new file mode 100644 index 00000000000..3076fe0948d --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/d3d11_view_uav.h @@ -0,0 +1,94 @@ +#pragma once + +#include "../dxvk/dxvk_device.h" + +#include "d3d11_device_child.h" +#include "d3d11_view.h" + +namespace dxvk { + + class D3D11Device; + + /** + * \brief Unordered access view + * + * Unordered access views are special in that they can + * have counters, which can be used inside shaders to + * atomically append or consume structures. + */ + class D3D11UnorderedAccessView : public D3D11DeviceChild { + + public: + + D3D11UnorderedAccessView( + D3D11Device* pDevice, + ID3D11Resource* pResource, + const D3D11_UNORDERED_ACCESS_VIEW_DESC1* pDesc); + + ~D3D11UnorderedAccessView(); + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) final; + + void STDMETHODCALLTYPE GetResource(ID3D11Resource** ppResource) final; + + void STDMETHODCALLTYPE GetDesc(D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc) final; + + void STDMETHODCALLTYPE GetDesc1(D3D11_UNORDERED_ACCESS_VIEW_DESC1* pDesc) final; + + const D3D11_VK_VIEW_INFO& GetViewInfo() const { + return m_info; + } + + BOOL HasBindFlag(UINT Flags) const { + return m_info.BindFlags & Flags; + } + + D3D11_RESOURCE_DIMENSION GetResourceType() const { + D3D11_RESOURCE_DIMENSION type; + m_resource->GetType(&type); + return type; + } + + Rc GetBufferView() const { + return m_bufferView; + } + + Rc GetImageView() const { + return m_imageView; + } + + DxvkBufferSlice GetCounterSlice() const { + return m_counterBuffer != nullptr + ? DxvkBufferSlice(m_counterBuffer) + : DxvkBufferSlice(); + } + + static HRESULT GetDescFromResource( + ID3D11Resource* pResource, + D3D11_UNORDERED_ACCESS_VIEW_DESC1* pDesc); + + static D3D11_UNORDERED_ACCESS_VIEW_DESC1 PromoteDesc( + const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc, + UINT Plane); + + static HRESULT NormalizeDesc( + ID3D11Resource* pResource, + D3D11_UNORDERED_ACCESS_VIEW_DESC1* pDesc); + + static UINT GetPlaneSlice( + const D3D11_UNORDERED_ACCESS_VIEW_DESC1* pDesc); + + private: + + ID3D11Resource* m_resource; + D3D11_UNORDERED_ACCESS_VIEW_DESC1 m_desc; + D3D11_VK_VIEW_INFO m_info; + Rc m_bufferView; + Rc m_imageView; + Rc m_counterBuffer; + + Rc CreateCounterBuffer(); + + }; + +} diff --git a/utils/dxvk-1.10.3/src/d3d11/meson.build b/utils/dxvk-1.10.3/src/d3d11/meson.build new file mode 100644 index 00000000000..85fe7807485 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/meson.build @@ -0,0 +1,81 @@ +d3d11_res = wrc_generator.process('version.rc') + +dxgi_common_src = [ + '../dxgi/dxgi_format.cpp', + '../dxgi/dxgi_monitor.cpp', + '../dxgi/dxgi_swapchain.cpp', +] + +d3d10_src = [ + '../d3d10/d3d10_blend.cpp', + '../d3d10/d3d10_buffer.cpp', + '../d3d10/d3d10_depth_stencil.cpp', + '../d3d10/d3d10_device.cpp', + '../d3d10/d3d10_input_layout.cpp', + '../d3d10/d3d10_multithread.cpp', + '../d3d10/d3d10_query.cpp', + '../d3d10/d3d10_rasterizer.cpp', + '../d3d10/d3d10_sampler.cpp', + '../d3d10/d3d10_texture.cpp', + '../d3d10/d3d10_util.cpp', + '../d3d10/d3d10_view_dsv.cpp', + '../d3d10/d3d10_view_rtv.cpp', + '../d3d10/d3d10_view_srv.cpp', +] + +d3d11_src = [ + 'd3d11_annotation.cpp', + 'd3d11_blend.cpp', + 'd3d11_buffer.cpp', + 'd3d11_class_linkage.cpp', + 'd3d11_cmdlist.cpp', + 'd3d11_context.cpp', + 'd3d11_context_def.cpp', + 'd3d11_context_ext.cpp', + 'd3d11_context_imm.cpp', + 'd3d11_cuda.cpp', + 'd3d11_depth_stencil.cpp', + 'd3d11_device.cpp', + 'd3d11_enums.cpp', + 'd3d11_fence.cpp', + 'd3d11_gdi.cpp', + 'd3d11_initializer.cpp', + 'd3d11_input_layout.cpp', + 'd3d11_interop.cpp', + 'd3d11_main.cpp', + 'd3d11_options.cpp', + 'd3d11_query.cpp', + 'd3d11_rasterizer.cpp', + 'd3d11_resource.cpp', + 'd3d11_sampler.cpp', + 'd3d11_shader.cpp', + 'd3d11_state.cpp', + 'd3d11_state_object.cpp', + 'd3d11_swapchain.cpp', + 'd3d11_texture.cpp', + 'd3d11_util.cpp', + 'd3d11_video.cpp', + 'd3d11_view_dsv.cpp', + 'd3d11_view_rtv.cpp', + 'd3d11_view_srv.cpp', + 'd3d11_view_uav.cpp', +] + +d3d11_shaders = files([ + 'shaders/d3d11_video_blit_frag.frag', + 'shaders/d3d11_video_blit_vert.vert', +]) + +d3d11_dll = shared_library('d3d11'+dll_ext, dxgi_common_src + d3d11_src + d3d10_src, + glsl_generator.process(d3d11_shaders), d3d11_res, + name_prefix : '', + dependencies : [ lib_dxgi, dxbc_dep, dxvk_dep ], + include_directories : dxvk_include_path, + install : true, + vs_module_defs : 'd3d11'+def_spec_ext, +) + +d3d11_dep = declare_dependency( + link_with : [ d3d11_dll ], + include_directories : [ dxvk_include_path ], +) diff --git a/utils/dxvk-1.10.3/src/d3d11/shaders/d3d11_video_blit_frag.frag b/utils/dxvk-1.10.3/src/d3d11/shaders/d3d11_video_blit_frag.frag new file mode 100644 index 00000000000..d659176cc01 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/shaders/d3d11_video_blit_frag.frag @@ -0,0 +1,56 @@ +#version 450 + +layout(constant_id = 3) const bool c_planar = true; + +// Can't use matrix types here since even a two-row +// matrix will be padded to 16 bytes per column for +// absolutely no reason +layout(std140, set = 0, binding = 0) +uniform ubo_t { + vec4 color_matrix_r1; + vec4 color_matrix_r2; + vec4 color_matrix_r3; + vec2 coord_matrix_c1; + vec2 coord_matrix_c2; + vec2 coord_matrix_c3; + float y_min; + float y_max; +}; + +layout(location = 0) in vec2 i_texcoord; +layout(location = 0) out vec4 o_color; + +layout(set = 0, binding = 1) uniform sampler s_sampler; +layout(set = 0, binding = 2) uniform texture2D s_inputY; +layout(set = 0, binding = 3) uniform texture2D s_inputCbCr; + +void main() { + // Transform input texture coordinates to + // account for rotation and source rectangle + mat3x2 coord_matrix = mat3x2( + coord_matrix_c1, + coord_matrix_c2, + coord_matrix_c3); + + vec2 coord = coord_matrix * vec3(i_texcoord, 1.0f); + + // Fetch source image color + vec4 color = vec4(0.0f, 0.0f, 0.0f, 1.0f); + + if (c_planar) { + color.g = texture(sampler2D(s_inputY, s_sampler), coord).r; + color.rb = texture(sampler2D(s_inputCbCr, s_sampler), coord).gr; + color.g = clamp((color.g - y_min) / (y_max - y_min), 0.0f, 1.0f); + } else { + color = texture(sampler2D(s_inputY, s_sampler), coord); + } + + // Color space transformation + mat3x4 color_matrix = mat3x4( + color_matrix_r1, + color_matrix_r2, + color_matrix_r3); + + o_color.rgb = vec4(color.rgb, 1.0f) * color_matrix; + o_color.a = color.a; +} diff --git a/utils/dxvk-1.10.3/src/d3d11/shaders/d3d11_video_blit_vert.vert b/utils/dxvk-1.10.3/src/d3d11/shaders/d3d11_video_blit_vert.vert new file mode 100644 index 00000000000..1980b3c9d0d --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/shaders/d3d11_video_blit_vert.vert @@ -0,0 +1,12 @@ +#version 450 + +layout(location = 0) out vec2 o_texcoord; + +void main() { + vec2 coord = vec2( + float(gl_VertexIndex & 1) * 2.0f, + float(gl_VertexIndex & 2)); + + o_texcoord = coord; + gl_Position = vec4(-1.0f + 2.0f * coord, 0.0f, 1.0f); +} diff --git a/utils/dxvk-1.10.3/src/d3d11/version.rc b/utils/dxvk-1.10.3/src/d3d11/version.rc new file mode 100644 index 00000000000..060ef7bc2cc --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d11/version.rc @@ -0,0 +1,32 @@ +#include + +// DLL version information. +VS_VERSION_INFO VERSIONINFO +FILEVERSION 10,0,17763,1 +PRODUCTVERSION 10,0,17763,1 +FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +FILEFLAGS 0 +FILEOS VOS_NT_WINDOWS32 +FILETYPE VFT_DLL +FILESUBTYPE VFT2_UNKNOWN +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "080904b0" + BEGIN + VALUE "CompanyName", "DXVK" + VALUE "FileDescription", "Direct3D 11 Runtime" + VALUE "FileVersion", "10.0.17763.1 (WinBuild.160101.0800)" + VALUE "InternalName", "D3D11.dll" + VALUE "LegalCopyright", "zlib/libpng license" + VALUE "OriginalFilename", "D3D11.dll" + VALUE "ProductName", "DXVK" + VALUE "ProductVersion", "10.0.17763.1" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0809, 1200 + END +END + diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9.def b/utils/dxvk-1.10.3/src/d3d9/d3d9.def new file mode 100644 index 00000000000..4e3f9ae516c --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9.def @@ -0,0 +1,27 @@ +LIBRARY D3D9.DLL +EXPORTS + Direct3DShaderValidatorCreate9 @24 + + PSGPError @25 + PSGPSampleTexture @26 + + D3DPERF_BeginEvent @27 + D3DPERF_EndEvent @28 + D3DPERF_GetStatus @29 + D3DPERF_QueryRepeatFrame @30 + D3DPERF_SetMarker @31 + D3DPERF_SetOptions @32 + D3DPERF_SetRegion @33 + + DebugSetLevel @34 + DebugSetMute @35 + + Direct3D9EnableMaximizedWindowedModeShim @36 + + Direct3DCreate9 @ 37 + Direct3DCreate9Ex @ 38 + + DXVK_RegisterAnnotation @ 28257 NONAME + DXVK_UnRegisterAnnotation @ 28258 NONAME + + Direct3D9ForceHybridEnumeration @16 NONAME PRIVATE diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_adapter.cpp b/utils/dxvk-1.10.3/src/d3d9/d3d9_adapter.cpp new file mode 100644 index 00000000000..4e93fb1adc7 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_adapter.cpp @@ -0,0 +1,816 @@ +#include "d3d9_adapter.h" + +#include "d3d9_interface.h" +#include "d3d9_monitor.h" +#include "d3d9_caps.h" +#include "d3d9_util.h" + +#include "../util/util_bit.h" +#include "../util/util_luid.h" +#include "../util/util_ratio.h" + +#include + +namespace dxvk { + + const char* GetDriverDLL(DxvkGpuVendor vendor) { + switch (vendor) { + default: + case DxvkGpuVendor::Nvidia: return "nvd3dum.dll"; + +#if defined(__x86_64__) || defined(_M_X64) + case DxvkGpuVendor::Amd: return "aticfx64.dll"; + case DxvkGpuVendor::Intel: return "igdumd64.dll"; +#else + case DxvkGpuVendor::Amd: return "aticfx32.dll"; + case DxvkGpuVendor::Intel: return "igdumd32.dll"; +#endif + } + } + + + D3D9Adapter::D3D9Adapter( + D3D9InterfaceEx* pParent, + Rc Adapter, + UINT Ordinal, + UINT DisplayIndex) + : m_parent (pParent), + m_adapter (Adapter), + m_ordinal (Ordinal), + m_displayIndex (DisplayIndex), + m_modeCacheFormat (D3D9Format::Unknown), + m_d3d9Formats (Adapter, m_parent->GetOptions()) { + m_adapter->logAdapterInfo(); + } + + template + static void copyToStringArray(char (&dst)[N], const char* src) { + dxvk::str::strlcpy(dst, src, N); + } + + + HRESULT D3D9Adapter::GetAdapterIdentifier( + DWORD Flags, + D3DADAPTER_IDENTIFIER9* pIdentifier) { + if (unlikely(pIdentifier == nullptr)) + return D3DERR_INVALIDCALL; + + auto& options = m_parent->GetOptions(); + + const auto& props = m_adapter->deviceProperties(); + + DISPLAY_DEVICEA device = { }; + device.cb = sizeof(device); + + if (!::EnumDisplayDevicesA(nullptr, m_displayIndex, &device, 0)) { + Logger::err("D3D9Adapter::GetAdapterIdentifier: Failed to query display info"); + return D3DERR_INVALIDCALL; + } + + GUID guid = bit::cast(m_adapter->devicePropertiesExt().coreDeviceId.deviceUUID); + + uint32_t vendorId = options.customVendorId == -1 ? props.vendorID : uint32_t(options.customVendorId); + uint32_t deviceId = options.customDeviceId == -1 ? props.deviceID : uint32_t(options.customDeviceId); + const char* desc = options.customDeviceDesc.empty() ? props.deviceName : options.customDeviceDesc.c_str(); + const char* driver = GetDriverDLL(DxvkGpuVendor(vendorId)); + + copyToStringArray(pIdentifier->Description, desc); + copyToStringArray(pIdentifier->DeviceName, device.DeviceName); // The GDI device name. Not the actual device name. + copyToStringArray(pIdentifier->Driver, driver); // This is the driver's dll. + + pIdentifier->DeviceIdentifier = guid; + pIdentifier->DeviceId = deviceId; + pIdentifier->VendorId = vendorId; + pIdentifier->Revision = 0; + pIdentifier->SubSysId = 0; + pIdentifier->WHQLLevel = m_parent->IsExtended() ? 1 : 0; // This doesn't check with the driver on Direct3D9Ex and is always 1. + pIdentifier->DriverVersion.QuadPart = INT64_MAX; + + return D3D_OK; + } + + + HRESULT D3D9Adapter::CheckDeviceType( + D3DDEVTYPE DevType, + D3D9Format AdapterFormat, + D3D9Format BackBufferFormat, + BOOL bWindowed) { + if (!IsSupportedAdapterFormat(AdapterFormat)) + return D3DERR_NOTAVAILABLE; + + if (!IsSupportedBackBufferFormat(AdapterFormat, BackBufferFormat, bWindowed)) + return D3DERR_NOTAVAILABLE; + + return D3D_OK; + } + + + HRESULT D3D9Adapter::CheckDeviceFormat( + D3DDEVTYPE DeviceType, + D3D9Format AdapterFormat, + DWORD Usage, + D3DRESOURCETYPE RType, + D3D9Format CheckFormat) { + if (!IsSupportedAdapterFormat(AdapterFormat)) + return D3DERR_NOTAVAILABLE; + + const bool dmap = Usage & D3DUSAGE_DMAP; + const bool rt = Usage & D3DUSAGE_RENDERTARGET; + const bool ds = Usage & D3DUSAGE_DEPTHSTENCIL; + + const bool surface = RType == D3DRTYPE_SURFACE; + const bool texture = RType == D3DRTYPE_TEXTURE; + + const bool twoDimensional = surface || texture; + + const bool srgb = (Usage & (D3DUSAGE_QUERY_SRGBREAD | D3DUSAGE_QUERY_SRGBWRITE)) != 0; + + if (CheckFormat == D3D9Format::INST) + return D3D_OK; + + if (rt && CheckFormat == D3D9Format::A8 && m_parent->GetOptions().disableA8RT) + return D3DERR_NOTAVAILABLE; + + if (ds && !IsDepthFormat(CheckFormat)) + return D3DERR_NOTAVAILABLE; + + if (rt && CheckFormat == D3D9Format::NULL_FORMAT && twoDimensional) + return D3D_OK; + + if (rt && CheckFormat == D3D9Format::RESZ && surface) + return D3D_OK; + + if (CheckFormat == D3D9Format::ATOC && surface) + return D3D_OK; + + if (CheckFormat == D3D9Format::NVDB && surface) + return m_adapter->features().core.features.depthBounds + ? D3D_OK + : D3DERR_NOTAVAILABLE; + + // I really don't want to support this... + if (dmap) + return D3DERR_NOTAVAILABLE; + + auto mapping = m_d3d9Formats.GetFormatMapping(CheckFormat); + if (mapping.FormatColor == VK_FORMAT_UNDEFINED) + return D3DERR_NOTAVAILABLE; + + if (mapping.FormatSrgb == VK_FORMAT_UNDEFINED && srgb) + return D3DERR_NOTAVAILABLE; + + if (RType == D3DRTYPE_VERTEXBUFFER || RType == D3DRTYPE_INDEXBUFFER) + return D3D_OK; + + // Let's actually ask Vulkan now that we got some quirks out the way! + return CheckDeviceVkFormat(mapping.FormatColor, Usage, RType); + } + + + HRESULT D3D9Adapter::CheckDeviceMultiSampleType( + D3DDEVTYPE DeviceType, + D3D9Format SurfaceFormat, + BOOL Windowed, + D3DMULTISAMPLE_TYPE MultiSampleType, + DWORD* pQualityLevels) { + if (pQualityLevels != nullptr) + *pQualityLevels = 1; + + auto dst = ConvertFormatUnfixed(SurfaceFormat); + if (dst.FormatColor == VK_FORMAT_UNDEFINED) + return D3DERR_NOTAVAILABLE; + + if (MultiSampleType != D3DMULTISAMPLE_NONE + && (SurfaceFormat == D3D9Format::D32_LOCKABLE + || SurfaceFormat == D3D9Format::D32F_LOCKABLE + || SurfaceFormat == D3D9Format::D16_LOCKABLE)) + return D3DERR_NOTAVAILABLE; + + uint32_t sampleCount = std::max(MultiSampleType, 1u); + + // Check if this is a power of two... + if (sampleCount & (sampleCount - 1)) + return D3DERR_NOTAVAILABLE; + + // Therefore... + VkSampleCountFlags sampleFlags = VkSampleCountFlags(sampleCount); + + auto availableFlags = !IsDepthFormat(SurfaceFormat) + ? m_adapter->deviceProperties().limits.framebufferColorSampleCounts + : m_adapter->deviceProperties().limits.framebufferDepthSampleCounts; + + if (!(availableFlags & sampleFlags)) + return D3DERR_NOTAVAILABLE; + + if (pQualityLevels != nullptr) { + if (MultiSampleType == D3DMULTISAMPLE_NONMASKABLE) + *pQualityLevels = 32 - bit::lzcnt(availableFlags); + else + *pQualityLevels = 1; + } + + return D3D_OK; + } + + + HRESULT D3D9Adapter::CheckDepthStencilMatch( + D3DDEVTYPE DeviceType, + D3D9Format AdapterFormat, + D3D9Format RenderTargetFormat, + D3D9Format DepthStencilFormat) { + if (!IsDepthFormat(DepthStencilFormat)) + return D3DERR_NOTAVAILABLE; + + if (RenderTargetFormat == dxvk::D3D9Format::NULL_FORMAT) + return D3D_OK; + + auto mapping = ConvertFormatUnfixed(RenderTargetFormat); + if (mapping.FormatColor == VK_FORMAT_UNDEFINED) + return D3DERR_NOTAVAILABLE; + + return D3D_OK; + } + + + HRESULT D3D9Adapter::CheckDeviceFormatConversion( + D3DDEVTYPE DeviceType, + D3D9Format SourceFormat, + D3D9Format TargetFormat) { + bool sourceSupported = SourceFormat != D3D9Format::Unknown + && IsSupportedBackBufferFormat(SourceFormat); + bool targetSupported = TargetFormat == D3D9Format::X1R5G5B5 + || TargetFormat == D3D9Format::A1R5G5B5 + || TargetFormat == D3D9Format::R5G6B5 + // || TargetFormat == D3D9Format::R8G8B8 <-- We don't support R8G8B8 + || TargetFormat == D3D9Format::X8R8G8B8 + || TargetFormat == D3D9Format::A8R8G8B8 + || TargetFormat == D3D9Format::A2R10G10B10 + || TargetFormat == D3D9Format::A16B16G16R16 + || TargetFormat == D3D9Format::A2B10G10R10 + || TargetFormat == D3D9Format::A8B8G8R8 + || TargetFormat == D3D9Format::X8B8G8R8 + || TargetFormat == D3D9Format::A16B16G16R16F + || TargetFormat == D3D9Format::A32B32G32R32F; + + return (sourceSupported && targetSupported) + ? D3D_OK + : D3DERR_NOTAVAILABLE; + } + + + HRESULT D3D9Adapter::GetDeviceCaps( + D3DDEVTYPE DeviceType, + D3DCAPS9* pCaps) { + using namespace dxvk::caps; + + if (pCaps == nullptr) + return D3DERR_INVALIDCALL; + + auto& options = m_parent->GetOptions(); + + // TODO: Actually care about what the adapter supports here. + // ^ For Intel and older cards most likely here. + + // Device Type + pCaps->DeviceType = DeviceType; + // Adapter Id + pCaps->AdapterOrdinal = m_ordinal; + // Caps 1 + pCaps->Caps = D3DCAPS_READ_SCANLINE; + // Caps 2 + pCaps->Caps2 = D3DCAPS2_FULLSCREENGAMMA + /* | D3DCAPS2_CANCALIBRATEGAMMA */ + /* | D3DCAPS2_RESERVED */ + /* | D3DCAPS2_CANMANAGERESOURCE */ + | D3DCAPS2_DYNAMICTEXTURES + | D3DCAPS2_CANAUTOGENMIPMAP + /* | D3DCAPS2_CANSHARERESOURCE */; + // Caps 3 + pCaps->Caps3 = D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD + | D3DCAPS3_LINEAR_TO_SRGB_PRESENTATION + | D3DCAPS3_COPY_TO_VIDMEM + | D3DCAPS3_COPY_TO_SYSTEMMEM + /* | D3DCAPS3_DXVAHD */ + /* | D3DCAPS3_DXVAHD_LIMITED */; + // Presentation Intervals + pCaps->PresentationIntervals = D3DPRESENT_INTERVAL_DEFAULT + | D3DPRESENT_INTERVAL_ONE + | D3DPRESENT_INTERVAL_TWO + | D3DPRESENT_INTERVAL_THREE + | D3DPRESENT_INTERVAL_FOUR + | D3DPRESENT_INTERVAL_IMMEDIATE; + // Cursor + pCaps->CursorCaps = D3DCURSORCAPS_COLOR; // I do not support Cursor yet, but I don't want to say I don't support it for compatibility reasons. + // Dev Caps + pCaps->DevCaps = D3DDEVCAPS_EXECUTESYSTEMMEMORY + | D3DDEVCAPS_EXECUTEVIDEOMEMORY + | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY + | D3DDEVCAPS_TLVERTEXVIDEOMEMORY + /* | D3DDEVCAPS_TEXTURESYSTEMMEMORY */ + | D3DDEVCAPS_TEXTUREVIDEOMEMORY + | D3DDEVCAPS_DRAWPRIMTLVERTEX + | D3DDEVCAPS_CANRENDERAFTERFLIP + | D3DDEVCAPS_TEXTURENONLOCALVIDMEM + | D3DDEVCAPS_DRAWPRIMITIVES2 + /* | D3DDEVCAPS_SEPARATETEXTUREMEMORIES */ + | D3DDEVCAPS_DRAWPRIMITIVES2EX + | D3DDEVCAPS_HWTRANSFORMANDLIGHT + | D3DDEVCAPS_CANBLTSYSTONONLOCAL + | D3DDEVCAPS_HWRASTERIZATION + | D3DDEVCAPS_PUREDEVICE + /* | D3DDEVCAPS_QUINTICRTPATCHES */ + /* | D3DDEVCAPS_RTPATCHES */ + /* | D3DDEVCAPS_RTPATCHHANDLEZERO */ + /* | D3DDEVCAPS_NPATCHES */; + // Primitive Misc. Caps + pCaps->PrimitiveMiscCaps = D3DPMISCCAPS_MASKZ + | D3DPMISCCAPS_CULLNONE + | D3DPMISCCAPS_CULLCW + | D3DPMISCCAPS_CULLCCW + | D3DPMISCCAPS_COLORWRITEENABLE + | D3DPMISCCAPS_CLIPPLANESCALEDPOINTS + | D3DPMISCCAPS_CLIPTLVERTS + | D3DPMISCCAPS_TSSARGTEMP + | D3DPMISCCAPS_BLENDOP + /* | D3DPMISCCAPS_NULLREFERENCE */ + | D3DPMISCCAPS_INDEPENDENTWRITEMASKS + | D3DPMISCCAPS_PERSTAGECONSTANT + | D3DPMISCCAPS_FOGANDSPECULARALPHA + | D3DPMISCCAPS_SEPARATEALPHABLEND + | D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS + | D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING + | D3DPMISCCAPS_FOGVERTEXCLAMPED + | D3DPMISCCAPS_POSTBLENDSRGBCONVERT; + // Raster Caps + pCaps->RasterCaps = D3DPRASTERCAPS_DITHER + | D3DPRASTERCAPS_ZTEST + | D3DPRASTERCAPS_FOGVERTEX + | D3DPRASTERCAPS_FOGTABLE + | D3DPRASTERCAPS_MIPMAPLODBIAS + /* | D3DPRASTERCAPS_ZBUFFERLESSHSR */ + | D3DPRASTERCAPS_FOGRANGE + | D3DPRASTERCAPS_ANISOTROPY + /* | D3DPRASTERCAPS_WBUFFER */ + | D3DPRASTERCAPS_WFOG + | D3DPRASTERCAPS_ZFOG + | D3DPRASTERCAPS_COLORPERSPECTIVE + | D3DPRASTERCAPS_SCISSORTEST + | D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS + | D3DPRASTERCAPS_DEPTHBIAS + | D3DPRASTERCAPS_MULTISAMPLE_TOGGLE; // <-- TODO! (but difficult in Vk) + // Z Comparison Caps + pCaps->ZCmpCaps = D3DPCMPCAPS_NEVER + | D3DPCMPCAPS_LESS + | D3DPCMPCAPS_EQUAL + | D3DPCMPCAPS_LESSEQUAL + | D3DPCMPCAPS_GREATER + | D3DPCMPCAPS_NOTEQUAL + | D3DPCMPCAPS_GREATEREQUAL + | D3DPCMPCAPS_ALWAYS; + // Source Blend Caps + pCaps->SrcBlendCaps = D3DPBLENDCAPS_ZERO + | D3DPBLENDCAPS_ONE + | D3DPBLENDCAPS_SRCCOLOR + | D3DPBLENDCAPS_INVSRCCOLOR + | D3DPBLENDCAPS_SRCALPHA + | D3DPBLENDCAPS_INVSRCALPHA + | D3DPBLENDCAPS_DESTALPHA + | D3DPBLENDCAPS_INVDESTALPHA + | D3DPBLENDCAPS_DESTCOLOR + | D3DPBLENDCAPS_INVDESTCOLOR + | D3DPBLENDCAPS_SRCALPHASAT + | D3DPBLENDCAPS_BOTHSRCALPHA + | D3DPBLENDCAPS_BOTHINVSRCALPHA + | D3DPBLENDCAPS_BLENDFACTOR + | D3DPBLENDCAPS_INVSRCCOLOR2 + | D3DPBLENDCAPS_SRCCOLOR2; + // Destination Blend Caps + pCaps->DestBlendCaps = pCaps->SrcBlendCaps; + // Alpha Comparison Caps + pCaps->AlphaCmpCaps = pCaps->ZCmpCaps; + // Shade Caps + pCaps->ShadeCaps = D3DPSHADECAPS_COLORGOURAUDRGB + | D3DPSHADECAPS_SPECULARGOURAUDRGB + | D3DPSHADECAPS_ALPHAGOURAUDBLEND + | D3DPSHADECAPS_FOGGOURAUD; + // Texture Caps + pCaps->TextureCaps = D3DPTEXTURECAPS_PERSPECTIVE + /* | D3DPTEXTURECAPS_POW2 */ + | D3DPTEXTURECAPS_ALPHA + /* | D3DPTEXTURECAPS_SQUAREONLY */ + | D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE + | D3DPTEXTURECAPS_ALPHAPALETTE + /* | D3DPTEXTURECAPS_NONPOW2CONDITIONAL */ + | D3DPTEXTURECAPS_PROJECTED + | D3DPTEXTURECAPS_CUBEMAP + | D3DPTEXTURECAPS_VOLUMEMAP + | D3DPTEXTURECAPS_MIPMAP + | D3DPTEXTURECAPS_MIPVOLUMEMAP + | D3DPTEXTURECAPS_MIPCUBEMAP + /* | D3DPTEXTURECAPS_CUBEMAP_POW2 */ + /* | D3DPTEXTURECAPS_VOLUMEMAP_POW2 */ + /* | D3DPTEXTURECAPS_NOPROJECTEDBUMPENV */; + // Texture Filter Caps + pCaps->TextureFilterCaps = D3DPTFILTERCAPS_MINFPOINT + | D3DPTFILTERCAPS_MINFLINEAR + | D3DPTFILTERCAPS_MINFANISOTROPIC + /* | D3DPTFILTERCAPS_MINFPYRAMIDALQUAD */ + /* | D3DPTFILTERCAPS_MINFGAUSSIANQUAD */ + | D3DPTFILTERCAPS_MIPFPOINT + | D3DPTFILTERCAPS_MIPFLINEAR + /* | D3DPTFILTERCAPS_CONVOLUTIONMONO */ + | D3DPTFILTERCAPS_MAGFPOINT + | D3DPTFILTERCAPS_MAGFLINEAR + | D3DPTFILTERCAPS_MAGFANISOTROPIC + /* | D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD */ + /* | D3DPTFILTERCAPS_MAGFGAUSSIANQUAD */; + // Cube Texture Filter Caps + pCaps->CubeTextureFilterCaps = pCaps->TextureFilterCaps; + // Volume Texture Filter Caps + pCaps->VolumeTextureFilterCaps = pCaps->TextureFilterCaps; + // Texture Address Caps + pCaps->TextureAddressCaps = D3DPTADDRESSCAPS_WRAP + | D3DPTADDRESSCAPS_MIRROR + | D3DPTADDRESSCAPS_CLAMP + | D3DPTADDRESSCAPS_BORDER + | D3DPTADDRESSCAPS_INDEPENDENTUV + | D3DPTADDRESSCAPS_MIRRORONCE; + // Volume Texture Address Caps + pCaps->VolumeTextureAddressCaps = pCaps->TextureAddressCaps; + // Line Caps + pCaps->LineCaps = D3DLINECAPS_TEXTURE + | D3DLINECAPS_ZTEST + | D3DLINECAPS_BLEND + | D3DLINECAPS_ALPHACMP + | D3DLINECAPS_FOG + | D3DLINECAPS_ANTIALIAS; //<-- Lying about doing AA lines here, we don't *fully* support that. + // Max Texture Width + pCaps->MaxTextureWidth = MaxTextureDimension; + // Max Texture Height + pCaps->MaxTextureHeight = MaxTextureDimension; + // Max Volume Extent + pCaps->MaxVolumeExtent = 8192; + // Max Texture Repeat + pCaps->MaxTextureRepeat = 8192; + // Max Texture Aspect Ratio + pCaps->MaxTextureAspectRatio = 8192; + // Max Anisotropy + pCaps->MaxAnisotropy = 16; + // Max Vertex W + pCaps->MaxVertexW = 1e10f; + // Guard Bands + pCaps->GuardBandLeft = -32768.0f; + pCaps->GuardBandTop = -32768.0f; + pCaps->GuardBandRight = 32768.0f; + pCaps->GuardBandBottom = 32768.0f; + // Extents Adjust + pCaps->ExtentsAdjust = 0.0f; + // Stencil Caps + pCaps->StencilCaps = D3DSTENCILCAPS_KEEP + | D3DSTENCILCAPS_ZERO + | D3DSTENCILCAPS_REPLACE + | D3DSTENCILCAPS_INCRSAT + | D3DSTENCILCAPS_DECRSAT + | D3DSTENCILCAPS_INVERT + | D3DSTENCILCAPS_INCR + | D3DSTENCILCAPS_DECR + | D3DSTENCILCAPS_TWOSIDED; + // FVF Caps + pCaps->FVFCaps = (MaxSimultaneousTextures & D3DFVFCAPS_TEXCOORDCOUNTMASK) + /* | D3DFVFCAPS_DONOTSTRIPELEMENTS */ + | D3DFVFCAPS_PSIZE; + // Texture Op Caps + pCaps->TextureOpCaps = D3DTEXOPCAPS_DISABLE + | D3DTEXOPCAPS_SELECTARG1 + | D3DTEXOPCAPS_SELECTARG2 + | D3DTEXOPCAPS_MODULATE + | D3DTEXOPCAPS_MODULATE2X + | D3DTEXOPCAPS_MODULATE4X + | D3DTEXOPCAPS_ADD + | D3DTEXOPCAPS_ADDSIGNED + | D3DTEXOPCAPS_ADDSIGNED2X + | D3DTEXOPCAPS_SUBTRACT + | D3DTEXOPCAPS_ADDSMOOTH + | D3DTEXOPCAPS_BLENDDIFFUSEALPHA + | D3DTEXOPCAPS_BLENDTEXTUREALPHA + | D3DTEXOPCAPS_BLENDFACTORALPHA + | D3DTEXOPCAPS_BLENDTEXTUREALPHAPM + | D3DTEXOPCAPS_BLENDCURRENTALPHA + | D3DTEXOPCAPS_PREMODULATE + | D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR + | D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA + | D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR + | D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA + | D3DTEXOPCAPS_BUMPENVMAP + | D3DTEXOPCAPS_BUMPENVMAPLUMINANCE + | D3DTEXOPCAPS_DOTPRODUCT3 + | D3DTEXOPCAPS_MULTIPLYADD + | D3DTEXOPCAPS_LERP; + // Max Texture Blend Stages + pCaps->MaxTextureBlendStages = MaxTextureBlendStages; + // Max Simultaneous Textures + pCaps->MaxSimultaneousTextures = MaxSimultaneousTextures; + // Vertex Processing Caps + pCaps->VertexProcessingCaps = D3DVTXPCAPS_TEXGEN + | D3DVTXPCAPS_MATERIALSOURCE7 + | D3DVTXPCAPS_DIRECTIONALLIGHTS + | D3DVTXPCAPS_POSITIONALLIGHTS + | D3DVTXPCAPS_LOCALVIEWER + | D3DVTXPCAPS_TWEENING + | D3DVTXPCAPS_TEXGEN_SPHEREMAP + /* | D3DVTXPCAPS_NO_TEXGEN_NONLOCALVIEWER*/; + // Max Active Lights + pCaps->MaxActiveLights = caps::MaxEnabledLights; + // Max User Clip Planes + pCaps->MaxUserClipPlanes = MaxClipPlanes; + // Max Vertex Blend Matrices + pCaps->MaxVertexBlendMatrices = 4; + // Max Vertex Blend Matrix Index + pCaps->MaxVertexBlendMatrixIndex = 8; + // Max Point Size + pCaps->MaxPointSize = 256.0f; + // Max Primitive Count + pCaps->MaxPrimitiveCount = 0x00555555; + // Max Vertex Index + pCaps->MaxVertexIndex = 0x00ffffff; + // Max Streams + pCaps->MaxStreams = MaxStreams; + // Max Stream Stride + pCaps->MaxStreamStride = 508; // bytes + + const uint32_t majorVersion = options.shaderModel; + const uint32_t minorVersion = options.shaderModel != 1 ? 0 : 4; + + // Shader Versions + pCaps->VertexShaderVersion = D3DVS_VERSION(majorVersion, minorVersion); + pCaps->PixelShaderVersion = D3DPS_VERSION(majorVersion, minorVersion); + + // Max Vertex Shader Const + pCaps->MaxVertexShaderConst = MaxFloatConstantsVS; + // Max PS1 Value + pCaps->PixelShader1xMaxValue = FLT_MAX; + // Dev Caps 2 + pCaps->DevCaps2 = D3DDEVCAPS2_STREAMOFFSET + /* | D3DDEVCAPS2_DMAPNPATCH */ + /* | D3DDEVCAPS2_ADAPTIVETESSRTPATCH */ + /* | D3DDEVCAPS2_ADAPTIVETESSNPATCH */ + | D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES + /* | D3DDEVCAPS2_PRESAMPLEDDMAPNPATCH */ + | D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET; + // Max N Patch Tesselation Level + pCaps->MaxNpatchTessellationLevel = 0.0f; + // Reserved for... something + pCaps->Reserved5 = 0; + // Master adapter for us is adapter 0, atm... + pCaps->MasterAdapterOrdinal = 0; + // The group of adapters this one is in + pCaps->AdapterOrdinalInGroup = 0; + // Number of adapters in current group + pCaps->NumberOfAdaptersInGroup = 1; + // Decl Type Caps + pCaps->DeclTypes = D3DDTCAPS_UBYTE4 + | D3DDTCAPS_UBYTE4N + | D3DDTCAPS_SHORT2N + | D3DDTCAPS_SHORT4N + | D3DDTCAPS_USHORT2N + | D3DDTCAPS_USHORT4N + | D3DDTCAPS_UDEC3 + | D3DDTCAPS_DEC3N + | D3DDTCAPS_FLOAT16_2 + | D3DDTCAPS_FLOAT16_4; + // Number of simultaneous RTs + pCaps->NumSimultaneousRTs = MaxSimultaneousRenderTargets; + // Possible StretchRect filters + pCaps->StretchRectFilterCaps = D3DPTFILTERCAPS_MINFPOINT + | D3DPTFILTERCAPS_MINFLINEAR + /* | D3DPTFILTERCAPS_MINFANISOTROPIC */ + /* | D3DPTFILTERCAPS_MINFPYRAMIDALQUAD */ + /* | D3DPTFILTERCAPS_MINFGAUSSIANQUAD */ + /* | D3DPTFILTERCAPS_MIPFPOINT */ + /* | D3DPTFILTERCAPS_MIPFLINEAR */ + /* | D3DPTFILTERCAPS_CONVOLUTIONMONO */ + | D3DPTFILTERCAPS_MAGFPOINT + | D3DPTFILTERCAPS_MAGFLINEAR + /* | D3DPTFILTERCAPS_MAGFANISOTROPIC */ + /* | D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD */ + /* | D3DPTFILTERCAPS_MAGFGAUSSIANQUAD */; + + // Not too bothered about doing these longhand + // We should match whatever my AMD hardware reports here + // methinks for the best chance of stuff working. + pCaps->VS20Caps.Caps = 1; + pCaps->VS20Caps.DynamicFlowControlDepth = 24; + pCaps->VS20Caps.NumTemps = 32; + pCaps->VS20Caps.StaticFlowControlDepth = 4; + + pCaps->PS20Caps.Caps = 31; + pCaps->PS20Caps.DynamicFlowControlDepth = 24; + pCaps->PS20Caps.NumTemps = 32; + pCaps->PS20Caps.StaticFlowControlDepth = 4; + + pCaps->PS20Caps.NumInstructionSlots = options.shaderModel >= 2 ? 512 : 256; + + pCaps->VertexTextureFilterCaps = 50332416; + pCaps->MaxVShaderInstructionsExecuted = 4294967295; + pCaps->MaxPShaderInstructionsExecuted = 4294967295; + + pCaps->MaxVertexShader30InstructionSlots = options.shaderModel == 3 ? 32768 : 0; + pCaps->MaxPixelShader30InstructionSlots = options.shaderModel == 3 ? 32768 : 0; + + return D3D_OK; + } + + + HMONITOR D3D9Adapter::GetMonitor() { + return GetDefaultMonitor(); + } + + + UINT D3D9Adapter::GetAdapterModeCountEx(const D3DDISPLAYMODEFILTER* pFilter) { + if (pFilter == nullptr) + return 0; + + // We don't offer any interlaced formats here so early out and avoid destroying mode cache. + if (pFilter->ScanLineOrdering == D3DSCANLINEORDERING_INTERLACED) + return 0; + + CacheModes(EnumerateFormat(pFilter->Format)); + return m_modes.size(); + } + + + HRESULT D3D9Adapter::EnumAdapterModesEx( + const D3DDISPLAYMODEFILTER* pFilter, + UINT Mode, + D3DDISPLAYMODEEX* pMode) { + if (pMode == nullptr || pFilter == nullptr) + return D3DERR_INVALIDCALL; + + const D3D9Format format = + EnumerateFormat(pFilter->Format); + + if (FAILED(CheckDeviceFormat( + D3DDEVTYPE_HAL, EnumerateFormat(pFilter->Format), + D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, + EnumerateFormat(pFilter->Format)))) + return D3DERR_INVALIDCALL; + + CacheModes(format); + + // We don't return any scanline orderings that aren't progressive, + // The format filtering is already handled for us by cache modes + // So we can early out here and then just index. + if (pFilter->ScanLineOrdering == D3DSCANLINEORDERING_INTERLACED) + return D3DERR_INVALIDCALL; + + if (Mode >= m_modes.size()) + return D3DERR_INVALIDCALL; + + *pMode = m_modes[Mode]; + + return D3D_OK; + } + + + HRESULT D3D9Adapter::GetAdapterDisplayModeEx( + D3DDISPLAYMODEEX* pMode, + D3DDISPLAYROTATION* pRotation) { + if (pMode == nullptr) + return D3DERR_INVALIDCALL; + + if (pRotation != nullptr) + *pRotation = D3DDISPLAYROTATION_IDENTITY; + + DEVMODEW devMode = DEVMODEW(); + devMode.dmSize = sizeof(devMode); + + if (!GetMonitorDisplayMode(GetDefaultMonitor(), ENUM_CURRENT_SETTINGS, &devMode)) { + Logger::err("D3D9Adapter::GetAdapterDisplayModeEx: Failed to enum display settings"); + return D3DERR_INVALIDCALL; + } + + pMode->Size = sizeof(D3DDISPLAYMODEEX); + pMode->Width = devMode.dmPelsWidth; + pMode->Height = devMode.dmPelsHeight; + pMode->RefreshRate = devMode.dmDisplayFrequency; + pMode->Format = D3DFMT_X8R8G8B8; + pMode->ScanLineOrdering = D3DSCANLINEORDERING_PROGRESSIVE; + return D3D_OK; + } + + + HRESULT D3D9Adapter::GetAdapterLUID(LUID* pLUID) { + if (pLUID == nullptr) + return D3DERR_INVALIDCALL; + + auto& deviceId = m_adapter->devicePropertiesExt().coreDeviceId; + + if (deviceId.deviceLUIDValid) + *pLUID = bit::cast(deviceId.deviceLUID); + else + *pLUID = dxvk::GetAdapterLUID(m_ordinal); + + return D3D_OK; + } + + + HRESULT D3D9Adapter::CheckDeviceVkFormat( + VkFormat Format, + DWORD Usage, + D3DRESOURCETYPE RType) { + VkFormatFeatureFlags checkFlags = 0; + + if (RType != D3DRTYPE_SURFACE) + checkFlags |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT; + + if (Usage & D3DUSAGE_RENDERTARGET) { + checkFlags |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT; + + if (Usage & D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) + checkFlags |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT; + } + + if (Usage & D3DUSAGE_DEPTHSTENCIL) + checkFlags |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT; + else + checkFlags |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT; + + VkFormatFeatureFlags checkFlagsMipGen = checkFlags; + + if (Usage & D3DUSAGE_AUTOGENMIPMAP) { + checkFlagsMipGen |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT; + checkFlagsMipGen |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT; + } + + VkFormatProperties fmtSupport = m_adapter->formatProperties(Format); + VkFormatFeatureFlags imgFeatures = fmtSupport.optimalTilingFeatures | fmtSupport.linearTilingFeatures; + + if ((imgFeatures & checkFlags) != checkFlags) + return D3DERR_NOTAVAILABLE; + + return ((imgFeatures & checkFlagsMipGen) != checkFlagsMipGen) + ? D3DOK_NOAUTOGEN + : D3D_OK; + } + + + void D3D9Adapter::CacheModes(D3D9Format Format) { + if (!m_modes.empty() && m_modeCacheFormat == Format) + return; // We already cached the modes for this format. No need to do it again. + + m_modes.clear(); + m_modeCacheFormat = Format; + + // Skip unsupported formats + if (!IsSupportedAdapterFormat(Format)) + return; + + auto& options = m_parent->GetOptions(); + + // Walk over all modes that the display supports and + // return those that match the requested format etc. + DEVMODEW devMode = { }; + devMode.dmSize = sizeof(DEVMODEW); + + uint32_t modeIndex = 0; + + const auto forcedRatio = Ratio(options.forceAspectRatio); + + while (GetMonitorDisplayMode(GetDefaultMonitor(), modeIndex++, &devMode)) { + // Skip interlaced modes altogether + if (devMode.dmDisplayFlags & DM_INTERLACED) + continue; + + // Skip modes with incompatible formats + if (devMode.dmBitsPerPel != GetMonitorFormatBpp(Format)) + continue; + + if (!forcedRatio.undefined() && Ratio(devMode.dmPelsWidth, devMode.dmPelsHeight) != forcedRatio) + continue; + + D3DDISPLAYMODEEX mode; + mode.Size = sizeof(D3DDISPLAYMODEEX); + mode.Width = devMode.dmPelsWidth; + mode.Height = devMode.dmPelsHeight; + mode.RefreshRate = devMode.dmDisplayFrequency; + mode.Format = static_cast(Format); + mode.ScanLineOrdering = D3DSCANLINEORDERING_PROGRESSIVE; + + m_modes.push_back(mode); + } + + // Sort display modes by width, height and refresh rate, + // in that order. Some games rely on correct ordering. + std::sort(m_modes.begin(), m_modes.end(), + [](const D3DDISPLAYMODEEX& a, const D3DDISPLAYMODEEX& b) { + if (a.Width < b.Width) return true; + if (a.Width > b.Width) return false; + + if (a.Height < b.Height) return true; + if (a.Height > b.Height) return false; + + return a.RefreshRate < b.RefreshRate; + }); + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_adapter.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_adapter.h new file mode 100644 index 00000000000..0cf74981971 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_adapter.h @@ -0,0 +1,112 @@ +#pragma once + +#include "d3d9_include.h" + +#include "d3d9_options.h" +#include "d3d9_format.h" + +#include "../dxvk/dxvk_adapter.h" + +namespace dxvk { + + class D3D9InterfaceEx; + + class D3D9Adapter { + + public: + + D3D9Adapter( + D3D9InterfaceEx* pParent, + Rc Adapter, + UINT Ordinal, + UINT DisplayIndex); + + HRESULT GetAdapterIdentifier( + DWORD Flags, + D3DADAPTER_IDENTIFIER9* pIdentifier); + + HRESULT CheckDeviceType( + D3DDEVTYPE DevType, + D3D9Format AdapterFormat, + D3D9Format BackBufferFormat, + BOOL bWindowed); + + HRESULT CheckDeviceFormat( + D3DDEVTYPE DeviceType, + D3D9Format AdapterFormat, + DWORD Usage, + D3DRESOURCETYPE RType, + D3D9Format CheckFormat); + + HRESULT CheckDeviceMultiSampleType( + D3DDEVTYPE DeviceType, + D3D9Format SurfaceFormat, + BOOL Windowed, + D3DMULTISAMPLE_TYPE MultiSampleType, + DWORD* pQualityLevels); + + HRESULT CheckDepthStencilMatch( + D3DDEVTYPE DeviceType, + D3D9Format AdapterFormat, + D3D9Format RenderTargetFormat, + D3D9Format DepthStencilFormat); + + HRESULT CheckDeviceFormatConversion( + D3DDEVTYPE DeviceType, + D3D9Format SourceFormat, + D3D9Format TargetFormat); + + HRESULT GetDeviceCaps( + D3DDEVTYPE DeviceType, + D3DCAPS9* pCaps); + + HMONITOR GetMonitor(); + + UINT GetAdapterModeCountEx(const D3DDISPLAYMODEFILTER* pFilter); + + HRESULT EnumAdapterModesEx( + const D3DDISPLAYMODEFILTER* pFilter, + UINT Mode, + D3DDISPLAYMODEEX* pMode); + + HRESULT GetAdapterDisplayModeEx( + D3DDISPLAYMODEEX* pMode, + D3DDISPLAYROTATION* pRotation); + + HRESULT GetAdapterLUID(LUID* pLUID); + + UINT GetOrdinal() { return m_ordinal; } + + Rc GetDXVKAdapter() { return m_adapter; } + + D3D9_VK_FORMAT_MAPPING GetFormatMapping(D3D9Format Format) const { + return m_d3d9Formats.GetFormatMapping(Format); + } + + const DxvkFormatInfo* GetUnsupportedFormatInfo(D3D9Format Format) const { + return m_d3d9Formats.GetUnsupportedFormatInfo(Format); + } + + private: + + HRESULT CheckDeviceVkFormat( + VkFormat Format, + DWORD Usage, + D3DRESOURCETYPE RType); + + void CacheModes(D3D9Format Format); + + D3D9InterfaceEx* m_parent; + + Rc m_adapter; + UINT m_ordinal; + UINT m_displayIndex; + + std::vector m_modes; + D3D9Format m_modeCacheFormat; + + const D3D9VkFormatTable m_d3d9Formats; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_annotation.cpp b/utils/dxvk-1.10.3/src/d3d9/d3d9_annotation.cpp new file mode 100644 index 00000000000..8949d1e3b6a --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_annotation.cpp @@ -0,0 +1,174 @@ +#include "d3d9_annotation.h" + +namespace dxvk { + + //////////////////////////// + // D3D9GlobalAnnotationList + //////////////////////////// + + D3D9GlobalAnnotationList::D3D9GlobalAnnotationList() + : m_shouldAnnotate(false) + , m_eventDepth(0) + {} + + + D3D9GlobalAnnotationList::~D3D9GlobalAnnotationList() + {} + + + void D3D9GlobalAnnotationList::RegisterAnnotator(IDXVKUserDefinedAnnotation* annotation) { + auto lock = std::unique_lock(m_mutex); + m_shouldAnnotate = true; + m_annotations.push_back(annotation); + } + + + void D3D9GlobalAnnotationList::UnregisterAnnotator(IDXVKUserDefinedAnnotation* annotation) { + auto lock = std::unique_lock(m_mutex); + auto iter = std::find(m_annotations.begin(), m_annotations.end(), annotation); + if (iter != m_annotations.end()) + m_annotations.erase(iter); + } + + + INT D3D9GlobalAnnotationList::BeginEvent(D3DCOLOR color, LPCWSTR name) { + if (!m_shouldAnnotate) + return 0; + + auto lock = std::unique_lock(m_mutex); + for (auto* annotation : m_annotations) + annotation->BeginEvent(color, name); + + return m_eventDepth++; + } + + + INT D3D9GlobalAnnotationList::EndEvent() { + if (!m_shouldAnnotate) + return 0; + + auto lock = std::unique_lock(m_mutex); + for (auto* annotation : m_annotations) + annotation->EndEvent(); + + return m_eventDepth--; + } + + + void D3D9GlobalAnnotationList::SetMarker(D3DCOLOR color, LPCWSTR name) { + if (!m_shouldAnnotate) + return; + + auto lock = std::unique_lock(m_mutex); + for (auto* annotation : m_annotations) + annotation->SetMarker(color, name); + } + + + void D3D9GlobalAnnotationList::SetRegion(D3DCOLOR color, LPCWSTR name) { + // This, by the documentation, does nothing. + } + + + BOOL D3D9GlobalAnnotationList::QueryRepeatFrame() const { + // This, by the documentation, does nothing. + // It's meant to return TRUE if the profiler/debugger + // wants a frame to be repeated, but we never need that. + return FALSE; + } + + + void D3D9GlobalAnnotationList::SetOptions(DWORD options) { + // This is used to say that the app should + // not be debugged/profiled. + } + + + DWORD D3D9GlobalAnnotationList::GetStatus() const { + // This returns whether the app is being + // profiled / debugged. + // Some apps may rely on this to emit + // debug markers. + return m_shouldAnnotate ? 1 : 0; + } + + //////////////////////////// + // D3D9UserDefinedAnnotation + //////////////////////////// + + D3D9UserDefinedAnnotation::D3D9UserDefinedAnnotation(D3D9DeviceEx* device) + : m_container(device) { + D3D9GlobalAnnotationList::Instance().RegisterAnnotator(this); + } + + + D3D9UserDefinedAnnotation::~D3D9UserDefinedAnnotation() { + D3D9GlobalAnnotationList::Instance().UnregisterAnnotator(this); + } + + + ULONG STDMETHODCALLTYPE D3D9UserDefinedAnnotation::AddRef() { + return m_container->AddRef(); + } + + + ULONG STDMETHODCALLTYPE D3D9UserDefinedAnnotation::Release() { + return m_container->Release(); + } + + + HRESULT STDMETHODCALLTYPE D3D9UserDefinedAnnotation::QueryInterface( + REFIID riid, + void** ppvObject) { + return m_container->QueryInterface(riid, ppvObject); + } + + + INT STDMETHODCALLTYPE D3D9UserDefinedAnnotation::BeginEvent( + D3DCOLOR Color, + LPCWSTR Name) { + m_container->EmitCs([color = Color, labelName = dxvk::str::fromws(Name)](DxvkContext *ctx) { + VkDebugUtilsLabelEXT label; + label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT; + label.pNext = nullptr; + label.pLabelName = labelName.c_str(); + DecodeD3DCOLOR(color, label.color); + + ctx->beginDebugLabel(&label); + }); + + // Handled by the global list. + return 0; + } + + + INT STDMETHODCALLTYPE D3D9UserDefinedAnnotation::EndEvent() { + m_container->EmitCs([](DxvkContext *ctx) { + ctx->endDebugLabel(); + }); + + // Handled by the global list. + return 0; + } + + + void STDMETHODCALLTYPE D3D9UserDefinedAnnotation::SetMarker( + D3DCOLOR Color, + LPCWSTR Name) { + m_container->EmitCs([color = Color, labelName = dxvk::str::fromws(Name)](DxvkContext *ctx) { + VkDebugUtilsLabelEXT label; + label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT; + label.pNext = nullptr; + label.pLabelName = labelName.c_str(); + DecodeD3DCOLOR(color, label.color); + + ctx->insertDebugLabel(&label); + }); + } + + + BOOL STDMETHODCALLTYPE D3D9UserDefinedAnnotation::GetStatus() { + return TRUE; + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_annotation.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_annotation.h new file mode 100644 index 00000000000..1fdb19fc2dd --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_annotation.h @@ -0,0 +1,88 @@ +#pragma once + +#include "d3d9_device.h" +#include "d3d9_include.h" +#include "../dxvk/dxvk_annotation.h" + +#include +#include +#include + +namespace dxvk { + + class D3D9GlobalAnnotationList { + + public: + + D3D9GlobalAnnotationList(); + ~D3D9GlobalAnnotationList(); + + void RegisterAnnotator(IDXVKUserDefinedAnnotation* annotation); + void UnregisterAnnotator(IDXVKUserDefinedAnnotation* annotation); + + INT BeginEvent(D3DCOLOR color, LPCWSTR name); + INT EndEvent(); + + void SetMarker(D3DCOLOR color, LPCWSTR name); + + void SetRegion(D3DCOLOR color, LPCWSTR name); + + BOOL QueryRepeatFrame() const; + + void SetOptions(DWORD options); + + DWORD GetStatus() const; + + static D3D9GlobalAnnotationList& Instance() { + return s_instance; + } + + private: + + static D3D9GlobalAnnotationList s_instance; + + std::atomic m_shouldAnnotate; + + std::mutex m_mutex; + std::vector m_annotations; + + // Provide our own event depth as we + // may have multiple annotators which could get out of sync. + int32_t m_eventDepth; + + }; + + class D3D9UserDefinedAnnotation final : public IDXVKUserDefinedAnnotation { + + public: + + D3D9UserDefinedAnnotation(D3D9DeviceEx* device); + ~D3D9UserDefinedAnnotation(); + + ULONG STDMETHODCALLTYPE AddRef(); + + ULONG STDMETHODCALLTYPE Release(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + INT STDMETHODCALLTYPE BeginEvent( + D3DCOLOR Color, + LPCWSTR Name); + + INT STDMETHODCALLTYPE EndEvent(); + + void STDMETHODCALLTYPE SetMarker( + D3DCOLOR Color, + LPCWSTR Name); + + BOOL STDMETHODCALLTYPE GetStatus(); + + private: + + D3D9DeviceEx* m_container; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_buffer.cpp b/utils/dxvk-1.10.3/src/d3d9/d3d9_buffer.cpp new file mode 100644 index 00000000000..c0b72c46eeb --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_buffer.cpp @@ -0,0 +1,116 @@ +#include "d3d9_buffer.h" + +namespace dxvk { + + //////////////////////// + // D3D9VertexBuffer + //////////////////////// + + D3D9VertexBuffer::D3D9VertexBuffer( + D3D9DeviceEx* pDevice, + const D3D9_BUFFER_DESC* pDesc) + : D3D9VertexBufferBase(pDevice, pDesc) { + + } + + + HRESULT STDMETHODCALLTYPE D3D9VertexBuffer::QueryInterface( + REFIID riid, + void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(IDirect3DResource9) + || riid == __uuidof(IDirect3DVertexBuffer9)) { + *ppvObject = ref(this); + return S_OK; + } + + Logger::warn("D3D9VertexBuffer::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + D3DRESOURCETYPE STDMETHODCALLTYPE D3D9VertexBuffer::GetType() { + return D3DRTYPE_VERTEXBUFFER; + } + + + HRESULT STDMETHODCALLTYPE D3D9VertexBuffer::GetDesc( + D3DVERTEXBUFFER_DESC* pDesc) { + if (pDesc == nullptr) + return D3DERR_INVALIDCALL; + + const D3D9_BUFFER_DESC* desc = m_buffer.Desc(); + + pDesc->Format = static_cast(desc->Format); + pDesc->Type = desc->Type; + pDesc->Usage = desc->Usage; + pDesc->Pool = desc->Pool; + pDesc->Size = desc->Size; + pDesc->FVF = desc->FVF; + + return D3D_OK; + } + + + ////////////////////// + // D3D9IndexBuffer + ////////////////////// + + + D3D9IndexBuffer::D3D9IndexBuffer( + D3D9DeviceEx* pDevice, + const D3D9_BUFFER_DESC* pDesc) + : D3D9IndexBufferBase(pDevice, pDesc) { + + } + + + HRESULT STDMETHODCALLTYPE D3D9IndexBuffer::QueryInterface( + REFIID riid, + void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(IDirect3DResource9) + || riid == __uuidof(IDirect3DIndexBuffer9)) { + *ppvObject = ref(this); + return S_OK; + } + + Logger::warn("D3D9IndexBuffer::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + D3DRESOURCETYPE STDMETHODCALLTYPE D3D9IndexBuffer::GetType() { + return D3DRTYPE_INDEXBUFFER; + } + + + HRESULT STDMETHODCALLTYPE D3D9IndexBuffer::GetDesc( + D3DINDEXBUFFER_DESC* pDesc) { + if (pDesc == nullptr) + return D3DERR_INVALIDCALL; + + const D3D9_BUFFER_DESC* desc = m_buffer.Desc(); + + pDesc->Format = static_cast(desc->Format); + pDesc->Type = desc->Type; + pDesc->Usage = desc->Usage; + pDesc->Pool = desc->Pool; + pDesc->Size = desc->Size; + + return D3D_OK; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_buffer.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_buffer.h new file mode 100644 index 00000000000..0600334c069 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_buffer.h @@ -0,0 +1,96 @@ +#pragma once + +#include "d3d9_resource.h" + +#include "d3d9_common_buffer.h" + +namespace dxvk { + + template + class D3D9Buffer : public D3D9Resource { + + public: + + D3D9Buffer( + D3D9DeviceEx* pDevice, + const D3D9_BUFFER_DESC* pDesc) + : D3D9Resource (pDevice), + m_buffer (pDevice, pDesc) { + + } + + HRESULT STDMETHODCALLTYPE Lock( + UINT OffsetToLock, + UINT SizeToLock, + void** ppbData, + DWORD Flags) final { + return m_buffer.Lock( + OffsetToLock, + SizeToLock, + ppbData, + Flags); + } + + HRESULT STDMETHODCALLTYPE Unlock() final { + return m_buffer.Unlock(); + } + + void STDMETHODCALLTYPE PreLoad() final { + m_buffer.PreLoad(); + } + + D3D9CommonBuffer* GetCommonBuffer() { + return &m_buffer; + } + + protected: + + D3D9CommonBuffer m_buffer; + + }; + + + using D3D9VertexBufferBase = D3D9Buffer; + class D3D9VertexBuffer final : public D3D9VertexBufferBase { + + public: + + D3D9VertexBuffer( + D3D9DeviceEx* pDevice, + const D3D9_BUFFER_DESC* pDesc); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + D3DRESOURCETYPE STDMETHODCALLTYPE GetType(); + + HRESULT STDMETHODCALLTYPE GetDesc(D3DVERTEXBUFFER_DESC* pDesc); + + }; + + using D3D9IndexBufferBase = D3D9Buffer; + class D3D9IndexBuffer final : public D3D9IndexBufferBase { + + public: + + D3D9IndexBuffer( + D3D9DeviceEx* pDevice, + const D3D9_BUFFER_DESC* pDesc); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + D3DRESOURCETYPE STDMETHODCALLTYPE GetType(); + + HRESULT STDMETHODCALLTYPE GetDesc(D3DINDEXBUFFER_DESC* pDesc); + + }; + + template + inline D3D9CommonBuffer* GetCommonBuffer(const T& pResource) { + return pResource != nullptr ? pResource->GetCommonBuffer() : nullptr; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_caps.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_caps.h new file mode 100644 index 00000000000..a894de17ace --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_caps.h @@ -0,0 +1,35 @@ +#pragma once + +#include "d3d9_include.h" + +namespace dxvk::caps { + + constexpr uint32_t MaxClipPlanes = 6; + constexpr uint32_t MaxSamplers = 16; + constexpr uint32_t MaxStreams = 16; + constexpr uint32_t MaxSimultaneousTextures = 8; + constexpr uint32_t MaxTextureBlendStages = MaxSimultaneousTextures; + constexpr uint32_t MaxSimultaneousRenderTargets = D3D_MAX_SIMULTANEOUS_RENDERTARGETS; + + constexpr uint32_t MaxFloatConstantsVS = 256; + constexpr uint32_t MaxFloatConstantsPS = 224; + constexpr uint32_t MaxOtherConstants = 16; + constexpr uint32_t MaxFloatConstantsSoftware = 8192; + constexpr uint32_t MaxOtherConstantsSoftware = 2048; + + constexpr uint32_t InputRegisterCount = 16; + + constexpr uint32_t MaxTextureDimension = 16384; + constexpr uint32_t MaxMipLevels = 15; + constexpr uint32_t MaxSubresources = 15 * 6; + + constexpr uint32_t MaxTransforms = 10 + 256; + + constexpr uint32_t TextureStageCount = MaxSimultaneousTextures; + + constexpr uint32_t MaxEnabledLights = 8; + + constexpr uint32_t MaxTexturesVS = 4; + constexpr uint32_t MaxTexturesPS = 16; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_common_buffer.cpp b/utils/dxvk-1.10.3/src/d3d9/d3d9_common_buffer.cpp new file mode 100644 index 00000000000..8d142373506 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_common_buffer.cpp @@ -0,0 +1,137 @@ +#include "d3d9_common_buffer.h" + +#include "d3d9_device.h" +#include "d3d9_util.h" + +namespace dxvk { + + D3D9CommonBuffer::D3D9CommonBuffer( + D3D9DeviceEx* pDevice, + const D3D9_BUFFER_DESC* pDesc) + : m_parent ( pDevice ), m_desc ( *pDesc ), + m_mapMode(DetermineMapMode(pDevice->GetOptions())) { + m_buffer = CreateBuffer(); + if (m_mapMode == D3D9_COMMON_BUFFER_MAP_MODE_BUFFER) + m_stagingBuffer = CreateStagingBuffer(); + + m_sliceHandle = GetMapBuffer()->getSliceHandle(); + + if (m_desc.Pool != D3DPOOL_DEFAULT) + m_dirtyRange = D3D9Range(0, m_desc.Size); + } + + + HRESULT D3D9CommonBuffer::Lock( + UINT OffsetToLock, + UINT SizeToLock, + void** ppbData, + DWORD Flags) { + return m_parent->LockBuffer( + this, + OffsetToLock, + SizeToLock, + ppbData, + Flags); + } + + + HRESULT D3D9CommonBuffer::Unlock() { + return m_parent->UnlockBuffer(this); + } + + + HRESULT D3D9CommonBuffer::ValidateBufferProperties(const D3D9_BUFFER_DESC* pDesc) { + if (pDesc->Size == 0) + return D3DERR_INVALIDCALL; + + return D3D_OK; + } + + + void D3D9CommonBuffer::PreLoad() { + if (IsPoolManaged(m_desc.Pool)) { + auto lock = m_parent->LockDevice(); + + if (NeedsUpload()) + m_parent->FlushBuffer(this); + } + } + + + Rc D3D9CommonBuffer::CreateBuffer() const { + DxvkBufferCreateInfo info; + info.size = m_desc.Size; + info.usage = 0; + info.stages = 0; + info.access = 0; + + VkMemoryPropertyFlags memoryFlags = 0; + + if (m_desc.Type == D3DRTYPE_VERTEXBUFFER) { + info.usage |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; + info.stages |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT; + info.access |= VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; + + if (m_parent->SupportsSWVP()) { + info.usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + info.stages |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT; + info.access |= VK_ACCESS_SHADER_WRITE_BIT; + } + } + else if (m_desc.Type == D3DRTYPE_INDEXBUFFER) { + info.usage |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT; + info.stages |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT; + info.access |= VK_ACCESS_INDEX_READ_BIT; + } + + if (m_mapMode == D3D9_COMMON_BUFFER_MAP_MODE_DIRECT) { + info.stages |= VK_PIPELINE_STAGE_HOST_BIT; + info.access |= VK_ACCESS_HOST_WRITE_BIT; + + if (!(m_desc.Usage & D3DUSAGE_WRITEONLY)) + info.access |= VK_ACCESS_HOST_READ_BIT; + + memoryFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT + | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT + | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + } + else { + info.stages |= VK_PIPELINE_STAGE_TRANSFER_BIT; + info.usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT; + info.access |= VK_ACCESS_TRANSFER_WRITE_BIT; + + memoryFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + } + + if (memoryFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT && m_parent->GetOptions()->apitraceMode) { + memoryFlags |= VK_MEMORY_PROPERTY_HOST_COHERENT_BIT + | VK_MEMORY_PROPERTY_HOST_CACHED_BIT; + } + + return m_parent->GetDXVKDevice()->createBuffer(info, memoryFlags); + } + + + Rc D3D9CommonBuffer::CreateStagingBuffer() const { + DxvkBufferCreateInfo info; + info.size = m_desc.Size; + info.stages = VK_PIPELINE_STAGE_HOST_BIT + | VK_PIPELINE_STAGE_TRANSFER_BIT; + + info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + + info.access = VK_ACCESS_HOST_WRITE_BIT + | VK_ACCESS_TRANSFER_READ_BIT; + + if (!(m_desc.Usage & D3DUSAGE_WRITEONLY)) + info.access |= VK_ACCESS_HOST_READ_BIT; + + VkMemoryPropertyFlags memoryFlags = + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT + | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT + | VK_MEMORY_PROPERTY_HOST_CACHED_BIT; + + return m_parent->GetDXVKDevice()->createBuffer(info, memoryFlags); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_common_buffer.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_common_buffer.h new file mode 100644 index 00000000000..c3bc413c166 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_common_buffer.h @@ -0,0 +1,263 @@ +#pragma once + +#include "../dxvk/dxvk_device.h" +#include "../dxvk/dxvk_cs.h" + +#include "d3d9_device_child.h" +#include "d3d9_format.h" + +namespace dxvk { + + /** + * \brief Buffer map mode + */ + enum D3D9_COMMON_BUFFER_MAP_MODE { + D3D9_COMMON_BUFFER_MAP_MODE_BUFFER, + D3D9_COMMON_BUFFER_MAP_MODE_DIRECT + }; + + /** + * \brief Common buffer descriptor + */ + struct D3D9_BUFFER_DESC { + D3DRESOURCETYPE Type; + UINT Size; + DWORD Usage; + D3D9Format Format; + D3DPOOL Pool; + DWORD FVF; + }; + + /** + * \brief The type of buffer you want to use + */ + enum D3D9_COMMON_BUFFER_TYPE { + D3D9_COMMON_BUFFER_TYPE_MAPPING, + D3D9_COMMON_BUFFER_TYPE_STAGING, + D3D9_COMMON_BUFFER_TYPE_REAL + }; + + struct D3D9Range { + D3D9Range() { Clear(); } + + D3D9Range(uint32_t min, uint32_t max) + : min(min), + max(max) { + + } + + inline bool IsDegenerate() { return min == max; } + + inline void Conjoin(D3D9Range range) { + if (IsDegenerate()) + *this = range; + else { + min = std::min(range.min, min); + max = std::max(range.max, max); + } + } + + inline bool Overlaps(D3D9Range range) { + if (IsDegenerate()) + return false; + + return range.max > min && range.min < max; + } + + inline void Clear() { min = 0; max = 0; } + + uint32_t min = 0; + uint32_t max = 0; + }; + + class D3D9CommonBuffer { + static constexpr VkDeviceSize BufferSliceAlignment = 64; + public: + + D3D9CommonBuffer( + D3D9DeviceEx* pDevice, + const D3D9_BUFFER_DESC* pDesc); + + HRESULT Lock( + UINT OffsetToLock, + UINT SizeToLock, + void** ppbData, + DWORD Flags); + + HRESULT Unlock(); + + /** + * \brief Determine the mapping mode of the buffer, (ie. direct mapping or backed) + */ + inline D3D9_COMMON_BUFFER_MAP_MODE DetermineMapMode(const D3D9Options* options) const { + return (m_desc.Pool == D3DPOOL_DEFAULT && (m_desc.Usage & (D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY)) && options->allowDirectBufferMapping) + ? D3D9_COMMON_BUFFER_MAP_MODE_DIRECT + : D3D9_COMMON_BUFFER_MAP_MODE_BUFFER; + } + + /** + * \brief Get the mapping mode of the buffer, (ie. direct mapping or backed) + */ + inline D3D9_COMMON_BUFFER_MAP_MODE GetMapMode() const { + return m_mapMode; + } + + /** + * \brief Abstraction for getting a type of buffer (mapping/staging/the real buffer) across mapping modes. + */ + template + inline const Rc& GetBuffer() const { + if constexpr (Type == D3D9_COMMON_BUFFER_TYPE_MAPPING) + return GetMapBuffer(); + else if constexpr (Type == D3D9_COMMON_BUFFER_TYPE_STAGING) + return GetStagingBuffer(); + else //if constexpr (Type == D3D9_COMMON_BUFFER_TYPE_REAL) + return GetRealBuffer(); + } + + template + inline DxvkBufferSlice GetBufferSlice() const { + return GetBufferSlice(0, m_desc.Size); + } + + template + inline DxvkBufferSlice GetBufferSlice(VkDeviceSize offset) const { + return GetBufferSlice(offset, m_desc.Size - offset); + } + + template + inline DxvkBufferSlice GetBufferSlice(VkDeviceSize offset, VkDeviceSize length) const { + return DxvkBufferSlice(GetBuffer(), offset, length); + } + + inline DxvkBufferSliceHandle AllocMapSlice() { + return GetMapBuffer()->allocSlice(); + } + + inline DxvkBufferSliceHandle DiscardMapSlice() { + m_sliceHandle = GetMapBuffer()->allocSlice(); + return m_sliceHandle; + } + + inline DxvkBufferSliceHandle GetMappedSlice() const { + return m_sliceHandle; + } + + inline DWORD GetMapFlags() const { return m_mapFlags; } + inline void SetMapFlags(DWORD Flags) { m_mapFlags = Flags; } + + inline const D3D9_BUFFER_DESC* Desc() const { return &m_desc; } + + static HRESULT ValidateBufferProperties(const D3D9_BUFFER_DESC* pDesc); + + /** + * \brief The range of the buffer that was changed using Lock calls + */ + inline D3D9Range& DirtyRange() { return m_dirtyRange; } + + /** + * \brief The range of the buffer that might currently be read by the GPU + */ + inline D3D9Range& GPUReadingRange() { return m_gpuReadingRange; } + + /** + * \brief Whether or not the buffer was written to by the GPU (in IDirect3DDevice9::ProcessVertices) + */ + inline bool NeedsReadback() const { return m_needsReadback; } + + /** + * \brief Sets whether or not the buffer was written to by the GPU + */ + inline void SetNeedsReadback(bool state) { m_needsReadback = state; } + + inline uint32_t IncrementLockCount() { return ++m_lockCount; } + inline uint32_t DecrementLockCount() { + if (m_lockCount == 0) + return 0; + + return --m_lockCount; + } + inline uint32_t GetLockCount() const { return m_lockCount; } + + /** + * \brief Whether or not the staging buffer needs to be copied to the actual buffer + */ + inline bool NeedsUpload() { return m_desc.Pool != D3DPOOL_DEFAULT && !m_dirtyRange.IsDegenerate(); } + + inline bool DoesStagingBufferUploads() const { return m_uploadUsingStaging; } + + inline void EnableStagingBufferUploads() { + if (GetMapMode() != D3D9_COMMON_BUFFER_MAP_MODE_BUFFER) + return; + + m_uploadUsingStaging = true; + } + + void PreLoad(); + + bool HasSequenceNumber() const { + return m_mapMode != D3D9_COMMON_BUFFER_MAP_MODE_DIRECT; + } + + /** + * \brief Tracks sequence number + * + * Stores which CS chunk the resource was last used on. + * \param [in] Seq Sequence number + */ + void TrackMappingBufferSequenceNumber(uint64_t Seq) { + m_seq = Seq; + } + + + /** + * \brief Queries sequence number for a given subresource + * + * Returns which CS chunk the resource was last used on. + * \param [in] Subresource Subresource index + * \returns Sequence number for the given subresource + */ + uint64_t GetMappingBufferSequenceNumber() const { + return HasSequenceNumber() ? m_seq + : DxvkCsThread::SynchronizeAll; + } + + private: + + Rc CreateBuffer() const; + Rc CreateStagingBuffer() const; + + inline const Rc& GetMapBuffer() const { + return m_stagingBuffer != nullptr ? m_stagingBuffer : m_buffer; + } + + inline const Rc& GetStagingBuffer() const { + return m_stagingBuffer; + } + + inline const Rc& GetRealBuffer() const { + return m_buffer; + } + + D3D9DeviceEx* m_parent; + const D3D9_BUFFER_DESC m_desc; + DWORD m_mapFlags; + bool m_needsReadback = false; + bool m_uploadUsingStaging = false; + D3D9_COMMON_BUFFER_MAP_MODE m_mapMode; + + Rc m_buffer; + Rc m_stagingBuffer; + + DxvkBufferSliceHandle m_sliceHandle; + + D3D9Range m_dirtyRange; + D3D9Range m_gpuReadingRange; + + uint32_t m_lockCount = 0; + + uint64_t m_seq = 0ull; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_common_texture.cpp b/utils/dxvk-1.10.3/src/d3d9/d3d9_common_texture.cpp new file mode 100644 index 00000000000..22bc37c9172 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_common_texture.cpp @@ -0,0 +1,610 @@ +#include "d3d9_common_texture.h" + +#include "d3d9_util.h" +#include "d3d9_device.h" + +#include "../util/util_shared_res.h" + +#include + +namespace dxvk { + + D3D9CommonTexture::D3D9CommonTexture( + D3D9DeviceEx* pDevice, + const D3D9_COMMON_TEXTURE_DESC* pDesc, + D3DRESOURCETYPE ResourceType, + HANDLE* pSharedHandle) + : m_device(pDevice), m_desc(*pDesc), m_type(ResourceType) { + if (m_desc.Format == D3D9Format::Unknown) + m_desc.Format = (m_desc.Usage & D3DUSAGE_DEPTHSTENCIL) + ? D3D9Format::D32 + : D3D9Format::X8R8G8B8; + + for (uint32_t i = 0; i < m_dirtyBoxes.size(); i++) { + AddDirtyBox(nullptr, i); + } + + if (m_desc.Pool != D3DPOOL_DEFAULT) { + const uint32_t subresources = CountSubresources(); + for (uint32_t i = 0; i < subresources; i++) { + SetNeedsUpload(i, true); + } + if (pSharedHandle) { + throw DxvkError("D3D9: Incompatible pool type for texture sharing."); + } + } + + m_mapping = pDevice->LookupFormat(m_desc.Format); + + m_mapMode = DetermineMapMode(); + m_shadow = DetermineShadowState(); + m_supportsFetch4 = DetermineFetch4Compatibility(); + + if (m_mapMode == D3D9_COMMON_TEXTURE_MAP_MODE_BACKED) { + bool plainSurface = m_type == D3DRTYPE_SURFACE && + !(m_desc.Usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)); + + try { + m_image = CreatePrimaryImage(ResourceType, plainSurface, pSharedHandle); + } + catch (const DxvkError& e) { + // D3DUSAGE_AUTOGENMIPMAP and offscreen plain is mutually exclusive + // so we can combine their retry this way. + if (m_desc.Usage & D3DUSAGE_AUTOGENMIPMAP || plainSurface) { + m_desc.Usage &= ~D3DUSAGE_AUTOGENMIPMAP; + m_desc.MipLevels = 1; + m_image = CreatePrimaryImage(ResourceType, false, pSharedHandle); + } + else + throw e; + } + + if (pSharedHandle && *pSharedHandle == nullptr) { + *pSharedHandle = m_image->sharedHandle(); + ExportImageInfo(); + } + + CreateSampleView(0); + + if (!IsManaged()) { + m_size = m_image->memSize(); + if (!m_device->ChangeReportedMemory(-m_size)) + throw DxvkError("D3D9: Reporting out of memory from tracking."); + } + } + + if (m_mapMode == D3D9_COMMON_TEXTURE_MAP_MODE_SYSTEMMEM) + CreateBuffers(); + + m_exposedMipLevels = m_desc.MipLevels; + + if (m_desc.Usage & D3DUSAGE_AUTOGENMIPMAP) + m_exposedMipLevels = 1; + } + + + D3D9CommonTexture::~D3D9CommonTexture() { + if (m_size != 0) + m_device->ChangeReportedMemory(m_size); + } + + + VkImageSubresource D3D9CommonTexture::GetSubresourceFromIndex( + VkImageAspectFlags Aspect, + UINT Subresource) const { + VkImageSubresource result; + result.aspectMask = Aspect; + result.mipLevel = Subresource % m_desc.MipLevels; + result.arrayLayer = Subresource / m_desc.MipLevels; + return result; + } + + + HRESULT D3D9CommonTexture::NormalizeTextureProperties( + D3D9DeviceEx* pDevice, + D3D9_COMMON_TEXTURE_DESC* pDesc) { + auto* options = pDevice->GetOptions(); + + ////////////////////// + // Mapping Validation + auto mapping = pDevice->LookupFormat(pDesc->Format); + + // Handle DisableA8RT hack for The Sims 2 + if (pDesc->Format == D3D9Format::A8 && + (pDesc->Usage & D3DUSAGE_RENDERTARGET) && + options->disableA8RT) + return D3DERR_INVALIDCALL; + + // If the mapping is invalid then lets return invalid + // Some edge cases: + // NULL format does not map to anything, but should succeed + // SCRATCH textures can still be made if the device does not support + // the format at all. + + if (!mapping.IsValid() && pDesc->Format != D3D9Format::NULL_FORMAT) { + auto info = pDevice->UnsupportedFormatInfo(pDesc->Format); + + if (pDesc->Pool != D3DPOOL_SCRATCH || info->elementSize == 0) + return D3DERR_INVALIDCALL; + } + + /////////////////// + // Desc Validation + + if (pDesc->Width == 0 || pDesc->Height == 0 || pDesc->Depth == 0) + return D3DERR_INVALIDCALL; + + if (FAILED(DecodeMultiSampleType(pDevice->GetDXVKDevice(), pDesc->MultiSample, pDesc->MultisampleQuality, nullptr))) + return D3DERR_INVALIDCALL; + + // Using MANAGED pool with DYNAMIC usage is illegal + if (IsPoolManaged(pDesc->Pool) && (pDesc->Usage & D3DUSAGE_DYNAMIC)) + return D3DERR_INVALIDCALL; + + // D3DUSAGE_WRITEONLY doesn't apply to textures. + if (pDesc->Usage & D3DUSAGE_WRITEONLY) + return D3DERR_INVALIDCALL; + + // RENDERTARGET and DEPTHSTENCIL must be default pool + constexpr DWORD incompatibleUsages = D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL; + if (pDesc->Pool != D3DPOOL_DEFAULT && (pDesc->Usage & incompatibleUsages)) + return D3DERR_INVALIDCALL; + + // Use the maximum possible mip level count if the supplied + // mip level count is either unspecified (0) or invalid + const uint32_t maxMipLevelCount = pDesc->MultiSample <= D3DMULTISAMPLE_NONMASKABLE + ? util::computeMipLevelCount({ pDesc->Width, pDesc->Height, pDesc->Depth }) + : 1u; + + if (pDesc->Usage & D3DUSAGE_AUTOGENMIPMAP) + pDesc->MipLevels = 0; + + if (pDesc->MipLevels == 0 || pDesc->MipLevels > maxMipLevelCount) + pDesc->MipLevels = maxMipLevelCount; + + return D3D_OK; + } + + + bool D3D9CommonTexture::CreateBufferSubresource(UINT Subresource) { + if (m_buffers[Subresource] != nullptr) + return false; + + DxvkBufferCreateInfo info; + info.size = GetMipSize(Subresource); + info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT + | VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT; + info.access = VK_ACCESS_TRANSFER_READ_BIT + | VK_ACCESS_TRANSFER_WRITE_BIT; + + if (m_mapping.ConversionFormatInfo.FormatType != D3D9ConversionFormat_None) { + info.usage |= VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT; + info.stages |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; + } + + VkMemoryPropertyFlags memType = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT + | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT + | VK_MEMORY_PROPERTY_HOST_CACHED_BIT; + + m_buffers[Subresource] = m_device->GetDXVKDevice()->createBuffer(info, memType); + m_mappedSlices[Subresource] = m_buffers[Subresource]->getSliceHandle(); + + return true; + } + + + VkDeviceSize D3D9CommonTexture::GetMipSize(UINT Subresource) const { + const UINT MipLevel = Subresource % m_desc.MipLevels; + + const DxvkFormatInfo* formatInfo = m_mapping.FormatColor != VK_FORMAT_UNDEFINED + ? imageFormatInfo(m_mapping.FormatColor) + : m_device->UnsupportedFormatInfo(m_desc.Format); + + const VkExtent3D mipExtent = util::computeMipLevelExtent( + GetExtent(), MipLevel); + + const VkExtent3D blockCount = util::computeBlockCount( + mipExtent, formatInfo->blockSize); + + const uint32_t planeCount = m_mapping.ConversionFormatInfo.PlaneCount; + + return std::min(planeCount, 2u) + * align(formatInfo->elementSize * blockCount.width, 4) + * blockCount.height + * blockCount.depth; + } + + + Rc D3D9CommonTexture::CreatePrimaryImage(D3DRESOURCETYPE ResourceType, bool TryOffscreenRT, HANDLE* pSharedHandle) const { + DxvkImageCreateInfo imageInfo; + imageInfo.type = GetImageTypeFromResourceType(ResourceType); + imageInfo.format = m_mapping.ConversionFormatInfo.FormatColor != VK_FORMAT_UNDEFINED + ? m_mapping.ConversionFormatInfo.FormatColor + : m_mapping.FormatColor; + imageInfo.flags = 0; + imageInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT; + imageInfo.extent.width = m_desc.Width; + imageInfo.extent.height = m_desc.Height; + imageInfo.extent.depth = m_desc.Depth; + imageInfo.numLayers = m_desc.ArraySize; + imageInfo.mipLevels = m_desc.MipLevels; + imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_SAMPLED_BIT; + imageInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT + | m_device->GetEnabledShaderStages(); + imageInfo.access = VK_ACCESS_TRANSFER_READ_BIT + | VK_ACCESS_TRANSFER_WRITE_BIT + | VK_ACCESS_SHADER_READ_BIT; + imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; + imageInfo.layout = VK_IMAGE_LAYOUT_GENERAL; + imageInfo.shared = m_desc.IsBackBuffer; + + if (pSharedHandle) { + imageInfo.sharing.type = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT; + imageInfo.sharing.mode = (*pSharedHandle == INVALID_HANDLE_VALUE || *pSharedHandle == nullptr) + ? DxvkSharedHandleMode::Export + : DxvkSharedHandleMode::Import; + imageInfo.sharing.type = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT; + imageInfo.sharing.handle = *pSharedHandle; + imageInfo.shared = true; + // TODO: validate metadata? + } + + if (m_mapping.ConversionFormatInfo.FormatType != D3D9ConversionFormat_None) { + imageInfo.usage |= VK_IMAGE_USAGE_STORAGE_BIT; + imageInfo.stages |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; + } + + DecodeMultiSampleType(m_device->GetDXVKDevice(), m_desc.MultiSample, m_desc.MultisampleQuality, &imageInfo.sampleCount); + + // The image must be marked as mutable if it can be reinterpreted + // by a view with a different format. Depth-stencil formats cannot + // be reinterpreted in Vulkan, so we'll ignore those. + auto formatProperties = imageFormatInfo(m_mapping.FormatColor); + + bool isMutable = m_mapping.FormatSrgb != VK_FORMAT_UNDEFINED; + bool isColorFormat = (formatProperties->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) != 0; + + if (isMutable && isColorFormat) { + imageInfo.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; + + imageInfo.viewFormatCount = 2; + imageInfo.viewFormats = m_mapping.Formats; + } + + // Are we an RT, need to gen mips or an offscreen plain surface? + if (m_desc.Usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP) || TryOffscreenRT) { + imageInfo.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + imageInfo.stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + imageInfo.access |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT + | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + } + + if (m_desc.Usage & D3DUSAGE_DEPTHSTENCIL) { + imageInfo.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + imageInfo.stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT + | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + imageInfo.access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT + | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + } + + if (ResourceType == D3DRTYPE_CUBETEXTURE) + imageInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; + + // Some image formats (i.e. the R32G32B32 ones) are + // only supported with linear tiling on most GPUs + if (!CheckImageSupport(&imageInfo, VK_IMAGE_TILING_OPTIMAL)) + imageInfo.tiling = VK_IMAGE_TILING_LINEAR; + + // We must keep LINEAR images in GENERAL layout, but we + // can choose a better layout for the image based on how + // it is going to be used by the game. + if (imageInfo.tiling == VK_IMAGE_TILING_OPTIMAL && imageInfo.sharing.mode == DxvkSharedHandleMode::None) + imageInfo.layout = OptimizeLayout(imageInfo.usage); + + // For some formats, we need to enable render target + // capabilities if available, but these should + // in no way affect the default image layout + imageInfo.usage |= EnableMetaCopyUsage(imageInfo.format, imageInfo.tiling); + + // Check if we can actually create the image + if (!CheckImageSupport(&imageInfo, imageInfo.tiling)) { + throw DxvkError(str::format( + "D3D9: Cannot create texture:", + "\n Type: ", std::hex, ResourceType, + "\n Format: ", m_desc.Format, + "\n Extent: ", m_desc.Width, + "x", m_desc.Height, + "x", m_desc.Depth, + "\n Samples: ", m_desc.MultiSample, + "\n Layers: ", m_desc.ArraySize, + "\n Levels: ", m_desc.MipLevels, + "\n Usage: ", std::hex, m_desc.Usage, + "\n Pool: ", std::hex, m_desc.Pool)); + } + + return m_device->GetDXVKDevice()->createImage(imageInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + } + + + Rc D3D9CommonTexture::CreateResolveImage() const { + DxvkImageCreateInfo imageInfo = m_image->info(); + imageInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT; + + return m_device->GetDXVKDevice()->createImage(imageInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + } + + + BOOL D3D9CommonTexture::DetermineShadowState() const { + constexpr std::array blacklist = { + D3D9Format::INTZ, D3D9Format::DF16, D3D9Format::DF24 + }; + + return IsDepthFormat(m_desc.Format) + && std::find(blacklist.begin(), blacklist.end(), m_desc.Format) == blacklist.end(); + } + + + BOOL D3D9CommonTexture::DetermineFetch4Compatibility() const { + constexpr std::array singleChannelFormats = { + D3D9Format::INTZ, D3D9Format::DF16, D3D9Format::DF24, + D3D9Format::R16F, D3D9Format::R32F, D3D9Format::A8, + D3D9Format::L8, D3D9Format::L16 + }; + + return std::find(singleChannelFormats.begin(), singleChannelFormats.end(), m_desc.Format) != singleChannelFormats.end(); + } + + + BOOL D3D9CommonTexture::CheckImageSupport( + const DxvkImageCreateInfo* pImageInfo, + VkImageTiling Tiling) const { + const Rc adapter = m_device->GetDXVKDevice()->adapter(); + + VkImageFormatProperties formatProps = { }; + + VkResult status = adapter->imageFormatProperties( + pImageInfo->format, pImageInfo->type, Tiling, + pImageInfo->usage, pImageInfo->flags, formatProps); + + if (status != VK_SUCCESS) + return FALSE; + + return (pImageInfo->extent.width <= formatProps.maxExtent.width) + && (pImageInfo->extent.height <= formatProps.maxExtent.height) + && (pImageInfo->extent.depth <= formatProps.maxExtent.depth) + && (pImageInfo->numLayers <= formatProps.maxArrayLayers) + && (pImageInfo->mipLevels <= formatProps.maxMipLevels) + && (pImageInfo->sampleCount & formatProps.sampleCounts); + } + + + VkImageUsageFlags D3D9CommonTexture::EnableMetaCopyUsage( + VkFormat Format, + VkImageTiling Tiling) const { + VkFormatFeatureFlags requestedFeatures = 0; + + if (Format == VK_FORMAT_D16_UNORM || Format == VK_FORMAT_D32_SFLOAT) + requestedFeatures |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT; + + if (Format == VK_FORMAT_R16_UNORM || Format == VK_FORMAT_R32_SFLOAT) + requestedFeatures |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT; + + if (requestedFeatures == 0) + return 0; + + // Enable usage flags for all supported and requested features + VkFormatProperties properties = m_device->GetDXVKDevice()->adapter()->formatProperties(Format); + + requestedFeatures &= Tiling == VK_IMAGE_TILING_OPTIMAL + ? properties.optimalTilingFeatures + : properties.linearTilingFeatures; + + VkImageUsageFlags requestedUsage = 0; + + if (requestedFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) + requestedUsage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + + if (requestedFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) + requestedUsage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + + return requestedUsage; + } + + + VkImageType D3D9CommonTexture::GetImageTypeFromResourceType(D3DRESOURCETYPE Type) { + switch (Type) { + case D3DRTYPE_SURFACE: + case D3DRTYPE_TEXTURE: return VK_IMAGE_TYPE_2D; + case D3DRTYPE_VOLUMETEXTURE: return VK_IMAGE_TYPE_3D; + case D3DRTYPE_CUBETEXTURE: return VK_IMAGE_TYPE_2D; + default: throw DxvkError("D3D9CommonTexture: Unhandled resource type"); + } + } + + + VkImageViewType D3D9CommonTexture::GetImageViewTypeFromResourceType( + D3DRESOURCETYPE Dimension, + UINT Layer) { + switch (Dimension) { + case D3DRTYPE_SURFACE: + case D3DRTYPE_TEXTURE: return VK_IMAGE_VIEW_TYPE_2D; + case D3DRTYPE_VOLUMETEXTURE: return VK_IMAGE_VIEW_TYPE_3D; + case D3DRTYPE_CUBETEXTURE: return Layer == AllLayers + ? VK_IMAGE_VIEW_TYPE_CUBE + : VK_IMAGE_VIEW_TYPE_2D; + default: throw DxvkError("D3D9CommonTexture: Unhandled resource type"); + } + } + + + VkImageLayout D3D9CommonTexture::OptimizeLayout(VkImageUsageFlags Usage) const { + const VkImageUsageFlags usageFlags = Usage; + + // Filter out unnecessary flags. Transfer operations + // are handled by the backend in a transparent manner. + Usage &= ~(VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_TRANSFER_SRC_BIT); + + // Ignore sampled bit in case the image was created with + // an image flag that only allows attachment usage + if (m_desc.IsAttachmentOnly) + Usage &= ~VK_IMAGE_USAGE_SAMPLED_BIT; + + // If the image is used only as an attachment, we never + // have to transform the image back to a different layout + if (Usage == VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) + return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + if (Usage == VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) + return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + Usage &= ~(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT + | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); + + // If the image is used for reading but not as a storage + // image, we can optimize the image for texture access + if (Usage == VK_IMAGE_USAGE_SAMPLED_BIT) { + return usageFlags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT + ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL + : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + } + + // Otherwise, we have to stick with the default layout + return VK_IMAGE_LAYOUT_GENERAL; + } + + + void D3D9CommonTexture::ExportImageInfo() { + /* From MSDN: + Textures being shared from D3D9 to D3D11 have the following restrictions. + + - Textures must be 2D + - Only 1 mip level is allowed + - Texture must have default usage + - Texture must be write only + - MSAA textures are not allowed + - Bind flags must have SHADER_RESOURCE and RENDER_TARGET set + - Only R10G10B10A2_UNORM, R16G16B16A16_FLOAT and R8G8B8A8_UNORM formats are allowed + */ + DXGI_FORMAT dxgiFormat = DXGI_FORMAT_UNKNOWN; + + switch (m_desc.Format) { + case D3D9Format::A2B10G10R10: dxgiFormat = DXGI_FORMAT_R10G10B10A2_UNORM; break; + case D3D9Format::A16B16G16R16F: dxgiFormat = DXGI_FORMAT_R16G16B16A16_FLOAT; break; + case D3D9Format::A8B8G8R8: dxgiFormat = DXGI_FORMAT_R8G8B8A8_UNORM; break; + case D3D9Format::X8B8G8R8: dxgiFormat = DXGI_FORMAT_R8G8B8A8_UNORM; break; /* No RGBX in DXGI */ + case D3D9Format::A8R8G8B8: dxgiFormat = DXGI_FORMAT_B8G8R8A8_UNORM; break; + case D3D9Format::X8R8G8B8: dxgiFormat = DXGI_FORMAT_B8G8R8X8_UNORM; break; + default: + Logger::warn(str::format("D3D9: Unsupported format for shared textures: ", m_desc.Format)); + return; + } + + if (m_desc.Depth == 1 && m_desc.MipLevels == 1 && m_desc.MultiSample == D3DMULTISAMPLE_NONE && + m_desc.Usage & D3DUSAGE_RENDERTARGET && dxgiFormat != DXGI_FORMAT_UNKNOWN) { + HANDLE ntHandle = openKmtHandle(m_image->sharedHandle()); + + DxvkSharedTextureMetadata metadata; + + metadata.Width = m_desc.Width; + metadata.Height = m_desc.Height; + metadata.MipLevels = m_desc.MipLevels; + metadata.ArraySize = m_desc.ArraySize; + metadata.Format = dxgiFormat; + metadata.SampleDesc.Count = 1; + metadata.SampleDesc.Quality = 0; + metadata.Usage = D3D11_USAGE_DEFAULT; + metadata.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + metadata.CPUAccessFlags = 0; + metadata.MiscFlags = D3D11_RESOURCE_MISC_SHARED; + metadata.TextureLayout = D3D11_TEXTURE_LAYOUT_UNDEFINED; + + if (ntHandle == INVALID_HANDLE_VALUE || !setSharedMetadata(ntHandle, &metadata, sizeof(metadata))) + Logger::warn("D3D9: Failed to write shared resource info for a texture"); + + if (ntHandle != INVALID_HANDLE_VALUE) + ::CloseHandle(ntHandle); + } + } + + + Rc D3D9CommonTexture::CreateView( + UINT Layer, + UINT Lod, + VkImageUsageFlags UsageFlags, + bool Srgb) { + DxvkImageViewCreateInfo viewInfo; + viewInfo.format = m_mapping.ConversionFormatInfo.FormatColor != VK_FORMAT_UNDEFINED + ? PickSRGB(m_mapping.ConversionFormatInfo.FormatColor, m_mapping.ConversionFormatInfo.FormatSrgb, Srgb) + : PickSRGB(m_mapping.FormatColor, m_mapping.FormatSrgb, Srgb); + viewInfo.aspect = imageFormatInfo(viewInfo.format)->aspectMask; + viewInfo.swizzle = m_mapping.Swizzle; + viewInfo.usage = UsageFlags; + viewInfo.type = GetImageViewTypeFromResourceType(m_type, Layer); + viewInfo.minLevel = Lod; + viewInfo.numLevels = m_desc.MipLevels - Lod; + viewInfo.minLayer = Layer == AllLayers ? 0 : Layer; + viewInfo.numLayers = Layer == AllLayers ? m_desc.ArraySize : 1; + + // Remove the stencil aspect if we are trying to create a regular image + // view of a depth stencil format + if (UsageFlags != VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) + viewInfo.aspect &= ~VK_IMAGE_ASPECT_STENCIL_BIT; + + if (UsageFlags == VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT || + UsageFlags == VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) + viewInfo.numLevels = 1; + + // Remove swizzle on depth views. + if (UsageFlags == VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) + viewInfo.swizzle = { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, + VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY }; + + // Create the underlying image view object + return m_device->GetDXVKDevice()->createImageView(GetImage(), viewInfo); + } + + + void D3D9CommonTexture::PreLoadAll() { + if (!IsManaged()) + return; + + auto lock = m_device->LockDevice(); + m_device->UploadManagedTexture(this); + m_device->MarkTextureUploaded(this); + } + + + void D3D9CommonTexture::PreLoadSubresource(UINT Subresource) { + if (IsManaged()) { + auto lock = m_device->LockDevice(); + + if (NeedsUpload(Subresource)) { + m_device->FlushImage(this, Subresource); + SetNeedsUpload(Subresource, false); + + if (!NeedsAnyUpload()) + m_device->MarkTextureUploaded(this); + } + } + } + + + void D3D9CommonTexture::CreateSampleView(UINT Lod) { + // This will be a no-op for SYSTEMMEM types given we + // don't expose the cap to allow texturing with them. + if (unlikely(m_mapMode == D3D9_COMMON_TEXTURE_MAP_MODE_SYSTEMMEM)) + return; + + m_sampleView.Color = CreateView(AllLayers, Lod, VK_IMAGE_USAGE_SAMPLED_BIT, false); + + if (IsSrgbCompatible()) + m_sampleView.Srgb = CreateView(AllLayers, Lod, VK_IMAGE_USAGE_SAMPLED_BIT, true); + } + + +} diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_common_texture.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_common_texture.h new file mode 100644 index 00000000000..e52ead2f1b0 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_common_texture.h @@ -0,0 +1,556 @@ +#pragma once + +#include "d3d9_format.h" +#include "d3d9_util.h" +#include "d3d9_caps.h" + +#include "../dxvk/dxvk_device.h" + +#include "../util/util_bit.h" + +namespace dxvk { + + class D3D9DeviceEx; + + /** + * \brief Image memory mapping mode + * + * Determines how exactly \c LockBox will + * behave when mapping an image. + */ + enum D3D9_COMMON_TEXTURE_MAP_MODE { + D3D9_COMMON_TEXTURE_MAP_MODE_NONE, ///< No mapping available + D3D9_COMMON_TEXTURE_MAP_MODE_BACKED, ///< Mapped image through buffer + D3D9_COMMON_TEXTURE_MAP_MODE_SYSTEMMEM, ///< Only a buffer - no image + }; + + /** + * \brief Common texture description + * + * Contains all members that can be + * defined for 2D, Cube and 3D textures. + */ + struct D3D9_COMMON_TEXTURE_DESC { + UINT Width; + UINT Height; + UINT Depth; + UINT ArraySize; + UINT MipLevels; + DWORD Usage; + D3D9Format Format; + D3DPOOL Pool; + D3DMULTISAMPLE_TYPE MultiSample; + DWORD MultisampleQuality; + bool Discard; + bool IsBackBuffer; + bool IsAttachmentOnly; + }; + + struct D3D9ColorView { + inline Rc& Pick(bool Srgb) { + return Srgb ? this->Srgb : this->Color; + } + + inline const Rc& Pick(bool Srgb) const { + return Srgb ? this->Srgb : this->Color; + } + + Rc Color; + Rc Srgb; + }; + + template + using D3D9SubresourceArray = std::array; + + using D3D9SubresourceBitset = bit::bitset; + + class D3D9CommonTexture { + + public: + + D3D9CommonTexture( + D3D9DeviceEx* pDevice, + const D3D9_COMMON_TEXTURE_DESC* pDesc, + D3DRESOURCETYPE ResourceType, + HANDLE* pSharedHandle); + + ~D3D9CommonTexture(); + + /** + * \brief Device + * \returns The parent device + */ + D3D9DeviceEx* Device() const { + return m_device; + } + + /** + * \brief Texture properties + * + * The returned data can be used to fill in + * \c D3D11_TEXTURE2D_DESC and similar structs. + * \returns Pointer to texture description + */ + const D3D9_COMMON_TEXTURE_DESC* Desc() const { + return &m_desc; + } + + /** + * \brief Vulkan Format + * \returns The Vulkan format of the resource + */ + const D3D9_VK_FORMAT_MAPPING& GetFormatMapping() const { + return m_mapping; + } + + /** + * \brief Counts number of subresources + * \returns Number of subresources + */ + UINT CountSubresources() const { + return m_desc.ArraySize * m_desc.MipLevels; + } + + /** + * \brief Map mode + * \returns Map mode + */ + D3D9_COMMON_TEXTURE_MAP_MODE GetMapMode() const { + return m_mapMode; + } + + /** + * \brief The DXVK image + * Note, this will be nullptr if the map mode is D3D9_COMMON_TEXTURE_MAP_MODE_SYSTEMMEM + * \returns The DXVK image + */ + const Rc& GetImage() const { + return m_image; + } + + /** + * \brief Get a copy of the main image, but with a single sample + * This function will allocate/reuse an image with the same info + * as the main image + * \returns An image with identical info, but 1 sample + */ + const Rc& GetResolveImage() { + if (unlikely(m_resolveImage == nullptr)) + m_resolveImage = CreateResolveImage(); + + return m_resolveImage; + } + + const Rc& GetBuffer(UINT Subresource) { + return m_buffers[Subresource]; + } + + + DxvkBufferSliceHandle GetMappedSlice(UINT Subresource) { + return m_mappedSlices[Subresource]; + } + + + DxvkBufferSliceHandle DiscardMapSlice(UINT Subresource) { + DxvkBufferSliceHandle handle = m_buffers[Subresource]->allocSlice(); + m_mappedSlices[Subresource] = handle; + return handle; + } + + /** + * \brief Computes subresource from the subresource index + * + * Used by some functions that operate on only + * one subresource, such as \c UpdateSurface. + * \param [in] Aspect The image aspect + * \param [in] Subresource Subresource index + * \returns The Vulkan image subresource + */ + VkImageSubresource GetSubresourceFromIndex( + VkImageAspectFlags Aspect, + UINT Subresource) const; + + /** + * \brief Normalizes and validates texture description + * + * Fills in undefined values and validates the texture + * parameters. Any error returned by this method should + * be forwarded to the application. + * \param [in,out] pDesc Texture description + * \returns \c S_OK if the parameters are valid + */ + static HRESULT NormalizeTextureProperties( + D3D9DeviceEx* pDevice, + D3D9_COMMON_TEXTURE_DESC* pDesc); + + /** + * \brief Shadow + * \returns Whether the texture is to be depth compared + */ + bool IsShadow() const { + return m_shadow; + } + + /** + * \brief FETCH4 compatibility + * \returns Whether the format of the texture supports the FETCH4 hack + */ + bool SupportsFetch4() const { + return m_supportsFetch4; + } + + /** + * \brief Null + * \returns Whether the texture is D3DFMT_NULL or not + */ + bool IsNull() const { + return m_desc.Format == D3D9Format::NULL_FORMAT; + } + + /** + * \brief Subresource + * \returns The subresource idx of a given face and mip level + */ + UINT CalcSubresource(UINT Face, UINT MipLevel) const { + return Face * m_desc.MipLevels + MipLevel; + } + + /** + * \brief Creates buffers + * Creates mapping and staging buffers for all subresources + * allocates new buffers if necessary + */ + void CreateBuffers() { + const uint32_t count = CountSubresources(); + for (uint32_t i = 0; i < count; i++) + CreateBufferSubresource(i); + } + + /** + * \brief Creates a buffer + * Creates mapping and staging buffers for a given subresource + * allocates new buffers if necessary + * \returns Whether an allocation happened + */ + bool CreateBufferSubresource(UINT Subresource); + + /** + * \brief Destroys a buffer + * Destroys mapping and staging buffers for a given subresource + */ + void DestroyBufferSubresource(UINT Subresource) { + m_buffers[Subresource] = nullptr; + SetNeedsReadback(Subresource, true); + } + + bool IsDynamic() const { + return m_desc.Usage & D3DUSAGE_DYNAMIC; + } + + /** + * \brief Managed + * \returns Whether a resource is managed (pool) or not + */ + bool IsManaged() const { + return IsPoolManaged(m_desc.Pool); + } + + /** + * \brief Render Target + * \returns Whether a resource is a render target or not + */ + bool IsRenderTarget() const { + return m_desc.Usage & D3DUSAGE_RENDERTARGET; + } + + /** + * \brief Depth stencil + * \returns Whether a resource is a depth stencil or not + */ + bool IsDepthStencil() const { + return m_desc.Usage & D3DUSAGE_DEPTHSTENCIL; + } + + /** + * \brief Autogen Mipmap + * \returns Whether the texture is to have automatic mip generation + */ + bool IsAutomaticMip() const { + return m_desc.Usage & D3DUSAGE_AUTOGENMIPMAP; + } + + /** + * \brief Checks whether sRGB views can be created + * \returns Whether the format is sRGB compatible. + */ + bool IsSrgbCompatible() const { + return m_mapping.FormatSrgb; + } + + /** + * \brief Recreate main image view + * Recreates the main view of the sampler w/ a specific LOD. + * SetLOD only works on MANAGED textures so this is A-okay. + */ + void CreateSampleView(UINT Lod); + + /** + * \brief Extent + * \returns The extent of the top-level mip + */ + VkExtent3D GetExtent() const { + return VkExtent3D{ m_desc.Width, m_desc.Height, m_desc.Depth }; + } + + /** + * \brief Mip Extent + * \returns The extent of a mip or subresource + */ + VkExtent3D GetExtentMip(UINT Subresource) const { + UINT MipLevel = Subresource % m_desc.MipLevels; + return util::computeMipLevelExtent(GetExtent(), MipLevel); + } + + bool MarkHazardous() { + return std::exchange(m_hazardous, true); + } + + D3DRESOURCETYPE GetType() { + return m_type; + } + + const D3D9_VK_FORMAT_MAPPING& GetMapping() { return m_mapping; } + + void SetLocked(UINT Subresource, bool value) { m_locked.set(Subresource, value); } + + bool GetLocked(UINT Subresource) const { return m_locked.get(Subresource); } + + bool IsAnySubresourceLocked() const { return m_locked.any(); } + + void SetNeedsReadback(UINT Subresource, bool value) { m_needsReadback.set(Subresource, value); } + + bool NeedsReachback(UINT Subresource) const { return m_needsReadback.get(Subresource); } + + void MarkAllNeedReadback() { m_needsReadback.setAll(); } + + void SetReadOnlyLocked(UINT Subresource, bool readOnly) { return m_readOnly.set(Subresource, readOnly); } + + bool GetReadOnlyLocked(UINT Subresource) const { return m_readOnly.get(Subresource); } + + const Rc& GetSampleView(bool srgb) const { + return m_sampleView.Pick(srgb && IsSrgbCompatible()); + } + + VkImageLayout DetermineRenderTargetLayout() const { + return m_image != nullptr && + m_image->info().tiling == VK_IMAGE_TILING_OPTIMAL && + !m_hazardous + ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL + : VK_IMAGE_LAYOUT_GENERAL; + } + + VkImageLayout DetermineDepthStencilLayout(bool write, bool hazardous) const { + VkImageLayout layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + if (unlikely(hazardous)) { + layout = write + ? VK_IMAGE_LAYOUT_GENERAL + : VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL; + } + + if (unlikely(m_image->info().tiling != VK_IMAGE_TILING_OPTIMAL)) + layout = VK_IMAGE_LAYOUT_GENERAL; + + return layout; + } + + Rc CreateView( + UINT Layer, + UINT Lod, + VkImageUsageFlags UsageFlags, + bool Srgb); + D3D9SubresourceBitset& GetUploadBitmask() { return m_needsUpload; } + + void SetAllNeedUpload() { + m_needsUpload.setAll(); + } + void SetNeedsUpload(UINT Subresource, bool upload) { m_needsUpload.set(Subresource, upload); } + bool NeedsUpload(UINT Subresource) const { return m_needsUpload.get(Subresource); } + bool NeedsAnyUpload() { return m_needsUpload.any(); } + void ClearNeedsUpload() { return m_needsUpload.clearAll(); } + bool DoesStagingBufferUploads(UINT Subresource) const { return m_uploadUsingStaging.get(Subresource); } + + void EnableStagingBufferUploads(UINT Subresource) { + m_uploadUsingStaging.set(Subresource, true); + } + + void SetNeedsMipGen(bool value) { m_needsMipGen = value; } + bool NeedsMipGen() const { return m_needsMipGen; } + + DWORD ExposedMipLevels() { return m_exposedMipLevels; } + + void SetMipFilter(D3DTEXTUREFILTERTYPE filter) { m_mipFilter = filter; } + D3DTEXTUREFILTERTYPE GetMipFilter() const { return m_mipFilter; } + + void PreLoadAll(); + void PreLoadSubresource(UINT Subresource); + + void AddDirtyBox(CONST D3DBOX* pDirtyBox, uint32_t layer) { + if (pDirtyBox) { + D3DBOX box = *pDirtyBox; + if (box.Right <= box.Left + || box.Bottom <= box.Top + || box.Back <= box.Front) + return; + + box.Right = std::min(box.Right, m_desc.Width); + box.Bottom = std::min(box.Bottom, m_desc.Height); + box.Back = std::min(box.Back, m_desc.Depth); + + D3DBOX& dirtyBox = m_dirtyBoxes[layer]; + if (dirtyBox.Left == dirtyBox.Right) { + dirtyBox = box; + } else { + dirtyBox.Left = std::min(dirtyBox.Left, box.Left); + dirtyBox.Right = std::max(dirtyBox.Right, box.Right); + dirtyBox.Top = std::min(dirtyBox.Top, box.Top); + dirtyBox.Bottom = std::max(dirtyBox.Bottom, box.Bottom); + dirtyBox.Front = std::min(dirtyBox.Front, box.Front); + dirtyBox.Back = std::max(dirtyBox.Back, box.Back); + } + } else { + m_dirtyBoxes[layer] = { 0, 0, m_desc.Width, m_desc.Height, 0, m_desc.Depth }; + } + } + + void ClearDirtyBoxes() { + for (uint32_t i = 0; i < m_dirtyBoxes.size(); i++) { + m_dirtyBoxes[i] = { 0, 0, 0, 0, 0, 0 }; + } + } + + const D3DBOX& GetDirtyBox(uint32_t layer) const { + return m_dirtyBoxes[layer]; + } + + static VkImageType GetImageTypeFromResourceType( + D3DRESOURCETYPE Dimension); + + /** + * \brief Tracks sequence number for a given subresource + * + * Stores which CS chunk the resource was last used on. + * \param [in] Subresource Subresource index + * \param [in] Seq Sequence number + */ + void TrackMappingBufferSequenceNumber(UINT Subresource, uint64_t Seq) { + if (Subresource < m_seqs.size()) + m_seqs[Subresource] = Seq; + } + + /** + * \brief Queries sequence number for a given subresource + * + * Returns which CS chunk the resource was last used on. + * \param [in] Subresource Subresource index + * \returns Sequence number for the given subresource + */ + uint64_t GetMappingBufferSequenceNumber(UINT Subresource) { + return Subresource < m_seqs.size() + ? m_seqs[Subresource] + : 0ull; + } + + private: + + D3D9DeviceEx* m_device; + D3D9_COMMON_TEXTURE_DESC m_desc; + D3DRESOURCETYPE m_type; + D3D9_COMMON_TEXTURE_MAP_MODE m_mapMode; + + Rc m_image; + Rc m_resolveImage; + D3D9SubresourceArray< + Rc> m_buffers; + D3D9SubresourceArray< + DxvkBufferSliceHandle> m_mappedSlices; + D3D9SubresourceArray< + uint64_t> m_seqs = { }; + + D3D9_VK_FORMAT_MAPPING m_mapping; + + bool m_shadow; //< Depth Compare-ness + bool m_supportsFetch4; + + int64_t m_size = 0; + + bool m_systemmemModified = false; + + bool m_hazardous = false; + + D3D9ColorView m_sampleView; + + D3D9SubresourceBitset m_locked = { }; + + D3D9SubresourceBitset m_readOnly = { }; + + D3D9SubresourceBitset m_needsReadback = { }; + + D3D9SubresourceBitset m_needsUpload = { }; + + D3D9SubresourceBitset m_uploadUsingStaging = { }; + + DWORD m_exposedMipLevels = 0; + + bool m_needsMipGen = false; + + D3DTEXTUREFILTERTYPE m_mipFilter = D3DTEXF_LINEAR; + + std::array m_dirtyBoxes; + + /** + * \brief Mip level + * \returns Size of packed mip level in bytes + */ + VkDeviceSize GetMipSize(UINT Subresource) const; + + Rc CreatePrimaryImage(D3DRESOURCETYPE ResourceType, bool TryOffscreenRT, HANDLE* pSharedHandle) const; + + Rc CreateResolveImage() const; + + BOOL DetermineShadowState() const; + + BOOL DetermineFetch4Compatibility() const; + + BOOL CheckImageSupport( + const DxvkImageCreateInfo* pImageInfo, + VkImageTiling Tiling) const; + + VkImageUsageFlags EnableMetaCopyUsage( + VkFormat Format, + VkImageTiling Tiling) const; + + D3D9_COMMON_TEXTURE_MAP_MODE DetermineMapMode() const { + if (m_desc.Format == D3D9Format::NULL_FORMAT) + return D3D9_COMMON_TEXTURE_MAP_MODE_NONE; + + if (m_desc.Pool == D3DPOOL_SYSTEMMEM || m_desc.Pool == D3DPOOL_SCRATCH) + return D3D9_COMMON_TEXTURE_MAP_MODE_SYSTEMMEM; + + return D3D9_COMMON_TEXTURE_MAP_MODE_BACKED; + } + + VkImageLayout OptimizeLayout( + VkImageUsageFlags Usage) const; + + void ExportImageInfo(); + + static VkImageViewType GetImageViewTypeFromResourceType( + D3DRESOURCETYPE Dimension, + UINT Layer); + + static constexpr UINT AllLayers = UINT32_MAX; + + }; + +} diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_constant_layout.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_constant_layout.h new file mode 100644 index 00000000000..44efafae6b6 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_constant_layout.h @@ -0,0 +1,31 @@ +#pragma once + +#include + +#include "d3d9_caps.h" + +namespace dxvk { + + struct D3D9ConstantLayout { + uint32_t floatCount; + uint32_t intCount; + uint32_t boolCount; + uint32_t bitmaskCount; + + uint32_t floatSize() const { return floatCount * 4 * sizeof(float); } + uint32_t intSize() const { return intCount * 4 * sizeof(int); } + uint32_t bitmaskSize() const { + // Account for SWVP (non SWVP uses a spec constant) + return bitmaskCount != 1 + ? bitmaskCount * 1 * sizeof(uint32_t) + : 0; + } + + uint32_t intOffset() const { return 0; } + uint32_t floatOffset() const { return intOffset() + intSize(); } + uint32_t bitmaskOffset() const { return floatOffset() + floatSize(); } + + uint32_t totalSize() const { return floatSize() + intSize() + bitmaskSize(); } + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_constant_set.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_constant_set.h new file mode 100644 index 00000000000..a927a1b15a4 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_constant_set.h @@ -0,0 +1,54 @@ +#pragma once + +#include "d3d9_caps.h" + +#include "../dxvk/dxvk_buffer.h" + +#include "../dxso/dxso_isgn.h" + +#include "../util/util_math.h" +#include "../util/util_vector.h" + +#include + +namespace dxvk { + + enum class D3D9ConstantType { + Float, + Int, + Bool + }; + + // We make an assumption later based on the packing of this struct for copying. + struct D3D9ShaderConstantsVSSoftware { + Vector4i iConsts[caps::MaxOtherConstantsSoftware]; + Vector4 fConsts[caps::MaxFloatConstantsSoftware]; + uint32_t bConsts[caps::MaxOtherConstantsSoftware / 32]; + }; + + struct D3D9ShaderConstantsVSHardware { + Vector4i iConsts[caps::MaxOtherConstants]; + Vector4 fConsts[caps::MaxFloatConstantsVS]; + uint32_t bConsts[1]; + }; + + struct D3D9ShaderConstantsPS { + Vector4i iConsts[caps::MaxOtherConstants]; + Vector4 fConsts[caps::MaxFloatConstantsPS]; + uint32_t bConsts[1]; + }; + + struct D3D9SwvpConstantBuffers { + Rc floatBuffer; + Rc intBuffer; + Rc boolBuffer; + }; + + struct D3D9ConstantSets { + D3D9SwvpConstantBuffers swvpBuffers; + Rc buffer; + DxsoShaderMetaInfo meta = {}; + bool dirty = true; + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_cursor.cpp b/utils/dxvk-1.10.3/src/d3d9/d3d9_cursor.cpp new file mode 100644 index 00000000000..408268c1681 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_cursor.cpp @@ -0,0 +1,47 @@ +#include "d3d9_cursor.h" +#include "d3d9_util.h" + +#include + +namespace dxvk { + + void D3D9Cursor::UpdateCursor(int X, int Y) { + POINT currentPos = { }; + if (::GetCursorPos(¤tPos) && currentPos == POINT{ X, Y }) + return; + + ::SetCursorPos(X, Y); + } + + + BOOL D3D9Cursor::ShowCursor(BOOL bShow) { + ::SetCursor(bShow ? m_hCursor : nullptr); + return std::exchange(m_visible, bShow); + } + + + HRESULT D3D9Cursor::SetHardwareCursor(UINT XHotSpot, UINT YHotSpot, const CursorBitmap& bitmap) { + DWORD mask[32]; + std::memset(mask, ~0, sizeof(mask)); + + ICONINFO info; + info.fIcon = FALSE; + info.xHotspot = XHotSpot; + info.yHotspot = YHotSpot; + info.hbmMask = ::CreateBitmap(HardwareCursorWidth, HardwareCursorHeight, 1, 1, mask); + info.hbmColor = ::CreateBitmap(HardwareCursorWidth, HardwareCursorHeight, 1, 32, &bitmap[0]); + + if (m_hCursor != nullptr) + ::DestroyCursor(m_hCursor); + + m_hCursor = ::CreateIconIndirect(&info); + + ::DeleteObject(info.hbmMask); + ::DeleteObject(info.hbmColor); + + ShowCursor(m_visible); + + return D3D_OK; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_cursor.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_cursor.h new file mode 100644 index 00000000000..32645d26c09 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_cursor.h @@ -0,0 +1,33 @@ +#pragma once + +#include "d3d9_include.h" + +namespace dxvk { + + constexpr uint32_t HardwareCursorWidth = 32u; + constexpr uint32_t HardwareCursorHeight = 32u; + constexpr uint32_t HardwareCursorFormatSize = 4u; + constexpr uint32_t HardwareCursorPitch = HardwareCursorWidth * HardwareCursorFormatSize; + + // Format Size of 4 bytes (ARGB) + using CursorBitmap = uint8_t[HardwareCursorHeight * HardwareCursorPitch]; + + class D3D9Cursor { + + public: + + void UpdateCursor(int X, int Y); + + BOOL ShowCursor(BOOL bShow); + + HRESULT SetHardwareCursor(UINT XHotSpot, UINT YHotSpot, const CursorBitmap& bitmap); + + private: + + BOOL m_visible = FALSE; + + HCURSOR m_hCursor = nullptr; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_device.cpp b/utils/dxvk-1.10.3/src/d3d9/d3d9_device.cpp new file mode 100644 index 00000000000..734a7a0c973 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_device.cpp @@ -0,0 +1,7402 @@ +#include "d3d9_device.h" + +#include "d3d9_annotation.h" +#include "d3d9_interface.h" +#include "d3d9_swapchain.h" +#include "d3d9_caps.h" +#include "d3d9_util.h" +#include "d3d9_texture.h" +#include "d3d9_buffer.h" +#include "d3d9_vertex_declaration.h" +#include "d3d9_shader.h" +#include "d3d9_query.h" +#include "d3d9_stateblock.h" +#include "d3d9_monitor.h" +#include "d3d9_spec_constants.h" +#include "d3d9_names.h" +#include "d3d9_format_helpers.h" + +#include "../dxvk/dxvk_adapter.h" +#include "../dxvk/dxvk_instance.h" + +#include "../util/util_bit.h" +#include "../util/util_math.h" + +#include "d3d9_initializer.h" + +#include +#include +#ifdef MSC_VER +#pragma fenv_access (on) +#endif + +namespace dxvk { + + D3D9DeviceEx::D3D9DeviceEx( + D3D9InterfaceEx* pParent, + D3D9Adapter* pAdapter, + D3DDEVTYPE DeviceType, + HWND hFocusWindow, + DWORD BehaviorFlags, + Rc dxvkDevice) + : m_parent ( pParent ) + , m_deviceType ( DeviceType ) + , m_window ( hFocusWindow ) + , m_behaviorFlags ( BehaviorFlags ) + , m_adapter ( pAdapter ) + , m_dxvkDevice ( dxvkDevice ) + , m_shaderModules ( new D3D9ShaderModuleSet ) + , m_d3d9Options ( dxvkDevice, pParent->GetInstance()->config() ) + , m_multithread ( BehaviorFlags & D3DCREATE_MULTITHREADED ) + , m_isSWVP ( (BehaviorFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING) ? true : false ) + , m_csThread ( dxvkDevice, dxvkDevice->createContext() ) + , m_csChunk ( AllocCsChunk() ) { + // If we can SWVP, then we use an extended constant set + // as SWVP has many more slots available than HWVP. + bool canSWVP = CanSWVP(); + DetermineConstantLayouts(canSWVP); + + if (canSWVP) + Logger::info("D3D9DeviceEx: Using extended constant set for software vertex processing."); + + if (m_dxvkDevice->instance()->extensions().extDebugUtils) + m_annotation = new D3D9UserDefinedAnnotation(this); + + m_initializer = new D3D9Initializer(m_dxvkDevice); + m_converter = new D3D9FormatHelper(m_dxvkDevice); + + EmitCs([ + cDevice = m_dxvkDevice + ] (DxvkContext* ctx) { + ctx->beginRecording(cDevice->createCommandList()); + + DxvkLogicOpState loState; + loState.enableLogicOp = VK_FALSE; + loState.logicOp = VK_LOGIC_OP_CLEAR; + ctx->setLogicOpState(loState); + }); + + if (!(BehaviorFlags & D3DCREATE_FPU_PRESERVE)) + SetupFPU(); + + m_dxsoOptions = DxsoOptions(this, m_d3d9Options); + + const bool supportsRobustness2 = m_dxvkDevice->features().extRobustness2.robustBufferAccess2; + bool useRobustConstantAccess = supportsRobustness2; + if (useRobustConstantAccess) { + m_robustSSBOAlignment = m_dxvkDevice->properties().extRobustness2.robustStorageBufferAccessSizeAlignment; + m_robustUBOAlignment = m_dxvkDevice->properties().extRobustness2.robustUniformBufferAccessSizeAlignment; + if (canSWVP) { + const uint32_t floatBufferAlignment = m_dxsoOptions.vertexFloatConstantBufferAsSSBO ? m_robustSSBOAlignment : m_robustUBOAlignment; + useRobustConstantAccess &= m_vsLayout.floatSize() % floatBufferAlignment == 0; + useRobustConstantAccess &= m_vsLayout.intSize() % m_robustUBOAlignment == 0; + useRobustConstantAccess &= m_vsLayout.bitmaskSize() % m_robustUBOAlignment == 0; + } else { + useRobustConstantAccess &= m_vsLayout.totalSize() % m_robustUBOAlignment == 0; + } + useRobustConstantAccess &= m_psLayout.totalSize() % m_robustUBOAlignment == 0; + } + + if (!useRobustConstantAccess) { + m_vsFloatConstsCount = m_vsLayout.floatCount; + m_vsIntConstsCount = m_vsLayout.intCount; + m_vsBoolConstsCount = m_vsLayout.boolCount; + m_psFloatConstsCount = m_psLayout.floatCount; + + if (supportsRobustness2) { + Logger::warn("Disabling robust constant buffer access because of alignment."); + } + } + + CreateConstantBuffers(); + + m_availableMemory = DetermineInitialTextureMemory(); + + // Initially set all the dirty flags so we + // always end up giving the backend *something* to work with. + m_flags.set(D3D9DeviceFlag::DirtyFramebuffer); + m_flags.set(D3D9DeviceFlag::DirtyClipPlanes); + m_flags.set(D3D9DeviceFlag::DirtyDepthStencilState); + m_flags.set(D3D9DeviceFlag::DirtyBlendState); + m_flags.set(D3D9DeviceFlag::DirtyRasterizerState); + m_flags.set(D3D9DeviceFlag::DirtyDepthBias); + m_flags.set(D3D9DeviceFlag::DirtyAlphaTestState); + m_flags.set(D3D9DeviceFlag::DirtyInputLayout); + m_flags.set(D3D9DeviceFlag::DirtyViewportScissor); + m_flags.set(D3D9DeviceFlag::DirtyMultiSampleState); + + m_flags.set(D3D9DeviceFlag::DirtyFogState); + m_flags.set(D3D9DeviceFlag::DirtyFogColor); + m_flags.set(D3D9DeviceFlag::DirtyFogDensity); + m_flags.set(D3D9DeviceFlag::DirtyFogScale); + m_flags.set(D3D9DeviceFlag::DirtyFogEnd); + + m_flags.set(D3D9DeviceFlag::DirtyFFVertexData); + m_flags.set(D3D9DeviceFlag::DirtyFFVertexBlend); + m_flags.set(D3D9DeviceFlag::DirtyFFVertexShader); + m_flags.set(D3D9DeviceFlag::DirtyFFPixelShader); + m_flags.set(D3D9DeviceFlag::DirtyFFViewport); + m_flags.set(D3D9DeviceFlag::DirtyFFPixelData); + m_flags.set(D3D9DeviceFlag::DirtyProgVertexShader); + m_flags.set(D3D9DeviceFlag::DirtySharedPixelShaderData); + m_flags.set(D3D9DeviceFlag::DirtyDepthBounds); + m_flags.set(D3D9DeviceFlag::DirtyPointScale); + } + + + D3D9DeviceEx::~D3D9DeviceEx() { + Flush(); + SynchronizeCsThread(DxvkCsThread::SynchronizeAll); + + if (m_annotation) + delete m_annotation; + + delete m_initializer; + delete m_converter; + + m_dxvkDevice->waitForIdle(); // Sync Device + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::QueryInterface(REFIID riid, void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + bool extended = m_parent->IsExtended() + && riid == __uuidof(IDirect3DDevice9Ex); + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(IDirect3DDevice9) + || extended) { + *ppvObject = ref(this); + return S_OK; + } + + // We want to ignore this if the extended device is queried and we weren't made extended. + if (riid == __uuidof(IDirect3DDevice9Ex)) + return E_NOINTERFACE; + + Logger::warn("D3D9DeviceEx::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::TestCooperativeLevel() { + // Equivelant of D3D11/DXGI present tests. We can always present. + return D3D_OK; + } + + + UINT STDMETHODCALLTYPE D3D9DeviceEx::GetAvailableTextureMem() { + // This is not meant to be accurate. + // The values are also wildly incorrect in d3d9... But some games rely + // on this inaccurate value... + + // Clamp to megabyte range, as per spec. + constexpr UINT range = 0xfff00000; + + // Can't have negative memory! + int64_t memory = std::max(m_availableMemory.load(), 0); + + return UINT(memory) & range; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::EvictManagedResources() { + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetDirect3D(IDirect3D9** ppD3D9) { + if (ppD3D9 == nullptr) + return D3DERR_INVALIDCALL; + + *ppD3D9 = m_parent.ref(); + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetDeviceCaps(D3DCAPS9* pCaps) { + return m_adapter->GetDeviceCaps(m_deviceType, pCaps); + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetDisplayMode(UINT iSwapChain, D3DDISPLAYMODE* pMode) { + if (unlikely(iSwapChain != 0)) + return D3DERR_INVALIDCALL; + + return m_implicitSwapchain->GetDisplayMode(pMode); + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetCreationParameters(D3DDEVICE_CREATION_PARAMETERS *pParameters) { + if (pParameters == nullptr) + return D3DERR_INVALIDCALL; + + pParameters->AdapterOrdinal = m_adapter->GetOrdinal(); + pParameters->BehaviorFlags = m_behaviorFlags; + pParameters->DeviceType = m_deviceType; + pParameters->hFocusWindow = m_window; + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetCursorProperties( + UINT XHotSpot, + UINT YHotSpot, + IDirect3DSurface9* pCursorBitmap) { + D3D9DeviceLock lock = LockDevice(); + + if (unlikely(pCursorBitmap == nullptr)) + return D3DERR_INVALIDCALL; + + auto* cursorTex = GetCommonTexture(pCursorBitmap); + if (unlikely(cursorTex->Desc()->Format != D3D9Format::A8R8G8B8)) + return D3DERR_INVALIDCALL; + + uint32_t inputWidth = cursorTex->Desc()->Width; + uint32_t inputHeight = cursorTex->Desc()->Height; + + // Always use a hardware cursor when windowed. + bool hwCursor = m_presentParams.Windowed; + + // Always use a hardware cursor w/h <= 32 px + hwCursor |= inputWidth <= HardwareCursorWidth + || inputHeight <= HardwareCursorHeight; + + if (hwCursor) { + D3DLOCKED_BOX lockedBox; + HRESULT hr = LockImage(cursorTex, 0, 0, &lockedBox, nullptr, D3DLOCK_READONLY); + if (FAILED(hr)) + return hr; + + const uint8_t* data = reinterpret_cast(lockedBox.pBits); + + // Windows works with a stride of 128, lets respect that. + // Copy data to the bitmap... + CursorBitmap bitmap = { 0 }; + size_t copyPitch = std::min( + HardwareCursorPitch, + inputWidth * inputHeight * HardwareCursorFormatSize); + + for (uint32_t h = 0; h < HardwareCursorHeight; h++) + std::memcpy(&bitmap[h * HardwareCursorPitch], &data[h * lockedBox.RowPitch], copyPitch); + + UnlockImage(cursorTex, 0, 0); + + // Set this as our cursor. + return m_cursor.SetHardwareCursor(XHotSpot, YHotSpot, bitmap); + } + + // Software Cursor... + Logger::warn("D3D9DeviceEx::SetCursorProperties: Software cursor not implemented."); + return D3D_OK; + } + + + void STDMETHODCALLTYPE D3D9DeviceEx::SetCursorPosition(int X, int Y, DWORD Flags) { + D3D9DeviceLock lock = LockDevice(); + + // I was not able to find an instance + // where the cursor update was not immediate. + + // Fullscreen + Windowed seem to have the same + // behaviour here. + + // Hence we ignore the flag D3DCURSOR_IMMEDIATE_UPDATE. + + m_cursor.UpdateCursor(X, Y); + } + + + BOOL STDMETHODCALLTYPE D3D9DeviceEx::ShowCursor(BOOL bShow) { + D3D9DeviceLock lock = LockDevice(); + + return m_cursor.ShowCursor(bShow); + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::CreateAdditionalSwapChain( + D3DPRESENT_PARAMETERS* pPresentationParameters, + IDirect3DSwapChain9** ppSwapChain) { + return CreateAdditionalSwapChainEx(pPresentationParameters, nullptr, ppSwapChain); + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetSwapChain(UINT iSwapChain, IDirect3DSwapChain9** pSwapChain) { + D3D9DeviceLock lock = LockDevice(); + + InitReturnPtr(pSwapChain); + + if (unlikely(pSwapChain == nullptr)) + return D3DERR_INVALIDCALL; + + // This only returns the implicit swapchain... + + if (unlikely(iSwapChain != 0)) + return D3DERR_INVALIDCALL; + + *pSwapChain = static_cast(m_implicitSwapchain.ref()); + + return D3D_OK; + } + + + UINT STDMETHODCALLTYPE D3D9DeviceEx::GetNumberOfSwapChains() { + // This only counts the implicit swapchain... + + return 1; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::Reset(D3DPRESENT_PARAMETERS* pPresentationParameters) { + D3D9DeviceLock lock = LockDevice(); + + HRESULT hr = ResetSwapChain(pPresentationParameters, nullptr); + if (FAILED(hr)) + return hr; + + hr = ResetState(pPresentationParameters); + if (FAILED(hr)) + return hr; + + Flush(); + SynchronizeCsThread(DxvkCsThread::SynchronizeAll); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::Present( + const RECT* pSourceRect, + const RECT* pDestRect, + HWND hDestWindowOverride, + const RGNDATA* pDirtyRegion) { + return PresentEx( + pSourceRect, + pDestRect, + hDestWindowOverride, + pDirtyRegion, + 0); + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetBackBuffer( + UINT iSwapChain, + UINT iBackBuffer, + D3DBACKBUFFER_TYPE Type, + IDirect3DSurface9** ppBackBuffer) { + InitReturnPtr(ppBackBuffer); + + if (unlikely(iSwapChain != 0)) + return D3DERR_INVALIDCALL; + + return m_implicitSwapchain->GetBackBuffer(iBackBuffer, Type, ppBackBuffer); + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetRasterStatus(UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) { + if (unlikely(iSwapChain != 0)) + return D3DERR_INVALIDCALL; + + return m_implicitSwapchain->GetRasterStatus(pRasterStatus); + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetDialogBoxMode(BOOL bEnableDialogs) { + return m_implicitSwapchain->SetDialogBoxMode(bEnableDialogs); + } + + + void STDMETHODCALLTYPE D3D9DeviceEx::SetGammaRamp( + UINT iSwapChain, + DWORD Flags, + const D3DGAMMARAMP* pRamp) { + if (unlikely(iSwapChain != 0)) + return; + + m_implicitSwapchain->SetGammaRamp(Flags, pRamp); + } + + + void STDMETHODCALLTYPE D3D9DeviceEx::GetGammaRamp(UINT iSwapChain, D3DGAMMARAMP* pRamp) { + if (unlikely(iSwapChain != 0)) + return; + + m_implicitSwapchain->GetGammaRamp(pRamp); + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::CreateTexture( + UINT Width, + UINT Height, + UINT Levels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + IDirect3DTexture9** ppTexture, + HANDLE* pSharedHandle) { + InitReturnPtr(ppTexture); + + if (unlikely(ppTexture == nullptr)) + return D3DERR_INVALIDCALL; + + D3D9_COMMON_TEXTURE_DESC desc; + desc.Width = Width; + desc.Height = Height; + desc.Depth = 1; + desc.ArraySize = 1; + desc.MipLevels = Levels; + desc.Usage = Usage; + desc.Format = EnumerateFormat(Format); + desc.Pool = Pool; + desc.Discard = FALSE; + desc.MultiSample = D3DMULTISAMPLE_NONE; + desc.MultisampleQuality = 0; + desc.IsBackBuffer = FALSE; + desc.IsAttachmentOnly = FALSE; + + if (FAILED(D3D9CommonTexture::NormalizeTextureProperties(this, &desc))) + return D3DERR_INVALIDCALL; + + try { + void* initialData = nullptr; + + if (Pool == D3DPOOL_SYSTEMMEM && Levels == 1 && pSharedHandle != nullptr) { + initialData = *(reinterpret_cast(pSharedHandle)); + pSharedHandle = nullptr; + } + + if (pSharedHandle != nullptr && Pool != D3DPOOL_DEFAULT) + return D3DERR_INVALIDCALL; + + const Com texture = new D3D9Texture2D(this, &desc, pSharedHandle); + + m_initializer->InitTexture(texture->GetCommonTexture(), initialData); + *ppTexture = texture.ref(); + + return D3D_OK; + } + catch (const DxvkError& e) { + Logger::err(e.message()); + return D3DERR_OUTOFVIDEOMEMORY; + } + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::CreateVolumeTexture( + UINT Width, + UINT Height, + UINT Depth, + UINT Levels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + IDirect3DVolumeTexture9** ppVolumeTexture, + HANDLE* pSharedHandle) { + InitReturnPtr(ppVolumeTexture); + + if (unlikely(ppVolumeTexture == nullptr)) + return D3DERR_INVALIDCALL; + + if (pSharedHandle) + Logger::err("CreateVolumeTexture: Shared volume textures not supported"); + + D3D9_COMMON_TEXTURE_DESC desc; + desc.Width = Width; + desc.Height = Height; + desc.Depth = Depth; + desc.ArraySize = 1; + desc.MipLevels = Levels; + desc.Usage = Usage; + desc.Format = EnumerateFormat(Format); + desc.Pool = Pool; + desc.Discard = FALSE; + desc.MultiSample = D3DMULTISAMPLE_NONE; + desc.MultisampleQuality = 0; + desc.IsBackBuffer = FALSE; + desc.IsAttachmentOnly = FALSE; + + if (FAILED(D3D9CommonTexture::NormalizeTextureProperties(this, &desc))) + return D3DERR_INVALIDCALL; + + try { + const Com texture = new D3D9Texture3D(this, &desc); + m_initializer->InitTexture(texture->GetCommonTexture()); + *ppVolumeTexture = texture.ref(); + + return D3D_OK; + } + catch (const DxvkError& e) { + Logger::err(e.message()); + return D3DERR_OUTOFVIDEOMEMORY; + } + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::CreateCubeTexture( + UINT EdgeLength, + UINT Levels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + IDirect3DCubeTexture9** ppCubeTexture, + HANDLE* pSharedHandle) { + InitReturnPtr(ppCubeTexture); + + if (unlikely(ppCubeTexture == nullptr)) + return D3DERR_INVALIDCALL; + + if (pSharedHandle) + Logger::err("CreateCubeTexture: Shared cube textures not supported"); + + D3D9_COMMON_TEXTURE_DESC desc; + desc.Width = EdgeLength; + desc.Height = EdgeLength; + desc.Depth = 1; + desc.ArraySize = 6; // A cube has 6 faces, wowwie! + desc.MipLevels = Levels; + desc.Usage = Usage; + desc.Format = EnumerateFormat(Format); + desc.Pool = Pool; + desc.Discard = FALSE; + desc.MultiSample = D3DMULTISAMPLE_NONE; + desc.MultisampleQuality = 0; + desc.IsBackBuffer = FALSE; + desc.IsAttachmentOnly = FALSE; + + if (FAILED(D3D9CommonTexture::NormalizeTextureProperties(this, &desc))) + return D3DERR_INVALIDCALL; + + try { + const Com texture = new D3D9TextureCube(this, &desc); + m_initializer->InitTexture(texture->GetCommonTexture()); + *ppCubeTexture = texture.ref(); + + return D3D_OK; + } + catch (const DxvkError& e) { + Logger::err(e.message()); + return D3DERR_OUTOFVIDEOMEMORY; + } + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::CreateVertexBuffer( + UINT Length, + DWORD Usage, + DWORD FVF, + D3DPOOL Pool, + IDirect3DVertexBuffer9** ppVertexBuffer, + HANDLE* pSharedHandle) { + InitReturnPtr(ppVertexBuffer); + + if (unlikely(ppVertexBuffer == nullptr)) + return D3DERR_INVALIDCALL; + + if (pSharedHandle) + Logger::err("CreateVertexBuffer: Shared vertex buffers not supported"); + + D3D9_BUFFER_DESC desc; + desc.Format = D3D9Format::VERTEXDATA; + desc.FVF = FVF; + desc.Pool = Pool; + desc.Size = Length; + desc.Type = D3DRTYPE_VERTEXBUFFER; + desc.Usage = Usage; + + if (FAILED(D3D9CommonBuffer::ValidateBufferProperties(&desc))) + return D3DERR_INVALIDCALL; + + try { + const Com buffer = new D3D9VertexBuffer(this, &desc); + m_initializer->InitBuffer(buffer->GetCommonBuffer()); + *ppVertexBuffer = buffer.ref(); + return D3D_OK; + } + catch (const DxvkError & e) { + Logger::err(e.message()); + return D3DERR_INVALIDCALL; + } + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::CreateIndexBuffer( + UINT Length, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + IDirect3DIndexBuffer9** ppIndexBuffer, + HANDLE* pSharedHandle) { + InitReturnPtr(ppIndexBuffer); + + if (unlikely(ppIndexBuffer == nullptr)) + return D3DERR_INVALIDCALL; + + if (pSharedHandle) + Logger::err("CreateIndexBuffer: Shared index buffers not supported"); + + D3D9_BUFFER_DESC desc; + desc.Format = EnumerateFormat(Format); + desc.Pool = Pool; + desc.Size = Length; + desc.Type = D3DRTYPE_INDEXBUFFER; + desc.Usage = Usage; + + if (FAILED(D3D9CommonBuffer::ValidateBufferProperties(&desc))) + return D3DERR_INVALIDCALL; + + try { + const Com buffer = new D3D9IndexBuffer(this, &desc); + m_initializer->InitBuffer(buffer->GetCommonBuffer()); + *ppIndexBuffer = buffer.ref(); + return D3D_OK; + } + catch (const DxvkError & e) { + Logger::err(e.message()); + return D3DERR_INVALIDCALL; + } + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::CreateRenderTarget( + UINT Width, + UINT Height, + D3DFORMAT Format, + D3DMULTISAMPLE_TYPE MultiSample, + DWORD MultisampleQuality, + BOOL Lockable, + IDirect3DSurface9** ppSurface, + HANDLE* pSharedHandle) { + return CreateRenderTargetEx( + Width, + Height, + Format, + MultiSample, + MultisampleQuality, + Lockable, + ppSurface, + pSharedHandle, + 0); + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::CreateDepthStencilSurface( + UINT Width, + UINT Height, + D3DFORMAT Format, + D3DMULTISAMPLE_TYPE MultiSample, + DWORD MultisampleQuality, + BOOL Discard, + IDirect3DSurface9** ppSurface, + HANDLE* pSharedHandle) { + return CreateDepthStencilSurfaceEx( + Width, + Height, + Format, + MultiSample, + MultisampleQuality, + Discard, + ppSurface, + pSharedHandle, + 0); + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::UpdateSurface( + IDirect3DSurface9* pSourceSurface, + const RECT* pSourceRect, + IDirect3DSurface9* pDestinationSurface, + const POINT* pDestPoint) { + D3D9DeviceLock lock = LockDevice(); + + D3D9Surface* src = static_cast(pSourceSurface); + D3D9Surface* dst = static_cast(pDestinationSurface); + + if (unlikely(src == nullptr || dst == nullptr)) + return D3DERR_INVALIDCALL; + + D3D9CommonTexture* srcTextureInfo = src->GetCommonTexture(); + D3D9CommonTexture* dstTextureInfo = dst->GetCommonTexture(); + + if (unlikely(srcTextureInfo->Desc()->Pool != D3DPOOL_SYSTEMMEM || dstTextureInfo->Desc()->Pool != D3DPOOL_DEFAULT)) + return D3DERR_INVALIDCALL; + + if (unlikely(srcTextureInfo->Desc()->Format != dstTextureInfo->Desc()->Format)) + return D3DERR_INVALIDCALL; + + const DxvkFormatInfo* formatInfo = imageFormatInfo(dstTextureInfo->GetFormatMapping().FormatColor); + + VkOffset3D srcOffset = { 0u, 0u, 0u }; + VkOffset3D dstOffset = { 0u, 0u, 0u }; + VkExtent3D texLevelExtent = srcTextureInfo->GetExtentMip(src->GetSubresource()); + VkExtent3D extent = texLevelExtent; + + if (pSourceRect != nullptr) { + srcOffset = { pSourceRect->left, + pSourceRect->top, + 0u }; + + extent = { uint32_t(pSourceRect->right - pSourceRect->left), uint32_t(pSourceRect->bottom - pSourceRect->top), 1 }; + + const bool extentAligned = extent.width % formatInfo->blockSize.width == 0 + && extent.height % formatInfo->blockSize.height == 0; + + if (pSourceRect->left < 0 + || pSourceRect->top < 0 + || pSourceRect->right <= pSourceRect->left + || pSourceRect->bottom <= pSourceRect->top + || pSourceRect->left % formatInfo->blockSize.width != 0 + || pSourceRect->top % formatInfo->blockSize.height != 0 + || (extent != texLevelExtent && !extentAligned)) + return D3DERR_INVALIDCALL; + } + + if (pDestPoint != nullptr) { + if (pDestPoint->x % formatInfo->blockSize.width != 0 + || pDestPoint->y % formatInfo->blockSize.height != 0 + || pDestPoint->x < 0 + || pDestPoint->y < 0) + return D3DERR_INVALIDCALL; + + dstOffset = { pDestPoint->x, + pDestPoint->y, + 0u }; + } + + UpdateTextureFromBuffer(dstTextureInfo, srcTextureInfo, dst->GetSubresource(), src->GetSubresource(), srcOffset, extent, dstOffset); + + dstTextureInfo->SetNeedsReadback(dst->GetSubresource(), true); + + if (dstTextureInfo->IsAutomaticMip()) + MarkTextureMipsDirty(dstTextureInfo); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::UpdateTexture( + IDirect3DBaseTexture9* pSourceTexture, + IDirect3DBaseTexture9* pDestinationTexture) { + D3D9DeviceLock lock = LockDevice(); + + if (!pDestinationTexture || !pSourceTexture) + return D3DERR_INVALIDCALL; + + D3D9CommonTexture* dstTexInfo = GetCommonTexture(pDestinationTexture); + D3D9CommonTexture* srcTexInfo = GetCommonTexture(pSourceTexture); + + if (unlikely(srcTexInfo->Desc()->Pool != D3DPOOL_SYSTEMMEM || dstTexInfo->Desc()->Pool != D3DPOOL_DEFAULT)) + return D3DERR_INVALIDCALL; + + if (unlikely(srcTexInfo->Desc()->MipLevels < dstTexInfo->Desc()->MipLevels && !dstTexInfo->IsAutomaticMip())) + return D3DERR_INVALIDCALL; + + if (unlikely(dstTexInfo->Desc()->Format != srcTexInfo->Desc()->Format)) + return D3DERR_INVALIDCALL; + + if (unlikely(srcTexInfo->IsAutomaticMip() && !dstTexInfo->IsAutomaticMip())) + return D3DERR_INVALIDCALL; + + const Rc dstImage = dstTexInfo->GetImage(); + uint32_t mipLevels = dstTexInfo->IsAutomaticMip() ? 1 : dstTexInfo->Desc()->MipLevels; + uint32_t arraySlices = std::min(srcTexInfo->Desc()->ArraySize, dstTexInfo->Desc()->ArraySize); + + uint32_t srcMipOffset = srcTexInfo->Desc()->MipLevels - mipLevels; + VkExtent3D srcFirstMipExtent = util::computeMipLevelExtent(srcTexInfo->GetExtent(), srcMipOffset); + VkExtent3D dstFirstMipExtent = dstTexInfo->GetExtent(); + if (srcFirstMipExtent != dstFirstMipExtent) + return D3DERR_INVALIDCALL; + + for (uint32_t a = 0; a < arraySlices; a++) { + const D3DBOX& box = srcTexInfo->GetDirtyBox(a); + if (box.Left >= box.Right || box.Top >= box.Bottom || box.Front >= box.Back) + continue; + + VkExtent3D mip0Extent = { + uint32_t(box.Right - box.Left), + uint32_t(box.Bottom - box.Top), + uint32_t(box.Back - box.Front) + }; + VkOffset3D mip0Offset = { int32_t(box.Left), int32_t(box.Top), int32_t(box.Front) }; + + for (uint32_t dstMip = 0; dstMip < mipLevels; dstMip++) { + uint32_t srcMip = dstMip + srcMipOffset; + uint32_t srcSubresource = srcTexInfo->CalcSubresource(a, srcMip); + uint32_t dstSubresource = dstTexInfo->CalcSubresource(a, dstMip); + VkExtent3D extent = util::computeMipLevelExtent(mip0Extent, srcMip); + VkOffset3D offset = util::computeMipLevelOffset(mip0Offset, srcMip); + + UpdateTextureFromBuffer(dstTexInfo, srcTexInfo, dstSubresource, srcSubresource, offset, extent, offset); + dstTexInfo->SetNeedsReadback(dstSubresource, true); + } + } + + srcTexInfo->ClearDirtyBoxes(); + if (dstTexInfo->IsAutomaticMip() && mipLevels != dstTexInfo->Desc()->MipLevels) + MarkTextureMipsDirty(dstTexInfo); + + FlushImplicit(false); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetRenderTargetData( + IDirect3DSurface9* pRenderTarget, + IDirect3DSurface9* pDestSurface) { + D3D9DeviceLock lock = LockDevice(); + + D3D9Surface* src = static_cast(pRenderTarget); + D3D9Surface* dst = static_cast(pDestSurface); + + if (unlikely(src == nullptr || dst == nullptr)) + return D3DERR_INVALIDCALL; + + if (pRenderTarget == pDestSurface) + return D3D_OK; + + D3D9CommonTexture* dstTexInfo = GetCommonTexture(dst); + D3D9CommonTexture* srcTexInfo = GetCommonTexture(src); + + if (srcTexInfo->Desc()->Format != dstTexInfo->Desc()->Format) + return D3DERR_INVALIDCALL; + + if (dstTexInfo->Desc()->Pool == D3DPOOL_DEFAULT) + return this->StretchRect(pRenderTarget, nullptr, pDestSurface, nullptr, D3DTEXF_NONE); + + Rc dstBuffer = dstTexInfo->GetBuffer(dst->GetSubresource()); + + Rc srcImage = srcTexInfo->GetImage(); + const DxvkFormatInfo* srcFormatInfo = imageFormatInfo(srcImage->info().format); + + const VkImageSubresource srcSubresource = srcTexInfo->GetSubresourceFromIndex(srcFormatInfo->aspectMask, src->GetSubresource()); + VkImageSubresourceLayers srcSubresourceLayers = { + srcSubresource.aspectMask, + srcSubresource.mipLevel, + srcSubresource.arrayLayer, 1 }; + + VkExtent3D srcExtent = srcTexInfo->GetExtentMip(src->GetMipLevel()); + + VkExtent3D texLevelExtentBlockCount = util::computeBlockCount(srcExtent, srcFormatInfo->blockSize); + VkDeviceSize pitch = align(texLevelExtentBlockCount.width * uint32_t(srcFormatInfo->elementSize), 4); + uint32_t pitchBlocks = uint32_t(pitch / srcFormatInfo->elementSize); + VkExtent2D dstExtent = VkExtent2D{ pitchBlocks, + texLevelExtentBlockCount.height * pitchBlocks }; + + EmitCs([ + cBuffer = dstBuffer, + cImage = srcImage, + cSubresources = srcSubresourceLayers, + cLevelExtent = srcExtent, + cDstExtent = dstExtent + ] (DxvkContext* ctx) { + ctx->copyImageToBuffer(cBuffer, 0, 4, 0, + cImage, cSubresources, VkOffset3D { 0, 0, 0 }, + cLevelExtent); + }); + + dstTexInfo->SetNeedsReadback(dst->GetSubresource(), true); + TrackTextureMappingBufferSequenceNumber(dstTexInfo, dst->GetSubresource()); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetFrontBufferData(UINT iSwapChain, IDirect3DSurface9* pDestSurface) { + if (unlikely(iSwapChain != 0)) + return D3DERR_INVALIDCALL; + + return m_implicitSwapchain->GetFrontBufferData(pDestSurface); + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::StretchRect( + IDirect3DSurface9* pSourceSurface, + const RECT* pSourceRect, + IDirect3DSurface9* pDestSurface, + const RECT* pDestRect, + D3DTEXTUREFILTERTYPE Filter) { + D3D9DeviceLock lock = LockDevice(); + + D3D9Surface* dst = static_cast(pDestSurface); + D3D9Surface* src = static_cast(pSourceSurface); + + if (unlikely(src == nullptr || dst == nullptr)) + return D3DERR_INVALIDCALL; + + if (unlikely(src == dst)) + return D3DERR_INVALIDCALL; + + bool fastPath = true; + + D3D9CommonTexture* dstTextureInfo = dst->GetCommonTexture(); + D3D9CommonTexture* srcTextureInfo = src->GetCommonTexture(); + + if (unlikely(dstTextureInfo->Desc()->Pool != D3DPOOL_DEFAULT || + srcTextureInfo->Desc()->Pool != D3DPOOL_DEFAULT)) + return D3DERR_INVALIDCALL; + + Rc dstImage = dstTextureInfo->GetImage(); + Rc srcImage = srcTextureInfo->GetImage(); + + if (dstImage == nullptr || srcImage == nullptr) + return D3DERR_INVALIDCALL; + + const DxvkFormatInfo* dstFormatInfo = imageFormatInfo(dstImage->info().format); + const DxvkFormatInfo* srcFormatInfo = imageFormatInfo(srcImage->info().format); + + const VkImageSubresource dstSubresource = dstTextureInfo->GetSubresourceFromIndex(dstFormatInfo->aspectMask, dst->GetSubresource()); + const VkImageSubresource srcSubresource = srcTextureInfo->GetSubresourceFromIndex(srcFormatInfo->aspectMask, src->GetSubresource()); + + if (unlikely((srcSubresource.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) && m_flags.test(D3D9DeviceFlag::InScene))) + return D3DERR_INVALIDCALL; + + VkExtent3D srcExtent = srcImage->mipLevelExtent(srcSubresource.mipLevel); + VkExtent3D dstExtent = dstImage->mipLevelExtent(dstSubresource.mipLevel); + + D3D9Format srcFormat = srcTextureInfo->Desc()->Format; + D3D9Format dstFormat = dstTextureInfo->Desc()->Format; + + // We may only fast path copy non identicals one way! + // We don't know what garbage could be in the X8 data. + bool similar = AreFormatsSimilar(srcFormat, dstFormat); + + // Copies are only supported on similar formats. + fastPath &= similar; + + // Copies are only supported if the sample count matches, + // otherwise we need to resolve. + bool needsResolve = srcImage->info().sampleCount != VK_SAMPLE_COUNT_1_BIT; + bool fbBlit = dstImage->info().sampleCount != VK_SAMPLE_COUNT_1_BIT; + fastPath &= !fbBlit; + + // Copies would only work if we are block aligned. + if (pSourceRect != nullptr) { + fastPath &= (pSourceRect->left % srcFormatInfo->blockSize.width == 0); + fastPath &= (pSourceRect->right % srcFormatInfo->blockSize.width == 0); + fastPath &= (pSourceRect->top % srcFormatInfo->blockSize.height == 0); + fastPath &= (pSourceRect->bottom % srcFormatInfo->blockSize.height == 0); + } + + if (pDestRect != nullptr) { + fastPath &= (pDestRect->left % dstFormatInfo->blockSize.width == 0); + fastPath &= (pDestRect->top % dstFormatInfo->blockSize.height == 0); + } + + VkImageSubresourceLayers dstSubresourceLayers = { + dstSubresource.aspectMask, + dstSubresource.mipLevel, + dstSubresource.arrayLayer, 1 }; + + VkImageSubresourceLayers srcSubresourceLayers = { + srcSubresource.aspectMask, + srcSubresource.mipLevel, + srcSubresource.arrayLayer, 1 }; + + VkImageBlit blitInfo; + blitInfo.dstSubresource = dstSubresourceLayers; + blitInfo.srcSubresource = srcSubresourceLayers; + + blitInfo.dstOffsets[0] = pDestRect != nullptr + ? VkOffset3D{ int32_t(pDestRect->left), int32_t(pDestRect->top), 0 } + : VkOffset3D{ 0, 0, 0 }; + + blitInfo.dstOffsets[1] = pDestRect != nullptr + ? VkOffset3D{ int32_t(pDestRect->right), int32_t(pDestRect->bottom), 1 } + : VkOffset3D{ int32_t(dstExtent.width), int32_t(dstExtent.height), 1 }; + + blitInfo.srcOffsets[0] = pSourceRect != nullptr + ? VkOffset3D{ int32_t(pSourceRect->left), int32_t(pSourceRect->top), 0 } + : VkOffset3D{ 0, 0, 0 }; + + blitInfo.srcOffsets[1] = pSourceRect != nullptr + ? VkOffset3D{ int32_t(pSourceRect->right), int32_t(pSourceRect->bottom), 1 } + : VkOffset3D{ int32_t(srcExtent.width), int32_t(srcExtent.height), 1 }; + + if (unlikely(IsBlitRegionInvalid(blitInfo.srcOffsets, srcExtent))) + return D3DERR_INVALIDCALL; + + if (unlikely(IsBlitRegionInvalid(blitInfo.dstOffsets, dstExtent))) + return D3DERR_INVALIDCALL; + + VkExtent3D srcCopyExtent = + { uint32_t(blitInfo.srcOffsets[1].x - blitInfo.srcOffsets[0].x), + uint32_t(blitInfo.srcOffsets[1].y - blitInfo.srcOffsets[0].y), + uint32_t(blitInfo.srcOffsets[1].z - blitInfo.srcOffsets[0].z) }; + + VkExtent3D dstCopyExtent = + { uint32_t(blitInfo.dstOffsets[1].x - blitInfo.dstOffsets[0].x), + uint32_t(blitInfo.dstOffsets[1].y - blitInfo.dstOffsets[0].y), + uint32_t(blitInfo.dstOffsets[1].z - blitInfo.dstOffsets[0].z) }; + + // Copies would only work if the extents match. (ie. no stretching) + bool stretch = srcCopyExtent != dstCopyExtent; + fastPath &= !stretch; + + if (!fastPath || needsResolve) { + // Compressed destination formats are forbidden for blits. + if (dstFormatInfo->flags.test(DxvkFormatFlag::BlockCompressed)) + return D3DERR_INVALIDCALL; + } + + auto EmitResolveCS = [&](const Rc& resolveDst, bool intermediate) { + VkImageResolve region; + region.srcSubresource = blitInfo.srcSubresource; + region.srcOffset = blitInfo.srcOffsets[0]; + region.dstSubresource = intermediate ? blitInfo.srcSubresource : blitInfo.dstSubresource; + region.dstOffset = intermediate ? blitInfo.srcOffsets[0] : blitInfo.dstOffsets[0]; + region.extent = srcCopyExtent; + + EmitCs([ + cDstImage = resolveDst, + cSrcImage = srcImage, + cRegion = region + ] (DxvkContext* ctx) { + if (cRegion.srcSubresource.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { + ctx->resolveImage( + cDstImage, cSrcImage, cRegion, + VK_FORMAT_UNDEFINED); + } + else { + ctx->resolveDepthStencilImage( + cDstImage, cSrcImage, cRegion, + VK_RESOLVE_MODE_AVERAGE_BIT_KHR, + VK_RESOLVE_MODE_SAMPLE_ZERO_BIT_KHR); + } + }); + }; + + if (fastPath) { + if (needsResolve) { + EmitResolveCS(dstImage, false); + } else { + EmitCs([ + cDstImage = dstImage, + cSrcImage = srcImage, + cDstLayers = blitInfo.dstSubresource, + cSrcLayers = blitInfo.srcSubresource, + cDstOffset = blitInfo.dstOffsets[0], + cSrcOffset = blitInfo.srcOffsets[0], + cExtent = srcCopyExtent + ] (DxvkContext* ctx) { + ctx->copyImage( + cDstImage, cDstLayers, cDstOffset, + cSrcImage, cSrcLayers, cSrcOffset, + cExtent); + }); + } + } + else { + if (needsResolve) { + auto resolveSrc = srcTextureInfo->GetResolveImage(); + + EmitResolveCS(resolveSrc, true); + srcImage = resolveSrc; + } + + EmitCs([ + cDstImage = dstImage, + cDstMap = dstTextureInfo->GetMapping().Swizzle, + cSrcImage = srcImage, + cSrcMap = srcTextureInfo->GetMapping().Swizzle, + cBlitInfo = blitInfo, + cFilter = stretch ? DecodeFilter(Filter) : VK_FILTER_NEAREST + ] (DxvkContext* ctx) { + ctx->blitImage( + cDstImage, + cDstMap, + cSrcImage, + cSrcMap, + cBlitInfo, + cFilter); + }); + } + + dstTextureInfo->SetNeedsReadback(dst->GetSubresource(), true); + + if (dstTextureInfo->IsAutomaticMip()) + MarkTextureMipsDirty(dstTextureInfo); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::ColorFill( + IDirect3DSurface9* pSurface, + const RECT* pRect, + D3DCOLOR Color) { + D3D9DeviceLock lock = LockDevice(); + + D3D9Surface* dst = static_cast(pSurface); + + if (unlikely(dst == nullptr)) + return D3DERR_INVALIDCALL; + + D3D9CommonTexture* dstTextureInfo = dst->GetCommonTexture(); + + if (unlikely(dstTextureInfo->Desc()->Pool != D3DPOOL_DEFAULT)) + return D3DERR_INVALIDCALL; + + VkExtent3D mipExtent = dstTextureInfo->GetExtentMip(dst->GetSubresource()); + + VkOffset3D offset = VkOffset3D{ 0u, 0u, 0u }; + VkExtent3D extent = mipExtent; + + bool isFullExtent = true; + if (pRect != nullptr) { + ConvertRect(*pRect, offset, extent); + + isFullExtent = offset == VkOffset3D{ 0u, 0u, 0u } + && extent == mipExtent; + } + + Rc rtView = dst->GetRenderTargetView(false); + + VkClearValue clearValue; + DecodeD3DCOLOR(Color, clearValue.color.float32); + + // Fast path for games that may use this as an + // alternative to Clear on render targets. + if (isFullExtent && rtView != nullptr) { + EmitCs([ + cImageView = rtView, + cClearValue = clearValue + ] (DxvkContext* ctx) { + ctx->clearRenderTarget( + cImageView, + VK_IMAGE_ASPECT_COLOR_BIT, + cClearValue); + }); + } else { + if (unlikely(rtView == nullptr)) { + const D3D9Format format = dstTextureInfo->Desc()->Format; + if (format != D3D9Format::NULL_FORMAT) + Logger::err(str::format("D3D9DeviceEx::ColorFill: Unsupported format ", format)); + + return D3D_OK; + } + + EmitCs([ + cImageView = rtView, + cOffset = offset, + cExtent = extent, + cClearValue = clearValue + ] (DxvkContext* ctx) { + ctx->clearImageView( + cImageView, + cOffset, cExtent, + VK_IMAGE_ASPECT_COLOR_BIT, + cClearValue); + }); + } + + dstTextureInfo->SetNeedsReadback(dst->GetSubresource(), true); + + if (dstTextureInfo->IsAutomaticMip()) + MarkTextureMipsDirty(dstTextureInfo); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::CreateOffscreenPlainSurface( + UINT Width, + UINT Height, + D3DFORMAT Format, + D3DPOOL Pool, + IDirect3DSurface9** ppSurface, + HANDLE* pSharedHandle) { + return CreateOffscreenPlainSurfaceEx( + Width, Height, + Format, Pool, + ppSurface, pSharedHandle, + 0); + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetRenderTarget( + DWORD RenderTargetIndex, + IDirect3DSurface9* pRenderTarget) { + D3D9DeviceLock lock = LockDevice(); + + if (unlikely(RenderTargetIndex >= caps::MaxSimultaneousRenderTargets + || (pRenderTarget == nullptr && RenderTargetIndex == 0))) + return D3DERR_INVALIDCALL; + + D3D9Surface* rt = static_cast(pRenderTarget); + D3D9CommonTexture* texInfo = rt != nullptr + ? rt->GetCommonTexture() + : nullptr; + + if (unlikely(rt != nullptr && !(texInfo->Desc()->Usage & D3DUSAGE_RENDERTARGET))) + return D3DERR_INVALIDCALL; + + if (RenderTargetIndex == 0) { + auto rtSize = rt->GetSurfaceExtent(); + + D3DVIEWPORT9 viewport; + viewport.X = 0; + viewport.Y = 0; + viewport.Width = rtSize.width; + viewport.Height = rtSize.height; + viewport.MinZ = 0.0f; + viewport.MaxZ = 1.0f; + + RECT scissorRect; + scissorRect.left = 0; + scissorRect.top = 0; + scissorRect.right = rtSize.width; + scissorRect.bottom = rtSize.height; + + if (m_state.viewport != viewport) { + m_flags.set(D3D9DeviceFlag::DirtyFFViewport); + m_flags.set(D3D9DeviceFlag::DirtyPointScale); + m_flags.set(D3D9DeviceFlag::DirtyViewportScissor); + m_state.viewport = viewport; + } + + if (m_state.scissorRect != scissorRect) { + m_flags.set(D3D9DeviceFlag::DirtyViewportScissor); + m_state.scissorRect = scissorRect; + } + } + + if (m_state.renderTargets[RenderTargetIndex] == rt) + return D3D_OK; + + // Do a strong flush if the first render target is changed. + FlushImplicit(RenderTargetIndex == 0 ? TRUE : FALSE); + m_flags.set(D3D9DeviceFlag::DirtyFramebuffer); + + m_state.renderTargets[RenderTargetIndex] = rt; + + UpdateBoundRTs(RenderTargetIndex); + UpdateActiveRTs(RenderTargetIndex); + + uint32_t originalAlphaSwizzleRTs = m_alphaSwizzleRTs; + + m_alphaSwizzleRTs &= ~(1 << RenderTargetIndex); + + if (rt != nullptr) { + if (texInfo->GetMapping().Swizzle.a == VK_COMPONENT_SWIZZLE_ONE) + m_alphaSwizzleRTs |= 1 << RenderTargetIndex; + + if (texInfo->IsAutomaticMip()) + texInfo->SetNeedsMipGen(true); + } + + if (originalAlphaSwizzleRTs != m_alphaSwizzleRTs) + m_flags.set(D3D9DeviceFlag::DirtyBlendState); + + if (RenderTargetIndex == 0) { + bool validSampleMask = texInfo->Desc()->MultiSample > D3DMULTISAMPLE_NONMASKABLE; + + if (validSampleMask != m_flags.test(D3D9DeviceFlag::ValidSampleMask)) { + m_flags.clr(D3D9DeviceFlag::ValidSampleMask); + if (validSampleMask) + m_flags.set(D3D9DeviceFlag::ValidSampleMask); + + m_flags.set(D3D9DeviceFlag::DirtyMultiSampleState); + } + } + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetRenderTarget( + DWORD RenderTargetIndex, + IDirect3DSurface9** ppRenderTarget) { + D3D9DeviceLock lock = LockDevice(); + + InitReturnPtr(ppRenderTarget); + + if (unlikely(ppRenderTarget == nullptr || RenderTargetIndex > caps::MaxSimultaneousRenderTargets)) + return D3DERR_INVALIDCALL; + + if (m_state.renderTargets[RenderTargetIndex] == nullptr) + return D3DERR_NOTFOUND; + + *ppRenderTarget = m_state.renderTargets[RenderTargetIndex].ref(); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetDepthStencilSurface(IDirect3DSurface9* pNewZStencil) { + D3D9DeviceLock lock = LockDevice(); + + D3D9Surface* ds = static_cast(pNewZStencil); + + if (unlikely(ds && !(ds->GetCommonTexture()->Desc()->Usage & D3DUSAGE_DEPTHSTENCIL))) + return D3DERR_INVALIDCALL; + + if (m_state.depthStencil == ds) + return D3D_OK; + + FlushImplicit(FALSE); + m_flags.set(D3D9DeviceFlag::DirtyFramebuffer); + + if (ds != nullptr) { + float rValue = GetDepthBufferRValue(ds->GetCommonTexture()->GetFormatMapping().FormatColor); + if (m_depthBiasScale != rValue) { + m_depthBiasScale = rValue; + m_flags.set(D3D9DeviceFlag::DirtyDepthBias); + } + } + + m_state.depthStencil = ds; + + UpdateActiveHazardsDS(UINT32_MAX); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetDepthStencilSurface(IDirect3DSurface9** ppZStencilSurface) { + D3D9DeviceLock lock = LockDevice(); + + InitReturnPtr(ppZStencilSurface); + + if (unlikely(ppZStencilSurface == nullptr)) + return D3DERR_INVALIDCALL; + + if (m_state.depthStencil == nullptr) + return D3DERR_NOTFOUND; + + *ppZStencilSurface = m_state.depthStencil.ref(); + + return D3D_OK; + } + + // The Begin/EndScene functions actually do nothing. + // Some games don't even call them. + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::BeginScene() { + D3D9DeviceLock lock = LockDevice(); + + if (unlikely(m_flags.test(D3D9DeviceFlag::InScene))) + return D3DERR_INVALIDCALL; + + m_flags.set(D3D9DeviceFlag::InScene); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::EndScene() { + D3D9DeviceLock lock = LockDevice(); + + if (unlikely(!m_flags.test(D3D9DeviceFlag::InScene))) + return D3DERR_INVALIDCALL; + + FlushImplicit(true); + + m_flags.clr(D3D9DeviceFlag::InScene); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::Clear( + DWORD Count, + const D3DRECT* pRects, + DWORD Flags, + D3DCOLOR Color, + float Z, + DWORD Stencil) { + if (unlikely(!Count && pRects)) + return D3D_OK; + + D3D9DeviceLock lock = LockDevice(); + + const auto& vp = m_state.viewport; + const auto& sc = m_state.scissorRect; + + bool srgb = m_state.renderStates[D3DRS_SRGBWRITEENABLE]; + bool scissor = m_state.renderStates[D3DRS_SCISSORTESTENABLE]; + + VkOffset3D offset = { int32_t(vp.X), int32_t(vp.Y), 0 }; + VkExtent3D extent = { vp.Width, vp.Height, 1u }; + + if (scissor) { + offset.x = std::max (offset.x, sc.left); + offset.y = std::max (offset.y, sc.top); + + extent.width = std::min(extent.width, sc.right - offset.x); + extent.height = std::min(extent.height, sc.bottom - offset.y); + } + + // This becomes pretty unreadable in one singular if statement... + if (Count) { + // If pRects is null, or our first rect encompasses the viewport: + if (!pRects) + Count = 0; + else if (pRects[0].x1 <= offset.x && pRects[0].y1 <= offset.y + && pRects[0].x2 >= offset.x + int32_t(extent.width) && pRects[0].y2 >= offset.y + int32_t(extent.height)) + Count = 0; + } + + // Here, Count of 0 will denote whether or not to care about user rects. + VkClearValue clearValueDepth; + clearValueDepth.depthStencil.depth = Z; + clearValueDepth.depthStencil.stencil = Stencil; + + VkClearValue clearValueColor; + DecodeD3DCOLOR(Color, clearValueColor.color.float32); + + VkImageAspectFlags depthAspectMask = 0; + if (m_state.depthStencil != nullptr) { + if (Flags & D3DCLEAR_ZBUFFER) + depthAspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT; + + if (Flags & D3DCLEAR_STENCIL) + depthAspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; + + depthAspectMask &= imageFormatInfo(m_state.depthStencil->GetCommonTexture()->GetFormatMapping().FormatColor)->aspectMask; + } + + auto ClearImageView = [this]( + uint32_t alignment, + VkOffset3D offset, + VkExtent3D extent, + const Rc& imageView, + VkImageAspectFlags aspectMask, + VkClearValue clearValue) { + + VkExtent3D imageExtent = imageView->mipLevelExtent(0); + extent.width = std::min(imageExtent.width, extent.width); + extent.height = std::min(imageExtent.height, extent.height); + + if (unlikely(uint32_t(offset.x) >= imageExtent.width || uint32_t(offset.y) >= imageExtent.height)) + return; + + const bool fullClear = align(extent.width, alignment) == align(imageExtent.width, alignment) + && align(extent.height, alignment) == align(imageExtent.height, alignment) + && offset.x == 0 + && offset.y == 0; + + if (fullClear) { + EmitCs([ + cClearValue = clearValue, + cAspectMask = aspectMask, + cImageView = imageView + ] (DxvkContext* ctx) { + ctx->clearRenderTarget( + cImageView, + cAspectMask, + cClearValue); + }); + } + else { + EmitCs([ + cClearValue = clearValue, + cAspectMask = aspectMask, + cImageView = imageView, + cOffset = offset, + cExtent = extent + ] (DxvkContext* ctx) { + ctx->clearImageView( + cImageView, + cOffset, cExtent, + cAspectMask, + cClearValue); + }); + } + }; + + auto ClearViewRect = [&]( + uint32_t alignment, + VkOffset3D offset, + VkExtent3D extent) { + // Clear depth if we need to. + if (depthAspectMask != 0) + ClearImageView(alignment, offset, extent, m_state.depthStencil->GetDepthStencilView(), depthAspectMask, clearValueDepth); + + // Clear render targets if we need to. + if (Flags & D3DCLEAR_TARGET) { + for (uint32_t rt : bit::BitMask(m_boundRTs)) { + const auto& rts = m_state.renderTargets[rt]; + const auto& rtv = rts->GetRenderTargetView(srgb); + + if (likely(rtv != nullptr)) { + ClearImageView(alignment, offset, extent, rtv, VK_IMAGE_ASPECT_COLOR_BIT, clearValueColor); + + D3D9CommonTexture* dstTexture = rts->GetCommonTexture(); + + if (dstTexture->IsAutomaticMip()) + MarkTextureMipsDirty(dstTexture); + } + } + } + }; + + // A Hat in Time and other UE3 games only gets partial clears here + // because of an oversized rt height due to their weird alignment... + // This works around that. + uint32_t alignment = m_d3d9Options.lenientClear ? 8 : 1; + + if (!Count) { + // Clear our viewport & scissor minified region in this rendertarget. + ClearViewRect(alignment, offset, extent); + } + else { + // Clear the application provided rects. + for (uint32_t i = 0; i < Count; i++) { + VkOffset3D rectOffset = { + std::max(pRects[i].x1, offset.x), + std::max(pRects[i].y1, offset.y), + 0 + }; + + VkExtent3D rectExtent = { + std::min(pRects[i].x2, offset.x + extent.width) - rectOffset.x, + std::min(pRects[i].y2, offset.y + extent.height) - rectOffset.y, + 1u + }; + + ClearViewRect(alignment, rectOffset, rectExtent); + } + } + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetTransform(D3DTRANSFORMSTATETYPE State, const D3DMATRIX* pMatrix) { + return SetStateTransform(GetTransformIndex(State), pMatrix); + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetTransform(D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) { + D3D9DeviceLock lock = LockDevice(); + + if (unlikely(pMatrix == nullptr)) + return D3DERR_INVALIDCALL; + + *pMatrix = bit::cast(m_state.transforms[GetTransformIndex(State)]); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::MultiplyTransform(D3DTRANSFORMSTATETYPE TransformState, const D3DMATRIX* pMatrix) { + D3D9DeviceLock lock = LockDevice(); + + if (unlikely(ShouldRecord())) + return m_recorder->MultiplyStateTransform(TransformState, pMatrix); + + uint32_t idx = GetTransformIndex(TransformState); + + m_state.transforms[idx] = m_state.transforms[idx] * ConvertMatrix(pMatrix); + + m_flags.set(D3D9DeviceFlag::DirtyFFVertexData); + + if (idx == GetTransformIndex(D3DTS_VIEW) || idx >= GetTransformIndex(D3DTS_WORLD)) + m_flags.set(D3D9DeviceFlag::DirtyFFVertexBlend); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetViewport(const D3DVIEWPORT9* pViewport) { + D3D9DeviceLock lock = LockDevice(); + + if (unlikely(ShouldRecord())) + return m_recorder->SetViewport(pViewport); + + if (m_state.viewport == *pViewport) + return D3D_OK; + + m_state.viewport = *pViewport; + + m_flags.set(D3D9DeviceFlag::DirtyViewportScissor); + m_flags.set(D3D9DeviceFlag::DirtyFFViewport); + m_flags.set(D3D9DeviceFlag::DirtyPointScale); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetViewport(D3DVIEWPORT9* pViewport) { + D3D9DeviceLock lock = LockDevice(); + + if (pViewport == nullptr) + return D3DERR_INVALIDCALL; + + *pViewport = m_state.viewport; + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetMaterial(const D3DMATERIAL9* pMaterial) { + D3D9DeviceLock lock = LockDevice(); + + if (unlikely(pMaterial == nullptr)) + return D3DERR_INVALIDCALL; + + if (unlikely(ShouldRecord())) + return m_recorder->SetMaterial(pMaterial); + + m_state.material = *pMaterial; + m_flags.set(D3D9DeviceFlag::DirtyFFVertexData); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetMaterial(D3DMATERIAL9* pMaterial) { + D3D9DeviceLock lock = LockDevice(); + + if (unlikely(pMaterial == nullptr)) + return D3DERR_INVALIDCALL; + + *pMaterial = m_state.material; + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetLight(DWORD Index, const D3DLIGHT9* pLight) { + D3D9DeviceLock lock = LockDevice(); + + if (unlikely(pLight == nullptr)) + return D3DERR_INVALIDCALL; + + if (unlikely(ShouldRecord())) { + Logger::warn("D3D9DeviceEx::SetLight: State block not implemented."); + return D3D_OK; + } + + if (Index >= m_state.lights.size()) + m_state.lights.resize(Index + 1); + + m_state.lights[Index] = *pLight; + + if (m_state.IsLightEnabled(Index)) + m_flags.set(D3D9DeviceFlag::DirtyFFVertexData); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetLight(DWORD Index, D3DLIGHT9* pLight) { + D3D9DeviceLock lock = LockDevice(); + + if (unlikely(pLight == nullptr)) + return D3DERR_INVALIDCALL; + + if (unlikely(Index >= m_state.lights.size() || !m_state.lights[Index])) + return D3DERR_INVALIDCALL; + + *pLight = m_state.lights[Index].value(); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::LightEnable(DWORD Index, BOOL Enable) { + D3D9DeviceLock lock = LockDevice(); + + if (unlikely(Index >= m_state.lights.size())) + m_state.lights.resize(Index + 1); + + if (unlikely(!m_state.lights[Index])) + m_state.lights[Index] = DefaultLight; + + if (m_state.IsLightEnabled(Index) == !!Enable) + return D3D_OK; + + uint32_t searchIndex = UINT32_MAX; + uint32_t setIndex = Index; + + if (!Enable) + std::swap(searchIndex, setIndex); + + for (auto& idx : m_state.enabledLightIndices) { + if (idx == searchIndex) { + idx = setIndex; + m_flags.set(D3D9DeviceFlag::DirtyFFVertexData); + m_flags.set(D3D9DeviceFlag::DirtyFFVertexShader); + break; + } + } + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetLightEnable(DWORD Index, BOOL* pEnable) { + D3D9DeviceLock lock = LockDevice(); + + if (unlikely(pEnable == nullptr)) + return D3DERR_INVALIDCALL; + + if (unlikely(Index >= m_state.lights.size() || !m_state.lights[Index])) + return D3DERR_INVALIDCALL; + + *pEnable = m_state.IsLightEnabled(Index) ? 128 : 0; // Weird quirk but OK. + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetClipPlane(DWORD Index, const float* pPlane) { + D3D9DeviceLock lock = LockDevice(); + + if (unlikely(Index >= caps::MaxClipPlanes || !pPlane)) + return D3DERR_INVALIDCALL; + + if (unlikely(ShouldRecord())) + return m_recorder->SetClipPlane(Index, pPlane); + + bool dirty = false; + + for (uint32_t i = 0; i < 4; i++) { + dirty |= m_state.clipPlanes[Index].coeff[i] != pPlane[i]; + m_state.clipPlanes[Index].coeff[i] = pPlane[i]; + } + + bool enabled = m_state.renderStates[D3DRS_CLIPPLANEENABLE] & (1u << Index); + dirty &= enabled; + + if (dirty) + m_flags.set(D3D9DeviceFlag::DirtyClipPlanes); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetClipPlane(DWORD Index, float* pPlane) { + D3D9DeviceLock lock = LockDevice(); + + if (unlikely(Index >= caps::MaxClipPlanes || !pPlane)) + return D3DERR_INVALIDCALL; + + for (uint32_t i = 0; i < 4; i++) + pPlane[i] = m_state.clipPlanes[Index].coeff[i]; + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetRenderState(D3DRENDERSTATETYPE State, DWORD Value) { + D3D9DeviceLock lock = LockDevice(); + + // D3D9 only allows reading for values 0 and 7-255 so we don't need to do anything but return OK + if (unlikely(State > 255 || (State < D3DRS_ZENABLE && State != 0))) { + return D3D_OK; + } + + if (unlikely(ShouldRecord())) + return m_recorder->SetRenderState(State, Value); + + auto& states = m_state.renderStates; + DWORD old = states[State]; + + bool changed = old != Value; + + if (likely(changed)) { + const bool oldClipPlaneEnabled = IsClipPlaneEnabled(); + + const bool oldDepthBiasEnabled = IsDepthBiasEnabled(); + + const bool oldATOC = IsAlphaToCoverageEnabled(); + const bool oldNVDB = states[D3DRS_ADAPTIVETESS_X] == uint32_t(D3D9Format::NVDB); + const bool oldAlphaTest = IsAlphaTestEnabled(); + + states[State] = Value; + + // AMD's driver hack for ATOC and RESZ + if (unlikely(State == D3DRS_POINTSIZE)) { + // ATOC + constexpr uint32_t AlphaToCoverageEnable = uint32_t(D3D9Format::A2M1); + constexpr uint32_t AlphaToCoverageDisable = uint32_t(D3D9Format::A2M0); + + if (Value == AlphaToCoverageEnable + || Value == AlphaToCoverageDisable) { + m_amdATOC = Value == AlphaToCoverageEnable; + + bool newATOC = IsAlphaToCoverageEnabled(); + bool newAlphaTest = IsAlphaTestEnabled(); + + if (oldATOC != newATOC) + m_flags.set(D3D9DeviceFlag::DirtyMultiSampleState); + + if (oldAlphaTest != newAlphaTest) + m_flags.set(D3D9DeviceFlag::DirtyAlphaTestState); + + return D3D_OK; + } + + // RESZ + constexpr uint32_t RESZ = 0x7fa05000; + if (Value == RESZ) { + ResolveZ(); + return D3D_OK; + } + } + + // NV's driver hack for ATOC. + if (unlikely(State == D3DRS_ADAPTIVETESS_Y)) { + constexpr uint32_t AlphaToCoverageEnable = uint32_t(D3D9Format::ATOC); + constexpr uint32_t AlphaToCoverageDisable = 0; + + if (Value == AlphaToCoverageEnable + || Value == AlphaToCoverageDisable) { + m_nvATOC = Value == AlphaToCoverageEnable; + + bool newATOC = IsAlphaToCoverageEnabled(); + bool newAlphaTest = IsAlphaTestEnabled(); + + if (oldATOC != newATOC) + m_flags.set(D3D9DeviceFlag::DirtyMultiSampleState); + + if (oldAlphaTest != newAlphaTest) + m_flags.set(D3D9DeviceFlag::DirtyAlphaTestState); + + return D3D_OK; + } + + if (unlikely(Value == uint32_t(D3D9Format::COPM))) { + // UE3 calls this MinimalNVIDIADriverShaderOptimization + Logger::info("D3D9DeviceEx::SetRenderState: MinimalNVIDIADriverShaderOptimization is unsupported"); + return D3D_OK; + } + } + + switch (State) { + case D3DRS_SEPARATEALPHABLENDENABLE: + case D3DRS_ALPHABLENDENABLE: + case D3DRS_BLENDOP: + case D3DRS_BLENDOPALPHA: + case D3DRS_DESTBLEND: + case D3DRS_DESTBLENDALPHA: + case D3DRS_SRCBLEND: + case D3DRS_SRCBLENDALPHA: + m_flags.set(D3D9DeviceFlag::DirtyBlendState); + break; + + case D3DRS_COLORWRITEENABLE: + if (likely(!old != !Value)) { + m_flags.set(D3D9DeviceFlag::DirtyFramebuffer); + UpdateActiveRTs(0); + } + m_flags.set(D3D9DeviceFlag::DirtyBlendState); + break; + case D3DRS_COLORWRITEENABLE1: + if (likely(!old != !Value && m_state.renderTargets[1] != nullptr)) { + m_flags.set(D3D9DeviceFlag::DirtyFramebuffer); + UpdateActiveRTs(1); + } + m_flags.set(D3D9DeviceFlag::DirtyBlendState); + break; + case D3DRS_COLORWRITEENABLE2: + if (likely(!old != !Value && m_state.renderTargets[2] != nullptr)) { + m_flags.set(D3D9DeviceFlag::DirtyFramebuffer); + UpdateActiveRTs(2); + } + m_flags.set(D3D9DeviceFlag::DirtyBlendState); + break; + case D3DRS_COLORWRITEENABLE3: + if (likely(!old != !Value && m_state.renderTargets[3] != nullptr)) { + m_flags.set(D3D9DeviceFlag::DirtyFramebuffer); + UpdateActiveRTs(3); + } + m_flags.set(D3D9DeviceFlag::DirtyBlendState); + break; + + case D3DRS_ALPHATESTENABLE: { + bool newATOC = IsAlphaToCoverageEnabled(); + bool newAlphaTest = IsAlphaTestEnabled(); + + if (oldATOC != newATOC) + m_flags.set(D3D9DeviceFlag::DirtyMultiSampleState); + + if (oldAlphaTest != newAlphaTest) + m_flags.set(D3D9DeviceFlag::DirtyAlphaTestState); + + break; + } + + case D3DRS_ALPHAFUNC: + m_flags.set(D3D9DeviceFlag::DirtyAlphaTestState); + break; + + case D3DRS_BLENDFACTOR: + BindBlendFactor(); + break; + + case D3DRS_MULTISAMPLEMASK: + if (m_flags.test(D3D9DeviceFlag::ValidSampleMask)) + m_flags.set(D3D9DeviceFlag::DirtyMultiSampleState); + break; + + case D3DRS_STENCILENABLE: + case D3DRS_ZWRITEENABLE: + case D3DRS_ZENABLE: + if (likely(m_state.depthStencil != nullptr)) + m_flags.set(D3D9DeviceFlag::DirtyFramebuffer); + + m_flags.set(D3D9DeviceFlag::DirtyDepthStencilState); + break; + + case D3DRS_ZFUNC: + case D3DRS_TWOSIDEDSTENCILMODE: + case D3DRS_STENCILFAIL: + case D3DRS_STENCILZFAIL: + case D3DRS_STENCILPASS: + case D3DRS_STENCILFUNC: + case D3DRS_CCW_STENCILFAIL: + case D3DRS_CCW_STENCILZFAIL: + case D3DRS_CCW_STENCILPASS: + case D3DRS_CCW_STENCILFUNC: + case D3DRS_STENCILMASK: + case D3DRS_STENCILWRITEMASK: + m_flags.set(D3D9DeviceFlag::DirtyDepthStencilState); + break; + + case D3DRS_STENCILREF: + BindDepthStencilRefrence(); + break; + + case D3DRS_SCISSORTESTENABLE: + m_flags.set(D3D9DeviceFlag::DirtyViewportScissor); + break; + + case D3DRS_SRGBWRITEENABLE: + m_flags.set(D3D9DeviceFlag::DirtyFramebuffer); + break; + + case D3DRS_DEPTHBIAS: + case D3DRS_SLOPESCALEDEPTHBIAS: { + const bool depthBiasEnabled = IsDepthBiasEnabled(); + + if (depthBiasEnabled != oldDepthBiasEnabled) + m_flags.set(D3D9DeviceFlag::DirtyRasterizerState); + + if (depthBiasEnabled) + m_flags.set(D3D9DeviceFlag::DirtyDepthBias); + + break; + } + case D3DRS_CULLMODE: + case D3DRS_FILLMODE: + m_flags.set(D3D9DeviceFlag::DirtyRasterizerState); + break; + + case D3DRS_CLIPPLANEENABLE: { + const bool clipPlaneEnabled = IsClipPlaneEnabled(); + + if (clipPlaneEnabled != oldClipPlaneEnabled) + m_flags.set(D3D9DeviceFlag::DirtyFFVertexShader); + + m_flags.set(D3D9DeviceFlag::DirtyClipPlanes); + break; + } + + case D3DRS_ALPHAREF: + UpdatePushConstant(); + break; + + case D3DRS_TEXTUREFACTOR: + m_flags.set(D3D9DeviceFlag::DirtyFFPixelData); + break; + + case D3DRS_DIFFUSEMATERIALSOURCE: + case D3DRS_AMBIENTMATERIALSOURCE: + case D3DRS_SPECULARMATERIALSOURCE: + case D3DRS_EMISSIVEMATERIALSOURCE: + case D3DRS_COLORVERTEX: + case D3DRS_LIGHTING: + case D3DRS_NORMALIZENORMALS: + case D3DRS_LOCALVIEWER: + m_flags.set(D3D9DeviceFlag::DirtyFFVertexShader); + break; + + case D3DRS_AMBIENT: + m_flags.set(D3D9DeviceFlag::DirtyFFVertexData); + break; + + case D3DRS_SPECULARENABLE: + m_flags.set(D3D9DeviceFlag::DirtyFFPixelShader); + break; + + case D3DRS_FOGENABLE: + case D3DRS_FOGVERTEXMODE: + case D3DRS_FOGTABLEMODE: + m_flags.set(D3D9DeviceFlag::DirtyFogState); + break; + + case D3DRS_RANGEFOGENABLE: + m_flags.set(D3D9DeviceFlag::DirtyFFVertexShader); + break; + + case D3DRS_FOGCOLOR: + m_flags.set(D3D9DeviceFlag::DirtyFogColor); + break; + + case D3DRS_FOGSTART: + m_flags.set(D3D9DeviceFlag::DirtyFogScale); + break; + + case D3DRS_FOGEND: + m_flags.set(D3D9DeviceFlag::DirtyFogScale); + m_flags.set(D3D9DeviceFlag::DirtyFogEnd); + break; + + case D3DRS_FOGDENSITY: + m_flags.set(D3D9DeviceFlag::DirtyFogDensity); + break; + + case D3DRS_POINTSIZE: + UpdatePushConstant(); + break; + + case D3DRS_POINTSIZE_MIN: + UpdatePushConstant(); + break; + + case D3DRS_POINTSIZE_MAX: + UpdatePushConstant(); + break; + + case D3DRS_POINTSCALE_A: + case D3DRS_POINTSCALE_B: + case D3DRS_POINTSCALE_C: + m_flags.set(D3D9DeviceFlag::DirtyPointScale); + break; + + case D3DRS_POINTSCALEENABLE: + case D3DRS_POINTSPRITEENABLE: + // Nothing to do here! + // This is handled in UpdatePointMode. + break; + + case D3DRS_SHADEMODE: + if (m_state.pixelShader != nullptr) { + BindShader( + GetCommonShader(m_state.pixelShader), + GetPixelShaderPermutation()); + } + + m_flags.set(D3D9DeviceFlag::DirtyFFPixelShader); + break; + + case D3DRS_TWEENFACTOR: + m_flags.set(D3D9DeviceFlag::DirtyFFVertexData); + break; + + case D3DRS_VERTEXBLEND: + m_flags.set(D3D9DeviceFlag::DirtyFFVertexShader); + break; + + case D3DRS_INDEXEDVERTEXBLENDENABLE: + if (CanSWVP() && Value) + m_flags.set(D3D9DeviceFlag::DirtyFFVertexBlend); + + m_flags.set(D3D9DeviceFlag::DirtyFFVertexShader); + break; + + case D3DRS_ADAPTIVETESS_X: + case D3DRS_ADAPTIVETESS_Z: + case D3DRS_ADAPTIVETESS_W: + if (states[D3DRS_ADAPTIVETESS_X] == uint32_t(D3D9Format::NVDB) || oldNVDB) { + m_flags.set(D3D9DeviceFlag::DirtyDepthBounds); + break; + } + [[fallthrough]]; + + default: + static bool s_errorShown[256]; + + if (!std::exchange(s_errorShown[State], true)) + Logger::warn(str::format("D3D9DeviceEx::SetRenderState: Unhandled render state ", State)); + break; + } + } + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetRenderState(D3DRENDERSTATETYPE State, DWORD* pValue) { + D3D9DeviceLock lock = LockDevice(); + + if (unlikely(pValue == nullptr)) + return D3DERR_INVALIDCALL; + + if (unlikely(State > 255 || (State < D3DRS_ZENABLE && State != 0))) { + return D3DERR_INVALIDCALL; + } + + if (State < D3DRS_ZENABLE || State > D3DRS_BLENDOPALPHA) + *pValue = 0; + else + *pValue = m_state.renderStates[State]; + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::CreateStateBlock( + D3DSTATEBLOCKTYPE Type, + IDirect3DStateBlock9** ppSB) { + D3D9DeviceLock lock = LockDevice(); + + InitReturnPtr(ppSB); + + if (unlikely(ppSB == nullptr)) + return D3DERR_INVALIDCALL; + + try { + const Com sb = new D3D9StateBlock(this, ConvertStateBlockType(Type)); + *ppSB = sb.ref(); + return D3D_OK; + } + catch (const DxvkError & e) { + Logger::err(e.message()); + return D3DERR_INVALIDCALL; + } + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::BeginStateBlock() { + D3D9DeviceLock lock = LockDevice(); + + if (unlikely(m_recorder != nullptr)) + return D3DERR_INVALIDCALL; + + m_recorder = new D3D9StateBlock(this, D3D9StateBlockType::None); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::EndStateBlock(IDirect3DStateBlock9** ppSB) { + D3D9DeviceLock lock = LockDevice(); + + InitReturnPtr(ppSB); + + if (unlikely(ppSB == nullptr || m_recorder == nullptr)) + return D3DERR_INVALIDCALL; + + *ppSB = m_recorder.ref(); + m_recorder = nullptr; + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetClipStatus(const D3DCLIPSTATUS9* pClipStatus) { + Logger::warn("D3D9DeviceEx::SetClipStatus: Stub"); + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetClipStatus(D3DCLIPSTATUS9* pClipStatus) { + Logger::warn("D3D9DeviceEx::GetClipStatus: Stub"); + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetTexture(DWORD Stage, IDirect3DBaseTexture9** ppTexture) { + D3D9DeviceLock lock = LockDevice(); + + if (ppTexture == nullptr) + return D3DERR_INVALIDCALL; + + *ppTexture = nullptr; + + if (unlikely(InvalidSampler(Stage))) + return D3D_OK; + + DWORD stateSampler = RemapSamplerState(Stage); + + *ppTexture = ref(m_state.textures[stateSampler]); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetTexture(DWORD Stage, IDirect3DBaseTexture9* pTexture) { + if (unlikely(InvalidSampler(Stage))) + return D3D_OK; + + DWORD stateSampler = RemapSamplerState(Stage); + + return SetStateTexture(stateSampler, pTexture); + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetTextureStageState( + DWORD Stage, + D3DTEXTURESTAGESTATETYPE Type, + DWORD* pValue) { + auto dxvkType = RemapTextureStageStateType(Type); + + if (unlikely(pValue == nullptr)) + return D3DERR_INVALIDCALL; + + *pValue = 0; + + if (unlikely(Stage >= caps::TextureStageCount)) + return D3DERR_INVALIDCALL; + + if (unlikely(dxvkType >= TextureStageStateCount)) + return D3DERR_INVALIDCALL; + + *pValue = m_state.textureStages[Stage][dxvkType]; + + return D3D_OK; + } + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetTextureStageState( + DWORD Stage, + D3DTEXTURESTAGESTATETYPE Type, + DWORD Value) { + return SetStateTextureStageState(Stage, RemapTextureStageStateType(Type), Value); + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetSamplerState( + DWORD Sampler, + D3DSAMPLERSTATETYPE Type, + DWORD* pValue) { + D3D9DeviceLock lock = LockDevice(); + + if (unlikely(pValue == nullptr)) + return D3DERR_INVALIDCALL; + + *pValue = 0; + + if (unlikely(InvalidSampler(Sampler))) + return D3D_OK; + + Sampler = RemapSamplerState(Sampler); + + *pValue = m_state.samplerStates[Sampler][Type]; + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetSamplerState( + DWORD Sampler, + D3DSAMPLERSTATETYPE Type, + DWORD Value) { + if (unlikely(InvalidSampler(Sampler))) + return D3D_OK; + + uint32_t stateSampler = RemapSamplerState(Sampler); + + return SetStateSamplerState(stateSampler, Type, Value); + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::ValidateDevice(DWORD* pNumPasses) { + if (pNumPasses != nullptr) + *pNumPasses = 1; + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetPaletteEntries(UINT PaletteNumber, const PALETTEENTRY* pEntries) { + // This succeeds even though we don't advertise support. + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetPaletteEntries(UINT PaletteNumber, PALETTEENTRY* pEntries) { + // Don't advertise support for this... + return D3DERR_INVALIDCALL; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetCurrentTexturePalette(UINT PaletteNumber) { + // This succeeds even though we don't advertise support. + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetCurrentTexturePalette(UINT *PaletteNumber) { + // Don't advertise support for this... + return D3DERR_INVALIDCALL; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetScissorRect(const RECT* pRect) { + D3D9DeviceLock lock = LockDevice(); + + if (unlikely(pRect == nullptr)) + return D3DERR_INVALIDCALL; + + if (unlikely(ShouldRecord())) + return m_recorder->SetScissorRect(pRect); + + if (m_state.scissorRect == *pRect) + return D3D_OK; + + m_state.scissorRect = *pRect; + + m_flags.set(D3D9DeviceFlag::DirtyViewportScissor); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetScissorRect(RECT* pRect) { + D3D9DeviceLock lock = LockDevice(); + + if (unlikely(pRect == nullptr)) + return D3DERR_INVALIDCALL; + + *pRect = m_state.scissorRect; + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetSoftwareVertexProcessing(BOOL bSoftware) { + auto lock = LockDevice(); + + if (bSoftware && !CanSWVP()) + return D3DERR_INVALIDCALL; + + m_isSWVP = bSoftware; + + return D3D_OK; + } + + + BOOL STDMETHODCALLTYPE D3D9DeviceEx::GetSoftwareVertexProcessing() { + auto lock = LockDevice(); + + return m_isSWVP; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetNPatchMode(float nSegments) { + return D3D_OK; + } + + + float STDMETHODCALLTYPE D3D9DeviceEx::GetNPatchMode() { + return 0.0f; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::DrawPrimitive( + D3DPRIMITIVETYPE PrimitiveType, + UINT StartVertex, + UINT PrimitiveCount) { + D3D9DeviceLock lock = LockDevice(); + + if (unlikely(m_state.vertexDecl == nullptr)) + return D3DERR_INVALIDCALL; + + if (unlikely(!PrimitiveCount)) + return S_OK; + + PrepareDraw(PrimitiveType); + + EmitCs([this, + cPrimType = PrimitiveType, + cPrimCount = PrimitiveCount, + cStartVertex = StartVertex, + cInstanceCount = GetInstanceCount() + ](DxvkContext* ctx) { + auto drawInfo = GenerateDrawInfo(cPrimType, cPrimCount, cInstanceCount); + + ApplyPrimitiveType(ctx, cPrimType); + + ctx->draw( + drawInfo.vertexCount, drawInfo.instanceCount, + cStartVertex, 0); + }); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::DrawIndexedPrimitive( + D3DPRIMITIVETYPE PrimitiveType, + INT BaseVertexIndex, + UINT MinVertexIndex, + UINT NumVertices, + UINT StartIndex, + UINT PrimitiveCount) { + D3D9DeviceLock lock = LockDevice(); + + if (unlikely(m_state.vertexDecl == nullptr)) + return D3DERR_INVALIDCALL; + + if (unlikely(!PrimitiveCount)) + return S_OK; + + PrepareDraw(PrimitiveType); + + EmitCs([this, + cPrimType = PrimitiveType, + cPrimCount = PrimitiveCount, + cStartIndex = StartIndex, + cBaseVertexIndex = BaseVertexIndex, + cInstanceCount = GetInstanceCount() + ](DxvkContext* ctx) { + auto drawInfo = GenerateDrawInfo(cPrimType, cPrimCount, cInstanceCount); + + ApplyPrimitiveType(ctx, cPrimType); + + ctx->drawIndexed( + drawInfo.vertexCount, drawInfo.instanceCount, + cStartIndex, + cBaseVertexIndex, 0); + }); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::DrawPrimitiveUP( + D3DPRIMITIVETYPE PrimitiveType, + UINT PrimitiveCount, + const void* pVertexStreamZeroData, + UINT VertexStreamZeroStride) { + D3D9DeviceLock lock = LockDevice(); + + if (unlikely(m_state.vertexDecl == nullptr)) + return D3DERR_INVALIDCALL; + + if (unlikely(!PrimitiveCount)) + return S_OK; + + PrepareDraw(PrimitiveType); + + auto drawInfo = GenerateDrawInfo(PrimitiveType, PrimitiveCount, 0); + + const uint32_t dataSize = GetUPDataSize(drawInfo.vertexCount, VertexStreamZeroStride); + const uint32_t bufferSize = GetUPBufferSize(drawInfo.vertexCount, VertexStreamZeroStride); + + auto upSlice = AllocTempBuffer(bufferSize); + FillUPVertexBuffer(upSlice.mapPtr, pVertexStreamZeroData, dataSize, bufferSize); + + EmitCs([this, + cBufferSlice = std::move(upSlice.slice), + cPrimType = PrimitiveType, + cPrimCount = PrimitiveCount, + cInstanceCount = GetInstanceCount(), + cStride = VertexStreamZeroStride + ](DxvkContext* ctx) { + auto drawInfo = GenerateDrawInfo(cPrimType, cPrimCount, cInstanceCount); + + ApplyPrimitiveType(ctx, cPrimType); + + ctx->bindVertexBuffer(0, cBufferSlice, cStride); + ctx->draw( + drawInfo.vertexCount, drawInfo.instanceCount, + 0, 0); + ctx->bindVertexBuffer(0, DxvkBufferSlice(), 0); + }); + + m_state.vertexBuffers[0].vertexBuffer = nullptr; + m_state.vertexBuffers[0].offset = 0; + m_state.vertexBuffers[0].stride = 0; + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::DrawIndexedPrimitiveUP( + D3DPRIMITIVETYPE PrimitiveType, + UINT MinVertexIndex, + UINT NumVertices, + UINT PrimitiveCount, + const void* pIndexData, + D3DFORMAT IndexDataFormat, + const void* pVertexStreamZeroData, + UINT VertexStreamZeroStride) { + D3D9DeviceLock lock = LockDevice(); + + if (unlikely(m_state.vertexDecl == nullptr)) + return D3DERR_INVALIDCALL; + + if (unlikely(!PrimitiveCount)) + return S_OK; + + PrepareDraw(PrimitiveType); + + auto drawInfo = GenerateDrawInfo(PrimitiveType, PrimitiveCount, 0); + + const uint32_t vertexDataSize = GetUPDataSize(MinVertexIndex + NumVertices, VertexStreamZeroStride); + const uint32_t vertexBufferSize = GetUPBufferSize(MinVertexIndex + NumVertices, VertexStreamZeroStride); + + const uint32_t indexSize = IndexDataFormat == D3DFMT_INDEX16 ? 2 : 4; + const uint32_t indicesSize = drawInfo.vertexCount * indexSize; + + const uint32_t upSize = vertexBufferSize + indicesSize; + + auto upSlice = AllocTempBuffer(upSize); + uint8_t* data = reinterpret_cast(upSlice.mapPtr); + FillUPVertexBuffer(data, pVertexStreamZeroData, vertexDataSize, vertexBufferSize); + std::memcpy(data + vertexBufferSize, pIndexData, indicesSize); + + EmitCs([this, + cVertexSize = vertexBufferSize, + cBufferSlice = std::move(upSlice.slice), + cPrimType = PrimitiveType, + cPrimCount = PrimitiveCount, + cStride = VertexStreamZeroStride, + cInstanceCount = GetInstanceCount(), + cIndexType = DecodeIndexType( + static_cast(IndexDataFormat)) + ](DxvkContext* ctx) { + auto drawInfo = GenerateDrawInfo(cPrimType, cPrimCount, cInstanceCount); + + ApplyPrimitiveType(ctx, cPrimType); + + ctx->bindVertexBuffer(0, cBufferSlice.subSlice(0, cVertexSize), cStride); + ctx->bindIndexBuffer(cBufferSlice.subSlice(cVertexSize, cBufferSlice.length() - cVertexSize), cIndexType); + ctx->drawIndexed( + drawInfo.vertexCount, drawInfo.instanceCount, + 0, + 0, 0); + ctx->bindVertexBuffer(0, DxvkBufferSlice(), 0); + ctx->bindIndexBuffer(DxvkBufferSlice(), VK_INDEX_TYPE_UINT32); + }); + + m_state.vertexBuffers[0].vertexBuffer = nullptr; + m_state.vertexBuffers[0].offset = 0; + m_state.vertexBuffers[0].stride = 0; + + m_state.indices = nullptr; + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::ProcessVertices( + UINT SrcStartIndex, + UINT DestIndex, + UINT VertexCount, + IDirect3DVertexBuffer9* pDestBuffer, + IDirect3DVertexDeclaration9* pVertexDecl, + DWORD Flags) { + D3D9DeviceLock lock = LockDevice(); + + if (unlikely(pDestBuffer == nullptr || pVertexDecl == nullptr)) + return D3DERR_INVALIDCALL; + + if (!SupportsSWVP()) { + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::err("D3D9DeviceEx::ProcessVertices: SWVP emu unsupported (vertexPipelineStoresAndAtomics)"); + + return D3D_OK; + } + + if (!VertexCount) + return D3D_OK; + + D3D9CommonBuffer* dst = static_cast(pDestBuffer)->GetCommonBuffer(); + D3D9VertexDecl* decl = static_cast (pVertexDecl); + + PrepareDraw(D3DPT_FORCE_DWORD); + + if (decl == nullptr) { + DWORD FVF = dst->Desc()->FVF; + + auto iter = m_fvfTable.find(FVF); + + if (iter == m_fvfTable.end()) { + decl = new D3D9VertexDecl(this, FVF); + m_fvfTable.insert(std::make_pair(FVF, decl)); + } + else + decl = iter->second.ptr(); + } + + uint32_t offset = DestIndex * decl->GetSize(); + + auto slice = dst->GetBufferSlice(); + slice = slice.subSlice(offset, slice.length() - offset); + + EmitCs([this, + cDecl = ref(decl), + cVertexCount = VertexCount, + cStartIndex = SrcStartIndex, + cInstanceCount = GetInstanceCount(), + cBufferSlice = slice, + cIndexed = m_state.indices != nullptr + ](DxvkContext* ctx) { + Rc shader = m_swvpEmulator.GetShaderModule(this, cDecl); + + auto drawInfo = GenerateDrawInfo(D3DPT_POINTLIST, cVertexCount, cInstanceCount); + + if (drawInfo.instanceCount != 1) { + drawInfo.instanceCount = 1; + + Logger::warn("D3D9DeviceEx::ProcessVertices: instancing unsupported"); + } + + ApplyPrimitiveType(ctx, D3DPT_POINTLIST); + + // Unbind the pixel shader, we aren't drawing + // to avoid val errors / UB. + ctx->bindShader(VK_SHADER_STAGE_FRAGMENT_BIT, nullptr); + + ctx->bindShader(VK_SHADER_STAGE_GEOMETRY_BIT, shader); + ctx->bindResourceBuffer(getSWVPBufferSlot(), cBufferSlice); + ctx->draw( + drawInfo.vertexCount, drawInfo.instanceCount, + cStartIndex, 0); + ctx->bindResourceBuffer(getSWVPBufferSlot(), DxvkBufferSlice()); + ctx->bindShader(VK_SHADER_STAGE_GEOMETRY_BIT, nullptr); + }); + + // We unbound the pixel shader before, + // let's make sure that gets rebound. + m_flags.set(D3D9DeviceFlag::DirtyFFPixelShader); + + if (m_state.pixelShader != nullptr) { + BindShader( + GetCommonShader(m_state.pixelShader), + GetPixelShaderPermutation()); + } + + if (dst->GetMapMode() == D3D9_COMMON_BUFFER_MAP_MODE_BUFFER) { + uint32_t copySize = VertexCount * decl->GetSize(); + + EmitCs([ + cSrcBuffer = dst->GetBuffer(), + cDstBuffer = dst->GetBuffer(), + cOffset = offset, + cCopySize = copySize + ](DxvkContext* ctx) { + ctx->copyBuffer(cDstBuffer, cOffset, cSrcBuffer, cOffset, cCopySize); + }); + } + + dst->SetNeedsReadback(true); + TrackBufferMappingBufferSequenceNumber(dst); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::CreateVertexDeclaration( + const D3DVERTEXELEMENT9* pVertexElements, + IDirect3DVertexDeclaration9** ppDecl) { + InitReturnPtr(ppDecl); + + if (unlikely(ppDecl == nullptr || pVertexElements == nullptr)) + return D3DERR_INVALIDCALL; + + const D3DVERTEXELEMENT9* counter = pVertexElements; + while (counter->Stream != 0xFF) + counter++; + + const uint32_t declCount = uint32_t(counter - pVertexElements); + + try { + const Com decl = new D3D9VertexDecl(this, pVertexElements, declCount); + *ppDecl = decl.ref(); + return D3D_OK; + } + catch (const DxvkError & e) { + Logger::err(e.message()); + return D3DERR_INVALIDCALL; + } + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetVertexDeclaration(IDirect3DVertexDeclaration9* pDecl) { + D3D9DeviceLock lock = LockDevice(); + + D3D9VertexDecl* decl = static_cast(pDecl); + + if (unlikely(ShouldRecord())) + return m_recorder->SetVertexDeclaration(decl); + + if (decl == m_state.vertexDecl.ptr()) + return D3D_OK; + + bool dirtyFFShader = decl == nullptr || m_state.vertexDecl == nullptr; + if (!dirtyFFShader) + dirtyFFShader |= decl->GetFlags() != m_state.vertexDecl->GetFlags() + || decl->GetTexcoordMask() != m_state.vertexDecl->GetTexcoordMask(); + + if (dirtyFFShader) + m_flags.set(D3D9DeviceFlag::DirtyFFVertexShader); + + m_state.vertexDecl = decl; + + m_flags.set(D3D9DeviceFlag::DirtyInputLayout); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetVertexDeclaration(IDirect3DVertexDeclaration9** ppDecl) { + D3D9DeviceLock lock = LockDevice(); + + InitReturnPtr(ppDecl); + + if (ppDecl == nullptr) + return D3D_OK; + + if (m_state.vertexDecl == nullptr) + return D3D_OK; + + *ppDecl = m_state.vertexDecl.ref(); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetFVF(DWORD FVF) { + D3D9DeviceLock lock = LockDevice(); + + if (FVF == 0) + return D3D_OK; + + D3D9VertexDecl* decl = nullptr; + + auto iter = m_fvfTable.find(FVF); + + if (iter == m_fvfTable.end()) { + decl = new D3D9VertexDecl(this, FVF); + m_fvfTable.insert(std::make_pair(FVF, decl)); + } + else + decl = iter->second.ptr(); + + return this->SetVertexDeclaration(decl); + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetFVF(DWORD* pFVF) { + D3D9DeviceLock lock = LockDevice(); + + if (pFVF == nullptr) + return D3DERR_INVALIDCALL; + + *pFVF = m_state.vertexDecl != nullptr + ? m_state.vertexDecl->GetFVF() + : 0; + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::CreateVertexShader( + const DWORD* pFunction, + IDirect3DVertexShader9** ppShader) { + // CreateVertexShader does not init the + // return ptr unlike CreatePixelShader + + if (unlikely(ppShader == nullptr)) + return D3DERR_INVALIDCALL; + + DxsoModuleInfo moduleInfo; + moduleInfo.options = m_dxsoOptions; + + D3D9CommonShader module; + + if (FAILED(this->CreateShaderModule(&module, + VK_SHADER_STAGE_VERTEX_BIT, + pFunction, + &moduleInfo))) + return D3DERR_INVALIDCALL; + + *ppShader = ref(new D3D9VertexShader(this, module)); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetVertexShader(IDirect3DVertexShader9* pShader) { + D3D9DeviceLock lock = LockDevice(); + + D3D9VertexShader* shader = static_cast(pShader); + + if (unlikely(ShouldRecord())) + return m_recorder->SetVertexShader(shader); + + if (shader == m_state.vertexShader.ptr()) + return D3D_OK; + + auto* oldShader = GetCommonShader(m_state.vertexShader); + auto* newShader = GetCommonShader(shader); + + bool oldCopies = oldShader && oldShader->GetMeta().needsConstantCopies; + bool newCopies = newShader && newShader->GetMeta().needsConstantCopies; + + m_consts[DxsoProgramTypes::VertexShader].dirty |= oldCopies || newCopies || !oldShader; + m_consts[DxsoProgramTypes::VertexShader].meta = newShader ? newShader->GetMeta() : DxsoShaderMetaInfo(); + + if (newShader && oldShader) { + m_consts[DxsoProgramTypes::VertexShader].dirty + |= newShader->GetMeta().maxConstIndexF > oldShader->GetMeta().maxConstIndexF + || newShader->GetMeta().maxConstIndexI > oldShader->GetMeta().maxConstIndexI + || newShader->GetMeta().maxConstIndexB > oldShader->GetMeta().maxConstIndexB; + } + + m_state.vertexShader = shader; + + if (shader != nullptr) { + m_flags.clr(D3D9DeviceFlag::DirtyProgVertexShader); + m_flags.set(D3D9DeviceFlag::DirtyFFVertexShader); + + BindShader( + GetCommonShader(shader), + GetVertexShaderPermutation()); + + m_vsShaderMasks = newShader->GetShaderMask(); + } + else + m_vsShaderMasks = D3D9ShaderMasks(); + + m_flags.set(D3D9DeviceFlag::DirtyInputLayout); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetVertexShader(IDirect3DVertexShader9** ppShader) { + D3D9DeviceLock lock = LockDevice(); + + InitReturnPtr(ppShader); + + if (unlikely(ppShader == nullptr)) + return D3DERR_INVALIDCALL; + + *ppShader = m_state.vertexShader.ref(); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetVertexShaderConstantF( + UINT StartRegister, + const float* pConstantData, + UINT Vector4fCount) { + D3D9DeviceLock lock = LockDevice(); + + return SetShaderConstants< + DxsoProgramTypes::VertexShader, + D3D9ConstantType::Float>( + StartRegister, + pConstantData, + Vector4fCount); + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetVertexShaderConstantF( + UINT StartRegister, + float* pConstantData, + UINT Vector4fCount) { + D3D9DeviceLock lock = LockDevice(); + + return GetShaderConstants< + DxsoProgramTypes::VertexShader, + D3D9ConstantType::Float>( + StartRegister, + pConstantData, + Vector4fCount); + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetVertexShaderConstantI( + UINT StartRegister, + const int* pConstantData, + UINT Vector4iCount) { + D3D9DeviceLock lock = LockDevice(); + + return SetShaderConstants< + DxsoProgramTypes::VertexShader, + D3D9ConstantType::Int>( + StartRegister, + pConstantData, + Vector4iCount); + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetVertexShaderConstantI( + UINT StartRegister, + int* pConstantData, + UINT Vector4iCount) { + D3D9DeviceLock lock = LockDevice(); + + return GetShaderConstants< + DxsoProgramTypes::VertexShader, + D3D9ConstantType::Int>( + StartRegister, + pConstantData, + Vector4iCount); + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetVertexShaderConstantB( + UINT StartRegister, + const BOOL* pConstantData, + UINT BoolCount) { + D3D9DeviceLock lock = LockDevice(); + + return SetShaderConstants< + DxsoProgramTypes::VertexShader, + D3D9ConstantType::Bool>( + StartRegister, + pConstantData, + BoolCount); + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetVertexShaderConstantB( + UINT StartRegister, + BOOL* pConstantData, + UINT BoolCount) { + D3D9DeviceLock lock = LockDevice(); + + return GetShaderConstants< + DxsoProgramTypes::VertexShader, + D3D9ConstantType::Bool>( + StartRegister, + pConstantData, + BoolCount); + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetStreamSource( + UINT StreamNumber, + IDirect3DVertexBuffer9* pStreamData, + UINT OffsetInBytes, + UINT Stride) { + D3D9DeviceLock lock = LockDevice(); + + if (unlikely(StreamNumber >= caps::MaxStreams)) + return D3DERR_INVALIDCALL; + + D3D9VertexBuffer* buffer = static_cast(pStreamData); + + if (unlikely(ShouldRecord())) + return m_recorder->SetStreamSource( + StreamNumber, + buffer, + OffsetInBytes, + Stride); + + auto& vbo = m_state.vertexBuffers[StreamNumber]; + bool needsUpdate = vbo.vertexBuffer != buffer; + + if (needsUpdate) + vbo.vertexBuffer = buffer; + + if (buffer != nullptr) { + needsUpdate |= vbo.offset != OffsetInBytes + || vbo.stride != Stride; + + vbo.offset = OffsetInBytes; + vbo.stride = Stride; + } + + if (needsUpdate) + BindVertexBuffer(StreamNumber, buffer, OffsetInBytes, Stride); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetStreamSource( + UINT StreamNumber, + IDirect3DVertexBuffer9** ppStreamData, + UINT* pOffsetInBytes, + UINT* pStride) { + D3D9DeviceLock lock = LockDevice(); + + InitReturnPtr(ppStreamData); + + if (likely(pOffsetInBytes != nullptr)) + *pOffsetInBytes = 0; + + if (likely(pStride != nullptr)) + *pStride = 0; + + if (unlikely(ppStreamData == nullptr || pOffsetInBytes == nullptr || pStride == nullptr)) + return D3DERR_INVALIDCALL; + + if (unlikely(StreamNumber >= caps::MaxStreams)) + return D3DERR_INVALIDCALL; + + const auto& vbo = m_state.vertexBuffers[StreamNumber]; + + *ppStreamData = vbo.vertexBuffer.ref(); + *pOffsetInBytes = vbo.offset; + *pStride = vbo.stride; + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetStreamSourceFreq(UINT StreamNumber, UINT Setting) { + D3D9DeviceLock lock = LockDevice(); + + if (unlikely(StreamNumber >= caps::MaxStreams)) + return D3DERR_INVALIDCALL; + + const bool indexed = Setting & D3DSTREAMSOURCE_INDEXEDDATA; + const bool instanced = Setting & D3DSTREAMSOURCE_INSTANCEDATA; + + if (unlikely(StreamNumber == 0 && instanced)) + return D3DERR_INVALIDCALL; + + if (unlikely(instanced && indexed)) + return D3DERR_INVALIDCALL; + + if (unlikely(Setting == 0)) + return D3DERR_INVALIDCALL; + + if (unlikely(ShouldRecord())) + return m_recorder->SetStreamSourceFreq(StreamNumber, Setting); + + if (m_state.streamFreq[StreamNumber] == Setting) + return D3D_OK; + + m_state.streamFreq[StreamNumber] = Setting; + + if (instanced) + m_instancedData |= 1u << StreamNumber; + else + m_instancedData &= ~(1u << StreamNumber); + + m_flags.set(D3D9DeviceFlag::DirtyInputLayout); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetStreamSourceFreq(UINT StreamNumber, UINT* pSetting) { + D3D9DeviceLock lock = LockDevice(); + + if (unlikely(StreamNumber >= caps::MaxStreams)) + return D3DERR_INVALIDCALL; + + if (unlikely(pSetting == nullptr)) + return D3DERR_INVALIDCALL; + + *pSetting = m_state.streamFreq[StreamNumber]; + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetIndices(IDirect3DIndexBuffer9* pIndexData) { + D3D9DeviceLock lock = LockDevice(); + + D3D9IndexBuffer* buffer = static_cast(pIndexData); + + if (unlikely(ShouldRecord())) + return m_recorder->SetIndices(buffer); + + if (buffer == m_state.indices.ptr()) + return D3D_OK; + + m_state.indices = buffer; + + BindIndices(); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetIndices(IDirect3DIndexBuffer9** ppIndexData) { + D3D9DeviceLock lock = LockDevice(); + InitReturnPtr(ppIndexData); + + if (unlikely(ppIndexData == nullptr)) + return D3DERR_INVALIDCALL; + + *ppIndexData = m_state.indices.ref(); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::CreatePixelShader( + const DWORD* pFunction, + IDirect3DPixelShader9** ppShader) { + InitReturnPtr(ppShader); + + if (unlikely(ppShader == nullptr)) + return D3DERR_INVALIDCALL; + + DxsoModuleInfo moduleInfo; + moduleInfo.options = m_dxsoOptions; + + D3D9CommonShader module; + + if (FAILED(this->CreateShaderModule(&module, + VK_SHADER_STAGE_FRAGMENT_BIT, + pFunction, + &moduleInfo))) + return D3DERR_INVALIDCALL; + + *ppShader = ref(new D3D9PixelShader(this, module)); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetPixelShader(IDirect3DPixelShader9* pShader) { + D3D9DeviceLock lock = LockDevice(); + + D3D9PixelShader* shader = static_cast(pShader); + + if (unlikely(ShouldRecord())) + return m_recorder->SetPixelShader(shader); + + if (shader == m_state.pixelShader.ptr()) + return D3D_OK; + + auto* oldShader = GetCommonShader(m_state.pixelShader); + auto* newShader = GetCommonShader(shader); + + bool oldCopies = oldShader && oldShader->GetMeta().needsConstantCopies; + bool newCopies = newShader && newShader->GetMeta().needsConstantCopies; + + m_consts[DxsoProgramTypes::PixelShader].dirty |= oldCopies || newCopies || !oldShader; + m_consts[DxsoProgramTypes::PixelShader].meta = newShader ? newShader->GetMeta() : DxsoShaderMetaInfo(); + + if (newShader && oldShader) { + m_consts[DxsoProgramTypes::PixelShader].dirty + |= newShader->GetMeta().maxConstIndexF > oldShader->GetMeta().maxConstIndexF + || newShader->GetMeta().maxConstIndexI > oldShader->GetMeta().maxConstIndexI + || newShader->GetMeta().maxConstIndexB > oldShader->GetMeta().maxConstIndexB; + } + + m_state.pixelShader = shader; + + if (shader != nullptr) { + m_flags.set(D3D9DeviceFlag::DirtyFFPixelShader); + + BindShader( + GetCommonShader(shader), + GetPixelShaderPermutation()); + + m_psShaderMasks = newShader->GetShaderMask(); + } + else { + // TODO: What fixed function textures are in use? + // Currently we are making all 8 of them as in use here. + + // The RT output is always 0 for fixed function. + m_psShaderMasks = FixedFunctionMask; + } + + UpdateActiveHazardsRT(UINT32_MAX); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetPixelShader(IDirect3DPixelShader9** ppShader) { + D3D9DeviceLock lock = LockDevice(); + + InitReturnPtr(ppShader); + + if (unlikely(ppShader == nullptr)) + return D3DERR_INVALIDCALL; + + *ppShader = m_state.pixelShader.ref(); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetPixelShaderConstantF( + UINT StartRegister, + const float* pConstantData, + UINT Vector4fCount) { + D3D9DeviceLock lock = LockDevice(); + + return SetShaderConstants < + DxsoProgramTypes::PixelShader, + D3D9ConstantType::Float>( + StartRegister, + pConstantData, + Vector4fCount); + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetPixelShaderConstantF( + UINT StartRegister, + float* pConstantData, + UINT Vector4fCount) { + D3D9DeviceLock lock = LockDevice(); + + return GetShaderConstants< + DxsoProgramTypes::PixelShader, + D3D9ConstantType::Float>( + StartRegister, + pConstantData, + Vector4fCount); + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetPixelShaderConstantI( + UINT StartRegister, + const int* pConstantData, + UINT Vector4iCount) { + D3D9DeviceLock lock = LockDevice(); + + return SetShaderConstants< + DxsoProgramTypes::PixelShader, + D3D9ConstantType::Int>( + StartRegister, + pConstantData, + Vector4iCount); + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetPixelShaderConstantI( + UINT StartRegister, + int* pConstantData, + UINT Vector4iCount) { + D3D9DeviceLock lock = LockDevice(); + + return GetShaderConstants< + DxsoProgramTypes::PixelShader, + D3D9ConstantType::Int>( + StartRegister, + pConstantData, + Vector4iCount); + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetPixelShaderConstantB( + UINT StartRegister, + const BOOL* pConstantData, + UINT BoolCount) { + D3D9DeviceLock lock = LockDevice(); + + return SetShaderConstants< + DxsoProgramTypes::PixelShader, + D3D9ConstantType::Bool>( + StartRegister, + pConstantData, + BoolCount); + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetPixelShaderConstantB( + UINT StartRegister, + BOOL* pConstantData, + UINT BoolCount) { + D3D9DeviceLock lock = LockDevice(); + + return GetShaderConstants< + DxsoProgramTypes::PixelShader, + D3D9ConstantType::Bool>( + StartRegister, + pConstantData, + BoolCount); + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::DrawRectPatch( + UINT Handle, + const float* pNumSegs, + const D3DRECTPATCH_INFO* pRectPatchInfo) { + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::warn("D3D9DeviceEx::DrawRectPatch: Stub"); + return D3DERR_INVALIDCALL; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::DrawTriPatch( + UINT Handle, + const float* pNumSegs, + const D3DTRIPATCH_INFO* pTriPatchInfo) { + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::warn("D3D9DeviceEx::DrawTriPatch: Stub"); + return D3DERR_INVALIDCALL; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::DeletePatch(UINT Handle) { + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::warn("D3D9DeviceEx::DeletePatch: Stub"); + return D3DERR_INVALIDCALL; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::CreateQuery(D3DQUERYTYPE Type, IDirect3DQuery9** ppQuery) { + HRESULT hr = D3D9Query::QuerySupported(this, Type); + + if (ppQuery == nullptr || hr != D3D_OK) + return hr; + + try { + *ppQuery = ref(new D3D9Query(this, Type)); + return D3D_OK; + } + catch (const DxvkError & e) { + Logger::err(e.message()); + return D3DERR_INVALIDCALL; + } + } + + + // Ex Methods + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetConvolutionMonoKernel( + UINT width, + UINT height, + float* rows, + float* columns) { + // We don't advertise support for this. + return D3DERR_INVALIDCALL; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::ComposeRects( + IDirect3DSurface9* pSrc, + IDirect3DSurface9* pDst, + IDirect3DVertexBuffer9* pSrcRectDescs, + UINT NumRects, + IDirect3DVertexBuffer9* pDstRectDescs, + D3DCOMPOSERECTSOP Operation, + int Xoffset, + int Yoffset) { + Logger::warn("D3D9DeviceEx::ComposeRects: Stub"); + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetGPUThreadPriority(INT* pPriority) { + Logger::warn("D3D9DeviceEx::GetGPUThreadPriority: Stub"); + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetGPUThreadPriority(INT Priority) { + Logger::warn("D3D9DeviceEx::SetGPUThreadPriority: Stub"); + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::WaitForVBlank(UINT iSwapChain) { + if (unlikely(iSwapChain != 0)) + return D3DERR_INVALIDCALL; + + return m_implicitSwapchain->WaitForVBlank(); + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::CheckResourceResidency(IDirect3DResource9** pResourceArray, UINT32 NumResources) { + Logger::warn("D3D9DeviceEx::CheckResourceResidency: Stub"); + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetMaximumFrameLatency(UINT MaxLatency) { + D3D9DeviceLock lock = LockDevice(); + + if (MaxLatency == 0) + MaxLatency = DefaultFrameLatency; + + if (MaxLatency > MaxFrameLatency) + MaxLatency = MaxFrameLatency; + + m_frameLatency = MaxLatency; + + m_implicitSwapchain->SyncFrameLatency(); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetMaximumFrameLatency(UINT* pMaxLatency) { + D3D9DeviceLock lock = LockDevice(); + + if (unlikely(pMaxLatency == nullptr)) + return D3DERR_INVALIDCALL; + + *pMaxLatency = m_frameLatency; + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::CheckDeviceState(HWND hDestinationWindow) { + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::PresentEx( + const RECT* pSourceRect, + const RECT* pDestRect, + HWND hDestWindowOverride, + const RGNDATA* pDirtyRegion, + DWORD dwFlags) { + return m_implicitSwapchain->Present( + pSourceRect, + pDestRect, + hDestWindowOverride, + pDirtyRegion, + dwFlags); + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::CreateRenderTargetEx( + UINT Width, + UINT Height, + D3DFORMAT Format, + D3DMULTISAMPLE_TYPE MultiSample, + DWORD MultisampleQuality, + BOOL Lockable, + IDirect3DSurface9** ppSurface, + HANDLE* pSharedHandle, + DWORD Usage) { + InitReturnPtr(ppSurface); + + if (unlikely(ppSurface == nullptr)) + return D3DERR_INVALIDCALL; + + D3D9_COMMON_TEXTURE_DESC desc; + desc.Width = Width; + desc.Height = Height; + desc.Depth = 1; + desc.ArraySize = 1; + desc.MipLevels = 1; + desc.Usage = Usage | D3DUSAGE_RENDERTARGET; + desc.Format = EnumerateFormat(Format); + desc.Pool = D3DPOOL_DEFAULT; + desc.Discard = FALSE; + desc.MultiSample = MultiSample; + desc.MultisampleQuality = MultisampleQuality; + desc.IsBackBuffer = FALSE; + desc.IsAttachmentOnly = TRUE; + + if (FAILED(D3D9CommonTexture::NormalizeTextureProperties(this, &desc))) + return D3DERR_INVALIDCALL; + + try { + const Com surface = new D3D9Surface(this, &desc, nullptr, pSharedHandle); + m_initializer->InitTexture(surface->GetCommonTexture()); + *ppSurface = surface.ref(); + return D3D_OK; + } + catch (const DxvkError& e) { + Logger::err(e.message()); + return D3DERR_OUTOFVIDEOMEMORY; + } + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::CreateOffscreenPlainSurfaceEx( + UINT Width, + UINT Height, + D3DFORMAT Format, + D3DPOOL Pool, + IDirect3DSurface9** ppSurface, + HANDLE* pSharedHandle, + DWORD Usage) { + InitReturnPtr(ppSurface); + + if (unlikely(ppSurface == nullptr)) + return D3DERR_INVALIDCALL; + + D3D9_COMMON_TEXTURE_DESC desc; + desc.Width = Width; + desc.Height = Height; + desc.Depth = 1; + desc.ArraySize = 1; + desc.MipLevels = 1; + desc.Usage = Usage; + desc.Format = EnumerateFormat(Format); + desc.Pool = Pool; + desc.Discard = FALSE; + desc.MultiSample = D3DMULTISAMPLE_NONE; + desc.MultisampleQuality = 0; + desc.IsBackBuffer = FALSE; + desc.IsAttachmentOnly = Pool == D3DPOOL_DEFAULT; + + if (FAILED(D3D9CommonTexture::NormalizeTextureProperties(this, &desc))) + return D3DERR_INVALIDCALL; + + if (pSharedHandle != nullptr && Pool != D3DPOOL_DEFAULT) + return D3DERR_INVALIDCALL; + + try { + const Com surface = new D3D9Surface(this, &desc, nullptr, pSharedHandle); + m_initializer->InitTexture(surface->GetCommonTexture()); + *ppSurface = surface.ref(); + return D3D_OK; + } + catch (const DxvkError& e) { + Logger::err(e.message()); + return D3DERR_OUTOFVIDEOMEMORY; + } + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::CreateDepthStencilSurfaceEx( + UINT Width, + UINT Height, + D3DFORMAT Format, + D3DMULTISAMPLE_TYPE MultiSample, + DWORD MultisampleQuality, + BOOL Discard, + IDirect3DSurface9** ppSurface, + HANDLE* pSharedHandle, + DWORD Usage) { + InitReturnPtr(ppSurface); + + if (unlikely(ppSurface == nullptr)) + return D3DERR_INVALIDCALL; + + D3D9_COMMON_TEXTURE_DESC desc; + desc.Width = Width; + desc.Height = Height; + desc.Depth = 1; + desc.ArraySize = 1; + desc.MipLevels = 1; + desc.Usage = Usage | D3DUSAGE_DEPTHSTENCIL; + desc.Format = EnumerateFormat(Format); + desc.Pool = D3DPOOL_DEFAULT; + desc.Discard = Discard; + desc.MultiSample = MultiSample; + desc.MultisampleQuality = MultisampleQuality; + desc.IsBackBuffer = FALSE; + desc.IsAttachmentOnly = TRUE; + + if (FAILED(D3D9CommonTexture::NormalizeTextureProperties(this, &desc))) + return D3DERR_INVALIDCALL; + + try { + const Com surface = new D3D9Surface(this, &desc, nullptr, pSharedHandle); + m_initializer->InitTexture(surface->GetCommonTexture()); + *ppSurface = surface.ref(); + return D3D_OK; + } + catch (const DxvkError& e) { + Logger::err(e.message()); + return D3DERR_OUTOFVIDEOMEMORY; + } + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::ResetEx( + D3DPRESENT_PARAMETERS* pPresentationParameters, + D3DDISPLAYMODEEX* pFullscreenDisplayMode) { + D3D9DeviceLock lock = LockDevice(); + + HRESULT hr = ResetSwapChain(pPresentationParameters, pFullscreenDisplayMode); + if (FAILED(hr)) + return hr; + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetDisplayModeEx( + UINT iSwapChain, + D3DDISPLAYMODEEX* pMode, + D3DDISPLAYROTATION* pRotation) { + if (unlikely(iSwapChain != 0)) + return D3DERR_INVALIDCALL; + + return m_implicitSwapchain->GetDisplayModeEx(pMode, pRotation); + } + + + HRESULT STDMETHODCALLTYPE D3D9DeviceEx::CreateAdditionalSwapChainEx( + D3DPRESENT_PARAMETERS* pPresentationParameters, + const D3DDISPLAYMODEEX* pFullscreenDisplayMode, + IDirect3DSwapChain9** ppSwapChain) { + D3D9DeviceLock lock = LockDevice(); + + InitReturnPtr(ppSwapChain); + + if (ppSwapChain == nullptr || pPresentationParameters == nullptr) + return D3DERR_INVALIDCALL; + + // Additional fullscreen swapchains are forbidden. + if (!pPresentationParameters->Windowed) + return D3DERR_INVALIDCALL; + + // We can't make another swapchain if we are fullscreen. + if (!m_implicitSwapchain->GetPresentParams()->Windowed) + return D3DERR_INVALIDCALL; + + m_implicitSwapchain->Invalidate(pPresentationParameters->hDeviceWindow); + + try { + auto* swapchain = new D3D9SwapChainEx(this, pPresentationParameters, pFullscreenDisplayMode); + *ppSwapChain = ref(swapchain); + } + catch (const DxvkError & e) { + Logger::err(e.message()); + return D3DERR_NOTAVAILABLE; + } + + return D3D_OK; + } + + + HRESULT D3D9DeviceEx::SetStateSamplerState( + DWORD StateSampler, + D3DSAMPLERSTATETYPE Type, + DWORD Value) { + D3D9DeviceLock lock = LockDevice(); + + if (unlikely(ShouldRecord())) + return m_recorder->SetStateSamplerState(StateSampler, Type, Value); + + auto& state = m_state.samplerStates; + + if (state[StateSampler][Type] == Value) + return D3D_OK; + + state[StateSampler][Type] = Value; + + if (Type == D3DSAMP_ADDRESSU + || Type == D3DSAMP_ADDRESSV + || Type == D3DSAMP_ADDRESSW + || Type == D3DSAMP_MAGFILTER + || Type == D3DSAMP_MINFILTER + || Type == D3DSAMP_MIPFILTER + || Type == D3DSAMP_MAXANISOTROPY + || Type == D3DSAMP_MIPMAPLODBIAS + || Type == D3DSAMP_MAXMIPLEVEL + || Type == D3DSAMP_BORDERCOLOR) + m_dirtySamplerStates |= 1u << StateSampler; + else if (Type == D3DSAMP_SRGBTEXTURE && (m_activeTextures & (1u << StateSampler))) + m_dirtyTextures |= 1u << StateSampler; + + constexpr DWORD Fetch4Enabled = MAKEFOURCC('G', 'E', 'T', '4'); + constexpr DWORD Fetch4Disabled = MAKEFOURCC('G', 'E', 'T', '1'); + + if (unlikely(Type == D3DSAMP_MIPMAPLODBIAS)) { + auto texture = GetCommonTexture(m_state.textures[StateSampler]); + bool textureSupportsFetch4 = texture != nullptr && texture->SupportsFetch4(); + + if (unlikely(Value == Fetch4Enabled)) { + m_fetch4Enabled |= 1u << StateSampler; + if (textureSupportsFetch4 && state[StateSampler][D3DSAMP_MAGFILTER] == D3DTEXF_POINT) { + m_fetch4 |= 1u << StateSampler; + } + } + else if (unlikely(Value == Fetch4Disabled)) { + m_fetch4Enabled &= ~(1u << StateSampler); + m_fetch4 &= ~(1u << StateSampler); + } + } + + if (unlikely(Type == D3DSAMP_MAGFILTER && (m_fetch4Enabled & (1u << StateSampler)))) { + auto texture = GetCommonTexture(m_state.textures[StateSampler]); + bool textureSupportsFetch4 = texture != nullptr && texture->SupportsFetch4(); + + if (Value == D3DTEXF_POINT && textureSupportsFetch4) + m_fetch4 |= 1u << StateSampler; + else + m_fetch4 &= ~(1u << StateSampler); + } + + return D3D_OK; + } + + + HRESULT D3D9DeviceEx::SetStateTexture(DWORD StateSampler, IDirect3DBaseTexture9* pTexture) { + D3D9DeviceLock lock = LockDevice(); + + if (unlikely(ShouldRecord())) + return m_recorder->SetStateTexture(StateSampler, pTexture); + + if (m_state.textures[StateSampler] == pTexture) + return D3D_OK; + + auto oldTexture = GetCommonTexture(m_state.textures[StateSampler]); + auto newTexture = GetCommonTexture(pTexture); + + // We need to check our ops and disable respective stages. + // Given we have transition from a null resource to + // a valid resource or vice versa. + if (StateSampler < caps::MaxTexturesPS) { + const uint32_t offset = StateSampler * 2; + const uint32_t textureType = newTexture != nullptr + ? uint32_t(newTexture->GetType() - D3DRTYPE_TEXTURE) + : 0; + const uint32_t textureBitMask = 0b11u << offset; + const uint32_t textureBits = textureType << offset; + + m_textureTypes &= ~textureBitMask; + m_textureTypes |= textureBits; + + if (newTexture == nullptr || oldTexture == nullptr) + m_flags.set(D3D9DeviceFlag::DirtyFFPixelShader); + } + + DWORD oldUsage = oldTexture != nullptr ? oldTexture->Desc()->Usage : 0; + DWORD newUsage = newTexture != nullptr ? newTexture->Desc()->Usage : 0; + + if (newTexture != nullptr) { + const bool oldDepth = m_depthTextures & (1u << StateSampler); + const bool newDepth = newTexture->IsShadow(); + + if (oldDepth != newDepth) { + m_depthTextures &= ~(1u << StateSampler); + if (newDepth) + m_depthTextures |= 1u << StateSampler; + + m_dirtySamplerStates |= 1u << StateSampler; + } + + if (unlikely(m_fetch4Enabled & (1u << StateSampler) && !(m_fetch4 & (1u << StateSampler)))) { + bool textureSupportsFetch4 = newTexture->SupportsFetch4(); + if (textureSupportsFetch4 + && m_state.samplerStates[StateSampler][D3DSAMP_MAGFILTER] == D3DTEXF_POINT + && m_state.samplerStates[StateSampler][D3DSAMP_MINFILTER] == D3DTEXF_POINT) { + m_fetch4 |= 1u << StateSampler; + m_dirtySamplerStates |= 1u << StateSampler; + } + } + } else if (unlikely(m_fetch4 & (1u << StateSampler))) { + m_fetch4 &= ~(1u << StateSampler); + m_dirtySamplerStates |= 1u << StateSampler; + } + + DWORD combinedUsage = oldUsage | newUsage; + + TextureChangePrivate(m_state.textures[StateSampler], pTexture); + + m_dirtyTextures |= 1u << StateSampler; + + UpdateActiveTextures(StateSampler, combinedUsage); + + return D3D_OK; + } + + + HRESULT D3D9DeviceEx::SetStateTransform(uint32_t idx, const D3DMATRIX* pMatrix) { + D3D9DeviceLock lock = LockDevice(); + + if (unlikely(ShouldRecord())) + return m_recorder->SetStateTransform(idx, pMatrix); + + m_state.transforms[idx] = ConvertMatrix(pMatrix); + + m_flags.set(D3D9DeviceFlag::DirtyFFVertexData); + + if (idx == GetTransformIndex(D3DTS_VIEW) || idx >= GetTransformIndex(D3DTS_WORLD)) + m_flags.set(D3D9DeviceFlag::DirtyFFVertexBlend); + + return D3D_OK; + } + + + HRESULT D3D9DeviceEx::SetStateTextureStageState( + DWORD Stage, + D3D9TextureStageStateTypes Type, + DWORD Value) { + D3D9DeviceLock lock = LockDevice(); + + if (unlikely(Stage >= caps::TextureStageCount)) + return D3DERR_INVALIDCALL; + + if (unlikely(Type >= TextureStageStateCount)) + return D3DERR_INVALIDCALL; + + if (unlikely(ShouldRecord())) + return m_recorder->SetStateTextureStageState(Stage, Type, Value); + + if (likely(m_state.textureStages[Stage][Type] != Value)) { + m_state.textureStages[Stage][Type] = Value; + + switch (Type) { + case DXVK_TSS_COLOROP: + case DXVK_TSS_COLORARG0: + case DXVK_TSS_COLORARG1: + case DXVK_TSS_COLORARG2: + case DXVK_TSS_ALPHAOP: + case DXVK_TSS_ALPHAARG0: + case DXVK_TSS_ALPHAARG1: + case DXVK_TSS_ALPHAARG2: + case DXVK_TSS_RESULTARG: + m_flags.set(D3D9DeviceFlag::DirtyFFPixelShader); + break; + + case DXVK_TSS_TEXCOORDINDEX: + m_flags.set(D3D9DeviceFlag::DirtyFFVertexShader); + break; + + case DXVK_TSS_TEXTURETRANSFORMFLAGS: + m_projectionBitfield &= ~(1 << Stage); + if (Value & D3DTTFF_PROJECTED) + m_projectionBitfield |= 1 << Stage; + + m_flags.set(D3D9DeviceFlag::DirtyFFVertexShader); + m_flags.set(D3D9DeviceFlag::DirtyFFPixelShader); + break; + + case DXVK_TSS_BUMPENVMAT00: + case DXVK_TSS_BUMPENVMAT01: + case DXVK_TSS_BUMPENVMAT10: + case DXVK_TSS_BUMPENVMAT11: + case DXVK_TSS_BUMPENVLSCALE: + case DXVK_TSS_BUMPENVLOFFSET: + case DXVK_TSS_CONSTANT: + m_flags.set(D3D9DeviceFlag::DirtySharedPixelShaderData); + break; + + default: break; + } + } + + return D3D_OK; + } + + + bool D3D9DeviceEx::IsExtended() { + return m_parent->IsExtended(); + } + + + bool D3D9DeviceEx::SupportsSWVP() { + return m_dxvkDevice->features().core.features.vertexPipelineStoresAndAtomics; + } + + + HWND D3D9DeviceEx::GetWindow() { + return m_window; + } + + + DxvkDeviceFeatures D3D9DeviceEx::GetDeviceFeatures(const Rc& adapter) { + DxvkDeviceFeatures supported = adapter->features(); + DxvkDeviceFeatures enabled = {}; + + // Geometry shaders are used for some meta ops + enabled.core.features.geometryShader = VK_TRUE; + enabled.core.features.robustBufferAccess = VK_TRUE; + enabled.extRobustness2.robustBufferAccess2 = supported.extRobustness2.robustBufferAccess2; + + enabled.extMemoryPriority.memoryPriority = supported.extMemoryPriority.memoryPriority; + + enabled.extShaderDemoteToHelperInvocation.shaderDemoteToHelperInvocation = supported.extShaderDemoteToHelperInvocation.shaderDemoteToHelperInvocation; + + enabled.extVertexAttributeDivisor.vertexAttributeInstanceRateDivisor = supported.extVertexAttributeDivisor.vertexAttributeInstanceRateDivisor; + enabled.extVertexAttributeDivisor.vertexAttributeInstanceRateZeroDivisor = supported.extVertexAttributeDivisor.vertexAttributeInstanceRateZeroDivisor; + + // Null Descriptors + enabled.extRobustness2.nullDescriptor = supported.extRobustness2.nullDescriptor; + + // ProcessVertices + enabled.core.features.vertexPipelineStoresAndAtomics = supported.core.features.vertexPipelineStoresAndAtomics; + + // DXVK Meta + enabled.core.features.shaderStorageImageWriteWithoutFormat = VK_TRUE; + enabled.core.features.imageCubeArray = VK_TRUE; + + // SM1 level hardware + enabled.core.features.depthClamp = VK_TRUE; + enabled.core.features.depthBiasClamp = VK_TRUE; + enabled.core.features.fillModeNonSolid = VK_TRUE; + enabled.core.features.pipelineStatisticsQuery = supported.core.features.pipelineStatisticsQuery; + enabled.core.features.sampleRateShading = VK_TRUE; + enabled.core.features.samplerAnisotropy = supported.core.features.samplerAnisotropy; + enabled.core.features.shaderClipDistance = VK_TRUE; + enabled.core.features.shaderCullDistance = VK_TRUE; + + // Ensure we support real BC formats and unofficial vendor ones. + enabled.core.features.textureCompressionBC = VK_TRUE; + + enabled.extDepthClipEnable.depthClipEnable = supported.extDepthClipEnable.depthClipEnable; + enabled.extHostQueryReset.hostQueryReset = VK_TRUE; + + // SM2 level hardware + enabled.core.features.occlusionQueryPrecise = VK_TRUE; + + // SM3 level hardware + enabled.core.features.multiViewport = VK_TRUE; + enabled.core.features.independentBlend = VK_TRUE; + + // D3D10 level hardware supports this in D3D9 native. + enabled.core.features.fullDrawIndexUint32 = VK_TRUE; + + // Enable depth bounds test if we support it. + enabled.core.features.depthBounds = supported.core.features.depthBounds; + + if (supported.extCustomBorderColor.customBorderColorWithoutFormat) { + enabled.extCustomBorderColor.customBorderColors = VK_TRUE; + enabled.extCustomBorderColor.customBorderColorWithoutFormat = VK_TRUE; + } + + enabled.extNonSeamlessCubeMap.nonSeamlessCubeMap = supported.extNonSeamlessCubeMap.nonSeamlessCubeMap; + + return enabled; + } + + + void D3D9DeviceEx::DetermineConstantLayouts(bool canSWVP) { + m_vsLayout.floatCount = canSWVP ? caps::MaxFloatConstantsSoftware : caps::MaxFloatConstantsVS; + m_vsLayout.intCount = canSWVP ? caps::MaxOtherConstantsSoftware : caps::MaxOtherConstants; + m_vsLayout.boolCount = canSWVP ? caps::MaxOtherConstantsSoftware : caps::MaxOtherConstants; + m_vsLayout.bitmaskCount = align(m_vsLayout.boolCount, 32) / 32; + + m_psLayout.floatCount = caps::MaxFloatConstantsPS; + m_psLayout.intCount = caps::MaxOtherConstants; + m_psLayout.boolCount = caps::MaxOtherConstants; + m_psLayout.bitmaskCount = align(m_psLayout.boolCount, 32) / 32; + } + + + template + D3D9BufferSlice D3D9DeviceEx::AllocTempBuffer(VkDeviceSize size) { + constexpr VkDeviceSize DefaultSize = 1 << 20; + + VkMemoryPropertyFlags memoryFlags + = VK_MEMORY_PROPERTY_HOST_COHERENT_BIT + | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; + + if constexpr (UpBuffer) { + memoryFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + } + + D3D9BufferSlice& currentSlice = UpBuffer ? m_upBuffer : m_managedUploadBuffer; + + if (size <= DefaultSize) { + if (unlikely(!currentSlice.slice.defined())) { + DxvkBufferCreateInfo info; + info.size = DefaultSize; + if constexpr (UpBuffer) { + info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT + | VK_BUFFER_USAGE_INDEX_BUFFER_BIT; + info.access = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT + | VK_ACCESS_INDEX_READ_BIT; + info.stages = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT; + } else { + info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT; + info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; + info.access = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_SHADER_READ_BIT; + } + + currentSlice.slice = DxvkBufferSlice(m_dxvkDevice->createBuffer(info, memoryFlags)); + currentSlice.mapPtr = currentSlice.slice.mapPtr(0); + } else if (unlikely(currentSlice.slice.length() < size)) { + auto physSlice = currentSlice.slice.buffer()->allocSlice(); + + currentSlice.slice = DxvkBufferSlice(currentSlice.slice.buffer()); + currentSlice.mapPtr = physSlice.mapPtr; + + EmitCs([ + cBuffer = currentSlice.slice.buffer(), + cSlice = physSlice + ] (DxvkContext* ctx) { + ctx->invalidateBuffer(cBuffer, cSlice); + }); + } + + D3D9BufferSlice result; + result.slice = currentSlice.slice.subSlice(0, size); + result.mapPtr = reinterpret_cast(currentSlice.mapPtr) + currentSlice.slice.offset(); + + VkDeviceSize adjust = align(size, CACHE_LINE_SIZE); + currentSlice.slice = currentSlice.slice.subSlice(adjust, currentSlice.slice.length() - adjust); + return result; + } else { + // Create a temporary buffer for very large allocations + DxvkBufferCreateInfo info; + info.size = size; + if constexpr (UpBuffer) { + info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT + | VK_BUFFER_USAGE_INDEX_BUFFER_BIT; + info.access = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT + | VK_ACCESS_INDEX_READ_BIT; + info.stages = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT; + } else { + info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT; + info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT; + info.access = VK_ACCESS_TRANSFER_READ_BIT; + } + + D3D9BufferSlice result; + result.slice = DxvkBufferSlice(m_dxvkDevice->createBuffer(info, memoryFlags)); + result.mapPtr = result.slice.mapPtr(0); + return result; + } + } + + bool D3D9DeviceEx::ShouldRecord() { + return m_recorder != nullptr && !m_recorder->IsApplying(); + } + + + D3D9_VK_FORMAT_MAPPING D3D9DeviceEx::LookupFormat( + D3D9Format Format) const { + return m_adapter->GetFormatMapping(Format); + } + + const DxvkFormatInfo* D3D9DeviceEx::UnsupportedFormatInfo( + D3D9Format Format) const { + return m_adapter->GetUnsupportedFormatInfo(Format); + } + + bool D3D9DeviceEx::WaitForResource( + const Rc& Resource, + uint64_t SequenceNumber, + DWORD MapFlags) { + // Wait for the any pending D3D9 command to be executed + // on the CS thread so that we can determine whether the + // resource is currently in use or not. + + // Determine access type to wait for based on map mode + DxvkAccess access = (MapFlags & D3DLOCK_READONLY) + ? DxvkAccess::Write + : DxvkAccess::Read; + + if (!Resource->isInUse(access)) + SynchronizeCsThread(SequenceNumber); + + if (Resource->isInUse(access)) { + if (MapFlags & D3DLOCK_DONOTWAIT) { + // We don't have to wait, but misbehaving games may + // still try to spin on `Map` until the resource is + // idle, so we should flush pending commands + FlushImplicit(FALSE); + return false; + } + else { + // Make sure pending commands using the resource get + // executed on the the GPU if we have to wait for it + Flush(); + SynchronizeCsThread(SequenceNumber); + + m_dxvkDevice->waitForResource(Resource, access); + } + } + + return true; + } + + + uint32_t D3D9DeviceEx::CalcImageLockOffset( + uint32_t SlicePitch, + uint32_t RowPitch, + const DxvkFormatInfo* FormatInfo, + const D3DBOX* pBox) { + if (pBox == nullptr) + return 0; + + std::array offsets = { pBox->Front, pBox->Top, pBox->Left }; + + uint32_t elementSize = 1; + + if (FormatInfo != nullptr) { + elementSize = FormatInfo->elementSize; + + offsets[0] = offsets[0] / FormatInfo->blockSize.depth; + offsets[1] = offsets[1] / FormatInfo->blockSize.height; + offsets[2] = offsets[2] / FormatInfo->blockSize.width; + } + + return offsets[0] * SlicePitch + + offsets[1] * RowPitch + + offsets[2] * elementSize; + } + + + HRESULT D3D9DeviceEx::LockImage( + D3D9CommonTexture* pResource, + UINT Face, + UINT MipLevel, + D3DLOCKED_BOX* pLockedBox, + const D3DBOX* pBox, + DWORD Flags) { + D3D9DeviceLock lock = LockDevice(); + + UINT Subresource = pResource->CalcSubresource(Face, MipLevel); + + // Don't allow multiple lockings. + if (unlikely(pResource->GetLocked(Subresource))) + return D3DERR_INVALIDCALL; + + if (unlikely((Flags & (D3DLOCK_DISCARD | D3DLOCK_READONLY)) == (D3DLOCK_DISCARD | D3DLOCK_READONLY))) + return D3DERR_INVALIDCALL; + + if (unlikely(!m_d3d9Options.allowDoNotWait)) + Flags &= ~D3DLOCK_DONOTWAIT; + + if (unlikely((Flags & (D3DLOCK_DISCARD | D3DLOCK_NOOVERWRITE)) == (D3DLOCK_DISCARD | D3DLOCK_NOOVERWRITE))) + Flags &= ~D3DLOCK_DISCARD; + + auto& desc = *(pResource->Desc()); + + bool alloced = pResource->CreateBufferSubresource(Subresource); + + const Rc mappedBuffer = pResource->GetBuffer(Subresource); + + auto& formatMapping = pResource->GetFormatMapping(); + + const DxvkFormatInfo* formatInfo = formatMapping.IsValid() + ? imageFormatInfo(formatMapping.FormatColor) : UnsupportedFormatInfo(pResource->Desc()->Format); + + auto subresource = pResource->GetSubresourceFromIndex( + formatInfo->aspectMask, Subresource); + + VkExtent3D levelExtent = pResource->GetExtentMip(MipLevel); + VkExtent3D blockCount = util::computeBlockCount(levelExtent, formatInfo->blockSize); + + const bool systemmem = desc.Pool == D3DPOOL_SYSTEMMEM; + const bool managed = IsPoolManaged(desc.Pool); + const bool scratch = desc.Pool == D3DPOOL_SCRATCH; + + bool fullResource = pBox == nullptr; + if (unlikely(!fullResource)) { + VkOffset3D lockOffset; + VkExtent3D lockExtent; + + ConvertBox(*pBox, lockOffset, lockExtent); + + fullResource = lockOffset == VkOffset3D{ 0, 0, 0 } + && lockExtent.width >= levelExtent.width + && lockExtent.height >= levelExtent.height + && lockExtent.depth >= levelExtent.depth; + } + + // If we are not locking the entire image + // a partial discard is meant to occur. + // We can't really implement that, so just ignore discard + // if we are not locking the full resource + + // DISCARD is also ignored for MANAGED and SYSTEMEM. + // DISCARD is not ignored for non-DYNAMIC unlike what the docs say. + + if (!fullResource || desc.Pool != D3DPOOL_DEFAULT) + Flags &= ~D3DLOCK_DISCARD; + + if (desc.Usage & D3DUSAGE_WRITEONLY) + Flags &= ~D3DLOCK_READONLY; + + const bool readOnly = Flags & D3DLOCK_READONLY; + pResource->SetReadOnlyLocked(Subresource, readOnly); + + bool renderable = desc.Usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL); + + // If we recently wrote to the texture on the gpu, + // then we need to copy -> buffer + // We are also always dirty if we are a render target, + // a depth stencil, or auto generate mipmaps. + bool needsReadback = pResource->NeedsReachback(Subresource) || renderable; + pResource->SetNeedsReadback(Subresource, false); + + DxvkBufferSliceHandle physSlice; + + if (Flags & D3DLOCK_DISCARD) { + // We do not have to preserve the contents of the + // buffer if the entire image gets discarded. + physSlice = pResource->DiscardMapSlice(Subresource); + + EmitCs([ + cImageBuffer = std::move(mappedBuffer), + cBufferSlice = physSlice + ] (DxvkContext* ctx) { + ctx->invalidateBuffer(cImageBuffer, cBufferSlice); + }); + } else { + physSlice = pResource->GetMappedSlice(Subresource); + + // We do not need to wait for the resource in the event the + // calling app promises not to overwrite data that is in use + // or is reading. Remember! This will only trigger for MANAGED resources + // that cannot get affected by GPU, therefore readonly is A-OK for NOT waiting. + const bool usesStagingBuffer = pResource->DoesStagingBufferUploads(Subresource); + const bool skipWait = (scratch || managed || systemmem) && !needsReadback + && (usesStagingBuffer || readOnly); + + if (alloced && !needsReadback) { + std::memset(physSlice.mapPtr, 0, physSlice.length); + } + else if (!skipWait) { + if (unlikely(needsReadback) && pResource->GetImage() != nullptr) { + Rc resourceImage = pResource->GetImage(); + + Rc mappedImage = resourceImage->info().sampleCount != 1 + ? pResource->GetResolveImage() + : std::move(resourceImage); + + // When using any map mode which requires the image contents + // to be preserved, and if the GPU has write access to the + // image, copy the current image contents into the buffer. + auto subresourceLayers = vk::makeSubresourceLayers(subresource); + + // We need to resolve this, some games + // lock MSAA render targets even though + // that's entirely illegal and they explicitly + // tell us that they do NOT want to lock them... + if (resourceImage != nullptr) { + EmitCs([ + cMainImage = resourceImage, + cResolveImage = mappedImage, + cSubresource = subresourceLayers + ] (DxvkContext* ctx) { + VkImageResolve region; + region.srcSubresource = cSubresource; + region.srcOffset = VkOffset3D { 0, 0, 0 }; + region.dstSubresource = cSubresource; + region.dstOffset = VkOffset3D { 0, 0, 0 }; + region.extent = cMainImage->mipLevelExtent(cSubresource.mipLevel); + + if (cSubresource.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { + ctx->resolveImage( + cResolveImage, cMainImage, region, + cMainImage->info().format); + } + else { + ctx->resolveDepthStencilImage( + cResolveImage, cMainImage, region, + VK_RESOLVE_MODE_SAMPLE_ZERO_BIT_KHR, + VK_RESOLVE_MODE_SAMPLE_ZERO_BIT_KHR); + } + }); + } + + VkFormat packedFormat = GetPackedDepthStencilFormat(desc.Format); + + EmitCs([ + cImageBuffer = mappedBuffer, + cImage = std::move(mappedImage), + cSubresources = subresourceLayers, + cLevelExtent = levelExtent, + cPackedFormat = packedFormat + ] (DxvkContext* ctx) { + if (cSubresources.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { + ctx->copyImageToBuffer(cImageBuffer, 0, 4, 0, + cImage, cSubresources, VkOffset3D { 0, 0, 0 }, + cLevelExtent); + } else { + // Copying DS to a packed buffer is only supported for D24S8 and D32S8 + // right now so the 4 byte row alignment is guaranteed by the format size + ctx->copyDepthStencilImageToPackedBuffer( + cImageBuffer, 0, + VkOffset2D { 0, 0 }, + VkExtent2D { cLevelExtent.width, cLevelExtent.height }, + cImage, cSubresources, + VkOffset2D { 0, 0 }, + VkExtent2D { cLevelExtent.width, cLevelExtent.height }, + cPackedFormat); + } + }); + TrackTextureMappingBufferSequenceNumber(pResource, Subresource); + } else if (!(Flags & D3DLOCK_DONOTWAIT) && !WaitForResource(mappedBuffer, pResource->GetMappingBufferSequenceNumber(Subresource), D3DLOCK_DONOTWAIT)) { + pResource->EnableStagingBufferUploads(Subresource); + } + + if (!WaitForResource(mappedBuffer, pResource->GetMappingBufferSequenceNumber(Subresource), Flags)) + return D3DERR_WASSTILLDRAWING; + } + } + + const bool atiHack = desc.Format == D3D9Format::ATI1 || desc.Format == D3D9Format::ATI2; + // Set up map pointer. + if (atiHack) { + // We need to lie here. The game is expected to use this info and do a workaround. + // It's stupid. I know. + pLockedBox->RowPitch = align(std::max(desc.Width >> MipLevel, 1u), 4); + pLockedBox->SlicePitch = pLockedBox->RowPitch * std::max(desc.Height >> MipLevel, 1u); + } + else { + // Data is tightly packed within the mapped buffer. + pLockedBox->RowPitch = align(formatInfo->elementSize * blockCount.width, 4); + pLockedBox->SlicePitch = pLockedBox->RowPitch * blockCount.height; + } + + pResource->SetLocked(Subresource, true); + + const bool noDirtyUpdate = Flags & D3DLOCK_NO_DIRTY_UPDATE; + if (likely((pResource->IsManaged() && m_d3d9Options.evictManagedOnUnlock) + || ((desc.Pool == D3DPOOL_DEFAULT || !noDirtyUpdate) && !readOnly))) { + if (pBox && MipLevel != 0) { + D3DBOX scaledBox = *pBox; + scaledBox.Left <<= MipLevel; + scaledBox.Right = std::min(scaledBox.Right << MipLevel, pResource->Desc()->Width); + scaledBox.Top <<= MipLevel; + scaledBox.Bottom = std::min(scaledBox.Bottom << MipLevel, pResource->Desc()->Height); + scaledBox.Back <<= MipLevel; + scaledBox.Front = std::min(scaledBox.Front << MipLevel, pResource->Desc()->Depth); + pResource->AddDirtyBox(&scaledBox, Face); + } else { + pResource->AddDirtyBox(pBox, Face); + } + } + + if (managed && !m_d3d9Options.evictManagedOnUnlock && !readOnly) { + pResource->SetNeedsUpload(Subresource, true); + + for (uint32_t i : bit::BitMask(m_activeTextures)) { + // Guaranteed to not be nullptr... + auto texInfo = GetCommonTexture(m_state.textures[i]); + + if (texInfo == pResource) { + m_activeTexturesToUpload |= 1 << i; + // We can early out here, no need to add another index for this. + break; + } + } + } + + const uint32_t offset = CalcImageLockOffset( + pLockedBox->SlicePitch, + pLockedBox->RowPitch, + (!atiHack) ? formatInfo : nullptr, + pBox); + + + uint8_t* data = reinterpret_cast(physSlice.mapPtr); + data += offset; + pLockedBox->pBits = data; + return D3D_OK; + } + + + HRESULT D3D9DeviceEx::UnlockImage( + D3D9CommonTexture* pResource, + UINT Face, + UINT MipLevel) { + D3D9DeviceLock lock = LockDevice(); + + UINT Subresource = pResource->CalcSubresource(Face, MipLevel); + + // We weren't locked anyway! + if (unlikely(!pResource->GetLocked(Subresource))) + return D3D_OK; + + pResource->SetLocked(Subresource, false); + + // Flush image contents from staging if we aren't read only + // and we aren't deferring for managed. + const D3DBOX& box = pResource->GetDirtyBox(Face); + bool shouldFlush = pResource->GetMapMode() == D3D9_COMMON_TEXTURE_MAP_MODE_BACKED; + shouldFlush &= box.Left < box.Right && box.Top < box.Bottom && box.Front < box.Back; + shouldFlush &= !pResource->IsManaged() || m_d3d9Options.evictManagedOnUnlock; + + if (shouldFlush) { + this->FlushImage(pResource, Subresource); + if (!pResource->IsAnySubresourceLocked()) + pResource->ClearDirtyBoxes(); + } + + // Toss our staging buffer if we're not dynamic + // and we aren't managed (for sysmem copy.) + bool shouldToss = pResource->GetMapMode() == D3D9_COMMON_TEXTURE_MAP_MODE_BACKED; + shouldToss &= !pResource->IsDynamic(); + shouldToss &= !pResource->IsManaged() || m_d3d9Options.evictManagedOnUnlock; + + if (shouldToss) { + pResource->DestroyBufferSubresource(Subresource); + pResource->SetNeedsReadback(Subresource, true); + } + + return D3D_OK; + } + + + HRESULT D3D9DeviceEx::FlushImage( + D3D9CommonTexture* pResource, + UINT Subresource) { + + const Rc image = pResource->GetImage(); + auto formatInfo = imageFormatInfo(image->info().format); + auto subresource = pResource->GetSubresourceFromIndex( + formatInfo->aspectMask, Subresource); + + const D3DBOX& box = pResource->GetDirtyBox(subresource.arrayLayer); + + VkExtent3D mip0Extent = { box.Right - box.Left, box.Bottom - box.Top, box.Back - box.Front }; + VkExtent3D extent = util::computeMipLevelExtent(mip0Extent, subresource.mipLevel); + VkOffset3D mip0Offset = { int32_t(box.Left), int32_t(box.Top), int32_t(box.Front) }; + VkOffset3D offset = util::computeMipLevelOffset(mip0Offset, subresource.mipLevel); + + UpdateTextureFromBuffer(pResource, pResource, Subresource, Subresource, offset, extent, offset); + + if (pResource->IsAutomaticMip()) + MarkTextureMipsDirty(pResource); + + return D3D_OK; + } + + void D3D9DeviceEx::UpdateTextureFromBuffer( + D3D9CommonTexture* pDestTexture, + D3D9CommonTexture* pSrcTexture, + UINT DestSubresource, + UINT SrcSubresource, + VkOffset3D SrcOffset, + VkExtent3D SrcExtent, + VkOffset3D DestOffset + ) { + const Rc image = pDestTexture->GetImage(); + + // Now that data has been written into the buffer, + // we need to copy its contents into the image + const DxvkBufferSliceHandle srcSlice = pSrcTexture->GetMappedSlice(SrcSubresource); + + auto formatInfo = imageFormatInfo(image->info().format); + auto srcSubresource = pSrcTexture->GetSubresourceFromIndex( + formatInfo->aspectMask, SrcSubresource); + + auto dstSubresource = pDestTexture->GetSubresourceFromIndex( + formatInfo->aspectMask, DestSubresource); + VkImageSubresourceLayers dstLayers = { dstSubresource.aspectMask, dstSubresource.mipLevel, dstSubresource.arrayLayer, 1 }; + + VkExtent3D dstTexLevelExtent = image->mipLevelExtent(dstSubresource.mipLevel); + VkExtent3D srcTexLevelExtent = util::computeMipLevelExtent(pSrcTexture->GetExtent(), srcSubresource.mipLevel); + VkExtent3D srcTexLevelExtentBlockCount = util::computeBlockCount(srcTexLevelExtent, formatInfo->blockSize); + + auto convertFormat = pDestTexture->GetFormatMapping().ConversionFormatInfo; + + if (likely(convertFormat.FormatType == D3D9ConversionFormat_None)) { + VkOffset3D alignedDestOffset = { + int32_t(alignDown(DestOffset.x, formatInfo->blockSize.width)), + int32_t(alignDown(DestOffset.y, formatInfo->blockSize.height)), + int32_t(alignDown(DestOffset.z, formatInfo->blockSize.depth)) + }; + VkOffset3D alignedSrcOffset = { + int32_t(alignDown(SrcOffset.x, formatInfo->blockSize.width)), + int32_t(alignDown(SrcOffset.y, formatInfo->blockSize.height)), + int32_t(alignDown(SrcOffset.z, formatInfo->blockSize.depth)) + }; + SrcExtent.width += SrcOffset.x - alignedSrcOffset.x; + SrcExtent.height += SrcOffset.y - alignedSrcOffset.y; + SrcExtent.depth += SrcOffset.z - alignedSrcOffset.z; + VkExtent3D extentBlockCount = util::computeBlockCount(SrcExtent, formatInfo->blockSize); + VkExtent3D alignedExtent = util::computeBlockExtent(extentBlockCount, formatInfo->blockSize); + + alignedExtent = util::snapExtent3D(alignedDestOffset, alignedExtent, dstTexLevelExtent); + alignedExtent = util::snapExtent3D(alignedSrcOffset, alignedExtent, srcTexLevelExtent); + + VkOffset3D srcOffsetBlockCount = util::computeBlockOffset(alignedSrcOffset, formatInfo->blockSize); + VkExtent3D srcTexLevelExtentBlockCount = util::computeBlockCount(srcTexLevelExtent, formatInfo->blockSize); + VkDeviceSize pitch = align(srcTexLevelExtentBlockCount.width * formatInfo->elementSize, 4); + VkDeviceSize copySrcOffset = srcOffsetBlockCount.z * srcTexLevelExtentBlockCount.height * pitch + + srcOffsetBlockCount.y * pitch + + srcOffsetBlockCount.x * formatInfo->elementSize; + + VkDeviceSize sliceAlignment = 1; + VkDeviceSize rowAlignment = 1; + DxvkBufferSlice copySrcSlice; + if (pSrcTexture->DoesStagingBufferUploads(SrcSubresource)) { + VkDeviceSize dirtySize = extentBlockCount.width * extentBlockCount.height * extentBlockCount.depth * formatInfo->elementSize; + D3D9BufferSlice slice = AllocTempBuffer(dirtySize); + copySrcSlice = slice.slice; + void* srcData = reinterpret_cast(srcSlice.mapPtr) + copySrcOffset; + util::packImageData( + slice.mapPtr, srcData, extentBlockCount, formatInfo->elementSize, + pitch, pitch * srcTexLevelExtentBlockCount.height); + } else { + copySrcSlice = DxvkBufferSlice(pSrcTexture->GetBuffer(SrcSubresource), copySrcOffset, srcSlice.length); + // row/slice alignment can act as the pitch parameter + rowAlignment = pitch; + sliceAlignment = srcTexLevelExtentBlockCount.height * pitch; + } + + EmitCs([ + cSrcSlice = std::move(copySrcSlice), + cDstImage = image, + cDstLayers = dstLayers, + cDstLevelExtent = alignedExtent, + cOffset = alignedDestOffset, + cRowAlignment = rowAlignment, + cSliceAlignment = sliceAlignment + ] (DxvkContext* ctx) { + ctx->copyBufferToImage( + cDstImage, cDstLayers, + cOffset, cDstLevelExtent, + cSrcSlice.buffer(), cSrcSlice.offset(), + cRowAlignment, cSliceAlignment); + }); + + TrackTextureMappingBufferSequenceNumber(pSrcTexture, SrcSubresource); + } + else { + const DxvkFormatInfo* formatInfo = imageFormatInfo(pDestTexture->GetFormatMapping().FormatColor); + + // Add more blocks for the other planes that we might have. + // TODO: PLEASE CLEAN ME + srcTexLevelExtentBlockCount.height *= std::min(convertFormat.PlaneCount, 2u); + + if (unlikely(SrcOffset.x != 0 || SrcOffset.y != 0 || SrcOffset.z != 0 + || DestOffset.x != 0 || DestOffset.y != 0 || DestOffset.z != 0 + || SrcExtent != srcTexLevelExtent)) { + Logger::warn("Offset and rect not supported with the texture converter."); + } + + if (unlikely(srcTexLevelExtent != dstTexLevelExtent)) { + Logger::err("Different extents are not supported with the texture converter."); + return; + } + + // the converter can not handle the 4 aligned pitch so we always repack into a staging buffer + D3D9BufferSlice slice = AllocTempBuffer(srcSlice.length); + VkDeviceSize pitch = align(srcTexLevelExtentBlockCount.width * formatInfo->elementSize, 4); + + util::packImageData( + slice.mapPtr, srcSlice.mapPtr, srcTexLevelExtentBlockCount, formatInfo->elementSize, + pitch, std::min(convertFormat.PlaneCount, 2u) * pitch * srcTexLevelExtentBlockCount.height); + + Flush(); + SynchronizeCsThread(DxvkCsThread::SynchronizeAll); + + m_converter->ConvertFormat( + convertFormat, + image, dstLayers, + slice.slice); + } + } + + void D3D9DeviceEx::EmitGenerateMips( + D3D9CommonTexture* pResource) { + if (pResource->IsManaged()) + UploadManagedTexture(pResource); + + EmitCs([ + cImageView = pResource->GetSampleView(false), + cFilter = pResource->GetMipFilter() + ] (DxvkContext* ctx) { + ctx->generateMipmaps(cImageView, DecodeFilter(cFilter)); + }); + } + + + HRESULT D3D9DeviceEx::LockBuffer( + D3D9CommonBuffer* pResource, + UINT OffsetToLock, + UINT SizeToLock, + void** ppbData, + DWORD Flags) { + D3D9DeviceLock lock = LockDevice(); + + if (unlikely(ppbData == nullptr)) + return D3DERR_INVALIDCALL; + + if (!m_d3d9Options.allowDiscard) + Flags &= ~D3DLOCK_DISCARD; + + auto& desc = *pResource->Desc(); + + // Ignore DISCARD if NOOVERWRITE is set + if (unlikely((Flags & (D3DLOCK_DISCARD | D3DLOCK_NOOVERWRITE)) == (D3DLOCK_DISCARD | D3DLOCK_NOOVERWRITE))) + Flags &= ~D3DLOCK_DISCARD; + + // Ignore DISCARD and NOOVERWRITE if the buffer is not DEFAULT pool (tests + Halo 2) + // The docs say DISCARD and NOOVERWRITE are ignored if the buffer is not DYNAMIC + // but tests say otherwise! + if (desc.Pool != D3DPOOL_DEFAULT) + Flags &= ~(D3DLOCK_DISCARD | D3DLOCK_NOOVERWRITE); + + // Ignore DONOTWAIT if we are DYNAMIC + // Yes... D3D9 is a good API. + if (desc.Usage & D3DUSAGE_DYNAMIC) + Flags &= ~D3DLOCK_DONOTWAIT; + + // We only bounds check for MANAGED. + // (TODO: Apparently this is meant to happen for DYNAMIC too but I am not sure + // how that works given it is meant to be a DIRECT access..?) + const bool respectUserBounds = !(Flags & D3DLOCK_DISCARD) && + SizeToLock != 0; + + // If we don't respect the bounds, encompass it all in our tests/checks + // These values may be out of range and don't get clamped. + uint32_t offset = respectUserBounds ? OffsetToLock : 0; + uint32_t size = respectUserBounds ? std::min(SizeToLock, desc.Size - offset) : desc.Size; + D3D9Range lockRange = D3D9Range(offset, offset + size); + + if ((desc.Pool == D3DPOOL_DEFAULT || !(Flags & D3DLOCK_NO_DIRTY_UPDATE)) && !(Flags & D3DLOCK_READONLY)) + pResource->DirtyRange().Conjoin(lockRange); + + Rc mappingBuffer = pResource->GetBuffer(); + + DxvkBufferSliceHandle physSlice; + + if (Flags & D3DLOCK_DISCARD) { + // Allocate a new backing slice for the buffer and set + // it as the 'new' mapped slice. This assumes that the + // only way to invalidate a buffer is by mapping it. + physSlice = pResource->DiscardMapSlice(); + + EmitCs([ + cBuffer = std::move(mappingBuffer), + cBufferSlice = physSlice + ] (DxvkContext* ctx) { + ctx->invalidateBuffer(cBuffer, cBufferSlice); + }); + + pResource->SetNeedsReadback(false); + pResource->GPUReadingRange().Clear(); + } + else { + // Use map pointer from previous map operation. This + // way we don't have to synchronize with the CS thread + // if the map mode is D3DLOCK_NOOVERWRITE. + physSlice = pResource->GetMappedSlice(); + + // NOOVERWRITE promises that they will not write in a currently used area. + // Therefore we can skip waiting for these two cases. + // We can also skip waiting if there is not dirty range overlap, if we are one of those resources. + + // If we are respecting the bounds ie. (MANAGED) we can test overlap + // of our bounds, otherwise we just ignore this and go for it all the time. + const bool needsReadback = pResource->NeedsReadback(); + const bool readOnly = Flags & D3DLOCK_READONLY; + const bool noOverlap = !pResource->GPUReadingRange().Overlaps(lockRange); + const bool noOverwrite = Flags & D3DLOCK_NOOVERWRITE; + const bool usesStagingBuffer = pResource->DoesStagingBufferUploads(); + const bool directMapping = pResource->GetMapMode() == D3D9_COMMON_BUFFER_MAP_MODE_DIRECT; + const bool skipWait = (!needsReadback && (usesStagingBuffer || readOnly || (noOverlap && !directMapping))) || noOverwrite; + if (!skipWait) { + if (unlikely(needsReadback)) { + Logger::warn("Buffer readback is unimplemented."); + // Remember to update the sequence number when implementing buffer readback. + } else if (!(Flags & D3DLOCK_DONOTWAIT) && !WaitForResource(mappingBuffer, pResource->GetMappingBufferSequenceNumber(), D3DLOCK_DONOTWAIT)) + pResource->EnableStagingBufferUploads(); + + if (!WaitForResource(mappingBuffer, pResource->GetMappingBufferSequenceNumber(), Flags)) + return D3DERR_WASSTILLDRAWING; + + pResource->SetNeedsReadback(false); + pResource->GPUReadingRange().Clear(); + } + } + + uint8_t* data = reinterpret_cast(physSlice.mapPtr); + // The offset/size is not clamped to or affected by the desc size. + data += OffsetToLock; + + *ppbData = reinterpret_cast(data); + + DWORD oldFlags = pResource->GetMapFlags(); + + // We need to remove the READONLY flags from the map flags + // if there was ever a non-readonly upload. + if (!(Flags & D3DLOCK_READONLY)) + oldFlags &= ~D3DLOCK_READONLY; + + pResource->SetMapFlags(Flags | oldFlags); + pResource->IncrementLockCount(); + + return D3D_OK; + } + + + HRESULT D3D9DeviceEx::FlushBuffer( + D3D9CommonBuffer* pResource) { + auto dstBuffer = pResource->GetBufferSlice(); + auto srcSlice = pResource->GetMappedSlice(); + + D3D9Range& range = pResource->DirtyRange(); + + DxvkBufferSlice copySrcSlice; + if (pResource->DoesStagingBufferUploads()) { + D3D9BufferSlice slice = AllocTempBuffer(range.max - range.min); + copySrcSlice = slice.slice; + void* srcData = reinterpret_cast(srcSlice.mapPtr) + range.min; + memcpy(slice.mapPtr, srcData, range.max - range.min); + } else { + copySrcSlice = DxvkBufferSlice(pResource->GetBuffer(), range.min, range.max - range.min); + } + + EmitCs([ + cDstSlice = dstBuffer, + cSrcSlice = copySrcSlice, + cDstOffset = range.min, + cLength = range.max - range.min + ] (DxvkContext* ctx) { + ctx->copyBuffer( + cDstSlice.buffer(), + cDstSlice.offset() + cDstOffset, + cSrcSlice.buffer(), + cSrcSlice.offset(), + cLength); + }); + + pResource->GPUReadingRange().Conjoin(pResource->DirtyRange()); + pResource->DirtyRange().Clear(); + TrackBufferMappingBufferSequenceNumber(pResource); + + return D3D_OK; + } + + + HRESULT D3D9DeviceEx::UnlockBuffer( + D3D9CommonBuffer* pResource) { + D3D9DeviceLock lock = LockDevice(); + + if (pResource->DecrementLockCount() != 0) + return D3D_OK; + + if (pResource->GetMapMode() != D3D9_COMMON_BUFFER_MAP_MODE_BUFFER) + return D3D_OK; + + if (pResource->DirtyRange().IsDegenerate()) + return D3D_OK; + + pResource->SetMapFlags(0); + + if (pResource->Desc()->Pool != D3DPOOL_DEFAULT) + return D3D_OK; + + FlushImplicit(FALSE); + + FlushBuffer(pResource); + + return D3D_OK; + } + + + void D3D9DeviceEx::EmitCsChunk(DxvkCsChunkRef&& chunk) { + m_csSeqNum = m_csThread.dispatchChunk(std::move(chunk)); + m_csIsBusy = true; + } + + + void D3D9DeviceEx::FlushImplicit(BOOL StrongHint) { + // Flush only if the GPU is about to go idle, in + // order to keep the number of submissions low. + uint32_t pending = m_dxvkDevice->pendingSubmissions(); + + if (StrongHint || pending <= MaxPendingSubmits) { + auto now = dxvk::high_resolution_clock::now(); + + uint32_t delay = MinFlushIntervalUs + + IncFlushIntervalUs * pending; + + // Prevent flushing too often in short intervals. + if (now - m_lastFlush >= std::chrono::microseconds(delay)) + Flush(); + } + } + + + void D3D9DeviceEx::SynchronizeCsThread(uint64_t SequenceNumber) { + D3D9DeviceLock lock = LockDevice(); + + // Dispatch current chunk so that all commands + // recorded prior to this function will be run + FlushCsChunk(); + + m_csThread.synchronize(SequenceNumber); + } + + + void D3D9DeviceEx::SetupFPU() { + // Should match d3d9 float behaviour. + +#if defined(_MSC_VER) + // For MSVC we can use these cross arch and platform funcs to set the FPU. + // This will work on any platform, x86, x64, ARM, etc. + + // Clear exceptions. + _clearfp(); + + // Disable exceptions + _controlfp(_MCW_EM, _MCW_EM); + +#ifndef _WIN64 + // Use 24 bit precision + _controlfp(_PC_24, _MCW_PC); +#endif + + // Round to nearest + _controlfp(_RC_NEAR, _MCW_RC); +#elif (defined(__GNUC__) || defined(__MINGW32__)) && (defined(__i386__) || defined(__x86_64__) || defined(__ia64)) + // For GCC/MinGW we can use inline asm to set it. + // This only works for x86 and x64 processors however. + + uint16_t control; + + // Get current control word. + __asm__ __volatile__("fnstcw %0" : "=m" (*&control)); + + // Clear existing settings. + control &= 0xF0C0; + + // Disable exceptions + // Use 24 bit precision + // Round to nearest + control |= 0x003F; + + // Set new control word. + __asm__ __volatile__("fldcw %0" : : "m" (*&control)); +#else + Logger::warn("D3D9DeviceEx::SetupFPU: not supported on this arch."); +#endif + } + + + int64_t D3D9DeviceEx::DetermineInitialTextureMemory() { + auto memoryProp = m_adapter->GetDXVKAdapter()->memoryProperties(); + + VkDeviceSize availableTextureMemory = 0; + + for (uint32_t i = 0; i < memoryProp.memoryHeapCount; i++) + availableTextureMemory += memoryProp.memoryHeaps[i].size; + + constexpr VkDeviceSize Megabytes = 1024 * 1024; + + // The value returned is a 32-bit value, so we need to clamp it. + VkDeviceSize maxMemory = (VkDeviceSize(m_d3d9Options.maxAvailableMemory) * Megabytes) - 1; + availableTextureMemory = std::min(availableTextureMemory, maxMemory); + + return int64_t(availableTextureMemory); + } + + + Rc D3D9DeviceEx::CreateConstantBuffer( + bool SSBO, + VkDeviceSize Size, + DxsoProgramType ShaderStage, + DxsoConstantBuffers BufferType) { + DxvkBufferCreateInfo info = { }; + info.usage = SSBO ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; + info.access = SSBO ? VK_ACCESS_SHADER_READ_BIT : VK_ACCESS_UNIFORM_READ_BIT; + info.size = Size; + info.stages = ShaderStage == DxsoProgramType::VertexShader + ? VK_PIPELINE_STAGE_VERTEX_SHADER_BIT + : VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + + VkMemoryPropertyFlags memoryFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT + | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + + if (m_d3d9Options.deviceLocalConstantBuffers) + memoryFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + + Rc buffer = m_dxvkDevice->createBuffer(info, memoryFlags); + + const uint32_t slotId = computeResourceSlotId( + ShaderStage, DxsoBindingType::ConstantBuffer, + BufferType); + + EmitCs([ + cSlotId = slotId, + cBuffer = buffer + ] (DxvkContext* ctx) { + ctx->bindResourceBuffer(cSlotId, + DxvkBufferSlice(cBuffer, 0, cBuffer->info().size)); + }); + + if (ShaderStage == DxsoProgramType::PixelShader) + m_boundPSConstantsBufferSize = buffer->info().size; + else + m_boundVSConstantsBufferSize = buffer->info().size; + + return buffer; + } + + + void D3D9DeviceEx::CreateConstantBuffers() { + if (!m_isSWVP) { + m_consts[DxsoProgramTypes::VertexShader].buffer = + CreateConstantBuffer(false, + m_vsLayout.totalSize(), + DxsoProgramType::VertexShader, + DxsoConstantBuffers::VSConstantBuffer); + } + // SWVP constant buffers are created late based on the amount of constants set by the application + m_consts[DxsoProgramTypes::PixelShader].buffer = + CreateConstantBuffer(false, + m_psLayout.totalSize(), + DxsoProgramType::PixelShader, + DxsoConstantBuffers::PSConstantBuffer); + + m_vsClipPlanes = + CreateConstantBuffer(false, + caps::MaxClipPlanes * sizeof(D3D9ClipPlane), + DxsoProgramType::VertexShader, + DxsoConstantBuffers::VSClipPlanes); + + m_vsFixedFunction = + CreateConstantBuffer(false, + sizeof(D3D9FixedFunctionVS), + DxsoProgramType::VertexShader, + DxsoConstantBuffers::VSFixedFunction); + + m_psFixedFunction = + CreateConstantBuffer(false, + sizeof(D3D9FixedFunctionPS), + DxsoProgramType::PixelShader, + DxsoConstantBuffers::PSFixedFunction); + + m_psShared = + CreateConstantBuffer(false, + sizeof(D3D9SharedPS), + DxsoProgramType::PixelShader, + DxsoConstantBuffers::PSShared); + + m_vsVertexBlend = + CreateConstantBuffer(true, + CanSWVP() + ? sizeof(D3D9FixedFunctionVertexBlendDataSW) + : sizeof(D3D9FixedFunctionVertexBlendDataHW), + DxsoProgramType::VertexShader, + DxsoConstantBuffers::VSVertexBlendData); + } + + + inline void D3D9DeviceEx::UploadSoftwareConstantSet(const D3D9ShaderConstantsVSSoftware& Src, const D3D9ConstantLayout& Layout) { + /* + * SWVP raises the amount of constants by a lot. + * To avoid copying huge amounts of data for every draw call, + * we track the highest set constant and only use a buffer big enough + * to fit that. We rely on robustness to return 0 for OOB reads. + */ + + D3D9ConstantSets& constSet = m_consts[DxsoProgramType::VertexShader]; + + if (!constSet.dirty) + return; + + constSet.dirty = false; + + uint32_t floatCount = m_vsFloatConstsCount; + if (constSet.meta.needsConstantCopies) { + auto shader = GetCommonShader(m_state.vertexShader); + floatCount = std::max(floatCount, shader->GetMaxDefinedConstant()); + } + floatCount = std::min(floatCount, constSet.meta.maxConstIndexF); + + const uint32_t floatDataSize = floatCount * sizeof(Vector4); + const uint32_t intDataSize = std::min(constSet.meta.maxConstIndexI, m_vsIntConstsCount) * sizeof(Vector4i); + const uint32_t boolDataSize = divCeil(std::min(constSet.meta.maxConstIndexB, m_vsBoolConstsCount), 32u) * uint32_t(sizeof(uint32_t)); + + Rc& floatBuffer = constSet.swvpBuffers.floatBuffer; + // Max copy source size is 8192 * 16 => always aligned to any plausible value + // => we won't copy out of bounds + if (likely(constSet.meta.maxConstIndexF != 0 || floatBuffer == nullptr)) { + DxvkBufferSliceHandle floatBufferSlice = CopySoftwareConstants(DxsoConstantBuffers::VSFloatConstantBuffer, floatBuffer, Src.fConsts, floatDataSize, m_dxsoOptions.vertexFloatConstantBufferAsSSBO); + + if (constSet.meta.needsConstantCopies) { + Vector4* data = reinterpret_cast(floatBufferSlice.mapPtr); + + auto& shaderConsts = GetCommonShader(m_state.vertexShader)->GetConstants(); + + for (const auto& constant : shaderConsts) { + if (constant.uboIdx < constSet.meta.maxConstIndexF) + data[constant.uboIdx] = *reinterpret_cast(constant.float32); + } + } + } + + Rc& intBuffer = constSet.swvpBuffers.intBuffer; + // Max copy source size is 2048 * 16 => always aligned to any plausible value + // => we won't copy out of bounds + if (likely(constSet.meta.maxConstIndexI != 0 || intBuffer == nullptr)) { + CopySoftwareConstants(DxsoConstantBuffers::VSIntConstantBuffer, intBuffer, Src.iConsts, intDataSize, false); + } + + Rc& boolBuffer = constSet.swvpBuffers.boolBuffer; + if (likely(constSet.meta.maxConstIndexB != 0 || boolBuffer == nullptr)) { + CopySoftwareConstants(DxsoConstantBuffers::VSBoolConstantBuffer, boolBuffer, Src.bConsts, boolDataSize, false); + } + } + + + inline DxvkBufferSliceHandle D3D9DeviceEx::CopySoftwareConstants(DxsoConstantBuffers cBufferTarget, Rc& dstBuffer, const void* src, uint32_t size, bool useSSBO) { + uint32_t alignment = useSSBO ? m_robustSSBOAlignment : m_robustUBOAlignment; + alignment = std::max(alignment, 64u); + size = std::max(size, alignment); + size = align(size, alignment); + + DxvkBufferSliceHandle slice; + if (unlikely(dstBuffer == nullptr || dstBuffer->info().size < size)) { + dstBuffer = CreateConstantBuffer(useSSBO, size, DxsoProgramType::VertexShader, cBufferTarget); + slice = dstBuffer->getSliceHandle(); + } else { + slice = dstBuffer->allocSlice(); + EmitCs([ + cBuffer = dstBuffer, + cSlice = slice + ] (DxvkContext* ctx) { + ctx->invalidateBuffer(cBuffer, cSlice); + }); + } + + std::memcpy(slice.mapPtr, src, size); + return slice; + } + + + template + inline void D3D9DeviceEx::UploadConstantSet(const SoftwareLayoutType& Src, const D3D9ConstantLayout& Layout, const ShaderType& Shader) { + /* + * We just copy the float constants that have been set by the application and rely on robustness + * to return 0 on OOB reads. + */ + D3D9ConstantSets& constSet = m_consts[ShaderStage]; + + if (!constSet.dirty) + return; + + constSet.dirty = false; + + uint32_t floatCount = ShaderStage == DxsoProgramType::VertexShader ? m_vsFloatConstsCount : m_psFloatConstsCount; + if (constSet.meta.needsConstantCopies) { + auto shader = GetCommonShader(Shader); + floatCount = std::max(floatCount, shader->GetMaxDefinedConstant()); + } + floatCount = std::min(constSet.meta.maxConstIndexF, floatCount); + + const uint32_t intRange = caps::MaxOtherConstants * sizeof(Vector4i); + const uint32_t intDataSize = constSet.meta.maxConstIndexI * sizeof(Vector4i); + uint32_t floatDataSize = floatCount * sizeof(Vector4); + const uint32_t alignment = std::max(m_robustUBOAlignment, 64u); // Make sure we do not recreate the buffer because the new one has to be a tiny bit larger + const uint32_t bufferSize = align(std::max(floatDataSize + intRange, alignment), alignment); + floatDataSize = bufferSize - intRange; // Read additional floats for padding so we don't end up with garbage data + + VkDeviceSize& boundConstantBufferSize = ShaderStage == DxsoProgramType::VertexShader ? m_boundVSConstantsBufferSize : m_boundPSConstantsBufferSize; + if (boundConstantBufferSize < bufferSize) { + constexpr uint32_t slotId = computeResourceSlotId(ShaderStage, DxsoBindingType::ConstantBuffer, 0); + EmitCs([ + cBuffer = constSet.buffer, + cSlotId = slotId, + cSize = bufferSize + ] (DxvkContext* ctx) { + ctx->bindResourceBuffer(cSlotId, + DxvkBufferSlice(cBuffer, 0, cSize)); + }); + boundConstantBufferSize = bufferSize; + } + + DxvkBufferSliceHandle slice = constSet.buffer->allocSlice(); + + EmitCs([ + cBuffer = constSet.buffer, + cSlice = slice + ] (DxvkContext* ctx) { + ctx->invalidateBuffer(cBuffer, cSlice); + }); + + auto* dst = reinterpret_cast(slice.mapPtr); + + if (constSet.meta.maxConstIndexI != 0) + std::memcpy(dst->iConsts, Src.iConsts, intDataSize); + if (constSet.meta.maxConstIndexF != 0) + std::memcpy(dst->fConsts, Src.fConsts, floatDataSize); + + if (constSet.meta.needsConstantCopies) { + Vector4* data = reinterpret_cast(dst->fConsts); + + auto& shaderConsts = GetCommonShader(Shader)->GetConstants(); + + for (const auto& constant : shaderConsts) { + if (constant.uboIdx < constSet.meta.maxConstIndexF) + data[constant.uboIdx] = *reinterpret_cast(constant.float32); + } + } + } + + + template + void D3D9DeviceEx::UploadConstants() { + if constexpr (ShaderStage == DxsoProgramTypes::VertexShader) { + if (CanSWVP()) + return UploadSoftwareConstantSet(m_state.vsConsts, m_vsLayout); + else + return UploadConstantSet(m_state.vsConsts, m_vsLayout, m_state.vertexShader); + } else { + return UploadConstantSet (m_state.psConsts, m_psLayout, m_state.pixelShader); + } + } + + + void D3D9DeviceEx::UpdateClipPlanes() { + m_flags.clr(D3D9DeviceFlag::DirtyClipPlanes); + + auto slice = m_vsClipPlanes->allocSlice(); + auto dst = reinterpret_cast(slice.mapPtr); + + for (uint32_t i = 0; i < caps::MaxClipPlanes; i++) { + dst[i] = (m_state.renderStates[D3DRS_CLIPPLANEENABLE] & (1 << i)) + ? m_state.clipPlanes[i] + : D3D9ClipPlane(); + } + + EmitCs([ + cBuffer = m_vsClipPlanes, + cSlice = slice + ] (DxvkContext* ctx) { + ctx->invalidateBuffer(cBuffer, cSlice); + }); + } + + + template + void D3D9DeviceEx::UpdatePushConstant(const void* pData) { + struct ConstantData { uint8_t Data[Length]; }; + + auto* constData = reinterpret_cast(pData); + + EmitCs([ + cData = *constData + ](DxvkContext* ctx) { + ctx->pushConstants(Offset, Length, &cData); + }); + } + + + template + void D3D9DeviceEx::UpdatePushConstant() { + auto& rs = m_state.renderStates; + + if constexpr (Item == D3D9RenderStateItem::AlphaRef) { + float alpha = float(rs[D3DRS_ALPHAREF] & 0xFF) / 255.0f; + UpdatePushConstant(&alpha); + } + else if constexpr (Item == D3D9RenderStateItem::FogColor) { + Vector4 color; + DecodeD3DCOLOR(D3DCOLOR(rs[D3DRS_FOGCOLOR]), color.data); + UpdatePushConstant(&color); + } + else if constexpr (Item == D3D9RenderStateItem::FogDensity) { + float density = bit::cast(rs[D3DRS_FOGDENSITY]); + UpdatePushConstant(&density); + } + else if constexpr (Item == D3D9RenderStateItem::FogEnd) { + float end = bit::cast(rs[D3DRS_FOGEND]); + UpdatePushConstant(&end); + } + else if constexpr (Item == D3D9RenderStateItem::FogScale) { + float end = bit::cast(rs[D3DRS_FOGEND]); + float start = bit::cast(rs[D3DRS_FOGSTART]); + + float scale = 1.0f / (end - start); + UpdatePushConstant(&scale); + } + else if constexpr (Item == D3D9RenderStateItem::PointSize) { + UpdatePushConstant(&rs[D3DRS_POINTSIZE]); + } + else if constexpr (Item == D3D9RenderStateItem::PointSizeMin) { + UpdatePushConstant(&rs[D3DRS_POINTSIZE_MIN]); + } + else if constexpr (Item == D3D9RenderStateItem::PointSizeMax) { + UpdatePushConstant(&rs[D3DRS_POINTSIZE_MAX]); + } + else if constexpr (Item == D3D9RenderStateItem::PointScaleA) { + float scale = bit::cast(rs[D3DRS_POINTSCALE_A]); + scale /= float(m_state.viewport.Height * m_state.viewport.Height); + + UpdatePushConstant(&scale); + } + else if constexpr (Item == D3D9RenderStateItem::PointScaleB) { + float scale = bit::cast(rs[D3DRS_POINTSCALE_B]); + scale /= float(m_state.viewport.Height * m_state.viewport.Height); + + UpdatePushConstant(&scale); + } + else if constexpr (Item == D3D9RenderStateItem::PointScaleC) { + float scale = bit::cast(rs[D3DRS_POINTSCALE_C]); + scale /= float(m_state.viewport.Height * m_state.viewport.Height); + + UpdatePushConstant(&scale); + } + else + Logger::warn("D3D9: Invalid push constant set to update."); + } + + + + void D3D9DeviceEx::Flush() { + D3D9DeviceLock lock = LockDevice(); + + m_initializer->Flush(); + m_converter->Flush(); + + if (m_csIsBusy || !m_csChunk->empty()) { + // Add commands to flush the threaded + // context, then flush the command list + EmitCs([](DxvkContext* ctx) { + ctx->flushCommandList(); + }); + + FlushCsChunk(); + + // Reset flush timer used for implicit flushes + m_lastFlush = dxvk::high_resolution_clock::now(); + m_csIsBusy = false; + } + } + + + inline void D3D9DeviceEx::UpdateBoundRTs(uint32_t index) { + const uint32_t bit = 1 << index; + + m_boundRTs &= ~bit; + + if (m_state.renderTargets[index] != nullptr && + !m_state.renderTargets[index]->IsNull()) + m_boundRTs |= bit; + } + + + inline void D3D9DeviceEx::UpdateActiveRTs(uint32_t index) { + const uint32_t bit = 1 << index; + + m_activeRTs &= ~bit; + + if ((m_boundRTs & bit) != 0 && + m_state.renderTargets[index]->GetBaseTexture() != nullptr && + m_state.renderStates[ColorWriteIndex(index)]) + m_activeRTs |= bit; + + UpdateActiveHazardsRT(bit); + } + + + inline void D3D9DeviceEx::UpdateActiveTextures(uint32_t index, DWORD combinedUsage) { + const uint32_t bit = 1 << index; + + m_activeRTTextures &= ~bit; + m_activeDSTextures &= ~bit; + m_activeTextures &= ~bit; + m_activeTexturesToUpload &= ~bit; + m_activeTexturesToGen &= ~bit; + + auto tex = GetCommonTexture(m_state.textures[index]); + if (tex != nullptr) { + m_activeTextures |= bit; + + if (unlikely(tex->IsRenderTarget())) + m_activeRTTextures |= bit; + + if (unlikely(tex->IsDepthStencil())) + m_activeDSTextures |= bit; + + if (unlikely(tex->NeedsAnyUpload())) + m_activeTexturesToUpload |= bit; + + if (unlikely(tex->NeedsMipGen())) + m_activeTexturesToGen |= bit; + } + + if (unlikely(combinedUsage & D3DUSAGE_RENDERTARGET)) + UpdateActiveHazardsRT(UINT32_MAX); + + if (unlikely(combinedUsage & D3DUSAGE_DEPTHSTENCIL)) + UpdateActiveHazardsDS(bit); + } + + + inline void D3D9DeviceEx::UpdateActiveHazardsRT(uint32_t rtMask) { + auto masks = m_psShaderMasks; + masks.rtMask &= m_activeRTs & rtMask; + masks.samplerMask &= m_activeRTTextures; + + m_activeHazardsRT = m_activeHazardsRT & (~rtMask); + for (uint32_t rtIdx : bit::BitMask(masks.rtMask)) { + for (uint32_t samplerIdx : bit::BitMask(masks.samplerMask)) { + D3D9Surface* rtSurf = m_state.renderTargets[rtIdx].ptr(); + + IDirect3DBaseTexture9* rtBase = rtSurf->GetBaseTexture(); + IDirect3DBaseTexture9* texBase = m_state.textures[samplerIdx]; + + // HACK: Don't mark for hazards if we aren't rendering to mip 0! + // Some games use screenspace passes like this for blurring + // Sampling from mip 0 (texture) -> mip 1 (rt) + // and we'd trigger the hazard path otherwise which is unnecessary, + // and would shove us into GENERAL and emitting readback barriers. + if (likely(rtSurf->GetMipLevel() != 0 || rtBase != texBase)) + continue; + + m_activeHazardsRT |= 1 << rtIdx; + } + } + } + + + inline void D3D9DeviceEx::UpdateActiveHazardsDS(uint32_t texMask) { + m_activeHazardsDS = m_activeHazardsDS & (~texMask); + if (m_state.depthStencil != nullptr && + m_state.depthStencil->GetBaseTexture() != nullptr) { + uint32_t samplerMask = m_activeDSTextures & texMask; + for (uint32_t samplerIdx : bit::BitMask(samplerMask)) { + IDirect3DBaseTexture9* dsBase = m_state.depthStencil->GetBaseTexture(); + IDirect3DBaseTexture9* texBase = m_state.textures[samplerIdx]; + + if (likely(dsBase != texBase)) + continue; + + m_activeHazardsDS |= 1 << samplerIdx; + } + } + } + + + void D3D9DeviceEx::MarkRenderHazards() { + for (uint32_t rtIdx : bit::BitMask(m_activeHazardsRT)) { + // Guaranteed to not be nullptr... + auto tex = m_state.renderTargets[rtIdx]->GetCommonTexture(); + if (unlikely(!tex->MarkHazardous())) { + TransitionImage(tex, VK_IMAGE_LAYOUT_GENERAL); + m_flags.set(D3D9DeviceFlag::DirtyFramebuffer); + } + } + } + + + void D3D9DeviceEx::UploadManagedTexture(D3D9CommonTexture* pResource) { + for (uint32_t subresource = 0; subresource < pResource->CountSubresources(); subresource++) { + if (!pResource->NeedsUpload(subresource) || pResource->GetBuffer(subresource) == nullptr) + continue; + + this->FlushImage(pResource, subresource); + } + + pResource->ClearDirtyBoxes(); + pResource->ClearNeedsUpload(); + } + + + void D3D9DeviceEx::UploadManagedTextures(uint32_t mask) { + // Guaranteed to not be nullptr... + for (uint32_t texIdx : bit::BitMask(mask)) + UploadManagedTexture(GetCommonTexture(m_state.textures[texIdx])); + + m_activeTexturesToUpload &= ~mask; + } + + + void D3D9DeviceEx::GenerateTextureMips(uint32_t mask) { + for (uint32_t texIdx : bit::BitMask(mask)) { + // Guaranteed to not be nullptr... + auto texInfo = GetCommonTexture(m_state.textures[texIdx]); + + if (texInfo->NeedsMipGen()) { + this->EmitGenerateMips(texInfo); + texInfo->SetNeedsMipGen(false); + } + } + + m_activeTexturesToGen &= ~mask; + } + + + void D3D9DeviceEx::MarkTextureMipsDirty(D3D9CommonTexture* pResource) { + pResource->SetNeedsMipGen(true); + pResource->MarkAllNeedReadback(); + + for (uint32_t i : bit::BitMask(m_activeTextures)) { + // Guaranteed to not be nullptr... + auto texInfo = GetCommonTexture(m_state.textures[i]); + + if (texInfo == pResource) { + m_activeTexturesToGen |= 1 << i; + // We can early out here, no need to add another index for this. + break; + } + } + } + + + void D3D9DeviceEx::MarkTextureMipsUnDirty(D3D9CommonTexture* pResource) { + pResource->SetNeedsMipGen(false); + + for (uint32_t i : bit::BitMask(m_activeTextures)) { + // Guaranteed to not be nullptr... + auto texInfo = GetCommonTexture(m_state.textures[i]); + + if (texInfo == pResource) + m_activeTexturesToGen &= ~(1 << i); + } + } + + + void D3D9DeviceEx::MarkTextureUploaded(D3D9CommonTexture* pResource) { + for (uint32_t i : bit::BitMask(m_activeTextures)) { + // Guaranteed to not be nullptr... + auto texInfo = GetCommonTexture(m_state.textures[i]); + + if (texInfo == pResource) + m_activeTexturesToUpload &= ~(1 << i); + } + } + + + template + void D3D9DeviceEx::UpdatePointMode() { + if constexpr (!Points) { + m_lastPointMode = 0; + + EmitCs([](DxvkContext* ctx) { + ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, D3D9SpecConstantId::PointMode, 0); + }); + } + else { + auto& rs = m_state.renderStates; + + const bool scale = rs[D3DRS_POINTSCALEENABLE] && !UseProgrammableVS(); + const bool sprite = rs[D3DRS_POINTSPRITEENABLE]; + + const uint32_t scaleBit = scale ? 1u : 0u; + const uint32_t spriteBit = sprite ? 2u : 0u; + + uint32_t mode = scaleBit | spriteBit; + + if (rs[D3DRS_POINTSCALEENABLE] && m_flags.test(D3D9DeviceFlag::DirtyPointScale)) { + m_flags.clr(D3D9DeviceFlag::DirtyPointScale); + + UpdatePushConstant(); + UpdatePushConstant(); + UpdatePushConstant(); + } + + if (unlikely(mode != m_lastPointMode)) { + EmitCs([cMode = mode] (DxvkContext* ctx) { + ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, D3D9SpecConstantId::PointMode, cMode); + }); + + m_lastPointMode = mode; + } + } + } + + + void D3D9DeviceEx::UpdateFog() { + auto& rs = m_state.renderStates; + + bool fogEnabled = rs[D3DRS_FOGENABLE]; + + bool pixelFog = rs[D3DRS_FOGTABLEMODE] != D3DFOG_NONE && fogEnabled; + bool vertexFog = rs[D3DRS_FOGVERTEXMODE] != D3DFOG_NONE && fogEnabled && !pixelFog; + + auto UpdateFogConstants = [&](D3DFOGMODE FogMode) { + if (m_flags.test(D3D9DeviceFlag::DirtyFogColor)) { + m_flags.clr(D3D9DeviceFlag::DirtyFogColor); + UpdatePushConstant(); + } + + if (FogMode == D3DFOG_LINEAR) { + if (m_flags.test(D3D9DeviceFlag::DirtyFogScale)) { + m_flags.clr(D3D9DeviceFlag::DirtyFogScale); + UpdatePushConstant(); + } + + if (m_flags.test(D3D9DeviceFlag::DirtyFogEnd)) { + m_flags.clr(D3D9DeviceFlag::DirtyFogEnd); + UpdatePushConstant(); + } + } + else if (FogMode == D3DFOG_EXP || FogMode == D3DFOG_EXP2) { + if (m_flags.test(D3D9DeviceFlag::DirtyFogDensity)) { + m_flags.clr(D3D9DeviceFlag::DirtyFogDensity); + UpdatePushConstant(); + } + } + }; + + if (vertexFog) { + D3DFOGMODE mode = D3DFOGMODE(rs[D3DRS_FOGVERTEXMODE]); + + UpdateFogConstants(mode); + + if (m_flags.test(D3D9DeviceFlag::DirtyFogState)) { + m_flags.clr(D3D9DeviceFlag::DirtyFogState); + + EmitCs([cMode = mode] (DxvkContext* ctx) { + ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, D3D9SpecConstantId::FogEnabled, true); + ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, D3D9SpecConstantId::VertexFogMode, cMode); + ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, D3D9SpecConstantId::PixelFogMode, D3DFOG_NONE); + }); + } + } + else if (pixelFog) { + D3DFOGMODE mode = D3DFOGMODE(rs[D3DRS_FOGTABLEMODE]); + + UpdateFogConstants(mode); + + if (m_flags.test(D3D9DeviceFlag::DirtyFogState)) { + m_flags.clr(D3D9DeviceFlag::DirtyFogState); + + EmitCs([cMode = mode] (DxvkContext* ctx) { + ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, D3D9SpecConstantId::FogEnabled, true); + ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, D3D9SpecConstantId::VertexFogMode, D3DFOG_NONE); + ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, D3D9SpecConstantId::PixelFogMode, cMode); + }); + } + } + else { + if (fogEnabled) + UpdateFogConstants(D3DFOG_NONE); + + if (m_flags.test(D3D9DeviceFlag::DirtyFogState)) { + m_flags.clr(D3D9DeviceFlag::DirtyFogState); + + EmitCs([cEnabled = fogEnabled] (DxvkContext* ctx) { + ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, D3D9SpecConstantId::FogEnabled, cEnabled); + ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, D3D9SpecConstantId::VertexFogMode, D3DFOG_NONE); + ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, D3D9SpecConstantId::PixelFogMode, D3DFOG_NONE); + }); + } + } + } + + + void D3D9DeviceEx::BindFramebuffer() { + m_flags.clr(D3D9DeviceFlag::DirtyFramebuffer); + + DxvkRenderTargets attachments; + + bool srgb = m_state.renderStates[D3DRS_SRGBWRITEENABLE]; + + // D3D9 doesn't have the concept of a framebuffer object, + // so we'll just create a new one every time the render + // target bindings are updated. Set up the attachments. + VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_FLAG_BITS_MAX_ENUM; + + for (uint32_t i : bit::BitMask(m_boundRTs)) { + const DxvkImageCreateInfo& rtImageInfo = m_state.renderTargets[i]->GetCommonTexture()->GetImage()->info(); + + if (likely(sampleCount == VK_SAMPLE_COUNT_FLAG_BITS_MAX_ENUM)) + sampleCount = rtImageInfo.sampleCount; + else if (unlikely(sampleCount != rtImageInfo.sampleCount)) + continue; + + if (!m_state.renderStates[ColorWriteIndex(i)]) + continue; + + attachments.color[i] = { + m_state.renderTargets[i]->GetRenderTargetView(srgb), + m_state.renderTargets[i]->GetRenderTargetLayout() }; + } + + if (m_state.depthStencil != nullptr && + (m_state.renderStates[D3DRS_ZENABLE] + || m_state.renderStates[D3DRS_ZWRITEENABLE] + || m_state.renderStates[D3DRS_STENCILENABLE])) { + const DxvkImageCreateInfo& dsImageInfo = m_state.depthStencil->GetCommonTexture()->GetImage()->info(); + const bool depthWrite = m_state.renderStates[D3DRS_ZWRITEENABLE]; + + if (likely(sampleCount == VK_SAMPLE_COUNT_FLAG_BITS_MAX_ENUM || sampleCount == dsImageInfo.sampleCount)) { + attachments.depth = { + m_state.depthStencil->GetDepthStencilView(), + m_state.depthStencil->GetDepthStencilLayout(depthWrite, m_activeHazardsDS != 0) }; + } + } + + // Create and bind the framebuffer object to the context + EmitCs([ + cAttachments = std::move(attachments) + ] (DxvkContext* ctx) { + ctx->bindRenderTargets(cAttachments); + }); + } + + + void D3D9DeviceEx::BindViewportAndScissor() { + m_flags.clr(D3D9DeviceFlag::DirtyViewportScissor); + + VkViewport viewport; + VkRect2D scissor; + + // D3D9's coordinate system has its origin in the bottom left, + // but the viewport coordinates are aligned to the top-left + // corner so we can get away with flipping the viewport. + const D3DVIEWPORT9& vp = m_state.viewport; + + // Correctness Factor for 1/2 texel offset + // We need to bias this slightly to make + // imprecision in games happy. + // Originally we did this only for powers of two + // resolutions but since NEAREST filtering fixed to + // truncate, we need to do this all the time now. + float cf = 0.5f - (1.0f / 128.0f); + + viewport = VkViewport{ + float(vp.X) + cf, float(vp.Height + vp.Y) + cf, + float(vp.Width), -float(vp.Height), + vp.MinZ, vp.MaxZ, + }; + + // Scissor rectangles. Vulkan does not provide an easy way + // to disable the scissor test, so we'll have to set scissor + // rects that are at least as large as the framebuffer. + bool enableScissorTest = m_state.renderStates[D3DRS_SCISSORTESTENABLE]; + + if (enableScissorTest) { + RECT sr = m_state.scissorRect; + + VkOffset2D srPosA; + srPosA.x = std::max(0, sr.left); + srPosA.x = std::max(vp.X, srPosA.x); + srPosA.y = std::max(0, sr.top); + srPosA.y = std::max(vp.Y, srPosA.y); + + VkOffset2D srPosB; + srPosB.x = std::max(srPosA.x, sr.right); + srPosB.x = std::min(vp.X + vp.Width, srPosB.x); + srPosB.y = std::max(srPosA.y, sr.bottom); + srPosB.y = std::min(vp.Y + vp.Height, srPosB.y); + + VkExtent2D srSize; + srSize.width = uint32_t(srPosB.x - srPosA.x); + srSize.height = uint32_t(srPosB.y - srPosA.y); + + scissor = VkRect2D{ srPosA, srSize }; + } + else { + scissor = VkRect2D{ + VkOffset2D { int32_t(vp.X), int32_t(vp.Y) }, + VkExtent2D { vp.Width, vp.Height }}; + } + + EmitCs([ + cViewport = viewport, + cScissor = scissor + ] (DxvkContext* ctx) { + ctx->setViewports( + 1, + &cViewport, + &cScissor); + }); + } + + + void D3D9DeviceEx::BindMultiSampleState() { + m_flags.clr(D3D9DeviceFlag::DirtyMultiSampleState); + + DxvkMultisampleState msState; + msState.sampleMask = m_flags.test(D3D9DeviceFlag::ValidSampleMask) + ? m_state.renderStates[D3DRS_MULTISAMPLEMASK] + : 0xffffffff; + msState.enableAlphaToCoverage = IsAlphaToCoverageEnabled(); + + EmitCs([ + cState = msState + ] (DxvkContext* ctx) { + ctx->setMultisampleState(cState); + }); + } + + + void D3D9DeviceEx::BindBlendState() { + m_flags.clr(D3D9DeviceFlag::DirtyBlendState); + + auto& state = m_state.renderStates; + + bool separateAlpha = state[D3DRS_SEPARATEALPHABLENDENABLE]; + + DxvkBlendMode mode; + mode.enableBlending = state[D3DRS_ALPHABLENDENABLE] != FALSE; + + D3D9BlendState color, alpha; + + color.Src = D3DBLEND(state[D3DRS_SRCBLEND]); + color.Dst = D3DBLEND(state[D3DRS_DESTBLEND]); + color.Op = D3DBLENDOP(state[D3DRS_BLENDOP]); + FixupBlendState(color); + + if (separateAlpha) { + alpha.Src = D3DBLEND(state[D3DRS_SRCBLENDALPHA]); + alpha.Dst = D3DBLEND(state[D3DRS_DESTBLENDALPHA]); + alpha.Op = D3DBLENDOP(state[D3DRS_BLENDOPALPHA]); + FixupBlendState(alpha); + } + else + alpha = color; + + mode.colorSrcFactor = DecodeBlendFactor(color.Src, false); + mode.colorDstFactor = DecodeBlendFactor(color.Dst, false); + mode.colorBlendOp = DecodeBlendOp (color.Op); + + mode.alphaSrcFactor = DecodeBlendFactor(alpha.Src, true); + mode.alphaDstFactor = DecodeBlendFactor(alpha.Dst, true); + mode.alphaBlendOp = DecodeBlendOp (alpha.Op); + + mode.writeMask = state[ColorWriteIndex(0)]; + + std::array extraWriteMasks; + for (uint32_t i = 0; i < 3; i++) + extraWriteMasks[i] = state[ColorWriteIndex(i + 1)]; + + EmitCs([ + cMode = mode, + cWriteMasks = extraWriteMasks, + cAlphaMasks = m_alphaSwizzleRTs + ](DxvkContext* ctx) { + for (uint32_t i = 0; i < 4; i++) { + DxvkBlendMode mode = cMode; + if (i != 0) + mode.writeMask = cWriteMasks[i - 1]; + + const bool alphaSwizzle = cAlphaMasks & (1 << i); + + auto NormalizeFactor = [alphaSwizzle](VkBlendFactor Factor) { + if (alphaSwizzle) { + if (Factor == VK_BLEND_FACTOR_DST_ALPHA) + return VK_BLEND_FACTOR_ONE; + else if (Factor == VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA) + return VK_BLEND_FACTOR_ZERO; + } + + return Factor; + }; + + mode.colorSrcFactor = NormalizeFactor(mode.colorSrcFactor); + mode.colorDstFactor = NormalizeFactor(mode.colorDstFactor); + mode.alphaSrcFactor = NormalizeFactor(mode.alphaSrcFactor); + mode.alphaDstFactor = NormalizeFactor(mode.alphaDstFactor); + + ctx->setBlendMode(i, mode); + } + }); + } + + + void D3D9DeviceEx::BindBlendFactor() { + DxvkBlendConstants blendConstants; + DecodeD3DCOLOR( + D3DCOLOR(m_state.renderStates[D3DRS_BLENDFACTOR]), + reinterpret_cast(&blendConstants)); + + EmitCs([ + cBlendConstants = blendConstants + ](DxvkContext* ctx) { + ctx->setBlendConstants(cBlendConstants); + }); + } + + + void D3D9DeviceEx::BindDepthStencilState() { + m_flags.clr(D3D9DeviceFlag::DirtyDepthStencilState); + + auto& rs = m_state.renderStates; + + bool stencil = rs[D3DRS_STENCILENABLE]; + bool twoSidedStencil = stencil && rs[D3DRS_TWOSIDEDSTENCILMODE]; + + DxvkDepthStencilState state; + state.enableDepthTest = rs[D3DRS_ZENABLE] != FALSE; + state.enableDepthWrite = rs[D3DRS_ZWRITEENABLE] != FALSE; + state.enableStencilTest = stencil; + state.depthCompareOp = DecodeCompareOp(D3DCMPFUNC(rs[D3DRS_ZFUNC])); + + if (stencil) { + state.stencilOpFront.failOp = DecodeStencilOp(D3DSTENCILOP(rs[D3DRS_STENCILFAIL])); + state.stencilOpFront.passOp = DecodeStencilOp(D3DSTENCILOP(rs[D3DRS_STENCILPASS])); + state.stencilOpFront.depthFailOp = DecodeStencilOp(D3DSTENCILOP(rs[D3DRS_STENCILZFAIL])); + state.stencilOpFront.compareOp = DecodeCompareOp(D3DCMPFUNC (rs[D3DRS_STENCILFUNC])); + state.stencilOpFront.compareMask = uint32_t(rs[D3DRS_STENCILMASK]); + state.stencilOpFront.writeMask = uint32_t(rs[D3DRS_STENCILWRITEMASK]); + state.stencilOpFront.reference = 0; + } + else + state.stencilOpFront = VkStencilOpState(); + + if (twoSidedStencil) { + state.stencilOpBack.failOp = DecodeStencilOp(D3DSTENCILOP(rs[D3DRS_CCW_STENCILFAIL])); + state.stencilOpBack.passOp = DecodeStencilOp(D3DSTENCILOP(rs[D3DRS_CCW_STENCILPASS])); + state.stencilOpBack.depthFailOp = DecodeStencilOp(D3DSTENCILOP(rs[D3DRS_CCW_STENCILZFAIL])); + state.stencilOpBack.compareOp = DecodeCompareOp(D3DCMPFUNC (rs[D3DRS_CCW_STENCILFUNC])); + state.stencilOpBack.compareMask = state.stencilOpFront.compareMask; + state.stencilOpBack.writeMask = state.stencilOpFront.writeMask; + state.stencilOpBack.reference = 0; + } + else + state.stencilOpBack = state.stencilOpFront; + + EmitCs([ + cState = state + ](DxvkContext* ctx) { + ctx->setDepthStencilState(cState); + }); + } + + + void D3D9DeviceEx::BindRasterizerState() { + m_flags.clr(D3D9DeviceFlag::DirtyRasterizerState); + + auto& rs = m_state.renderStates; + + DxvkRasterizerState state; + state.cullMode = DecodeCullMode(D3DCULL(rs[D3DRS_CULLMODE])); + state.depthBiasEnable = IsDepthBiasEnabled(); + state.depthClipEnable = true; + state.frontFace = VK_FRONT_FACE_CLOCKWISE; + state.polygonMode = DecodeFillMode(D3DFILLMODE(rs[D3DRS_FILLMODE])); + state.conservativeMode = VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT; + state.sampleCount = 0; + + EmitCs([ + cState = state + ](DxvkContext* ctx) { + ctx->setRasterizerState(cState); + }); + } + + + void D3D9DeviceEx::BindDepthBias() { + m_flags.clr(D3D9DeviceFlag::DirtyDepthBias); + + auto& rs = m_state.renderStates; + + float depthBias = bit::cast(rs[D3DRS_DEPTHBIAS]) * m_depthBiasScale; + float slopeScaledDepthBias = bit::cast(rs[D3DRS_SLOPESCALEDEPTHBIAS]); + + DxvkDepthBias biases; + biases.depthBiasConstant = depthBias; + biases.depthBiasSlope = slopeScaledDepthBias; + biases.depthBiasClamp = 0.0f; + + EmitCs([ + cBiases = biases + ](DxvkContext* ctx) { + ctx->setDepthBias(cBiases); + }); + } + + + void D3D9DeviceEx::BindAlphaTestState() { + m_flags.clr(D3D9DeviceFlag::DirtyAlphaTestState); + + auto& rs = m_state.renderStates; + + VkCompareOp alphaOp = IsAlphaTestEnabled() + ? DecodeCompareOp(D3DCMPFUNC(rs[D3DRS_ALPHAFUNC])) + : VK_COMPARE_OP_ALWAYS; + + EmitCs([cAlphaOp = alphaOp] (DxvkContext* ctx) { + ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, D3D9SpecConstantId::AlphaCompareOp, cAlphaOp); + }); + } + + + void D3D9DeviceEx::BindDepthStencilRefrence() { + auto& rs = m_state.renderStates; + + uint32_t ref = uint32_t(rs[D3DRS_STENCILREF]) & 0xff; + + EmitCs([cRef = ref] (DxvkContext* ctx) { + ctx->setStencilReference(cRef); + }); + } + + + void D3D9DeviceEx::BindSampler(DWORD Sampler) { + auto& state = m_state.samplerStates[Sampler]; + + D3D9SamplerKey key; + key.AddressU = D3DTEXTUREADDRESS(state[D3DSAMP_ADDRESSU]); + key.AddressV = D3DTEXTUREADDRESS(state[D3DSAMP_ADDRESSV]); + key.AddressW = D3DTEXTUREADDRESS(state[D3DSAMP_ADDRESSW]); + key.MagFilter = D3DTEXTUREFILTERTYPE(state[D3DSAMP_MAGFILTER]); + key.MinFilter = D3DTEXTUREFILTERTYPE(state[D3DSAMP_MINFILTER]); + key.MipFilter = D3DTEXTUREFILTERTYPE(state[D3DSAMP_MIPFILTER]); + key.MaxAnisotropy = state[D3DSAMP_MAXANISOTROPY]; + key.MipmapLodBias = bit::cast(state[D3DSAMP_MIPMAPLODBIAS]); + key.MaxMipLevel = state[D3DSAMP_MAXMIPLEVEL]; + key.BorderColor = D3DCOLOR(state[D3DSAMP_BORDERCOLOR]); + key.Depth = m_depthTextures & (1u << Sampler); + + if (m_d3d9Options.samplerAnisotropy != -1) { + if (key.MagFilter == D3DTEXF_LINEAR) + key.MagFilter = D3DTEXF_ANISOTROPIC; + + if (key.MinFilter == D3DTEXF_LINEAR) + key.MinFilter = D3DTEXF_ANISOTROPIC; + + key.MaxAnisotropy = m_d3d9Options.samplerAnisotropy; + } + + NormalizeSamplerKey(key); + + auto samplerInfo = RemapStateSamplerShader(Sampler); + + const uint32_t slot = computeResourceSlotId( + samplerInfo.first, DxsoBindingType::Image, + samplerInfo.second); + + EmitCs([this, + cSlot = slot, + cKey = key + ] (DxvkContext* ctx) { + auto pair = m_samplers.find(cKey); + if (pair != m_samplers.end()) { + ctx->bindResourceSampler(cSlot, pair->second); + return; + } + + auto mipFilter = DecodeMipFilter(cKey.MipFilter); + + DxvkSamplerCreateInfo info; + info.addressModeU = DecodeAddressMode(cKey.AddressU); + info.addressModeV = DecodeAddressMode(cKey.AddressV); + info.addressModeW = DecodeAddressMode(cKey.AddressW); + info.compareToDepth = cKey.Depth; + info.compareOp = cKey.Depth ? VK_COMPARE_OP_LESS_OR_EQUAL : VK_COMPARE_OP_NEVER; + info.magFilter = DecodeFilter(cKey.MagFilter); + info.minFilter = DecodeFilter(cKey.MinFilter); + info.mipmapMode = mipFilter.MipFilter; + info.maxAnisotropy = float(cKey.MaxAnisotropy); + info.useAnisotropy = cKey.MaxAnisotropy > 1; + info.mipmapLodBias = cKey.MipmapLodBias; + info.mipmapLodMin = mipFilter.MipsEnabled ? float(cKey.MaxMipLevel) : 0; + info.mipmapLodMax = mipFilter.MipsEnabled ? FLT_MAX : 0; + info.usePixelCoord = VK_FALSE; + info.nonSeamless = m_dxvkDevice->features().extNonSeamlessCubeMap.nonSeamlessCubeMap && !m_d3d9Options.seamlessCubes; + + DecodeD3DCOLOR(cKey.BorderColor, info.borderColor.float32); + + if (!m_dxvkDevice->features().extCustomBorderColor.customBorderColorWithoutFormat) { + // HACK: Let's get OPAQUE_WHITE border color over + // TRANSPARENT_BLACK if the border RGB is white. + if (info.borderColor.float32[0] == 1.0f + && info.borderColor.float32[1] == 1.0f + && info.borderColor.float32[2] == 1.0f + && !m_dxvkDevice->features().extCustomBorderColor.customBorderColors) { + // Then set the alpha to 1. + info.borderColor.float32[3] = 1.0f; + } + } + + try { + auto sampler = m_dxvkDevice->createSampler(info); + + m_samplers.insert(std::make_pair(cKey, sampler)); + ctx->bindResourceSampler(cSlot, std::move(sampler)); + + m_samplerCount++; + } + catch (const DxvkError& e) { + Logger::err(e.message()); + } + }); + } + + + void D3D9DeviceEx::BindTexture(DWORD StateSampler) { + auto shaderSampler = RemapStateSamplerShader(StateSampler); + + uint32_t slot = computeResourceSlotId(shaderSampler.first, + DxsoBindingType::Image, uint32_t(shaderSampler.second)); + + const bool srgb = + m_state.samplerStates[StateSampler][D3DSAMP_SRGBTEXTURE] & 0x1; + + D3D9CommonTexture* commonTex = + GetCommonTexture(m_state.textures[StateSampler]); + + EmitCs([ + cSlot = slot, + cImageView = commonTex->GetSampleView(srgb) + ](DxvkContext* ctx) { + ctx->bindResourceView(cSlot, cImageView, nullptr); + }); + } + + + void D3D9DeviceEx::UnbindTextures(uint32_t mask) { + EmitCs([ + cMask = mask + ](DxvkContext* ctx) { + for (uint32_t i : bit::BitMask(cMask)) { + auto shaderSampler = RemapStateSamplerShader(i); + + uint32_t slot = computeResourceSlotId(shaderSampler.first, + DxsoBindingType::Image, uint32_t(shaderSampler.second)); + + ctx->bindResourceView(slot, nullptr, nullptr); + } + }); + } + + + void D3D9DeviceEx::UndirtySamplers(uint32_t mask) { + for (uint32_t i : bit::BitMask(mask)) + BindSampler(i); + + m_dirtySamplerStates &= ~mask; + } + + + void D3D9DeviceEx::UndirtyTextures(uint32_t usedMask) { + const uint32_t activeMask = usedMask & m_activeTextures; + const uint32_t inactiveMask = usedMask & ~m_activeTextures; + + for (uint32_t i : bit::BitMask(activeMask)) + BindTexture(i); + + if (inactiveMask) + UnbindTextures(inactiveMask); + + m_dirtyTextures &= ~usedMask; + } + + void D3D9DeviceEx::MarkTextureBindingDirty(IDirect3DBaseTexture9* texture) { + D3D9DeviceLock lock = LockDevice(); + + for (uint32_t i : bit::BitMask(m_activeTextures)) { + if (m_state.textures[i] == texture) + m_dirtyTextures |= 1u << i; + } + } + + + D3D9DrawInfo D3D9DeviceEx::GenerateDrawInfo( + D3DPRIMITIVETYPE PrimitiveType, + UINT PrimitiveCount, + UINT InstanceCount) { + D3D9DrawInfo drawInfo; + drawInfo.vertexCount = GetVertexCount(PrimitiveType, PrimitiveCount); + drawInfo.instanceCount = m_iaState.streamsInstanced & m_iaState.streamsUsed + ? InstanceCount + : 1u; + return drawInfo; + } + + + uint32_t D3D9DeviceEx::GetInstanceCount() const { + return std::max(m_state.streamFreq[0] & 0x7FFFFFu, 1u); + } + + + void D3D9DeviceEx::PrepareDraw(D3DPRIMITIVETYPE PrimitiveType) { + if (unlikely(m_activeHazardsRT != 0)) { + EmitCs([](DxvkContext* ctx) { + ctx->emitRenderTargetReadbackBarrier(); + }); + + if (m_d3d9Options.generalHazards) + MarkRenderHazards(); + } + + if (unlikely((m_lastHazardsDS == 0) != (m_activeHazardsDS == 0))) { + m_flags.set(D3D9DeviceFlag::DirtyFramebuffer); + m_lastHazardsDS = m_activeHazardsDS; + } + + for (uint32_t i = 0; i < caps::MaxStreams; i++) { + auto* vbo = GetCommonBuffer(m_state.vertexBuffers[i].vertexBuffer); + if (vbo != nullptr && vbo->NeedsUpload()) + FlushBuffer(vbo); + } + + const uint32_t usedSamplerMask = m_psShaderMasks.samplerMask | m_vsShaderMasks.samplerMask; + const uint32_t usedTextureMask = m_activeTextures & usedSamplerMask; + + const uint32_t texturesToUpload = m_activeTexturesToUpload & usedTextureMask; + if (unlikely(texturesToUpload != 0)) + UploadManagedTextures(texturesToUpload); + + const uint32_t texturesToGen = m_activeTexturesToGen & usedTextureMask; + if (unlikely(texturesToGen != 0)) + GenerateTextureMips(texturesToGen); + + auto* ibo = GetCommonBuffer(m_state.indices); + if (ibo != nullptr && ibo->NeedsUpload()) + FlushBuffer(ibo); + + UpdateFog(); + + if (m_flags.test(D3D9DeviceFlag::DirtyFramebuffer)) + BindFramebuffer(); + + if (m_flags.test(D3D9DeviceFlag::DirtyViewportScissor)) + BindViewportAndScissor(); + + const uint32_t activeDirtySamplers = m_dirtySamplerStates & usedTextureMask; + if (activeDirtySamplers) + UndirtySamplers(activeDirtySamplers); + + const uint32_t usedDirtyTextures = m_dirtyTextures & usedSamplerMask; + if (usedDirtyTextures) + UndirtyTextures(usedDirtyTextures); + + if (m_flags.test(D3D9DeviceFlag::DirtyBlendState)) + BindBlendState(); + + if (m_flags.test(D3D9DeviceFlag::DirtyDepthStencilState)) + BindDepthStencilState(); + + if (m_flags.test(D3D9DeviceFlag::DirtyRasterizerState)) + BindRasterizerState(); + + if (m_flags.test(D3D9DeviceFlag::DirtyDepthBias)) + BindDepthBias(); + + if (m_flags.test(D3D9DeviceFlag::DirtyMultiSampleState)) + BindMultiSampleState(); + + if (m_flags.test(D3D9DeviceFlag::DirtyAlphaTestState)) + BindAlphaTestState(); + + if (m_flags.test(D3D9DeviceFlag::DirtyClipPlanes)) + UpdateClipPlanes(); + + if (PrimitiveType == D3DPT_POINTLIST) + UpdatePointMode(); + else if (m_lastPointMode != 0) + UpdatePointMode(); + + if (likely(UseProgrammableVS())) { + if (unlikely(m_flags.test(D3D9DeviceFlag::DirtyProgVertexShader))) { + m_flags.set(D3D9DeviceFlag::DirtyInputLayout); + + BindShader( + GetCommonShader(m_state.vertexShader), + GetVertexShaderPermutation()); + } + UploadConstants(); + + if (likely(!CanSWVP())) { + UpdateBoolSpecConstantVertex( + m_state.vsConsts.bConsts[0] & + m_consts[DxsoProgramType::VertexShader].meta.boolConstantMask); + } else + UpdateBoolSpecConstantVertex(0); + } + else { + UpdateBoolSpecConstantVertex(0); + UpdateFixedFunctionVS(); + } + + if (m_flags.test(D3D9DeviceFlag::DirtyInputLayout)) + BindInputLayout(); + + auto UpdateSamplerTypes = [&](uint32_t types, uint32_t projections, uint32_t fetch4) { + if (m_lastSamplerTypes != types) + UpdateSamplerSpecConsant(types); + + if (m_lastProjectionBitfield != projections) + UpdateProjectionSpecConstant(projections); + + if (m_lastFetch4 != fetch4) + UpdateFetch4SpecConstant(fetch4); + }; + + if (likely(UseProgrammablePS())) { + UploadConstants(); + + const uint32_t psTextureMask = usedTextureMask & ((1u << caps::MaxTexturesPS) - 1u); + const uint32_t fetch4 = m_fetch4 & psTextureMask; + const uint32_t projected = m_projectionBitfield & psTextureMask; + + const auto& programInfo = GetCommonShader(m_state.pixelShader)->GetInfo(); + + if (programInfo.majorVersion() >= 2) + UpdateSamplerTypes(m_d3d9Options.forceSamplerTypeSpecConstants ? m_textureTypes : 0u, 0u, fetch4); + else + UpdateSamplerTypes(m_textureTypes, programInfo.minorVersion() >= 4 ? 0u : projected, fetch4); // For implicit samplers... + + UpdateBoolSpecConstantPixel( + m_state.psConsts.bConsts[0] & + m_consts[DxsoProgramType::PixelShader].meta.boolConstantMask); + } + else { + UpdateBoolSpecConstantPixel(0); + UpdateSamplerTypes(0u, 0u, 0u); + + UpdateFixedFunctionPS(); + } + + const uint32_t depthTextureMask = m_depthTextures & usedTextureMask; + if (depthTextureMask != m_lastSamplerDepthMode) + UpdateSamplerDepthModeSpecConstant(depthTextureMask); + + if (m_flags.test(D3D9DeviceFlag::DirtySharedPixelShaderData)) { + m_flags.clr(D3D9DeviceFlag::DirtySharedPixelShaderData); + + DxvkBufferSliceHandle slice = m_psShared->allocSlice(); + + EmitCs([ + cBuffer = m_psShared, + cSlice = slice + ] (DxvkContext* ctx) { + ctx->invalidateBuffer(cBuffer, cSlice); + }); + + D3D9SharedPS* data = reinterpret_cast(slice.mapPtr); + + for (uint32_t i = 0; i < caps::TextureStageCount; i++) { + DecodeD3DCOLOR(D3DCOLOR(m_state.textureStages[i][DXVK_TSS_CONSTANT]), data->Stages[i].Constant); + + // Flip major-ness so we can get away with a nice easy + // dot in the shader without complex access + data->Stages[i].BumpEnvMat[0][0] = bit::cast(m_state.textureStages[i][DXVK_TSS_BUMPENVMAT00]); + data->Stages[i].BumpEnvMat[1][0] = bit::cast(m_state.textureStages[i][DXVK_TSS_BUMPENVMAT01]); + data->Stages[i].BumpEnvMat[0][1] = bit::cast(m_state.textureStages[i][DXVK_TSS_BUMPENVMAT10]); + data->Stages[i].BumpEnvMat[1][1] = bit::cast(m_state.textureStages[i][DXVK_TSS_BUMPENVMAT11]); + + data->Stages[i].BumpEnvLScale = bit::cast(m_state.textureStages[i][DXVK_TSS_BUMPENVLSCALE]); + data->Stages[i].BumpEnvLOffset = bit::cast(m_state.textureStages[i][DXVK_TSS_BUMPENVLOFFSET]); + } + } + + if (m_flags.test(D3D9DeviceFlag::DirtyDepthBounds)) { + m_flags.clr(D3D9DeviceFlag::DirtyDepthBounds); + + DxvkDepthBounds db; + db.enableDepthBounds = (m_state.renderStates[D3DRS_ADAPTIVETESS_X] == uint32_t(D3D9Format::NVDB)); + db.minDepthBounds = bit::cast(m_state.renderStates[D3DRS_ADAPTIVETESS_Z]); + db.maxDepthBounds = bit::cast(m_state.renderStates[D3DRS_ADAPTIVETESS_W]); + + EmitCs([ + cDepthBounds = db + ] (DxvkContext* ctx) { + ctx->setDepthBounds(cDepthBounds); + }); + } + } + + + template + void D3D9DeviceEx::BindShader( + const D3D9CommonShader* pShaderModule, + D3D9ShaderPermutation Permutation) { + EmitCs([ + cShader = pShaderModule->GetShader(Permutation) + ] (DxvkContext* ctx) { + ctx->bindShader(GetShaderStage(ShaderStage), cShader); + }); + } + + + void D3D9DeviceEx::BindInputLayout() { + m_flags.clr(D3D9DeviceFlag::DirtyInputLayout); + + if (m_state.vertexDecl == nullptr) { + EmitCs([&cIaState = m_iaState] (DxvkContext* ctx) { + cIaState.streamsUsed = 0; + ctx->setInputLayout(0, nullptr, 0, nullptr); + }); + } + else { + std::array streamFreq; + + for (uint32_t i = 0; i < caps::MaxStreams; i++) + streamFreq[i] = m_state.streamFreq[i]; + + Com vertexDecl = m_state.vertexDecl; + Com vertexShader; + + if (UseProgrammableVS()) + vertexShader = m_state.vertexShader; + + EmitCs([ + &cIaState = m_iaState, + cVertexDecl = std::move(vertexDecl), + cVertexShader = std::move(vertexShader), + cStreamsInstanced = m_instancedData, + cStreamFreq = streamFreq + ] (DxvkContext* ctx) { + cIaState.streamsInstanced = cStreamsInstanced; + cIaState.streamsUsed = 0; + + const auto& elements = cVertexDecl->GetElements(); + + std::array attrList; + std::array bindList; + + uint32_t attrMask = 0; + uint32_t bindMask = 0; + + const auto& isgn = cVertexShader != nullptr + ? GetCommonShader(cVertexShader)->GetIsgn() + : GetFixedFunctionIsgn(); + + for (uint32_t i = 0; i < isgn.elemCount; i++) { + const auto& decl = isgn.elems[i]; + + DxvkVertexAttribute attrib; + attrib.location = i; + attrib.binding = NullStreamIdx; + attrib.format = VK_FORMAT_R32G32B32A32_SFLOAT; + attrib.offset = 0; + + for (const auto& element : elements) { + DxsoSemantic elementSemantic = { static_cast(element.Usage), element.UsageIndex }; + if (elementSemantic.usage == DxsoUsage::PositionT) + elementSemantic.usage = DxsoUsage::Position; + + if (elementSemantic == decl.semantic) { + attrib.binding = uint32_t(element.Stream); + attrib.format = DecodeDecltype(D3DDECLTYPE(element.Type)); + attrib.offset = element.Offset; + + cIaState.streamsUsed |= 1u << attrib.binding; + break; + } + } + + attrList[i] = attrib; + + DxvkVertexBinding binding; + binding.binding = attrib.binding; + + uint32_t instanceData = cStreamFreq[binding.binding % caps::MaxStreams]; + if (instanceData & D3DSTREAMSOURCE_INSTANCEDATA) { + binding.fetchRate = instanceData & 0x7FFFFF; // Remove instance packed-in flags in the data. + binding.inputRate = VK_VERTEX_INPUT_RATE_INSTANCE; + } + else { + binding.fetchRate = 0; + binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + } + + // Check if the binding was already defined. + bool bindingDefined = false; + + for (uint32_t j = 0; j < i; j++) { + uint32_t bindingId = attrList.at(j).binding; + + if (binding.binding == bindingId) { + bindingDefined = true; + } + } + + if (!bindingDefined) + bindList.at(binding.binding) = binding; + + attrMask |= 1u << i; + bindMask |= 1u << binding.binding; + } + + // Compact the attribute and binding lists to filter + // out attributes and bindings not used by the shader + uint32_t attrCount = CompactSparseList(attrList.data(), attrMask); + uint32_t bindCount = CompactSparseList(bindList.data(), bindMask); + + ctx->setInputLayout( + attrCount, attrList.data(), + bindCount, bindList.data()); + }); + } + } + + + void D3D9DeviceEx::BindVertexBuffer( + UINT Slot, + D3D9VertexBuffer* pBuffer, + UINT Offset, + UINT Stride) { + EmitCs([ + cSlotId = Slot, + cBufferSlice = pBuffer != nullptr ? + pBuffer->GetCommonBuffer()->GetBufferSlice(Offset) + : DxvkBufferSlice(), + cStride = pBuffer != nullptr ? Stride : 0 + ] (DxvkContext* ctx) { + ctx->bindVertexBuffer(cSlotId, cBufferSlice, cStride); + }); + } + + void D3D9DeviceEx::BindIndices() { + D3D9CommonBuffer* buffer = GetCommonBuffer(m_state.indices); + + D3D9Format format = buffer != nullptr + ? buffer->Desc()->Format + : D3D9Format::INDEX32; + + const VkIndexType indexType = DecodeIndexType(format); + + EmitCs([ + cBufferSlice = buffer != nullptr ? buffer->GetBufferSlice() : DxvkBufferSlice(), + cIndexType = indexType + ](DxvkContext* ctx) { + ctx->bindIndexBuffer(cBufferSlice, cIndexType); + }); + } + + + void D3D9DeviceEx::Begin(D3D9Query* pQuery) { + D3D9DeviceLock lock = LockDevice(); + + EmitCs([cQuery = Com(pQuery)](DxvkContext* ctx) { + cQuery->Begin(ctx); + }); + } + + + void D3D9DeviceEx::End(D3D9Query* pQuery) { + D3D9DeviceLock lock = LockDevice(); + + EmitCs([cQuery = Com(pQuery)](DxvkContext* ctx) { + cQuery->End(ctx); + }); + + pQuery->NotifyEnd(); + if (unlikely(pQuery->IsEvent())) { + pQuery->IsStalling() + ? Flush() + : FlushImplicit(TRUE); + } else if (pQuery->IsStalling()) { + FlushImplicit(FALSE); + } + } + + + void D3D9DeviceEx::SetVertexBoolBitfield(uint32_t idx, uint32_t mask, uint32_t bits) { + m_state.vsConsts.bConsts[idx] &= ~mask; + m_state.vsConsts.bConsts[idx] |= bits & mask; + + m_consts[DxsoProgramTypes::VertexShader].dirty = true; + } + + + void D3D9DeviceEx::SetPixelBoolBitfield(uint32_t idx, uint32_t mask, uint32_t bits) { + m_state.psConsts.bConsts[idx] &= ~mask; + m_state.psConsts.bConsts[idx] |= bits & mask; + + m_consts[DxsoProgramTypes::PixelShader].dirty = true; + } + + + HRESULT D3D9DeviceEx::CreateShaderModule( + D3D9CommonShader* pShaderModule, + VkShaderStageFlagBits ShaderStage, + const DWORD* pShaderBytecode, + const DxsoModuleInfo* pModuleInfo) { + try { + m_shaderModules->GetShaderModule(this, pShaderModule, + ShaderStage, pModuleInfo, pShaderBytecode); + + return D3D_OK; + } + catch (const DxvkError& e) { + Logger::err(e.message()); + return D3DERR_INVALIDCALL; + } + } + + + template < + DxsoProgramType ProgramType, + D3D9ConstantType ConstantType, + typename T> + HRESULT D3D9DeviceEx::SetShaderConstants( + UINT StartRegister, + const T* pConstantData, + UINT Count) { + const uint32_t regCountHardware = DetermineHardwareRegCount(); + constexpr uint32_t regCountSoftware = DetermineSoftwareRegCount(); + + if (unlikely(StartRegister + Count > regCountSoftware)) + return D3DERR_INVALIDCALL; + + Count = UINT( + std::max( + std::clamp(Count + StartRegister, 0, regCountHardware) - INT(StartRegister), + 0)); + + if (unlikely(Count == 0)) + return D3D_OK; + + if (unlikely(pConstantData == nullptr)) + return D3DERR_INVALIDCALL; + + if (unlikely(ShouldRecord())) + return m_recorder->SetShaderConstants( + StartRegister, + pConstantData, + Count); + + if constexpr (ProgramType == DxsoProgramType::VertexShader) { + if constexpr (ConstantType == D3D9ConstantType::Float) { + m_vsFloatConstsCount = std::max(m_vsFloatConstsCount, StartRegister + Count); + } else if constexpr (ConstantType == D3D9ConstantType::Int) { + m_vsIntConstsCount = std::max(m_vsIntConstsCount, StartRegister + Count); + } else /* if constexpr (ConstantType == D3D9ConstantType::Bool) */ { + m_vsBoolConstsCount = std::max(m_vsBoolConstsCount, StartRegister + Count); + } + } else { + if constexpr (ConstantType == D3D9ConstantType::Float) { + m_psFloatConstsCount = std::max(m_psFloatConstsCount, StartRegister + Count); + } + } + + if constexpr (ConstantType != D3D9ConstantType::Bool) { + uint32_t maxCount = ConstantType == D3D9ConstantType::Float + ? m_consts[ProgramType].meta.maxConstIndexF + : m_consts[ProgramType].meta.maxConstIndexI; + + m_consts[ProgramType].dirty |= StartRegister < maxCount; + } else if constexpr (ProgramType == DxsoProgramType::VertexShader) { + if (unlikely(CanSWVP())) { + m_consts[DxsoProgramType::VertexShader].dirty |= StartRegister < m_consts[ProgramType].meta.maxConstIndexB; + } + } + + UpdateStateConstants( + &m_state, + StartRegister, + pConstantData, + Count, + m_d3d9Options.d3d9FloatEmulation == D3D9FloatEmulation::Enabled); + + return D3D_OK; + } + + + void D3D9DeviceEx::UpdateFixedFunctionVS() { + // Shader... + bool hasPositionT = m_state.vertexDecl != nullptr ? m_state.vertexDecl->TestFlag(D3D9VertexDeclFlag::HasPositionT) : false; + bool hasBlendWeight = m_state.vertexDecl != nullptr ? m_state.vertexDecl->TestFlag(D3D9VertexDeclFlag::HasBlendWeight) : false; + bool hasBlendIndices = m_state.vertexDecl != nullptr ? m_state.vertexDecl->TestFlag(D3D9VertexDeclFlag::HasBlendIndices) : false; + + bool indexedVertexBlend = hasBlendIndices && m_state.renderStates[D3DRS_INDEXEDVERTEXBLENDENABLE]; + + D3D9FF_VertexBlendMode vertexBlendMode = D3D9FF_VertexBlendMode_Disabled; + + if (m_state.renderStates[D3DRS_VERTEXBLEND] != D3DVBF_DISABLE && !hasPositionT) { + vertexBlendMode = m_state.renderStates[D3DRS_VERTEXBLEND] == D3DVBF_TWEENING + ? D3D9FF_VertexBlendMode_Tween + : D3D9FF_VertexBlendMode_Normal; + + if (m_state.renderStates[D3DRS_VERTEXBLEND] != D3DVBF_0WEIGHTS) { + if (!hasBlendWeight) + vertexBlendMode = D3D9FF_VertexBlendMode_Disabled; + } + else if (!indexedVertexBlend) + vertexBlendMode = D3D9FF_VertexBlendMode_Disabled; + } + + if (unlikely(hasPositionT && m_state.vertexShader != nullptr && !m_flags.test(D3D9DeviceFlag::DirtyProgVertexShader))) { + m_flags.set(D3D9DeviceFlag::DirtyInputLayout); + m_flags.set(D3D9DeviceFlag::DirtyFFVertexShader); + m_flags.set(D3D9DeviceFlag::DirtyProgVertexShader); + } + + if (m_flags.test(D3D9DeviceFlag::DirtyFFVertexShader)) { + m_flags.clr(D3D9DeviceFlag::DirtyFFVertexShader); + + D3D9FFShaderKeyVS key; + key.Data.Contents.HasPositionT = hasPositionT; + key.Data.Contents.HasColor0 = m_state.vertexDecl != nullptr ? m_state.vertexDecl->TestFlag(D3D9VertexDeclFlag::HasColor0) : false; + key.Data.Contents.HasColor1 = m_state.vertexDecl != nullptr ? m_state.vertexDecl->TestFlag(D3D9VertexDeclFlag::HasColor1) : false; + key.Data.Contents.HasPointSize = m_state.vertexDecl != nullptr ? m_state.vertexDecl->TestFlag(D3D9VertexDeclFlag::HasPointSize) : false; + key.Data.Contents.HasFog = m_state.vertexDecl != nullptr ? m_state.vertexDecl->TestFlag(D3D9VertexDeclFlag::HasFog) : false; + + bool lighting = m_state.renderStates[D3DRS_LIGHTING] != 0 && !key.Data.Contents.HasPositionT; + bool colorVertex = m_state.renderStates[D3DRS_COLORVERTEX] != 0; + uint32_t mask = (lighting && colorVertex) + ? (key.Data.Contents.HasColor0 ? D3DMCS_COLOR1 : D3DMCS_MATERIAL) + | (key.Data.Contents.HasColor1 ? D3DMCS_COLOR2 : D3DMCS_MATERIAL) + : 0; + + key.Data.Contents.UseLighting = lighting; + key.Data.Contents.NormalizeNormals = m_state.renderStates[D3DRS_NORMALIZENORMALS]; + key.Data.Contents.LocalViewer = m_state.renderStates[D3DRS_LOCALVIEWER] && lighting; + + key.Data.Contents.RangeFog = m_state.renderStates[D3DRS_RANGEFOGENABLE]; + + key.Data.Contents.DiffuseSource = m_state.renderStates[D3DRS_DIFFUSEMATERIALSOURCE] & mask; + key.Data.Contents.AmbientSource = m_state.renderStates[D3DRS_AMBIENTMATERIALSOURCE] & mask; + key.Data.Contents.SpecularSource = m_state.renderStates[D3DRS_SPECULARMATERIALSOURCE] & mask; + key.Data.Contents.EmissiveSource = m_state.renderStates[D3DRS_EMISSIVEMATERIALSOURCE] & mask; + + uint32_t lightCount = 0; + + if (key.Data.Contents.UseLighting) { + for (uint32_t i = 0; i < caps::MaxEnabledLights; i++) { + if (m_state.enabledLightIndices[i] != UINT32_MAX) + lightCount++; + } + } + + key.Data.Contents.LightCount = lightCount; + + for (uint32_t i = 0; i < caps::MaxTextureBlendStages; i++) { + uint32_t transformFlags = m_state.textureStages[i][DXVK_TSS_TEXTURETRANSFORMFLAGS] & ~(D3DTTFF_PROJECTED); + uint32_t index = m_state.textureStages[i][DXVK_TSS_TEXCOORDINDEX]; + uint32_t indexFlags = (index & TCIMask) >> TCIOffset; + + transformFlags &= 0b111; + index &= 0b111; + + key.Data.Contents.TransformFlags |= transformFlags << (i * 3); + key.Data.Contents.TexcoordFlags |= indexFlags << (i * 3); + key.Data.Contents.TexcoordIndices |= index << (i * 3); + } + + key.Data.Contents.TexcoordDeclMask = m_state.vertexDecl != nullptr ? m_state.vertexDecl->GetTexcoordMask() : 0; + + key.Data.Contents.VertexBlendMode = uint32_t(vertexBlendMode); + + if (vertexBlendMode == D3D9FF_VertexBlendMode_Normal) { + key.Data.Contents.VertexBlendIndexed = indexedVertexBlend; + key.Data.Contents.VertexBlendCount = m_state.renderStates[D3DRS_VERTEXBLEND] & 0xff; + } + + key.Data.Contents.VertexClipping = IsClipPlaneEnabled(); + + EmitCs([ + this, + cKey = key, + &cShaders = m_ffModules + ](DxvkContext* ctx) { + auto shader = cShaders.GetShaderModule(this, cKey); + ctx->bindShader(VK_SHADER_STAGE_VERTEX_BIT, shader.GetShader()); + }); + } + + if (hasPositionT && (m_flags.test(D3D9DeviceFlag::DirtyFFViewport) || m_ffZTest != IsZTestEnabled())) { + m_flags.clr(D3D9DeviceFlag::DirtyFFViewport); + m_flags.set(D3D9DeviceFlag::DirtyFFVertexData); + + const auto& vp = m_state.viewport; + // For us to account for the Vulkan viewport rules + // when translating Window Coords -> Real Coords: + // We need to negate the inverse extent we multiply by, + // this follows through to the offset when that gets + // timesed by it. + // The 1.0f additional offset however does not, + // so we account for that there manually. + + m_ffZTest = IsZTestEnabled(); + + m_viewportInfo.inverseExtent = Vector4( + 2.0f / float(vp.Width), + -2.0f / float(vp.Height), + m_ffZTest ? 1.0f : 0.0f, + 1.0f); + + m_viewportInfo.inverseOffset = Vector4( + -float(vp.X), -float(vp.Y), + 0.0f, 0.0f); + + m_viewportInfo.inverseOffset = m_viewportInfo.inverseOffset * m_viewportInfo.inverseExtent; + + m_viewportInfo.inverseOffset = m_viewportInfo.inverseOffset + Vector4(-1.0f, 1.0f, 0.0f, 0.0f); + } + + // Constants... + if (m_flags.test(D3D9DeviceFlag::DirtyFFVertexData)) { + m_flags.clr(D3D9DeviceFlag::DirtyFFVertexData); + + DxvkBufferSliceHandle slice = m_vsFixedFunction->allocSlice(); + + EmitCs([ + cBuffer = m_vsFixedFunction, + cSlice = slice + ] (DxvkContext* ctx) { + ctx->invalidateBuffer(cBuffer, cSlice); + }); + + auto WorldView = m_state.transforms[GetTransformIndex(D3DTS_VIEW)] * m_state.transforms[GetTransformIndex(D3DTS_WORLD)]; + auto NormalMatrix = inverse(WorldView); + + D3D9FixedFunctionVS* data = reinterpret_cast(slice.mapPtr); + data->WorldView = WorldView; + data->NormalMatrix = NormalMatrix; + data->InverseView = transpose(inverse(m_state.transforms[GetTransformIndex(D3DTS_VIEW)])); + data->Projection = m_state.transforms[GetTransformIndex(D3DTS_PROJECTION)]; + + for (uint32_t i = 0; i < data->TexcoordMatrices.size(); i++) + data->TexcoordMatrices[i] = m_state.transforms[GetTransformIndex(D3DTS_TEXTURE0) + i]; + + data->ViewportInfo = m_viewportInfo; + + DecodeD3DCOLOR(m_state.renderStates[D3DRS_AMBIENT], data->GlobalAmbient.data); + + uint32_t lightIdx = 0; + for (uint32_t i = 0; i < caps::MaxEnabledLights; i++) { + auto idx = m_state.enabledLightIndices[i]; + if (idx == UINT32_MAX) + continue; + + data->Lights[lightIdx++] = D3D9Light(m_state.lights[idx].value(), m_state.transforms[GetTransformIndex(D3DTS_VIEW)]); + } + + data->Material = m_state.material; + data->TweenFactor = bit::cast(m_state.renderStates[D3DRS_TWEENFACTOR]); + } + + if (m_flags.test(D3D9DeviceFlag::DirtyFFVertexBlend) && vertexBlendMode == D3D9FF_VertexBlendMode_Normal) { + m_flags.clr(D3D9DeviceFlag::DirtyFFVertexBlend); + + DxvkBufferSliceHandle slice = m_vsVertexBlend->allocSlice(); + + EmitCs([ + cBuffer = m_vsVertexBlend, + cSlice = slice + ] (DxvkContext* ctx) { + ctx->invalidateBuffer(cBuffer, cSlice); + }); + + auto UploadVertexBlendData = [&](auto data) { + for (uint32_t i = 0; i < std::size(data->WorldView); i++) + data->WorldView[i] = m_state.transforms[GetTransformIndex(D3DTS_VIEW)] * m_state.transforms[GetTransformIndex(D3DTS_WORLDMATRIX(i))]; + }; + + (m_isSWVP && indexedVertexBlend) + ? UploadVertexBlendData(reinterpret_cast(slice.mapPtr)) + : UploadVertexBlendData(reinterpret_cast(slice.mapPtr)); + } + } + + + void D3D9DeviceEx::UpdateFixedFunctionPS() { + // Shader... + if (m_flags.test(D3D9DeviceFlag::DirtyFFPixelShader) || m_lastSamplerTypesFF != m_textureTypes) { + m_flags.clr(D3D9DeviceFlag::DirtyFFPixelShader); + m_lastSamplerTypesFF = m_textureTypes; + + // Used args for a given operation. + auto ArgsMask = [](DWORD Op) { + switch (Op) { + case D3DTOP_DISABLE: + return 0b000u; // No Args + case D3DTOP_SELECTARG1: + case D3DTOP_PREMODULATE: + return 0b010u; // Arg 1 + case D3DTOP_SELECTARG2: + return 0b100u; // Arg 2 + case D3DTOP_MULTIPLYADD: + case D3DTOP_LERP: + return 0b111u; // Arg 0, 1, 2 + default: + return 0b110u; // Arg 1, 2 + } + }; + + D3D9FFShaderKeyFS key; + + uint32_t idx; + for (idx = 0; idx < caps::TextureStageCount; idx++) { + auto& stage = key.Stages[idx].Contents; + auto& data = m_state.textureStages[idx]; + + // Subsequent stages do not occur if this is true. + if (data[DXVK_TSS_COLOROP] == D3DTOP_DISABLE) + break; + + // If the stage is invalid (ie. no texture bound), + // this and all subsequent stages get disabled. + if (m_state.textures[idx] == nullptr) { + if (((data[DXVK_TSS_COLORARG0] & D3DTA_SELECTMASK) == D3DTA_TEXTURE && (ArgsMask(data[DXVK_TSS_COLOROP]) & (1 << 0u))) + || ((data[DXVK_TSS_COLORARG1] & D3DTA_SELECTMASK) == D3DTA_TEXTURE && (ArgsMask(data[DXVK_TSS_COLOROP]) & (1 << 1u))) + || ((data[DXVK_TSS_COLORARG2] & D3DTA_SELECTMASK) == D3DTA_TEXTURE && (ArgsMask(data[DXVK_TSS_COLOROP]) & (1 << 2u)))) + break; + } + + stage.ColorOp = data[DXVK_TSS_COLOROP]; + stage.AlphaOp = data[DXVK_TSS_ALPHAOP]; + + stage.ColorArg0 = data[DXVK_TSS_COLORARG0]; + stage.ColorArg1 = data[DXVK_TSS_COLORARG1]; + stage.ColorArg2 = data[DXVK_TSS_COLORARG2]; + + stage.AlphaArg0 = data[DXVK_TSS_ALPHAARG0]; + stage.AlphaArg1 = data[DXVK_TSS_ALPHAARG1]; + stage.AlphaArg2 = data[DXVK_TSS_ALPHAARG2]; + + const uint32_t samplerOffset = idx * 2; + stage.Type = (m_textureTypes >> samplerOffset) & 0xffu; + stage.ResultIsTemp = data[DXVK_TSS_RESULTARG] == D3DTA_TEMP; + + uint32_t ttff = data[DXVK_TSS_TEXTURETRANSFORMFLAGS]; + uint32_t count = ttff & ~D3DTTFF_PROJECTED; + + stage.Projected = (ttff & D3DTTFF_PROJECTED) ? 1 : 0; + stage.ProjectedCount = (ttff & D3DTTFF_PROJECTED) ? count : 0; + } + + auto& stage0 = key.Stages[0].Contents; + + if (stage0.ResultIsTemp && + stage0.ColorOp != D3DTOP_DISABLE && + stage0.AlphaOp == D3DTOP_DISABLE) { + stage0.AlphaOp = D3DTOP_SELECTARG1; + stage0.AlphaArg1 = D3DTA_DIFFUSE; + } + + stage0.GlobalSpecularEnable = m_state.renderStates[D3DRS_SPECULARENABLE]; + stage0.GlobalFlatShade = m_state.renderStates[D3DRS_SHADEMODE] == D3DSHADE_FLAT; + + // The last stage *always* writes to current. + if (idx >= 1) + key.Stages[idx - 1].Contents.ResultIsTemp = false; + + EmitCs([ + this, + cKey = key, + &cShaders = m_ffModules + ](DxvkContext* ctx) { + auto shader = cShaders.GetShaderModule(this, cKey); + ctx->bindShader(VK_SHADER_STAGE_FRAGMENT_BIT, shader.GetShader()); + }); + } + + // Constants + + if (m_flags.test(D3D9DeviceFlag::DirtyFFPixelData)) { + m_flags.clr(D3D9DeviceFlag::DirtyFFPixelData); + + DxvkBufferSliceHandle slice = m_psFixedFunction->allocSlice(); + + EmitCs([ + cBuffer = m_psFixedFunction, + cSlice = slice + ] (DxvkContext* ctx) { + ctx->invalidateBuffer(cBuffer, cSlice); + }); + + auto& rs = m_state.renderStates; + + D3D9FixedFunctionPS* data = reinterpret_cast(slice.mapPtr); + DecodeD3DCOLOR((D3DCOLOR)rs[D3DRS_TEXTUREFACTOR], data->textureFactor.data); + } + } + + + bool D3D9DeviceEx::UseProgrammableVS() { + return m_state.vertexShader != nullptr + && m_state.vertexDecl != nullptr + && !m_state.vertexDecl->TestFlag(D3D9VertexDeclFlag::HasPositionT); + } + + + bool D3D9DeviceEx::UseProgrammablePS() { + return m_state.pixelShader != nullptr; + } + + + void D3D9DeviceEx::UpdateBoolSpecConstantVertex(uint32_t value) { + if (value == m_lastBoolSpecConstantVertex) + return; + + EmitCs([cBitfield = value](DxvkContext* ctx) { + ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, D3D9SpecConstantId::VertexShaderBools, cBitfield); + }); + + m_lastBoolSpecConstantVertex = value; + } + + + void D3D9DeviceEx::UpdateBoolSpecConstantPixel(uint32_t value) { + if (value == m_lastBoolSpecConstantPixel) + return; + + EmitCs([cBitfield = value](DxvkContext* ctx) { + ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, D3D9SpecConstantId::PixelShaderBools, cBitfield); + }); + + m_lastBoolSpecConstantPixel = value; + } + + + void D3D9DeviceEx::UpdateSamplerSpecConsant(uint32_t value) { + EmitCs([cBitfield = value](DxvkContext* ctx) { + ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, D3D9SpecConstantId::SamplerType, cBitfield); + }); + + m_lastSamplerTypes = value; + } + + + void D3D9DeviceEx::UpdateProjectionSpecConstant(uint32_t value) { + EmitCs([cBitfield = value](DxvkContext* ctx) { + ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, D3D9SpecConstantId::ProjectionType, cBitfield); + }); + + m_lastProjectionBitfield = value; + } + + + void D3D9DeviceEx::UpdateFetch4SpecConstant(uint32_t value) { + EmitCs([cBitfield = value](DxvkContext* ctx) { + ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, D3D9SpecConstantId::Fetch4, cBitfield); + }); + + m_lastFetch4 = value; + } + + + void D3D9DeviceEx::UpdateSamplerDepthModeSpecConstant(uint32_t value) { + EmitCs([cBitfield = value](DxvkContext* ctx) { + ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, D3D9SpecConstantId::SamplerDepthMode, cBitfield); + }); + + m_lastSamplerDepthMode = value; + } + + + void D3D9DeviceEx::ApplyPrimitiveType( + DxvkContext* pContext, + D3DPRIMITIVETYPE PrimType) { + if (m_iaState.primitiveType != PrimType) { + m_iaState.primitiveType = PrimType; + + auto iaState = DecodeInputAssemblyState(PrimType); + pContext->setInputAssemblyState(iaState); + } + } + + + void D3D9DeviceEx::ResolveZ() { + D3D9Surface* src = m_state.depthStencil.ptr(); + IDirect3DBaseTexture9* dst = m_state.textures[0]; + + if (unlikely(!src || !dst)) + return; + + D3D9CommonTexture* srcTextureInfo = GetCommonTexture(src); + D3D9CommonTexture* dstTextureInfo = GetCommonTexture(dst); + + const D3D9_COMMON_TEXTURE_DESC* srcDesc = srcTextureInfo->Desc(); + const D3D9_COMMON_TEXTURE_DESC* dstDesc = dstTextureInfo->Desc(); + + VkSampleCountFlagBits dstSampleCount; + DecodeMultiSampleType(m_dxvkDevice, dstDesc->MultiSample, dstDesc->MultisampleQuality, &dstSampleCount); + + if (unlikely(dstSampleCount != VK_SAMPLE_COUNT_1_BIT)) { + Logger::warn("D3D9DeviceEx::ResolveZ: dstSampleCount != 1. Discarding."); + return; + } + + const D3D9_VK_FORMAT_MAPPING srcFormatInfo = LookupFormat(srcDesc->Format); + const D3D9_VK_FORMAT_MAPPING dstFormatInfo = LookupFormat(dstDesc->Format); + + auto srcVulkanFormatInfo = imageFormatInfo(srcFormatInfo.FormatColor); + auto dstVulkanFormatInfo = imageFormatInfo(dstFormatInfo.FormatColor); + + const VkImageSubresource dstSubresource = + dstTextureInfo->GetSubresourceFromIndex( + dstVulkanFormatInfo->aspectMask, 0); + + const VkImageSubresource srcSubresource = + srcTextureInfo->GetSubresourceFromIndex( + srcVulkanFormatInfo->aspectMask, src->GetSubresource()); + + const VkImageSubresourceLayers dstSubresourceLayers = { + dstSubresource.aspectMask, + dstSubresource.mipLevel, + dstSubresource.arrayLayer, 1 }; + + const VkImageSubresourceLayers srcSubresourceLayers = { + srcSubresource.aspectMask, + srcSubresource.mipLevel, + srcSubresource.arrayLayer, 1 }; + + VkSampleCountFlagBits srcSampleCount; + DecodeMultiSampleType(m_dxvkDevice, srcDesc->MultiSample, srcDesc->MultisampleQuality, &srcSampleCount); + + if (srcSampleCount == VK_SAMPLE_COUNT_1_BIT) { + EmitCs([ + cDstImage = dstTextureInfo->GetImage(), + cSrcImage = srcTextureInfo->GetImage(), + cDstLayers = dstSubresourceLayers, + cSrcLayers = srcSubresourceLayers + ] (DxvkContext* ctx) { + ctx->copyImage( + cDstImage, cDstLayers, VkOffset3D { 0, 0, 0 }, + cSrcImage, cSrcLayers, VkOffset3D { 0, 0, 0 }, + cDstImage->mipLevelExtent(cDstLayers.mipLevel)); + }); + } else { + EmitCs([ + cDstImage = dstTextureInfo->GetImage(), + cSrcImage = srcTextureInfo->GetImage(), + cDstSubres = dstSubresourceLayers, + cSrcSubres = srcSubresourceLayers + ] (DxvkContext* ctx) { + // We should resolve using the first sample according to + // http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2012/10/Advanced-DX9-Capabilities-for-ATI-Radeon-Cards_v2.pdf + // "The resolve operation copies the depth value from the *first sample only* into the resolved depth stencil texture." + constexpr auto resolveMode = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT_KHR; + + VkImageResolve region; + region.srcSubresource = cSrcSubres; + region.srcOffset = VkOffset3D { 0, 0, 0 }; + region.dstSubresource = cDstSubres; + region.dstOffset = VkOffset3D { 0, 0, 0 }; + region.extent = cDstImage->mipLevelExtent(cDstSubres.mipLevel); + + ctx->resolveDepthStencilImage(cDstImage, cSrcImage, region, resolveMode, resolveMode); + }); + } + + dstTextureInfo->MarkAllNeedReadback(); + } + + + void D3D9DeviceEx::TransitionImage(D3D9CommonTexture* pResource, VkImageLayout NewLayout) { + EmitCs([ + cImage = pResource->GetImage(), + cNewLayout = NewLayout + ] (DxvkContext* ctx) { + ctx->changeImageLayout( + cImage, cNewLayout); + }); + } + + + void D3D9DeviceEx::TransformImage( + D3D9CommonTexture* pResource, + const VkImageSubresourceRange* pSubresources, + VkImageLayout OldLayout, + VkImageLayout NewLayout) { + EmitCs([ + cImage = pResource->GetImage(), + cSubresources = *pSubresources, + cOldLayout = OldLayout, + cNewLayout = NewLayout + ] (DxvkContext* ctx) { + ctx->transformImage( + cImage, cSubresources, + cOldLayout, cNewLayout); + }); + } + + + HRESULT D3D9DeviceEx::ResetState(D3DPRESENT_PARAMETERS* pPresentationParameters) { + if (!pPresentationParameters->EnableAutoDepthStencil) + SetDepthStencilSurface(nullptr); + + for (uint32_t i = 1; i < caps::MaxSimultaneousRenderTargets; i++) + SetRenderTarget(i, nullptr); + + auto& rs = m_state.renderStates; + + rs[D3DRS_SEPARATEALPHABLENDENABLE] = FALSE; + rs[D3DRS_ALPHABLENDENABLE] = FALSE; + rs[D3DRS_BLENDOP] = D3DBLENDOP_ADD; + rs[D3DRS_BLENDOPALPHA] = D3DBLENDOP_ADD; + rs[D3DRS_DESTBLEND] = D3DBLEND_ZERO; + rs[D3DRS_DESTBLENDALPHA] = D3DBLEND_ZERO; + rs[D3DRS_COLORWRITEENABLE] = 0x0000000f; + rs[D3DRS_COLORWRITEENABLE1] = 0x0000000f; + rs[D3DRS_COLORWRITEENABLE2] = 0x0000000f; + rs[D3DRS_COLORWRITEENABLE3] = 0x0000000f; + rs[D3DRS_SRCBLEND] = D3DBLEND_ONE; + rs[D3DRS_SRCBLENDALPHA] = D3DBLEND_ONE; + BindBlendState(); + + rs[D3DRS_BLENDFACTOR] = 0xffffffff; + BindBlendFactor(); + + rs[D3DRS_ZENABLE] = pPresentationParameters->EnableAutoDepthStencil + ? D3DZB_TRUE + : D3DZB_FALSE; + rs[D3DRS_ZFUNC] = D3DCMP_LESSEQUAL; + rs[D3DRS_TWOSIDEDSTENCILMODE] = FALSE; + rs[D3DRS_ZWRITEENABLE] = TRUE; + rs[D3DRS_STENCILENABLE] = FALSE; + rs[D3DRS_STENCILFAIL] = D3DSTENCILOP_KEEP; + rs[D3DRS_STENCILZFAIL] = D3DSTENCILOP_KEEP; + rs[D3DRS_STENCILPASS] = D3DSTENCILOP_KEEP; + rs[D3DRS_STENCILFUNC] = D3DCMP_ALWAYS; + rs[D3DRS_CCW_STENCILFAIL] = D3DSTENCILOP_KEEP; + rs[D3DRS_CCW_STENCILZFAIL] = D3DSTENCILOP_KEEP; + rs[D3DRS_CCW_STENCILPASS] = D3DSTENCILOP_KEEP; + rs[D3DRS_CCW_STENCILFUNC] = D3DCMP_ALWAYS; + rs[D3DRS_STENCILMASK] = 0xFFFFFFFF; + rs[D3DRS_STENCILWRITEMASK] = 0xFFFFFFFF; + BindDepthStencilState(); + + rs[D3DRS_STENCILREF] = 0; + BindDepthStencilRefrence(); + + rs[D3DRS_FILLMODE] = D3DFILL_SOLID; + rs[D3DRS_CULLMODE] = D3DCULL_CCW; + rs[D3DRS_DEPTHBIAS] = bit::cast(0.0f); + rs[D3DRS_SLOPESCALEDEPTHBIAS] = bit::cast(0.0f); + BindRasterizerState(); + BindDepthBias(); + + rs[D3DRS_SCISSORTESTENABLE] = FALSE; + + rs[D3DRS_ALPHATESTENABLE] = FALSE; + rs[D3DRS_ALPHAFUNC] = D3DCMP_ALWAYS; + BindAlphaTestState(); + rs[D3DRS_ALPHAREF] = 0; + UpdatePushConstant(); + + rs[D3DRS_MULTISAMPLEMASK] = 0xffffffff; + BindMultiSampleState(); + + rs[D3DRS_TEXTUREFACTOR] = 0xffffffff; + m_flags.set(D3D9DeviceFlag::DirtyFFPixelData); + + rs[D3DRS_DIFFUSEMATERIALSOURCE] = D3DMCS_COLOR1; + rs[D3DRS_SPECULARMATERIALSOURCE] = D3DMCS_COLOR2; + rs[D3DRS_AMBIENTMATERIALSOURCE] = D3DMCS_MATERIAL; + rs[D3DRS_EMISSIVEMATERIALSOURCE] = D3DMCS_MATERIAL; + rs[D3DRS_LIGHTING] = TRUE; + rs[D3DRS_COLORVERTEX] = TRUE; + rs[D3DRS_LOCALVIEWER] = TRUE; + rs[D3DRS_RANGEFOGENABLE] = FALSE; + rs[D3DRS_NORMALIZENORMALS] = FALSE; + m_flags.set(D3D9DeviceFlag::DirtyFFVertexShader); + + // PS + rs[D3DRS_SPECULARENABLE] = FALSE; + + rs[D3DRS_AMBIENT] = 0; + m_flags.set(D3D9DeviceFlag::DirtyFFVertexData); + + rs[D3DRS_FOGENABLE] = FALSE; + rs[D3DRS_FOGCOLOR] = 0; + rs[D3DRS_FOGTABLEMODE] = D3DFOG_NONE; + rs[D3DRS_FOGSTART] = bit::cast(0.0f); + rs[D3DRS_FOGEND] = bit::cast(1.0f); + rs[D3DRS_FOGDENSITY] = bit::cast(1.0f); + rs[D3DRS_FOGVERTEXMODE] = D3DFOG_NONE; + m_flags.set(D3D9DeviceFlag::DirtyFogColor); + m_flags.set(D3D9DeviceFlag::DirtyFogDensity); + m_flags.set(D3D9DeviceFlag::DirtyFogEnd); + m_flags.set(D3D9DeviceFlag::DirtyFogScale); + m_flags.set(D3D9DeviceFlag::DirtyFogState); + + rs[D3DRS_CLIPPLANEENABLE] = 0; + m_flags.set(D3D9DeviceFlag::DirtyClipPlanes); + + rs[D3DRS_POINTSPRITEENABLE] = FALSE; + rs[D3DRS_POINTSCALEENABLE] = FALSE; + rs[D3DRS_POINTSCALE_A] = bit::cast(1.0f); + rs[D3DRS_POINTSCALE_B] = bit::cast(0.0f); + rs[D3DRS_POINTSCALE_C] = bit::cast(0.0f); + rs[D3DRS_POINTSIZE] = bit::cast(1.0f); + rs[D3DRS_POINTSIZE_MIN] = bit::cast(1.0f); + rs[D3DRS_POINTSIZE_MAX] = bit::cast(64.0f); + UpdatePushConstant(); + UpdatePushConstant(); + UpdatePushConstant(); + m_flags.set(D3D9DeviceFlag::DirtyPointScale); + UpdatePointMode(); + + rs[D3DRS_SRGBWRITEENABLE] = 0; + + rs[D3DRS_SHADEMODE] = D3DSHADE_GOURAUD; + + rs[D3DRS_VERTEXBLEND] = D3DVBF_DISABLE; + rs[D3DRS_INDEXEDVERTEXBLENDENABLE] = FALSE; + rs[D3DRS_TWEENFACTOR] = bit::cast(0.0f); + m_flags.set(D3D9DeviceFlag::DirtyFFVertexBlend); + + // Render States not implemented beyond this point. + rs[D3DRS_LASTPIXEL] = TRUE; + rs[D3DRS_DITHERENABLE] = FALSE; + rs[D3DRS_WRAP0] = 0; + rs[D3DRS_WRAP1] = 0; + rs[D3DRS_WRAP2] = 0; + rs[D3DRS_WRAP3] = 0; + rs[D3DRS_WRAP4] = 0; + rs[D3DRS_WRAP5] = 0; + rs[D3DRS_WRAP6] = 0; + rs[D3DRS_WRAP7] = 0; + rs[D3DRS_CLIPPING] = TRUE; + rs[D3DRS_MULTISAMPLEANTIALIAS] = TRUE; + rs[D3DRS_PATCHEDGESTYLE] = D3DPATCHEDGE_DISCRETE; + rs[D3DRS_DEBUGMONITORTOKEN] = D3DDMT_ENABLE; + rs[D3DRS_POSITIONDEGREE] = D3DDEGREE_CUBIC; + rs[D3DRS_NORMALDEGREE] = D3DDEGREE_LINEAR; + rs[D3DRS_ANTIALIASEDLINEENABLE] = FALSE; + rs[D3DRS_MINTESSELLATIONLEVEL] = bit::cast(1.0f); + rs[D3DRS_MAXTESSELLATIONLEVEL] = bit::cast(1.0f); + rs[D3DRS_ADAPTIVETESS_X] = bit::cast(0.0f); + rs[D3DRS_ADAPTIVETESS_Y] = bit::cast(0.0f); + rs[D3DRS_ADAPTIVETESS_Z] = bit::cast(1.0f); + rs[D3DRS_ADAPTIVETESS_W] = bit::cast(0.0f); + rs[D3DRS_ENABLEADAPTIVETESSELLATION] = FALSE; + rs[D3DRS_WRAP8] = 0; + rs[D3DRS_WRAP9] = 0; + rs[D3DRS_WRAP10] = 0; + rs[D3DRS_WRAP11] = 0; + rs[D3DRS_WRAP12] = 0; + rs[D3DRS_WRAP13] = 0; + rs[D3DRS_WRAP14] = 0; + rs[D3DRS_WRAP15] = 0; + // End Unimplemented Render States + + for (uint32_t i = 0; i < caps::TextureStageCount; i++) { + auto& stage = m_state.textureStages[i]; + + stage[DXVK_TSS_COLOROP] = i == 0 ? D3DTOP_MODULATE : D3DTOP_DISABLE; + stage[DXVK_TSS_COLORARG1] = D3DTA_TEXTURE; + stage[DXVK_TSS_COLORARG2] = D3DTA_CURRENT; + stage[DXVK_TSS_ALPHAOP] = i == 0 ? D3DTOP_SELECTARG1 : D3DTOP_DISABLE; + stage[DXVK_TSS_ALPHAARG1] = D3DTA_TEXTURE; + stage[DXVK_TSS_ALPHAARG2] = D3DTA_CURRENT; + stage[DXVK_TSS_BUMPENVMAT00] = bit::cast(0.0f); + stage[DXVK_TSS_BUMPENVMAT01] = bit::cast(0.0f); + stage[DXVK_TSS_BUMPENVMAT10] = bit::cast(0.0f); + stage[DXVK_TSS_BUMPENVMAT11] = bit::cast(0.0f); + stage[DXVK_TSS_TEXCOORDINDEX] = i; + stage[DXVK_TSS_BUMPENVLSCALE] = bit::cast(0.0f); + stage[DXVK_TSS_BUMPENVLOFFSET] = bit::cast(0.0f); + stage[DXVK_TSS_TEXTURETRANSFORMFLAGS] = D3DTTFF_DISABLE; + stage[DXVK_TSS_COLORARG0] = D3DTA_CURRENT; + stage[DXVK_TSS_ALPHAARG0] = D3DTA_CURRENT; + stage[DXVK_TSS_RESULTARG] = D3DTA_CURRENT; + stage[DXVK_TSS_CONSTANT] = 0x00000000; + } + m_flags.set(D3D9DeviceFlag::DirtySharedPixelShaderData); + m_flags.set(D3D9DeviceFlag::DirtyFFPixelShader); + + for (uint32_t i = 0; i < caps::MaxStreams; i++) + m_state.streamFreq[i] = 1; + + for (uint32_t i = 0; i < m_state.textures.size(); i++) + TextureChangePrivate(m_state.textures[i], nullptr); + + EmitCs([ + cSize = m_state.textures.size() + ](DxvkContext* ctx) { + for (uint32_t i = 0; i < cSize; i++) { + auto samplerInfo = RemapStateSamplerShader(DWORD(i)); + uint32_t slot = computeResourceSlotId(samplerInfo.first, DxsoBindingType::Image, uint32_t(samplerInfo.second)); + ctx->bindResourceView(slot, nullptr, nullptr); + } + }); + + m_dirtyTextures = 0; + m_depthTextures = 0; + + auto& ss = m_state.samplerStates; + for (uint32_t i = 0; i < ss.size(); i++) { + auto& state = ss[i]; + state[D3DSAMP_ADDRESSU] = D3DTADDRESS_WRAP; + state[D3DSAMP_ADDRESSV] = D3DTADDRESS_WRAP; + state[D3DSAMP_ADDRESSW] = D3DTADDRESS_WRAP; + state[D3DSAMP_BORDERCOLOR] = 0x00000000; + state[D3DSAMP_MAGFILTER] = D3DTEXF_POINT; + state[D3DSAMP_MINFILTER] = D3DTEXF_POINT; + state[D3DSAMP_MIPFILTER] = D3DTEXF_NONE; + state[D3DSAMP_MIPMAPLODBIAS] = bit::cast(0.0f); + state[D3DSAMP_MAXMIPLEVEL] = 0; + state[D3DSAMP_MAXANISOTROPY] = 1; + state[D3DSAMP_SRGBTEXTURE] = 0; + state[D3DSAMP_ELEMENTINDEX] = 0; + state[D3DSAMP_DMAPOFFSET] = 0; + + BindSampler(i); + } + + m_dirtySamplerStates = 0; + + for (uint32_t i = 0; i < caps::MaxClipPlanes; i++) { + float plane[4] = { 0, 0, 0, 0 }; + SetClipPlane(i, plane); + } + + // We should do this... + m_flags.set(D3D9DeviceFlag::DirtyInputLayout); + + UpdateSamplerSpecConsant(0u); + UpdateBoolSpecConstantVertex(0u); + UpdateBoolSpecConstantPixel(0u); + UpdateSamplerDepthModeSpecConstant(0u); + + return D3D_OK; + } + + + HRESULT D3D9DeviceEx::ResetSwapChain(D3DPRESENT_PARAMETERS* pPresentationParameters, D3DDISPLAYMODEEX* pFullscreenDisplayMode) { + D3D9Format backBufferFmt = EnumerateFormat(pPresentationParameters->BackBufferFormat); + + Logger::info(str::format( + "D3D9DeviceEx::ResetSwapChain:\n", + " Requested Presentation Parameters\n", + " - Width: ", pPresentationParameters->BackBufferWidth, "\n", + " - Height: ", pPresentationParameters->BackBufferHeight, "\n", + " - Format: ", backBufferFmt, "\n" + " - Auto Depth Stencil: ", pPresentationParameters->EnableAutoDepthStencil ? "true" : "false", "\n", + " ^ Format: ", EnumerateFormat(pPresentationParameters->AutoDepthStencilFormat), "\n", + " - Windowed: ", pPresentationParameters->Windowed ? "true" : "false", "\n")); + + if (backBufferFmt != D3D9Format::Unknown) { + if (!IsSupportedBackBufferFormat(backBufferFmt)) { + Logger::err(str::format("D3D9DeviceEx::ResetSwapChain: Unsupported backbuffer format: ", + EnumerateFormat(pPresentationParameters->BackBufferFormat))); + return D3DERR_INVALIDCALL; + } + } + + if (m_implicitSwapchain != nullptr) { + if (FAILED(m_implicitSwapchain->Reset(pPresentationParameters, pFullscreenDisplayMode))) + return D3DERR_INVALIDCALL; + } + else + m_implicitSwapchain = new D3D9SwapChainEx(this, pPresentationParameters, pFullscreenDisplayMode); + + if (pPresentationParameters->EnableAutoDepthStencil) { + D3D9_COMMON_TEXTURE_DESC desc; + desc.Width = pPresentationParameters->BackBufferWidth; + desc.Height = pPresentationParameters->BackBufferHeight; + desc.Depth = 1; + desc.ArraySize = 1; + desc.MipLevels = 1; + desc.Usage = D3DUSAGE_DEPTHSTENCIL; + desc.Format = EnumerateFormat(pPresentationParameters->AutoDepthStencilFormat); + desc.Pool = D3DPOOL_DEFAULT; + desc.Discard = FALSE; + desc.MultiSample = pPresentationParameters->MultiSampleType; + desc.MultisampleQuality = pPresentationParameters->MultiSampleQuality; + desc.IsBackBuffer = FALSE; + desc.IsAttachmentOnly = TRUE; + + if (FAILED(D3D9CommonTexture::NormalizeTextureProperties(this, &desc))) + return D3DERR_NOTAVAILABLE; + + m_autoDepthStencil = new D3D9Surface(this, &desc, nullptr, nullptr); + m_initializer->InitTexture(m_autoDepthStencil->GetCommonTexture()); + SetDepthStencilSurface(m_autoDepthStencil.ptr()); + } + + SetRenderTarget(0, m_implicitSwapchain->GetBackBuffer(0)); + + // Force this if we end up binding the same RT to make scissor change go into effect. + BindViewportAndScissor(); + + return D3D_OK; + } + + + HRESULT D3D9DeviceEx::InitialReset(D3DPRESENT_PARAMETERS* pPresentationParameters, D3DDISPLAYMODEEX* pFullscreenDisplayMode) { + HRESULT hr = ResetSwapChain(pPresentationParameters, pFullscreenDisplayMode); + if (FAILED(hr)) + return hr; + + hr = ResetState(pPresentationParameters); + if (FAILED(hr)) + return hr; + + Flush(); + SynchronizeCsThread(DxvkCsThread::SynchronizeAll); + + return D3D_OK; + } + + void D3D9DeviceEx::TrackBufferMappingBufferSequenceNumber( + D3D9CommonBuffer* pResource) { + uint64_t sequenceNumber = GetCurrentSequenceNumber(); + pResource->TrackMappingBufferSequenceNumber(sequenceNumber); + } + + void D3D9DeviceEx::TrackTextureMappingBufferSequenceNumber( + D3D9CommonTexture* pResource, + UINT Subresource) { + uint64_t sequenceNumber = GetCurrentSequenceNumber(); + pResource->TrackMappingBufferSequenceNumber(Subresource, sequenceNumber); + } + + uint64_t D3D9DeviceEx::GetCurrentSequenceNumber() { + // We do not flush empty chunks, so if we are tracking a resource + // immediately after a flush, we need to use the sequence number + // of the previously submitted chunk to prevent deadlocks. + return m_csChunk->empty() ? m_csSeqNum : m_csSeqNum + 1; + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_device.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_device.h new file mode 100644 index 00000000000..cec48291c13 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_device.h @@ -0,0 +1,1278 @@ +#pragma once + +#include "../dxvk/dxvk_device.h" +#include "../dxvk/dxvk_cs.h" + +#include "d3d9_include.h" +#include "d3d9_cursor.h" +#include "d3d9_format.h" +#include "d3d9_multithread.h" +#include "d3d9_adapter.h" +#include "d3d9_constant_set.h" + +#include "d3d9_state.h" + +#include "d3d9_options.h" + +#include "../dxso/dxso_module.h" +#include "../dxso/dxso_util.h" +#include "../dxso/dxso_options.h" +#include "../dxso/dxso_modinfo.h" + +#include "d3d9_sampler.h" +#include "d3d9_fixed_function.h" +#include "d3d9_swvp_emu.h" + +#include "d3d9_shader_permutations.h" + +#include +#include +#include + +namespace dxvk { + + class D3D9InterfaceEx; + class D3D9SwapChainEx; + class D3D9CommonTexture; + class D3D9CommonBuffer; + class D3D9CommonShader; + class D3D9ShaderModuleSet; + class D3D9Initializer; + class D3D9Query; + class D3D9StateBlock; + class D3D9FormatHelper; + class D3D9UserDefinedAnnotation; + + enum class D3D9DeviceFlag : uint32_t { + DirtyFramebuffer, + DirtyClipPlanes, + DirtyDepthStencilState, + DirtyBlendState, + DirtyRasterizerState, + DirtyDepthBias, + DirtyAlphaTestState, + DirtyInputLayout, + DirtyViewportScissor, + DirtyMultiSampleState, + + DirtyFogState, + DirtyFogColor, + DirtyFogDensity, + DirtyFogScale, + DirtyFogEnd, + + DirtyFFVertexData, + DirtyFFVertexBlend, + DirtyFFVertexShader, + DirtyFFPixelShader, + DirtyFFViewport, + DirtyFFPixelData, + DirtyProgVertexShader, + DirtySharedPixelShaderData, + ValidSampleMask, + DirtyDepthBounds, + DirtyPointScale, + + InScene, + }; + + using D3D9DeviceFlags = Flags; + + struct D3D9DrawInfo { + uint32_t vertexCount; + uint32_t instanceCount; + }; + + struct D3D9BufferSlice { + DxvkBufferSlice slice = {}; + void* mapPtr = nullptr; + }; + + class D3D9DeviceEx final : public ComObjectClamp { + constexpr static uint32_t DefaultFrameLatency = 3; + constexpr static uint32_t MaxFrameLatency = 20; + + constexpr static uint32_t MinFlushIntervalUs = 750; + constexpr static uint32_t IncFlushIntervalUs = 250; + constexpr static uint32_t MaxPendingSubmits = 6; + + constexpr static uint32_t NullStreamIdx = caps::MaxStreams; + + friend class D3D9SwapChainEx; + friend class D3D9UserDefinedAnnotation; + public: + + D3D9DeviceEx( + D3D9InterfaceEx* pParent, + D3D9Adapter* pAdapter, + D3DDEVTYPE DeviceType, + HWND hFocusWindow, + DWORD BehaviorFlags, + Rc dxvkDevice); + + ~D3D9DeviceEx(); + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject); + + HRESULT STDMETHODCALLTYPE TestCooperativeLevel(); + + UINT STDMETHODCALLTYPE GetAvailableTextureMem(); + + HRESULT STDMETHODCALLTYPE EvictManagedResources(); + + HRESULT STDMETHODCALLTYPE GetDirect3D(IDirect3D9** ppD3D9); + + HRESULT STDMETHODCALLTYPE GetDeviceCaps(D3DCAPS9* pCaps); + + HRESULT STDMETHODCALLTYPE GetDisplayMode(UINT iSwapChain, D3DDISPLAYMODE* pMode); + + HRESULT STDMETHODCALLTYPE GetCreationParameters(D3DDEVICE_CREATION_PARAMETERS *pParameters); + + HRESULT STDMETHODCALLTYPE SetCursorProperties( + UINT XHotSpot, + UINT YHotSpot, + IDirect3DSurface9* pCursorBitmap); + + void STDMETHODCALLTYPE SetCursorPosition(int X, int Y, DWORD Flags); + + BOOL STDMETHODCALLTYPE ShowCursor(BOOL bShow); + + HRESULT STDMETHODCALLTYPE CreateAdditionalSwapChain( + D3DPRESENT_PARAMETERS* pPresentationParameters, + IDirect3DSwapChain9** ppSwapChain); + + HRESULT STDMETHODCALLTYPE GetSwapChain(UINT iSwapChain, IDirect3DSwapChain9** pSwapChain); + + UINT STDMETHODCALLTYPE GetNumberOfSwapChains(); + + HRESULT STDMETHODCALLTYPE Reset(D3DPRESENT_PARAMETERS* pPresentationParameters); + + HRESULT STDMETHODCALLTYPE Present( + const RECT* pSourceRect, + const RECT* pDestRect, HWND hDestWindowOverride, + const RGNDATA* pDirtyRegion); + + HRESULT STDMETHODCALLTYPE GetBackBuffer( + UINT iSwapChain, + UINT iBackBuffer, + D3DBACKBUFFER_TYPE Type, + IDirect3DSurface9** ppBackBuffer); + + HRESULT STDMETHODCALLTYPE GetRasterStatus(UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus); + + HRESULT STDMETHODCALLTYPE SetDialogBoxMode(BOOL bEnableDialogs); + + void STDMETHODCALLTYPE SetGammaRamp( + UINT iSwapChain, + DWORD Flags, + const D3DGAMMARAMP* pRamp); + + void STDMETHODCALLTYPE GetGammaRamp(UINT iSwapChain, D3DGAMMARAMP* pRamp); + + HRESULT STDMETHODCALLTYPE CreateTexture( + UINT Width, + UINT Height, + UINT Levels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + IDirect3DTexture9** ppTexture, + HANDLE* pSharedHandle); + + HRESULT STDMETHODCALLTYPE CreateVolumeTexture( + UINT Width, + UINT Height, + UINT Depth, + UINT Levels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + IDirect3DVolumeTexture9** ppVolumeTexture, + HANDLE* pSharedHandle); + + HRESULT STDMETHODCALLTYPE CreateCubeTexture( + UINT EdgeLength, + UINT Levels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + IDirect3DCubeTexture9** ppCubeTexture, + HANDLE* pSharedHandle); + + HRESULT STDMETHODCALLTYPE CreateVertexBuffer( + UINT Length, + DWORD Usage, + DWORD FVF, + D3DPOOL Pool, + IDirect3DVertexBuffer9** ppVertexBuffer, + HANDLE* pSharedHandle); + + HRESULT STDMETHODCALLTYPE CreateIndexBuffer( + UINT Length, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + IDirect3DIndexBuffer9** ppIndexBuffer, + HANDLE* pSharedHandle); + + HRESULT STDMETHODCALLTYPE CreateRenderTarget( + UINT Width, + UINT Height, + D3DFORMAT Format, + D3DMULTISAMPLE_TYPE MultiSample, + DWORD MultisampleQuality, + BOOL Lockable, + IDirect3DSurface9** ppSurface, + HANDLE* pSharedHandle); + + HRESULT STDMETHODCALLTYPE CreateDepthStencilSurface( + UINT Width, + UINT Height, + D3DFORMAT Format, + D3DMULTISAMPLE_TYPE MultiSample, + DWORD MultisampleQuality, + BOOL Discard, + IDirect3DSurface9** ppSurface, + HANDLE* pSharedHandle); + + HRESULT STDMETHODCALLTYPE UpdateSurface( + IDirect3DSurface9* pSourceSurface, + const RECT* pSourceRect, + IDirect3DSurface9* pDestinationSurface, + const POINT* pDestPoint); + + HRESULT STDMETHODCALLTYPE UpdateTexture( + IDirect3DBaseTexture9* pSourceTexture, + IDirect3DBaseTexture9* pDestinationTexture); + + HRESULT STDMETHODCALLTYPE GetRenderTargetData( + IDirect3DSurface9* pRenderTarget, + IDirect3DSurface9* pDestSurface); + + HRESULT STDMETHODCALLTYPE GetFrontBufferData(UINT iSwapChain, IDirect3DSurface9* pDestSurface); + + HRESULT STDMETHODCALLTYPE StretchRect( + IDirect3DSurface9* pSourceSurface, + const RECT* pSourceRect, + IDirect3DSurface9* pDestSurface, + const RECT* pDestRect, + D3DTEXTUREFILTERTYPE Filter); + + HRESULT STDMETHODCALLTYPE ColorFill( + IDirect3DSurface9* pSurface, + const RECT* pRect, + D3DCOLOR Color); + + HRESULT STDMETHODCALLTYPE CreateOffscreenPlainSurface( + UINT Width, + UINT Height, + D3DFORMAT Format, + D3DPOOL Pool, + IDirect3DSurface9** ppSurface, + HANDLE* pSharedHandle); + + HRESULT STDMETHODCALLTYPE SetRenderTarget( + DWORD RenderTargetIndex, + IDirect3DSurface9* pRenderTarget); + + HRESULT STDMETHODCALLTYPE GetRenderTarget( + DWORD RenderTargetIndex, + IDirect3DSurface9** ppRenderTarget); + + HRESULT STDMETHODCALLTYPE SetDepthStencilSurface(IDirect3DSurface9* pNewZStencil); + + HRESULT STDMETHODCALLTYPE GetDepthStencilSurface(IDirect3DSurface9** ppZStencilSurface); + + HRESULT STDMETHODCALLTYPE BeginScene(); + + HRESULT STDMETHODCALLTYPE EndScene(); + + HRESULT STDMETHODCALLTYPE Clear( + DWORD Count, + const D3DRECT* pRects, + DWORD Flags, + D3DCOLOR Color, + float Z, + DWORD Stencil); + + HRESULT STDMETHODCALLTYPE SetTransform(D3DTRANSFORMSTATETYPE State, const D3DMATRIX* pMatrix); + + HRESULT STDMETHODCALLTYPE GetTransform(D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix); + + HRESULT STDMETHODCALLTYPE MultiplyTransform(D3DTRANSFORMSTATETYPE TransformState, const D3DMATRIX* pMatrix); + + HRESULT STDMETHODCALLTYPE SetViewport(const D3DVIEWPORT9* pViewport); + + HRESULT STDMETHODCALLTYPE GetViewport(D3DVIEWPORT9* pViewport); + + HRESULT STDMETHODCALLTYPE SetMaterial(const D3DMATERIAL9* pMaterial); + + HRESULT STDMETHODCALLTYPE GetMaterial(D3DMATERIAL9* pMaterial); + + HRESULT STDMETHODCALLTYPE SetLight(DWORD Index, const D3DLIGHT9* pLight); + + HRESULT STDMETHODCALLTYPE GetLight(DWORD Index, D3DLIGHT9* pLight); + + HRESULT STDMETHODCALLTYPE LightEnable(DWORD Index, BOOL Enable); + + HRESULT STDMETHODCALLTYPE GetLightEnable(DWORD Index, BOOL* pEnable); + + HRESULT STDMETHODCALLTYPE SetClipPlane(DWORD Index, const float* pPlane); + + HRESULT STDMETHODCALLTYPE GetClipPlane(DWORD Index, float* pPlane); + + HRESULT STDMETHODCALLTYPE SetRenderState(D3DRENDERSTATETYPE State, DWORD Value); + + HRESULT STDMETHODCALLTYPE GetRenderState(D3DRENDERSTATETYPE State, DWORD* pValue); + + HRESULT STDMETHODCALLTYPE CreateStateBlock( + D3DSTATEBLOCKTYPE Type, + IDirect3DStateBlock9** ppSB); + + HRESULT STDMETHODCALLTYPE BeginStateBlock(); + + HRESULT STDMETHODCALLTYPE EndStateBlock(IDirect3DStateBlock9** ppSB); + + HRESULT STDMETHODCALLTYPE SetClipStatus(const D3DCLIPSTATUS9* pClipStatus); + + HRESULT STDMETHODCALLTYPE GetClipStatus(D3DCLIPSTATUS9* pClipStatus); + + HRESULT STDMETHODCALLTYPE GetTexture(DWORD Stage, IDirect3DBaseTexture9** ppTexture); + + HRESULT STDMETHODCALLTYPE SetTexture(DWORD Stage, IDirect3DBaseTexture9* pTexture); + + HRESULT STDMETHODCALLTYPE GetTextureStageState( + DWORD Stage, + D3DTEXTURESTAGESTATETYPE Type, + DWORD* pValue); + + HRESULT STDMETHODCALLTYPE SetTextureStageState( + DWORD Stage, + D3DTEXTURESTAGESTATETYPE Type, + DWORD Value); + + HRESULT STDMETHODCALLTYPE GetSamplerState( + DWORD Sampler, + D3DSAMPLERSTATETYPE Type, + DWORD* pValue); + + HRESULT STDMETHODCALLTYPE SetSamplerState( + DWORD Sampler, + D3DSAMPLERSTATETYPE Type, + DWORD Value); + + HRESULT STDMETHODCALLTYPE ValidateDevice(DWORD* pNumPasses); + + HRESULT STDMETHODCALLTYPE SetPaletteEntries(UINT PaletteNumber, const PALETTEENTRY* pEntries); + + HRESULT STDMETHODCALLTYPE GetPaletteEntries(UINT PaletteNumber, PALETTEENTRY* pEntries); + + HRESULT STDMETHODCALLTYPE SetCurrentTexturePalette(UINT PaletteNumber); + + HRESULT STDMETHODCALLTYPE GetCurrentTexturePalette(UINT *PaletteNumber); + + HRESULT STDMETHODCALLTYPE SetScissorRect(const RECT* pRect); + + HRESULT STDMETHODCALLTYPE GetScissorRect(RECT* pRect); + + HRESULT STDMETHODCALLTYPE SetSoftwareVertexProcessing(BOOL bSoftware); + + BOOL STDMETHODCALLTYPE GetSoftwareVertexProcessing(); + + HRESULT STDMETHODCALLTYPE SetNPatchMode(float nSegments); + + float STDMETHODCALLTYPE GetNPatchMode(); + + HRESULT STDMETHODCALLTYPE DrawPrimitive( + D3DPRIMITIVETYPE PrimitiveType, + UINT StartVertex, + UINT PrimitiveCount); + + HRESULT STDMETHODCALLTYPE DrawIndexedPrimitive( + D3DPRIMITIVETYPE PrimitiveType, + INT BaseVertexIndex, + UINT MinVertexIndex, + UINT NumVertices, + UINT StartIndex, + UINT PrimitiveCount); + + HRESULT STDMETHODCALLTYPE DrawPrimitiveUP( + D3DPRIMITIVETYPE PrimitiveType, + UINT PrimitiveCount, + const void* pVertexStreamZeroData, + UINT VertexStreamZeroStride); + + HRESULT STDMETHODCALLTYPE DrawIndexedPrimitiveUP( + D3DPRIMITIVETYPE PrimitiveType, + UINT MinVertexIndex, + UINT NumVertices, + UINT PrimitiveCount, + const void* pIndexData, + D3DFORMAT IndexDataFormat, + const void* pVertexStreamZeroData, + UINT VertexStreamZeroStride); + + HRESULT STDMETHODCALLTYPE ProcessVertices( + UINT SrcStartIndex, + UINT DestIndex, + UINT VertexCount, + IDirect3DVertexBuffer9* pDestBuffer, + IDirect3DVertexDeclaration9* pVertexDecl, + DWORD Flags); + + HRESULT STDMETHODCALLTYPE CreateVertexDeclaration( + const D3DVERTEXELEMENT9* pVertexElements, + IDirect3DVertexDeclaration9** ppDecl); + + HRESULT STDMETHODCALLTYPE SetVertexDeclaration(IDirect3DVertexDeclaration9* pDecl); + + HRESULT STDMETHODCALLTYPE GetVertexDeclaration(IDirect3DVertexDeclaration9** ppDecl); + + HRESULT STDMETHODCALLTYPE SetFVF(DWORD FVF); + + HRESULT STDMETHODCALLTYPE GetFVF(DWORD* pFVF); + + HRESULT STDMETHODCALLTYPE CreateVertexShader( + const DWORD* pFunction, + IDirect3DVertexShader9** ppShader); + + HRESULT STDMETHODCALLTYPE SetVertexShader(IDirect3DVertexShader9* pShader); + + HRESULT STDMETHODCALLTYPE GetVertexShader(IDirect3DVertexShader9** ppShader); + + HRESULT STDMETHODCALLTYPE SetVertexShaderConstantF( + UINT StartRegister, + const float* pConstantData, + UINT Vector4fCount); + + HRESULT STDMETHODCALLTYPE GetVertexShaderConstantF( + UINT StartRegister, + float* pConstantData, + UINT Vector4fCount); + + HRESULT STDMETHODCALLTYPE SetVertexShaderConstantI( + UINT StartRegister, + const int* pConstantData, + UINT Vector4iCount); + + HRESULT STDMETHODCALLTYPE GetVertexShaderConstantI( + UINT StartRegister, + int* pConstantData, + UINT Vector4iCount); + + HRESULT STDMETHODCALLTYPE SetVertexShaderConstantB( + UINT StartRegister, + const BOOL* pConstantData, + UINT BoolCount); + + HRESULT STDMETHODCALLTYPE GetVertexShaderConstantB( + UINT StartRegister, + BOOL* pConstantData, + UINT BoolCount); + + HRESULT STDMETHODCALLTYPE SetStreamSource( + UINT StreamNumber, + IDirect3DVertexBuffer9* pStreamData, + UINT OffsetInBytes, + UINT Stride); + + HRESULT STDMETHODCALLTYPE GetStreamSource( + UINT StreamNumber, + IDirect3DVertexBuffer9** ppStreamData, + UINT* pOffsetInBytes, + UINT* pStride); + + HRESULT STDMETHODCALLTYPE SetStreamSourceFreq(UINT StreamNumber, UINT Setting); + + HRESULT STDMETHODCALLTYPE GetStreamSourceFreq(UINT StreamNumber, UINT* pSetting); + + HRESULT STDMETHODCALLTYPE SetIndices(IDirect3DIndexBuffer9* pIndexData); + + HRESULT STDMETHODCALLTYPE GetIndices(IDirect3DIndexBuffer9** ppIndexData); + + HRESULT STDMETHODCALLTYPE CreatePixelShader( + const DWORD* pFunction, + IDirect3DPixelShader9** ppShader); + + HRESULT STDMETHODCALLTYPE SetPixelShader(IDirect3DPixelShader9* pShader); + + HRESULT STDMETHODCALLTYPE GetPixelShader(IDirect3DPixelShader9** ppShader); + + HRESULT STDMETHODCALLTYPE SetPixelShaderConstantF( + UINT StartRegister, + const float* pConstantData, + UINT Vector4fCount); + + HRESULT STDMETHODCALLTYPE GetPixelShaderConstantF( + UINT StartRegister, + float* pConstantData, + UINT Vector4fCount); + + HRESULT STDMETHODCALLTYPE SetPixelShaderConstantI( + UINT StartRegister, + const int* pConstantData, + UINT Vector4iCount); + + HRESULT STDMETHODCALLTYPE GetPixelShaderConstantI( + UINT StartRegister, + int* pConstantData, + UINT Vector4iCount); + + HRESULT STDMETHODCALLTYPE SetPixelShaderConstantB( + UINT StartRegister, + const BOOL* pConstantData, + UINT BoolCount); + + HRESULT STDMETHODCALLTYPE GetPixelShaderConstantB( + UINT StartRegister, + BOOL* pConstantData, + UINT BoolCount); + + HRESULT STDMETHODCALLTYPE DrawRectPatch( + UINT Handle, + const float* pNumSegs, + const D3DRECTPATCH_INFO* pRectPatchInfo); + + HRESULT STDMETHODCALLTYPE DrawTriPatch( + UINT Handle, + const float* pNumSegs, + const D3DTRIPATCH_INFO* pTriPatchInfo); + + HRESULT STDMETHODCALLTYPE DeletePatch(UINT Handle); + + HRESULT STDMETHODCALLTYPE CreateQuery(D3DQUERYTYPE Type, IDirect3DQuery9** ppQuery); + + // Ex Methods + + HRESULT STDMETHODCALLTYPE SetConvolutionMonoKernel( + UINT width, + UINT height, + float* rows, + float* columns); + + HRESULT STDMETHODCALLTYPE ComposeRects( + IDirect3DSurface9* pSrc, + IDirect3DSurface9* pDst, + IDirect3DVertexBuffer9* pSrcRectDescs, + UINT NumRects, + IDirect3DVertexBuffer9* pDstRectDescs, + D3DCOMPOSERECTSOP Operation, + int Xoffset, + int Yoffset); + + HRESULT STDMETHODCALLTYPE GetGPUThreadPriority(INT* pPriority); + + HRESULT STDMETHODCALLTYPE SetGPUThreadPriority(INT Priority); + + HRESULT STDMETHODCALLTYPE WaitForVBlank(UINT iSwapChain); + + HRESULT STDMETHODCALLTYPE CheckResourceResidency(IDirect3DResource9** pResourceArray, UINT32 NumResources); + + HRESULT STDMETHODCALLTYPE SetMaximumFrameLatency(UINT MaxLatency); + + HRESULT STDMETHODCALLTYPE GetMaximumFrameLatency(UINT* pMaxLatency); + + HRESULT STDMETHODCALLTYPE CheckDeviceState(HWND hDestinationWindow); + + HRESULT STDMETHODCALLTYPE PresentEx( + const RECT* pSourceRect, + const RECT* pDestRect, + HWND hDestWindowOverride, + const RGNDATA* pDirtyRegion, + DWORD dwFlags); + + HRESULT STDMETHODCALLTYPE CreateRenderTargetEx( + UINT Width, + UINT Height, + D3DFORMAT Format, + D3DMULTISAMPLE_TYPE MultiSample, + DWORD MultisampleQuality, + BOOL Lockable, + IDirect3DSurface9** ppSurface, + HANDLE* pSharedHandle, + DWORD Usage); + + HRESULT STDMETHODCALLTYPE CreateOffscreenPlainSurfaceEx( + UINT Width, + UINT Height, + D3DFORMAT Format, + D3DPOOL Pool, + IDirect3DSurface9** ppSurface, + HANDLE* pSharedHandle, + DWORD Usage); + + HRESULT STDMETHODCALLTYPE CreateDepthStencilSurfaceEx( + UINT Width, + UINT Height, + D3DFORMAT Format, + D3DMULTISAMPLE_TYPE MultiSample, + DWORD MultisampleQuality, + BOOL Discard, + IDirect3DSurface9** ppSurface, + HANDLE* pSharedHandle, + DWORD Usage); + + HRESULT STDMETHODCALLTYPE ResetEx( + D3DPRESENT_PARAMETERS* pPresentationParameters, + D3DDISPLAYMODEEX* pFullscreenDisplayMode); + + HRESULT STDMETHODCALLTYPE GetDisplayModeEx( + UINT iSwapChain, + D3DDISPLAYMODEEX* pMode, + D3DDISPLAYROTATION* pRotation); + + HRESULT STDMETHODCALLTYPE CreateAdditionalSwapChainEx( + D3DPRESENT_PARAMETERS* pPresentationParameters, + const D3DDISPLAYMODEEX* pFullscreenDisplayMode, + IDirect3DSwapChain9** ppSwapChain); + + HRESULT SetStateSamplerState( + DWORD StateSampler, + D3DSAMPLERSTATETYPE Type, + DWORD Value); + + HRESULT SetStateTexture(DWORD StateSampler, IDirect3DBaseTexture9* pTexture); + + HRESULT SetStateTransform(uint32_t idx, const D3DMATRIX* pMatrix); + + HRESULT SetStateTextureStageState( + DWORD Stage, + D3D9TextureStageStateTypes Type, + DWORD Value); + + VkPipelineStageFlags GetEnabledShaderStages() const { + return m_dxvkDevice->getShaderPipelineStages(); + } + + static DxvkDeviceFeatures GetDeviceFeatures(const Rc& adapter); + + bool SupportsSWVP(); + + bool IsExtended(); + + HWND GetWindow(); + + Rc GetDXVKDevice() { + return m_dxvkDevice; + } + + D3D9_VK_FORMAT_MAPPING LookupFormat( + D3D9Format Format) const; + + const DxvkFormatInfo* UnsupportedFormatInfo( + D3D9Format Format) const; + + bool WaitForResource( + const Rc& Resource, + uint64_t SequenceNumber, + DWORD MapFlags); + + /** + * \brief Locks a subresource of an image + * + * \param [in] Subresource The subresource of the image to lock + * \param [out] pLockedBox The returned locked box of the image, containing data ptr and strides + * \param [in] pBox The region of the subresource to lock. This offsets the returned data ptr + * \param [in] Flags The D3DLOCK_* flags to lock the image with + * \returns \c D3D_OK if the parameters are valid or D3DERR_INVALIDCALL if it fails. + */ + HRESULT LockImage( + D3D9CommonTexture* pResource, + UINT Face, + UINT Mip, + D3DLOCKED_BOX* pLockedBox, + const D3DBOX* pBox, + DWORD Flags); + + uint32_t CalcImageLockOffset( + uint32_t SlicePitch, + uint32_t RowPitch, + const DxvkFormatInfo* FormatInfo, + const D3DBOX* pBox); + + /** + * \brief Unlocks a subresource of an image + * + * Passthrough to device unlock. + * \param [in] Subresource The subresource of the image to unlock + * \returns \c D3D_OK if the parameters are valid or D3DERR_INVALIDCALL if it fails. + */ + HRESULT UnlockImage( + D3D9CommonTexture* pResource, + UINT Face, + UINT MipLevel); + + HRESULT FlushImage( + D3D9CommonTexture* pResource, + UINT Subresource); + + void UpdateTextureFromBuffer( + D3D9CommonTexture* pDestTexture, + D3D9CommonTexture* pSrcTexture, + UINT DestSubresource, + UINT SrcSubresource, + VkOffset3D SrcOffset, + VkExtent3D SrcExtent, + VkOffset3D DestOffset); + + void EmitGenerateMips( + D3D9CommonTexture* pResource); + + HRESULT LockBuffer( + D3D9CommonBuffer* pResource, + UINT OffsetToLock, + UINT SizeToLock, + void** ppbData, + DWORD Flags); + + HRESULT FlushBuffer( + D3D9CommonBuffer* pResource); + + HRESULT UnlockBuffer( + D3D9CommonBuffer* pResource); + + void SetupFPU(); + + int64_t DetermineInitialTextureMemory(); + + Rc CreateConstantBuffer( + bool SSBO, + VkDeviceSize Size, + DxsoProgramType ShaderStage, + DxsoConstantBuffers BufferType); + + void CreateConstantBuffers(); + + void SynchronizeCsThread(uint64_t SequenceNumber); + + void Flush(); + + void UpdateBoundRTs(uint32_t index); + + void UpdateActiveRTs(uint32_t index); + + void UpdateActiveTextures(uint32_t index, DWORD combinedUsage); + + void UpdateActiveHazardsRT(uint32_t rtMask); + + void UpdateActiveHazardsDS(uint32_t texMask); + + void MarkRenderHazards(); + + void UploadManagedTexture(D3D9CommonTexture* pResource); + + void UploadManagedTextures(uint32_t mask); + + void GenerateTextureMips(uint32_t mask); + + void MarkTextureMipsDirty(D3D9CommonTexture* pResource); + + void MarkTextureMipsUnDirty(D3D9CommonTexture* pResource); + + void MarkTextureUploaded(D3D9CommonTexture* pResource); + + template + void UpdatePointMode(); + + void UpdateFog(); + + void BindFramebuffer(); + + void BindViewportAndScissor(); + + inline bool IsAlphaToCoverageEnabled() { + const bool alphaTest = m_state.renderStates[D3DRS_ALPHATESTENABLE] != 0; + + return m_amdATOC || (m_nvATOC && alphaTest); + } + + inline bool IsDepthBiasEnabled() { + const auto& rs = m_state.renderStates; + + float depthBias = bit::cast(rs[D3DRS_DEPTHBIAS]); + float slopeScaledDepthBias = bit::cast(rs[D3DRS_SLOPESCALEDEPTHBIAS]); + + return depthBias != 0.0f || slopeScaledDepthBias != 0.0f; + } + + inline bool IsAlphaTestEnabled() { + return m_state.renderStates[D3DRS_ALPHATESTENABLE] && !IsAlphaToCoverageEnabled(); + } + + inline bool IsZTestEnabled() { + return m_state.renderStates[D3DRS_ZENABLE] && m_state.depthStencil != nullptr; + } + + inline bool IsClipPlaneEnabled() { + return m_state.renderStates[D3DRS_CLIPPLANEENABLE] != 0; + } + + void BindMultiSampleState(); + + void BindBlendState(); + + void BindBlendFactor(); + + void BindDepthStencilState(); + + void BindDepthStencilRefrence(); + + void BindRasterizerState(); + + void BindDepthBias(); + + void BindAlphaTestState(); + + inline void UploadSoftwareConstantSet(const D3D9ShaderConstantsVSSoftware& Src, const D3D9ConstantLayout& Layout); + + inline DxvkBufferSliceHandle CopySoftwareConstants(DxsoConstantBuffers cBufferTarget, Rc& dstBuffer, const void* src, uint32_t copySize, bool useSSBO); + + template + inline void UploadConstantSet(const SoftwareLayoutType& Src, const D3D9ConstantLayout& Layout, const ShaderType& Shader); + + template + void UploadConstants(); + + void UpdateClipPlanes(); + + template + void UpdatePushConstant(const void* pData); + + template + void UpdatePushConstant(); + + void BindSampler(DWORD Sampler); + + void BindTexture(DWORD SamplerSampler); + + void UnbindTextures(uint32_t mask); + + void UndirtySamplers(uint32_t mask); + + void UndirtyTextures(uint32_t usedMask); + + void MarkTextureBindingDirty(IDirect3DBaseTexture9* texture); + + D3D9DrawInfo GenerateDrawInfo( + D3DPRIMITIVETYPE PrimitiveType, + UINT PrimitiveCount, + UINT InstanceCount); + + uint32_t GetInstanceCount() const; + + void PrepareDraw(D3DPRIMITIVETYPE PrimitiveType); + + template + void BindShader( + const D3D9CommonShader* pShaderModule, + D3D9ShaderPermutation Permutation); + + void BindInputLayout(); + + void BindVertexBuffer( + UINT Slot, + D3D9VertexBuffer* pBuffer, + UINT Offset, + UINT Stride); + + void BindIndices(); + + D3D9DeviceLock LockDevice() { + return m_multithread.AcquireLock(); + } + + const D3D9Options* GetOptions() const { + return &m_d3d9Options; + } + + Direct3DState9* GetRawState() { + return &m_state; + } + + void Begin(D3D9Query* pQuery); + void End(D3D9Query* pQuery); + + void SetVertexBoolBitfield(uint32_t idx, uint32_t mask, uint32_t bits); + void SetPixelBoolBitfield (uint32_t idx, uint32_t mask, uint32_t bits); + + void FlushImplicit(BOOL StrongHint); + + bool ChangeReportedMemory(int64_t delta) { + if (IsExtended()) + return true; + + int64_t availableMemory = m_availableMemory.fetch_add(delta); + + return !m_d3d9Options.memoryTrackTest || availableMemory >= delta; + } + + void ResolveZ(); + + void TransitionImage(D3D9CommonTexture* pResource, VkImageLayout NewLayout); + + void TransformImage( + D3D9CommonTexture* pResource, + const VkImageSubresourceRange* pSubresources, + VkImageLayout OldLayout, + VkImageLayout NewLayout); + + const D3D9ConstantLayout& GetVertexConstantLayout() { return m_vsLayout; } + const D3D9ConstantLayout& GetPixelConstantLayout() { return m_psLayout; } + + HRESULT ResetState(D3DPRESENT_PARAMETERS* pPresentationParameters); + HRESULT ResetSwapChain(D3DPRESENT_PARAMETERS* pPresentationParameters, D3DDISPLAYMODEEX* pFullscreenDisplayMode); + + HRESULT InitialReset(D3DPRESENT_PARAMETERS* pPresentationParameters, D3DDISPLAYMODEEX* pFullscreenDisplayMode); + + UINT GetSamplerCount() const { + return m_samplerCount.load(); + } + + private: + + DxvkCsChunkRef AllocCsChunk() { + DxvkCsChunk* chunk = m_csChunkPool.allocChunk(DxvkCsChunkFlag::SingleUse); + return DxvkCsChunkRef(chunk, &m_csChunkPool); + } + + template + void EmitCs(Cmd&& command) { + if (unlikely(!m_csChunk->push(command))) { + EmitCsChunk(std::move(m_csChunk)); + + m_csChunk = AllocCsChunk(); + m_csChunk->push(command); + } + } + + void EmitCsChunk(DxvkCsChunkRef&& chunk); + + void FlushCsChunk() { + if (likely(!m_csChunk->empty())) { + EmitCsChunk(std::move(m_csChunk)); + m_csChunk = AllocCsChunk(); + } + } + + bool CanSWVP() { + return m_behaviorFlags & (D3DCREATE_MIXED_VERTEXPROCESSING | D3DCREATE_SOFTWARE_VERTEXPROCESSING); + } + + inline constexpr D3D9ShaderPermutation GetVertexShaderPermutation() { + return D3D9ShaderPermutations::None; + } + + inline D3D9ShaderPermutation GetPixelShaderPermutation() { + if (unlikely(m_state.renderStates[D3DRS_SHADEMODE] == D3DSHADE_FLAT)) + return D3D9ShaderPermutations::FlatShade; + + return D3D9ShaderPermutations::None; + } + + void DetermineConstantLayouts(bool canSWVP); + + template + D3D9BufferSlice AllocTempBuffer(VkDeviceSize size); + + bool ShouldRecord(); + + HRESULT CreateShaderModule( + D3D9CommonShader* pShaderModule, + VkShaderStageFlagBits ShaderStage, + const DWORD* pShaderBytecode, + const DxsoModuleInfo* pModuleInfo); + + inline uint32_t GetUPDataSize(uint32_t vertexCount, uint32_t stride) { + return vertexCount * stride; + } + + inline uint32_t GetUPBufferSize(uint32_t vertexCount, uint32_t stride) { + return (vertexCount - 1) * stride + std::max(m_state.vertexDecl->GetSize(), stride); + } + + inline void FillUPVertexBuffer(void* buffer, const void* userData, uint32_t dataSize, uint32_t bufferSize) { + uint8_t* data = reinterpret_cast(buffer); + // Don't copy excess data if we don't end up needing it. + dataSize = std::min(dataSize, bufferSize); + std::memcpy(data, userData, dataSize); + // Pad out with 0 to make buffer range checks happy + // Some games have components out of range in the vertex decl + // that they don't read from the shader. + // My tests show that these are read back as 0 always if out of range of + // the dataSize. + // + // So... make the actual buffer the range that satisfies the range of the vertex + // declaration and pad with 0s outside of it. + if (dataSize < bufferSize) + std::memset(data + dataSize, 0, bufferSize - dataSize); + } + + // So we don't do OOB. + template + inline static constexpr uint32_t DetermineSoftwareRegCount() { + constexpr bool isVS = ProgramType == DxsoProgramType::VertexShader; + + switch (ConstantType) { + default: + case D3D9ConstantType::Float: return isVS ? caps::MaxFloatConstantsSoftware : caps::MaxFloatConstantsPS; + case D3D9ConstantType::Int: return isVS ? caps::MaxOtherConstantsSoftware : caps::MaxOtherConstants; + case D3D9ConstantType::Bool: return isVS ? caps::MaxOtherConstantsSoftware : caps::MaxOtherConstants; + } + } + + // So we don't copy more than we need. + template + inline uint32_t DetermineHardwareRegCount() const { + const auto& layout = ProgramType == DxsoProgramType::VertexShader + ? m_vsLayout : m_psLayout; + + switch (ConstantType) { + default: + case D3D9ConstantType::Float: return layout.floatCount; + case D3D9ConstantType::Int: return layout.intCount; + case D3D9ConstantType::Bool: return layout.boolCount; + } + } + + inline uint32_t GetFrameLatency() { + return m_frameLatency; + } + + template < + DxsoProgramType ProgramType, + D3D9ConstantType ConstantType, + typename T> + HRESULT SetShaderConstants( + UINT StartRegister, + const T* pConstantData, + UINT Count); + + template < + DxsoProgramType ProgramType, + D3D9ConstantType ConstantType, + typename T> + HRESULT GetShaderConstants( + UINT StartRegister, + T* pConstantData, + UINT Count) { + auto GetHelper = [&] (const auto& set) { + const uint32_t regCountHardware = DetermineHardwareRegCount(); + constexpr uint32_t regCountSoftware = DetermineSoftwareRegCount(); + + if (StartRegister + Count > regCountSoftware) + return D3DERR_INVALIDCALL; + + Count = UINT( + std::max( + std::clamp(Count + StartRegister, 0, regCountHardware) - INT(StartRegister), + 0)); + + if (Count == 0) + return D3D_OK; + + if (pConstantData == nullptr) + return D3DERR_INVALIDCALL; + + if constexpr (ConstantType == D3D9ConstantType::Float) { + const float* source = set.fConsts[StartRegister].data; + const size_t size = Count * sizeof(Vector4); + + std::memcpy(pConstantData, source, size); + } + else if constexpr (ConstantType == D3D9ConstantType::Int) { + const int* source = set.iConsts[StartRegister].data; + const size_t size = Count * sizeof(Vector4i); + + std::memcpy(pConstantData, source, size); + } + else { + for (uint32_t i = 0; i < Count; i++) { + const uint32_t constantIdx = StartRegister + i; + const uint32_t arrayIdx = constantIdx / 32; + const uint32_t bitIdx = constantIdx % 32; + + const uint32_t bit = (1u << bitIdx); + + bool constValue = set.bConsts[arrayIdx] & bit; + pConstantData[i] = constValue ? TRUE : FALSE; + } + } + + return D3D_OK; + }; + + return ProgramType == DxsoProgramTypes::VertexShader + ? GetHelper(m_state.vsConsts) + : GetHelper(m_state.psConsts); + } + + void UpdateFixedFunctionVS(); + + void UpdateFixedFunctionPS(); + + void ApplyPrimitiveType( + DxvkContext* pContext, + D3DPRIMITIVETYPE PrimType); + + bool UseProgrammableVS(); + + bool UseProgrammablePS(); + + void UpdateBoolSpecConstantVertex(uint32_t value); + + void UpdateBoolSpecConstantPixel(uint32_t value); + + void UpdateSamplerSpecConsant(uint32_t value); + + void UpdateProjectionSpecConstant(uint32_t value); + + void UpdateFetch4SpecConstant(uint32_t value); + + void UpdateSamplerDepthModeSpecConstant(uint32_t value); + + void TrackBufferMappingBufferSequenceNumber( + D3D9CommonBuffer* pResource); + + void TrackTextureMappingBufferSequenceNumber( + D3D9CommonTexture* pResource, + UINT Subresource); + + uint64_t GetCurrentSequenceNumber(); + + Com m_parent; + D3DDEVTYPE m_deviceType; + HWND m_window; + WORD m_behaviorFlags; + D3DPRESENT_PARAMETERS m_presentParams; + + D3D9Adapter* m_adapter; + Rc m_dxvkDevice; + + uint32_t m_frameLatency = DefaultFrameLatency; + + D3D9Initializer* m_initializer = nullptr; + D3D9FormatHelper* m_converter = nullptr; + + D3D9FFShaderModuleSet m_ffModules; + D3D9SWVPEmulator m_swvpEmulator; + + Com m_recorder; + + Rc m_shaderModules; + + Rc m_vsClipPlanes; + + Rc m_vsFixedFunction; + Rc m_vsVertexBlend; + Rc m_psFixedFunction; + Rc m_psShared; + + D3D9BufferSlice m_upBuffer; + D3D9BufferSlice m_managedUploadBuffer; + + D3D9Cursor m_cursor; + + Com m_autoDepthStencil; + + Com m_implicitSwapchain; + + const D3D9Options m_d3d9Options; + DxsoOptions m_dxsoOptions; + + std::unordered_map< + D3D9SamplerKey, + Rc, + D3D9SamplerKeyHash, + D3D9SamplerKeyEq> m_samplers; + + std::unordered_map< + DWORD, + Com> m_fvfTable; + + D3D9Multithread m_multithread; + D3D9InputAssemblyState m_iaState; + + D3D9DeviceFlags m_flags; + // Last state of depth textures. Doesn't update when NULL is bound. + // & with m_activeTextures to normalize. + uint32_t m_instancedData = 0; + + uint32_t m_depthTextures = 0; + uint32_t m_textureTypes = 0; + uint32_t m_projectionBitfield = 0; + + uint32_t m_dirtySamplerStates = 0; + uint32_t m_dirtyTextures = 0; + + uint32_t m_boundRTs = 0; + + uint32_t m_activeRTs = 0; + uint32_t m_activeRTTextures = 0; + uint32_t m_activeDSTextures = 0; + uint32_t m_activeHazardsRT = 0; + uint32_t m_activeHazardsDS = 0; + uint32_t m_alphaSwizzleRTs = 0; + uint32_t m_activeTextures = 0; + uint32_t m_activeTexturesToUpload = 0; + uint32_t m_activeTexturesToGen = 0; + + uint32_t m_fetch4Enabled = 0; + uint32_t m_fetch4 = 0; + + uint32_t m_lastBoolSpecConstantVertex = 0; + uint32_t m_lastBoolSpecConstantPixel = 0; + uint32_t m_lastSamplerDepthMode = 0; + uint32_t m_lastProjectionBitfield = 0; + uint32_t m_lastSamplerTypes = 0; + uint32_t m_lastPointMode = 0; + uint32_t m_lastFetch4 = 0; + uint32_t m_lastHazardsDS = 0; + uint32_t m_lastSamplerTypesFF = 0; + + D3D9ShaderMasks m_vsShaderMasks = D3D9ShaderMasks(); + D3D9ShaderMasks m_psShaderMasks = FixedFunctionMask; + + bool m_isSWVP; + bool m_amdATOC = false; + bool m_nvATOC = false; + bool m_ffZTest = false; + + float m_depthBiasScale = 0.0f; + + uint32_t m_robustSSBOAlignment = 1; + uint32_t m_robustUBOAlignment = 1; + + uint32_t m_vsFloatConstsCount = 0; + uint32_t m_vsIntConstsCount = 0; + uint32_t m_vsBoolConstsCount = 0; + uint32_t m_psFloatConstsCount = 0; + VkDeviceSize m_boundVSConstantsBufferSize = 0; + VkDeviceSize m_boundPSConstantsBufferSize = 0; + + D3D9ConstantLayout m_vsLayout; + D3D9ConstantLayout m_psLayout; + D3D9ConstantSets m_consts[DxsoProgramTypes::Count]; + + D3D9UserDefinedAnnotation* m_annotation = nullptr; + + D3D9ViewportInfo m_viewportInfo; + + DxvkCsChunkPool m_csChunkPool; + dxvk::high_resolution_clock::time_point m_lastFlush + = dxvk::high_resolution_clock::now(); + DxvkCsThread m_csThread; + DxvkCsChunkRef m_csChunk; + uint64_t m_csSeqNum = 0ull; + bool m_csIsBusy = false; + + std::atomic m_availableMemory = { 0 }; + std::atomic m_samplerCount = { 0 }; + + Direct3DState9 m_state; + + }; + +} diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_device_child.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_device_child.h new file mode 100644 index 00000000000..433a269ac8b --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_device_child.h @@ -0,0 +1,61 @@ +#pragma once + +#include "d3d9_include.h" + +namespace dxvk { + + class D3D9DeviceEx; + + template + class D3D9DeviceChild : public ComObjectClamp { + + public: + + D3D9DeviceChild(D3D9DeviceEx* pDevice) + : m_parent( pDevice ) { } + + ULONG STDMETHODCALLTYPE AddRef() { + uint32_t refCount = this->m_refCount++; + if (unlikely(!refCount)) { + this->AddRefPrivate(); + GetDevice()->AddRef(); + } + + return refCount + 1; + } + + ULONG STDMETHODCALLTYPE Release() { + uint32_t refCount = --this->m_refCount; + if (unlikely(!refCount)) { + auto* pDevice = GetDevice(); + this->ReleasePrivate(); + pDevice->Release(); + } + return refCount; + } + + HRESULT STDMETHODCALLTYPE GetDevice(IDirect3DDevice9** ppDevice) { + InitReturnPtr(ppDevice); + + if (ppDevice == nullptr) + return D3DERR_INVALIDCALL; + + *ppDevice = ref(GetDevice()); + return D3D_OK; + } + + IDirect3DDevice9Ex* GetDevice() { + return reinterpret_cast(m_parent); + } + + D3D9DeviceEx* GetParent() { + return m_parent; + } + + protected: + + D3D9DeviceEx* m_parent; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_fixed_function.cpp b/utils/dxvk-1.10.3/src/d3d9/d3d9_fixed_function.cpp new file mode 100644 index 00000000000..37f6e1ab504 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_fixed_function.cpp @@ -0,0 +1,2482 @@ +#include "d3d9_fixed_function.h" + +#include "d3d9_device.h" +#include "d3d9_util.h" +#include "d3d9_spec_constants.h" + +#include "../dxvk/dxvk_hash.h" +#include "../dxvk/dxvk_spec_const.h" + +#include "../spirv/spirv_module.h" + +#include + +namespace dxvk { + + D3D9FixedFunctionOptions::D3D9FixedFunctionOptions(const D3D9Options* options) { + invariantPosition = options->invariantPosition; + } + + uint32_t DoFixedFunctionFog(SpirvModule& spvModule, const D3D9FogContext& fogCtx) { + uint32_t floatType = spvModule.defFloatType(32); + uint32_t uint32Type = spvModule.defIntType(32, 0); + uint32_t vec3Type = spvModule.defVectorType(floatType, 3); + uint32_t vec4Type = spvModule.defVectorType(floatType, 4); + uint32_t floatPtr = spvModule.defPointerType(floatType, spv::StorageClassPushConstant); + uint32_t vec3Ptr = spvModule.defPointerType(vec3Type, spv::StorageClassPushConstant); + + uint32_t fogColorMember = spvModule.constu32(uint32_t(D3D9RenderStateItem::FogColor)); + uint32_t fogColor = spvModule.opLoad(vec3Type, + spvModule.opAccessChain(vec3Ptr, fogCtx.RenderState, 1, &fogColorMember)); + + uint32_t fogScaleMember = spvModule.constu32(uint32_t(D3D9RenderStateItem::FogScale)); + uint32_t fogScale = spvModule.opLoad(floatType, + spvModule.opAccessChain(floatPtr, fogCtx.RenderState, 1, &fogScaleMember)); + + uint32_t fogEndMember = spvModule.constu32(uint32_t(D3D9RenderStateItem::FogEnd)); + uint32_t fogEnd = spvModule.opLoad(floatType, + spvModule.opAccessChain(floatPtr, fogCtx.RenderState, 1, &fogEndMember)); + + uint32_t fogDensityMember = spvModule.constu32(uint32_t(D3D9RenderStateItem::FogDensity)); + uint32_t fogDensity = spvModule.opLoad(floatType, + spvModule.opAccessChain(floatPtr, fogCtx.RenderState, 1, &fogDensityMember)); + + uint32_t fogMode = spvModule.specConst32(uint32Type, 0); + + if (!fogCtx.IsPixel) { + spvModule.setDebugName(fogMode, "vertex_fog_mode"); + spvModule.decorateSpecId(fogMode, getSpecId(D3D9SpecConstantId::VertexFogMode)); + } + else { + spvModule.setDebugName(fogMode, "pixel_fog_mode"); + spvModule.decorateSpecId(fogMode, getSpecId(D3D9SpecConstantId::PixelFogMode)); + } + + uint32_t fogEnabled = spvModule.specConstBool(false); + spvModule.setDebugName(fogEnabled, "fog_enabled"); + spvModule.decorateSpecId(fogEnabled, getSpecId(D3D9SpecConstantId::FogEnabled)); + + uint32_t doFog = spvModule.allocateId(); + uint32_t skipFog = spvModule.allocateId(); + + uint32_t returnType = fogCtx.IsPixel ? vec4Type : floatType; + uint32_t returnTypePtr = spvModule.defPointerType(returnType, spv::StorageClassPrivate); + uint32_t returnValuePtr = spvModule.newVar(returnTypePtr, spv::StorageClassPrivate); + spvModule.opStore(returnValuePtr, fogCtx.IsPixel ? fogCtx.oColor : spvModule.constf32(0.0f)); + + // Actually do the fog now we have all the vars in-place. + + spvModule.opSelectionMerge(skipFog, spv::SelectionControlMaskNone); + spvModule.opBranchConditional(fogEnabled, doFog, skipFog); + + spvModule.opLabel(doFog); + + uint32_t wIndex = 3; + uint32_t zIndex = 2; + + uint32_t w = spvModule.opCompositeExtract(floatType, fogCtx.vPos, 1, &wIndex); + uint32_t z = spvModule.opCompositeExtract(floatType, fogCtx.vPos, 1, &zIndex); + + uint32_t depth = 0; + if (fogCtx.IsPixel) + depth = spvModule.opFMul(floatType, z, spvModule.opFDiv(floatType, spvModule.constf32(1.0f), w)); + else { + if (fogCtx.RangeFog) { + std::array indices = { 0, 1, 2 }; + uint32_t pos3 = spvModule.opVectorShuffle(vec3Type, fogCtx.vPos, fogCtx.vPos, indices.size(), indices.data()); + depth = spvModule.opLength(floatType, pos3); + } + else + depth = fogCtx.HasFogInput + ? fogCtx.vFog + : spvModule.opFAbs(floatType, z); + } + uint32_t fogFactor; + if (!fogCtx.IsPixel && fogCtx.IsFixedFunction && fogCtx.IsPositionT) { + fogFactor = fogCtx.HasSpecular + ? spvModule.opCompositeExtract(floatType, fogCtx.Specular, 1, &wIndex) + : spvModule.constf32(1.0f); + } else { + uint32_t applyFogFactor = spvModule.allocateId(); + + std::array fogVariables; + + std::array fogCaseLabels = { { + { uint32_t(D3DFOG_NONE), spvModule.allocateId() }, + { uint32_t(D3DFOG_EXP), spvModule.allocateId() }, + { uint32_t(D3DFOG_EXP2), spvModule.allocateId() }, + { uint32_t(D3DFOG_LINEAR), spvModule.allocateId() }, + } }; + + spvModule.opSelectionMerge(applyFogFactor, spv::SelectionControlMaskNone); + spvModule.opSwitch(fogMode, + fogCaseLabels[D3DFOG_NONE].labelId, + fogCaseLabels.size(), + fogCaseLabels.data()); + + for (uint32_t i = 0; i < fogCaseLabels.size(); i++) { + spvModule.opLabel(fogCaseLabels[i].labelId); + + fogVariables[i].labelId = fogCaseLabels[i].labelId; + fogVariables[i].varId = [&] { + auto mode = D3DFOGMODE(fogCaseLabels[i].literal); + switch (mode) { + default: + // vFog + case D3DFOG_NONE: { + if (fogCtx.IsPixel) + return fogCtx.vFog; + + if (fogCtx.IsFixedFunction && fogCtx.HasSpecular) + return spvModule.opCompositeExtract(floatType, fogCtx.Specular, 1, &wIndex); + + return spvModule.constf32(1.0f); + } + + // (end - d) / (end - start) + case D3DFOG_LINEAR: { + uint32_t fogFactor = spvModule.opFSub(floatType, fogEnd, depth); + fogFactor = spvModule.opFMul(floatType, fogFactor, fogScale); + fogFactor = spvModule.opNClamp(floatType, fogFactor, spvModule.constf32(0.0f), spvModule.constf32(1.0f)); + return fogFactor; + } + + // 1 / (e^[d * density])^2 + case D3DFOG_EXP2: + // 1 / (e^[d * density]) + case D3DFOG_EXP: { + uint32_t fogFactor = spvModule.opFMul(floatType, depth, fogDensity); + + if (mode == D3DFOG_EXP2) + fogFactor = spvModule.opFMul(floatType, fogFactor, fogFactor); + + // Provides the rcp. + fogFactor = spvModule.opFNegate(floatType, fogFactor); + fogFactor = spvModule.opExp(floatType, fogFactor); + return fogFactor; + } + } + }(); + + spvModule.opBranch(applyFogFactor); + } + + spvModule.opLabel(applyFogFactor); + + fogFactor = spvModule.opPhi(floatType, + fogVariables.size(), + fogVariables.data()); + } + + uint32_t fogRetValue = 0; + + // Return the new color if we are doing this in PS + // or just the fog factor for oFog in VS + if (fogCtx.IsPixel) { + std::array indices = { 0, 1, 2, 6 }; + + uint32_t color = fogCtx.oColor; + + uint32_t color3 = spvModule.opVectorShuffle(vec3Type, color, color, 3, indices.data()); + + std::array fogFacIndices = { fogFactor, fogFactor, fogFactor }; + uint32_t fogFact3 = spvModule.opCompositeConstruct(vec3Type, fogFacIndices.size(), fogFacIndices.data()); + + uint32_t lerpedFrog = spvModule.opFMix(vec3Type, fogColor, color3, fogFact3); + + fogRetValue = spvModule.opVectorShuffle(vec4Type, lerpedFrog, color, indices.size(), indices.data()); + } + else + fogRetValue = fogFactor; + + spvModule.opStore(returnValuePtr, fogRetValue); + + spvModule.opBranch(skipFog); + + spvModule.opLabel(skipFog); + + return spvModule.opLoad(returnType, returnValuePtr); + } + + + uint32_t SetupRenderStateBlock(SpirvModule& spvModule, uint32_t count) { + uint32_t floatType = spvModule.defFloatType(32); + uint32_t vec3Type = spvModule.defVectorType(floatType, 3); + + std::array rsMembers = {{ + vec3Type, + floatType, + floatType, + floatType, + floatType, + + floatType, + floatType, + floatType, + floatType, + floatType, + floatType, + }}; + + uint32_t rsStruct = spvModule.defStructTypeUnique(count, rsMembers.data()); + uint32_t rsBlock = spvModule.newVar( + spvModule.defPointerType(rsStruct, spv::StorageClassPushConstant), + spv::StorageClassPushConstant); + + spvModule.setDebugName (rsBlock, "render_state"); + + spvModule.setDebugName (rsStruct, "render_state_t"); + spvModule.decorate (rsStruct, spv::DecorationBlock); + + uint32_t memberIdx = 0; + auto SetMemberName = [&](const char* name, uint32_t offset) { + if (memberIdx >= count) + return; + + spvModule.setDebugMemberName (rsStruct, memberIdx, name); + spvModule.memberDecorateOffset (rsStruct, memberIdx, offset); + memberIdx++; + }; + + SetMemberName("fog_color", offsetof(D3D9RenderStateInfo, fogColor)); + SetMemberName("fog_scale", offsetof(D3D9RenderStateInfo, fogScale)); + SetMemberName("fog_end", offsetof(D3D9RenderStateInfo, fogEnd)); + SetMemberName("fog_density", offsetof(D3D9RenderStateInfo, fogDensity)); + SetMemberName("alpha_ref", offsetof(D3D9RenderStateInfo, alphaRef)); + SetMemberName("point_size", offsetof(D3D9RenderStateInfo, pointSize)); + SetMemberName("point_size_min", offsetof(D3D9RenderStateInfo, pointSizeMin)); + SetMemberName("point_size_max", offsetof(D3D9RenderStateInfo, pointSizeMax)); + SetMemberName("point_scale_a", offsetof(D3D9RenderStateInfo, pointScaleA)); + SetMemberName("point_scale_b", offsetof(D3D9RenderStateInfo, pointScaleB)); + SetMemberName("point_scale_c", offsetof(D3D9RenderStateInfo, pointScaleC)); + + return rsBlock; + } + + + D3D9PointSizeInfoVS GetPointSizeInfoVS(SpirvModule& spvModule, uint32_t vPos, uint32_t vtx, uint32_t perVertPointSize, uint32_t rsBlock, bool isFixedFunction) { + uint32_t floatType = spvModule.defFloatType(32); + uint32_t floatPtr = spvModule.defPointerType(floatType, spv::StorageClassPushConstant); + uint32_t vec3Type = spvModule.defVectorType(floatType, 3); + uint32_t vec4Type = spvModule.defVectorType(floatType, 4); + uint32_t uint32Type = spvModule.defIntType(32, 0); + uint32_t boolType = spvModule.defBoolType(); + + auto LoadFloat = [&](D3D9RenderStateItem item) { + uint32_t index = spvModule.constu32(uint32_t(item)); + return spvModule.opLoad(floatType, spvModule.opAccessChain(floatPtr, rsBlock, 1, &index)); + }; + + uint32_t value = perVertPointSize != 0 ? perVertPointSize : LoadFloat(D3D9RenderStateItem::PointSize); + + if (isFixedFunction) { + uint32_t pointMode = spvModule.specConst32(uint32Type, 0); + spvModule.setDebugName(pointMode, "point_mode"); + spvModule.decorateSpecId(pointMode, getSpecId(D3D9SpecConstantId::PointMode)); + + uint32_t scaleBit = spvModule.opBitFieldUExtract(uint32Type, pointMode, spvModule.consti32(0), spvModule.consti32(1)); + uint32_t isScale = spvModule.opIEqual(boolType, scaleBit, spvModule.constu32(1)); + + uint32_t scaleC = LoadFloat(D3D9RenderStateItem::PointScaleC); + uint32_t scaleB = LoadFloat(D3D9RenderStateItem::PointScaleB); + uint32_t scaleA = LoadFloat(D3D9RenderStateItem::PointScaleA); + + std::array indices = { 0, 1, 2, 3 }; + + uint32_t vtx3; + if (vPos != 0) { + vPos = spvModule.opLoad(vec4Type, vPos); + + uint32_t rhw = spvModule.opCompositeExtract(floatType, vPos, 1, &indices[3]); + rhw = spvModule.opFDiv(floatType, spvModule.constf32(1.0f), rhw); + uint32_t pos3 = spvModule.opVectorShuffle(vec3Type, vPos, vPos, 3, indices.data()); + vtx3 = spvModule.opVectorTimesScalar(vec3Type, pos3, rhw); + } else { + vtx3 = spvModule.opVectorShuffle(vec3Type, vtx, vtx, 3, indices.data()); + } + + uint32_t DeSqr = spvModule.opDot (floatType, vtx3, vtx3); + uint32_t De = spvModule.opSqrt(floatType, DeSqr); + uint32_t scaleValue = spvModule.opFMul(floatType, scaleC, DeSqr); + scaleValue = spvModule.opFFma(floatType, scaleB, De, scaleValue); + scaleValue = spvModule.opFAdd(floatType, scaleA, scaleValue); + scaleValue = spvModule.opSqrt(floatType, scaleValue); + scaleValue = spvModule.opFDiv(floatType, value, scaleValue); + + value = spvModule.opSelect(floatType, isScale, scaleValue, value); + } + + uint32_t min = LoadFloat(D3D9RenderStateItem::PointSizeMin); + uint32_t max = LoadFloat(D3D9RenderStateItem::PointSizeMax); + + D3D9PointSizeInfoVS info; + info.defaultValue = value; + info.min = min; + info.max = max; + + return info; + } + + + D3D9PointSizeInfoPS GetPointSizeInfoPS(SpirvModule& spvModule, uint32_t rsBlock) { + uint32_t uint32Type = spvModule.defIntType(32, 0); + uint32_t boolType = spvModule.defBoolType(); + uint32_t boolVec4 = spvModule.defVectorType(boolType, 4); + + uint32_t pointMode = spvModule.specConst32(uint32Type, 0); + spvModule.setDebugName(pointMode, "point_mode"); + spvModule.decorateSpecId(pointMode, getSpecId(D3D9SpecConstantId::PointMode)); + + uint32_t spriteBit = spvModule.opBitFieldUExtract(uint32Type, pointMode, spvModule.consti32(1), spvModule.consti32(1)); + uint32_t isSprite = spvModule.opIEqual(boolType, spriteBit, spvModule.constu32(1)); + + std::array isSpriteIndices; + for (uint32_t i = 0; i < isSpriteIndices.size(); i++) + isSpriteIndices[i] = isSprite; + + isSprite = spvModule.opCompositeConstruct(boolVec4, isSpriteIndices.size(), isSpriteIndices.data()); + + D3D9PointSizeInfoPS info; + info.isSprite = isSprite; + + return info; + } + + + uint32_t GetPointCoord(SpirvModule& spvModule, std::vector& entryPointInterfaces) { + uint32_t floatType = spvModule.defFloatType(32); + uint32_t vec2Type = spvModule.defVectorType(floatType, 2); + uint32_t vec4Type = spvModule.defVectorType(floatType, 4); + uint32_t vec2Ptr = spvModule.defPointerType(vec2Type, spv::StorageClassInput); + + uint32_t pointCoordPtr = spvModule.newVar(vec2Ptr, spv::StorageClassInput); + + spvModule.decorateBuiltIn(pointCoordPtr, spv::BuiltInPointCoord); + entryPointInterfaces.push_back(pointCoordPtr); + + uint32_t pointCoord = spvModule.opLoad(vec2Type, pointCoordPtr); + + std::array indices = { 0, 1, 2, 3 }; + + std::array pointCoordIndices = { + spvModule.opCompositeExtract(floatType, pointCoord, 1, &indices[0]), + spvModule.opCompositeExtract(floatType, pointCoord, 1, &indices[1]), + spvModule.constf32(0.0f), + spvModule.constf32(0.0f) + }; + + return spvModule.opCompositeConstruct(vec4Type, pointCoordIndices.size(), pointCoordIndices.data()); + } + + + uint32_t GetSharedConstants(SpirvModule& spvModule) { + uint32_t float_t = spvModule.defFloatType(32); + uint32_t vec2_t = spvModule.defVectorType(float_t, 2); + uint32_t vec4_t = spvModule.defVectorType(float_t, 4); + + std::array stageMembers = { + vec4_t, + + vec2_t, + vec2_t, + + float_t, + float_t, + }; + + std::array members; + + for (auto& member : members) + member = stageMembers; + + const uint32_t structType = + spvModule.defStructType(members.size() * stageMembers.size(), members[0].data()); + + spvModule.decorateBlock(structType); + + uint32_t offset = 0; + for (uint32_t stage = 0; stage < caps::TextureStageCount; stage++) { + spvModule.memberDecorateOffset(structType, stage * D3D9SharedPSStages_Count + D3D9SharedPSStages_Constant, offset); + offset += sizeof(float) * 4; + + spvModule.memberDecorateOffset(structType, stage * D3D9SharedPSStages_Count + D3D9SharedPSStages_BumpEnvMat0, offset); + offset += sizeof(float) * 2; + + spvModule.memberDecorateOffset(structType, stage * D3D9SharedPSStages_Count + D3D9SharedPSStages_BumpEnvMat1, offset); + offset += sizeof(float) * 2; + + spvModule.memberDecorateOffset(structType, stage * D3D9SharedPSStages_Count + D3D9SharedPSStages_BumpEnvLScale, offset); + offset += sizeof(float); + + spvModule.memberDecorateOffset(structType, stage * D3D9SharedPSStages_Count + D3D9SharedPSStages_BumpEnvLOffset, offset); + offset += sizeof(float); + + // Padding... + offset += sizeof(float) * 2; + } + + uint32_t sharedState = spvModule.newVar( + spvModule.defPointerType(structType, spv::StorageClassUniform), + spv::StorageClassUniform); + + spvModule.setDebugName(sharedState, "D3D9SharedPS"); + + return sharedState; + } + + + enum class D3D9FFVSMembers { + WorldViewMatrix, + NormalMatrix, + InverseViewMatrix, + ProjMatrix, + + Texcoord0, + Texcoord1, + Texcoord2, + Texcoord3, + Texcoord4, + Texcoord5, + Texcoord6, + Texcoord7, + + InverseOffset, + InverseExtent, + + GlobalAmbient, + + Light0, + Light1, + Light2, + Light3, + Light4, + Light5, + Light6, + Light7, + + MaterialDiffuse, + MaterialAmbient, + MaterialSpecular, + MaterialEmissive, + MaterialPower, + + TweenFactor, + + MemberCount + }; + + struct D3D9FFVertexData { + uint32_t constantBuffer; + uint32_t vertexBlendData; + uint32_t lightType; + + struct { + uint32_t worldview; + uint32_t normal; + uint32_t inverseView; + uint32_t proj; + + uint32_t texcoord[8]; + + uint32_t invOffset; + uint32_t invExtent; + + uint32_t globalAmbient; + + uint32_t materialDiffuse; + uint32_t materialSpecular; + uint32_t materialAmbient; + uint32_t materialEmissive; + uint32_t materialPower; + uint32_t tweenFactor; + } constants; + + struct { + uint32_t POSITION; + uint32_t POSITION1; + uint32_t POINTSIZE; + uint32_t NORMAL; + uint32_t NORMAL1; + uint32_t TEXCOORD[8]; + uint32_t COLOR[2]; + uint32_t FOG; + + uint32_t BLENDWEIGHT; + uint32_t BLENDINDICES; + } in; + + struct { + uint32_t POSITION; + uint32_t POINTSIZE; + uint32_t NORMAL; + uint32_t TEXCOORD[8]; + uint32_t COLOR[2]; + uint32_t FOG; + } out; + }; + + enum D3D9FFPSMembers { + TextureFactor = 0, + + MemberCount + }; + + struct D3D9FFPixelData { + uint32_t constantBuffer; + uint32_t sharedState; + + struct { + uint32_t textureFactor; + } constants; + + struct { + uint32_t TEXCOORD[8]; + uint32_t COLOR[2]; + uint32_t FOG; + uint32_t POS; + } in; + + struct { + uint32_t texcoordCnt; + uint32_t typeId; + uint32_t varId; + uint32_t bound; + } samplers[8]; + + struct { + uint32_t COLOR; + } out; + }; + + class D3D9FFShaderCompiler { + + public: + + D3D9FFShaderCompiler( + Rc Device, + const D3D9FFShaderKeyVS& Key, + const std::string& Name, + D3D9FixedFunctionOptions Options); + + D3D9FFShaderCompiler( + Rc Device, + const D3D9FFShaderKeyFS& Key, + const std::string& Name, + D3D9FixedFunctionOptions Options); + + Rc compile(); + + DxsoIsgn isgn() { return m_isgn; } + + private: + + // Returns value for inputs + // Returns ptr for outputs + uint32_t declareIO(bool input, DxsoSemantic semantic, spv::BuiltIn builtin = spv::BuiltInMax); + + void compileVS(); + + void setupRenderStateInfo(); + + void emitLightTypeDecl(); + + void emitBaseBufferDecl(); + + void emitVertexBlendDecl(); + + void setupVS(); + + void compilePS(); + + void setupPS(); + + void emitPsSharedConstants(); + + void emitVsClipping(uint32_t vtx); + + void alphaTestPS(); + + bool isVS() { return m_programType == DxsoProgramType::VertexShader; } + bool isPS() { return !isVS(); } + + std::string m_filename; + + SpirvModule m_module; + std::vector + m_resourceSlots; + std::vector m_entryPointInterfaces; + + uint32_t m_inputMask = 0u; + uint32_t m_outputMask = 0u; + uint32_t m_pushConstOffset = 0u; + uint32_t m_pushConstSize = 0u; + + DxsoProgramType m_programType; + D3D9FFShaderKeyVS m_vsKey; + D3D9FFShaderKeyFS m_fsKey; + + D3D9FFVertexData m_vs = { }; + D3D9FFPixelData m_ps = { }; + + DxsoIsgn m_isgn; + DxsoIsgn m_osgn; + + uint32_t m_floatType; + uint32_t m_uint32Type; + uint32_t m_vec4Type; + uint32_t m_vec3Type; + uint32_t m_vec2Type; + uint32_t m_mat3Type; + uint32_t m_mat4Type; + + uint32_t m_entryPointId; + + uint32_t m_rsBlock; + uint32_t m_mainFuncLabel; + + D3D9FixedFunctionOptions m_options; + }; + + D3D9FFShaderCompiler::D3D9FFShaderCompiler( + Rc Device, + const D3D9FFShaderKeyVS& Key, + const std::string& Name, + D3D9FixedFunctionOptions Options) + : m_module(spvVersion(1, 3)), m_options(Options) { + m_programType = DxsoProgramTypes::VertexShader; + m_vsKey = Key; + m_filename = Name; + } + + + D3D9FFShaderCompiler::D3D9FFShaderCompiler( + Rc Device, + const D3D9FFShaderKeyFS& Key, + const std::string& Name, + D3D9FixedFunctionOptions Options) + : m_module(spvVersion(1, 3)), m_options(Options) { + m_programType = DxsoProgramTypes::PixelShader; + m_fsKey = Key; + m_filename = Name; + } + + + Rc D3D9FFShaderCompiler::compile() { + m_floatType = m_module.defFloatType(32); + m_uint32Type = m_module.defIntType(32, 0); + m_vec4Type = m_module.defVectorType(m_floatType, 4); + m_vec3Type = m_module.defVectorType(m_floatType, 3); + m_vec2Type = m_module.defVectorType(m_floatType, 2); + m_mat3Type = m_module.defMatrixType(m_vec3Type, 3); + m_mat4Type = m_module.defMatrixType(m_vec4Type, 4); + + m_entryPointId = m_module.allocateId(); + + // Set the shader name so that we recognize it in renderdoc + m_module.setDebugSource( + spv::SourceLanguageUnknown, 0, + m_module.addDebugString(m_filename.c_str()), + nullptr); + + // Set the memory model. This is the same for all shaders. + m_module.setMemoryModel( + spv::AddressingModelLogical, + spv::MemoryModelGLSL450); + + m_module.enableCapability(spv::CapabilityShader); + m_module.enableCapability(spv::CapabilityImageQuery); + + m_module.functionBegin( + m_module.defVoidType(), m_entryPointId, m_module.defFunctionType( + m_module.defVoidType(), 0, nullptr), + spv::FunctionControlMaskNone); + m_module.setDebugName(m_entryPointId, "main"); + + m_mainFuncLabel = m_module.allocateId(); + m_module.opLabel(m_mainFuncLabel); + + if (isVS()) + compileVS(); + else + compilePS(); + + m_module.opReturn(); + m_module.functionEnd(); + + // Declare the entry point, we now have all the + // information we need, including the interfaces + m_module.addEntryPoint(m_entryPointId, + isVS() ? spv::ExecutionModelVertex : spv::ExecutionModelFragment, "main", + m_entryPointInterfaces.size(), + m_entryPointInterfaces.data()); + + // Create the shader module object + DxvkShaderCreateInfo info; + info.stage = isVS() ? VK_SHADER_STAGE_VERTEX_BIT : VK_SHADER_STAGE_FRAGMENT_BIT; + info.resourceSlotCount = m_resourceSlots.size(); + info.resourceSlots = m_resourceSlots.data(); + info.inputMask = m_inputMask; + info.outputMask = m_outputMask; + info.pushConstOffset = m_pushConstOffset; + info.pushConstSize = m_pushConstOffset; + + return new DxvkShader(info, m_module.compile()); + } + + + uint32_t D3D9FFShaderCompiler::declareIO(bool input, DxsoSemantic semantic, spv::BuiltIn builtin) { + // Declare in ISGN and do linkage + auto& sgn = input + ? m_isgn : m_osgn; + + uint32_t& slots = input + ? m_inputMask + : m_outputMask; + + uint32_t i = sgn.elemCount++; + + uint32_t slot = i; + + if (builtin == spv::BuiltInMax) { + if (input != isVS()) { + slot = RegisterLinkerSlot(semantic); // Requires linkage... + } + + slots |= 1u << slot; + } + + auto& elem = sgn.elems[i]; + elem.slot = slot; + elem.semantic = semantic; + + // Declare variable + spv::StorageClass storageClass = input ? + spv::StorageClassInput : spv::StorageClassOutput; + + const bool scalar = semantic.usage == DxsoUsage::Fog || semantic.usage == DxsoUsage::PointSize; + uint32_t type = scalar ? m_floatType : m_vec4Type; + + uint32_t ptrType = m_module.defPointerType(type, storageClass); + + uint32_t ptr = m_module.newVar(ptrType, storageClass); + + if (builtin == spv::BuiltInMax) + m_module.decorateLocation(ptr, slot); + else + m_module.decorateBuiltIn(ptr, builtin); + + bool diffuseOrSpec = semantic == DxsoSemantic{ DxsoUsage::Color, 0 } + || semantic == DxsoSemantic{ DxsoUsage::Color, 1 }; + + if (diffuseOrSpec && m_fsKey.Stages[0].Contents.GlobalFlatShade) + m_module.decorate(ptr, spv::DecorationFlat); + + std::string name = str::format(input ? "in_" : "out_", semantic.usage, semantic.usageIndex); + m_module.setDebugName(ptr, name.c_str()); + + m_entryPointInterfaces.push_back(ptr); + + if (input) + return m_module.opLoad(type, ptr); + + return ptr; + } + + + void D3D9FFShaderCompiler::compileVS() { + setupVS(); + + std::array indices = { 0, 1, 2, 3 }; + + uint32_t gl_Position = m_vs.in.POSITION; + uint32_t vtx = m_vs.in.POSITION; + uint32_t normal = m_module.opVectorShuffle(m_vec3Type, m_vs.in.NORMAL, m_vs.in.NORMAL, 3, indices.data()); + + if (m_vsKey.Data.Contents.VertexBlendMode == D3D9FF_VertexBlendMode_Tween) { + uint32_t vtx1 = m_vs.in.POSITION1; + uint32_t normal1 = m_module.opVectorShuffle(m_vec3Type, m_vs.in.NORMAL1, m_vs.in.NORMAL1, 3, indices.data()); + + vtx = m_module.opFMix(m_vec3Type, vtx, vtx1, m_vs.constants.tweenFactor); + normal = m_module.opFMix(m_vec3Type, normal, normal1, m_vs.constants.tweenFactor); + } + + const uint32_t wIndex = 3; + + if (!m_vsKey.Data.Contents.HasPositionT) { + if (m_vsKey.Data.Contents.VertexBlendMode == D3D9FF_VertexBlendMode_Normal) { + uint32_t blendWeightRemaining = m_module.constf32(1); + uint32_t vtxSum = m_module.constvec4f32(0, 0, 0, 0); + uint32_t nrmSum = m_module.constvec3f32(0, 0, 0); + + for (uint32_t i = 0; i <= m_vsKey.Data.Contents.VertexBlendCount; i++) { + std::array arrayIndices; + + if (m_vsKey.Data.Contents.VertexBlendIndexed) { + uint32_t index = m_module.opCompositeExtract(m_floatType, m_vs.in.BLENDINDICES, 1, &i); + index = m_module.opConvertFtoU(m_uint32Type, m_module.opRound(m_floatType, index)); + + arrayIndices = { m_module.constu32(0), index }; + } + else + arrayIndices = { m_module.constu32(0), m_module.constu32(i) }; + + uint32_t worldview = m_module.opLoad(m_mat4Type, + m_module.opAccessChain( + m_module.defPointerType(m_mat4Type, spv::StorageClassUniform), m_vs.vertexBlendData, arrayIndices.size(), arrayIndices.data())); + + uint32_t nrmMtx = worldview; + + std::array mtxIndices; + for (uint32_t i = 0; i < 3; i++) { + mtxIndices[i] = m_module.opCompositeExtract(m_vec4Type, nrmMtx, 1, &i); + mtxIndices[i] = m_module.opVectorShuffle(m_vec3Type, mtxIndices[i], mtxIndices[i], 3, indices.data()); + } + nrmMtx = m_module.opCompositeConstruct(m_mat3Type, mtxIndices.size(), mtxIndices.data()); + + uint32_t vtxResult = m_module.opVectorTimesMatrix(m_vec4Type, vtx, worldview); + uint32_t nrmResult = m_module.opVectorTimesMatrix(m_vec3Type, normal, nrmMtx); + + uint32_t weight; + if (i != m_vsKey.Data.Contents.VertexBlendCount) { + weight = m_module.opCompositeExtract(m_floatType, m_vs.in.BLENDWEIGHT, 1, &i); + blendWeightRemaining = m_module.opFSub(m_floatType, blendWeightRemaining, weight); + } + else + weight = blendWeightRemaining; + + vtxResult = m_module.opVectorTimesScalar(m_vec4Type, vtxResult, weight); + nrmResult = m_module.opVectorTimesScalar(m_vec3Type, nrmResult, weight); + + vtxSum = m_module.opFAdd(m_vec4Type, vtxSum, vtxResult); + nrmSum = m_module.opFAdd(m_vec3Type, nrmSum, nrmResult); + } + + vtx = vtxSum; + normal = nrmSum; + } + else { + vtx = m_module.opVectorTimesMatrix(m_vec4Type, vtx, m_vs.constants.worldview); + + uint32_t nrmMtx = m_vs.constants.normal; + + std::array mtxIndices; + for (uint32_t i = 0; i < 3; i++) { + mtxIndices[i] = m_module.opCompositeExtract(m_vec4Type, nrmMtx, 1, &i); + mtxIndices[i] = m_module.opVectorShuffle(m_vec3Type, mtxIndices[i], mtxIndices[i], 3, indices.data()); + } + nrmMtx = m_module.opCompositeConstruct(m_mat3Type, mtxIndices.size(), mtxIndices.data()); + + normal = m_module.opMatrixTimesVector(m_vec3Type, nrmMtx, normal); + } + + // Some games rely no normals not being normal. + if (m_vsKey.Data.Contents.NormalizeNormals) { + uint32_t bool_t = m_module.defBoolType(); + uint32_t bool3_t = m_module.defVectorType(bool_t, 3); + + uint32_t isZeroNormal = m_module.opAll(bool_t, m_module.opFOrdEqual(bool3_t, normal, m_module.constvec3f32(0.0f, 0.0f, 0.0f))); + + std::array members = { isZeroNormal, isZeroNormal, isZeroNormal }; + uint32_t isZeroNormal3 = m_module.opCompositeConstruct(bool3_t, members.size(), members.data()); + + normal = m_module.opNormalize(m_vec3Type, normal); + normal = m_module.opSelect(m_vec3Type, isZeroNormal3, m_module.constvec3f32(0.0f, 0.0f, 0.0f), normal); + } + + gl_Position = m_module.opVectorTimesMatrix(m_vec4Type, vtx, m_vs.constants.proj); + } else { + gl_Position = m_module.opFMul(m_vec4Type, gl_Position, m_vs.constants.invExtent); + gl_Position = m_module.opFAdd(m_vec4Type, gl_Position, m_vs.constants.invOffset); + + // We still need to account for perspective correction here... + + // gl_Position.w = 1.0f / gl_Position.w + // gl_Position.xyz *= gl_Position.w; + + uint32_t bool_t = m_module.defBoolType(); + + uint32_t w = m_module.opCompositeExtract (m_floatType, gl_Position, 1, &wIndex); // w = gl_Position.w + uint32_t is0 = m_module.opFOrdEqual (bool_t, w, m_module.constf32(0)); // is0 = w == 0 + uint32_t rhw = m_module.opFDiv (m_floatType, m_module.constf32(1.0f), w); // rhw = 1.0f / w + rhw = m_module.opSelect (m_floatType, is0, m_module.constf32(1.0), rhw); // rhw = w == 0 ? 1.0 : rhw + gl_Position = m_module.opVectorTimesScalar(m_vec4Type, gl_Position, rhw); // gl_Position.xyz *= rhw + gl_Position = m_module.opCompositeInsert (m_vec4Type, rhw, gl_Position, 1, &wIndex); // gl_Position.w = rhw + } + + m_module.opStore(m_vs.out.POSITION, gl_Position); + + std::array outNrmIndices; + for (uint32_t i = 0; i < 3; i++) + outNrmIndices[i] = m_module.opCompositeExtract(m_floatType, normal, 1, &i); + outNrmIndices[3] = m_module.constf32(1.0f); + + uint32_t outNrm = m_module.opCompositeConstruct(m_vec4Type, outNrmIndices.size(), outNrmIndices.data()); + + m_module.opStore(m_vs.out.NORMAL, outNrm); + + for (uint32_t i = 0; i < caps::TextureStageCount; i++) { + uint32_t inputIndex = (m_vsKey.Data.Contents.TexcoordIndices >> (i * 3)) & 0b111; + uint32_t inputFlags = (m_vsKey.Data.Contents.TexcoordFlags >> (i * 3)) & 0b111; + + uint32_t transformed; + + const uint32_t wIndex = 3; + + uint32_t flags = (m_vsKey.Data.Contents.TransformFlags >> (i * 3)) & 0b111; + uint32_t count = flags; + switch (inputFlags) { + default: + case (DXVK_TSS_TCI_PASSTHRU >> TCIOffset): + transformed = m_vs.in.TEXCOORD[inputIndex & 0xFF]; + break; + + case (DXVK_TSS_TCI_CAMERASPACENORMAL >> TCIOffset): + transformed = outNrm; + count = 4; + break; + + case (DXVK_TSS_TCI_CAMERASPACEPOSITION >> TCIOffset): + transformed = m_module.opCompositeInsert(m_vec4Type, m_module.constf32(1.0f), vtx, 1, &wIndex); + count = 4; + break; + + case (DXVK_TSS_TCI_CAMERASPACEREFLECTIONVECTOR >> TCIOffset): { + uint32_t vtx3 = m_module.opVectorShuffle(m_vec3Type, vtx, vtx, 3, indices.data()); + vtx3 = m_module.opNormalize(m_vec3Type, vtx3); + + uint32_t reflection = m_module.opReflect(m_vec3Type, vtx3, normal); + + std::array transformIndices; + for (uint32_t i = 0; i < 3; i++) + transformIndices[i] = m_module.opCompositeExtract(m_floatType, reflection, 1, &i); + transformIndices[3] = m_module.constf32(1.0f); + + transformed = m_module.opCompositeConstruct(m_vec4Type, transformIndices.size(), transformIndices.data()); + count = 4; + break; + } + + case (DXVK_TSS_TCI_SPHEREMAP >> TCIOffset): { + uint32_t vtx3 = m_module.opVectorShuffle(m_vec3Type, vtx, vtx, 3, indices.data()); + vtx3 = m_module.opNormalize(m_vec3Type, vtx3); + + uint32_t reflection = m_module.opReflect(m_vec3Type, vtx3, normal); + uint32_t m = m_module.opFAdd(m_vec3Type, reflection, m_module.constvec3f32(0, 0, 1)); + m = m_module.opLength(m_floatType, m); + m = m_module.opFMul(m_floatType, m, m_module.constf32(2.0f)); + + std::array transformIndices; + for (uint32_t i = 0; i < 2; i++) { + transformIndices[i] = m_module.opCompositeExtract(m_floatType, reflection, 1, &i); + transformIndices[i] = m_module.opFDiv(m_floatType, transformIndices[i], m); + transformIndices[i] = m_module.opFAdd(m_floatType, transformIndices[i], m_module.constf32(0.5f)); + } + + transformIndices[2] = m_module.constf32(0.0f); + transformIndices[3] = m_module.constf32(1.0f); + + transformed = m_module.opCompositeConstruct(m_vec4Type, transformIndices.size(), transformIndices.data()); + count = 4; + break; + } + } + + uint32_t type = flags; + if (type != D3DTTFF_DISABLE) { + if (!m_vsKey.Data.Contents.HasPositionT) { + for (uint32_t j = count; j < 4; j++) { + // If we're outside the component count of the vertex decl for this texcoord then we pad with zeroes. + // Otherwise, pad with ones. + + // Very weird quirk in order to get texcoord transforms to work like they do in native. + // In future, maybe we could sort this out properly by chopping matrices of different sizes, but thats + // a project for another day. + uint32_t texcoordCount = (m_vsKey.Data.Contents.TexcoordDeclMask >> (3 * inputIndex)) & 0x7; + uint32_t value = j > texcoordCount ? m_module.constf32(0) : m_module.constf32(1); + transformed = m_module.opCompositeInsert(m_vec4Type, value, transformed, 1, &j); + } + + transformed = m_module.opVectorTimesMatrix(m_vec4Type, transformed, m_vs.constants.texcoord[i]); + } + + // Pad the unused section of it with the value for projection. + uint32_t lastIdx = count - 1; + uint32_t projValue = m_module.opCompositeExtract(m_floatType, transformed, 1, &lastIdx); + + for (uint32_t j = count; j < 4; j++) + transformed = m_module.opCompositeInsert(m_vec4Type, projValue, transformed, 1, &j); + } + + m_module.opStore(m_vs.out.TEXCOORD[i], transformed); + } + + if (m_vsKey.Data.Contents.UseLighting) { + auto PickSource = [&](uint32_t Source, uint32_t Material) { + if (Source == D3DMCS_MATERIAL) + return Material; + else if (Source == D3DMCS_COLOR1) + return m_vs.in.COLOR[0]; + else + return m_vs.in.COLOR[1]; + }; + + uint32_t diffuseValue = m_module.constvec4f32(0.0f, 0.0f, 0.0f, 0.0f); + uint32_t specularValue = m_module.constvec4f32(0.0f, 0.0f, 0.0f, 0.0f); + uint32_t ambientValue = m_module.constvec4f32(0.0f, 0.0f, 0.0f, 0.0f); + + for (uint32_t i = 0; i < m_vsKey.Data.Contents.LightCount; i++) { + uint32_t light_ptr_t = m_module.defPointerType(m_vs.lightType, spv::StorageClassUniform); + + uint32_t indexVal = m_module.constu32(uint32_t(D3D9FFVSMembers::Light0) + i); + uint32_t lightPtr = m_module.opAccessChain(light_ptr_t, m_vs.constantBuffer, 1, &indexVal); + + auto LoadLightItem = [&](uint32_t type, uint32_t idx) { + uint32_t typePtr = m_module.defPointerType(type, spv::StorageClassUniform); + + idx = m_module.constu32(idx); + + return m_module.opLoad(type, + m_module.opAccessChain(typePtr, lightPtr, 1, &idx)); + }; + + uint32_t diffuse = LoadLightItem(m_vec4Type, 0); + uint32_t specular = LoadLightItem(m_vec4Type, 1); + uint32_t ambient = LoadLightItem(m_vec4Type, 2); + uint32_t position = LoadLightItem(m_vec4Type, 3); + uint32_t direction = LoadLightItem(m_vec4Type, 4); + uint32_t type = LoadLightItem(m_uint32Type, 5); + uint32_t range = LoadLightItem(m_floatType, 6); + uint32_t falloff = LoadLightItem(m_floatType, 7); + uint32_t atten0 = LoadLightItem(m_floatType, 8); + uint32_t atten1 = LoadLightItem(m_floatType, 9); + uint32_t atten2 = LoadLightItem(m_floatType, 10); + uint32_t theta = LoadLightItem(m_floatType, 11); + uint32_t phi = LoadLightItem(m_floatType, 12); + + uint32_t bool_t = m_module.defBoolType(); + uint32_t bool3_t = m_module.defVectorType(bool_t, 3); + + uint32_t isSpot = m_module.opIEqual(bool_t, type, m_module.constu32(D3DLIGHT_SPOT)); + uint32_t isDirectional = m_module.opIEqual(bool_t, type, m_module.constu32(D3DLIGHT_DIRECTIONAL)); + + std::array members = { isDirectional, isDirectional, isDirectional }; + + uint32_t isDirectional3 = m_module.opCompositeConstruct(bool3_t, members.size(), members.data()); + + uint32_t vtx3 = m_module.opVectorShuffle(m_vec3Type, vtx, vtx, 3, indices.data()); + position = m_module.opVectorShuffle(m_vec3Type, position, position, 3, indices.data()); + direction = m_module.opVectorShuffle(m_vec3Type, direction, direction, 3, indices.data()); + + uint32_t delta = m_module.opFSub(m_vec3Type, position, vtx3); + uint32_t d = m_module.opLength(m_floatType, delta); + uint32_t hitDir = m_module.opFNegate(m_vec3Type, direction); + hitDir = m_module.opSelect(m_vec3Type, isDirectional3, hitDir, delta); + hitDir = m_module.opNormalize(m_vec3Type, hitDir); + + uint32_t atten = m_module.opFFma (m_floatType, d, atten2, atten1); + atten = m_module.opFFma (m_floatType, d, atten, atten0); + atten = m_module.opFDiv (m_floatType, m_module.constf32(1.0f), atten); + atten = m_module.opNMin (m_floatType, atten, m_module.constf32(FLT_MAX)); + + atten = m_module.opSelect(m_floatType, m_module.opFOrdGreaterThan(bool_t, d, range), m_module.constf32(0.0f), atten); + atten = m_module.opSelect(m_floatType, isDirectional, m_module.constf32(1.0f), atten); + + // Spot Lighting + { + uint32_t rho = m_module.opDot (m_floatType, m_module.opFNegate(m_vec3Type, hitDir), direction); + uint32_t spotAtten = m_module.opFSub(m_floatType, rho, phi); + spotAtten = m_module.opFDiv(m_floatType, spotAtten, m_module.opFSub(m_floatType, theta, phi)); + spotAtten = m_module.opPow (m_floatType, spotAtten, falloff); + + uint32_t insideThetaAndPhi = m_module.opFOrdLessThanEqual(bool_t, rho, theta); + uint32_t insidePhi = m_module.opFOrdGreaterThan(bool_t, rho, phi); + spotAtten = m_module.opSelect(m_floatType, insidePhi, spotAtten, m_module.constf32(0.0f)); + spotAtten = m_module.opSelect(m_floatType, insideThetaAndPhi, spotAtten, m_module.constf32(1.0f)); + spotAtten = m_module.opFClamp(m_floatType, spotAtten, m_module.constf32(0.0f), m_module.constf32(1.0f)); + + spotAtten = m_module.opFMul(m_floatType, atten, spotAtten); + atten = m_module.opSelect(m_floatType, isSpot, spotAtten, atten); + } + + + uint32_t hitDot = m_module.opDot(m_floatType, normal, hitDir); + hitDot = m_module.opFClamp(m_floatType, hitDot, m_module.constf32(0.0f), m_module.constf32(1.0f)); + + uint32_t diffuseness = m_module.opFMul(m_floatType, hitDot, atten); + + uint32_t mid; + if (m_vsKey.Data.Contents.LocalViewer) { + mid = m_module.opNormalize(m_vec3Type, vtx3); + mid = m_module.opFSub(m_vec3Type, hitDir, mid); + } + else + mid = m_module.opFSub(m_vec3Type, hitDir, m_module.constvec3f32(0.0f, 0.0f, 1.0f)); + + mid = m_module.opNormalize(m_vec3Type, mid); + + uint32_t midDot = m_module.opDot(m_floatType, normal, mid); + midDot = m_module.opFClamp(m_floatType, midDot, m_module.constf32(0.0f), m_module.constf32(1.0f)); + uint32_t doSpec = m_module.opFOrdGreaterThan(bool_t, midDot, m_module.constf32(0.0f)); + uint32_t specularness = m_module.opPow(m_floatType, midDot, m_vs.constants.materialPower); + specularness = m_module.opFMul(m_floatType, specularness, atten); + specularness = m_module.opSelect(m_floatType, doSpec, specularness, m_module.constf32(0.0f)); + + uint32_t lightAmbient = m_module.opVectorTimesScalar(m_vec4Type, ambient, atten); + uint32_t lightDiffuse = m_module.opVectorTimesScalar(m_vec4Type, diffuse, diffuseness); + uint32_t lightSpecular = m_module.opVectorTimesScalar(m_vec4Type, specular, specularness); + + ambientValue = m_module.opFAdd(m_vec4Type, ambientValue, lightAmbient); + diffuseValue = m_module.opFAdd(m_vec4Type, diffuseValue, lightDiffuse); + specularValue = m_module.opFAdd(m_vec4Type, specularValue, lightSpecular); + } + + uint32_t mat_diffuse = PickSource(m_vsKey.Data.Contents.DiffuseSource, m_vs.constants.materialDiffuse); + uint32_t mat_ambient = PickSource(m_vsKey.Data.Contents.AmbientSource, m_vs.constants.materialAmbient); + uint32_t mat_emissive = PickSource(m_vsKey.Data.Contents.EmissiveSource, m_vs.constants.materialEmissive); + uint32_t mat_specular = PickSource(m_vsKey.Data.Contents.SpecularSource, m_vs.constants.materialSpecular); + + std::array alphaSwizzle = {0, 1, 2, 7}; + uint32_t finalColor0 = m_module.opFFma(m_vec4Type, mat_ambient, m_vs.constants.globalAmbient, mat_emissive); + finalColor0 = m_module.opFFma(m_vec4Type, mat_ambient, ambientValue, finalColor0); + finalColor0 = m_module.opFFma(m_vec4Type, mat_diffuse, diffuseValue, finalColor0); + finalColor0 = m_module.opVectorShuffle(m_vec4Type, finalColor0, mat_diffuse, alphaSwizzle.size(), alphaSwizzle.data()); + + uint32_t finalColor1 = m_module.opFMul(m_vec4Type, mat_specular, specularValue); + + // Saturate + finalColor0 = m_module.opFClamp(m_vec4Type, finalColor0, + m_module.constvec4f32(0.0f, 0.0f, 0.0f, 0.0f), + m_module.constvec4f32(1.0f, 1.0f, 1.0f, 1.0f)); + + finalColor1 = m_module.opFClamp(m_vec4Type, finalColor1, + m_module.constvec4f32(0.0f, 0.0f, 0.0f, 0.0f), + m_module.constvec4f32(1.0f, 1.0f, 1.0f, 1.0f)); + + m_module.opStore(m_vs.out.COLOR[0], finalColor0); + m_module.opStore(m_vs.out.COLOR[1], finalColor1); + } + else { + m_module.opStore(m_vs.out.COLOR[0], m_vs.in.COLOR[0]); + m_module.opStore(m_vs.out.COLOR[1], m_vs.in.COLOR[1]); + } + + D3D9FogContext fogCtx; + fogCtx.IsPixel = false; + fogCtx.RangeFog = m_vsKey.Data.Contents.RangeFog; + fogCtx.RenderState = m_rsBlock; + fogCtx.vPos = vtx; + fogCtx.HasFogInput = m_vsKey.Data.Contents.HasFog; + fogCtx.vFog = m_vs.in.FOG; + fogCtx.oColor = 0; + fogCtx.IsFixedFunction = true; + fogCtx.IsPositionT = m_vsKey.Data.Contents.HasPositionT; + fogCtx.HasSpecular = m_vsKey.Data.Contents.HasColor1; + fogCtx.Specular = m_vs.in.COLOR[1]; + m_module.opStore(m_vs.out.FOG, DoFixedFunctionFog(m_module, fogCtx)); + + auto pointInfo = GetPointSizeInfoVS(m_module, 0, vtx, m_vs.in.POINTSIZE, m_rsBlock, true); + + uint32_t pointSize = m_module.opFClamp(m_floatType, pointInfo.defaultValue, pointInfo.min, pointInfo.max); + m_module.opStore(m_vs.out.POINTSIZE, pointSize); + + if (m_vsKey.Data.Contents.VertexClipping) + emitVsClipping(vtx); + } + + + void D3D9FFShaderCompiler::setupRenderStateInfo() { + uint32_t count; + + if (m_programType == DxsoProgramType::PixelShader) { + m_pushConstOffset = 0; + m_pushConstSize = offsetof(D3D9RenderStateInfo, pointSize); + count = 5; + } + else { + m_pushConstOffset = offsetof(D3D9RenderStateInfo, pointSize); + m_pushConstSize = sizeof(float) * 6; + count = 11; + } + + m_rsBlock = SetupRenderStateBlock(m_module, count); + } + + + void D3D9FFShaderCompiler::emitLightTypeDecl() { + std::array light_members = { + m_vec4Type, // Diffuse + m_vec4Type, // Specular + m_vec4Type, // Ambient + m_vec4Type, // Position + m_vec4Type, // Direction + m_uint32Type, // Type + m_floatType, // Range + m_floatType, // Falloff + m_floatType, // Attenuation0 + m_floatType, // Attenuation1 + m_floatType, // Attenuation2 + m_floatType, // Theta + m_floatType, // Phi + }; + + m_vs.lightType = + m_module.defStructType(light_members.size(), light_members.data()); + + m_module.setDebugName(m_vs.lightType, "light_t"); + + uint32_t offset = 0; + + m_module.memberDecorateOffset(m_vs.lightType, 0, offset); offset += 4 * sizeof(float); + m_module.setDebugMemberName (m_vs.lightType, 0, "Diffuse"); + m_module.memberDecorateOffset(m_vs.lightType, 1, offset); offset += 4 * sizeof(float); + m_module.setDebugMemberName (m_vs.lightType, 1, "Specular"); + m_module.memberDecorateOffset(m_vs.lightType, 2, offset); offset += 4 * sizeof(float); + m_module.setDebugMemberName (m_vs.lightType, 2, "Ambient"); + + m_module.memberDecorateOffset(m_vs.lightType, 3, offset); offset += 4 * sizeof(float); + m_module.setDebugMemberName (m_vs.lightType, 3, "Position"); + m_module.memberDecorateOffset(m_vs.lightType, 4, offset); offset += 4 * sizeof(float); + m_module.setDebugMemberName (m_vs.lightType, 4, "Direction"); + + m_module.memberDecorateOffset(m_vs.lightType, 5, offset); offset += 1 * sizeof(uint32_t); + m_module.setDebugMemberName (m_vs.lightType, 5, "Type"); + + m_module.memberDecorateOffset(m_vs.lightType, 6, offset); offset += 1 * sizeof(float); + m_module.setDebugMemberName (m_vs.lightType, 6, "Range"); + m_module.memberDecorateOffset(m_vs.lightType, 7, offset); offset += 1 * sizeof(float); + m_module.setDebugMemberName (m_vs.lightType, 7, "Falloff"); + + m_module.memberDecorateOffset(m_vs.lightType, 8, offset); offset += 1 * sizeof(float); + m_module.setDebugMemberName (m_vs.lightType, 8, "Attenuation0"); + m_module.memberDecorateOffset(m_vs.lightType, 9, offset); offset += 1 * sizeof(float); + m_module.setDebugMemberName (m_vs.lightType, 9, "Attenuation1"); + m_module.memberDecorateOffset(m_vs.lightType, 10, offset); offset += 1 * sizeof(float); + m_module.setDebugMemberName (m_vs.lightType, 10, "Attenuation2"); + + m_module.memberDecorateOffset(m_vs.lightType, 11, offset); offset += 1 * sizeof(float); + m_module.setDebugMemberName (m_vs.lightType, 11, "Theta"); + m_module.memberDecorateOffset(m_vs.lightType, 12, offset); offset += 1 * sizeof(float); + m_module.setDebugMemberName (m_vs.lightType, 12, "Phi"); + } + + + void D3D9FFShaderCompiler::emitBaseBufferDecl() { + // Constant Buffer for VS. + std::array members = { + m_mat4Type, // World + m_mat4Type, // View + m_mat4Type, // InverseView + m_mat4Type, // Proj + + m_mat4Type, // Texture0 + m_mat4Type, // Texture1 + m_mat4Type, // Texture2 + m_mat4Type, // Texture3 + m_mat4Type, // Texture4 + m_mat4Type, // Texture5 + m_mat4Type, // Texture6 + m_mat4Type, // Texture7 + + m_vec4Type, // Inverse Offset + m_vec4Type, // Inverse Extent + + m_vec4Type, // Global Ambient + + m_vs.lightType, // Light0 + m_vs.lightType, // Light1 + m_vs.lightType, // Light2 + m_vs.lightType, // Light3 + m_vs.lightType, // Light4 + m_vs.lightType, // Light5 + m_vs.lightType, // Light6 + m_vs.lightType, // Light7 + + m_vec4Type, // Material Diffuse + m_vec4Type, // Material Ambient + m_vec4Type, // Material Specular + m_vec4Type, // Material Emissive + m_floatType, // Material Power + + m_floatType, // Tween Factor + }; + + const uint32_t structType = + m_module.defStructType(members.size(), members.data()); + + m_module.decorateBlock(structType); + + uint32_t offset = 0; + + for (uint32_t i = 0; i < uint32_t(D3D9FFVSMembers::InverseOffset); i++) { + m_module.memberDecorateOffset(structType, i, offset); + offset += sizeof(Matrix4); + m_module.memberDecorateMatrixStride(structType, i, 16); + m_module.memberDecorate(structType, i, spv::DecorationRowMajor); + } + + for (uint32_t i = uint32_t(D3D9FFVSMembers::InverseOffset); i < uint32_t(D3D9FFVSMembers::Light0); i++) { + m_module.memberDecorateOffset(structType, i, offset); + offset += sizeof(Vector4); + } + + for (uint32_t i = 0; i < caps::MaxEnabledLights; i++) { + m_module.memberDecorateOffset(structType, uint32_t(D3D9FFVSMembers::Light0) + i, offset); + offset += sizeof(D3D9Light); + } + + for (uint32_t i = uint32_t(D3D9FFVSMembers::MaterialDiffuse); i < uint32_t(D3D9FFVSMembers::MaterialPower); i++) { + m_module.memberDecorateOffset(structType, i, offset); + offset += sizeof(Vector4); + } + + m_module.memberDecorateOffset(structType, uint32_t(D3D9FFVSMembers::MaterialPower), offset); + offset += sizeof(float); + + m_module.memberDecorateOffset(structType, uint32_t(D3D9FFVSMembers::TweenFactor), offset); + offset += sizeof(float); + + m_module.setDebugName(structType, "D3D9FixedFunctionVS"); + uint32_t member = 0; + m_module.setDebugMemberName(structType, member++, "WorldView"); + m_module.setDebugMemberName(structType, member++, "Normal"); + m_module.setDebugMemberName(structType, member++, "InverseView"); + m_module.setDebugMemberName(structType, member++, "Projection"); + + m_module.setDebugMemberName(structType, member++, "TexcoordTransform0"); + m_module.setDebugMemberName(structType, member++, "TexcoordTransform1"); + m_module.setDebugMemberName(structType, member++, "TexcoordTransform2"); + m_module.setDebugMemberName(structType, member++, "TexcoordTransform3"); + m_module.setDebugMemberName(structType, member++, "TexcoordTransform4"); + m_module.setDebugMemberName(structType, member++, "TexcoordTransform5"); + m_module.setDebugMemberName(structType, member++, "TexcoordTransform6"); + m_module.setDebugMemberName(structType, member++, "TexcoordTransform7"); + + m_module.setDebugMemberName(structType, member++, "ViewportInfo_InverseOffset"); + m_module.setDebugMemberName(structType, member++, "ViewportInfo_InverseExtent"); + + m_module.setDebugMemberName(structType, member++, "GlobalAmbient"); + + m_module.setDebugMemberName(structType, member++, "Light0"); + m_module.setDebugMemberName(structType, member++, "Light1"); + m_module.setDebugMemberName(structType, member++, "Light2"); + m_module.setDebugMemberName(structType, member++, "Light3"); + m_module.setDebugMemberName(structType, member++, "Light4"); + m_module.setDebugMemberName(structType, member++, "Light5"); + m_module.setDebugMemberName(structType, member++, "Light6"); + m_module.setDebugMemberName(structType, member++, "Light7"); + + m_module.setDebugMemberName(structType, member++, "Material_Diffuse"); + m_module.setDebugMemberName(structType, member++, "Material_Ambient"); + m_module.setDebugMemberName(structType, member++, "Material_Specular"); + m_module.setDebugMemberName(structType, member++, "Material_Emissive"); + m_module.setDebugMemberName(structType, member++, "Material_Power"); + + m_module.setDebugMemberName(structType, member++, "TweenFactor"); + + m_vs.constantBuffer = m_module.newVar( + m_module.defPointerType(structType, spv::StorageClassUniform), + spv::StorageClassUniform); + + m_module.setDebugName(m_vs.constantBuffer, "consts"); + + const uint32_t bindingId = computeResourceSlotId( + DxsoProgramType::VertexShader, DxsoBindingType::ConstantBuffer, + DxsoConstantBuffers::VSFixedFunction); + + m_module.decorateDescriptorSet(m_vs.constantBuffer, 0); + m_module.decorateBinding(m_vs.constantBuffer, bindingId); + + DxvkResourceSlot resource; + resource.slot = bindingId; + resource.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + resource.view = VK_IMAGE_VIEW_TYPE_MAX_ENUM; + resource.access = VK_ACCESS_UNIFORM_READ_BIT; + m_resourceSlots.push_back(resource); + } + + + void D3D9FFShaderCompiler::emitVertexBlendDecl() { + const uint32_t arrayType = m_module.defRuntimeArrayTypeUnique(m_mat4Type); + m_module.decorateArrayStride(arrayType, sizeof(Matrix4)); + + const uint32_t structType = m_module.defStructTypeUnique(1, &arrayType); + + m_module.memberDecorateMatrixStride(structType, 0, 16); + m_module.memberDecorate(structType, 0, spv::DecorationRowMajor); + + m_module.decorate(structType, spv::DecorationBufferBlock); + + m_module.memberDecorateOffset(structType, 0, 0); + + m_module.setDebugName(structType, "D3D9FF_VertexBlendData"); + m_module.setDebugMemberName(structType, 0, "WorldViewArray"); + + m_vs.vertexBlendData = m_module.newVar( + m_module.defPointerType(structType, spv::StorageClassUniform), + spv::StorageClassUniform); + + m_module.setDebugName(m_vs.vertexBlendData, "VertexBlendData"); + + const uint32_t bindingId = computeResourceSlotId( + DxsoProgramType::VertexShader, DxsoBindingType::ConstantBuffer, + DxsoConstantBuffers::VSVertexBlendData); + + m_module.decorateDescriptorSet(m_vs.vertexBlendData, 0); + m_module.decorateBinding(m_vs.vertexBlendData, bindingId); + + m_module.decorate(m_vs.vertexBlendData, spv::DecorationNonWritable); + + DxvkResourceSlot resource; + resource.slot = bindingId; + resource.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + resource.view = VK_IMAGE_VIEW_TYPE_MAX_ENUM; + resource.access = VK_ACCESS_SHADER_READ_BIT; + m_resourceSlots.push_back(resource); + } + + + void D3D9FFShaderCompiler::setupVS() { + setupRenderStateInfo(); + + // VS Caps + m_module.enableCapability(spv::CapabilityClipDistance); + + emitLightTypeDecl(); + emitBaseBufferDecl(); + + if (m_vsKey.Data.Contents.VertexBlendMode == D3D9FF_VertexBlendMode_Normal) + emitVertexBlendDecl(); + + // Load constants + auto LoadConstant = [&](uint32_t type, uint32_t idx) { + uint32_t offset = m_module.constu32(idx); + uint32_t typePtr = m_module.defPointerType(type, spv::StorageClassUniform); + + return m_module.opLoad(type, + m_module.opAccessChain(typePtr, m_vs.constantBuffer, 1, &offset)); + }; + + m_vs.constants.worldview = LoadConstant(m_mat4Type, uint32_t(D3D9FFVSMembers::WorldViewMatrix)); + m_vs.constants.normal = LoadConstant(m_mat4Type, uint32_t(D3D9FFVSMembers::NormalMatrix)); + m_vs.constants.inverseView = LoadConstant(m_mat4Type, uint32_t(D3D9FFVSMembers::InverseViewMatrix)); + m_vs.constants.proj = LoadConstant(m_mat4Type, uint32_t(D3D9FFVSMembers::ProjMatrix)); + + for (uint32_t i = 0; i < caps::TextureStageCount; i++) + m_vs.constants.texcoord[i] = LoadConstant(m_mat4Type, uint32_t(D3D9FFVSMembers::Texcoord0) + i); + + m_vs.constants.invOffset = LoadConstant(m_vec4Type, uint32_t(D3D9FFVSMembers::InverseOffset)); + m_vs.constants.invExtent = LoadConstant(m_vec4Type, uint32_t(D3D9FFVSMembers::InverseExtent)); + + m_vs.constants.globalAmbient = LoadConstant(m_vec4Type, uint32_t(D3D9FFVSMembers::GlobalAmbient)); + + m_vs.constants.materialDiffuse = LoadConstant(m_vec4Type, uint32_t(D3D9FFVSMembers::MaterialDiffuse)); + m_vs.constants.materialAmbient = LoadConstant(m_vec4Type, uint32_t(D3D9FFVSMembers::MaterialAmbient)); + m_vs.constants.materialSpecular = LoadConstant(m_vec4Type, uint32_t(D3D9FFVSMembers::MaterialSpecular)); + m_vs.constants.materialEmissive = LoadConstant(m_vec4Type, uint32_t(D3D9FFVSMembers::MaterialEmissive)); + m_vs.constants.materialPower = LoadConstant(m_floatType, uint32_t(D3D9FFVSMembers::MaterialPower)); + m_vs.constants.tweenFactor = LoadConstant(m_floatType, uint32_t(D3D9FFVSMembers::TweenFactor)); + + // Do IO + m_vs.in.POSITION = declareIO(true, DxsoSemantic{ DxsoUsage::Position, 0 }); + m_vs.in.NORMAL = declareIO(true, DxsoSemantic{ DxsoUsage::Normal, 0 }); + + if (m_vsKey.Data.Contents.VertexBlendMode == D3D9FF_VertexBlendMode_Tween) { + m_vs.in.POSITION1 = declareIO(true, DxsoSemantic{ DxsoUsage::Position, 1 }); + m_vs.in.NORMAL1 = declareIO(true, DxsoSemantic{ DxsoUsage::Normal, 1 }); + } + else { + m_isgn.elemCount++; + m_isgn.elemCount++; + } + + for (uint32_t i = 0; i < caps::TextureStageCount; i++) + m_vs.in.TEXCOORD[i] = declareIO(true, DxsoSemantic{ DxsoUsage::Texcoord, i }); + + if (m_vsKey.Data.Contents.HasColor0) + m_vs.in.COLOR[0] = declareIO(true, DxsoSemantic{ DxsoUsage::Color, 0 }); + else { + m_vs.in.COLOR[0] = m_module.constvec4f32(1.0f, 1.0f, 1.0f, 1.0f); + m_isgn.elemCount++; + } + + if (m_vsKey.Data.Contents.HasColor1) + m_vs.in.COLOR[1] = declareIO(true, DxsoSemantic{ DxsoUsage::Color, 1 }); + else { + m_vs.in.COLOR[1] = m_module.constvec4f32(0.0f, 0.0f, 0.0f, 0.0f); + m_isgn.elemCount++; + } + + if (m_vsKey.Data.Contents.HasFog) + m_vs.in.FOG = declareIO(true, DxsoSemantic{ DxsoUsage::Fog, 0 }); + else + m_isgn.elemCount++; + + if (m_vsKey.Data.Contents.HasPointSize) + m_vs.in.POINTSIZE = declareIO(true, DxsoSemantic{ DxsoUsage::PointSize, 0 }); + else + m_isgn.elemCount++; + + if (m_vsKey.Data.Contents.VertexBlendMode == D3D9FF_VertexBlendMode_Normal) { + m_vs.in.BLENDWEIGHT = declareIO(true, DxsoSemantic{ DxsoUsage::BlendWeight, 0 }); + m_vs.in.BLENDINDICES = declareIO(true, DxsoSemantic{ DxsoUsage::BlendIndices, 0 }); + } + else { + m_isgn.elemCount++; + m_isgn.elemCount++; + } + + // Declare Outputs + m_vs.out.POSITION = declareIO(false, DxsoSemantic{ DxsoUsage::Position, 0 }, spv::BuiltInPosition); + if (m_options.invariantPosition) + m_module.decorate(m_vs.out.POSITION, spv::DecorationInvariant); + + m_vs.out.POINTSIZE = declareIO(false, DxsoSemantic{ DxsoUsage::PointSize, 0 }, spv::BuiltInPointSize); + + m_vs.out.NORMAL = declareIO(false, DxsoSemantic{ DxsoUsage::Normal, 0 }); + + for (uint32_t i = 0; i < caps::TextureStageCount; i++) + m_vs.out.TEXCOORD[i] = declareIO(false, DxsoSemantic{ DxsoUsage::Texcoord, i }); + + m_vs.out.COLOR[0] = declareIO(false, DxsoSemantic{ DxsoUsage::Color, 0 }); + m_vs.out.COLOR[1] = declareIO(false, DxsoSemantic{ DxsoUsage::Color, 1 }); + + m_vs.out.FOG = declareIO(false, DxsoSemantic{ DxsoUsage::Fog, 0 }); + } + + + void D3D9FFShaderCompiler::compilePS() { + setupPS(); + + uint32_t diffuse = m_ps.in.COLOR[0]; + uint32_t specular = m_ps.in.COLOR[1]; + + // Current starts of as equal to diffuse. + uint32_t current = diffuse; + // Temp starts off as equal to vec4(0) + uint32_t temp = m_module.constvec4f32(0.0f, 0.0f, 0.0f, 0.0f); + + uint32_t texture = m_module.constvec4f32(0.0f, 0.0f, 0.0f, 1.0f); + + for (uint32_t i = 0; i < caps::TextureStageCount; i++) { + const auto& stage = m_fsKey.Stages[i].Contents; + + bool processedTexture = false; + + auto DoBumpmapCoords = [&](uint32_t typeId, uint32_t baseCoords) { + uint32_t stage = i - 1; + + uint32_t coords = baseCoords; + for (uint32_t i = 0; i < 2; i++) { + std::array indices = { 0, 1, 2, 3 }; + + uint32_t tc_m_n = m_module.opCompositeExtract(m_floatType, coords, 1, &i); + + uint32_t offset = m_module.constu32(D3D9SharedPSStages_Count * stage + D3D9SharedPSStages_BumpEnvMat0 + i); + uint32_t bm = m_module.opAccessChain(m_module.defPointerType(m_vec2Type, spv::StorageClassUniform), + m_ps.sharedState, 1, &offset); + bm = m_module.opLoad(m_vec2Type, bm); + + uint32_t t = m_module.opVectorShuffle(m_vec2Type, texture, texture, 2, indices.data()); + + uint32_t dot = m_module.opDot(m_floatType, bm, t); + + uint32_t result = m_module.opFAdd(m_floatType, tc_m_n, dot); + coords = m_module.opCompositeInsert(typeId, result, coords, 1, &i); + } + + return coords; + }; + + auto GetTexture = [&]() { + if (!processedTexture) { + SpirvImageOperands imageOperands; + uint32_t imageVarId = m_module.opLoad(m_ps.samplers[i].typeId, m_ps.samplers[i].varId); + + uint32_t texcoordCnt = m_ps.samplers[i].texcoordCnt; + + // Add one for the texcoord count + // if we need to include the divider + if (m_fsKey.Stages[i].Contents.Projected) + texcoordCnt++; + + std::array indices = { 0, 1, 2, 3 }; + + uint32_t texcoord = m_ps.in.TEXCOORD[i]; + uint32_t texcoord_t = m_module.defVectorType(m_floatType, texcoordCnt); + texcoord = m_module.opVectorShuffle(texcoord_t, + texcoord, texcoord, texcoordCnt, indices.data()); + + uint32_t projIdx = m_fsKey.Stages[i].Contents.ProjectedCount; + if (projIdx == 0) + projIdx = texcoordCnt; + else + projIdx--; + + uint32_t projValue = 0; + + if (m_fsKey.Stages[i].Contents.Projected) { + projValue = m_module.opCompositeExtract(m_floatType, m_ps.in.TEXCOORD[i], 1, &projIdx); + uint32_t insertIdx = texcoordCnt - 1; + texcoord = m_module.opCompositeInsert(texcoord_t, projValue, texcoord, 1, &insertIdx); + } + + bool shouldProject = m_fsKey.Stages[i].Contents.Projected; + + if (i != 0 && ( + m_fsKey.Stages[i - 1].Contents.ColorOp == D3DTOP_BUMPENVMAP || + m_fsKey.Stages[i - 1].Contents.ColorOp == D3DTOP_BUMPENVMAPLUMINANCE)) { + if (shouldProject) { + uint32_t projRcp = m_module.opFDiv(m_floatType, m_module.constf32(1.0), projValue); + texcoord = m_module.opVectorTimesScalar(texcoord_t, texcoord, projRcp); + } + + texcoord = DoBumpmapCoords(texcoord_t, texcoord); + + shouldProject = false; + } + + if (shouldProject) + texture = m_module.opImageSampleProjImplicitLod(m_vec4Type, imageVarId, texcoord, imageOperands); + else + texture = m_module.opImageSampleImplicitLod(m_vec4Type, imageVarId, texcoord, imageOperands); + + if (i != 0 && m_fsKey.Stages[i - 1].Contents.ColorOp == D3DTOP_BUMPENVMAPLUMINANCE) { + uint32_t index = m_module.constu32(D3D9SharedPSStages_Count * (i - 1) + D3D9SharedPSStages_BumpEnvLScale); + uint32_t lScale = m_module.opAccessChain(m_module.defPointerType(m_floatType, spv::StorageClassUniform), + m_ps.sharedState, 1, &index); + lScale = m_module.opLoad(m_floatType, lScale); + + index = m_module.constu32(D3D9SharedPSStages_Count * (i - 1) + D3D9SharedPSStages_BumpEnvLOffset); + uint32_t lOffset = m_module.opAccessChain(m_module.defPointerType(m_floatType, spv::StorageClassUniform), + m_ps.sharedState, 1, &index); + lOffset = m_module.opLoad(m_floatType, lOffset); + + uint32_t zIndex = 2; + uint32_t scale = m_module.opCompositeExtract(m_floatType, texture, 1, &zIndex); + scale = m_module.opFMul(m_floatType, scale, lScale); + scale = m_module.opFAdd(m_floatType, scale, lOffset); + scale = m_module.opFClamp(m_floatType, scale, m_module.constf32(0.0f), m_module.constf32(1.0)); + + texture = m_module.opVectorTimesScalar(m_vec4Type, texture, scale); + } + + uint32_t bool_t = m_module.defBoolType(); + uint32_t bvec4_t = m_module.defVectorType(bool_t, 4); + std::array boundIndices = { m_ps.samplers[i].bound, m_ps.samplers[i].bound, m_ps.samplers[i].bound, m_ps.samplers[i].bound }; + uint32_t bound4 = m_module.opCompositeConstruct(bvec4_t, boundIndices.size(), boundIndices.data()); + texture = m_module.opSelect(m_vec4Type, bound4, texture, m_module.constvec4f32(0.0f, 0.0f, 0.0f, 1.0f)); + } + + processedTexture = true; + + return texture; + }; + + auto ScalarReplicate = [&](uint32_t reg) { + std::array replicant = { reg, reg, reg, reg }; + return m_module.opCompositeConstruct(m_vec4Type, replicant.size(), replicant.data()); + }; + + auto AlphaReplicate = [&](uint32_t reg) { + uint32_t alphaComponentId = 3; + uint32_t alpha = m_module.opCompositeExtract(m_floatType, reg, 1, &alphaComponentId); + + return ScalarReplicate(alpha); + }; + + auto Complement = [&](uint32_t reg) { + return m_module.opFSub(m_vec4Type, + m_module.constvec4f32(1.0f, 1.0f, 1.0f, 1.0f), + reg); + }; + + auto Saturate = [&](uint32_t reg) { + return m_module.opFClamp(m_vec4Type, reg, + m_module.constvec4f32(0.0f, 0.0f, 0.0f, 0.0f), + m_module.constvec4f32(1.0f, 1.0f, 1.0f, 1.0f)); + }; + + auto GetArg = [&] (uint32_t arg) { + uint32_t reg = m_module.constvec4f32(1.0f, 1.0f, 1.0f, 1.0f); + + switch (arg & D3DTA_SELECTMASK) { + case D3DTA_CONSTANT: { + uint32_t offset = m_module.constu32(D3D9SharedPSStages_Count * i + D3D9SharedPSStages_Constant); + uint32_t ptr = m_module.opAccessChain(m_module.defPointerType(m_vec4Type, spv::StorageClassUniform), + m_ps.sharedState, 1, &offset); + + reg = m_module.opLoad(m_vec4Type, ptr); + break; + } + case D3DTA_CURRENT: + reg = current; + break; + case D3DTA_DIFFUSE: + reg = diffuse; + break; + case D3DTA_SPECULAR: + reg = specular; + break; + case D3DTA_TEMP: + reg = temp; + break; + case D3DTA_TEXTURE: + reg = GetTexture(); + break; + case D3DTA_TFACTOR: + reg = m_ps.constants.textureFactor; + break; + default: + break; + } + + // reg = 1 - reg + if (arg & D3DTA_COMPLEMENT) + reg = Complement(reg); + + // reg = reg.wwww + if (arg & D3DTA_ALPHAREPLICATE) + reg = AlphaReplicate(reg); + + return reg; + }; + + auto DoOp = [&](D3DTEXTUREOP op, uint32_t dst, std::array arg) { + switch (op) { + case D3DTOP_SELECTARG1: + dst = arg[1]; + break; + + case D3DTOP_SELECTARG2: + dst = arg[2]; + break; + + case D3DTOP_MODULATE4X: + dst = m_module.opFMul(m_vec4Type, arg[1], arg[2]); + dst = m_module.opVectorTimesScalar(m_vec4Type, dst, m_module.constf32(4.0f)); + dst = Saturate(dst); + break; + + case D3DTOP_MODULATE2X: + dst = m_module.opFMul(m_vec4Type, arg[1], arg[2]); + dst = m_module.opVectorTimesScalar(m_vec4Type, dst, m_module.constf32(2.0f)); + dst = Saturate(dst); + break; + + case D3DTOP_MODULATE: + dst = m_module.opFMul(m_vec4Type, arg[1], arg[2]); + break; + + case D3DTOP_ADDSIGNED2X: + arg[2] = m_module.opFSub(m_vec4Type, arg[2], + m_module.constvec4f32(0.5f, 0.5f, 0.5f, 0.5f)); + + dst = m_module.opFAdd(m_vec4Type, arg[1], arg[2]); + dst = m_module.opVectorTimesScalar(m_vec4Type, dst, m_module.constf32(2.0f)); + dst = Saturate(dst); + break; + + case D3DTOP_ADDSIGNED: + arg[2] = m_module.opFSub(m_vec4Type, arg[2], + m_module.constvec4f32(0.5f, 0.5f, 0.5f, 0.5f)); + + dst = m_module.opFAdd(m_vec4Type, arg[1], arg[2]); + dst = Saturate(dst); + break; + + case D3DTOP_ADD: + dst = m_module.opFAdd(m_vec4Type, arg[1], arg[2]); + dst = Saturate(dst); + break; + + case D3DTOP_SUBTRACT: + dst = m_module.opFSub(m_vec4Type, arg[1], arg[2]); + dst = Saturate(dst); + break; + + case D3DTOP_ADDSMOOTH: + dst = m_module.opFFma(m_vec4Type, Complement(arg[1]), arg[2], arg[1]); + dst = Saturate(dst); + break; + + case D3DTOP_BLENDDIFFUSEALPHA: + dst = m_module.opFMix(m_vec4Type, arg[2], arg[1], AlphaReplicate(diffuse)); + break; + + case D3DTOP_BLENDTEXTUREALPHA: + dst = m_module.opFMix(m_vec4Type, arg[2], arg[1], AlphaReplicate(GetTexture())); + break; + + case D3DTOP_BLENDFACTORALPHA: + dst = m_module.opFMix(m_vec4Type, arg[2], arg[1], AlphaReplicate(m_ps.constants.textureFactor)); + break; + + case D3DTOP_BLENDTEXTUREALPHAPM: + dst = m_module.opFFma(m_vec4Type, arg[2], Complement(AlphaReplicate(GetTexture())), arg[1]); + dst = Saturate(dst); + break; + + case D3DTOP_BLENDCURRENTALPHA: + dst = m_module.opFMix(m_vec4Type, arg[2], arg[1], AlphaReplicate(current)); + break; + + case D3DTOP_PREMODULATE: + Logger::warn("D3DTOP_PREMODULATE: not implemented"); + break; + + case D3DTOP_MODULATEALPHA_ADDCOLOR: + dst = m_module.opFFma(m_vec4Type, AlphaReplicate(arg[1]), arg[2], arg[1]); + dst = Saturate(dst); + break; + + case D3DTOP_MODULATECOLOR_ADDALPHA: + dst = m_module.opFFma(m_vec4Type, arg[1], arg[2], AlphaReplicate(arg[1])); + dst = Saturate(dst); + break; + + case D3DTOP_MODULATEINVALPHA_ADDCOLOR: + dst = m_module.opFFma(m_vec4Type, Complement(AlphaReplicate(arg[1])), arg[2], arg[1]); + dst = Saturate(dst); + break; + + case D3DTOP_MODULATEINVCOLOR_ADDALPHA: + dst = m_module.opFFma(m_vec4Type, Complement(arg[1]), arg[2], AlphaReplicate(arg[1])); + dst = Saturate(dst); + break; + + case D3DTOP_BUMPENVMAPLUMINANCE: + case D3DTOP_BUMPENVMAP: + // Load texture for the next stage... + texture = GetTexture(); + break; + + case D3DTOP_DOTPRODUCT3: { + // Get vec3 of arg1 & 2 + uint32_t vec3Type = m_module.defVectorType(m_floatType, 3); + std::array indices = { 0, 1, 2 }; + arg[1] = m_module.opVectorShuffle(vec3Type, arg[1], arg[1], indices.size(), indices.data()); + arg[2] = m_module.opVectorShuffle(vec3Type, arg[2], arg[2], indices.size(), indices.data()); + + // Bias according to spec. + arg[1] = m_module.opFSub(vec3Type, arg[1], m_module.constvec3f32(0.5f, 0.5f, 0.5f)); + arg[2] = m_module.opFSub(vec3Type, arg[2], m_module.constvec3f32(0.5f, 0.5f, 0.5f)); + + // Do the dotting! + dst = m_module.opDot(m_floatType, arg[1], arg[2]); + + // Multiply by 4 and replicate -> vec4 + dst = m_module.opFMul(m_floatType, dst, m_module.constf32(4.0f)); + dst = ScalarReplicate(dst); + + // Saturate + dst = Saturate(dst); + + break; + } + + case D3DTOP_MULTIPLYADD: + dst = m_module.opFFma(m_vec4Type, arg[1], arg[2], arg[0]); + dst = Saturate(dst); + break; + + case D3DTOP_LERP: + dst = m_module.opFMix(m_vec4Type, arg[2], arg[1], arg[0]); + break; + + default: + Logger::warn("Unhandled texture op!"); + break; + } + + return dst; + }; + + uint32_t& dst = stage.ResultIsTemp ? temp : current; + + D3DTEXTUREOP colorOp = (D3DTEXTUREOP)stage.ColorOp; + + // This cancels all subsequent stages. + if (colorOp == D3DTOP_DISABLE) + break; + + std::array colorArgs = { + stage.ColorArg0, + stage.ColorArg1, + stage.ColorArg2}; + + D3DTEXTUREOP alphaOp = (D3DTEXTUREOP)stage.AlphaOp; + std::array alphaArgs = { + stage.AlphaArg0, + stage.AlphaArg1, + stage.AlphaArg2}; + + auto ProcessArgs = [&](auto op, auto& args) { + for (uint32_t& arg : args) + arg = GetArg(arg); + }; + + // Fast path if alpha/color path is identical. + // D3DTOP_DOTPRODUCT3 also has special quirky behaviour here. + const bool fastPath = colorOp == alphaOp && colorArgs == alphaArgs; + if (fastPath || colorOp == D3DTOP_DOTPRODUCT3) { + if (colorOp != D3DTOP_DISABLE) { + ProcessArgs(colorOp, colorArgs); + dst = DoOp(colorOp, dst, colorArgs); + } + } + else { + std::array indices = { 0, 1, 2, 4 + 3 }; + + uint32_t colorResult = dst; + uint32_t alphaResult = dst; + if (colorOp != D3DTOP_DISABLE) { + ProcessArgs(colorOp, colorArgs); + colorResult = DoOp(colorOp, dst, colorArgs); + } + + if (alphaOp != D3DTOP_DISABLE) { + ProcessArgs(alphaOp, alphaArgs); + alphaResult = DoOp(alphaOp, dst, alphaArgs); + } + + // src0.x, src0.y, src0.z src1.w + if (colorResult != dst) + dst = m_module.opVectorShuffle(m_vec4Type, colorResult, dst, indices.size(), indices.data()); + + // src0.x, src0.y, src0.z src1.w + // But we flip src0, src1 to be inverse of color. + if (alphaResult != dst) + dst = m_module.opVectorShuffle(m_vec4Type, dst, alphaResult, indices.size(), indices.data()); + } + } + + if (m_fsKey.Stages[0].Contents.GlobalSpecularEnable) { + uint32_t specular = m_module.opFMul(m_vec4Type, m_ps.in.COLOR[1], m_module.constvec4f32(1.0f, 1.0f, 1.0f, 0.0f)); + + current = m_module.opFAdd(m_vec4Type, current, specular); + } + + D3D9FogContext fogCtx; + fogCtx.IsPixel = true; + fogCtx.RangeFog = false; + fogCtx.RenderState = m_rsBlock; + fogCtx.vPos = m_ps.in.POS; + fogCtx.vFog = m_ps.in.FOG; + fogCtx.oColor = current; + fogCtx.IsFixedFunction = true; + fogCtx.IsPositionT = false; + fogCtx.HasSpecular = false; + fogCtx.Specular = 0; + current = DoFixedFunctionFog(m_module, fogCtx); + + m_module.opStore(m_ps.out.COLOR, current); + + alphaTestPS(); + } + + void D3D9FFShaderCompiler::setupPS() { + setupRenderStateInfo(); + + // PS Caps + m_module.enableCapability(spv::CapabilityDerivativeControl); + + m_module.setExecutionMode(m_entryPointId, + spv::ExecutionModeOriginUpperLeft); + + uint32_t pointCoord = GetPointCoord(m_module, m_entryPointInterfaces); + auto pointInfo = GetPointSizeInfoPS(m_module, m_rsBlock); + + // We need to replace TEXCOORD inputs with gl_PointCoord + // if D3DRS_POINTSPRITEENABLE is set. + for (uint32_t i = 0; i < caps::TextureStageCount; i++) { + m_ps.in.TEXCOORD[i] = declareIO(true, DxsoSemantic{ DxsoUsage::Texcoord, i }); + m_ps.in.TEXCOORD[i] = m_module.opSelect(m_vec4Type, pointInfo.isSprite, pointCoord, m_ps.in.TEXCOORD[i]); + } + + m_ps.in.COLOR[0] = declareIO(true, DxsoSemantic{ DxsoUsage::Color, 0 }); + m_ps.in.COLOR[1] = declareIO(true, DxsoSemantic{ DxsoUsage::Color, 1 }); + + m_ps.in.FOG = declareIO(true, DxsoSemantic{ DxsoUsage::Fog, 0 }); + m_ps.in.POS = declareIO(true, DxsoSemantic{ DxsoUsage::Position, 0 }, spv::BuiltInFragCoord); + + m_ps.out.COLOR = declareIO(false, DxsoSemantic{ DxsoUsage::Color, 0 }); + + // Constant Buffer for PS. + std::array members = { + m_vec4Type // Texture Factor + }; + + const uint32_t structType = + m_module.defStructType(members.size(), members.data()); + + m_module.decorateBlock(structType); + uint32_t offset = 0; + + for (uint32_t i = 0; i < uint32_t(D3D9FFPSMembers::MemberCount); i++) { + m_module.memberDecorateOffset(structType, i, offset); + offset += sizeof(Vector4); + } + + m_module.setDebugName(structType, "D3D9FixedFunctionPS"); + m_module.setDebugMemberName(structType, 0, "textureFactor"); + + m_ps.constantBuffer = m_module.newVar( + m_module.defPointerType(structType, spv::StorageClassUniform), + spv::StorageClassUniform); + + m_module.setDebugName(m_ps.constantBuffer, "consts"); + + const uint32_t bindingId = computeResourceSlotId( + DxsoProgramType::PixelShader, DxsoBindingType::ConstantBuffer, + DxsoConstantBuffers::PSFixedFunction); + + m_module.decorateDescriptorSet(m_ps.constantBuffer, 0); + m_module.decorateBinding(m_ps.constantBuffer, bindingId); + + DxvkResourceSlot resource; + resource.slot = bindingId; + resource.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + resource.view = VK_IMAGE_VIEW_TYPE_MAX_ENUM; + resource.access = VK_ACCESS_UNIFORM_READ_BIT; + m_resourceSlots.push_back(resource); + + // Load constants + auto LoadConstant = [&](uint32_t type, uint32_t idx) { + uint32_t offset = m_module.constu32(idx); + uint32_t typePtr = m_module.defPointerType(type, spv::StorageClassUniform); + + return m_module.opLoad(type, + m_module.opAccessChain(typePtr, m_ps.constantBuffer, 1, &offset)); + }; + + m_ps.constants.textureFactor = LoadConstant(m_vec4Type, uint32_t(D3D9FFPSMembers::TextureFactor)); + + // Samplers + for (uint32_t i = 0; i < caps::TextureStageCount; i++) { + auto& sampler = m_ps.samplers[i]; + D3DRESOURCETYPE type = D3DRESOURCETYPE(m_fsKey.Stages[i].Contents.Type + D3DRTYPE_TEXTURE); + + spv::Dim dimensionality; + VkImageViewType viewType; + + switch (type) { + default: + case D3DRTYPE_TEXTURE: + dimensionality = spv::Dim2D; + sampler.texcoordCnt = 2; + viewType = VK_IMAGE_VIEW_TYPE_2D; + break; + case D3DRTYPE_CUBETEXTURE: + dimensionality = spv::DimCube; + sampler.texcoordCnt = 3; + viewType = VK_IMAGE_VIEW_TYPE_CUBE; + break; + case D3DRTYPE_VOLUMETEXTURE: + dimensionality = spv::Dim3D; + sampler.texcoordCnt = 3; + viewType = VK_IMAGE_VIEW_TYPE_3D; + break; + } + + sampler.typeId = m_module.defImageType( + m_module.defFloatType(32), + dimensionality, 0, 0, 0, 1, + spv::ImageFormatUnknown); + + sampler.typeId = m_module.defSampledImageType(sampler.typeId); + + sampler.varId = m_module.newVar( + m_module.defPointerType( + sampler.typeId, spv::StorageClassUniformConstant), + spv::StorageClassUniformConstant); + + std::string name = str::format("s", i); + m_module.setDebugName(sampler.varId, name.c_str()); + + const uint32_t bindingId = computeResourceSlotId(DxsoProgramType::PixelShader, + DxsoBindingType::Image, i); + + sampler.bound = m_module.specConstBool(true); + m_module.decorateSpecId(sampler.bound, bindingId); + m_module.setDebugName(sampler.bound, + str::format("s", i, "_bound").c_str()); + + m_module.decorateDescriptorSet(sampler.varId, 0); + m_module.decorateBinding(sampler.varId, bindingId); + + // Store descriptor info for the shader interface + DxvkResourceSlot resource; + resource.slot = bindingId; + resource.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + resource.view = viewType; + resource.access = VK_ACCESS_SHADER_READ_BIT; + m_resourceSlots.push_back(resource); + } + + emitPsSharedConstants(); + } + + + void D3D9FFShaderCompiler::emitPsSharedConstants() { + m_ps.sharedState = GetSharedConstants(m_module); + + const uint32_t bindingId = computeResourceSlotId( + m_programType, DxsoBindingType::ConstantBuffer, + PSShared); + + m_module.decorateDescriptorSet(m_ps.sharedState, 0); + m_module.decorateBinding(m_ps.sharedState, bindingId); + + DxvkResourceSlot resource; + resource.slot = bindingId; + resource.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + resource.view = VK_IMAGE_VIEW_TYPE_MAX_ENUM; + resource.access = VK_ACCESS_UNIFORM_READ_BIT; + m_resourceSlots.push_back(resource); + } + + + void D3D9FFShaderCompiler::emitVsClipping(uint32_t vtx) { + uint32_t worldPos = m_module.opMatrixTimesVector(m_vec4Type, m_vs.constants.inverseView, vtx); + + uint32_t clipPlaneCountId = m_module.constu32(caps::MaxClipPlanes); + + uint32_t floatType = m_module.defFloatType(32); + uint32_t vec4Type = m_module.defVectorType(floatType, 4); + + // Declare uniform buffer containing clip planes + uint32_t clipPlaneArray = m_module.defArrayTypeUnique(vec4Type, clipPlaneCountId); + uint32_t clipPlaneStruct = m_module.defStructTypeUnique(1, &clipPlaneArray); + uint32_t clipPlaneBlock = m_module.newVar( + m_module.defPointerType(clipPlaneStruct, spv::StorageClassUniform), + spv::StorageClassUniform); + + m_module.decorateArrayStride (clipPlaneArray, 16); + + m_module.setDebugName (clipPlaneStruct, "clip_info_t"); + m_module.setDebugMemberName (clipPlaneStruct, 0, "clip_planes"); + m_module.decorate (clipPlaneStruct, spv::DecorationBlock); + m_module.memberDecorateOffset (clipPlaneStruct, 0, 0); + + uint32_t bindingId = computeResourceSlotId( + DxsoProgramType::VertexShader, + DxsoBindingType::ConstantBuffer, + DxsoConstantBuffers::VSClipPlanes); + + m_module.setDebugName (clipPlaneBlock, "clip_info"); + m_module.decorateDescriptorSet(clipPlaneBlock, 0); + m_module.decorateBinding (clipPlaneBlock, bindingId); + + DxvkResourceSlot resource; + resource.slot = bindingId; + resource.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + resource.view = VK_IMAGE_VIEW_TYPE_MAX_ENUM; + resource.access = VK_ACCESS_UNIFORM_READ_BIT; + m_resourceSlots.push_back(resource); + + // Declare output array for clip distances + uint32_t clipDistArray = m_module.newVar( + m_module.defPointerType( + m_module.defArrayType(floatType, clipPlaneCountId), + spv::StorageClassOutput), + spv::StorageClassOutput); + + m_module.decorateBuiltIn(clipDistArray, spv::BuiltInClipDistance); + m_entryPointInterfaces.push_back(clipDistArray); + + // Compute clip distances + for (uint32_t i = 0; i < caps::MaxClipPlanes; i++) { + std::array blockMembers = {{ + m_module.constu32(0), + m_module.constu32(i), + }}; + + uint32_t planeId = m_module.opLoad(vec4Type, + m_module.opAccessChain( + m_module.defPointerType(vec4Type, spv::StorageClassUniform), + clipPlaneBlock, blockMembers.size(), blockMembers.data())); + + uint32_t distId = m_module.opDot(floatType, worldPos, planeId); + + m_module.opStore( + m_module.opAccessChain( + m_module.defPointerType(floatType, spv::StorageClassOutput), + clipDistArray, 1, &blockMembers[1]), + distId); + } + } + + + void D3D9FFShaderCompiler::alphaTestPS() { + // Alpha testing + uint32_t boolType = m_module.defBoolType(); + uint32_t floatPtr = m_module.defPointerType(m_floatType, spv::StorageClassPushConstant); + + // Declare spec constants for render states + uint32_t alphaFuncId = m_module.specConst32(m_module.defIntType(32, 0), 0); + m_module.setDebugName(alphaFuncId, "alpha_func"); + m_module.decorateSpecId(alphaFuncId, getSpecId(D3D9SpecConstantId::AlphaCompareOp)); + + // Implement alpha test + auto oC0 = m_ps.out.COLOR; + // Labels for the alpha test + std::array atestCaseLabels = { { + { uint32_t(VK_COMPARE_OP_NEVER), m_module.allocateId() }, + { uint32_t(VK_COMPARE_OP_LESS), m_module.allocateId() }, + { uint32_t(VK_COMPARE_OP_EQUAL), m_module.allocateId() }, + { uint32_t(VK_COMPARE_OP_LESS_OR_EQUAL), m_module.allocateId() }, + { uint32_t(VK_COMPARE_OP_GREATER), m_module.allocateId() }, + { uint32_t(VK_COMPARE_OP_NOT_EQUAL), m_module.allocateId() }, + { uint32_t(VK_COMPARE_OP_GREATER_OR_EQUAL), m_module.allocateId() }, + { uint32_t(VK_COMPARE_OP_ALWAYS), m_module.allocateId() }, + } }; + + uint32_t atestBeginLabel = m_module.allocateId(); + uint32_t atestTestLabel = m_module.allocateId(); + uint32_t atestDiscardLabel = m_module.allocateId(); + uint32_t atestKeepLabel = m_module.allocateId(); + uint32_t atestSkipLabel = m_module.allocateId(); + + // if (alpha_test) { ... } + uint32_t isNotAlways = m_module.opINotEqual(boolType, alphaFuncId, m_module.constu32(VK_COMPARE_OP_ALWAYS)); + m_module.opSelectionMerge(atestSkipLabel, spv::SelectionControlMaskNone); + m_module.opBranchConditional(isNotAlways, atestBeginLabel, atestSkipLabel); + m_module.opLabel(atestBeginLabel); + + // Load alpha component + uint32_t alphaComponentId = 3; + uint32_t alphaId = m_module.opCompositeExtract(m_floatType, + m_module.opLoad(m_vec4Type, oC0), + 1, &alphaComponentId); + + // Load alpha reference + uint32_t alphaRefMember = m_module.constu32(uint32_t(D3D9RenderStateItem::AlphaRef)); + uint32_t alphaRefId = m_module.opLoad(m_floatType, + m_module.opAccessChain(floatPtr, m_rsBlock, 1, &alphaRefMember)); + + // switch (alpha_func) { ... } + m_module.opSelectionMerge(atestTestLabel, spv::SelectionControlMaskNone); + m_module.opSwitch(alphaFuncId, + atestCaseLabels[uint32_t(VK_COMPARE_OP_ALWAYS)].labelId, + atestCaseLabels.size(), + atestCaseLabels.data()); + + std::array atestVariables; + + for (uint32_t i = 0; i < atestCaseLabels.size(); i++) { + m_module.opLabel(atestCaseLabels[i].labelId); + + atestVariables[i].labelId = atestCaseLabels[i].labelId; + atestVariables[i].varId = [&] { + switch (VkCompareOp(atestCaseLabels[i].literal)) { + case VK_COMPARE_OP_NEVER: return m_module.constBool(false); + case VK_COMPARE_OP_LESS: return m_module.opFOrdLessThan(boolType, alphaId, alphaRefId); + case VK_COMPARE_OP_EQUAL: return m_module.opFOrdEqual(boolType, alphaId, alphaRefId); + case VK_COMPARE_OP_LESS_OR_EQUAL: return m_module.opFOrdLessThanEqual(boolType, alphaId, alphaRefId); + case VK_COMPARE_OP_GREATER: return m_module.opFOrdGreaterThan(boolType, alphaId, alphaRefId); + case VK_COMPARE_OP_NOT_EQUAL: return m_module.opFOrdNotEqual(boolType, alphaId, alphaRefId); + case VK_COMPARE_OP_GREATER_OR_EQUAL: return m_module.opFOrdGreaterThanEqual(boolType, alphaId, alphaRefId); + default: + case VK_COMPARE_OP_ALWAYS: return m_module.constBool(true); + } + }(); + + m_module.opBranch(atestTestLabel); + } + + // end switch + m_module.opLabel(atestTestLabel); + + uint32_t atestResult = m_module.opPhi(boolType, + atestVariables.size(), + atestVariables.data()); + uint32_t atestDiscard = m_module.opLogicalNot(boolType, atestResult); + + // if (do_discard) { ... } + m_module.opSelectionMerge(atestKeepLabel, spv::SelectionControlMaskNone); + m_module.opBranchConditional(atestDiscard, atestDiscardLabel, atestKeepLabel); + + m_module.opLabel(atestDiscardLabel); + m_module.opKill(); + + // end if (do_discard) + m_module.opLabel(atestKeepLabel); + m_module.opBranch(atestSkipLabel); + + // end if (alpha_test) + m_module.opLabel(atestSkipLabel); + } + + + D3D9FFShader::D3D9FFShader( + D3D9DeviceEx* pDevice, + const D3D9FFShaderKeyVS& Key) { + Sha1Hash hash = Sha1Hash::compute(&Key, sizeof(Key)); + DxvkShaderKey shaderKey = { VK_SHADER_STAGE_VERTEX_BIT, hash }; + + std::string name = str::format("FF_", shaderKey.toString()); + + D3D9FFShaderCompiler compiler( + pDevice->GetDXVKDevice(), + Key, name, + pDevice->GetOptions()); + + m_shader = compiler.compile(); + m_isgn = compiler.isgn(); + + Dump(Key, name); + + m_shader->setShaderKey(shaderKey); + pDevice->GetDXVKDevice()->registerShader(m_shader); + } + + + D3D9FFShader::D3D9FFShader( + D3D9DeviceEx* pDevice, + const D3D9FFShaderKeyFS& Key) { + Sha1Hash hash = Sha1Hash::compute(&Key, sizeof(Key)); + DxvkShaderKey shaderKey = { VK_SHADER_STAGE_FRAGMENT_BIT, hash }; + + std::string name = str::format("FF_", shaderKey.toString()); + + D3D9FFShaderCompiler compiler( + pDevice->GetDXVKDevice(), + Key, name, + pDevice->GetOptions()); + + m_shader = compiler.compile(); + m_isgn = compiler.isgn(); + + Dump(Key, name); + + m_shader->setShaderKey(shaderKey); + pDevice->GetDXVKDevice()->registerShader(m_shader); + } + + template + void D3D9FFShader::Dump(const T& Key, const std::string& Name) { + const std::string dumpPath = env::getEnvVar("DXVK_SHADER_DUMP_PATH"); + + if (dumpPath.size() != 0) { + std::ofstream dumpStream( + str::tows(str::format(dumpPath, "/", Name, ".spv").c_str()).c_str(), + std::ios_base::binary | std::ios_base::trunc); + + m_shader->dump(dumpStream); + } + } + + + D3D9FFShader D3D9FFShaderModuleSet::GetShaderModule( + D3D9DeviceEx* pDevice, + const D3D9FFShaderKeyVS& ShaderKey) { + // Use the shader's unique key for the lookup + auto entry = m_vsModules.find(ShaderKey); + if (entry != m_vsModules.end()) + return entry->second; + + D3D9FFShader shader( + pDevice, ShaderKey); + + m_vsModules.insert({ShaderKey, shader}); + + return shader; + } + + + D3D9FFShader D3D9FFShaderModuleSet::GetShaderModule( + D3D9DeviceEx* pDevice, + const D3D9FFShaderKeyFS& ShaderKey) { + // Use the shader's unique key for the lookup + auto entry = m_fsModules.find(ShaderKey); + if (entry != m_fsModules.end()) + return entry->second; + + D3D9FFShader shader( + pDevice, ShaderKey); + + m_fsModules.insert({ShaderKey, shader}); + + return shader; + } + + + size_t D3D9FFShaderKeyHash::operator () (const D3D9FFShaderKeyVS& key) const { + DxvkHashState state; + + std::hash uint32hash; + + for (uint32_t i = 0; i < std::size(key.Data.Primitive); i++) + state.add(uint32hash(key.Data.Primitive[i])); + + return state; + } + + + size_t D3D9FFShaderKeyHash::operator () (const D3D9FFShaderKeyFS& key) const { + DxvkHashState state; + + std::hash uint32hash; + + for (uint32_t i = 0; i < caps::TextureStageCount; i++) { + for (uint32_t j = 0; j < std::size(key.Stages[i].Primitive); j++) + state.add(uint32hash(key.Stages[i].Primitive[j])); + } + + return state; + } + + + bool operator == (const D3D9FFShaderKeyVS& a, const D3D9FFShaderKeyVS& b) { + return std::memcmp(&a, &b, sizeof(D3D9FFShaderKeyVS)) == 0; + } + + + bool operator == (const D3D9FFShaderKeyFS& a, const D3D9FFShaderKeyFS& b) { + return std::memcmp(&a, &b, sizeof(D3D9FFShaderKeyFS)) == 0; + } + + + bool operator != (const D3D9FFShaderKeyVS& a, const D3D9FFShaderKeyVS& b) { + return !(a == b); + } + + + bool operator != (const D3D9FFShaderKeyFS& a, const D3D9FFShaderKeyFS& b) { + return !(a == b); + } + + + bool D3D9FFShaderKeyEq::operator () (const D3D9FFShaderKeyVS& a, const D3D9FFShaderKeyVS& b) const { + return a == b; + } + + + bool D3D9FFShaderKeyEq::operator () (const D3D9FFShaderKeyFS& a, const D3D9FFShaderKeyFS& b) const { + return a == b; + } + + + static inline DxsoIsgn CreateFixedFunctionIsgn() { + DxsoIsgn ffIsgn; + + ffIsgn.elems[ffIsgn.elemCount++].semantic = DxsoSemantic{ DxsoUsage::Position, 0 }; + ffIsgn.elems[ffIsgn.elemCount++].semantic = DxsoSemantic{ DxsoUsage::Normal, 0 }; + ffIsgn.elems[ffIsgn.elemCount++].semantic = DxsoSemantic{ DxsoUsage::Position, 1 }; + ffIsgn.elems[ffIsgn.elemCount++].semantic = DxsoSemantic{ DxsoUsage::Normal, 1 }; + for (uint32_t i = 0; i < 8; i++) + ffIsgn.elems[ffIsgn.elemCount++].semantic = DxsoSemantic{ DxsoUsage::Texcoord, i }; + ffIsgn.elems[ffIsgn.elemCount++].semantic = DxsoSemantic{ DxsoUsage::Color, 0 }; + ffIsgn.elems[ffIsgn.elemCount++].semantic = DxsoSemantic{ DxsoUsage::Color, 1 }; + ffIsgn.elems[ffIsgn.elemCount++].semantic = DxsoSemantic{ DxsoUsage::Fog, 0 }; + ffIsgn.elems[ffIsgn.elemCount++].semantic = DxsoSemantic{ DxsoUsage::PointSize, 0 }; + ffIsgn.elems[ffIsgn.elemCount++].semantic = DxsoSemantic{ DxsoUsage::BlendWeight, 0 }; + ffIsgn.elems[ffIsgn.elemCount++].semantic = DxsoSemantic{ DxsoUsage::BlendIndices, 0 }; + + return ffIsgn; + } + + + DxsoIsgn g_ffIsgn = CreateFixedFunctionIsgn(); + +} diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_fixed_function.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_fixed_function.h new file mode 100644 index 00000000000..8e312aa2ddf --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_fixed_function.h @@ -0,0 +1,254 @@ +#pragma once + +#include "d3d9_include.h" + +#include "d3d9_caps.h" + +#include "../dxvk/dxvk_shader.h" + +#include "../dxso/dxso_isgn.h" + +#include +#include + +namespace dxvk { + + class D3D9DeviceEx; + class SpirvModule; + + struct D3D9Options; + + struct D3D9FogContext { + // General inputs... + bool IsPixel; + bool RangeFog; + uint32_t RenderState; + uint32_t vPos; + uint32_t vFog; + + uint32_t oColor; + + bool HasFogInput; + + bool IsFixedFunction; + bool IsPositionT; + bool HasSpecular; + uint32_t Specular; + }; + + struct D3D9FixedFunctionOptions { + D3D9FixedFunctionOptions(const D3D9Options* options); + + bool invariantPosition; + }; + + // Returns new oFog if VS + // Returns new oColor if PS + uint32_t DoFixedFunctionFog(SpirvModule& spvModule, const D3D9FogContext& fogCtx); + + // Returns a render state block + uint32_t SetupRenderStateBlock(SpirvModule& spvModule, uint32_t count); + + struct D3D9PointSizeInfoVS { + uint32_t defaultValue; + uint32_t min; + uint32_t max; + }; + + // Default point size and point scale magic! + D3D9PointSizeInfoVS GetPointSizeInfoVS(SpirvModule& spvModule, uint32_t vPos, uint32_t vtx, uint32_t perVertPointSize, uint32_t rsBlock, bool isFixedFunction); + + struct D3D9PointSizeInfoPS { + uint32_t isSprite; + }; + + D3D9PointSizeInfoPS GetPointSizeInfoPS(SpirvModule& spvModule, uint32_t rsBlock); + + uint32_t GetPointCoord(SpirvModule& spvModule, std::vector& entryPointInterfaces); + + uint32_t GetSharedConstants(SpirvModule& spvModule); + + constexpr uint32_t TCIOffset = 16; + constexpr uint32_t TCIMask = 0b111 << TCIOffset; + + enum D3D9FF_VertexBlendMode { + D3D9FF_VertexBlendMode_Disabled, + D3D9FF_VertexBlendMode_Normal, + D3D9FF_VertexBlendMode_Tween, + }; + + struct D3D9FFShaderKeyVSData { + union { + struct { + uint32_t TexcoordIndices : 24; + + uint32_t HasPositionT : 1; + + uint32_t HasColor0 : 1; // Diffuse + uint32_t HasColor1 : 1; // Specular + + uint32_t HasPointSize : 1; + + uint32_t UseLighting : 1; + + uint32_t NormalizeNormals : 1; + uint32_t LocalViewer : 1; + uint32_t RangeFog : 1; + + uint32_t TexcoordFlags : 24; + + uint32_t DiffuseSource : 2; + uint32_t AmbientSource : 2; + uint32_t SpecularSource : 2; + uint32_t EmissiveSource : 2; + + uint32_t TransformFlags : 24; + + uint32_t LightCount : 4; + + uint32_t TexcoordDeclMask : 24; + uint32_t HasFog : 1; + + uint32_t VertexBlendMode : 2; + uint32_t VertexBlendIndexed : 1; + uint32_t VertexBlendCount : 3; + + uint32_t VertexClipping : 1; + } Contents; + + uint32_t Primitive[4]; + }; + }; + + struct D3D9FFShaderKeyVS { + D3D9FFShaderKeyVS() { + // memcmp safety + std::memset(&Data, 0, sizeof(Data)); + } + + D3D9FFShaderKeyVSData Data; + }; + + constexpr uint32_t TextureArgCount = 3; + + struct D3D9FFShaderStage { + union { + struct { + uint32_t ColorOp : 5; + uint32_t ColorArg0 : 6; + uint32_t ColorArg1 : 6; + uint32_t ColorArg2 : 6; + + uint32_t AlphaOp : 5; + uint32_t AlphaArg0 : 6; + uint32_t AlphaArg1 : 6; + uint32_t AlphaArg2 : 6; + + uint32_t Type : 2; + uint32_t ResultIsTemp : 1; + uint32_t Projected : 1; + + uint32_t ProjectedCount : 3; + + // Included in here, read from Stage 0 for packing reasons + // Affects all stages. + uint32_t GlobalSpecularEnable : 1; + uint32_t GlobalFlatShade : 1; + } Contents; + + uint32_t Primitive[2]; + }; + }; + + struct D3D9FFShaderKeyFS { + D3D9FFShaderKeyFS() { + // memcmp safety + std::memset(Stages, 0, sizeof(Stages)); + + // Normalize this. DISABLE != 0. + for (uint32_t i = 0; i < caps::TextureStageCount; i++) { + Stages[i].Contents.ColorOp = D3DTOP_DISABLE; + Stages[i].Contents.AlphaOp = D3DTOP_DISABLE; + } + } + + D3D9FFShaderStage Stages[caps::TextureStageCount]; + }; + + struct D3D9FFShaderKeyHash { + size_t operator () (const D3D9FFShaderKeyVS& key) const; + size_t operator () (const D3D9FFShaderKeyFS& key) const; + }; + + bool operator == (const D3D9FFShaderKeyVS& a, const D3D9FFShaderKeyVS& b); + bool operator != (const D3D9FFShaderKeyVS& a, const D3D9FFShaderKeyVS& b); + bool operator == (const D3D9FFShaderKeyFS& a, const D3D9FFShaderKeyFS& b); + bool operator != (const D3D9FFShaderKeyFS& a, const D3D9FFShaderKeyFS& b); + + struct D3D9FFShaderKeyEq { + bool operator () (const D3D9FFShaderKeyVS& a, const D3D9FFShaderKeyVS& b) const; + bool operator () (const D3D9FFShaderKeyFS& a, const D3D9FFShaderKeyFS& b) const; + }; + + class D3D9FFShader { + + public: + + D3D9FFShader( + D3D9DeviceEx* pDevice, + const D3D9FFShaderKeyVS& Key); + + D3D9FFShader( + D3D9DeviceEx* pDevice, + const D3D9FFShaderKeyFS& Key); + + template + void Dump(const T& Key, const std::string& Name); + + Rc GetShader() const { + return m_shader; + } + + private: + + Rc m_shader; + + DxsoIsgn m_isgn; + + }; + + + class D3D9FFShaderModuleSet : public RcObject { + + public: + + D3D9FFShader GetShaderModule( + D3D9DeviceEx* pDevice, + const D3D9FFShaderKeyVS& ShaderKey); + + D3D9FFShader GetShaderModule( + D3D9DeviceEx* pDevice, + const D3D9FFShaderKeyFS& ShaderKey); + + private: + + std::unordered_map< + D3D9FFShaderKeyVS, + D3D9FFShader, + D3D9FFShaderKeyHash, D3D9FFShaderKeyEq> m_vsModules; + + std::unordered_map< + D3D9FFShaderKeyFS, + D3D9FFShader, + D3D9FFShaderKeyHash, D3D9FFShaderKeyEq> m_fsModules; + + }; + + + inline const DxsoIsgn& GetFixedFunctionIsgn() { + extern DxsoIsgn g_ffIsgn; + + return g_ffIsgn; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_format.cpp b/utils/dxvk-1.10.3/src/d3d9/d3d9_format.cpp new file mode 100644 index 00000000000..5654337d741 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_format.cpp @@ -0,0 +1,565 @@ +#include "d3d9_format.h" + +namespace dxvk { + + // It is also worth noting that the msb/lsb-ness is flipped between VK and D3D9. + D3D9_VK_FORMAT_MAPPING ConvertFormatUnfixed(D3D9Format Format) { + switch (Format) { + case D3D9Format::Unknown: return {}; + + case D3D9Format::R8G8B8: return {}; // Unsupported + + case D3D9Format::A8R8G8B8: return { + VK_FORMAT_B8G8R8A8_UNORM, + VK_FORMAT_B8G8R8A8_SRGB, + VK_IMAGE_ASPECT_COLOR_BIT }; + + case D3D9Format::X8R8G8B8: return { + VK_FORMAT_B8G8R8A8_UNORM, + VK_FORMAT_B8G8R8A8_SRGB, + VK_IMAGE_ASPECT_COLOR_BIT, + { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, + VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_ONE }}; + + case D3D9Format::R5G6B5: return { + VK_FORMAT_R5G6B5_UNORM_PACK16, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT}; + + case D3D9Format::X1R5G5B5: return { + VK_FORMAT_A1R5G5B5_UNORM_PACK16, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT, + { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, + VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_ONE }}; + + case D3D9Format::A1R5G5B5: return { + VK_FORMAT_A1R5G5B5_UNORM_PACK16, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }; + + case D3D9Format::A4R4G4B4: return { + VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }; + + case D3D9Format::R3G3B2: return {}; // Unsupported + + case D3D9Format::A8: return { + VK_FORMAT_R8_UNORM, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT, + { VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO, + VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_R }}; + + case D3D9Format::A8R3G3B2: return {}; // Unsupported + + case D3D9Format::X4R4G4B4: return { + VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }; + + case D3D9Format::A2B10G10R10: return { + VK_FORMAT_A2B10G10R10_UNORM_PACK32, // The A2 is out of place here. This should be investigated. + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }; + + case D3D9Format::A8B8G8R8: return { + VK_FORMAT_R8G8B8A8_UNORM, + VK_FORMAT_R8G8B8A8_SRGB, + VK_IMAGE_ASPECT_COLOR_BIT }; + + case D3D9Format::X8B8G8R8: return { + VK_FORMAT_R8G8B8A8_UNORM, + VK_FORMAT_R8G8B8A8_SRGB, + VK_IMAGE_ASPECT_COLOR_BIT, + { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, + VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_ONE }}; + + case D3D9Format::G16R16: return { + VK_FORMAT_R16G16_UNORM, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT, + { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, + VK_COMPONENT_SWIZZLE_ONE, VK_COMPONENT_SWIZZLE_ONE }}; + + case D3D9Format::A2R10G10B10: return { + VK_FORMAT_A2R10G10B10_UNORM_PACK32, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }; + + case D3D9Format::A16B16G16R16: return { + VK_FORMAT_R16G16B16A16_UNORM, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }; + + case D3D9Format::A8P8: return {}; // Unsupported + + case D3D9Format::P8: return {}; // Unsupported + + case D3D9Format::L8: return { + VK_FORMAT_R8_UNORM, + VK_FORMAT_R8_SRGB, + VK_IMAGE_ASPECT_COLOR_BIT, + { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R, + VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_ONE }}; + + case D3D9Format::A8L8: return { + VK_FORMAT_R8G8_UNORM, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT, + { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R, + VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G }}; + + case D3D9Format::A4L4: return { + VK_FORMAT_R4G4_UNORM_PACK8, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT, + { VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_G, + VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R }}; + + case D3D9Format::V8U8: return { + VK_FORMAT_R8G8_SNORM, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT, + { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, + VK_COMPONENT_SWIZZLE_ONE, VK_COMPONENT_SWIZZLE_ONE }}; + + case D3D9Format::L6V5U5: return { + // Any PACK16 format will do... + VK_FORMAT_B5G6R5_UNORM_PACK16, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT, + { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, + VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }, + { D3D9ConversionFormat_L6V5U5, 1u, + // Convert -> float (this is a mixed snorm and unorm type) + VK_FORMAT_R16G16B16A16_SFLOAT } }; + + case D3D9Format::X8L8V8U8: return { + VK_FORMAT_B8G8R8A8_UNORM, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT, + { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, + VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_ONE }, + { D3D9ConversionFormat_X8L8V8U8, 1u, + // Convert -> float (this is a mixed snorm and unorm type) + VK_FORMAT_R16G16B16A16_SFLOAT } }; + + case D3D9Format::Q8W8V8U8: return { + VK_FORMAT_R8G8B8A8_SNORM, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }; + + case D3D9Format::V16U16: return { + VK_FORMAT_R16G16_SNORM, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT, + { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, + VK_COMPONENT_SWIZZLE_ONE, VK_COMPONENT_SWIZZLE_ONE }}; + + case D3D9Format::A2W10V10U10: return { + VK_FORMAT_A2B10G10R10_UNORM_PACK32, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT, + { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, + VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }, + { D3D9ConversionFormat_A2W10V10U10, 1u, + // Convert -> float (this is a mixed snorm and unorm type) + VK_FORMAT_R16G16B16A16_SFLOAT } }; + + case D3D9Format::UYVY: return { + VK_FORMAT_B8G8R8A8_UNORM, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT, + { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, + VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY }, + { D3D9ConversionFormat_UYVY, 1u } + }; + + case D3D9Format::R8G8_B8G8: return { + VK_FORMAT_G8B8G8R8_422_UNORM, // This format may have been _SCALED in DX9. + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }; + + case D3D9Format::YUY2: return { + VK_FORMAT_B8G8R8A8_UNORM, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT, + { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, + VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY }, + { D3D9ConversionFormat_YUY2, 1u } + }; + + case D3D9Format::G8R8_G8B8: return { + VK_FORMAT_B8G8R8G8_422_UNORM, // This format may have been _SCALED in DX9. + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }; + + case D3D9Format::DXT1: return { + VK_FORMAT_BC1_RGBA_UNORM_BLOCK, + VK_FORMAT_BC1_RGBA_SRGB_BLOCK, + VK_IMAGE_ASPECT_COLOR_BIT }; + + case D3D9Format::DXT2: return { + VK_FORMAT_BC2_UNORM_BLOCK, + VK_FORMAT_BC2_SRGB_BLOCK, + VK_IMAGE_ASPECT_COLOR_BIT }; + + case D3D9Format::DXT3: return { + VK_FORMAT_BC2_UNORM_BLOCK, + VK_FORMAT_BC2_SRGB_BLOCK, + VK_IMAGE_ASPECT_COLOR_BIT }; + + case D3D9Format::DXT4: return { + VK_FORMAT_BC3_UNORM_BLOCK, + VK_FORMAT_BC3_SRGB_BLOCK, + VK_IMAGE_ASPECT_COLOR_BIT }; + + case D3D9Format::DXT5: return { + VK_FORMAT_BC3_UNORM_BLOCK, + VK_FORMAT_BC3_SRGB_BLOCK, + VK_IMAGE_ASPECT_COLOR_BIT }; + + case D3D9Format::D16_LOCKABLE: return { + VK_FORMAT_D16_UNORM, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_DEPTH_BIT }; + + case D3D9Format::D32: return {}; // Unsupported (everywhere) + + case D3D9Format::D15S1: return {}; // Unsupported (everywhere) + + case D3D9Format::D24S8: return { + VK_FORMAT_D24_UNORM_S8_UINT, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT }; + + case D3D9Format::D24X8: return { + VK_FORMAT_D24_UNORM_S8_UINT, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_DEPTH_BIT }; + + case D3D9Format::D24X4S4: return {}; // Unsupported (everywhere) + + case D3D9Format::D16: return { + VK_FORMAT_D16_UNORM, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_DEPTH_BIT }; + + case D3D9Format::D32F_LOCKABLE: return { + VK_FORMAT_D32_SFLOAT, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_DEPTH_BIT }; + + case D3D9Format::D24FS8: return { + VK_FORMAT_D24_UNORM_S8_UINT, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT }; + + case D3D9Format::D32_LOCKABLE: return { + VK_FORMAT_D32_SFLOAT, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_DEPTH_BIT }; + + case D3D9Format::S8_LOCKABLE: return { + VK_FORMAT_S8_UINT, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_STENCIL_BIT }; + + case D3D9Format::L16: return { + VK_FORMAT_R16_UNORM, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT, + { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R, + VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_ONE }}; + + case D3D9Format::VERTEXDATA: return { + VK_FORMAT_R8_UINT, + VK_FORMAT_UNDEFINED, + 0 }; + + case D3D9Format::INDEX16: return { + VK_FORMAT_R16_UINT, + VK_FORMAT_UNDEFINED, + 0 }; + + case D3D9Format::INDEX32: return { + VK_FORMAT_R32_UINT, + VK_FORMAT_UNDEFINED, + 0 }; + + case D3D9Format::Q16W16V16U16: return { + VK_FORMAT_R16G16B16A16_SNORM, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }; + + case D3D9Format::MULTI2_ARGB8: return {}; // Unsupported + + case D3D9Format::R16F: return { + VK_FORMAT_R16_SFLOAT, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT, + { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_ONE, + VK_COMPONENT_SWIZZLE_ONE, VK_COMPONENT_SWIZZLE_ONE }}; + + case D3D9Format::G16R16F: return { + VK_FORMAT_R16G16_SFLOAT, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT, + { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, + VK_COMPONENT_SWIZZLE_ONE, VK_COMPONENT_SWIZZLE_ONE }}; + + case D3D9Format::A16B16G16R16F: return { + VK_FORMAT_R16G16B16A16_SFLOAT, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }; + + case D3D9Format::R32F: return { + VK_FORMAT_R32_SFLOAT, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT, + { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_ONE, + VK_COMPONENT_SWIZZLE_ONE, VK_COMPONENT_SWIZZLE_ONE }}; + + case D3D9Format::G32R32F: return { + VK_FORMAT_R32G32_SFLOAT, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT, + { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, + VK_COMPONENT_SWIZZLE_ONE, VK_COMPONENT_SWIZZLE_ONE }}; + + case D3D9Format::A32B32G32R32F: return { + VK_FORMAT_R32G32B32A32_SFLOAT, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }; + + case D3D9Format::CxV8U8: return {}; // Unsupported + + case D3D9Format::A1: return {}; // Unsupported + + case D3D9Format::A2B10G10R10_XR_BIAS: return { + VK_FORMAT_A2B10G10R10_SNORM_PACK32, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }; + + case D3D9Format::BINARYBUFFER: return { + VK_FORMAT_R8_UINT, + VK_FORMAT_UNDEFINED, + 0 }; + + case D3D9Format::ATI1: return { + VK_FORMAT_BC4_UNORM_BLOCK, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT, + { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_ZERO, + VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ONE }}; + + case D3D9Format::ATI2: return { + VK_FORMAT_BC5_UNORM_BLOCK, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT, + { VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R, + VK_COMPONENT_SWIZZLE_ONE, VK_COMPONENT_SWIZZLE_ONE }}; + + case D3D9Format::INST: return {}; // Driver hack, handled elsewhere + + case D3D9Format::DF24: return { + VK_FORMAT_D24_UNORM_S8_UINT, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_DEPTH_BIT, + { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_ZERO, + VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ONE }}; + + case D3D9Format::DF16: return { + VK_FORMAT_D16_UNORM, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_DEPTH_BIT, + { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_ZERO, + VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ONE }}; + + case D3D9Format::NULL_FORMAT: return {}; // Driver hack, handled elsewhere + + case D3D9Format::GET4: return {}; // Unsupported + + case D3D9Format::GET1: return {}; // Unsupported + + case D3D9Format::NVDB: return {}; // Driver hack, handled elsewhere + + case D3D9Format::A2M1: return {}; // Driver hack, handled elsewhere + + case D3D9Format::A2M0: return {}; // Driver hack, handled elsewhere + + case D3D9Format::ATOC: return {}; // Driver hack, handled elsewhere + + case D3D9Format::INTZ: return { + VK_FORMAT_D24_UNORM_S8_UINT, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, + { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R, + VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R }}; + + case D3D9Format::NV12: return { + VK_FORMAT_R8_UNORM, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT, + { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, + VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY }, + { D3D9ConversionFormat_NV12, 2u, VK_FORMAT_B8G8R8A8_UNORM } + }; + + case D3D9Format::YV12: return { + VK_FORMAT_R8_UNORM, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT, + { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, + VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY }, + { D3D9ConversionFormat_YV12, 3u, VK_FORMAT_B8G8R8A8_UNORM } + }; + + case D3D9Format::RAWZ: return {}; // Unsupported + + default: + Logger::warn(str::format("ConvertFormat: Unknown format encountered: ", Format)); + return {}; // Unsupported + } + } + + D3D9VkFormatTable::D3D9VkFormatTable( + const Rc& adapter, + const D3D9Options& options) { + m_dfSupport = options.supportDFFormats; + m_x4r4g4b4Support = options.supportX4R4G4B4; + m_d32supportFinal = options.supportD32; + + // AMD do not support 24-bit depth buffers on Vulkan, + // so we have to fall back to a 32-bit depth format. + m_d24s8Support = CheckImageFormatSupport(adapter, VK_FORMAT_D24_UNORM_S8_UINT, + VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | + VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT); + + // NVIDIA do not support 16-bit depth buffers with stencil on Vulkan, + // so we have to fall back to a 32-bit depth format. + m_d16s8Support = CheckImageFormatSupport(adapter, VK_FORMAT_D16_UNORM_S8_UINT, + VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | + VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT); + + // VK_EXT_4444_formats + m_a4r4g4b4Support = CheckImageFormatSupport(adapter, VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT); + + if (!m_d24s8Support) + Logger::info("D3D9: VK_FORMAT_D24_UNORM_S8_UINT -> VK_FORMAT_D32_SFLOAT_S8_UINT"); + + if (!m_d16s8Support) { + if (m_d24s8Support) + Logger::info("D3D9: VK_FORMAT_D16_UNORM_S8_UINT -> VK_FORMAT_D24_UNORM_S8_UINT"); + else + Logger::info("D3D9: VK_FORMAT_D16_UNORM_S8_UINT -> VK_FORMAT_D32_SFLOAT_S8_UINT"); + } + + if (!m_a4r4g4b4Support) + Logger::warn("D3D9: VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT -> VK_FORMAT_B4G4R4A4_UNORM_PACK16"); + } + + D3D9_VK_FORMAT_MAPPING D3D9VkFormatTable::GetFormatMapping( + D3D9Format Format) const { + D3D9_VK_FORMAT_MAPPING mapping = ConvertFormatUnfixed(Format); + + if (Format == D3D9Format::X4R4G4B4 && !m_x4r4g4b4Support) + return D3D9_VK_FORMAT_MAPPING(); + + if (Format == D3D9Format::DF16 && !m_dfSupport) + return D3D9_VK_FORMAT_MAPPING(); + + if (Format == D3D9Format::DF24 && !m_dfSupport) + return D3D9_VK_FORMAT_MAPPING(); + + if (Format == D3D9Format::D32 && !m_d32supportFinal) + return D3D9_VK_FORMAT_MAPPING(); + + if (!m_d24s8Support && mapping.FormatColor == VK_FORMAT_D24_UNORM_S8_UINT) + mapping.FormatColor = VK_FORMAT_D32_SFLOAT_S8_UINT; + + if (!m_d16s8Support && mapping.FormatColor == VK_FORMAT_D16_UNORM_S8_UINT) + mapping.FormatColor = m_d24s8Support ? VK_FORMAT_D24_UNORM_S8_UINT : VK_FORMAT_D32_SFLOAT_S8_UINT; + + if (!m_a4r4g4b4Support && mapping.FormatColor == VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT) { + VkComponentSwizzle alphaSwizzle = Format == D3D9Format::A4R4G4B4 + ? VK_COMPONENT_SWIZZLE_B + : VK_COMPONENT_SWIZZLE_ONE; + + mapping.FormatColor = VK_FORMAT_B4G4R4A4_UNORM_PACK16; + mapping.Swizzle = { + VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R, + VK_COMPONENT_SWIZZLE_A, alphaSwizzle }; + } + + return mapping; + } + + + const DxvkFormatInfo* D3D9VkFormatTable::GetUnsupportedFormatInfo( + D3D9Format Format) const { + static const DxvkFormatInfo r8b8g8 = { 3, VK_IMAGE_ASPECT_COLOR_BIT }; + static const DxvkFormatInfo r3g3b2 = { 1, VK_IMAGE_ASPECT_COLOR_BIT }; + static const DxvkFormatInfo a8r3g3b2 = { 2, VK_IMAGE_ASPECT_COLOR_BIT }; + static const DxvkFormatInfo a8p8 = { 2, VK_IMAGE_ASPECT_COLOR_BIT }; + static const DxvkFormatInfo p8 = { 1, VK_IMAGE_ASPECT_COLOR_BIT }; + static const DxvkFormatInfo l6v5u5 = { 2, VK_IMAGE_ASPECT_COLOR_BIT }; + static const DxvkFormatInfo x8l8v8u8 = { 4, VK_IMAGE_ASPECT_COLOR_BIT }; + static const DxvkFormatInfo a2w10v10u10 = { 4, VK_IMAGE_ASPECT_COLOR_BIT }; + static const DxvkFormatInfo cxv8u8 = { 2, VK_IMAGE_ASPECT_COLOR_BIT }; + static const DxvkFormatInfo unknown = {}; + + switch (Format) { + case D3D9Format::R8G8B8: + return &r8b8g8; + + case D3D9Format::R3G3B2: + return &r3g3b2; + + case D3D9Format::A8R3G3B2: + return &a8r3g3b2; + + case D3D9Format::A8P8: + return &a8p8; + + case D3D9Format::P8: + return &p8; + + case D3D9Format::L6V5U5: + return &l6v5u5; + + case D3D9Format::X8L8V8U8: + return &x8l8v8u8; + + case D3D9Format::A2W10V10U10: + return &a2w10v10u10; + + // MULTI2_ARGB8 -> Don't have a clue what this is. + + case D3D9Format::CxV8U8: + return &cxv8u8; + + // A1 -> Doesn't map nicely here cause it's not byte aligned. + // Gonna just pretend that doesn't exist until something + // depends on that. + + default: + return &unknown; + } + } + + + bool D3D9VkFormatTable::CheckImageFormatSupport( + const Rc& Adapter, + VkFormat Format, + VkFormatFeatureFlags Features) const { + VkFormatProperties supported = Adapter->formatProperties(Format); + + return (supported.linearTilingFeatures & Features) == Features + || (supported.optimalTilingFeatures & Features) == Features; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_format.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_format.h new file mode 100644 index 00000000000..0c9ab1688fe --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_format.h @@ -0,0 +1,223 @@ +#pragma once + +#include +#include "d3d9_options.h" + +#include "../dxvk/dxvk_adapter.h" +#include "../dxvk/dxvk_format.h" + +#include + +namespace dxvk { + + enum class D3D9Format : uint32_t { + Unknown = 0, + + R8G8B8 = 20, + A8R8G8B8 = 21, + X8R8G8B8 = 22, + R5G6B5 = 23, + X1R5G5B5 = 24, + A1R5G5B5 = 25, + A4R4G4B4 = 26, + R3G3B2 = 27, + A8 = 28, + A8R3G3B2 = 29, + X4R4G4B4 = 30, + A2B10G10R10 = 31, + A8B8G8R8 = 32, + X8B8G8R8 = 33, + G16R16 = 34, + A2R10G10B10 = 35, + A16B16G16R16 = 36, + A8P8 = 40, + P8 = 41, + L8 = 50, + A8L8 = 51, + A4L4 = 52, + V8U8 = 60, + L6V5U5 = 61, + X8L8V8U8 = 62, + Q8W8V8U8 = 63, + V16U16 = 64, + A2W10V10U10 = 67, + UYVY = MAKEFOURCC('U', 'Y', 'V', 'Y'), + R8G8_B8G8 = MAKEFOURCC('R', 'G', 'B', 'G'), + YUY2 = MAKEFOURCC('Y', 'U', 'Y', '2'), + G8R8_G8B8 = MAKEFOURCC('G', 'R', 'G', 'B'), + DXT1 = MAKEFOURCC('D', 'X', 'T', '1'), + DXT2 = MAKEFOURCC('D', 'X', 'T', '2'), + DXT3 = MAKEFOURCC('D', 'X', 'T', '3'), + DXT4 = MAKEFOURCC('D', 'X', 'T', '4'), + DXT5 = MAKEFOURCC('D', 'X', 'T', '5'), + D16_LOCKABLE = 70, + D32 = 71, + D15S1 = 73, + D24S8 = 75, + D24X8 = 77, + D24X4S4 = 79, + D16 = 80, + D32F_LOCKABLE = 82, + D24FS8 = 83, + D32_LOCKABLE = 84, + S8_LOCKABLE = 85, + L16 = 81, + VERTEXDATA = 100, + INDEX16 = 101, + INDEX32 = 102, + Q16W16V16U16 = 110, + MULTI2_ARGB8 = MAKEFOURCC('M', 'E', 'T', '1'), + R16F = 111, + G16R16F = 112, + A16B16G16R16F = 113, + R32F = 114, + G32R32F = 115, + A32B32G32R32F = 116, + CxV8U8 = 117, + A1 = 118, + A2B10G10R10_XR_BIAS = 119, + BINARYBUFFER = 199, + + // Driver Hacks / Unofficial Formats + ATI1 = MAKEFOURCC('A', 'T', 'I', '1'), + ATI2 = MAKEFOURCC('A', 'T', 'I', '2'), + INST = MAKEFOURCC('I', 'N', 'S', 'T'), + DF24 = MAKEFOURCC('D', 'F', '2', '4'), + DF16 = MAKEFOURCC('D', 'F', '1', '6'), + NULL_FORMAT = MAKEFOURCC('N', 'U', 'L', 'L'), + GET4 = MAKEFOURCC('G', 'E', 'T', '4'), + GET1 = MAKEFOURCC('G', 'E', 'T', '1'), + NVDB = MAKEFOURCC('N', 'V', 'D', 'B'), + A2M1 = MAKEFOURCC('A', '2', 'M', '1'), + A2M0 = MAKEFOURCC('A', '2', 'M', '0'), + ATOC = MAKEFOURCC('A', 'T', 'O', 'C'), + INTZ = MAKEFOURCC('I', 'N', 'T', 'Z'), + RAWZ = MAKEFOURCC('R', 'A', 'W', 'Z'), + RESZ = MAKEFOURCC('R', 'E', 'S', 'Z'), + + NV11 = MAKEFOURCC('N', 'V', '1', '1'), + NV12 = MAKEFOURCC('N', 'V', '1', '2'), + P010 = MAKEFOURCC('P', '0', '1', '0'), // Same as NV12 but 10 bit + P016 = MAKEFOURCC('P', '0', '1', '6'), // Same as NV12 but 16 bit + Y210 = MAKEFOURCC('Y', '2', '1', '0'), + Y216 = MAKEFOURCC('Y', '2', '1', '6'), + Y410 = MAKEFOURCC('Y', '4', '1', '0'), + AYUV = MAKEFOURCC('A', 'Y', 'U', 'V'), + YV12 = MAKEFOURCC('Y', 'V', '1', '2'), + OPAQUE_420 = MAKEFOURCC('4', '2', '0', 'O'), + + // Not supported but exist + AI44 = MAKEFOURCC('A', 'I', '4', '4'), + IA44 = MAKEFOURCC('I', 'A', '4', '4'), + R2VB = MAKEFOURCC('R', '2', 'V', 'B'), + COPM = MAKEFOURCC('C', 'O', 'P', 'M'), + SSAA = MAKEFOURCC('S', 'S', 'A', 'A'), + AL16 = MAKEFOURCC('A', 'L', '1', '6'), + R16 = MAKEFOURCC(' ', 'R', '1', '6'), + + EXT1 = MAKEFOURCC('E', 'X', 'T', '1'), + FXT1 = MAKEFOURCC('F', 'X', 'T', '1'), + GXT1 = MAKEFOURCC('G', 'X', 'T', '1'), + HXT1 = MAKEFOURCC('H', 'X', 'T', '1'), + }; + + inline D3D9Format EnumerateFormat(D3DFORMAT format) { + return static_cast(format); + } + + std::ostream& operator << (std::ostream& os, D3D9Format format); + + enum D3D9ConversionFormat : uint32_t { + D3D9ConversionFormat_None = 0, + D3D9ConversionFormat_YUY2 = 1, + D3D9ConversionFormat_UYVY, + D3D9ConversionFormat_L6V5U5, + D3D9ConversionFormat_X8L8V8U8, + D3D9ConversionFormat_A2W10V10U10, + D3D9ConversionFormat_NV12, + D3D9ConversionFormat_YV12, + D3D9ConversionFormat_Count + }; + + struct D3D9_CONVERSION_FORMAT_INFO { + D3D9ConversionFormat FormatType = D3D9ConversionFormat_None; + uint32_t PlaneCount = 1; + VkFormat FormatColor = VK_FORMAT_UNDEFINED; + VkFormat FormatSrgb = VK_FORMAT_UNDEFINED; + }; + + /** + * \brief Format mapping + * + * Maps a D3D9 format to a set of Vulkan formats. + */ + struct D3D9_VK_FORMAT_MAPPING { + union { + struct { + VkFormat FormatColor; ///< Corresponding color format + VkFormat FormatSrgb; ///< Corresponding color format + }; + VkFormat Formats[2]; + }; + VkImageAspectFlags Aspect = 0; ///< Defined aspects for the color format + VkComponentMapping Swizzle = { ///< Color component swizzle + VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, + VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY }; + D3D9_CONVERSION_FORMAT_INFO ConversionFormatInfo = { }; + + bool IsValid() const { return FormatColor != VK_FORMAT_UNDEFINED; } + }; + + D3D9_VK_FORMAT_MAPPING ConvertFormatUnfixed(D3D9Format Format); + + /** + * \brief Format table + * + * Initializes a format table for a specific + * device and provides methods to look up + * formats. + */ + class D3D9VkFormatTable { + + public: + + D3D9VkFormatTable( + const Rc& adapter, + const D3D9Options& options); + + /** + * \brief Retrieves info for a given D3D9 format + * + * \param [in] Format The D3D9 format to look up + * \param [in] Mode the format lookup mode + * \returns Format info + */ + D3D9_VK_FORMAT_MAPPING GetFormatMapping( + D3D9Format Format) const; + + /** + * \brief Retrieves format info for unsupported + * formats. + * + * \param [in] Format The D3D9 format to look up + */ + const DxvkFormatInfo* GetUnsupportedFormatInfo( + D3D9Format Format) const; + + private: + + bool CheckImageFormatSupport( + const Rc& Adapter, + VkFormat Format, + VkFormatFeatureFlags Features) const; + + bool m_a4r4g4b4Support; + bool m_d24s8Support; + bool m_d16s8Support; + + bool m_dfSupport; + bool m_x4r4g4b4Support; + bool m_d32supportFinal; + }; + +} diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_format_helpers.cpp b/utils/dxvk-1.10.3/src/d3d9/d3d9_format_helpers.cpp new file mode 100644 index 00000000000..e528f90cf03 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_format_helpers.cpp @@ -0,0 +1,150 @@ +#include "d3d9_format_helpers.h" + +#include +#include +#include +#include +#include +#include + +namespace dxvk { + + D3D9FormatHelper::D3D9FormatHelper(const Rc& device) + : m_device(device), m_context(m_device->createContext()) { + m_context->beginRecording( + m_device->createCommandList()); + + InitShaders(); + } + + + void D3D9FormatHelper::Flush() { + if (m_transferCommands != 0) + FlushInternal(); + } + + + void D3D9FormatHelper::ConvertFormat( + D3D9_CONVERSION_FORMAT_INFO conversionFormat, + const Rc& dstImage, + VkImageSubresourceLayers dstSubresource, + const DxvkBufferSlice& srcSlice) { + switch (conversionFormat.FormatType) { + case D3D9ConversionFormat_YUY2: + case D3D9ConversionFormat_UYVY: { + uint32_t specConstant = conversionFormat.FormatType == D3D9ConversionFormat_UYVY ? 1 : 0; + ConvertGenericFormat(conversionFormat, dstImage, dstSubresource, srcSlice, VK_FORMAT_R32_UINT, specConstant, { 2u, 1u }); + break; + } + + case D3D9ConversionFormat_NV12: + ConvertGenericFormat(conversionFormat, dstImage, dstSubresource, srcSlice, VK_FORMAT_R16_UINT, 0, { 2u, 1u }); + break; + + case D3D9ConversionFormat_YV12: + ConvertGenericFormat(conversionFormat, dstImage, dstSubresource, srcSlice, VK_FORMAT_R8_UINT, 0, { 1u, 1u }); + break; + + case D3D9ConversionFormat_L6V5U5: + ConvertGenericFormat(conversionFormat, dstImage, dstSubresource, srcSlice, VK_FORMAT_R16_UINT, 0, { 1u, 1u }); + break; + + case D3D9ConversionFormat_X8L8V8U8: + ConvertGenericFormat(conversionFormat, dstImage, dstSubresource, srcSlice, VK_FORMAT_R32_UINT, 0, { 1u, 1u }); + break; + + case D3D9ConversionFormat_A2W10V10U10: + ConvertGenericFormat(conversionFormat, dstImage, dstSubresource, srcSlice, VK_FORMAT_R32_UINT, 0, { 1u, 1u }); + break; + + default: + Logger::warn("Unimplemented format conversion"); + } + } + + + void D3D9FormatHelper::ConvertGenericFormat( + D3D9_CONVERSION_FORMAT_INFO videoFormat, + const Rc& dstImage, + VkImageSubresourceLayers dstSubresource, + const DxvkBufferSlice& srcSlice, + VkFormat bufferFormat, + uint32_t specConstantValue, + VkExtent2D macroPixelRun) { + DxvkImageViewCreateInfo imageViewInfo; + imageViewInfo.type = VK_IMAGE_VIEW_TYPE_2D; + imageViewInfo.format = dstImage->info().format; + imageViewInfo.usage = VK_IMAGE_USAGE_STORAGE_BIT; + imageViewInfo.aspect = dstSubresource.aspectMask; + imageViewInfo.minLevel = dstSubresource.mipLevel; + imageViewInfo.numLevels = 1; + imageViewInfo.minLayer = dstSubresource.baseArrayLayer; + imageViewInfo.numLayers = dstSubresource.layerCount; + auto tmpImageView = m_device->createImageView(dstImage, imageViewInfo); + + VkExtent3D imageExtent = dstImage->mipLevelExtent(dstSubresource.mipLevel); + imageExtent = VkExtent3D{ imageExtent.width / macroPixelRun.width, + imageExtent.height / macroPixelRun.height, + 1 }; + + DxvkBufferViewCreateInfo bufferViewInfo; + bufferViewInfo.format = bufferFormat; + bufferViewInfo.rangeOffset = srcSlice.offset(); + bufferViewInfo.rangeLength = srcSlice.length(); + auto tmpBufferView = m_device->createBufferView(srcSlice.buffer(), bufferViewInfo); + + if (specConstantValue) + m_context->setSpecConstant(VK_PIPELINE_BIND_POINT_COMPUTE, 0, specConstantValue); + + m_context->bindResourceView(BindingIds::Image, tmpImageView, nullptr); + m_context->bindResourceView(BindingIds::Buffer, nullptr, tmpBufferView); + m_context->bindShader(VK_SHADER_STAGE_COMPUTE_BIT, m_shaders[videoFormat.FormatType]); + m_context->pushConstants(0, sizeof(VkExtent2D), &imageExtent); + m_context->dispatch( + (imageExtent.width / 8) + (imageExtent.width % 8), + (imageExtent.height / 8) + (imageExtent.height % 8), + 1); + + // Reset the spec constants used... + if (specConstantValue) + m_context->setSpecConstant(VK_PIPELINE_BIND_POINT_COMPUTE, 0, 0); + + m_transferCommands += 1; + } + + + void D3D9FormatHelper::InitShaders() { + m_shaders[D3D9ConversionFormat_YUY2] = InitShader(d3d9_convert_yuy2_uyvy); + m_shaders[D3D9ConversionFormat_UYVY] = m_shaders[D3D9ConversionFormat_YUY2]; + m_shaders[D3D9ConversionFormat_L6V5U5] = InitShader(d3d9_convert_l6v5u5); + m_shaders[D3D9ConversionFormat_X8L8V8U8] = InitShader(d3d9_convert_x8l8v8u8); + m_shaders[D3D9ConversionFormat_A2W10V10U10] = InitShader(d3d9_convert_a2w10v10u10); + m_shaders[D3D9ConversionFormat_NV12] = InitShader(d3d9_convert_nv12); + m_shaders[D3D9ConversionFormat_YV12] = InitShader(d3d9_convert_yv12); + } + + + Rc D3D9FormatHelper::InitShader(SpirvCodeBuffer code) { + const std::array resourceSlots = { { + { BindingIds::Image, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_IMAGE_VIEW_TYPE_2D }, + { BindingIds::Buffer, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, VK_IMAGE_VIEW_TYPE_1D }, + } }; + + DxvkShaderCreateInfo info; + info.stage = VK_SHADER_STAGE_COMPUTE_BIT; + info.resourceSlotCount = resourceSlots.size(); + info.resourceSlots = resourceSlots.data(); + info.pushConstOffset = 0; + info.pushConstSize = sizeof(VkExtent2D); + + return new DxvkShader(info, std::move(code)); + } + + + void D3D9FormatHelper::FlushInternal() { + m_context->flushCommandList(); + + m_transferCommands = 0; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_format_helpers.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_format_helpers.h new file mode 100644 index 00000000000..16348eda297 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_format_helpers.h @@ -0,0 +1,55 @@ +#pragma once + +#include "d3d9_include.h" +#include "d3d9_format.h" +#include "../dxvk/dxvk_device.h" +#include "../dxvk/dxvk_context.h" + +namespace dxvk { + + class D3D9FormatHelper { + + public: + + D3D9FormatHelper(const Rc& device); + + void Flush(); + + void ConvertFormat( + D3D9_CONVERSION_FORMAT_INFO conversionFormat, + const Rc& dstImage, + VkImageSubresourceLayers dstSubresource, + const DxvkBufferSlice& srcSlice); + + private: + + void ConvertGenericFormat( + D3D9_CONVERSION_FORMAT_INFO videoFormat, + const Rc& dstImage, + VkImageSubresourceLayers dstSubresource, + const DxvkBufferSlice& srcSlice, + VkFormat bufferFormat, + uint32_t specConstantValue, + VkExtent2D macroPixelRun); + + enum BindingIds : uint32_t { + Image = 0, + Buffer = 1, + }; + + void InitShaders(); + + Rc InitShader(SpirvCodeBuffer code); + + void FlushInternal(); + + Rc m_device; + Rc m_context; + + size_t m_transferCommands = 0; + + std::array, D3D9ConversionFormat_Count> m_shaders; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_hud.cpp b/utils/dxvk-1.10.3/src/d3d9/d3d9_hud.cpp new file mode 100644 index 00000000000..e37a5a0e370 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_hud.cpp @@ -0,0 +1,36 @@ +#include "d3d9_hud.h" + +namespace dxvk::hud { + + HudSamplerCount::HudSamplerCount(D3D9DeviceEx* device) + : m_device (device) + , m_samplerCount ("0"){ + + } + + + void HudSamplerCount::update(dxvk::high_resolution_clock::time_point time) { + m_samplerCount = str::format(m_device->GetSamplerCount()); + } + + + HudPos HudSamplerCount::render( + HudRenderer& renderer, + HudPos position) { + position.y += 16.0f; + + renderer.drawText(16.0f, + { position.x, position.y }, + { 0.0f, 1.0f, 0.75f, 1.0f }, + "Samplers:"); + + renderer.drawText(16.0f, + { position.x + 120.0f, position.y }, + { 1.0f, 1.0f, 1.0f, 1.0f }, + m_samplerCount); + + position.y += 8.0f; + return position; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_hud.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_hud.h new file mode 100644 index 00000000000..b500e48b6f1 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_hud.h @@ -0,0 +1,31 @@ +#pragma once + +#include "d3d9_device.h" +#include "../dxvk/hud/dxvk_hud_item.h" + +namespace dxvk::hud { + + /** + * \brief HUD item to display DXVK version + */ + class HudSamplerCount : public HudItem { + + public: + + HudSamplerCount(D3D9DeviceEx* device); + + void update(dxvk::high_resolution_clock::time_point time); + + HudPos render( + HudRenderer& renderer, + HudPos position); + + private: + + D3D9DeviceEx* m_device; + + std::string m_samplerCount; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_include.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_include.h new file mode 100644 index 00000000000..a8a79560679 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_include.h @@ -0,0 +1,97 @@ +#pragma once + +#ifndef _MSC_VER +#ifdef _WIN32_WINNT +#undef _WIN32_WINNT +#endif +#define _WIN32_WINNT 0x0A00 +#endif + +#include +#include + +//for some reason we need to specify __declspec(dllexport) for MinGW +#if defined(__WINE__) +#define DLLEXPORT __attribute__((visibility("default"))) +#else +#define DLLEXPORT +#endif + + +#include "../util/com/com_guid.h" +#include "../util/com/com_object.h" +#include "../util/com/com_pointer.h" + +#include "../util/log/log.h" +#include "../util/log/log_debug.h" + +#include "../util/rc/util_rc.h" +#include "../util/rc/util_rc_ptr.h" + +#include "../util/sync/sync_recursive.h" + +#include "../util/util_env.h" +#include "../util/util_enum.h" +#include "../util/util_error.h" +#include "../util/util_flags.h" +#include "../util/util_likely.h" +#include "../util/util_math.h" +#include "../util/util_monitor.h" +#include "../util/util_string.h" + +// Missed definitions in Wine/MinGW. + +#ifndef D3DPRESENT_BACK_BUFFERS_MAX_EX +#define D3DPRESENT_BACK_BUFFERS_MAX_EX 30 +#endif + +#ifndef D3DSI_OPCODE_MASK +#define D3DSI_OPCODE_MASK 0x0000FFFF +#endif + +#ifndef D3DSP_TEXTURETYPE_MASK +#define D3DSP_TEXTURETYPE_MASK 0x78000000 +#endif + +#ifndef D3DUSAGE_AUTOGENMIPMAP +#define D3DUSAGE_AUTOGENMIPMAP 0x00000400L +#endif + +#ifndef D3DSP_DCL_USAGE_MASK +#define D3DSP_DCL_USAGE_MASK 0x0000000f +#endif + +#ifndef D3DSP_OPCODESPECIFICCONTROL_MASK +#define D3DSP_OPCODESPECIFICCONTROL_MASK 0x00ff0000 +#endif + +#ifndef D3DSP_OPCODESPECIFICCONTROL_SHIFT +#define D3DSP_OPCODESPECIFICCONTROL_SHIFT 16 +#endif + +#ifndef D3DCURSOR_IMMEDIATE_UPDATE +#define D3DCURSOR_IMMEDIATE_UPDATE 0x00000001L +#endif + +#ifndef D3DPRESENT_FORCEIMMEDIATE +#define D3DPRESENT_FORCEIMMEDIATE 0x00000100L +#endif + +// MinGW headers are broken. Who'dve guessed? +#ifndef _MSC_VER +namespace dxvk { +typedef struct _D3DDEVINFO_RESOURCEMANAGER +{ + char dummy; +} D3DDEVINFO_RESOURCEMANAGER, * LPD3DDEVINFO_RESOURCEMANAGER; +} + +#ifndef __WINE__ +extern "C" WINUSERAPI WINBOOL WINAPI SetProcessDPIAware(VOID); +#endif +#endif + +// This is the managed pool on D3D9Ex, it's just hidden! +#define D3DPOOL_MANAGED_EX D3DPOOL(6) + +using D3D9VertexElements = std::vector; diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_initializer.cpp b/utils/dxvk-1.10.3/src/d3d9/d3d9_initializer.cpp new file mode 100644 index 00000000000..22088c9b293 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_initializer.cpp @@ -0,0 +1,163 @@ +#include + +#include "d3d9_initializer.h" + +namespace dxvk { + + D3D9Initializer::D3D9Initializer( + const Rc& Device) + : m_device(Device), m_context(m_device->createContext()) { + m_context->beginRecording( + m_device->createCommandList()); + } + + + D3D9Initializer::~D3D9Initializer() { + + } + + + void D3D9Initializer::Flush() { + std::lock_guard lock(m_mutex); + + if (m_transferCommands != 0) + FlushInternal(); + } + + + void D3D9Initializer::InitBuffer( + D3D9CommonBuffer* pBuffer) { + VkMemoryPropertyFlags memFlags = pBuffer->GetBuffer()->memFlags(); + + (memFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) + ? InitHostVisibleBuffer(pBuffer->GetBufferSlice()) + : InitDeviceLocalBuffer(pBuffer->GetBufferSlice()); + + if (pBuffer->GetMapMode() == D3D9_COMMON_BUFFER_MAP_MODE_BUFFER) + InitHostVisibleBuffer(pBuffer->GetBufferSlice()); + } + + + void D3D9Initializer::InitTexture( + D3D9CommonTexture* pTexture, + void* pInitialData) { + if (pTexture->GetMapMode() == D3D9_COMMON_TEXTURE_MAP_MODE_NONE) + return; + + (pTexture->GetMapMode() == D3D9_COMMON_TEXTURE_MAP_MODE_BACKED) + ? InitDeviceLocalTexture(pTexture) + : InitHostVisibleTexture(pTexture, pInitialData); + } + + + void D3D9Initializer::InitDeviceLocalBuffer( + DxvkBufferSlice Slice) { + std::lock_guard lock(m_mutex); + + m_transferCommands += 1; + + m_context->initBuffer( + Slice.buffer()); + + FlushImplicit(); + } + + + void D3D9Initializer::InitHostVisibleBuffer( + DxvkBufferSlice Slice) { + // If the buffer is mapped, we can write data directly + // to the mapped memory region instead of doing it on + // the GPU. Same goes for zero-initialization. + std::memset( + Slice.mapPtr(0), 0, + Slice.length()); + } + + + void D3D9Initializer::InitDeviceLocalTexture( + D3D9CommonTexture* pTexture) { + std::lock_guard lock(m_mutex); + + auto InitImage = [&](Rc image) { + if (image == nullptr) + return; + + auto formatInfo = imageFormatInfo(image->info().format); + + m_transferCommands += 1; + + // While the Microsoft docs state that resource contents are + // undefined if no initial data is provided, some applications + // expect a resource to be pre-cleared. + VkImageSubresourceRange subresources; + subresources.aspectMask = formatInfo->aspectMask; + subresources.baseMipLevel = 0; + subresources.levelCount = image->info().mipLevels; + subresources.baseArrayLayer = 0; + subresources.layerCount = image->info().numLayers; + + m_context->initImage(image, subresources, VK_IMAGE_LAYOUT_UNDEFINED); + }; + + InitImage(pTexture->GetImage()); + + FlushImplicit(); + } + + + void D3D9Initializer::InitHostVisibleTexture( + D3D9CommonTexture* pTexture, + void* pInitialData) { + // If the buffer is mapped, we can write data directly + // to the mapped memory region instead of doing it on + // the GPU. Same goes for zero-initialization. + const D3D9_COMMON_TEXTURE_DESC* desc = pTexture->Desc(); + for (uint32_t a = 0; a < desc->ArraySize; a++) { + for (uint32_t m = 0; m < desc->MipLevels; m++) { + uint32_t subresource = pTexture->CalcSubresource(a, m); + DxvkBufferSliceHandle mapSlice = pTexture->GetBuffer(subresource)->getSliceHandle(); + + if (pInitialData != nullptr) { + VkExtent3D mipExtent = pTexture->GetExtentMip(m); + const DxvkFormatInfo* formatInfo = imageFormatInfo(pTexture->GetFormatMapping().FormatColor); + VkExtent3D blockCount = util::computeBlockCount(mipExtent, formatInfo->blockSize); + uint32_t pitch = blockCount.width * formatInfo->elementSize; + uint32_t alignedPitch = align(pitch, 4); + + util::packImageData( + mapSlice.mapPtr, + pInitialData, + pitch, + pitch * blockCount.height, + alignedPitch, + alignedPitch * blockCount.height, + D3D9CommonTexture::GetImageTypeFromResourceType(pTexture->GetType()), + mipExtent, + pTexture->Desc()->ArraySize, + formatInfo, + VK_IMAGE_ASPECT_COLOR_BIT); + } else { + std::memset( + mapSlice.mapPtr, 0, + mapSlice.length); + } + } + } + } + + + void D3D9Initializer::FlushImplicit() { + if (m_transferCommands > MaxTransferCommands + || m_transferMemory > MaxTransferMemory) + FlushInternal(); + } + + + void D3D9Initializer::FlushInternal() { + m_context->flushCommandList(); + + m_transferCommands = 0; + m_transferMemory = 0; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_initializer.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_initializer.h new file mode 100644 index 00000000000..59802f9550f --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_initializer.h @@ -0,0 +1,62 @@ +#pragma once + +#include "d3d9_common_buffer.h" +#include "d3d9_common_texture.h" + +namespace dxvk { + + /** + * \brief Resource initialization context + * + * Manages a context which is used for resource + * initialization. This includes + * zero-initialization for buffers and images. + */ + class D3D9Initializer { + constexpr static size_t MaxTransferMemory = 32 * 1024 * 1024; + constexpr static size_t MaxTransferCommands = 512; + public: + + D3D9Initializer( + const Rc& Device); + + ~D3D9Initializer(); + + void Flush(); + + void InitBuffer( + D3D9CommonBuffer* pBuffer); + + void InitTexture( + D3D9CommonTexture* pTexture, + void* pInitialData = nullptr); + + private: + + dxvk::mutex m_mutex; + + Rc m_device; + Rc m_context; + + size_t m_transferCommands = 0; + size_t m_transferMemory = 0; + + void InitDeviceLocalBuffer( + DxvkBufferSlice Slice); + + void InitHostVisibleBuffer( + DxvkBufferSlice Slice); + + void InitDeviceLocalTexture( + D3D9CommonTexture* pTexture); + + void InitHostVisibleTexture( + D3D9CommonTexture* pTexture, + void* pInitialData); + + void FlushImplicit(); + void FlushInternal(); + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_interface.cpp b/utils/dxvk-1.10.3/src/d3d9/d3d9_interface.cpp new file mode 100644 index 00000000000..43f14e8969d --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_interface.cpp @@ -0,0 +1,369 @@ +#include "d3d9_interface.h" + +#include "d3d9_monitor.h" +#include "d3d9_caps.h" +#include "d3d9_device.h" + +#include + +namespace dxvk { + + D3D9InterfaceEx::D3D9InterfaceEx(bool bExtended) + : m_instance ( new DxvkInstance() ) + , m_extended ( bExtended ) + , m_d3d9Options ( nullptr, m_instance->config() ) { + // D3D9 doesn't enumerate adapters like physical adapters... + // only as connected displays. + + // Let's create some "adapters" for the amount of displays we have. + // We'll go through and match up displays -> our adapters in order. + // If we run out of adapters, then we'll just make repeats of the first one. + // We can't match up by names on Linux/Wine as they don't match at all + // like on Windows, so this is our best option. + if (m_d3d9Options.enumerateByDisplays) { + DISPLAY_DEVICEA device = { }; + device.cb = sizeof(device); + + uint32_t adapterOrdinal = 0; + uint32_t i = 0; + while (::EnumDisplayDevicesA(nullptr, i++, &device, 0)) { + // If we aren't attached, skip over. + if (!(device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)) + continue; + + // If we are a mirror, skip over this device. + if (device.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) + continue; + + Rc adapter = adapterOrdinal >= m_instance->adapterCount() + ? m_instance->enumAdapters(0) + : m_instance->enumAdapters(adapterOrdinal); + + if (adapter != nullptr) + m_adapters.emplace_back(this, adapter, adapterOrdinal++, i - 1); + } + } + else + { + const uint32_t adapterCount = m_instance->adapterCount(); + m_adapters.reserve(adapterCount); + + for (uint32_t i = 0; i < adapterCount; i++) + m_adapters.emplace_back(this, m_instance->enumAdapters(i), i, 0); + } + + if (m_d3d9Options.dpiAware) { + Logger::info("Process set as DPI aware"); + SetProcessDPIAware(); + } + } + + + HRESULT STDMETHODCALLTYPE D3D9InterfaceEx::QueryInterface(REFIID riid, void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(IDirect3D9) + || (m_extended && riid == __uuidof(IDirect3D9Ex))) { + *ppvObject = ref(this); + return S_OK; + } + + Logger::warn("D3D9InterfaceEx::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + HRESULT STDMETHODCALLTYPE D3D9InterfaceEx::RegisterSoftwareDevice(void* pInitializeFunction) { + Logger::warn("D3D9InterfaceEx::RegisterSoftwareDevice: Stub"); + return D3D_OK; + } + + + UINT STDMETHODCALLTYPE D3D9InterfaceEx::GetAdapterCount() { + return UINT(m_adapters.size()); + } + + + HRESULT STDMETHODCALLTYPE D3D9InterfaceEx::GetAdapterIdentifier( + UINT Adapter, + DWORD Flags, + D3DADAPTER_IDENTIFIER9* pIdentifier) { + if (auto* adapter = GetAdapter(Adapter)) + return adapter->GetAdapterIdentifier(Flags, pIdentifier); + + return D3DERR_INVALIDCALL; + } + + + UINT STDMETHODCALLTYPE D3D9InterfaceEx::GetAdapterModeCount(UINT Adapter, D3DFORMAT Format) { + D3DDISPLAYMODEFILTER filter; + filter.Size = sizeof(D3DDISPLAYMODEFILTER); + filter.Format = Format; + filter.ScanLineOrdering = D3DSCANLINEORDERING_PROGRESSIVE; + + return this->GetAdapterModeCountEx(Adapter, &filter); + } + + + HRESULT STDMETHODCALLTYPE D3D9InterfaceEx::GetAdapterDisplayMode(UINT Adapter, D3DDISPLAYMODE* pMode) { + if (auto* adapter = GetAdapter(Adapter)) { + D3DDISPLAYMODEEX modeEx = { }; + modeEx.Size = sizeof(D3DDISPLAYMODEEX); + HRESULT hr = adapter->GetAdapterDisplayModeEx(&modeEx, nullptr); + + if (FAILED(hr)) + return hr; + + pMode->Width = modeEx.Width; + pMode->Height = modeEx.Height; + pMode->RefreshRate = modeEx.RefreshRate; + pMode->Format = modeEx.Format; + + return D3D_OK; + } + + return D3DERR_INVALIDCALL; + } + + + HRESULT STDMETHODCALLTYPE D3D9InterfaceEx::CheckDeviceType( + UINT Adapter, + D3DDEVTYPE DevType, + D3DFORMAT AdapterFormat, + D3DFORMAT BackBufferFormat, + BOOL bWindowed) { + if (auto* adapter = GetAdapter(Adapter)) + return adapter->CheckDeviceType( + DevType, EnumerateFormat(AdapterFormat), + EnumerateFormat(BackBufferFormat), bWindowed); + + return D3DERR_INVALIDCALL; + } + + + HRESULT STDMETHODCALLTYPE D3D9InterfaceEx::CheckDeviceFormat( + UINT Adapter, + D3DDEVTYPE DeviceType, + D3DFORMAT AdapterFormat, + DWORD Usage, + D3DRESOURCETYPE RType, + D3DFORMAT CheckFormat) { + if (auto* adapter = GetAdapter(Adapter)) + return adapter->CheckDeviceFormat( + DeviceType, EnumerateFormat(AdapterFormat), + Usage, RType, + EnumerateFormat(CheckFormat)); + + return D3DERR_INVALIDCALL; + } + + + HRESULT STDMETHODCALLTYPE D3D9InterfaceEx::CheckDeviceMultiSampleType( + UINT Adapter, + D3DDEVTYPE DeviceType, + D3DFORMAT SurfaceFormat, + BOOL Windowed, + D3DMULTISAMPLE_TYPE MultiSampleType, + DWORD* pQualityLevels) { + if (auto* adapter = GetAdapter(Adapter)) + return adapter->CheckDeviceMultiSampleType( + DeviceType, EnumerateFormat(SurfaceFormat), + Windowed, MultiSampleType, + pQualityLevels); + + return D3DERR_INVALIDCALL; + } + + + HRESULT STDMETHODCALLTYPE D3D9InterfaceEx::CheckDepthStencilMatch( + UINT Adapter, + D3DDEVTYPE DeviceType, + D3DFORMAT AdapterFormat, + D3DFORMAT RenderTargetFormat, + D3DFORMAT DepthStencilFormat) { + if (auto* adapter = GetAdapter(Adapter)) + return adapter->CheckDepthStencilMatch( + DeviceType, EnumerateFormat(AdapterFormat), + EnumerateFormat(RenderTargetFormat), + EnumerateFormat(DepthStencilFormat)); + + return D3DERR_INVALIDCALL; + } + + + HRESULT STDMETHODCALLTYPE D3D9InterfaceEx::CheckDeviceFormatConversion( + UINT Adapter, + D3DDEVTYPE DeviceType, + D3DFORMAT SourceFormat, + D3DFORMAT TargetFormat) { + if (auto* adapter = GetAdapter(Adapter)) + return adapter->CheckDeviceFormatConversion( + DeviceType, EnumerateFormat(SourceFormat), + EnumerateFormat(TargetFormat)); + + return D3DERR_INVALIDCALL; + } + + + HRESULT STDMETHODCALLTYPE D3D9InterfaceEx::GetDeviceCaps( + UINT Adapter, + D3DDEVTYPE DeviceType, + D3DCAPS9* pCaps) { + if (auto* adapter = GetAdapter(Adapter)) + return adapter->GetDeviceCaps( + DeviceType, pCaps); + + return D3DERR_INVALIDCALL; + } + + + HMONITOR STDMETHODCALLTYPE D3D9InterfaceEx::GetAdapterMonitor(UINT Adapter) { + if (auto* adapter = GetAdapter(Adapter)) + return adapter->GetMonitor(); + + return nullptr; + } + + + HRESULT STDMETHODCALLTYPE D3D9InterfaceEx::CreateDevice( + UINT Adapter, + D3DDEVTYPE DeviceType, + HWND hFocusWindow, + DWORD BehaviorFlags, + D3DPRESENT_PARAMETERS* pPresentationParameters, + IDirect3DDevice9** ppReturnedDeviceInterface) { + return this->CreateDeviceEx( + Adapter, + DeviceType, + hFocusWindow, + BehaviorFlags, + pPresentationParameters, + nullptr, // <-- pFullscreenDisplayMode + reinterpret_cast(ppReturnedDeviceInterface)); + } + + + HRESULT STDMETHODCALLTYPE D3D9InterfaceEx::EnumAdapterModes( + UINT Adapter, + D3DFORMAT Format, + UINT Mode, + D3DDISPLAYMODE* pMode) { + if (pMode == nullptr) + return D3DERR_INVALIDCALL; + + D3DDISPLAYMODEFILTER filter; + filter.Format = Format; + filter.ScanLineOrdering = D3DSCANLINEORDERING_PROGRESSIVE; + filter.Size = sizeof(D3DDISPLAYMODEFILTER); + + D3DDISPLAYMODEEX modeEx = { }; + modeEx.Size = sizeof(D3DDISPLAYMODEEX); + HRESULT hr = this->EnumAdapterModesEx(Adapter, &filter, Mode, &modeEx); + + if (FAILED(hr)) + return hr; + + pMode->Width = modeEx.Width; + pMode->Height = modeEx.Height; + pMode->RefreshRate = modeEx.RefreshRate; + pMode->Format = modeEx.Format; + + return D3D_OK; + } + + + // Ex Methods + + + UINT STDMETHODCALLTYPE D3D9InterfaceEx::GetAdapterModeCountEx(UINT Adapter, CONST D3DDISPLAYMODEFILTER* pFilter) { + if (auto* adapter = GetAdapter(Adapter)) + return adapter->GetAdapterModeCountEx(pFilter); + + return 0; + } + + + HRESULT STDMETHODCALLTYPE D3D9InterfaceEx::EnumAdapterModesEx( + UINT Adapter, + const D3DDISPLAYMODEFILTER* pFilter, + UINT Mode, + D3DDISPLAYMODEEX* pMode) { + if (auto* adapter = GetAdapter(Adapter)) + return adapter->EnumAdapterModesEx(pFilter, Mode, pMode); + + return D3DERR_INVALIDCALL; + } + + + HRESULT STDMETHODCALLTYPE D3D9InterfaceEx::GetAdapterDisplayModeEx( + UINT Adapter, + D3DDISPLAYMODEEX* pMode, + D3DDISPLAYROTATION* pRotation) { + if (auto* adapter = GetAdapter(Adapter)) + return adapter->GetAdapterDisplayModeEx(pMode, pRotation); + + return D3DERR_INVALIDCALL; + } + + + HRESULT STDMETHODCALLTYPE D3D9InterfaceEx::CreateDeviceEx( + UINT Adapter, + D3DDEVTYPE DeviceType, + HWND hFocusWindow, + DWORD BehaviorFlags, + D3DPRESENT_PARAMETERS* pPresentationParameters, + D3DDISPLAYMODEEX* pFullscreenDisplayMode, + IDirect3DDevice9Ex** ppReturnedDeviceInterface) { + InitReturnPtr(ppReturnedDeviceInterface); + + if (ppReturnedDeviceInterface == nullptr + || pPresentationParameters == nullptr) + return D3DERR_INVALIDCALL; + + auto* adapter = GetAdapter(Adapter); + + if (adapter == nullptr) + return D3DERR_INVALIDCALL; + + auto dxvkAdapter = adapter->GetDXVKAdapter(); + + try { + auto dxvkDevice = dxvkAdapter->createDevice(m_instance, D3D9DeviceEx::GetDeviceFeatures(dxvkAdapter)); + + auto* device = new D3D9DeviceEx( + this, + adapter, + DeviceType, + hFocusWindow, + BehaviorFlags, + dxvkDevice); + + HRESULT hr = device->InitialReset(pPresentationParameters, pFullscreenDisplayMode); + + if (FAILED(hr)) + return hr; + + *ppReturnedDeviceInterface = ref(device); + } + catch (const DxvkError& e) { + Logger::err(e.message()); + return D3DERR_NOTAVAILABLE; + } + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9InterfaceEx::GetAdapterLUID(UINT Adapter, LUID* pLUID) { + if (auto* adapter = GetAdapter(Adapter)) + return adapter->GetAdapterLUID(pLUID); + + return D3DERR_INVALIDCALL; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_interface.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_interface.h new file mode 100644 index 00000000000..85cc5a03670 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_interface.h @@ -0,0 +1,148 @@ +#pragma once + +#include "d3d9_adapter.h" + +#include "../dxvk/dxvk_instance.h" + +namespace dxvk { + + /** + * \brief D3D9 interface implementation + * + * Implements the IDirect3DDevice9Ex interfaces + * which provides the way to get adapters and create other objects such as \ref IDirect3DDevice9Ex. + * similar to \ref DxgiFactory but for D3D9. + */ + class D3D9InterfaceEx final : public ComObjectClamp { + + public: + + D3D9InterfaceEx(bool bExtended); + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject); + + HRESULT STDMETHODCALLTYPE RegisterSoftwareDevice(void* pInitializeFunction); + + UINT STDMETHODCALLTYPE GetAdapterCount(); + + HRESULT STDMETHODCALLTYPE GetAdapterIdentifier( + UINT Adapter, + DWORD Flags, + D3DADAPTER_IDENTIFIER9* pIdentifier); + + UINT STDMETHODCALLTYPE GetAdapterModeCount(UINT Adapter, D3DFORMAT Format); + + HRESULT STDMETHODCALLTYPE GetAdapterDisplayMode(UINT Adapter, D3DDISPLAYMODE* pMode); + + HRESULT STDMETHODCALLTYPE CheckDeviceType( + UINT Adapter, + D3DDEVTYPE DevType, + D3DFORMAT AdapterFormat, + D3DFORMAT BackBufferFormat, + BOOL bWindowed); + + HRESULT STDMETHODCALLTYPE CheckDeviceFormat( + UINT Adapter, + D3DDEVTYPE DeviceType, + D3DFORMAT AdapterFormat, + DWORD Usage, + D3DRESOURCETYPE RType, + D3DFORMAT CheckFormat); + + HRESULT STDMETHODCALLTYPE CheckDeviceMultiSampleType( + UINT Adapter, + D3DDEVTYPE DeviceType, + D3DFORMAT SurfaceFormat, + BOOL Windowed, + D3DMULTISAMPLE_TYPE MultiSampleType, + DWORD* pQualityLevels); + + HRESULT STDMETHODCALLTYPE CheckDepthStencilMatch( + UINT Adapter, + D3DDEVTYPE DeviceType, + D3DFORMAT AdapterFormat, + D3DFORMAT RenderTargetFormat, + D3DFORMAT DepthStencilFormat); + + HRESULT STDMETHODCALLTYPE CheckDeviceFormatConversion( + UINT Adapter, + D3DDEVTYPE DeviceType, + D3DFORMAT SourceFormat, + D3DFORMAT TargetFormat); + + HRESULT STDMETHODCALLTYPE GetDeviceCaps( + UINT Adapter, + D3DDEVTYPE DeviceType, + D3DCAPS9* pCaps); + + HMONITOR STDMETHODCALLTYPE GetAdapterMonitor(UINT Adapter); + + HRESULT STDMETHODCALLTYPE CreateDevice( + UINT Adapter, + D3DDEVTYPE DeviceType, + HWND hFocusWindow, + DWORD BehaviorFlags, + D3DPRESENT_PARAMETERS* pPresentationParameters, + IDirect3DDevice9** ppReturnedDeviceInterface); + + HRESULT STDMETHODCALLTYPE EnumAdapterModes( + UINT Adapter, + D3DFORMAT Format, + UINT Mode, + D3DDISPLAYMODE* pMode); + + // Ex Methods + + UINT STDMETHODCALLTYPE GetAdapterModeCountEx(UINT Adapter, CONST D3DDISPLAYMODEFILTER* pFilter); + + HRESULT STDMETHODCALLTYPE EnumAdapterModesEx( + UINT Adapter, + const D3DDISPLAYMODEFILTER* pFilter, + UINT Mode, + D3DDISPLAYMODEEX* pMode); + + HRESULT STDMETHODCALLTYPE GetAdapterDisplayModeEx( + UINT Adapter, + D3DDISPLAYMODEEX* pMode, + D3DDISPLAYROTATION* pRotation); + + HRESULT STDMETHODCALLTYPE CreateDeviceEx( + UINT Adapter, + D3DDEVTYPE DeviceType, + HWND hFocusWindow, + DWORD BehaviorFlags, + D3DPRESENT_PARAMETERS* pPresentationParameters, + D3DDISPLAYMODEEX* pFullscreenDisplayMode, + IDirect3DDevice9Ex** ppReturnedDeviceInterface); + + HRESULT STDMETHODCALLTYPE GetAdapterLUID(UINT Adapter, LUID* pLUID); + + const D3D9Options& GetOptions() { return m_d3d9Options; } + + D3D9Adapter* GetAdapter(UINT Ordinal) { + return Ordinal < m_adapters.size() + ? &m_adapters[Ordinal] + : nullptr; + } + + bool IsExtended() { return m_extended; } + + Rc GetInstance() { return m_instance; } + + private: + + void CacheModes(D3D9Format Format); + + static const char* GetDriverDllName(DxvkGpuVendor vendor); + + Rc m_instance; + + bool m_extended; + + D3D9Options m_d3d9Options; + + std::vector m_adapters; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_main.cpp b/utils/dxvk-1.10.3/src/d3d9/d3d9_main.cpp new file mode 100644 index 00000000000..e182b5fa3f6 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_main.cpp @@ -0,0 +1,104 @@ +#include "../dxvk/dxvk_instance.h" + +#include "d3d9_interface.h" +#include "d3d9_shader_validator.h" + +#include "d3d9_annotation.h" + +class D3DFE_PROCESSVERTICES; +using PSGPERRORID = UINT; + +namespace dxvk { + Logger Logger::s_instance("d3d9.log"); + D3D9GlobalAnnotationList D3D9GlobalAnnotationList::s_instance; + + HRESULT CreateD3D9( + bool Extended, + IDirect3D9Ex** ppDirect3D9Ex) { + if (!ppDirect3D9Ex) + return D3DERR_INVALIDCALL; + + *ppDirect3D9Ex = ref(new D3D9InterfaceEx( Extended )); + return D3D_OK; + } +} + + +extern "C" { + + DLLEXPORT IDirect3D9* __stdcall Direct3DCreate9(UINT nSDKVersion) { + IDirect3D9Ex* pDirect3D = nullptr; + dxvk::CreateD3D9(false, &pDirect3D); + + return pDirect3D; + } + + DLLEXPORT HRESULT __stdcall Direct3DCreate9Ex(UINT nSDKVersion, IDirect3D9Ex** ppDirect3D9Ex) { + return dxvk::CreateD3D9(true, ppDirect3D9Ex); + } + + DLLEXPORT int __stdcall D3DPERF_BeginEvent(D3DCOLOR col, LPCWSTR wszName) { + return dxvk::D3D9GlobalAnnotationList::Instance().BeginEvent(col, wszName); + } + + DLLEXPORT int __stdcall D3DPERF_EndEvent(void) { + return dxvk::D3D9GlobalAnnotationList::Instance().EndEvent(); + } + + DLLEXPORT void __stdcall D3DPERF_SetMarker(D3DCOLOR col, LPCWSTR wszName) { + dxvk::D3D9GlobalAnnotationList::Instance().SetMarker(col, wszName); + } + + DLLEXPORT void __stdcall D3DPERF_SetRegion(D3DCOLOR col, LPCWSTR wszName) { + dxvk::D3D9GlobalAnnotationList::Instance().SetRegion(col, wszName); + } + + DLLEXPORT BOOL __stdcall D3DPERF_QueryRepeatFrame(void) { + return dxvk::D3D9GlobalAnnotationList::Instance().QueryRepeatFrame(); + } + + DLLEXPORT void __stdcall D3DPERF_SetOptions(DWORD dwOptions) { + dxvk::D3D9GlobalAnnotationList::Instance().SetOptions(dwOptions); + } + + DLLEXPORT DWORD __stdcall D3DPERF_GetStatus(void) { + return dxvk::D3D9GlobalAnnotationList::Instance().GetStatus(); + } + + + DLLEXPORT void __stdcall DebugSetMute(void) { + } + + DLLEXPORT int __stdcall DebugSetLevel(void) { + return 0; + } + + // Processor Specific Geometry Pipeline + // for P3 SIMD/AMD 3DNow. + + DLLEXPORT void __stdcall PSGPError(D3DFE_PROCESSVERTICES* a, PSGPERRORID b, UINT c) { + } + + DLLEXPORT void __stdcall PSGPSampleTexture(D3DFE_PROCESSVERTICES* a, UINT b, float(*const c)[4], UINT d, float(*const e)[4]) { + } + + DLLEXPORT dxvk::D3D9ShaderValidator* __stdcall Direct3DShaderValidatorCreate9(void) { + return ref(new dxvk::D3D9ShaderValidator()); + } + + DLLEXPORT int __stdcall Direct3D9EnableMaximizedWindowedModeShim(UINT a) { + return 0; + } + + DLLEXPORT void __stdcall DXVK_RegisterAnnotation(IDXVKUserDefinedAnnotation* annotation) { + dxvk::D3D9GlobalAnnotationList::Instance().RegisterAnnotator(annotation); + } + + DLLEXPORT void __stdcall DXVK_UnRegisterAnnotation(IDXVKUserDefinedAnnotation* annotation) { + dxvk::D3D9GlobalAnnotationList::Instance().UnregisterAnnotator(annotation); + } + + DLLEXPORT void __stdcall Direct3D9ForceHybridEnumeration(UINT uHybrid) { + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_monitor.cpp b/utils/dxvk-1.10.3/src/d3d9/d3d9_monitor.cpp new file mode 100644 index 00000000000..51167afd2df --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_monitor.cpp @@ -0,0 +1,64 @@ +#include "d3d9_monitor.h" + +#include "d3d9_format.h" + +namespace dxvk { + + uint32_t GetMonitorFormatBpp(D3D9Format Format) { + switch (Format) { + case D3D9Format::A8R8G8B8: + case D3D9Format::X8R8G8B8: // This is still 32 bit even though the alpha is unspecified. + case D3D9Format::A2R10G10B10: + return 32; + + case D3D9Format::A1R5G5B5: + case D3D9Format::X1R5G5B5: + case D3D9Format::R5G6B5: + return 16; + + default: + Logger::warn(str::format( + "GetMonitorFormatBpp: Unknown format: ", + Format)); + return 32; + } + } + + + bool IsSupportedAdapterFormat( + D3D9Format Format) { + return Format == D3D9Format::A2R10G10B10 + || Format == D3D9Format::X8R8G8B8 + || Format == D3D9Format::X1R5G5B5 + || Format == D3D9Format::R5G6B5; + } + + + bool IsSupportedBackBufferFormat( + D3D9Format AdapterFormat, + D3D9Format BackBufferFormat, + BOOL Windowed) { + if (!Windowed) { + return (AdapterFormat == D3D9Format::A2R10G10B10 && BackBufferFormat == D3D9Format::A2R10G10B10) || + (AdapterFormat == D3D9Format::X8R8G8B8 && BackBufferFormat == D3D9Format::X8R8G8B8) || + (AdapterFormat == D3D9Format::X8R8G8B8 && BackBufferFormat == D3D9Format::A8R8G8B8) || + (AdapterFormat == D3D9Format::X1R5G5B5 && BackBufferFormat == D3D9Format::X1R5G5B5) || + (AdapterFormat == D3D9Format::X1R5G5B5 && BackBufferFormat == D3D9Format::A1R5G5B5) || + (AdapterFormat == D3D9Format::R5G6B5 && BackBufferFormat == D3D9Format::R5G6B5); + } + + return IsSupportedBackBufferFormat(BackBufferFormat); + } + + bool IsSupportedBackBufferFormat( + D3D9Format BackBufferFormat) { + return BackBufferFormat == D3D9Format::A2R10G10B10 + || BackBufferFormat == D3D9Format::A8R8G8B8 + || BackBufferFormat == D3D9Format::X8R8G8B8 + || BackBufferFormat == D3D9Format::A1R5G5B5 + || BackBufferFormat == D3D9Format::X1R5G5B5 + || BackBufferFormat == D3D9Format::R5G6B5 + || BackBufferFormat == D3D9Format::Unknown; + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_monitor.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_monitor.h new file mode 100644 index 00000000000..0a9d1a89da2 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_monitor.h @@ -0,0 +1,35 @@ +#pragma once + +#include "d3d9_include.h" + +#include "d3d9_format.h" + +namespace dxvk { + + /** + * \brief Queries bits per pixel for a format + * + * The format must be a valid swap chain format. + * \param [in] Format The D3D9 format to query + * \returns Bits per pixel for this format + */ + uint32_t GetMonitorFormatBpp( + D3D9Format Format); + + /** + * \brief Returns if a format is supported for a backbuffer/swapchain. + * + * \param [in] Format The D3D9 format to query + * \returns If it is supported as a swapchain/backbuffer format. + */ + bool IsSupportedAdapterFormat( + D3D9Format Format); + + bool IsSupportedBackBufferFormat( + D3D9Format AdapterFormat, + D3D9Format BackBufferFormat, + BOOL Windowed); + + bool IsSupportedBackBufferFormat( + D3D9Format BackBufferFormat); +} diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_multithread.cpp b/utils/dxvk-1.10.3/src/d3d9/d3d9_multithread.cpp new file mode 100644 index 00000000000..0e10a093123 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_multithread.cpp @@ -0,0 +1,9 @@ +#include "d3d9_device.h" + +namespace dxvk { + + D3D9Multithread::D3D9Multithread( + BOOL Protected) + : m_protected( Protected ) { } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_multithread.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_multithread.h new file mode 100644 index 00000000000..f91857b6a3a --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_multithread.h @@ -0,0 +1,77 @@ +#pragma once + +#include "d3d9_include.h" + +namespace dxvk { + + /** + * \brief Device lock + * + * Lightweight RAII wrapper that implements + * a subset of the functionality provided by + * \c std::unique_lock, with the goal of being + * cheaper to construct and destroy. + */ + class D3D9DeviceLock { + + public: + + D3D9DeviceLock() + : m_mutex(nullptr) { } + + D3D9DeviceLock(sync::RecursiveSpinlock& mutex) + : m_mutex(&mutex) { + mutex.lock(); + } + + D3D9DeviceLock(D3D9DeviceLock&& other) + : m_mutex(other.m_mutex) { + other.m_mutex = nullptr; + } + + D3D9DeviceLock& operator = (D3D9DeviceLock&& other) { + if (m_mutex) + m_mutex->unlock(); + + m_mutex = other.m_mutex; + other.m_mutex = nullptr; + return *this; + } + + ~D3D9DeviceLock() { + if (m_mutex != nullptr) + m_mutex->unlock(); + } + + private: + + sync::RecursiveSpinlock* m_mutex; + + }; + + + /** + * \brief D3D9 context lock + */ + class D3D9Multithread { + + public: + + D3D9Multithread( + BOOL Protected); + + D3D9DeviceLock AcquireLock() { + return m_protected + ? D3D9DeviceLock(m_mutex) + : D3D9DeviceLock(); + } + + private: + + BOOL m_protected; + + sync::RecursiveSpinlock m_mutex; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_names.cpp b/utils/dxvk-1.10.3/src/d3d9/d3d9_names.cpp new file mode 100644 index 00000000000..e7b7b6a669a --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_names.cpp @@ -0,0 +1,230 @@ +#include "d3d9_format.h" + +namespace dxvk { + + std::ostream& operator << (std::ostream& os, D3D9Format e) { + switch (e) { + ENUM_NAME(D3D9Format::Unknown); + + ENUM_NAME(D3D9Format::R8G8B8); + ENUM_NAME(D3D9Format::A8R8G8B8); + ENUM_NAME(D3D9Format::X8R8G8B8); + ENUM_NAME(D3D9Format::R5G6B5); + ENUM_NAME(D3D9Format::X1R5G5B5); + ENUM_NAME(D3D9Format::A1R5G5B5); + ENUM_NAME(D3D9Format::A4R4G4B4); + ENUM_NAME(D3D9Format::R3G3B2); + ENUM_NAME(D3D9Format::A8); + ENUM_NAME(D3D9Format::A8R3G3B2); + ENUM_NAME(D3D9Format::X4R4G4B4); + ENUM_NAME(D3D9Format::A2B10G10R10); + ENUM_NAME(D3D9Format::A8B8G8R8); + ENUM_NAME(D3D9Format::X8B8G8R8); + ENUM_NAME(D3D9Format::G16R16); + ENUM_NAME(D3D9Format::A2R10G10B10); + ENUM_NAME(D3D9Format::A16B16G16R16); + ENUM_NAME(D3D9Format::A8P8); + ENUM_NAME(D3D9Format::P8); + ENUM_NAME(D3D9Format::L8); + ENUM_NAME(D3D9Format::A8L8); + ENUM_NAME(D3D9Format::A4L4); + ENUM_NAME(D3D9Format::V8U8); + ENUM_NAME(D3D9Format::L6V5U5); + ENUM_NAME(D3D9Format::X8L8V8U8); + ENUM_NAME(D3D9Format::Q8W8V8U8); + ENUM_NAME(D3D9Format::V16U16); + ENUM_NAME(D3D9Format::A2W10V10U10); + ENUM_NAME(D3D9Format::UYVY); + ENUM_NAME(D3D9Format::R8G8_B8G8); + ENUM_NAME(D3D9Format::YUY2); + ENUM_NAME(D3D9Format::G8R8_G8B8); + ENUM_NAME(D3D9Format::DXT1); + ENUM_NAME(D3D9Format::DXT2); + ENUM_NAME(D3D9Format::DXT3); + ENUM_NAME(D3D9Format::DXT4); + ENUM_NAME(D3D9Format::DXT5); + ENUM_NAME(D3D9Format::D16_LOCKABLE); + ENUM_NAME(D3D9Format::D32); + ENUM_NAME(D3D9Format::D15S1); + ENUM_NAME(D3D9Format::D24S8); + ENUM_NAME(D3D9Format::D24X8); + ENUM_NAME(D3D9Format::D24X4S4); + ENUM_NAME(D3D9Format::D16); + ENUM_NAME(D3D9Format::D32F_LOCKABLE); + ENUM_NAME(D3D9Format::D24FS8); + ENUM_NAME(D3D9Format::D32_LOCKABLE); + ENUM_NAME(D3D9Format::S8_LOCKABLE); + ENUM_NAME(D3D9Format::L16); + ENUM_NAME(D3D9Format::VERTEXDATA); + ENUM_NAME(D3D9Format::INDEX16); + ENUM_NAME(D3D9Format::INDEX32); + ENUM_NAME(D3D9Format::Q16W16V16U16); + ENUM_NAME(D3D9Format::MULTI2_ARGB8); + ENUM_NAME(D3D9Format::R16F); + ENUM_NAME(D3D9Format::G16R16F); + ENUM_NAME(D3D9Format::A16B16G16R16F); + ENUM_NAME(D3D9Format::R32F); + ENUM_NAME(D3D9Format::G32R32F); + ENUM_NAME(D3D9Format::A32B32G32R32F); + ENUM_NAME(D3D9Format::CxV8U8); + ENUM_NAME(D3D9Format::A1); + ENUM_NAME(D3D9Format::A2B10G10R10_XR_BIAS); + ENUM_NAME(D3D9Format::BINARYBUFFER); + + // Driver Hacks / Unofficial Formats + ENUM_NAME(D3D9Format::ATI1); + ENUM_NAME(D3D9Format::ATI2); + ENUM_NAME(D3D9Format::INST); + ENUM_NAME(D3D9Format::DF24); + ENUM_NAME(D3D9Format::DF16); + ENUM_NAME(D3D9Format::NULL_FORMAT); + ENUM_NAME(D3D9Format::GET4); + ENUM_NAME(D3D9Format::GET1); + ENUM_NAME(D3D9Format::NVDB); + ENUM_NAME(D3D9Format::A2M1); + ENUM_NAME(D3D9Format::A2M0); + ENUM_NAME(D3D9Format::ATOC); + ENUM_NAME(D3D9Format::INTZ); + ENUM_NAME(D3D9Format::RAWZ); + ENUM_NAME(D3D9Format::RESZ); + + ENUM_NAME(D3D9Format::NV11); + ENUM_NAME(D3D9Format::NV12); + ENUM_NAME(D3D9Format::P010); + ENUM_NAME(D3D9Format::P016); + ENUM_NAME(D3D9Format::Y210); + ENUM_NAME(D3D9Format::Y216); + ENUM_NAME(D3D9Format::Y410); + ENUM_NAME(D3D9Format::AYUV); + ENUM_NAME(D3D9Format::YV12); + ENUM_NAME(D3D9Format::OPAQUE_420); + + ENUM_NAME(D3D9Format::AI44); + ENUM_NAME(D3D9Format::IA44); + ENUM_NAME(D3D9Format::R2VB); + ENUM_NAME(D3D9Format::COPM); + ENUM_NAME(D3D9Format::SSAA); + ENUM_NAME(D3D9Format::AL16); + ENUM_NAME(D3D9Format::R16); + + ENUM_NAME(D3D9Format::EXT1); + ENUM_NAME(D3D9Format::FXT1); + ENUM_NAME(D3D9Format::GXT1); + ENUM_NAME(D3D9Format::HXT1); + + ENUM_DEFAULT(e); + } + } + + + std::ostream& operator << (std::ostream& os, D3DRENDERSTATETYPE e) { + switch (e) { + ENUM_NAME(D3DRS_ZENABLE); + ENUM_NAME(D3DRS_FILLMODE); + ENUM_NAME(D3DRS_SHADEMODE); + ENUM_NAME(D3DRS_ZWRITEENABLE); + ENUM_NAME(D3DRS_ALPHATESTENABLE); + ENUM_NAME(D3DRS_LASTPIXEL); + ENUM_NAME(D3DRS_SRCBLEND); + ENUM_NAME(D3DRS_DESTBLEND); + ENUM_NAME(D3DRS_CULLMODE); + ENUM_NAME(D3DRS_ZFUNC); + ENUM_NAME(D3DRS_ALPHAREF); + ENUM_NAME(D3DRS_ALPHAFUNC); + ENUM_NAME(D3DRS_DITHERENABLE); + ENUM_NAME(D3DRS_ALPHABLENDENABLE); + ENUM_NAME(D3DRS_FOGENABLE); + ENUM_NAME(D3DRS_SPECULARENABLE); + ENUM_NAME(D3DRS_FOGCOLOR); + ENUM_NAME(D3DRS_FOGTABLEMODE); + ENUM_NAME(D3DRS_FOGSTART); + ENUM_NAME(D3DRS_FOGEND); + ENUM_NAME(D3DRS_FOGDENSITY); + ENUM_NAME(D3DRS_RANGEFOGENABLE); + ENUM_NAME(D3DRS_STENCILENABLE); + ENUM_NAME(D3DRS_STENCILFAIL); + ENUM_NAME(D3DRS_STENCILZFAIL); + ENUM_NAME(D3DRS_STENCILPASS); + ENUM_NAME(D3DRS_STENCILFUNC); + ENUM_NAME(D3DRS_STENCILREF); + ENUM_NAME(D3DRS_STENCILMASK); + ENUM_NAME(D3DRS_STENCILWRITEMASK); + ENUM_NAME(D3DRS_TEXTUREFACTOR); + ENUM_NAME(D3DRS_WRAP0); + ENUM_NAME(D3DRS_WRAP1); + ENUM_NAME(D3DRS_WRAP2); + ENUM_NAME(D3DRS_WRAP3); + ENUM_NAME(D3DRS_WRAP4); + ENUM_NAME(D3DRS_WRAP5); + ENUM_NAME(D3DRS_WRAP6); + ENUM_NAME(D3DRS_WRAP7); + ENUM_NAME(D3DRS_CLIPPING); + ENUM_NAME(D3DRS_LIGHTING); + ENUM_NAME(D3DRS_AMBIENT); + ENUM_NAME(D3DRS_FOGVERTEXMODE); + ENUM_NAME(D3DRS_COLORVERTEX); + ENUM_NAME(D3DRS_LOCALVIEWER); + ENUM_NAME(D3DRS_NORMALIZENORMALS); + ENUM_NAME(D3DRS_DIFFUSEMATERIALSOURCE); + ENUM_NAME(D3DRS_SPECULARMATERIALSOURCE); + ENUM_NAME(D3DRS_AMBIENTMATERIALSOURCE); + ENUM_NAME(D3DRS_EMISSIVEMATERIALSOURCE); + ENUM_NAME(D3DRS_VERTEXBLEND); + ENUM_NAME(D3DRS_CLIPPLANEENABLE); + ENUM_NAME(D3DRS_POINTSIZE); + ENUM_NAME(D3DRS_POINTSIZE_MIN); + ENUM_NAME(D3DRS_POINTSPRITEENABLE); + ENUM_NAME(D3DRS_POINTSCALEENABLE); + ENUM_NAME(D3DRS_POINTSCALE_A); + ENUM_NAME(D3DRS_POINTSCALE_B); + ENUM_NAME(D3DRS_POINTSCALE_C); + ENUM_NAME(D3DRS_MULTISAMPLEANTIALIAS); + ENUM_NAME(D3DRS_MULTISAMPLEMASK); + ENUM_NAME(D3DRS_PATCHEDGESTYLE); + ENUM_NAME(D3DRS_DEBUGMONITORTOKEN); + ENUM_NAME(D3DRS_POINTSIZE_MAX); + ENUM_NAME(D3DRS_INDEXEDVERTEXBLENDENABLE); + ENUM_NAME(D3DRS_COLORWRITEENABLE); + ENUM_NAME(D3DRS_TWEENFACTOR); + ENUM_NAME(D3DRS_BLENDOP); + ENUM_NAME(D3DRS_POSITIONDEGREE); + ENUM_NAME(D3DRS_NORMALDEGREE); + ENUM_NAME(D3DRS_SCISSORTESTENABLE); + ENUM_NAME(D3DRS_SLOPESCALEDEPTHBIAS); + ENUM_NAME(D3DRS_ANTIALIASEDLINEENABLE); + ENUM_NAME(D3DRS_MINTESSELLATIONLEVEL); + ENUM_NAME(D3DRS_MAXTESSELLATIONLEVEL); + ENUM_NAME(D3DRS_ADAPTIVETESS_X); + ENUM_NAME(D3DRS_ADAPTIVETESS_Y); + ENUM_NAME(D3DRS_ADAPTIVETESS_Z); + ENUM_NAME(D3DRS_ADAPTIVETESS_W); + ENUM_NAME(D3DRS_ENABLEADAPTIVETESSELLATION); + ENUM_NAME(D3DRS_TWOSIDEDSTENCILMODE); + ENUM_NAME(D3DRS_CCW_STENCILFAIL); + ENUM_NAME(D3DRS_CCW_STENCILZFAIL); + ENUM_NAME(D3DRS_CCW_STENCILPASS); + ENUM_NAME(D3DRS_CCW_STENCILFUNC); + ENUM_NAME(D3DRS_COLORWRITEENABLE1); + ENUM_NAME(D3DRS_COLORWRITEENABLE2); + ENUM_NAME(D3DRS_COLORWRITEENABLE3); + ENUM_NAME(D3DRS_BLENDFACTOR); + ENUM_NAME(D3DRS_SRGBWRITEENABLE); + ENUM_NAME(D3DRS_DEPTHBIAS); + ENUM_NAME(D3DRS_WRAP8); + ENUM_NAME(D3DRS_WRAP9); + ENUM_NAME(D3DRS_WRAP10); + ENUM_NAME(D3DRS_WRAP11); + ENUM_NAME(D3DRS_WRAP12); + ENUM_NAME(D3DRS_WRAP13); + ENUM_NAME(D3DRS_WRAP14); + ENUM_NAME(D3DRS_WRAP15); + ENUM_NAME(D3DRS_SEPARATEALPHABLENDENABLE); + ENUM_NAME(D3DRS_SRCBLENDALPHA); + ENUM_NAME(D3DRS_DESTBLENDALPHA); + ENUM_NAME(D3DRS_BLENDOPALPHA); + + ENUM_DEFAULT(e); + } + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_names.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_names.h new file mode 100644 index 00000000000..82d9c47907f --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_names.h @@ -0,0 +1,7 @@ +#include "d3d9_include.h" + +namespace dxvk { + + std::ostream& operator << (std::ostream& os, D3DRENDERSTATETYPE e); + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_options.cpp b/utils/dxvk-1.10.3/src/d3d9/d3d9_options.cpp new file mode 100644 index 00000000000..29d2c60a627 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_options.cpp @@ -0,0 +1,103 @@ +#include "d3d9_options.h" + +#include "d3d9_caps.h" + +namespace dxvk { + + static int32_t parsePciId(const std::string& str) { + if (str.size() != 4) + return -1; + + int32_t id = 0; + + for (size_t i = 0; i < str.size(); i++) { + id *= 16; + + if (str[i] >= '0' && str[i] <= '9') + id += str[i] - '0'; + else if (str[i] >= 'A' && str[i] <= 'F') + id += str[i] - 'A' + 10; + else if (str[i] >= 'a' && str[i] <= 'f') + id += str[i] - 'a' + 10; + else + return -1; + } + + return id; + } + + + D3D9Options::D3D9Options(const Rc& device, const Config& config) { + const Rc adapter = device != nullptr ? device->adapter() : nullptr; + + // Fetch these as a string representing a hexadecimal number and parse it. + this->customVendorId = parsePciId(config.getOption("d3d9.customVendorId")); + this->customDeviceId = parsePciId(config.getOption("d3d9.customDeviceId")); + this->customDeviceDesc = config.getOption("d3d9.customDeviceDesc"); + + const int32_t vendorId = this->customDeviceId != -1 + ? this->customDeviceId + : (adapter != nullptr ? adapter->deviceProperties().vendorID : 0); + + this->maxFrameLatency = config.getOption ("d3d9.maxFrameLatency", 0); + this->maxFrameRate = config.getOption ("d3d9.maxFrameRate", 0); + this->presentInterval = config.getOption ("d3d9.presentInterval", -1); + this->shaderModel = config.getOption ("d3d9.shaderModel", 3); + this->evictManagedOnUnlock = config.getOption ("d3d9.evictManagedOnUnlock", false); + this->dpiAware = config.getOption ("d3d9.dpiAware", true); + this->strictConstantCopies = config.getOption ("d3d9.strictConstantCopies", false); + this->strictPow = config.getOption ("d3d9.strictPow", true); + this->lenientClear = config.getOption ("d3d9.lenientClear", false); + this->numBackBuffers = config.getOption ("d3d9.numBackBuffers", 0); + this->noExplicitFrontBuffer = config.getOption ("d3d9.noExplicitFrontBuffer", false); + this->deferSurfaceCreation = config.getOption ("d3d9.deferSurfaceCreation", false); + this->samplerAnisotropy = config.getOption ("d3d9.samplerAnisotropy", -1); + this->maxAvailableMemory = config.getOption ("d3d9.maxAvailableMemory", 4096); + this->supportDFFormats = config.getOption ("d3d9.supportDFFormats", true); + this->supportX4R4G4B4 = config.getOption ("d3d9.supportX4R4G4B4", true); + this->supportD32 = config.getOption ("d3d9.supportD32", true); + this->disableA8RT = config.getOption ("d3d9.disableA8RT", false); + this->invariantPosition = config.getOption ("d3d9.invariantPosition", true); + this->memoryTrackTest = config.getOption ("d3d9.memoryTrackTest", false); + this->supportVCache = config.getOption ("d3d9.supportVCache", vendorId == 0x10de); + this->enableDialogMode = config.getOption ("d3d9.enableDialogMode", false); + this->forceSamplerTypeSpecConstants = config.getOption ("d3d9.forceSamplerTypeSpecConstants", false); + this->forceSwapchainMSAA = config.getOption ("d3d9.forceSwapchainMSAA", -1); + this->forceAspectRatio = config.getOption ("d3d9.forceAspectRatio", ""); + this->allowDoNotWait = config.getOption ("d3d9.allowDoNotWait", true); + this->allowDiscard = config.getOption ("d3d9.allowDiscard", true); + this->enumerateByDisplays = config.getOption ("d3d9.enumerateByDisplays", true); + this->longMad = config.getOption ("d3d9.longMad", false); + this->tearFree = config.getOption ("d3d9.tearFree", Tristate::Auto); + this->alphaTestWiggleRoom = config.getOption ("d3d9.alphaTestWiggleRoom", false); + this->apitraceMode = config.getOption ("d3d9.apitraceMode", false); + this->deviceLocalConstantBuffers = config.getOption ("d3d9.deviceLocalConstantBuffers", false); + this->allowDirectBufferMapping = config.getOption ("d3d9.allowDirectBufferMapping", true); + this->seamlessCubes = config.getOption ("d3d9.seamlessCubes", false); + + // If we are not Nvidia, enable general hazards. + this->generalHazards = adapter != nullptr + && !adapter->matchesDriver( + DxvkGpuVendor::Nvidia, + VK_DRIVER_ID_NVIDIA_PROPRIETARY_KHR, + 0, 0); + applyTristate(this->generalHazards, config.getOption("d3d9.generalHazards", Tristate::Auto)); + + std::string floatEmulation = Config::toLower(config.getOption("d3d9.floatEmulation", "auto")); + if (floatEmulation == "strict") { + d3d9FloatEmulation = D3D9FloatEmulation::Strict; + } else if (floatEmulation == "false") { + d3d9FloatEmulation = D3D9FloatEmulation::Disabled; + } else if (floatEmulation == "true") { + d3d9FloatEmulation = D3D9FloatEmulation::Enabled; + } else { + bool hasMulz = adapter != nullptr + && adapter->matchesDriver(DxvkGpuVendor::Amd, + VK_DRIVER_ID_MESA_RADV, + VK_MAKE_VERSION(21, 99, 99), + 0); + d3d9FloatEmulation = hasMulz ? D3D9FloatEmulation::Strict : D3D9FloatEmulation::Enabled; + } + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_options.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_options.h new file mode 100644 index 00000000000..17ffb41d7e2 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_options.h @@ -0,0 +1,165 @@ +#pragma once + +#include "../util/config/config.h" +#include "../dxvk/dxvk_device.h" + +namespace dxvk { + + enum class D3D9FloatEmulation { + Disabled, + Enabled, + Strict + }; + + struct D3D9Options { + + D3D9Options(const Rc& device, const Config& config); + + /// Override PCI vendor and device IDs reported to the + /// application. This may make apps think they are running + /// on a different GPU than they do and behave differently. + int32_t customVendorId; + int32_t customDeviceId; + std::string customDeviceDesc; + + /// Present interval. Overrides the value + /// in D3DPRESENT_PARAMS used in swapchain present. + int32_t presentInterval; + + /// Override maximum frame latency if the app specifies + /// a higher value. May help with frame timing issues. + int32_t maxFrameLatency; + + /// Limit frame rate + int32_t maxFrameRate; + + /// Set the max shader model the device can support in the caps. + int32_t shaderModel; + + /// Whether or not managed resources should stay in memory until unlock, or until manually evicted. + bool evictManagedOnUnlock; + + /// Whether or not to set the process as DPI aware in Windows when the API interface is created. + bool dpiAware; + + /// True: Copy our constant set into UBO if we are relative indexing ever. + /// False: Copy our constant set into UBO if we are relative indexing at the start of a defined constant + /// Why?: In theory, FXC should never generate code where this would be an issue. + bool strictConstantCopies; + + /// Whether or not we should care about pow(0, 0) = 1 + bool strictPow; + + /// Whether or not to do a fast path clear if we're close enough to the whole render target. + bool lenientClear; + + /// Back buffer count for the Vulkan swap chain. + /// Overrides buffer count in present parameters. + int32_t numBackBuffers; + + /// Don't create an explicit front buffer in our own swapchain. The Vulkan swapchain is unaffected. + /// Some games don't handle front/backbuffer flipping very well because they don't always redraw + /// each frame completely, and rely on old pixel data from the previous frame to still be there. + /// When this option is set and a game only requests one backbuffer, there will be no flipping in + /// our own swapchain, so the game will always draw to the same buffer and can rely on old pixel + /// data to still be there after a Present call. + /// This means that D3D9SwapChainEx::GetFrontBufferData returns data from the backbuffer of the + /// previous frame, which is the same as the current backbuffer if only 1 backbuffer was requested. + bool noExplicitFrontBuffer; + + /// Defer surface creation + bool deferSurfaceCreation; + + /// Whether to transition to general + /// for rendering hazards + bool generalHazards; + + /// Anisotropic filter override + /// + /// Enforces anisotropic filtering with the + /// given anisotropy value for all samplers. + int32_t samplerAnisotropy; + + /// Max available memory override + /// + /// Changes the max initial value used in + /// tracking and GetAvailableTextureMem + uint32_t maxAvailableMemory; + + /// D3D9 Floating Point Emulation (anything * 0 = 0) + D3D9FloatEmulation d3d9FloatEmulation; + + /// Support the DF16 & DF24 texture format + bool supportDFFormats; + + /// Support X4R4G4B4 + bool supportX4R4G4B4; + + /// Support D32 + bool supportD32; + + /// Disable D3DFMT_A8 for render targets. + /// Specifically to work around a game + /// bug in The Sims 2 that happens on native too! + bool disableA8RT; + + /// Work around a NV driver quirk + /// Fixes flickering/z-fighting in some games. + bool invariantPosition; + + /// Whether or not to respect memory tracking for + /// failing resource allocation. + bool memoryTrackTest; + + /// Support VCACHE query + bool supportVCache; + + /// Forced aspect ratio, disable other modes + std::string forceAspectRatio; + + /// Enable dialog mode (ie. no exclusive fullscreen) + bool enableDialogMode; + + /// Always use a spec constant to determine sampler type (instead of just in PS 1.x) + /// Works around a game bug in Halo CE where it gives cube textures to 2d/volume samplers + bool forceSamplerTypeSpecConstants; + + /// Forces an MSAA level on the swapchain + int32_t forceSwapchainMSAA; + + /// Allow D3DLOCK_DONOTWAIT + bool allowDoNotWait; + + /// Allow D3DLOCK_DISCARD + bool allowDiscard; + + /// Enumerate adapters by displays + bool enumerateByDisplays; + + /// Should we make our Mads a FFma or do it the long way with an FMul and an FAdd? + /// This solves some rendering bugs in games that have z-pass shaders which + /// don't match entirely to the regular vertex shader in this way. + bool longMad; + + /// Tear-free mode if vsync is disabled + /// Tearing mode if vsync is enabled + Tristate tearFree; + + /// Workaround for games using alpha test == 1.0, etc due to wonky interpolation or + /// misc. imprecision on some vendors + bool alphaTestWiggleRoom; + + /// Apitrace mode: Maps all buffers in cached memory. + bool apitraceMode; + + /// Use device local memory for constant buffers. + bool deviceLocalConstantBuffers; + + /// Disable direct buffer mapping + bool allowDirectBufferMapping; + + /// Don't use non seamless cube maps + bool seamlessCubes; + }; + +} diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_query.cpp b/utils/dxvk-1.10.3/src/d3d9/d3d9_query.cpp new file mode 100644 index 00000000000..7ce47cf97da --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_query.cpp @@ -0,0 +1,338 @@ +#include "d3d9_query.h" + +#include "d3d9_device.h" + +namespace dxvk { + + D3D9Query::D3D9Query( + D3D9DeviceEx* pDevice, + D3DQUERYTYPE QueryType) + : D3D9DeviceChild(pDevice) + , m_queryType (QueryType) + , m_state (D3D9_VK_QUERY_INITIAL) { + Rc dxvkDevice = m_parent->GetDXVKDevice(); + + switch (m_queryType) { + case D3DQUERYTYPE_VCACHE: + break; + + case D3DQUERYTYPE_EVENT: + m_event[0] = dxvkDevice->createGpuEvent(); + break; + + case D3DQUERYTYPE_OCCLUSION: + m_query[0] = dxvkDevice->createGpuQuery( + VK_QUERY_TYPE_OCCLUSION, + VK_QUERY_CONTROL_PRECISE_BIT, 0); + break; + + case D3DQUERYTYPE_TIMESTAMP: + m_query[0] = dxvkDevice->createGpuQuery( + VK_QUERY_TYPE_TIMESTAMP, 0, 0); + break; + + case D3DQUERYTYPE_TIMESTAMPDISJOINT: + for (uint32_t i = 0; i < 2; i++) { + m_query[i] = dxvkDevice->createGpuQuery( + VK_QUERY_TYPE_TIMESTAMP, 0, 0); + } + break; + + case D3DQUERYTYPE_TIMESTAMPFREQ: + break; + + case D3DQUERYTYPE_VERTEXSTATS: + m_query[0] = dxvkDevice->createGpuQuery( + VK_QUERY_TYPE_PIPELINE_STATISTICS, 0, 0); + break; + + default: + throw DxvkError(str::format("D3D9Query: Unsupported query type ", m_queryType)); + } + } + + + HRESULT STDMETHODCALLTYPE D3D9Query::QueryInterface(REFIID riid, void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(IDirect3DQuery9)) { + *ppvObject = ref(this); + return S_OK; + } + + Logger::warn("D3D9Query::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + D3DQUERYTYPE STDMETHODCALLTYPE D3D9Query::GetType() { + return m_queryType; + } + + + DWORD STDMETHODCALLTYPE D3D9Query::GetDataSize() { + switch (m_queryType) { + case D3DQUERYTYPE_VCACHE: return sizeof(D3DDEVINFO_VCACHE); + case D3DQUERYTYPE_RESOURCEMANAGER: return sizeof(D3DDEVINFO_RESOURCEMANAGER); + case D3DQUERYTYPE_VERTEXSTATS: return sizeof(D3DDEVINFO_D3DVERTEXSTATS); + case D3DQUERYTYPE_EVENT: return sizeof(BOOL); + case D3DQUERYTYPE_OCCLUSION: return sizeof(DWORD); + case D3DQUERYTYPE_TIMESTAMP: return sizeof(UINT64); + case D3DQUERYTYPE_TIMESTAMPDISJOINT: return sizeof(BOOL); + case D3DQUERYTYPE_TIMESTAMPFREQ: return sizeof(UINT64); + case D3DQUERYTYPE_PIPELINETIMINGS: return sizeof(D3DDEVINFO_D3D9PIPELINETIMINGS); + case D3DQUERYTYPE_INTERFACETIMINGS: return sizeof(D3DDEVINFO_D3D9INTERFACETIMINGS); + case D3DQUERYTYPE_VERTEXTIMINGS: return sizeof(D3DDEVINFO_D3D9STAGETIMINGS); + case D3DQUERYTYPE_PIXELTIMINGS: return sizeof(D3DDEVINFO_D3D9PIPELINETIMINGS); + case D3DQUERYTYPE_BANDWIDTHTIMINGS: return sizeof(D3DDEVINFO_D3D9BANDWIDTHTIMINGS); + case D3DQUERYTYPE_CACHEUTILIZATION: return sizeof(D3DDEVINFO_D3D9CACHEUTILIZATION); + default: return 0; + } + } + + + HRESULT STDMETHODCALLTYPE D3D9Query::Issue(DWORD dwIssueFlags) { + // Note: No need to submit to CS if we don't do anything! + + if (dwIssueFlags == D3DISSUE_BEGIN) { + if (QueryBeginnable(m_queryType)) { + if (m_state == D3D9_VK_QUERY_BEGUN && QueryEndable(m_queryType)) + m_parent->End(this); + + m_parent->Begin(this); + + m_state = D3D9_VK_QUERY_BEGUN; + } + } + else { + if (QueryEndable(m_queryType)) { + if (m_state != D3D9_VK_QUERY_BEGUN && QueryBeginnable(m_queryType)) + m_parent->Begin(this); + + m_resetCtr.fetch_add(1, std::memory_order_acquire); + + m_parent->End(this); + + } + m_state = D3D9_VK_QUERY_ENDED; + } + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9Query::GetData(void* pData, DWORD dwSize, DWORD dwGetDataFlags) { + if (m_state == D3D9_VK_QUERY_CACHED) { + // Query data was already retrieved once. + // Use cached query data to prevent having to check the VK event + // and having to iterate over the VK queries again + if (likely(pData && dwSize)) { + if (m_queryType != D3DQUERYTYPE_EVENT) { + memcpy(pData, &m_dataCache, dwSize); + } else { + *static_cast(pData) = true; + } + } + return D3D_OK; + } + + HRESULT hr = this->GetQueryData(pData, dwSize); + + bool flush = dwGetDataFlags & D3DGETDATA_FLUSH; + + // If we get S_FALSE and it's not from the fact + // they didn't call end, do some flushy stuff... + if (flush && hr == S_FALSE && m_state != D3D9_VK_QUERY_BEGUN) { + this->NotifyStall(); + m_parent->FlushImplicit(FALSE); + } + + return hr; + } + + + HRESULT D3D9Query::GetQueryData(void* pData, DWORD dwSize) { + // Let the game know that calling end might be a good idea... + if (m_state == D3D9_VK_QUERY_BEGUN) + return S_FALSE; + + if (unlikely(!pData && dwSize)) + return D3DERR_INVALIDCALL; + + // The game forgot to even issue the query! + // Let's do it for them... + // This will issue both the begin, and the end. + if (m_state == D3D9_VK_QUERY_INITIAL) + this->Issue(D3DISSUE_END); + + if (m_resetCtr != 0u) + return S_FALSE; + + if (m_queryType == D3DQUERYTYPE_EVENT) { + DxvkGpuEventStatus status = m_event[0]->test(); + + if (status == DxvkGpuEventStatus::Invalid) + return D3DERR_INVALIDCALL; + + bool signaled = status == DxvkGpuEventStatus::Signaled; + + if (pData != nullptr) + *static_cast(pData) = signaled; + + if (signaled) { + m_state = D3D9_VK_QUERY_CACHED; + return D3D_OK; + } else { + return S_FALSE; + } + } + else { + std::array queryData = { }; + + for (uint32_t i = 0; i < MaxGpuQueries && m_query[i] != nullptr; i++) { + DxvkGpuQueryStatus status = m_query[i]->getData(queryData[i]); + + if (status == DxvkGpuQueryStatus::Invalid + || status == DxvkGpuQueryStatus::Failed) + return D3DERR_INVALIDCALL; + + if (status == DxvkGpuQueryStatus::Pending) + return S_FALSE; + } + + if (pData == nullptr) + return D3D_OK; + + + switch (m_queryType) { + case D3DQUERYTYPE_VCACHE: + // Don't know what the hell any of this means. + // Nor do I care. This just makes games work. + m_dataCache.VCache.Pattern = MAKEFOURCC('H', 'C', 'A', 'C'); + m_dataCache.VCache.OptMethod = 1; + m_dataCache.VCache.CacheSize = 24; + m_dataCache.VCache.MagicNumber = 20; + break; + + case D3DQUERYTYPE_OCCLUSION: + m_dataCache.Occlusion = DWORD(queryData[0].occlusion.samplesPassed); + break; + + case D3DQUERYTYPE_TIMESTAMP: + m_dataCache.Timestamp = queryData[0].timestamp.time; + break; + + case D3DQUERYTYPE_TIMESTAMPDISJOINT: + m_dataCache.TimestampDisjoint = queryData[0].timestamp.time < queryData[1].timestamp.time; + break; + + case D3DQUERYTYPE_TIMESTAMPFREQ: + m_dataCache.TimestampFreq = GetTimestampQueryFrequency(); + break; + + case D3DQUERYTYPE_VERTEXSTATS: + m_dataCache.VertexStats.NumRenderedTriangles = queryData[0].statistic.iaPrimitives; + m_dataCache.VertexStats.NumExtraClippingTriangles = queryData[0].statistic.clipPrimitives; + break; + + default: + break; + } + + if (likely(pData && dwSize)) + memcpy(pData, &m_dataCache, dwSize); + + m_state = D3D9_VK_QUERY_CACHED; + return D3D_OK; + } + } + + + UINT64 D3D9Query::GetTimestampQueryFrequency() const { + Rc device = m_parent->GetDXVKDevice(); + Rc adapter = device->adapter(); + + VkPhysicalDeviceLimits limits = adapter->deviceProperties().limits; + return uint64_t(1'000'000'000.0f / limits.timestampPeriod); + } + + + void D3D9Query::Begin(DxvkContext* ctx) { + switch (m_queryType) { + case D3DQUERYTYPE_OCCLUSION: + case D3DQUERYTYPE_VERTEXSTATS: + ctx->beginQuery(m_query[0]); + break; + + case D3DQUERYTYPE_TIMESTAMPDISJOINT: + ctx->writeTimestamp(m_query[1]); + break; + + default: break; + } + } + + + void D3D9Query::End(DxvkContext* ctx) { + switch (m_queryType) { + case D3DQUERYTYPE_TIMESTAMP: + case D3DQUERYTYPE_TIMESTAMPDISJOINT: + ctx->writeTimestamp(m_query[0]); + break; + + case D3DQUERYTYPE_VERTEXSTATS: + case D3DQUERYTYPE_OCCLUSION: + ctx->endQuery(m_query[0]); + break; + + case D3DQUERYTYPE_EVENT: + ctx->signalGpuEvent(m_event[0]); + break; + + default: break; + } + + m_resetCtr.fetch_sub(1, std::memory_order_release); + } + + + bool D3D9Query::QueryBeginnable(D3DQUERYTYPE QueryType) { + return QueryType == D3DQUERYTYPE_OCCLUSION + || QueryType == D3DQUERYTYPE_VERTEXSTATS + || QueryType == D3DQUERYTYPE_TIMESTAMPDISJOINT; + } + + + bool D3D9Query::QueryEndable(D3DQUERYTYPE QueryType) { + return QueryBeginnable(QueryType) + || QueryType == D3DQUERYTYPE_TIMESTAMP + || QueryType == D3DQUERYTYPE_EVENT; + } + + + HRESULT D3D9Query::QuerySupported(D3D9DeviceEx* pDevice, D3DQUERYTYPE QueryType) { + switch (QueryType) { + case D3DQUERYTYPE_VCACHE: + if (!pDevice->GetOptions()->supportVCache) + return D3DERR_NOTAVAILABLE; + + return D3D_OK; + case D3DQUERYTYPE_EVENT: + case D3DQUERYTYPE_OCCLUSION: + case D3DQUERYTYPE_TIMESTAMP: + case D3DQUERYTYPE_TIMESTAMPDISJOINT: + case D3DQUERYTYPE_TIMESTAMPFREQ: + case D3DQUERYTYPE_VERTEXSTATS: + return D3D_OK; + + default: + return D3DERR_NOTAVAILABLE; + } + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_query.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_query.h new file mode 100644 index 00000000000..8d742c96c49 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_query.h @@ -0,0 +1,91 @@ +#pragma once + +#include "d3d9_device_child.h" + +#include "../dxvk/dxvk_context.h" + +namespace dxvk { + + enum D3D9_VK_QUERY_STATE : uint32_t { + D3D9_VK_QUERY_INITIAL, + D3D9_VK_QUERY_BEGUN, + D3D9_VK_QUERY_ENDED, + D3D9_VK_QUERY_CACHED + }; + + union D3D9_QUERY_DATA { + D3DDEVINFO_VCACHE VCache; + DWORD Occlusion; + UINT64 Timestamp; + BOOL TimestampDisjoint; + UINT64 TimestampFreq; + D3DDEVINFO_D3DVERTEXSTATS VertexStats; + }; + + class D3D9Query : public D3D9DeviceChild { + constexpr static uint32_t MaxGpuQueries = 2; + constexpr static uint32_t MaxGpuEvents = 1; + public: + + D3D9Query( + D3D9DeviceEx* pDevice, + D3DQUERYTYPE QueryType); + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject); + + D3DQUERYTYPE STDMETHODCALLTYPE GetType() final; + + DWORD STDMETHODCALLTYPE GetDataSize() final; + + HRESULT STDMETHODCALLTYPE Issue(DWORD dwIssueFlags) final; + + HRESULT STDMETHODCALLTYPE GetData(void* pData, DWORD dwSize, DWORD dwGetDataFlags) final; + + HRESULT GetQueryData(void* pData, DWORD dwSize); + + void Begin(DxvkContext* ctx); + void End(DxvkContext* ctx); + + static bool QueryBeginnable(D3DQUERYTYPE QueryType); + static bool QueryEndable(D3DQUERYTYPE QueryType); + + static HRESULT QuerySupported(D3D9DeviceEx* pDevice, D3DQUERYTYPE QueryType); + + bool IsEvent() const { + return m_queryType == D3DQUERYTYPE_EVENT; + } + + bool IsStalling() const { + return m_stallFlag; + } + + void NotifyEnd() { + m_stallMask <<= 1; + } + + void NotifyStall() { + m_stallMask |= 1; + m_stallFlag |= bit::popcnt(m_stallMask) >= 16; + } + + private: + + D3DQUERYTYPE m_queryType; + + D3D9_VK_QUERY_STATE m_state; + + std::array, MaxGpuQueries> m_query; + std::array, MaxGpuEvents> m_event; + + uint32_t m_stallMask = 0; + bool m_stallFlag = false; + + std::atomic m_resetCtr = { 0u }; + + D3D9_QUERY_DATA m_dataCache; + + UINT64 GetTimestampQueryFrequency() const; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_resource.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_resource.h new file mode 100644 index 00000000000..5d343e2039e --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_resource.h @@ -0,0 +1,84 @@ +#pragma once + +#include "d3d9_device_child.h" + +#include "../util/com/com_private_data.h" + +namespace dxvk { + + template + class D3D9Resource : public D3D9DeviceChild { + + public: + + D3D9Resource(D3D9DeviceEx* pDevice) + : D3D9DeviceChild(pDevice) + , m_priority ( 0 ) { } + + HRESULT STDMETHODCALLTYPE SetPrivateData( + REFGUID refguid, + const void* pData, + DWORD SizeOfData, + DWORD Flags) final { + HRESULT hr; + if (Flags & D3DSPD_IUNKNOWN) { + IUnknown* unknown = + const_cast( + reinterpret_cast(pData)); + hr = m_privateData.setInterface( + refguid, unknown); + } + else + hr = m_privateData.setData( + refguid, SizeOfData, pData); + + if (FAILED(hr)) + return D3DERR_INVALIDCALL; + + return D3D_OK; + } + + HRESULT STDMETHODCALLTYPE GetPrivateData( + REFGUID refguid, + void* pData, + DWORD* pSizeOfData) final { + HRESULT hr = m_privateData.getData( + refguid, reinterpret_cast(pSizeOfData), pData); + + if (FAILED(hr)) + return D3DERR_INVALIDCALL; + + return D3D_OK; + } + + HRESULT STDMETHODCALLTYPE FreePrivateData(REFGUID refguid) final { + HRESULT hr = m_privateData.setData(refguid, 0, nullptr); + + if (FAILED(hr)) + return D3DERR_INVALIDCALL; + + return D3D_OK; + } + + DWORD STDMETHODCALLTYPE SetPriority(DWORD PriorityNew) { + DWORD oldPriority = m_priority; + m_priority = PriorityNew; + return oldPriority; + } + + DWORD STDMETHODCALLTYPE GetPriority() { + return m_priority; + } + + + protected: + + DWORD m_priority; + + private: + + ComPrivateData m_privateData; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_sampler.cpp b/utils/dxvk-1.10.3/src/d3d9/d3d9_sampler.cpp new file mode 100644 index 00000000000..6a68f220005 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_sampler.cpp @@ -0,0 +1,44 @@ +#include "d3d9_sampler.h" + +namespace dxvk { + + size_t D3D9SamplerKeyHash::operator () (const D3D9SamplerKey& key) const { + DxvkHashState state; + + std::hash dhash; + std::hash tahash; + std::hash tfhash; + std::hash fhash; + std::hash bhash; + + state.add(tahash(key.AddressU)); + state.add(tahash(key.AddressV)); + state.add(tahash(key.AddressW)); + state.add(tfhash(key.MagFilter)); + state.add(tfhash(key.MinFilter)); + state.add(tfhash(key.MipFilter)); + state.add(dhash (key.MaxAnisotropy)); + state.add(fhash (key.MipmapLodBias)); + state.add(dhash (key.MaxMipLevel)); + state.add(dhash (key.BorderColor)); + state.add(bhash (key.Depth)); + + return state; + } + + + bool D3D9SamplerKeyEq::operator () (const D3D9SamplerKey& a, const D3D9SamplerKey& b) const { + return a.AddressU == b.AddressU + && a.AddressV == b.AddressV + && a.AddressW == b.AddressW + && a.MagFilter == b.MagFilter + && a.MinFilter == b.MinFilter + && a.MipFilter == b.MipFilter + && a.MaxAnisotropy == b.MaxAnisotropy + && a.MipmapLodBias == b.MipmapLodBias + && a.MaxMipLevel == b.MaxMipLevel + && a.BorderColor == b.BorderColor + && a.Depth == b.Depth; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_sampler.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_sampler.h new file mode 100644 index 00000000000..44471094e81 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_sampler.h @@ -0,0 +1,75 @@ +#pragma once + +#include "d3d9_include.h" + +#include "d3d9_util.h" + +#include "../dxvk/dxvk_hash.h" + +#include "../util/util_math.h" + +namespace dxvk { + + struct D3D9SamplerKey { + D3DTEXTUREADDRESS AddressU; + D3DTEXTUREADDRESS AddressV; + D3DTEXTUREADDRESS AddressW; + D3DTEXTUREFILTERTYPE MagFilter; + D3DTEXTUREFILTERTYPE MinFilter; + D3DTEXTUREFILTERTYPE MipFilter; + DWORD MaxAnisotropy; + float MipmapLodBias; + DWORD MaxMipLevel; + D3DCOLOR BorderColor; + bool Depth; + }; + + struct D3D9SamplerKeyHash { + size_t operator () (const D3D9SamplerKey& key) const; + }; + + struct D3D9SamplerKeyEq { + bool operator () (const D3D9SamplerKey& a, const D3D9SamplerKey& b) const; + }; + + inline void NormalizeSamplerKey(D3D9SamplerKey& key) { + key.AddressU = std::clamp(key.AddressU, D3DTADDRESS_WRAP, D3DTADDRESS_MIRRORONCE); + key.AddressV = std::clamp(key.AddressV, D3DTADDRESS_WRAP, D3DTADDRESS_MIRRORONCE); + key.AddressW = std::clamp(key.AddressW, D3DTADDRESS_WRAP, D3DTADDRESS_MIRRORONCE); + + bool hasAnisotropy = IsAnisotropic(key.MagFilter) || IsAnisotropic(key.MinFilter); + + key.MagFilter = std::clamp(key.MagFilter, D3DTEXF_NONE, D3DTEXF_LINEAR); + key.MinFilter = std::clamp(key.MinFilter, D3DTEXF_NONE, D3DTEXF_LINEAR); + key.MipFilter = std::clamp(key.MipFilter, D3DTEXF_NONE, D3DTEXF_LINEAR); + + key.MaxAnisotropy = hasAnisotropy + ? std::clamp(key.MaxAnisotropy, 1, 16) + : 1; + + if (key.MipFilter == D3DTEXF_NONE) { + // May as well try and keep slots down. + key.MipmapLodBias = 0; + } + else { + // Games also pass NAN here, this accounts for that. + if (unlikely(key.MipmapLodBias != key.MipmapLodBias)) + key.MipmapLodBias = 0.0f; + + // Clamp between -15.0f and 15.0f, matching mip limits of d3d9. + key.MipmapLodBias = std::clamp(key.MipmapLodBias, -15.0f, 15.0f); + + // Round to the nearest .5 + // Fixes sampler leaks in UE3 games w/ mip streaming + // eg. Borderlands 2 + key.MipmapLodBias = std::round(key.MipmapLodBias * 2.0f) / 2.0f; + } + + if (key.AddressU != D3DTADDRESS_BORDER + && key.AddressV != D3DTADDRESS_BORDER + && key.AddressW != D3DTADDRESS_BORDER) { + key.BorderColor = 0; + } + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_shader.cpp b/utils/dxvk-1.10.3/src/d3d9/d3d9_shader.cpp new file mode 100644 index 00000000000..8b5bb8bd6aa --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_shader.cpp @@ -0,0 +1,151 @@ +#include "d3d9_shader.h" + +#include "d3d9_caps.h" +#include "d3d9_device.h" +#include "d3d9_util.h" + +namespace dxvk { + + D3D9CommonShader::D3D9CommonShader() {} + + D3D9CommonShader::D3D9CommonShader( + D3D9DeviceEx* pDevice, + VkShaderStageFlagBits ShaderStage, + const DxvkShaderKey& Key, + const DxsoModuleInfo* pDxsoModuleInfo, + const void* pShaderBytecode, + const DxsoAnalysisInfo& AnalysisInfo, + DxsoModule* pModule) { + const uint32_t bytecodeLength = AnalysisInfo.bytecodeByteLength; + m_bytecode.resize(bytecodeLength); + std::memcpy(m_bytecode.data(), pShaderBytecode, bytecodeLength); + + const std::string name = Key.toString(); + Logger::debug(str::format("Compiling shader ", name)); + + // If requested by the user, dump both the raw DXBC + // shader and the compiled SPIR-V module to a file. + const std::string dumpPath = env::getEnvVar("DXVK_SHADER_DUMP_PATH"); + + if (dumpPath.size() != 0) { + DxsoReader reader( + reinterpret_cast(pShaderBytecode)); + + reader.store(std::ofstream(str::tows(str::format(dumpPath, "/", name, ".dxso").c_str()).c_str(), + std::ios_base::binary | std::ios_base::trunc), bytecodeLength); + + char comment[2048]; + Com blob; + HRESULT hr = DisassembleShader( + pShaderBytecode, + TRUE, + comment, + &blob); + + if (SUCCEEDED(hr)) { + std::ofstream disassembledOut(str::tows(str::format(dumpPath, "/", name, ".dxso.dis").c_str()).c_str(), std::ios_base::binary | std::ios_base::trunc); + disassembledOut.write( + reinterpret_cast(blob->GetBufferPointer()), + blob->GetBufferSize()); + } + } + + // Decide whether we need to create a pass-through + // geometry shader for vertex shader stream output + + const D3D9ConstantLayout& constantLayout = ShaderStage == VK_SHADER_STAGE_VERTEX_BIT + ? pDevice->GetVertexConstantLayout() + : pDevice->GetPixelConstantLayout(); + m_shaders = pModule->compile(*pDxsoModuleInfo, name, AnalysisInfo, constantLayout); + m_isgn = pModule->isgn(); + m_usedSamplers = pModule->usedSamplers(); + + // Shift up these sampler bits so we can just + // do an or per-draw in the device. + // We shift by 17 because 16 ps samplers + 1 dmap (tess) + if (ShaderStage == VK_SHADER_STAGE_VERTEX_BIT) + m_usedSamplers <<= caps::MaxTexturesPS + 1; + + m_usedRTs = pModule->usedRTs(); + + m_info = pModule->info(); + m_meta = pModule->meta(); + m_constants = pModule->constants(); + m_maxDefinedConst = pModule->maxDefinedConstant(); + + m_shaders[0]->setShaderKey(Key); + + if (m_shaders[1] != nullptr) { + // Lets lie about the shader key type for the state cache. + m_shaders[1]->setShaderKey({ VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, Key.sha1() }); + } + + if (dumpPath.size() != 0) { + std::ofstream dumpStream( + str::tows(str::format(dumpPath, "/", name, ".spv").c_str()).c_str(), + std::ios_base::binary | std::ios_base::trunc); + + m_shaders[0]->dump(dumpStream); + } + + pDevice->GetDXVKDevice()->registerShader(m_shaders[0]); + + if (m_shaders[1] != nullptr) + pDevice->GetDXVKDevice()->registerShader(m_shaders[1]); + } + + + void D3D9ShaderModuleSet::GetShaderModule( + D3D9DeviceEx* pDevice, + D3D9CommonShader* pShaderModule, + VkShaderStageFlagBits ShaderStage, + const DxsoModuleInfo* pDxbcModuleInfo, + const void* pShaderBytecode) { + DxsoReader reader( + reinterpret_cast(pShaderBytecode)); + + DxsoModule module(reader); + + if (module.info().majorVersion() > pDxbcModuleInfo->options.shaderModel) + throw DxvkError("GetShaderModule: Out of range of supported shader model"); + + if (module.info().shaderStage() != ShaderStage) + throw DxvkError("GetShaderModule: Bytecode does not match shader stage"); + + DxsoAnalysisInfo info = module.analyze(); + + DxvkShaderKey lookupKey = DxvkShaderKey( + ShaderStage, + Sha1Hash::compute(pShaderBytecode, info.bytecodeByteLength)); + + // Use the shader's unique key for the lookup + { std::unique_lock lock(m_mutex); + + auto entry = m_modules.find(lookupKey); + if (entry != m_modules.end()) { + *pShaderModule = entry->second; + return; + } + } + + // This shader has not been compiled yet, so we have to create a + // new module. This takes a while, so we won't lock the structure. + *pShaderModule = D3D9CommonShader( + pDevice, ShaderStage, lookupKey, + pDxbcModuleInfo, pShaderBytecode, + info, &module); + + // Insert the new module into the lookup table. If another thread + // has compiled the same shader in the meantime, we should return + // that object instead and discard the newly created module. + { std::unique_lock lock(m_mutex); + + auto status = m_modules.insert({ lookupKey, *pShaderModule }); + if (!status.second) { + *pShaderModule = status.first->second; + return; + } + } + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_shader.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_shader.h new file mode 100644 index 00000000000..d896f019c17 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_shader.h @@ -0,0 +1,199 @@ +#pragma once + +#include "d3d9_resource.h" +#include "../dxso/dxso_module.h" +#include "d3d9_shader_permutations.h" +#include "d3d9_util.h" + +#include + +namespace dxvk { + + + /** + * \brief Common shader object + * + * Stores the compiled SPIR-V shader and the SHA-1 + * hash of the original DXBC shader, which can be + * used to identify the shader. + */ + class D3D9CommonShader { + + public: + + D3D9CommonShader(); + + D3D9CommonShader( + D3D9DeviceEx* pDevice, + VkShaderStageFlagBits ShaderStage, + const DxvkShaderKey& Key, + const DxsoModuleInfo* pDxbcModuleInfo, + const void* pShaderBytecode, + const DxsoAnalysisInfo& AnalysisInfo, + DxsoModule* pModule); + + + Rc GetShader(D3D9ShaderPermutation Permutation) const { + return m_shaders[Permutation]; + } + + std::string GetName() const { + return m_shaders[D3D9ShaderPermutations::None]->debugName(); + } + + const std::vector& GetBytecode() const { + return m_bytecode; + } + + const DxsoIsgn& GetIsgn() const { + return m_isgn; + } + + const DxsoShaderMetaInfo& GetMeta() const { return m_meta; } + const DxsoDefinedConstants& GetConstants() const { return m_constants; } + + D3D9ShaderMasks GetShaderMask() const { return D3D9ShaderMasks{ m_usedSamplers, m_usedRTs }; } + + const DxsoProgramInfo& GetInfo() const { return m_info; } + + uint32_t GetMaxDefinedConstant() const { return m_maxDefinedConst; } + + private: + + DxsoIsgn m_isgn; + uint32_t m_usedSamplers; + uint32_t m_usedRTs; + + DxsoProgramInfo m_info; + DxsoShaderMetaInfo m_meta; + DxsoDefinedConstants m_constants; + uint32_t m_maxDefinedConst; + + DxsoPermutations m_shaders; + + std::vector m_bytecode; + + }; + + /** + * \brief Common shader interface + * + * Implements methods for all D3D11*Shader + * interfaces and stores the actual shader + * module object. + */ + template + class D3D9Shader : public D3D9DeviceChild { + + public: + + D3D9Shader( + D3D9DeviceEx* pDevice, + const D3D9CommonShader& CommonShader) + : D3D9DeviceChild( pDevice ) + , m_shader ( CommonShader ) { } + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(Base)) { + *ppvObject = ref(this); + return S_OK; + } + + Logger::warn("D3D9Shader::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + HRESULT STDMETHODCALLTYPE GetFunction(void* pOut, UINT* pSizeOfData) { + if (pSizeOfData == nullptr) + return D3DERR_INVALIDCALL; + + const auto& bytecode = m_shader.GetBytecode(); + + if (pOut == nullptr) { + *pSizeOfData = bytecode.size(); + return D3D_OK; + } + + size_t copyAmount = std::min(size_t(*pSizeOfData), bytecode.size()); + std::memcpy(pOut, bytecode.data(), copyAmount); + + return D3D_OK; + } + + const D3D9CommonShader* GetCommonShader() const { + return &m_shader; + } + + private: + + D3D9CommonShader m_shader; + + }; + + // Needs their own classes and not usings for forward decl. + + class D3D9VertexShader final : public D3D9Shader { + + public: + + D3D9VertexShader( + D3D9DeviceEx* pDevice, + const D3D9CommonShader& CommonShader) + : D3D9Shader( pDevice, CommonShader ) { } + + }; + + class D3D9PixelShader final : public D3D9Shader { + + public: + + D3D9PixelShader( + D3D9DeviceEx* pDevice, + const D3D9CommonShader& CommonShader) + : D3D9Shader( pDevice, CommonShader ) { } + + }; + + /** + * \brief Shader module set + * + * Some applications may compile the same shader multiple + * times, so we should cache the resulting shader modules + * and reuse them rather than creating new ones. This + * class is thread-safe. + */ + class D3D9ShaderModuleSet : public RcObject { + + public: + + void GetShaderModule( + D3D9DeviceEx* pDevice, + D3D9CommonShader* pShaderModule, + VkShaderStageFlagBits ShaderStage, + const DxsoModuleInfo* pDxbcModuleInfo, + const void* pShaderBytecode); + + private: + + dxvk::mutex m_mutex; + + std::unordered_map< + DxvkShaderKey, + D3D9CommonShader, + DxvkHash, DxvkEq> m_modules; + + }; + + template + const D3D9CommonShader* GetCommonShader(const T& pShader) { + return pShader != nullptr ? pShader->GetCommonShader() : nullptr; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_shader_permutations.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_shader_permutations.h new file mode 100644 index 00000000000..cf2301d2956 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_shader_permutations.h @@ -0,0 +1,20 @@ +#pragma once + +#include "d3d9_include.h" + +namespace dxvk { + + class DxvkShader; + + namespace D3D9ShaderPermutations { + enum D3D9ShaderPermutation { + None, + FlatShade, + Count + }; + } + using D3D9ShaderPermutation = D3D9ShaderPermutations::D3D9ShaderPermutation; + + using DxsoPermutations = std::array, D3D9ShaderPermutations::Count>; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_shader_validator.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_shader_validator.h new file mode 100644 index 00000000000..8e433027c60 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_shader_validator.h @@ -0,0 +1,68 @@ +#pragma once + +#include "d3d9_include.h" + +namespace dxvk { + + class IDirect3DShaderValidator9 : public IUnknown { + + public: + + virtual HRESULT STDMETHODCALLTYPE Begin( + void* pCallback, + void* pUserParam, + DWORD Unknown) = 0; + + virtual HRESULT STDMETHODCALLTYPE Instruction( + const char* pUnknown1, + UINT Unknown2, + const DWORD* pInstruction, + DWORD InstructionLength) = 0; + + virtual HRESULT STDMETHODCALLTYPE End() = 0; + + }; + + class D3D9ShaderValidator final : public ComObjectClamp { + + public: + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = ref(this); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE Begin( + void* pCallback, + void* pUserParam, + DWORD Unknown) { + Logger::debug("D3D9ShaderValidator::Begin: Stub"); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE Instruction( + const char* pUnknown1, + UINT Unknown2, + const DWORD* pInstruction, + DWORD InstructionLength) { + Logger::debug("D3D9ShaderValidator::Instruction: Stub"); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE End() { + Logger::debug("D3D9ShaderValidator::End: Stub"); + + return D3D_OK; + } + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_spec_constants.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_spec_constants.h new file mode 100644 index 00000000000..7a8a33d5e6a --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_spec_constants.h @@ -0,0 +1,24 @@ +#pragma once + +#include + +namespace dxvk { + + enum D3D9SpecConstantId : uint32_t { + AlphaCompareOp = 0, + SamplerType = 1, + FogEnabled = 2, + VertexFogMode = 3, + PixelFogMode = 4, + + PointMode = 5, + ProjectionType = 6, + + VertexShaderBools = 7, + PixelShaderBools = 8, + Fetch4 = 9, + + SamplerDepthMode = 10, + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_state.cpp b/utils/dxvk-1.10.3/src/d3d9/d3d9_state.cpp new file mode 100644 index 00000000000..2c32bef45d9 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_state.cpp @@ -0,0 +1,20 @@ +#include "d3d9_state.h" + +#include "d3d9_texture.h" + +namespace dxvk { + + D3D9CapturableState::D3D9CapturableState() { + for (uint32_t i = 0; i < streamFreq.size(); i++) + streamFreq[i] = 1; + + for (uint32_t i = 0; i < enabledLightIndices.size(); i++) + enabledLightIndices[i] = UINT32_MAX; + } + + D3D9CapturableState::~D3D9CapturableState() { + for (uint32_t i = 0; i < textures.size(); i++) + TextureChangePrivate(textures[i], nullptr); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_state.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_state.h new file mode 100644 index 00000000000..d87b8f53109 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_state.h @@ -0,0 +1,300 @@ +#pragma once + +#include "d3d9_caps.h" +#include "d3d9_constant_set.h" +#include "../dxso/dxso_common.h" +#include "../util/util_matrix.h" + +#include "d3d9_surface.h" +#include "d3d9_shader.h" +#include "d3d9_vertex_declaration.h" +#include "d3d9_buffer.h" + +#include +#include +#include + +namespace dxvk { + + static constexpr uint32_t RenderStateCount = 256; + static constexpr uint32_t SamplerStateCount = D3DSAMP_DMAPOFFSET + 1; + static constexpr uint32_t SamplerCount = caps::MaxTexturesPS + caps::MaxTexturesVS + 1; + static constexpr uint32_t TextureStageStateCount = DXVK_TSS_COUNT; + + namespace hacks::PointSize { + static constexpr DWORD AlphaToCoverageDisabled = MAKEFOURCC('A', '2', 'M', '0'); + static constexpr DWORD AlphaToCoverageEnabled = MAKEFOURCC('A', '2', 'M', '1'); + } + + struct D3D9ClipPlane { + float coeff[4] = {}; + }; + + struct D3D9RenderStateInfo { + std::array fogColor = { }; + float fogScale = 0.0f; + float fogEnd = 1.0f; + float fogDensity = 1.0f; + + float alphaRef = 0.0f; + + float pointSize = 1.0f; + float pointSizeMin = 1.0f; + float pointSizeMax = 64.0f; + float pointScaleA = 1.0f; + float pointScaleB = 0.0f; + float pointScaleC = 0.0f; + }; + + enum class D3D9RenderStateItem { + FogColor = 0, + FogScale = 1, + FogEnd, + FogDensity, + AlphaRef, + + PointSize, + PointSizeMin, + PointSizeMax, + PointScaleA, + PointScaleB, + PointScaleC, + + Count + }; + + + // This is needed in fixed function for POSITION_T support. + // These are constants we need to * and add to move + // Window Coords -> Real Coords w/ respect to the viewport. + struct D3D9ViewportInfo { + Vector4 inverseOffset; + Vector4 inverseExtent; + }; + + struct D3D9Light { + D3D9Light(const D3DLIGHT9& light, Matrix4 viewMtx) { + Diffuse = Vector4(light.Diffuse.r, light.Diffuse.g, light.Diffuse.b, light.Diffuse.a); + Specular = Vector4(light.Specular.r, light.Specular.g, light.Specular.b, light.Specular.a); + Ambient = Vector4(light.Ambient.r, light.Ambient.g, light.Ambient.b, light.Ambient.a); + + Position = viewMtx * Vector4(light.Position.x, light.Position.y, light.Position.z, 1.0f); + Direction = Vector4(light.Direction.x, light.Direction.y, light.Direction.z, 0.0f); + Direction = normalize(viewMtx * Direction); + + Type = light.Type; + Range = light.Range; + Falloff = light.Falloff; + Attenuation0 = light.Attenuation0; + Attenuation1 = light.Attenuation1; + Attenuation2 = light.Attenuation2; + Theta = cosf(light.Theta / 2.0f); + Phi = cosf(light.Phi / 2.0f); + } + + Vector4 Diffuse; + Vector4 Specular; + Vector4 Ambient; + + Vector4 Position; + Vector4 Direction; + + D3DLIGHTTYPE Type; + float Range; + float Falloff; + float Attenuation0; + float Attenuation1; + float Attenuation2; + float Theta; + float Phi; + }; + + + struct D3D9FixedFunctionVS { + Matrix4 WorldView; + Matrix4 NormalMatrix; + Matrix4 InverseView; + Matrix4 Projection; + + std::array TexcoordMatrices; + + D3D9ViewportInfo ViewportInfo; + + Vector4 GlobalAmbient; + std::array Lights; + D3DMATERIAL9 Material; + float TweenFactor; + }; + + + struct D3D9FixedFunctionVertexBlendDataHW { + Matrix4 WorldView[8]; + }; + + + struct D3D9FixedFunctionVertexBlendDataSW { + Matrix4 WorldView[256]; + }; + + + struct D3D9FixedFunctionPS { + Vector4 textureFactor; + }; + + enum D3D9SharedPSStages { + D3D9SharedPSStages_Constant, + D3D9SharedPSStages_BumpEnvMat0, + D3D9SharedPSStages_BumpEnvMat1, + D3D9SharedPSStages_BumpEnvLScale, + D3D9SharedPSStages_BumpEnvLOffset, + D3D9SharedPSStages_Count, + }; + + struct D3D9SharedPS { + struct Stage { + float Constant[4]; + float BumpEnvMat[2][2]; + float BumpEnvLScale; + float BumpEnvLOffset; + float Padding[2]; + } Stages[8]; + }; + + struct D3D9VBO { + Com vertexBuffer; + + UINT offset = 0; + UINT stride = 0; + }; + + constexpr D3DLIGHT9 DefaultLight = { + D3DLIGHT_DIRECTIONAL, // Type + {1.0f, 1.0f, 1.0f, 1.0f}, // Diffuse + {0.0f, 0.0f, 0.0f, 0.0f}, // Specular + {0.0f, 0.0f, 0.0f, 0.0f}, // Ambient + {0.0f, 0.0f, 0.0f}, // Position + {0.0f, 0.0f, 0.0f}, // Direction + 0.0f, // Range + 0.0f, // Falloff + 0.0f, 0.0f, 0.0f, // Attenuations [constant, linear, quadratic] + 0.0f, // Theta + 0.0f // Phi + }; + + struct D3D9CapturableState { + D3D9CapturableState(); + + ~D3D9CapturableState(); + + Com vertexDecl; + Com indices; + + std::array renderStates = {}; + + std::array< + std::array, + SamplerCount> samplerStates = {}; + + std::array vertexBuffers = {}; + + std::array< + IDirect3DBaseTexture9*, + SamplerCount> textures = {}; + + Com vertexShader; + Com pixelShader; + + D3DVIEWPORT9 viewport = {}; + RECT scissorRect = {}; + + std::array< + D3D9ClipPlane, + caps::MaxClipPlanes> clipPlanes = {}; + + std::array< + std::array, + caps::TextureStageCount> textureStages = {}; + + D3D9ShaderConstantsVSSoftware vsConsts; + D3D9ShaderConstantsPS psConsts; + + std::array streamFreq = {}; + + std::array transforms = {}; + + D3DMATERIAL9 material = {}; + + std::vector> lights; + std::array enabledLightIndices; + + bool IsLightEnabled(DWORD Index) { + const auto& indices = enabledLightIndices; + return std::find(indices.begin(), indices.end(), Index) != indices.end(); + } + }; + + template < + DxsoProgramType ProgramType, + D3D9ConstantType ConstantType, + typename T> + HRESULT UpdateStateConstants( + D3D9CapturableState* pState, + UINT StartRegister, + const T* pConstantData, + UINT Count, + bool FloatEmu) { + auto UpdateHelper = [&] (auto& set) { + if constexpr (ConstantType == D3D9ConstantType::Float) { + + if (!FloatEmu) { + size_t size = Count * sizeof(Vector4); + + std::memcpy(set.fConsts[StartRegister].data, pConstantData, size); + } + else { + for (UINT i = 0; i < Count; i++) + set.fConsts[StartRegister + i] = replaceNaN(pConstantData + (i * 4)); + } + } + else if constexpr (ConstantType == D3D9ConstantType::Int) { + size_t size = Count * sizeof(Vector4i); + + std::memcpy(set.iConsts[StartRegister].data, pConstantData, size); + } + else { + for (uint32_t i = 0; i < Count; i++) { + const uint32_t constantIdx = StartRegister + i; + const uint32_t arrayIdx = constantIdx / 32; + const uint32_t bitIdx = constantIdx % 32; + + const uint32_t bit = 1u << bitIdx; + + set.bConsts[arrayIdx] &= ~bit; + if (pConstantData[i]) + set.bConsts[arrayIdx] |= bit; + } + } + + return D3D_OK; + }; + + return ProgramType == DxsoProgramTypes::VertexShader + ? UpdateHelper(pState->vsConsts) + : UpdateHelper(pState->psConsts); + } + + struct Direct3DState9 : public D3D9CapturableState { + + std::array, caps::MaxSimultaneousRenderTargets> renderTargets; + Com depthStencil; + + }; + + + struct D3D9InputAssemblyState { + D3DPRIMITIVETYPE primitiveType = D3DPRIMITIVETYPE(0); + uint32_t streamsInstanced = 0; + uint32_t streamsUsed = 0; + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_stateblock.cpp b/utils/dxvk-1.10.3/src/d3d9/d3d9_stateblock.cpp new file mode 100644 index 00000000000..9ad2a590d5b --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_stateblock.cpp @@ -0,0 +1,532 @@ +#include "d3d9_stateblock.h" + +#include "d3d9_caps.h" +#include "d3d9_device.h" +#include "d3d9_vertex_declaration.h" +#include "d3d9_buffer.h" +#include "d3d9_shader.h" +#include "d3d9_texture.h" + +#include "d3d9_util.h" + +namespace dxvk { + + D3D9StateBlock::D3D9StateBlock(D3D9DeviceEx* pDevice, D3D9StateBlockType Type) + : D3D9StateBlockBase(pDevice) + , m_deviceState (pDevice->GetRawState()) { + CaptureType(Type); + } + + + HRESULT STDMETHODCALLTYPE D3D9StateBlock::QueryInterface( + REFIID riid, + void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(IDirect3DStateBlock9)) { + *ppvObject = ref(this); + return S_OK; + } + + Logger::warn("D3D9StateBlock::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + HRESULT STDMETHODCALLTYPE D3D9StateBlock::Capture() { + if (m_captures.flags.test(D3D9CapturedStateFlag::VertexDecl)) + SetVertexDeclaration(m_deviceState->vertexDecl.ptr()); + + ApplyOrCapture(); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9StateBlock::Apply() { + m_applying = true; + + if (m_captures.flags.test(D3D9CapturedStateFlag::VertexDecl) && m_state.vertexDecl != nullptr) + m_parent->SetVertexDeclaration(m_state.vertexDecl.ptr()); + + ApplyOrCapture(); + m_applying = false; + + return D3D_OK; + } + + + HRESULT D3D9StateBlock::SetVertexDeclaration(D3D9VertexDecl* pDecl) { + m_state.vertexDecl = pDecl; + + m_captures.flags.set(D3D9CapturedStateFlag::VertexDecl); + return D3D_OK; + } + + + HRESULT D3D9StateBlock::SetIndices(D3D9IndexBuffer* pIndexData) { + m_state.indices = pIndexData; + + m_captures.flags.set(D3D9CapturedStateFlag::Indices); + return D3D_OK; + } + + + HRESULT D3D9StateBlock::SetRenderState(D3DRENDERSTATETYPE State, DWORD Value) { + m_state.renderStates[State] = Value; + + m_captures.flags.set(D3D9CapturedStateFlag::RenderStates); + m_captures.renderStates.set(State, true); + return D3D_OK; + } + + + HRESULT D3D9StateBlock::SetStateSamplerState( + DWORD StateSampler, + D3DSAMPLERSTATETYPE Type, + DWORD Value) { + m_state.samplerStates[StateSampler][Type] = Value; + + m_captures.flags.set(D3D9CapturedStateFlag::SamplerStates); + m_captures.samplers.set(StateSampler, true); + m_captures.samplerStates[StateSampler].set(Type, true); + return D3D_OK; + } + + + HRESULT D3D9StateBlock::SetStreamSource( + UINT StreamNumber, + D3D9VertexBuffer* pStreamData, + UINT OffsetInBytes, + UINT Stride) { + m_state.vertexBuffers[StreamNumber].vertexBuffer = pStreamData; + + m_state.vertexBuffers[StreamNumber].offset = OffsetInBytes; + m_state.vertexBuffers[StreamNumber].stride = Stride; + + m_captures.flags.set(D3D9CapturedStateFlag::VertexBuffers); + m_captures.vertexBuffers.set(StreamNumber, true); + return D3D_OK; + } + + + HRESULT D3D9StateBlock::SetStreamSourceFreq(UINT StreamNumber, UINT Setting) { + m_state.streamFreq[StreamNumber] = Setting; + + m_captures.flags.set(D3D9CapturedStateFlag::StreamFreq); + m_captures.streamFreq.set(StreamNumber, true); + return D3D_OK; + } + + + HRESULT D3D9StateBlock::SetStateTexture(DWORD StateSampler, IDirect3DBaseTexture9* pTexture) { + TextureChangePrivate(m_state.textures[StateSampler], pTexture); + + m_captures.flags.set(D3D9CapturedStateFlag::Textures); + m_captures.textures.set(StateSampler, true); + return D3D_OK; + } + + + HRESULT D3D9StateBlock::SetVertexShader(D3D9VertexShader* pShader) { + m_state.vertexShader = pShader; + + m_captures.flags.set(D3D9CapturedStateFlag::VertexShader); + return D3D_OK; + } + + + HRESULT D3D9StateBlock::SetPixelShader(D3D9PixelShader* pShader) { + m_state.pixelShader = pShader; + + m_captures.flags.set(D3D9CapturedStateFlag::PixelShader); + return D3D_OK; + } + + + HRESULT D3D9StateBlock::SetMaterial(const D3DMATERIAL9* pMaterial) { + m_state.material = *pMaterial; + + m_captures.flags.set(D3D9CapturedStateFlag::Material); + return D3D_OK; + } + + + HRESULT D3D9StateBlock::SetStateTransform(uint32_t idx, const D3DMATRIX* pMatrix) { + m_state.transforms[idx] = ConvertMatrix(pMatrix); + + m_captures.flags.set(D3D9CapturedStateFlag::Transforms); + m_captures.transforms.set(idx, true); + return D3D_OK; + } + + + HRESULT D3D9StateBlock::SetStateTextureStageState( + DWORD Stage, + D3D9TextureStageStateTypes Type, + DWORD Value) { + m_state.textureStages[Stage][Type] = Value; + + m_captures.flags.set(D3D9CapturedStateFlag::TextureStages); + m_captures.textureStages.set(Stage, true); + m_captures.textureStageStates[Stage].set(Type, true); + return D3D_OK; + } + + + HRESULT D3D9StateBlock::MultiplyStateTransform(uint32_t idx, const D3DMATRIX* pMatrix) { + m_state.transforms[idx] = m_state.transforms[idx] * ConvertMatrix(pMatrix); + + m_captures.flags.set(D3D9CapturedStateFlag::Transforms); + m_captures.transforms.set(idx, true); + return D3D_OK; + } + + + HRESULT D3D9StateBlock::SetViewport(const D3DVIEWPORT9* pViewport) { + m_state.viewport = *pViewport; + + m_captures.flags.set(D3D9CapturedStateFlag::Viewport); + return D3D_OK; + } + + + HRESULT D3D9StateBlock::SetScissorRect(const RECT* pRect) { + m_state.scissorRect = *pRect; + + m_captures.flags.set(D3D9CapturedStateFlag::ScissorRect); + return D3D_OK; + } + + + HRESULT D3D9StateBlock::SetClipPlane(DWORD Index, const float* pPlane) { + for (uint32_t i = 0; i < 4; i++) + m_state.clipPlanes[Index].coeff[i] = pPlane[i]; + + m_captures.flags.set(D3D9CapturedStateFlag::ClipPlanes); + m_captures.clipPlanes.set(Index, true); + return D3D_OK; + } + + + HRESULT D3D9StateBlock::SetVertexShaderConstantF( + UINT StartRegister, + const float* pConstantData, + UINT Vector4fCount) { + return SetShaderConstants< + DxsoProgramTypes::VertexShader, + D3D9ConstantType::Float>( + StartRegister, + pConstantData, + Vector4fCount); + } + + + HRESULT D3D9StateBlock::SetVertexShaderConstantI( + UINT StartRegister, + const int* pConstantData, + UINT Vector4iCount) { + return SetShaderConstants< + DxsoProgramTypes::VertexShader, + D3D9ConstantType::Int>( + StartRegister, + pConstantData, + Vector4iCount); + } + + + HRESULT D3D9StateBlock::SetVertexShaderConstantB( + UINT StartRegister, + const BOOL* pConstantData, + UINT BoolCount) { + return SetShaderConstants< + DxsoProgramTypes::VertexShader, + D3D9ConstantType::Bool>( + StartRegister, + pConstantData, + BoolCount); + } + + + HRESULT D3D9StateBlock::SetPixelShaderConstantF( + UINT StartRegister, + const float* pConstantData, + UINT Vector4fCount) { + return SetShaderConstants< + DxsoProgramTypes::PixelShader, + D3D9ConstantType::Float>( + StartRegister, + pConstantData, + Vector4fCount); + } + + + HRESULT D3D9StateBlock::SetPixelShaderConstantI( + UINT StartRegister, + const int* pConstantData, + UINT Vector4iCount) { + return SetShaderConstants< + DxsoProgramTypes::PixelShader, + D3D9ConstantType::Int>( + StartRegister, + pConstantData, + Vector4iCount); + } + + + HRESULT D3D9StateBlock::SetPixelShaderConstantB( + UINT StartRegister, + const BOOL* pConstantData, + UINT BoolCount) { + return SetShaderConstants< + DxsoProgramTypes::PixelShader, + D3D9ConstantType::Bool>( + StartRegister, + pConstantData, + BoolCount); + } + + + HRESULT D3D9StateBlock::SetVertexBoolBitfield(uint32_t idx, uint32_t mask, uint32_t bits) { + m_state.vsConsts.bConsts[idx] &= ~mask; + m_state.vsConsts.bConsts[idx] |= bits & mask; + return D3D_OK; + } + + + HRESULT D3D9StateBlock::SetPixelBoolBitfield(uint32_t idx, uint32_t mask, uint32_t bits) { + m_state.psConsts.bConsts[idx] &= ~mask; + m_state.psConsts.bConsts[idx] |= bits & mask; + return D3D_OK; + } + + + void D3D9StateBlock::CapturePixelRenderStates() { + m_captures.flags.set(D3D9CapturedStateFlag::RenderStates); + + m_captures.renderStates.set(D3DRS_ZENABLE, true); + m_captures.renderStates.set(D3DRS_FILLMODE, true); + m_captures.renderStates.set(D3DRS_SHADEMODE, true); + m_captures.renderStates.set(D3DRS_ZWRITEENABLE, true); + m_captures.renderStates.set(D3DRS_ALPHATESTENABLE, true); + m_captures.renderStates.set(D3DRS_LASTPIXEL, true); + m_captures.renderStates.set(D3DRS_SRCBLEND, true); + m_captures.renderStates.set(D3DRS_DESTBLEND, true); + m_captures.renderStates.set(D3DRS_ZFUNC, true); + m_captures.renderStates.set(D3DRS_ALPHAREF, true); + m_captures.renderStates.set(D3DRS_ALPHAFUNC, true); + m_captures.renderStates.set(D3DRS_DITHERENABLE, true); + m_captures.renderStates.set(D3DRS_FOGSTART, true); + m_captures.renderStates.set(D3DRS_FOGEND, true); + m_captures.renderStates.set(D3DRS_FOGDENSITY, true); + m_captures.renderStates.set(D3DRS_ALPHABLENDENABLE, true); + m_captures.renderStates.set(D3DRS_DEPTHBIAS, true); + m_captures.renderStates.set(D3DRS_STENCILENABLE, true); + m_captures.renderStates.set(D3DRS_STENCILFAIL, true); + m_captures.renderStates.set(D3DRS_STENCILZFAIL, true); + m_captures.renderStates.set(D3DRS_STENCILPASS, true); + m_captures.renderStates.set(D3DRS_STENCILFUNC, true); + m_captures.renderStates.set(D3DRS_STENCILREF, true); + m_captures.renderStates.set(D3DRS_STENCILMASK, true); + m_captures.renderStates.set(D3DRS_STENCILWRITEMASK, true); + m_captures.renderStates.set(D3DRS_TEXTUREFACTOR, true); + m_captures.renderStates.set(D3DRS_WRAP0, true); + m_captures.renderStates.set(D3DRS_WRAP1, true); + m_captures.renderStates.set(D3DRS_WRAP2, true); + m_captures.renderStates.set(D3DRS_WRAP3, true); + m_captures.renderStates.set(D3DRS_WRAP4, true); + m_captures.renderStates.set(D3DRS_WRAP5, true); + m_captures.renderStates.set(D3DRS_WRAP6, true); + m_captures.renderStates.set(D3DRS_WRAP7, true); + m_captures.renderStates.set(D3DRS_WRAP8, true); + m_captures.renderStates.set(D3DRS_WRAP9, true); + m_captures.renderStates.set(D3DRS_WRAP10, true); + m_captures.renderStates.set(D3DRS_WRAP11, true); + m_captures.renderStates.set(D3DRS_WRAP12, true); + m_captures.renderStates.set(D3DRS_WRAP13, true); + m_captures.renderStates.set(D3DRS_WRAP14, true); + m_captures.renderStates.set(D3DRS_WRAP15, true); + m_captures.renderStates.set(D3DRS_COLORWRITEENABLE, true); + m_captures.renderStates.set(D3DRS_BLENDOP, true); + m_captures.renderStates.set(D3DRS_SCISSORTESTENABLE, true); + m_captures.renderStates.set(D3DRS_SLOPESCALEDEPTHBIAS, true); + m_captures.renderStates.set(D3DRS_ANTIALIASEDLINEENABLE, true); + m_captures.renderStates.set(D3DRS_TWOSIDEDSTENCILMODE, true); + m_captures.renderStates.set(D3DRS_CCW_STENCILFAIL, true); + m_captures.renderStates.set(D3DRS_CCW_STENCILZFAIL, true); + m_captures.renderStates.set(D3DRS_CCW_STENCILPASS, true); + m_captures.renderStates.set(D3DRS_CCW_STENCILFUNC, true); + m_captures.renderStates.set(D3DRS_COLORWRITEENABLE1, true); + m_captures.renderStates.set(D3DRS_COLORWRITEENABLE2, true); + m_captures.renderStates.set(D3DRS_COLORWRITEENABLE3, true); + m_captures.renderStates.set(D3DRS_BLENDFACTOR, true); + m_captures.renderStates.set(D3DRS_SRGBWRITEENABLE, true); + m_captures.renderStates.set(D3DRS_SEPARATEALPHABLENDENABLE, true); + m_captures.renderStates.set(D3DRS_SRCBLENDALPHA, true); + m_captures.renderStates.set(D3DRS_DESTBLENDALPHA, true); + m_captures.renderStates.set(D3DRS_BLENDOPALPHA, true); + } + + + void D3D9StateBlock::CapturePixelSamplerStates() { + m_captures.flags.set(D3D9CapturedStateFlag::SamplerStates); + + for (uint32_t i = 0; i < caps::MaxTexturesPS + 1; i++) { + m_captures.samplers.set(i, true); + + m_captures.samplerStates[i].set(D3DSAMP_ADDRESSU, true); + m_captures.samplerStates[i].set(D3DSAMP_ADDRESSV, true); + m_captures.samplerStates[i].set(D3DSAMP_ADDRESSW, true); + m_captures.samplerStates[i].set(D3DSAMP_BORDERCOLOR, true); + m_captures.samplerStates[i].set(D3DSAMP_MAGFILTER, true); + m_captures.samplerStates[i].set(D3DSAMP_MINFILTER, true); + m_captures.samplerStates[i].set(D3DSAMP_MIPFILTER, true); + m_captures.samplerStates[i].set(D3DSAMP_MIPMAPLODBIAS, true); + m_captures.samplerStates[i].set(D3DSAMP_MAXMIPLEVEL, true); + m_captures.samplerStates[i].set(D3DSAMP_MAXANISOTROPY, true); + m_captures.samplerStates[i].set(D3DSAMP_SRGBTEXTURE, true); + m_captures.samplerStates[i].set(D3DSAMP_ELEMENTINDEX, true); + } + } + + + void D3D9StateBlock::CapturePixelShaderStates() { + m_captures.flags.set(D3D9CapturedStateFlag::PixelShader); + m_captures.flags.set(D3D9CapturedStateFlag::PsConstants); + + m_captures.psConsts.fConsts.setAll(); + m_captures.psConsts.iConsts.setAll(); + m_captures.psConsts.bConsts.setAll(); + } + + + void D3D9StateBlock::CaptureVertexRenderStates() { + m_captures.flags.set(D3D9CapturedStateFlag::RenderStates); + + m_captures.renderStates.set(D3DRS_CULLMODE, true); + m_captures.renderStates.set(D3DRS_FOGENABLE, true); + m_captures.renderStates.set(D3DRS_FOGCOLOR, true); + m_captures.renderStates.set(D3DRS_FOGTABLEMODE, true); + m_captures.renderStates.set(D3DRS_FOGSTART, true); + m_captures.renderStates.set(D3DRS_FOGEND, true); + m_captures.renderStates.set(D3DRS_FOGDENSITY, true); + m_captures.renderStates.set(D3DRS_RANGEFOGENABLE, true); + m_captures.renderStates.set(D3DRS_AMBIENT, true); + m_captures.renderStates.set(D3DRS_COLORVERTEX, true); + m_captures.renderStates.set(D3DRS_FOGVERTEXMODE, true); + m_captures.renderStates.set(D3DRS_CLIPPING, true); + m_captures.renderStates.set(D3DRS_LIGHTING, true); + m_captures.renderStates.set(D3DRS_LOCALVIEWER, true); + m_captures.renderStates.set(D3DRS_EMISSIVEMATERIALSOURCE, true); + m_captures.renderStates.set(D3DRS_AMBIENTMATERIALSOURCE, true); + m_captures.renderStates.set(D3DRS_DIFFUSEMATERIALSOURCE, true); + m_captures.renderStates.set(D3DRS_SPECULARMATERIALSOURCE, true); + m_captures.renderStates.set(D3DRS_VERTEXBLEND, true); + m_captures.renderStates.set(D3DRS_CLIPPLANEENABLE, true); + m_captures.renderStates.set(D3DRS_POINTSIZE, true); + m_captures.renderStates.set(D3DRS_POINTSIZE_MIN, true); + m_captures.renderStates.set(D3DRS_POINTSPRITEENABLE, true); + m_captures.renderStates.set(D3DRS_POINTSCALEENABLE, true); + m_captures.renderStates.set(D3DRS_POINTSCALE_A, true); + m_captures.renderStates.set(D3DRS_POINTSCALE_B, true); + m_captures.renderStates.set(D3DRS_POINTSCALE_C, true); + m_captures.renderStates.set(D3DRS_MULTISAMPLEANTIALIAS, true); + m_captures.renderStates.set(D3DRS_MULTISAMPLEMASK, true); + m_captures.renderStates.set(D3DRS_PATCHEDGESTYLE, true); + m_captures.renderStates.set(D3DRS_POINTSIZE_MAX, true); + m_captures.renderStates.set(D3DRS_INDEXEDVERTEXBLENDENABLE, true); + m_captures.renderStates.set(D3DRS_TWEENFACTOR, true); + m_captures.renderStates.set(D3DRS_POSITIONDEGREE, true); + m_captures.renderStates.set(D3DRS_NORMALDEGREE, true); + m_captures.renderStates.set(D3DRS_MINTESSELLATIONLEVEL, true); + m_captures.renderStates.set(D3DRS_MAXTESSELLATIONLEVEL, true); + m_captures.renderStates.set(D3DRS_ADAPTIVETESS_X, true); + m_captures.renderStates.set(D3DRS_ADAPTIVETESS_Y, true); + m_captures.renderStates.set(D3DRS_ADAPTIVETESS_Z, true); + m_captures.renderStates.set(D3DRS_ADAPTIVETESS_W, true); + m_captures.renderStates.set(D3DRS_ENABLEADAPTIVETESSELLATION, true); + m_captures.renderStates.set(D3DRS_NORMALIZENORMALS, true); + m_captures.renderStates.set(D3DRS_SPECULARENABLE, true); + m_captures.renderStates.set(D3DRS_SHADEMODE, true); + } + + + void D3D9StateBlock::CaptureVertexSamplerStates() { + m_captures.flags.set(D3D9CapturedStateFlag::SamplerStates); + + for (uint32_t i = caps::MaxTexturesPS + 1; i < SamplerCount; i++) { + m_captures.samplers.set(i, true); + m_captures.samplerStates[i].set(D3DSAMP_DMAPOFFSET, true); + } + } + + + void D3D9StateBlock::CaptureVertexShaderStates() { + m_captures.flags.set(D3D9CapturedStateFlag::VertexShader); + m_captures.flags.set(D3D9CapturedStateFlag::VsConstants); + + for (uint32_t i = 0; i < m_parent->GetVertexConstantLayout().floatCount / 32; i++) + m_captures.vsConsts.fConsts.dword(i) = std::numeric_limits::max(); + + for (uint32_t i = 0; i < m_parent->GetVertexConstantLayout().intCount / 32; i++) + m_captures.vsConsts.iConsts.dword(i) = std::numeric_limits::max(); + + for (uint32_t i = 0; i < m_parent->GetVertexConstantLayout().bitmaskCount; i++) + m_captures.vsConsts.bConsts.dword(i) = std::numeric_limits::max(); + } + + + void D3D9StateBlock::CaptureType(D3D9StateBlockType Type) { + if (Type == D3D9StateBlockType::PixelState || Type == D3D9StateBlockType::All) { + CapturePixelRenderStates(); + CapturePixelSamplerStates(); + CapturePixelShaderStates(); + + m_captures.flags.set(D3D9CapturedStateFlag::TextureStages); + m_captures.textureStages.setAll(); + for (auto& stage : m_captures.textureStageStates) + stage.setAll(); + } + + if (Type == D3D9StateBlockType::VertexState || Type == D3D9StateBlockType::All) { + CaptureVertexRenderStates(); + CaptureVertexSamplerStates(); + CaptureVertexShaderStates(); + + m_captures.flags.set(D3D9CapturedStateFlag::VertexDecl); + m_captures.flags.set(D3D9CapturedStateFlag::StreamFreq); + + for (uint32_t i = 0; i < caps::MaxStreams; i++) + m_captures.streamFreq.set(i, true); + } + + if (Type == D3D9StateBlockType::All) { + m_captures.flags.set(D3D9CapturedStateFlag::Textures); + m_captures.textures.setAll(); + + m_captures.flags.set(D3D9CapturedStateFlag::VertexBuffers); + m_captures.vertexBuffers.setAll(); + + m_captures.flags.set(D3D9CapturedStateFlag::Indices); + m_captures.flags.set(D3D9CapturedStateFlag::Viewport); + m_captures.flags.set(D3D9CapturedStateFlag::ScissorRect); + + m_captures.flags.set(D3D9CapturedStateFlag::ClipPlanes); + m_captures.clipPlanes.setAll(); + + m_captures.flags.set(D3D9CapturedStateFlag::Transforms); + m_captures.transforms.setAll(); + + m_captures.flags.set(D3D9CapturedStateFlag::Material); + } + + if (Type != D3D9StateBlockType::None) + this->Capture(); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_stateblock.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_stateblock.h new file mode 100644 index 00000000000..43a712ad6fa --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_stateblock.h @@ -0,0 +1,380 @@ +#pragma once + +#include "d3d9_device_child.h" +#include "d3d9_device.h" +#include "d3d9_state.h" + +#include "../util/util_bit.h" + +namespace dxvk { + + enum class D3D9CapturedStateFlag : uint32_t { + VertexDecl, + Indices, + RenderStates, + SamplerStates, + VertexBuffers, + Textures, + VertexShader, + PixelShader, + Viewport, + ScissorRect, + ClipPlanes, + VsConstants, + PsConstants, + StreamFreq, + Transforms, + TextureStages, + Material + }; + + using D3D9CapturedStateFlags = Flags; + + struct D3D9StateCaptures { + D3D9CapturedStateFlags flags; + + bit::bitset renderStates; + + bit::bitset samplers; + std::array< + bit::bitset, + SamplerCount> samplerStates; + + bit::bitset vertexBuffers; + bit::bitset textures; + bit::bitset clipPlanes; + bit::bitset streamFreq; + bit::bitset transforms; + bit::bitset textureStages; + std::array< + bit::bitset, + caps::TextureStageCount> textureStageStates; + + struct { + bit::bitset fConsts; + bit::bitset iConsts; + bit::bitset bConsts; + } vsConsts; + + struct { + bit::bitset fConsts; + bit::bitset iConsts; + bit::bitset bConsts; + } psConsts; + }; + + enum class D3D9StateBlockType :uint32_t { + None, + VertexState, + PixelState, + All + }; + + inline D3D9StateBlockType ConvertStateBlockType(D3DSTATEBLOCKTYPE type) { + switch (type) { + case D3DSBT_PIXELSTATE: return D3D9StateBlockType::PixelState; + case D3DSBT_VERTEXSTATE: return D3D9StateBlockType::VertexState; + default: + case D3DSBT_ALL: return D3D9StateBlockType::All; + } + } + + using D3D9StateBlockBase = D3D9DeviceChild; + class D3D9StateBlock : public D3D9StateBlockBase { + + public: + + D3D9StateBlock(D3D9DeviceEx* pDevice, D3D9StateBlockType Type); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject) final; + + HRESULT STDMETHODCALLTYPE Capture() final; + HRESULT STDMETHODCALLTYPE Apply() final; + + HRESULT SetVertexDeclaration(D3D9VertexDecl* pDecl); + + HRESULT SetIndices(D3D9IndexBuffer* pIndexData); + + HRESULT SetRenderState(D3DRENDERSTATETYPE State, DWORD Value); + + HRESULT SetStateSamplerState( + DWORD StateSampler, + D3DSAMPLERSTATETYPE Type, + DWORD Value); + + HRESULT SetStreamSource( + UINT StreamNumber, + D3D9VertexBuffer* pStreamData, + UINT OffsetInBytes, + UINT Stride); + + HRESULT SetStreamSourceFreq(UINT StreamNumber, UINT Setting); + + HRESULT SetStateTexture(DWORD StateSampler, IDirect3DBaseTexture9* pTexture); + + HRESULT SetVertexShader(D3D9VertexShader* pShader); + + HRESULT SetPixelShader(D3D9PixelShader* pShader); + + HRESULT SetMaterial(const D3DMATERIAL9* pMaterial); + + HRESULT SetStateTransform(uint32_t idx, const D3DMATRIX* pMatrix); + + HRESULT SetStateTextureStageState( + DWORD Stage, + D3D9TextureStageStateTypes Type, + DWORD Value); + + HRESULT MultiplyStateTransform(uint32_t idx, const D3DMATRIX* pMatrix); + + HRESULT SetViewport(const D3DVIEWPORT9* pViewport); + + HRESULT SetScissorRect(const RECT* pRect); + + HRESULT SetClipPlane(DWORD Index, const float* pPlane); + + + HRESULT SetVertexShaderConstantF( + UINT StartRegister, + const float* pConstantData, + UINT Vector4fCount); + + HRESULT SetVertexShaderConstantI( + UINT StartRegister, + const int* pConstantData, + UINT Vector4iCount); + + HRESULT SetVertexShaderConstantB( + UINT StartRegister, + const BOOL* pConstantData, + UINT BoolCount); + + + HRESULT SetPixelShaderConstantF( + UINT StartRegister, + const float* pConstantData, + UINT Vector4fCount); + + HRESULT SetPixelShaderConstantI( + UINT StartRegister, + const int* pConstantData, + UINT Vector4iCount); + + HRESULT SetPixelShaderConstantB( + UINT StartRegister, + const BOOL* pConstantData, + UINT BoolCount); + + enum class D3D9StateFunction { + Apply, + Capture + }; + + template + void ApplyOrCapture(Dst* dst, const Src* src) { + if (m_captures.flags.test(D3D9CapturedStateFlag::StreamFreq)) { + for (uint32_t idx : bit::BitMask(m_captures.streamFreq.dword(0))) + dst->SetStreamSourceFreq(idx, src->streamFreq[idx]); + } + + if (m_captures.flags.test(D3D9CapturedStateFlag::Indices)) + dst->SetIndices(src->indices.ptr()); + + if (m_captures.flags.test(D3D9CapturedStateFlag::RenderStates)) { + for (uint32_t i = 0; i < m_captures.renderStates.dwordCount(); i++) { + for (uint32_t rs : bit::BitMask(m_captures.renderStates.dword(i))) { + uint32_t idx = i * 32 + rs; + + dst->SetRenderState(D3DRENDERSTATETYPE(idx), src->renderStates[idx]); + } + } + } + + if (m_captures.flags.test(D3D9CapturedStateFlag::SamplerStates)) { + for (uint32_t samplerIdx : bit::BitMask(m_captures.samplers.dword(0))) { + for (uint32_t stateIdx : bit::BitMask(m_captures.samplerStates[samplerIdx].dword(0))) + dst->SetStateSamplerState(samplerIdx, D3DSAMPLERSTATETYPE(stateIdx), src->samplerStates[samplerIdx][stateIdx]); + } + } + + if (m_captures.flags.test(D3D9CapturedStateFlag::VertexBuffers)) { + for (uint32_t idx : bit::BitMask(m_captures.vertexBuffers.dword(0))) { + const auto& vbo = src->vertexBuffers[idx]; + dst->SetStreamSource( + idx, + vbo.vertexBuffer.ptr(), + vbo.offset, + vbo.stride); + } + } + + if (m_captures.flags.test(D3D9CapturedStateFlag::Material)) + dst->SetMaterial(&src->material); + + if (m_captures.flags.test(D3D9CapturedStateFlag::Textures)) { + for (uint32_t idx : bit::BitMask(m_captures.textures.dword(0))) + dst->SetStateTexture(idx, src->textures[idx]); + } + + if (m_captures.flags.test(D3D9CapturedStateFlag::VertexShader)) + dst->SetVertexShader(src->vertexShader.ptr()); + + if (m_captures.flags.test(D3D9CapturedStateFlag::PixelShader)) + dst->SetPixelShader(src->pixelShader.ptr()); + + if (m_captures.flags.test(D3D9CapturedStateFlag::Transforms)) { + for (uint32_t i = 0; i < m_captures.transforms.dwordCount(); i++) { + for (uint32_t trans : bit::BitMask(m_captures.transforms.dword(i))) { + uint32_t idx = i * 32 + trans; + + dst->SetStateTransform(idx, reinterpret_cast(&src->transforms[idx])); + } + } + } + + if (m_captures.flags.test(D3D9CapturedStateFlag::TextureStages)) { + for (uint32_t stageIdx : bit::BitMask(m_captures.textureStages.dword(0))) { + for (uint32_t stateIdx : bit::BitMask(m_captures.textureStageStates[stageIdx].dword(0))) + dst->SetStateTextureStageState(stageIdx, D3D9TextureStageStateTypes(stateIdx), src->textureStages[stageIdx][stateIdx]); + } + } + + if (m_captures.flags.test(D3D9CapturedStateFlag::Viewport)) + dst->SetViewport(&src->viewport); + + if (m_captures.flags.test(D3D9CapturedStateFlag::ScissorRect)) + dst->SetScissorRect(&src->scissorRect); + + if (m_captures.flags.test(D3D9CapturedStateFlag::ClipPlanes)) { + for (uint32_t idx : bit::BitMask(m_captures.clipPlanes.dword(0))) + dst->SetClipPlane(idx, src->clipPlanes[idx].coeff); + } + + if (m_captures.flags.test(D3D9CapturedStateFlag::VsConstants)) { + for (uint32_t i = 0; i < m_captures.vsConsts.fConsts.dwordCount(); i++) { + for (uint32_t consts : bit::BitMask(m_captures.vsConsts.fConsts.dword(i))) { + uint32_t idx = i * 32 + consts; + + dst->SetVertexShaderConstantF(idx, (float*)&src->vsConsts.fConsts[idx], 1); + } + } + + for (uint32_t i = 0; i < m_captures.vsConsts.iConsts.dwordCount(); i++) { + for (uint32_t consts : bit::BitMask(m_captures.vsConsts.iConsts.dword(i))) { + uint32_t idx = i * 32 + consts; + + dst->SetVertexShaderConstantI(idx, (int*)&src->vsConsts.iConsts[idx], 1); + } + } + + if (m_captures.vsConsts.bConsts.any()) { + for (uint32_t i = 0; i < m_captures.vsConsts.bConsts.dwordCount(); i++) + dst->SetVertexBoolBitfield(i, m_captures.vsConsts.bConsts.dword(i), src->vsConsts.bConsts[i]); + } + } + + if (m_captures.flags.test(D3D9CapturedStateFlag::PsConstants)) { + for (uint32_t i = 0; i < m_captures.psConsts.fConsts.dwordCount(); i++) { + for (uint32_t consts : bit::BitMask(m_captures.psConsts.fConsts.dword(i))) { + uint32_t idx = i * 32 + consts; + + dst->SetPixelShaderConstantF(idx, (float*)&src->psConsts.fConsts[idx], 1); + } + } + + for (uint32_t i = 0; i < m_captures.psConsts.iConsts.dwordCount(); i++) { + for (uint32_t consts : bit::BitMask(m_captures.psConsts.iConsts.dword(i))) { + uint32_t idx = i * 32 + consts; + + dst->SetPixelShaderConstantI(idx, (int*)&src->psConsts.iConsts[idx], 1); + } + } + + if (m_captures.psConsts.bConsts.any()) { + for (uint32_t i = 0; i < m_captures.psConsts.bConsts.dwordCount(); i++) + dst->SetPixelBoolBitfield(i, m_captures.psConsts.bConsts.dword(i), src->psConsts.bConsts[i]); + } + } + } + + template + void ApplyOrCapture() { + if constexpr (Func == D3D9StateFunction::Apply) + ApplyOrCapture(m_parent, &m_state); + else if constexpr (Func == D3D9StateFunction::Capture) + ApplyOrCapture(this, m_deviceState); + } + + template < + DxsoProgramType ProgramType, + D3D9ConstantType ConstantType, + typename T> + HRESULT SetShaderConstants( + UINT StartRegister, + const T* pConstantData, + UINT Count) { + auto SetHelper = [&](auto& setCaptures) { + if constexpr (ProgramType == DxsoProgramTypes::VertexShader) + m_captures.flags.set(D3D9CapturedStateFlag::VsConstants); + else + m_captures.flags.set(D3D9CapturedStateFlag::PsConstants); + + for (uint32_t i = 0; i < Count; i++) { + uint32_t reg = StartRegister + i; + if constexpr (ConstantType == D3D9ConstantType::Float) + setCaptures.fConsts.set(reg, true); + else if constexpr (ConstantType == D3D9ConstantType::Int) + setCaptures.iConsts.set(reg, true); + else if constexpr (ConstantType == D3D9ConstantType::Bool) + setCaptures.bConsts.set(reg, true); + } + + UpdateStateConstants< + ProgramType, + ConstantType, + T>( + &m_state, + StartRegister, + pConstantData, + Count, + false); + + return D3D_OK; + }; + + return ProgramType == DxsoProgramTypes::VertexShader + ? SetHelper(m_captures.vsConsts) + : SetHelper(m_captures.psConsts); + } + + HRESULT SetVertexBoolBitfield(uint32_t idx, uint32_t mask, uint32_t bits); + HRESULT SetPixelBoolBitfield (uint32_t idx, uint32_t mask, uint32_t bits); + + inline bool IsApplying() { + return m_applying; + } + + private: + + void CapturePixelRenderStates(); + void CapturePixelSamplerStates(); + void CapturePixelShaderStates(); + + void CaptureVertexRenderStates(); + void CaptureVertexSamplerStates(); + void CaptureVertexShaderStates(); + + void CaptureType(D3D9StateBlockType State); + + D3D9CapturableState m_state; + D3D9StateCaptures m_captures; + + D3D9CapturableState* m_deviceState; + + bool m_applying = false; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_subresource.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_subresource.h new file mode 100644 index 00000000000..8d0475018b0 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_subresource.h @@ -0,0 +1,149 @@ +#pragma once + +#include "d3d9_resource.h" +#include "d3d9_common_texture.h" + +namespace dxvk { + + template + class D3D9Subresource : public D3D9Resource { + + public: + + D3D9Subresource( + D3D9DeviceEx* pDevice, + D3D9CommonTexture* pTexture, + UINT Face, + UINT MipLevel, + IDirect3DBaseTexture9* pBaseTexture, + IUnknown* pContainer) + : D3D9Resource(pDevice), + m_container (pContainer), + m_baseTexture (pBaseTexture), + m_texture (pTexture), + m_face (Face), + m_mipLevel (MipLevel), + m_isSrgbCompatible (pTexture->IsSrgbCompatible()), + m_isNull (pTexture->IsNull()) { + + } + + ~D3D9Subresource() { + // We own the texture! + if (m_baseTexture == nullptr) + delete m_texture; + } + + ULONG STDMETHODCALLTYPE AddRef() final { + if (m_baseTexture != nullptr) + return m_baseTexture->AddRef(); + + return D3D9Resource::AddRef(); + } + + ULONG STDMETHODCALLTYPE Release() final { + if (m_baseTexture != nullptr) + return m_baseTexture->Release(); + + return D3D9Resource::Release(); + } + + HRESULT STDMETHODCALLTYPE GetContainer(REFIID riid, void** ppContainer) final { + if (m_container != nullptr) + return m_container->QueryInterface(riid, ppContainer); + + return this->GetDevice()->QueryInterface(riid, ppContainer); + } + + void STDMETHODCALLTYPE PreLoad() { + m_texture->PreLoadSubresource(GetSubresource()); + } + + inline D3D9CommonTexture* GetCommonTexture() { + return m_texture; + } + + inline UINT GetFace() const { + return m_face; + } + + inline UINT GetMipLevel() const { + return m_mipLevel; + } + + inline UINT GetSubresource() const { + return m_texture->CalcSubresource(m_face, m_mipLevel); + } + + inline const Rc& GetImageView(bool Srgb) { + Srgb &= m_isSrgbCompatible; + Rc& view = m_sampleView.Pick(Srgb); + + if (unlikely(view == nullptr && !IsNull())) + view = m_texture->CreateView(m_face, m_mipLevel, VK_IMAGE_USAGE_SAMPLED_BIT, Srgb); + + return view; + } + + inline const Rc& GetRenderTargetView(bool Srgb) { + Srgb &= m_isSrgbCompatible; + Rc& view = m_renderTargetView.Pick(Srgb); + + if (unlikely(view == nullptr && !IsNull())) + view = m_texture->CreateView(m_face, m_mipLevel, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, Srgb); + + return view; + } + + inline VkImageLayout GetRenderTargetLayout() const { + return m_texture->DetermineRenderTargetLayout(); + } + + inline const Rc& GetDepthStencilView() { + Rc& view = m_depthStencilView; + + if (unlikely(view == nullptr)) + view = m_texture->CreateView(m_face, m_mipLevel, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, false); + + return view; + } + + inline VkImageLayout GetDepthStencilLayout(bool write, bool hazardous) const { + return m_texture->DetermineDepthStencilLayout(write, hazardous); + } + + inline bool IsNull() { + return m_isNull; + } + + inline IDirect3DBaseTexture9* GetBaseTexture() { + return m_baseTexture; + } + + inline void Swap(D3D9Subresource* Other) { + // Only used for swap chain back buffers that don't + // have a container and all have identical properties + std::swap(m_texture, Other->m_texture); + std::swap(m_sampleView, Other->m_sampleView); + std::swap(m_renderTargetView, Other->m_renderTargetView); + } + + protected: + + IUnknown* m_container; + IDirect3DBaseTexture9* m_baseTexture; + + D3D9CommonTexture* m_texture; + + UINT m_face : 8; + UINT m_mipLevel : 16; + UINT m_isSrgbCompatible : 1; + UINT m_isNull : 1; + + D3D9ColorView m_sampleView; + D3D9ColorView m_renderTargetView; + Rc m_depthStencilView; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_surface.cpp b/utils/dxvk-1.10.3/src/d3d9/d3d9_surface.cpp new file mode 100644 index 00000000000..300782e991e --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_surface.cpp @@ -0,0 +1,192 @@ +#include "d3d9_surface.h" +#include "d3d9_texture.h" +#include "d3d9_swapchain.h" + +#include "d3d9_device.h" + +namespace dxvk { + + D3D9Surface::D3D9Surface( + D3D9DeviceEx* pDevice, + const D3D9_COMMON_TEXTURE_DESC* pDesc, + IUnknown* pContainer, + HANDLE* pSharedHandle) + : D3D9SurfaceBase( + pDevice, + new D3D9CommonTexture( pDevice, pDesc, D3DRTYPE_SURFACE, pSharedHandle), + 0, 0, + nullptr, + pContainer) { } + + D3D9Surface::D3D9Surface( + D3D9DeviceEx* pDevice, + D3D9CommonTexture* pTexture, + UINT Face, + UINT MipLevel, + IDirect3DBaseTexture9* pBaseTexture) + : D3D9SurfaceBase( + pDevice, + pTexture, + Face, MipLevel, + pBaseTexture, + pBaseTexture) { } + + void D3D9Surface::AddRefPrivate() { + if (m_baseTexture != nullptr) { + D3DRESOURCETYPE type = m_baseTexture->GetType(); + if (type == D3DRTYPE_TEXTURE) + static_cast (m_baseTexture)->AddRefPrivate(); + else //if (type == D3DRTYPE_CUBETEXTURE) + static_cast(m_baseTexture)->AddRefPrivate(); + + return; + } + + D3D9SurfaceBase::AddRefPrivate(); + } + + void D3D9Surface::ReleasePrivate() { + if (m_baseTexture != nullptr) { + D3DRESOURCETYPE type = m_baseTexture->GetType(); + if (type == D3DRTYPE_TEXTURE) + static_cast (m_baseTexture)->ReleasePrivate(); + else //if (type == D3DRTYPE_CUBETEXTURE) + static_cast(m_baseTexture)->ReleasePrivate(); + + return; + } + + D3D9SurfaceBase::ReleasePrivate(); + } + + HRESULT STDMETHODCALLTYPE D3D9Surface::QueryInterface(REFIID riid, void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(IDirect3DResource9) + || riid == __uuidof(IDirect3DSurface9)) { + *ppvObject = ref(this); + return S_OK; + } + + Logger::warn("D3D9Surface::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + D3DRESOURCETYPE STDMETHODCALLTYPE D3D9Surface::GetType() { + return D3DRTYPE_SURFACE; + } + + HRESULT STDMETHODCALLTYPE D3D9Surface::GetDesc(D3DSURFACE_DESC *pDesc) { + if (pDesc == nullptr) + return D3DERR_INVALIDCALL; + + auto& desc = *(m_texture->Desc()); + + pDesc->Format = static_cast(desc.Format); + pDesc->Type = D3DRTYPE_SURFACE; + pDesc->Usage = desc.Usage; + pDesc->Pool = desc.Pool; + + pDesc->MultiSampleType = desc.MultiSample; + pDesc->MultiSampleQuality = desc.MultisampleQuality; + pDesc->Width = std::max(1u, desc.Width >> m_mipLevel); + pDesc->Height = std::max(1u, desc.Height >> m_mipLevel); + + return D3D_OK; + } + + HRESULT STDMETHODCALLTYPE D3D9Surface::LockRect(D3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) { + if (unlikely(pLockedRect == nullptr)) + return D3DERR_INVALIDCALL; + + D3DBOX box; + if (pRect != nullptr) { + box.Left = pRect->left; + box.Right = pRect->right; + box.Top = pRect->top; + box.Bottom = pRect->bottom; + box.Front = 0; + box.Back = 1; + } + + D3DLOCKED_BOX lockedBox; + + HRESULT hr = m_parent->LockImage( + m_texture, + m_face, m_mipLevel, + &lockedBox, + pRect != nullptr ? &box : nullptr, + Flags); + + pLockedRect->pBits = lockedBox.pBits; + pLockedRect->Pitch = lockedBox.RowPitch; + + return hr; + } + + HRESULT STDMETHODCALLTYPE D3D9Surface::UnlockRect() { + return m_parent->UnlockImage( + m_texture, + m_face, m_mipLevel); + } + + HRESULT STDMETHODCALLTYPE D3D9Surface::GetDC(HDC *phDC) { + if (phDC == nullptr) + return D3DERR_INVALIDCALL; + + const D3D9_COMMON_TEXTURE_DESC& desc = *m_texture->Desc(); + + D3DLOCKED_RECT lockedRect; + HRESULT hr = LockRect(&lockedRect, nullptr, 0); + if (FAILED(hr)) + return hr; + + D3DKMT_CREATEDCFROMMEMORY createInfo; + // In... + createInfo.pMemory = lockedRect.pBits; + createInfo.Format = static_cast(desc.Format); + createInfo.Width = desc.Width; + createInfo.Height = desc.Height; + createInfo.Pitch = lockedRect.Pitch; + createInfo.hDeviceDc = CreateCompatibleDC(NULL); + createInfo.pColorTable = nullptr; + + // Out... + createInfo.hBitmap = nullptr; + createInfo.hDc = nullptr; + + D3DKMTCreateDCFromMemory(&createInfo); + DeleteDC(createInfo.hDeviceDc); + + // These should now be set... + m_dcDesc.hDC = createInfo.hDc; + m_dcDesc.hBitmap = createInfo.hBitmap; + + *phDC = m_dcDesc.hDC; + return D3D_OK; + } + + HRESULT STDMETHODCALLTYPE D3D9Surface::ReleaseDC(HDC hDC) { + if (m_dcDesc.hDC == nullptr || m_dcDesc.hDC != hDC) + return D3DERR_INVALIDCALL; + + D3DKMTDestroyDCFromMemory(&m_dcDesc); + + HRESULT hr = UnlockRect(); + if (FAILED(hr)) + return hr; + + return D3D_OK; + } + + + void D3D9Surface::ClearContainer() { + m_container = nullptr; + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_surface.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_surface.h new file mode 100644 index 00000000000..3f4205390aa --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_surface.h @@ -0,0 +1,67 @@ +#pragma once + +#include "d3d9_subresource.h" + +#include "d3d9_common_texture.h" + +#include "../util/util_gdi.h" + +#include + +namespace dxvk { + + using D3D9GDIDesc = D3DKMT_DESTROYDCFROMMEMORY; + + using D3D9SurfaceBase = D3D9Subresource; + class D3D9Surface final : public D3D9SurfaceBase { + + public: + + D3D9Surface( + D3D9DeviceEx* pDevice, + const D3D9_COMMON_TEXTURE_DESC* pDesc, + IUnknown* pContainer, + HANDLE* pSharedHandle); + + D3D9Surface( + D3D9DeviceEx* pDevice, + D3D9CommonTexture* pTexture, + UINT Face, + UINT MipLevel, + IDirect3DBaseTexture9* pBaseTexture); + + void AddRefPrivate(); + + void ReleasePrivate(); + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject); + + D3DRESOURCETYPE STDMETHODCALLTYPE GetType() final; + + HRESULT STDMETHODCALLTYPE GetDesc(D3DSURFACE_DESC *pDesc) final; + + HRESULT STDMETHODCALLTYPE LockRect(D3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) final; + + HRESULT STDMETHODCALLTYPE UnlockRect() final; + + HRESULT STDMETHODCALLTYPE GetDC(HDC *phDC) final; + + HRESULT STDMETHODCALLTYPE ReleaseDC(HDC hDC) final; + + inline VkExtent2D GetSurfaceExtent() const { + const auto* desc = m_texture->Desc(); + + return VkExtent2D { + std::max(1u, desc->Width >> GetMipLevel()), + std::max(1u, desc->Height >> GetMipLevel()) + }; + } + + void ClearContainer(); + + private: + + D3D9GDIDesc m_dcDesc; + + }; +} diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_swapchain.cpp b/utils/dxvk-1.10.3/src/d3d9/d3d9_swapchain.cpp new file mode 100644 index 00000000000..306a79b7fca --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_swapchain.cpp @@ -0,0 +1,1374 @@ +#include "d3d9_swapchain.h" +#include "d3d9_surface.h" +#include "d3d9_monitor.h" + +#include "d3d9_hud.h" + +namespace dxvk { + + + struct D3D9WindowData { + bool unicode; + bool filter; + bool activateProcessed; + WNDPROC proc; + D3D9SwapChainEx* swapchain; + }; + + + static dxvk::recursive_mutex g_windowProcMapMutex; + static std::unordered_map g_windowProcMap; + + static void SetActivateProcessed(HWND window, bool processed) + { + std::lock_guard lock(g_windowProcMapMutex); + auto it = g_windowProcMap.find(window); + if (it != g_windowProcMap.end()) + it->second.activateProcessed = processed; + } + + template + auto CallCharsetFunction(T unicode, J ascii, bool isUnicode, Args... args) { + return isUnicode + ? unicode(args...) + : ascii (args...); + } + + + class D3D9WindowMessageFilter { + + public: + + D3D9WindowMessageFilter(HWND window, bool filter = true) + : m_window(window) { + std::lock_guard lock(g_windowProcMapMutex); + auto it = g_windowProcMap.find(m_window); + m_filter = std::exchange(it->second.filter, filter); + } + + ~D3D9WindowMessageFilter() { + std::lock_guard lock(g_windowProcMapMutex); + auto it = g_windowProcMap.find(m_window); + it->second.filter = m_filter; + } + + D3D9WindowMessageFilter (const D3D9WindowMessageFilter&) = delete; + D3D9WindowMessageFilter& operator = (const D3D9WindowMessageFilter&) = delete; + + private: + + HWND m_window; + bool m_filter; + + }; + + + LRESULT CALLBACK D3D9WindowProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam); + + + void ResetWindowProc(HWND window) { + std::lock_guard lock(g_windowProcMapMutex); + + auto it = g_windowProcMap.find(window); + if (it == g_windowProcMap.end()) + return; + + auto proc = reinterpret_cast( + CallCharsetFunction( + GetWindowLongPtrW, GetWindowLongPtrA, it->second.unicode, + window, GWLP_WNDPROC)); + + + if (proc == D3D9WindowProc) + CallCharsetFunction( + SetWindowLongPtrW, SetWindowLongPtrA, it->second.unicode, + window, GWLP_WNDPROC, reinterpret_cast(it->second.proc)); + + g_windowProcMap.erase(window); + } + + + void HookWindowProc(HWND window, D3D9SwapChainEx* swapchain) { + std::lock_guard lock(g_windowProcMapMutex); + + ResetWindowProc(window); + + D3D9WindowData windowData; + windowData.unicode = IsWindowUnicode(window); + windowData.filter = false; + windowData.activateProcessed = false; + windowData.proc = reinterpret_cast( + CallCharsetFunction( + SetWindowLongPtrW, SetWindowLongPtrA, windowData.unicode, + window, GWLP_WNDPROC, reinterpret_cast(D3D9WindowProc))); + windowData.swapchain = swapchain; + + g_windowProcMap[window] = std::move(windowData); + } + + + LRESULT CALLBACK D3D9WindowProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam) { + if (message == WM_NCCALCSIZE && wparam == TRUE) + return 0; + + D3D9WindowData windowData = {}; + + { + std::lock_guard lock(g_windowProcMapMutex); + + auto it = g_windowProcMap.find(window); + if (it != g_windowProcMap.end()) + windowData = it->second; + } + + bool unicode = windowData.proc + ? windowData.unicode + : IsWindowUnicode(window); + + if (!windowData.proc || windowData.filter) + return CallCharsetFunction( + DefWindowProcW, DefWindowProcA, unicode, + window, message, wparam, lparam); + + if (message == WM_DESTROY) + ResetWindowProc(window); + else if (message == WM_ACTIVATEAPP) { + D3DDEVICE_CREATION_PARAMETERS create_parms; + windowData.swapchain->GetDevice()->GetCreationParameters(&create_parms); + + if (!(create_parms.BehaviorFlags & D3DCREATE_NOWINDOWCHANGES)) { + D3D9WindowMessageFilter filter(window); + if (wparam && !windowData.activateProcessed) { + // Heroes of Might and Magic V needs this to resume drawing after a focus loss + D3DPRESENT_PARAMETERS params; + RECT rect; + + GetMonitorRect(GetDefaultMonitor(), &rect); + windowData.swapchain->GetPresentParameters(¶ms); + SetWindowPos(window, nullptr, rect.left, rect.top, params.BackBufferWidth, params.BackBufferHeight, + SWP_NOACTIVATE | SWP_NOZORDER); + SetActivateProcessed(window, true); + } + else if (!wparam) { + if (IsWindowVisible(window)) + ShowWindow(window, SW_MINIMIZE); + SetActivateProcessed(window, false); + } + } + } + else if (message == WM_SIZE) + { + D3DDEVICE_CREATION_PARAMETERS create_parms; + windowData.swapchain->GetDevice()->GetCreationParameters(&create_parms); + + if (!(create_parms.BehaviorFlags & D3DCREATE_NOWINDOWCHANGES) && !IsIconic(window)) + PostMessageW(window, WM_ACTIVATEAPP, 1, GetCurrentThreadId()); + } + + return CallCharsetFunction( + CallWindowProcW, CallWindowProcA, unicode, + windowData.proc, window, message, wparam, lparam); + } + + + static uint16_t MapGammaControlPoint(float x) { + if (x < 0.0f) x = 0.0f; + if (x > 1.0f) x = 1.0f; + return uint16_t(65535.0f * x); + } + + + struct D3D9PresentInfo { + float scale[2]; + float offset[2]; + }; + + + D3D9SwapChainEx::D3D9SwapChainEx( + D3D9DeviceEx* pDevice, + D3DPRESENT_PARAMETERS* pPresentParams, + const D3DDISPLAYMODEEX* pFullscreenDisplayMode) + : D3D9SwapChainExBase(pDevice) + , m_device (pDevice->GetDXVKDevice()) + , m_context (m_device->createContext()) + , m_frameLatencyCap (pDevice->GetOptions()->maxFrameLatency) + , m_frameLatencySignal(new sync::Fence(m_frameId)) + , m_dialog (pDevice->GetOptions()->enableDialogMode) { + this->NormalizePresentParameters(pPresentParams); + m_presentParams = *pPresentParams; + m_window = m_presentParams.hDeviceWindow; + + UpdatePresentRegion(nullptr, nullptr); + if (m_window && !pDevice->GetOptions()->deferSurfaceCreation) + CreatePresenter(); + + CreateBackBuffers(m_presentParams.BackBufferCount); + CreateBlitter(); + CreateHud(); + + InitRamp(); + + // Apply initial window mode and fullscreen state + if (!m_presentParams.Windowed && FAILED(EnterFullscreenMode(pPresentParams, pFullscreenDisplayMode))) + throw DxvkError("D3D9: Failed to set initial fullscreen state"); + } + + + D3D9SwapChainEx::~D3D9SwapChainEx() { + DestroyBackBuffers(); + + ResetWindowProc(m_window); + RestoreDisplayMode(m_monitor); + + m_device->waitForSubmission(&m_presentStatus); + m_device->waitForIdle(); + } + + + HRESULT STDMETHODCALLTYPE D3D9SwapChainEx::QueryInterface(REFIID riid, void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(IDirect3DSwapChain9) + || (GetParent()->IsExtended() && riid == __uuidof(IDirect3DSwapChain9Ex))) { + *ppvObject = ref(this); + return S_OK; + } + + Logger::warn("D3D9SwapChainEx::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + HRESULT STDMETHODCALLTYPE D3D9SwapChainEx::Present( + const RECT* pSourceRect, + const RECT* pDestRect, + HWND hDestWindowOverride, + const RGNDATA* pDirtyRegion, + DWORD dwFlags) { + D3D9DeviceLock lock = m_parent->LockDevice(); + + uint32_t presentInterval = m_presentParams.PresentationInterval; + + // This is not true directly in d3d9 to to timing differences that don't matter for us. + // For our purposes... + // D3DPRESENT_INTERVAL_DEFAULT (0) == D3DPRESENT_INTERVAL_ONE (1) which means VSYNC. + presentInterval = std::max(presentInterval, 1u); + + if (presentInterval == D3DPRESENT_INTERVAL_IMMEDIATE || (dwFlags & D3DPRESENT_FORCEIMMEDIATE)) + presentInterval = 0; + + auto options = m_parent->GetOptions(); + + if (options->presentInterval >= 0) + presentInterval = options->presentInterval; + + bool vsync = presentInterval != 0; + + HWND window = m_presentParams.hDeviceWindow; + if (hDestWindowOverride != nullptr) + window = hDestWindowOverride; + + bool recreate = false; + recreate |= m_presenter == nullptr; + recreate |= window != m_window; + recreate |= m_dialog != m_lastDialog; + + m_window = window; + + m_dirty |= vsync != m_vsync; + m_dirty |= UpdatePresentRegion(pSourceRect, pDestRect); + m_dirty |= recreate; + m_dirty |= m_presenter != nullptr && + !m_presenter->hasSwapChain(); + + m_vsync = vsync; + + m_lastDialog = m_dialog; + + try { + if (recreate) + CreatePresenter(); + + if (std::exchange(m_dirty, false)) + RecreateSwapChain(vsync); + + // We aren't going to device loss simply because + // 99% of D3D9 games don't handle this properly and + // just end up crashing (like with alt-tab loss) + if (!m_presenter->hasSwapChain()) + return D3D_OK; + + PresentImage(presentInterval); + return D3D_OK; + } catch (const DxvkError& e) { + Logger::err(e.message()); + return D3DERR_DEVICEREMOVED; + } + } + + + HRESULT STDMETHODCALLTYPE D3D9SwapChainEx::GetFrontBufferData(IDirect3DSurface9* pDestSurface) { + D3D9DeviceLock lock = m_parent->LockDevice(); + + // This function can do absolutely everything! + // Copies the front buffer between formats with an implicit resolve. + // Oh, and the dest is systemmem... + // This is a slow function anyway, it waits for the copy to finish. + // so there's no reason to not just make and throwaway temp images. + + // If extent of dst > src, then we blit to a subrect of the size + // of src onto a temp image of dst's extents, + // then copy buffer back to dst (given dst is subresource) + + D3D9Surface* dst = static_cast(pDestSurface); + + if (unlikely(dst == nullptr)) + return D3DERR_INVALIDCALL; + + D3D9CommonTexture* dstTexInfo = dst->GetCommonTexture(); + D3D9CommonTexture* srcTexInfo = m_backBuffers.back()->GetCommonTexture(); + + if (unlikely(dstTexInfo->Desc()->Pool != D3DPOOL_SYSTEMMEM && dstTexInfo->Desc()->Pool != D3DPOOL_SCRATCH)) + return D3DERR_INVALIDCALL; + + Rc dstBuffer = dstTexInfo->GetBuffer(dst->GetSubresource()); + Rc srcImage = srcTexInfo->GetImage(); + + if (srcImage->info().sampleCount != VK_SAMPLE_COUNT_1_BIT) { + DxvkImageCreateInfo resolveInfo; + resolveInfo.type = VK_IMAGE_TYPE_2D; + resolveInfo.format = srcImage->info().format; + resolveInfo.flags = 0; + resolveInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT; + resolveInfo.extent = srcImage->info().extent; + resolveInfo.numLayers = 1; + resolveInfo.mipLevels = 1; + resolveInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT + | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + resolveInfo.stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT + | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT + | VK_PIPELINE_STAGE_TRANSFER_BIT; + resolveInfo.access = VK_ACCESS_SHADER_READ_BIT + | VK_ACCESS_TRANSFER_WRITE_BIT + | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT + | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + resolveInfo.tiling = VK_IMAGE_TILING_OPTIMAL; + resolveInfo.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + + Rc resolvedSrc = m_device->createImage( + resolveInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + + m_parent->EmitCs([ + cDstImage = resolvedSrc, + cSrcImage = srcImage + ] (DxvkContext* ctx) { + VkImageSubresourceLayers resolveSubresource; + resolveSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + resolveSubresource.mipLevel = 0; + resolveSubresource.baseArrayLayer = 0; + resolveSubresource.layerCount = 1; + + VkImageResolve resolveRegion; + resolveRegion.srcSubresource = resolveSubresource; + resolveRegion.srcOffset = VkOffset3D { 0, 0, 0 }; + resolveRegion.dstSubresource = resolveSubresource; + resolveRegion.dstOffset = VkOffset3D { 0, 0, 0 }; + resolveRegion.extent = cSrcImage->info().extent; + + ctx->resolveImage( + cDstImage, cSrcImage, + resolveRegion, VK_FORMAT_UNDEFINED); + }); + + srcImage = std::move(resolvedSrc); + } + + D3D9Format srcFormat = srcTexInfo->Desc()->Format; + D3D9Format dstFormat = dstTexInfo->Desc()->Format; + + bool similar = AreFormatsSimilar(srcFormat, dstFormat); + + if (!similar || srcImage->info().extent != dstTexInfo->GetExtent()) { + DxvkImageCreateInfo blitCreateInfo; + blitCreateInfo.type = VK_IMAGE_TYPE_2D; + blitCreateInfo.format = dstTexInfo->GetFormatMapping().FormatColor; + blitCreateInfo.flags = 0; + blitCreateInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT; + blitCreateInfo.extent = dstTexInfo->GetExtent(); + blitCreateInfo.numLayers = 1; + blitCreateInfo.mipLevels = 1; + blitCreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT + | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + blitCreateInfo.stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT + | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT + | VK_PIPELINE_STAGE_TRANSFER_BIT; + blitCreateInfo.access = VK_ACCESS_SHADER_READ_BIT + | VK_ACCESS_TRANSFER_WRITE_BIT + | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT + | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + blitCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; + blitCreateInfo.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + + Rc blittedSrc = m_device->createImage( + blitCreateInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + + const DxvkFormatInfo* dstFormatInfo = imageFormatInfo(blittedSrc->info().format); + const DxvkFormatInfo* srcFormatInfo = imageFormatInfo(srcImage->info().format); + + const VkImageSubresource dstSubresource = dstTexInfo->GetSubresourceFromIndex(dstFormatInfo->aspectMask, 0); + const VkImageSubresource srcSubresource = srcTexInfo->GetSubresourceFromIndex(srcFormatInfo->aspectMask, 0); + + VkImageSubresourceLayers dstSubresourceLayers = { + dstSubresource.aspectMask, + dstSubresource.mipLevel, + dstSubresource.arrayLayer, 1 }; + + VkImageSubresourceLayers srcSubresourceLayers = { + srcSubresource.aspectMask, + srcSubresource.mipLevel, + srcSubresource.arrayLayer, 1 }; + + VkExtent3D srcExtent = srcImage->mipLevelExtent(srcSubresource.mipLevel); + + // Blit to a subrect of the src extents + VkImageBlit blitInfo; + blitInfo.dstSubresource = dstSubresourceLayers; + blitInfo.srcSubresource = srcSubresourceLayers; + blitInfo.dstOffsets[0] = VkOffset3D{ 0, 0, 0 }; + blitInfo.dstOffsets[1] = VkOffset3D{ int32_t(srcExtent.width), int32_t(srcExtent.height), 1 }; + blitInfo.srcOffsets[0] = VkOffset3D{ 0, 0, 0 }; + blitInfo.srcOffsets[1] = VkOffset3D{ int32_t(srcExtent.width), int32_t(srcExtent.height), 1 }; + + m_parent->EmitCs([ + cDstImage = blittedSrc, + cDstMap = dstTexInfo->GetMapping().Swizzle, + cSrcImage = srcImage, + cSrcMap = srcTexInfo->GetMapping().Swizzle, + cBlitInfo = blitInfo + ] (DxvkContext* ctx) { + ctx->blitImage( + cDstImage, cDstMap, + cSrcImage, cSrcMap, + cBlitInfo, VK_FILTER_NEAREST); + }); + + srcImage = std::move(blittedSrc); + } + + const DxvkFormatInfo* srcFormatInfo = imageFormatInfo(srcImage->info().format); + const VkImageSubresource srcSubresource = srcTexInfo->GetSubresourceFromIndex(srcFormatInfo->aspectMask, 0); + VkImageSubresourceLayers srcSubresourceLayers = { + srcSubresource.aspectMask, + srcSubresource.mipLevel, + srcSubresource.arrayLayer, 1 }; + VkExtent3D srcExtent = srcImage->mipLevelExtent(srcSubresource.mipLevel); + + m_parent->EmitCs([ + cBuffer = dstBuffer, + cImage = srcImage, + cSubresources = srcSubresourceLayers, + cLevelExtent = srcExtent + ] (DxvkContext* ctx) { + ctx->copyImageToBuffer(cBuffer, 0, 4, 0, + cImage, cSubresources, VkOffset3D { 0, 0, 0 }, + cLevelExtent); + }); + + dstTexInfo->SetNeedsReadback(dst->GetSubresource(), true); + m_parent->TrackTextureMappingBufferSequenceNumber(dstTexInfo, dst->GetSubresource()); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9SwapChainEx::GetBackBuffer( + UINT iBackBuffer, + D3DBACKBUFFER_TYPE Type, + IDirect3DSurface9** ppBackBuffer) { + // Could be doing a device reset... + D3D9DeviceLock lock = m_parent->LockDevice(); + + if (unlikely(ppBackBuffer == nullptr)) + return D3DERR_INVALIDCALL; + + if (unlikely(iBackBuffer >= m_presentParams.BackBufferCount)) { + Logger::err(str::format("D3D9: GetBackBuffer: Invalid back buffer index: ", iBackBuffer)); + return D3DERR_INVALIDCALL; + } + + *ppBackBuffer = ref(m_backBuffers[iBackBuffer].ptr()); + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9SwapChainEx::GetRasterStatus(D3DRASTER_STATUS* pRasterStatus) { + // We could use D3DKMTGetScanLine but Wine doesn't implement that. + // So... we lie here and make some stuff up + // enough that it makes games work. + + // Assume there's 20 lines in a vBlank. + constexpr uint32_t vBlankLineCount = 20; + + if (pRasterStatus == nullptr) + return D3DERR_INVALIDCALL; + + D3DDISPLAYMODEEX mode; + mode.Size = sizeof(mode); + if (FAILED(this->GetDisplayModeEx(&mode, nullptr))) + return D3DERR_INVALIDCALL; + + uint32_t scanLineCount = mode.Height + vBlankLineCount; + + auto nowUs = std::chrono::time_point_cast( + dxvk::high_resolution_clock::now()) + .time_since_epoch(); + + auto frametimeUs = std::chrono::microseconds(1000000u / mode.RefreshRate); + auto scanLineUs = frametimeUs / scanLineCount; + + pRasterStatus->ScanLine = (nowUs % frametimeUs) / scanLineUs; + pRasterStatus->InVBlank = pRasterStatus->ScanLine >= mode.Height; + + if (pRasterStatus->InVBlank) + pRasterStatus->ScanLine = 0; + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9SwapChainEx::GetDisplayMode(D3DDISPLAYMODE* pMode) { + if (pMode == nullptr) + return D3DERR_INVALIDCALL; + + *pMode = D3DDISPLAYMODE(); + + D3DDISPLAYMODEEX mode; + mode.Size = sizeof(mode); + HRESULT hr = this->GetDisplayModeEx(&mode, nullptr); + + if (FAILED(hr)) + return hr; + + pMode->Width = mode.Width; + pMode->Height = mode.Height; + pMode->Format = mode.Format; + pMode->RefreshRate = mode.RefreshRate; + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9SwapChainEx::GetPresentParameters(D3DPRESENT_PARAMETERS* pPresentationParameters) { + if (pPresentationParameters == nullptr) + return D3DERR_INVALIDCALL; + + *pPresentationParameters = m_presentParams; + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9SwapChainEx::GetLastPresentCount(UINT* pLastPresentCount) { + Logger::warn("D3D9SwapChainEx::GetLastPresentCount: Stub"); + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9SwapChainEx::GetPresentStats(D3DPRESENTSTATS* pPresentationStatistics) { + Logger::warn("D3D9SwapChainEx::GetPresentStats: Stub"); + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9SwapChainEx::GetDisplayModeEx(D3DDISPLAYMODEEX* pMode, D3DDISPLAYROTATION* pRotation) { + if (pMode == nullptr && pRotation == nullptr) + return D3DERR_INVALIDCALL; + + if (pRotation != nullptr) + *pRotation = D3DDISPLAYROTATION_IDENTITY; + + if (pMode != nullptr) { + DEVMODEW devMode = DEVMODEW(); + devMode.dmSize = sizeof(devMode); + + if (!GetMonitorDisplayMode(GetDefaultMonitor(), ENUM_CURRENT_SETTINGS, &devMode)) { + Logger::err("D3D9SwapChainEx::GetDisplayModeEx: Failed to enum display settings"); + return D3DERR_INVALIDCALL; + } + + pMode->Size = sizeof(D3DDISPLAYMODEEX); + pMode->Width = devMode.dmPelsWidth; + pMode->Height = devMode.dmPelsHeight; + pMode->RefreshRate = devMode.dmDisplayFrequency; + pMode->Format = D3DFMT_X8R8G8B8; + pMode->ScanLineOrdering = D3DSCANLINEORDERING_PROGRESSIVE; + } + + return D3D_OK; + } + + + HRESULT D3D9SwapChainEx::Reset( + D3DPRESENT_PARAMETERS* pPresentParams, + D3DDISPLAYMODEEX* pFullscreenDisplayMode) { + D3D9DeviceLock lock = m_parent->LockDevice(); + + this->SynchronizePresent(); + this->NormalizePresentParameters(pPresentParams); + + m_dirty |= m_presentParams.BackBufferFormat != pPresentParams->BackBufferFormat + || m_presentParams.BackBufferCount != pPresentParams->BackBufferCount; + + bool changeFullscreen = m_presentParams.Windowed != pPresentParams->Windowed; + + if (pPresentParams->Windowed) { + if (changeFullscreen) + this->LeaveFullscreenMode(); + } + else { + if (changeFullscreen) { + if (FAILED(this->EnterFullscreenMode(pPresentParams, pFullscreenDisplayMode))) + return D3DERR_INVALIDCALL; + } + + D3D9WindowMessageFilter filter(m_window); + + if (!changeFullscreen) { + if (FAILED(ChangeDisplayMode(pPresentParams, pFullscreenDisplayMode))) + return D3DERR_INVALIDCALL; + } + + // Move the window so that it covers the entire output + RECT rect; + GetMonitorRect(GetDefaultMonitor(), &rect); + + ::SetWindowPos(m_window, HWND_TOPMOST, + rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, + SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOACTIVATE); + } + + m_presentParams = *pPresentParams; + + if (changeFullscreen) + SetGammaRamp(0, &m_ramp); + + CreateBackBuffers(m_presentParams.BackBufferCount); + + return D3D_OK; + } + + + HRESULT D3D9SwapChainEx::WaitForVBlank() { + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::warn("D3D9SwapChainEx::WaitForVBlank: Stub"); + + return D3D_OK; + } + + static bool validateGammaRamp(const WORD (&ramp)[256]) { + if (ramp[0] >= ramp[std::size(ramp) - 1]) { + Logger::err("validateGammaRamp: ramp inverted or flat"); + return false; + } + + for (size_t i = 1; i < std::size(ramp); i++) { + if (ramp[i] < ramp[i - 1]) { + Logger::err("validateGammaRamp: ramp not monotonically increasing"); + return false; + } + if (ramp[i] - ramp[i - 1] >= UINT16_MAX / 2) { + Logger::err("validateGammaRamp: huuuge jump"); + return false; + } + } + + return true; + } + + + void D3D9SwapChainEx::SetGammaRamp( + DWORD Flags, + const D3DGAMMARAMP* pRamp) { + D3D9DeviceLock lock = m_parent->LockDevice(); + + if (unlikely(pRamp == nullptr)) + return; + + if (unlikely(!validateGammaRamp(pRamp->red) + && !validateGammaRamp(pRamp->blue) + && !validateGammaRamp(pRamp->green))) + return; + + m_ramp = *pRamp; + + bool isIdentity = true; + + std::array cp; + + for (uint32_t i = 0; i < NumControlPoints; i++) { + uint16_t identity = MapGammaControlPoint(float(i) / float(NumControlPoints - 1)); + + cp[i].r = pRamp->red[i]; + cp[i].g = pRamp->green[i]; + cp[i].b = pRamp->blue[i]; + cp[i].a = 0; + + isIdentity &= cp[i].r == identity + && cp[i].g == identity + && cp[i].b == identity; + } + + if (!isIdentity && !m_presentParams.Windowed) + m_blitter->setGammaRamp(NumControlPoints, cp.data()); + else + m_blitter->setGammaRamp(0, nullptr); + } + + + void D3D9SwapChainEx::GetGammaRamp(D3DGAMMARAMP* pRamp) { + D3D9DeviceLock lock = m_parent->LockDevice(); + + if (likely(pRamp != nullptr)) + *pRamp = m_ramp; + } + + + void D3D9SwapChainEx::Invalidate(HWND hWindow) { + if (hWindow == nullptr) + hWindow = m_parent->GetWindow(); + + if (m_presentParams.hDeviceWindow == hWindow) { + m_presenter = nullptr; + + m_device->waitForSubmission(&m_presentStatus); + m_device->waitForIdle(); + } + } + + + HRESULT D3D9SwapChainEx::SetDialogBoxMode(bool bEnableDialogs) { + D3D9DeviceLock lock = m_parent->LockDevice(); + + // https://docs.microsoft.com/en-us/windows/win32/api/d3d9/nf-d3d9-idirect3ddevice9-setdialogboxmode + // The MSDN documentation says this will error out under many weird conditions. + // However it doesn't appear to error at all in any of my tests of these + // cases described in the documentation. + + m_dialog = bEnableDialogs; + + return D3D_OK; + } + + + D3D9Surface* D3D9SwapChainEx::GetBackBuffer(UINT iBackBuffer) { + if (iBackBuffer >= m_presentParams.BackBufferCount) + return nullptr; + + return m_backBuffers[iBackBuffer].ptr(); + } + + + void D3D9SwapChainEx::NormalizePresentParameters(D3DPRESENT_PARAMETERS* pPresentParams) { + if (pPresentParams->hDeviceWindow == nullptr) + pPresentParams->hDeviceWindow = m_parent->GetWindow(); + + pPresentParams->BackBufferCount = std::max(pPresentParams->BackBufferCount, 1u); + + const int32_t forcedMSAA = m_parent->GetOptions()->forceSwapchainMSAA; + if (forcedMSAA != -1) { + pPresentParams->MultiSampleType = D3DMULTISAMPLE_TYPE(forcedMSAA); + pPresentParams->MultiSampleQuality = 0; + } + + if (pPresentParams->Windowed) { + GetWindowClientSize(pPresentParams->hDeviceWindow, + pPresentParams->BackBufferWidth ? nullptr : &pPresentParams->BackBufferWidth, + pPresentParams->BackBufferHeight ? nullptr : &pPresentParams->BackBufferHeight); + } + else { + GetMonitorClientSize(GetDefaultMonitor(), + pPresentParams->BackBufferWidth ? nullptr : &pPresentParams->BackBufferWidth, + pPresentParams->BackBufferHeight ? nullptr : &pPresentParams->BackBufferHeight); + } + + if (pPresentParams->BackBufferFormat == D3DFMT_UNKNOWN) + pPresentParams->BackBufferFormat = D3DFMT_X8R8G8B8; + + if (env::getEnvVar("DXVK_FORCE_WINDOWED") == "1") + pPresentParams->Windowed = TRUE; + } + + + void D3D9SwapChainEx::PresentImage(UINT SyncInterval) { + m_parent->Flush(); + + // Retrieve the image and image view to present + auto swapImage = m_backBuffers[0]->GetCommonTexture()->GetImage(); + auto swapImageView = m_backBuffers[0]->GetImageView(false); + + // Bump our frame id. + ++m_frameId; + + for (uint32_t i = 0; i < SyncInterval || i < 1; i++) { + SynchronizePresent(); + + // Presentation semaphores and WSI swap chain image + vk::PresenterInfo info = m_presenter->info(); + vk::PresenterSync sync; + + uint32_t imageIndex = 0; + + VkResult status = m_presenter->acquireNextImage(sync, imageIndex); + + while (status != VK_SUCCESS && status != VK_SUBOPTIMAL_KHR) { + RecreateSwapChain(m_vsync); + + info = m_presenter->info(); + status = m_presenter->acquireNextImage(sync, imageIndex); + } + + m_context->beginRecording( + m_device->createCommandList()); + + VkRect2D srcRect = { + { int32_t(m_srcRect.left), int32_t(m_srcRect.top) }, + { uint32_t(m_srcRect.right - m_srcRect.left), uint32_t(m_srcRect.bottom - m_srcRect.top) } }; + + VkRect2D dstRect = { + { int32_t(m_dstRect.left), int32_t(m_dstRect.top) }, + { uint32_t(m_dstRect.right - m_dstRect.left), uint32_t(m_dstRect.bottom - m_dstRect.top) } }; + + m_blitter->presentImage(m_context.ptr(), + m_imageViews.at(imageIndex), dstRect, + swapImageView, srcRect); + + if (m_hud != nullptr) + m_hud->render(m_context, info.format, info.imageExtent); + + if (i + 1 >= SyncInterval) + m_context->signal(m_frameLatencySignal, m_frameId); + + SubmitPresent(sync, i); + } + + SyncFrameLatency(); + + // Rotate swap chain buffers so that the back + // buffer at index 0 becomes the front buffer. + for (uint32_t i = 1; i < m_backBuffers.size(); i++) + m_backBuffers[i]->Swap(m_backBuffers[i - 1].ptr()); + + m_parent->m_flags.set(D3D9DeviceFlag::DirtyFramebuffer); + } + + + void D3D9SwapChainEx::SubmitPresent(const vk::PresenterSync& Sync, uint32_t FrameId) { + // Present from CS thread so that we don't + // have to synchronize with it first. + m_presentStatus.result = VK_NOT_READY; + + m_parent->EmitCs([this, + cFrameId = FrameId, + cSync = Sync, + cHud = m_hud, + cCommandList = m_context->endRecording() + ] (DxvkContext* ctx) { + m_device->submitCommandList(cCommandList, + cSync.acquire, cSync.present); + + if (cHud != nullptr && !cFrameId) + cHud->update(); + + m_device->presentImage(m_presenter, &m_presentStatus); + }); + + m_parent->FlushCsChunk(); + } + + + void D3D9SwapChainEx::SynchronizePresent() { + // Recreate swap chain if the previous present call failed + VkResult status = m_device->waitForSubmission(&m_presentStatus); + + if (status != VK_SUCCESS) + RecreateSwapChain(m_vsync); + } + + + void D3D9SwapChainEx::RecreateSwapChain(BOOL Vsync) { + // Ensure that we can safely destroy the swap chain + m_device->waitForSubmission(&m_presentStatus); + m_device->waitForIdle(); + + m_presentStatus.result = VK_SUCCESS; + + vk::PresenterDesc presenterDesc; + presenterDesc.imageExtent = GetPresentExtent(); + presenterDesc.imageCount = PickImageCount(m_presentParams.BackBufferCount + 1); + presenterDesc.numFormats = PickFormats(EnumerateFormat(m_presentParams.BackBufferFormat), presenterDesc.formats); + presenterDesc.numPresentModes = PickPresentModes(Vsync, presenterDesc.presentModes); + presenterDesc.fullScreenExclusive = PickFullscreenMode(); + + if (m_presenter->recreateSwapChain(presenterDesc) != VK_SUCCESS) + throw DxvkError("D3D9SwapChainEx: Failed to recreate swap chain"); + + CreateRenderTargetViews(); + } + + + void D3D9SwapChainEx::CreatePresenter() { + // Ensure that we can safely destroy the swap chain + m_device->waitForSubmission(&m_presentStatus); + m_device->waitForIdle(); + + m_presentStatus.result = VK_SUCCESS; + + DxvkDeviceQueue graphicsQueue = m_device->queues().graphics; + + vk::PresenterDevice presenterDevice; + presenterDevice.queueFamily = graphicsQueue.queueFamily; + presenterDevice.queue = graphicsQueue.queueHandle; + presenterDevice.adapter = m_device->adapter()->handle(); + + vk::PresenterDesc presenterDesc; + presenterDesc.imageExtent = GetPresentExtent(); + presenterDesc.imageCount = PickImageCount(m_presentParams.BackBufferCount + 1); + presenterDesc.numFormats = PickFormats(EnumerateFormat(m_presentParams.BackBufferFormat), presenterDesc.formats); + presenterDesc.numPresentModes = PickPresentModes(false, presenterDesc.presentModes); + presenterDesc.fullScreenExclusive = PickFullscreenMode(); + + m_presenter = new vk::Presenter(m_window, + m_device->adapter()->vki(), + m_device->vkd(), + presenterDevice, + presenterDesc); + + m_presenter->setFrameRateLimit(m_parent->GetOptions()->maxFrameRate); + m_presenter->setFrameRateLimiterRefreshRate(m_displayRefreshRate); + + CreateRenderTargetViews(); + } + + + void D3D9SwapChainEx::CreateRenderTargetViews() { + vk::PresenterInfo info = m_presenter->info(); + + m_imageViews.clear(); + m_imageViews.resize(info.imageCount); + + DxvkImageCreateInfo imageInfo; + imageInfo.type = VK_IMAGE_TYPE_2D; + imageInfo.format = info.format.format; + imageInfo.flags = 0; + imageInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT; + imageInfo.extent = { info.imageExtent.width, info.imageExtent.height, 1 }; + imageInfo.numLayers = 1; + imageInfo.mipLevels = 1; + imageInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + imageInfo.stages = 0; + imageInfo.access = 0; + imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; + imageInfo.layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + imageInfo.shared = VK_TRUE; + + DxvkImageViewCreateInfo viewInfo; + viewInfo.type = VK_IMAGE_VIEW_TYPE_2D; + viewInfo.format = info.format.format; + viewInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + viewInfo.aspect = VK_IMAGE_ASPECT_COLOR_BIT; + viewInfo.minLevel = 0; + viewInfo.numLevels = 1; + viewInfo.minLayer = 0; + viewInfo.numLayers = 1; + + for (uint32_t i = 0; i < info.imageCount; i++) { + VkImage imageHandle = m_presenter->getImage(i).image; + + Rc image = new DxvkImage( + m_device.ptr(), imageInfo, imageHandle); + + m_imageViews[i] = new DxvkImageView( + m_device->vkd(), image, viewInfo); + } + } + + + void D3D9SwapChainEx::DestroyBackBuffers() { + for (auto& backBuffer : m_backBuffers) + backBuffer->ClearContainer(); + + m_backBuffers.clear(); + } + + + void D3D9SwapChainEx::CreateBackBuffers(uint32_t NumBackBuffers) { + // Explicitly destroy current swap image before + // creating a new one to free up resources + DestroyBackBuffers(); + + int NumFrontBuffer = m_parent->GetOptions()->noExplicitFrontBuffer ? 0 : 1; + m_backBuffers.resize(NumBackBuffers + NumFrontBuffer); + + // Create new back buffer + D3D9_COMMON_TEXTURE_DESC desc; + desc.Width = std::max(m_presentParams.BackBufferWidth, 1u); + desc.Height = std::max(m_presentParams.BackBufferHeight, 1u); + desc.Depth = 1; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = EnumerateFormat(m_presentParams.BackBufferFormat); + desc.MultiSample = m_presentParams.MultiSampleType; + desc.MultisampleQuality = m_presentParams.MultiSampleQuality; + desc.Pool = D3DPOOL_DEFAULT; + desc.Usage = D3DUSAGE_RENDERTARGET; + desc.Discard = FALSE; + desc.IsBackBuffer = TRUE; + desc.IsAttachmentOnly = FALSE; + + for (uint32_t i = 0; i < m_backBuffers.size(); i++) + m_backBuffers[i] = new D3D9Surface(m_parent, &desc, this, nullptr); + + auto swapImage = m_backBuffers[0]->GetCommonTexture()->GetImage(); + + // Initialize the image so that we can use it. Clearing + // to black prevents garbled output for the first frame. + VkImageSubresourceRange subresources; + subresources.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + subresources.baseMipLevel = 0; + subresources.levelCount = 1; + subresources.baseArrayLayer = 0; + subresources.layerCount = 1; + + m_context->beginRecording( + m_device->createCommandList()); + + for (uint32_t i = 0; i < m_backBuffers.size(); i++) { + m_context->initImage( + m_backBuffers[i]->GetCommonTexture()->GetImage(), + subresources, VK_IMAGE_LAYOUT_UNDEFINED); + } + + m_device->submitCommandList( + m_context->endRecording(), + VK_NULL_HANDLE, + VK_NULL_HANDLE); + } + + + void D3D9SwapChainEx::CreateBlitter() { + m_blitter = new DxvkSwapchainBlitter(m_device); + } + + + void D3D9SwapChainEx::CreateHud() { + m_hud = hud::Hud::createHud(m_device); + + if (m_hud != nullptr) { + m_hud->addItem("api", 1, GetApiName()); + m_hud->addItem("samplers", -1, m_parent); + } + } + + + void D3D9SwapChainEx::InitRamp() { + for (uint32_t i = 0; i < NumControlPoints; i++) { + DWORD identity = DWORD(MapGammaControlPoint(float(i) / float(NumControlPoints - 1))); + + m_ramp.red[i] = identity; + m_ramp.green[i] = identity; + m_ramp.blue[i] = identity; + } + } + + + void D3D9SwapChainEx::SyncFrameLatency() { + // Wait for the sync event so that we respect the maximum frame latency + m_frameLatencySignal->wait(m_frameId - GetActualFrameLatency()); + } + + + uint32_t D3D9SwapChainEx::GetActualFrameLatency() { + uint32_t maxFrameLatency = m_parent->GetFrameLatency(); + + if (m_frameLatencyCap) + maxFrameLatency = std::min(maxFrameLatency, m_frameLatencyCap); + + maxFrameLatency = std::min(maxFrameLatency, m_presentParams.BackBufferCount + 1); + return maxFrameLatency; + } + + + uint32_t D3D9SwapChainEx::PickFormats( + D3D9Format Format, + VkSurfaceFormatKHR* pDstFormats) { + uint32_t n = 0; + + switch (Format) { + default: + Logger::warn(str::format("D3D9SwapChainEx: Unexpected format: ", Format)); + [[fallthrough]]; + + case D3D9Format::A8R8G8B8: + case D3D9Format::X8R8G8B8: + case D3D9Format::A8B8G8R8: + case D3D9Format::X8B8G8R8: { + pDstFormats[n++] = { VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }; + pDstFormats[n++] = { VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }; + } break; + + case D3D9Format::A2R10G10B10: + case D3D9Format::A2B10G10R10: { + pDstFormats[n++] = { VK_FORMAT_A2B10G10R10_UNORM_PACK32, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }; + pDstFormats[n++] = { VK_FORMAT_A2R10G10B10_UNORM_PACK32, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }; + } break; + + case D3D9Format::X1R5G5B5: + case D3D9Format::A1R5G5B5: { + pDstFormats[n++] = { VK_FORMAT_B5G5R5A1_UNORM_PACK16, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }; + pDstFormats[n++] = { VK_FORMAT_R5G5B5A1_UNORM_PACK16, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }; + pDstFormats[n++] = { VK_FORMAT_A1R5G5B5_UNORM_PACK16, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }; + } break; + + case D3D9Format::R5G6B5: { + pDstFormats[n++] = { VK_FORMAT_B5G6R5_UNORM_PACK16, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }; + pDstFormats[n++] = { VK_FORMAT_R5G6B5_UNORM_PACK16, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }; + } break; + } + + return n; + } + + + uint32_t D3D9SwapChainEx::PickPresentModes( + BOOL Vsync, + VkPresentModeKHR* pDstModes) { + uint32_t n = 0; + + if (Vsync) { + if (m_parent->GetOptions()->tearFree == Tristate::False) + pDstModes[n++] = VK_PRESENT_MODE_FIFO_RELAXED_KHR; + pDstModes[n++] = VK_PRESENT_MODE_FIFO_KHR; + } else { + if (m_parent->GetOptions()->tearFree != Tristate::True) + pDstModes[n++] = VK_PRESENT_MODE_IMMEDIATE_KHR; + pDstModes[n++] = VK_PRESENT_MODE_MAILBOX_KHR; + } + + return n; + } + + + uint32_t D3D9SwapChainEx::PickImageCount( + UINT Preferred) { + int32_t option = m_parent->GetOptions()->numBackBuffers; + return option > 0 ? uint32_t(option) : uint32_t(Preferred); + } + + + void D3D9SwapChainEx::NotifyDisplayRefreshRate( + double RefreshRate) { + m_displayRefreshRate = RefreshRate; + + if (m_presenter != nullptr) + m_presenter->setFrameRateLimiterRefreshRate(RefreshRate); + } + + + HRESULT D3D9SwapChainEx::EnterFullscreenMode( + D3DPRESENT_PARAMETERS* pPresentParams, + const D3DDISPLAYMODEEX* pFullscreenDisplayMode) { + // Find a display mode that matches what we need + ::GetWindowRect(m_window, &m_windowState.rect); + + if (FAILED(ChangeDisplayMode(pPresentParams, pFullscreenDisplayMode))) { + Logger::err("D3D9: EnterFullscreenMode: Failed to change display mode"); + return D3DERR_INVALIDCALL; + } + + // Testing shows we shouldn't hook WM_NCCALCSIZE but we shouldn't change + // windows style either. + // + // Some games restore window styles after we have changed it, so hooking is + // also required. Doing it will allow us to create fullscreen windows + // regardless of their style and it also appears to work on Windows. + HookWindowProc(m_window, this); + + D3D9WindowMessageFilter filter(m_window); + + // Change the window flags to remove the decoration etc. + LONG style = ::GetWindowLongW(m_window, GWL_STYLE); + LONG exstyle = ::GetWindowLongW(m_window, GWL_EXSTYLE); + + m_windowState.style = style; + m_windowState.exstyle = exstyle; + + style &= ~WS_OVERLAPPEDWINDOW; + exstyle &= ~WS_EX_OVERLAPPEDWINDOW; + + ::SetWindowLongW(m_window, GWL_STYLE, style); + ::SetWindowLongW(m_window, GWL_EXSTYLE, exstyle); + + // Move the window so that it covers the entire output + RECT rect; + GetMonitorRect(GetDefaultMonitor(), &rect); + + ::SetWindowPos(m_window, HWND_TOPMOST, + rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, + SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOACTIVATE); + + m_monitor = GetDefaultMonitor(); + return D3D_OK; + } + + + HRESULT D3D9SwapChainEx::LeaveFullscreenMode() { + if (!IsWindow(m_window)) + return D3DERR_INVALIDCALL; + + if (FAILED(RestoreDisplayMode(m_monitor))) + Logger::warn("D3D9: LeaveFullscreenMode: Failed to restore display mode"); + + m_monitor = nullptr; + + ResetWindowProc(m_window); + + // Only restore the window style if the application hasn't + // changed them. This is in line with what native D3D9 does. + LONG curStyle = ::GetWindowLongW(m_window, GWL_STYLE) & ~WS_VISIBLE; + LONG curExstyle = ::GetWindowLongW(m_window, GWL_EXSTYLE) & ~WS_EX_TOPMOST; + + if (curStyle == (m_windowState.style & ~(WS_VISIBLE | WS_OVERLAPPEDWINDOW)) + && curExstyle == (m_windowState.exstyle & ~(WS_EX_TOPMOST | WS_EX_OVERLAPPEDWINDOW))) { + ::SetWindowLongW(m_window, GWL_STYLE, m_windowState.style); + ::SetWindowLongW(m_window, GWL_EXSTYLE, m_windowState.exstyle); + } + + // Restore window position and apply the style + const RECT rect = m_windowState.rect; + + ::SetWindowPos(m_window, 0, + rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, + SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOACTIVATE); + + return D3D_OK; + } + + + HRESULT D3D9SwapChainEx::ChangeDisplayMode( + D3DPRESENT_PARAMETERS* pPresentParams, + const D3DDISPLAYMODEEX* pFullscreenDisplayMode) { + D3DDISPLAYMODEEX mode; + + if (pFullscreenDisplayMode) { + mode = *pFullscreenDisplayMode; + } else { + mode.Width = pPresentParams->BackBufferWidth; + mode.Height = pPresentParams->BackBufferHeight; + mode.Format = pPresentParams->BackBufferFormat; + mode.RefreshRate = pPresentParams->FullScreen_RefreshRateInHz; + mode.ScanLineOrdering = D3DSCANLINEORDERING_PROGRESSIVE; + mode.Size = sizeof(D3DDISPLAYMODEEX); + } + + DEVMODEW devMode = { }; + devMode.dmSize = sizeof(devMode); + devMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL; + devMode.dmPelsWidth = mode.Width; + devMode.dmPelsHeight = mode.Height; + devMode.dmBitsPerPel = GetMonitorFormatBpp(EnumerateFormat(mode.Format)); + + if (mode.RefreshRate != 0) { + devMode.dmFields |= DM_DISPLAYFREQUENCY; + devMode.dmDisplayFrequency = mode.RefreshRate; + } + + HMONITOR monitor = GetDefaultMonitor(); + + if (!SetMonitorDisplayMode(monitor, &devMode)) + return D3DERR_NOTAVAILABLE; + + devMode.dmFields = DM_DISPLAYFREQUENCY; + + if (GetMonitorDisplayMode(monitor, ENUM_CURRENT_SETTINGS, &devMode)) + NotifyDisplayRefreshRate(double(devMode.dmDisplayFrequency)); + else + NotifyDisplayRefreshRate(0.0); + + return D3D_OK; + } + + + HRESULT D3D9SwapChainEx::RestoreDisplayMode(HMONITOR hMonitor) { + if (hMonitor == nullptr) + return D3DERR_INVALIDCALL; + + if (!RestoreMonitorDisplayMode()) + return D3DERR_NOTAVAILABLE; + + NotifyDisplayRefreshRate(0.0); + return D3D_OK; + } + + bool D3D9SwapChainEx::UpdatePresentRegion(const RECT* pSourceRect, const RECT* pDestRect) { + if (pSourceRect == nullptr) { + m_srcRect.top = 0; + m_srcRect.left = 0; + m_srcRect.right = m_presentParams.BackBufferWidth; + m_srcRect.bottom = m_presentParams.BackBufferHeight; + } + else + m_srcRect = *pSourceRect; + + RECT dstRect; + if (pDestRect == nullptr) { + // TODO: Should we hook WM_SIZE message for this? + UINT width, height; + GetWindowClientSize(m_window, &width, &height); + + dstRect.top = 0; + dstRect.left = 0; + dstRect.right = LONG(width); + dstRect.bottom = LONG(height); + } + else + dstRect = *pDestRect; + + bool recreate = + m_dstRect.left != dstRect.left + || m_dstRect.top != dstRect.top + || m_dstRect.right != dstRect.right + || m_dstRect.bottom != dstRect.bottom; + + m_dstRect = dstRect; + + return recreate; + } + + VkExtent2D D3D9SwapChainEx::GetPresentExtent() { + return VkExtent2D { + std::max(m_dstRect.right - m_dstRect.left, 1u), + std::max(m_dstRect.bottom - m_dstRect.top, 1u) }; + } + + + VkFullScreenExclusiveEXT D3D9SwapChainEx::PickFullscreenMode() { + return m_dialog + ? VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT + : VK_FULL_SCREEN_EXCLUSIVE_DEFAULT_EXT; + } + + + std::string D3D9SwapChainEx::GetApiName() { + return this->GetParent()->IsExtended() ? "D3D9Ex" : "D3D9"; + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_swapchain.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_swapchain.h new file mode 100644 index 00000000000..150578ca44a --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_swapchain.h @@ -0,0 +1,197 @@ +#pragma once + +#include "d3d9_device_child.h" +#include "d3d9_device.h" +#include "d3d9_format.h" + +#include "../dxvk/hud/dxvk_hud.h" + +#include "../dxvk/dxvk_swapchain_blitter.h" + +#include "../util/sync/sync_signal.h" + +#include + +namespace dxvk { + + class D3D9Surface; + + using D3D9SwapChainExBase = D3D9DeviceChild; + class D3D9SwapChainEx final : public D3D9SwapChainExBase { + static constexpr uint32_t NumControlPoints = 256; + public: + + D3D9SwapChainEx( + D3D9DeviceEx* pDevice, + D3DPRESENT_PARAMETERS* pPresentParams, + const D3DDISPLAYMODEEX* pFullscreenDisplayMode); + + ~D3D9SwapChainEx(); + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject); + + HRESULT STDMETHODCALLTYPE Present( + const RECT* pSourceRect, + const RECT* pDestRect, + HWND hDestWindowOverride, + const RGNDATA* pDirtyRegion, + DWORD dwFlags); + + HRESULT STDMETHODCALLTYPE GetFrontBufferData(IDirect3DSurface9* pDestSurface); + + HRESULT STDMETHODCALLTYPE GetBackBuffer( + UINT iBackBuffer, + D3DBACKBUFFER_TYPE Type, + IDirect3DSurface9** ppBackBuffer); + + HRESULT STDMETHODCALLTYPE GetRasterStatus(D3DRASTER_STATUS* pRasterStatus); + + HRESULT STDMETHODCALLTYPE GetDisplayMode(D3DDISPLAYMODE* pMode); + + HRESULT STDMETHODCALLTYPE GetPresentParameters(D3DPRESENT_PARAMETERS* pPresentationParameters); + + HRESULT STDMETHODCALLTYPE GetLastPresentCount(UINT* pLastPresentCount); + + HRESULT STDMETHODCALLTYPE GetPresentStats(D3DPRESENTSTATS* pPresentationStatistics); + + HRESULT STDMETHODCALLTYPE GetDisplayModeEx(D3DDISPLAYMODEEX* pMode, D3DDISPLAYROTATION* pRotation); + + HRESULT Reset( + D3DPRESENT_PARAMETERS* pPresentParams, + D3DDISPLAYMODEEX* pFullscreenDisplayMode); + + HRESULT WaitForVBlank(); + + void SetGammaRamp( + DWORD Flags, + const D3DGAMMARAMP* pRamp); + + void GetGammaRamp(D3DGAMMARAMP* pRamp); + + void Invalidate(HWND hWindow); + + HRESULT SetDialogBoxMode(bool bEnableDialogs); + + D3D9Surface* GetBackBuffer(UINT iBackBuffer); + + const D3DPRESENT_PARAMETERS* GetPresentParams() const { return &m_presentParams; } + + void SyncFrameLatency(); + + private: + + enum BindingIds : uint32_t { + Image = 0, + Gamma = 1, + }; + + + struct WindowState { + LONG style = 0; + LONG exstyle = 0; + RECT rect = { 0, 0, 0, 0 }; + }; + + D3DPRESENT_PARAMETERS m_presentParams; + D3DGAMMARAMP m_ramp; + + Rc m_device; + Rc m_context; + Rc m_blitter; + + Rc m_presenter; + + Rc m_hud; + + std::vector> m_backBuffers; + + RECT m_srcRect; + RECT m_dstRect; + + DxvkSubmitStatus m_presentStatus; + + std::vector> m_imageViews; + + + uint64_t m_frameId = D3D9DeviceEx::MaxFrameLatency; + uint32_t m_frameLatencyCap = 0; + Rc m_frameLatencySignal; + + bool m_dirty = true; + bool m_vsync = true; + + bool m_dialog; + bool m_lastDialog = false; + + HWND m_window = nullptr; + HMONITOR m_monitor = nullptr; + + WindowState m_windowState; + + double m_displayRefreshRate = 0.0; + + void PresentImage(UINT PresentInterval); + + void SubmitPresent(const vk::PresenterSync& Sync, uint32_t FrameId); + + void SynchronizePresent(); + + void RecreateSwapChain( + BOOL Vsync); + + void CreatePresenter(); + + void CreateRenderTargetViews(); + + void DestroyBackBuffers(); + + void CreateBackBuffers( + uint32_t NumBackBuffers); + + void CreateBlitter(); + + void CreateHud(); + + void InitRamp(); + + uint32_t GetActualFrameLatency(); + + uint32_t PickFormats( + D3D9Format Format, + VkSurfaceFormatKHR* pDstFormats); + + uint32_t PickPresentModes( + BOOL Vsync, + VkPresentModeKHR* pDstModes); + + uint32_t PickImageCount( + UINT Preferred); + + void NormalizePresentParameters(D3DPRESENT_PARAMETERS* pPresentParams); + + void NotifyDisplayRefreshRate( + double RefreshRate); + + HRESULT EnterFullscreenMode( + D3DPRESENT_PARAMETERS* pPresentParams, + const D3DDISPLAYMODEEX* pFullscreenDisplayMode); + + HRESULT LeaveFullscreenMode(); + + HRESULT ChangeDisplayMode( + D3DPRESENT_PARAMETERS* pPresentParams, + const D3DDISPLAYMODEEX* pFullscreenDisplayMode); + + HRESULT RestoreDisplayMode(HMONITOR hMonitor); + + bool UpdatePresentRegion(const RECT* pSourceRect, const RECT* pDestRect); + + VkExtent2D GetPresentExtent(); + + VkFullScreenExclusiveEXT PickFullscreenMode(); + + std::string GetApiName(); + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_swvp_emu.cpp b/utils/dxvk-1.10.3/src/d3d9/d3d9_swvp_emu.cpp new file mode 100644 index 00000000000..40a38fdc421 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_swvp_emu.cpp @@ -0,0 +1,353 @@ +#include "d3d9_swvp_emu.h" + +#include "d3d9_device.h" +#include "d3d9_vertex_declaration.h" + +#include "../spirv/spirv_module.h" + +namespace dxvk { + + // Doesn't compare everything, only what we use in SWVP. + + size_t D3D9VertexDeclHash::operator () (const D3D9VertexElements& key) const { + DxvkHashState hash; + + std::hash bytehash; + std::hash wordhash; + + for (auto& element : key) { + hash.add(wordhash(element.Stream)); + hash.add(wordhash(element.Offset)); + hash.add(bytehash(element.Type)); + hash.add(bytehash(element.Method)); + hash.add(bytehash(element.Usage)); + hash.add(bytehash(element.UsageIndex)); + } + + return hash; + } + + bool D3D9VertexDeclEq::operator () (const D3D9VertexElements& a, const D3D9VertexElements& b) const { + if (a.size() != b.size()) + return false; + + bool equal = true; + + for (uint32_t i = 0; i < a.size(); i++) + equal &= std::memcmp(&a[i], &b[i], sizeof(a[0])) == 0; + + return equal; + } + + enum class DecltypeClass { + Float, Byte, Short, Dec, Half + }; + + enum DecltypeFlags { + Signed = 1, + Normalize = 2, + ReverseRGB = 4 + }; + + struct Decltype { + DecltypeClass Class; + uint32_t VectorCount; + uint32_t Flags; + }; + + Decltype ClassifyDecltype(D3DDECLTYPE Type) { + switch (Type) { + case D3DDECLTYPE_FLOAT1: return { DecltypeClass::Float, 1, DecltypeFlags::Signed }; + case D3DDECLTYPE_FLOAT2: return { DecltypeClass::Float, 2, DecltypeFlags::Signed }; + case D3DDECLTYPE_FLOAT3: return { DecltypeClass::Float, 3, DecltypeFlags::Signed }; + case D3DDECLTYPE_FLOAT4: return { DecltypeClass::Float, 4, DecltypeFlags::Signed }; + case D3DDECLTYPE_D3DCOLOR: return { DecltypeClass::Byte, 4, DecltypeFlags::Normalize | DecltypeFlags::ReverseRGB }; + case D3DDECLTYPE_UBYTE4: return { DecltypeClass::Byte, 4, 0 }; + case D3DDECLTYPE_SHORT2: return { DecltypeClass::Short, 2, DecltypeFlags::Signed }; + case D3DDECLTYPE_SHORT4: return { DecltypeClass::Short, 4, DecltypeFlags::Signed }; + case D3DDECLTYPE_UBYTE4N: return { DecltypeClass::Byte, 4, DecltypeFlags::Normalize }; + case D3DDECLTYPE_SHORT2N: return { DecltypeClass::Short, 2, DecltypeFlags::Signed | DecltypeFlags::Normalize }; + case D3DDECLTYPE_SHORT4N: return { DecltypeClass::Short, 4, DecltypeFlags::Signed | DecltypeFlags::Normalize }; + case D3DDECLTYPE_USHORT2N: return { DecltypeClass::Short, 2, DecltypeFlags::Normalize }; + case D3DDECLTYPE_USHORT4N: return { DecltypeClass::Short, 4, DecltypeFlags::Normalize }; + case D3DDECLTYPE_UDEC3: return { DecltypeClass::Dec, 3, 0 }; + case D3DDECLTYPE_DEC3N: return { DecltypeClass::Dec, 3, DecltypeFlags::Signed | DecltypeFlags::Normalize }; + case D3DDECLTYPE_FLOAT16_2: return { DecltypeClass::Half, 2, DecltypeFlags::Signed }; + case D3DDECLTYPE_FLOAT16_4: return { DecltypeClass::Half, 4, DecltypeFlags::Signed }; + default: return { DecltypeClass::Float, 4, DecltypeFlags::Signed }; + } + } + + class D3D9SWVPEmulatorGenerator { + + public: + + D3D9SWVPEmulatorGenerator(const std::string& name) + : m_module(spvVersion(1, 3)) { + m_entryPointId = m_module.allocateId(); + + m_module.setDebugSource( + spv::SourceLanguageUnknown, 0, + m_module.addDebugString(name.c_str()), + nullptr); + + m_module.setMemoryModel( + spv::AddressingModelLogical, + spv::MemoryModelGLSL450); + + m_module.enableCapability(spv::CapabilityGeometry); + + m_module.setExecutionMode(m_entryPointId, spv::ExecutionModeInputPoints); + m_module.setExecutionMode(m_entryPointId, spv::ExecutionModeOutputPoints); + // This has to be > 0 for some reason even though + // we will never emit a vertex + m_module.setOutputVertices(m_entryPointId, 1); + m_module.setInvocations(m_entryPointId, 1); + + m_module.functionBegin(m_module.defVoidType(), m_entryPointId, m_module.defFunctionType( + m_module.defVoidType(), 0, nullptr), spv::FunctionControlMaskNone); + m_module.opLabel(m_module.allocateId()); + } + + void compile(const D3D9VertexDecl* pDecl) { + uint32_t uint_t = m_module.defIntType(32, false); + uint32_t float_t = m_module.defFloatType(32); + uint32_t vec4_t = m_module.defVectorType(float_t, 4); + + uint32_t vec4_singular_array_t = m_module.defArrayType(vec4_t, m_module.constu32(1)); + + // Setup the buffer + uint32_t bufferSlot = getSWVPBufferSlot(); + + uint32_t arrayType = m_module.defRuntimeArrayTypeUnique(uint_t); + m_module.decorateArrayStride(arrayType, sizeof(uint32_t)); + + uint32_t buffer_t = m_module.defStructTypeUnique(1, &arrayType); + m_module.memberDecorateOffset(buffer_t, 0, 0); + m_module.decorate(buffer_t, spv::DecorationBufferBlock); + + uint32_t buffer = m_module.newVar(m_module.defPointerType(buffer_t, spv::StorageClassUniform), spv::StorageClassUniform); + m_module.decorateDescriptorSet(buffer, 0); + m_module.decorateBinding(buffer, bufferSlot); + + m_bufferResource.slot = bufferSlot; + m_bufferResource.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + m_bufferResource.view = VK_IMAGE_VIEW_TYPE_MAX_ENUM; + m_bufferResource.access = VK_ACCESS_SHADER_WRITE_BIT; + + // Load our builtins + uint32_t primitiveIdPtr = m_module.newVar(m_module.defPointerType(uint_t, spv::StorageClassInput), spv::StorageClassInput); + m_module.decorateBuiltIn(primitiveIdPtr, spv::BuiltInPrimitiveId); + m_entryPointInterfaces.push_back(primitiveIdPtr); + + uint32_t primitiveId = m_module.opLoad(uint_t, primitiveIdPtr); + + // The size of any given vertex + uint32_t vertexSize = m_module.constu32(pDecl->GetSize() / sizeof(uint32_t)); + + //The offset of this vertex from the beginning of the buffer + uint32_t thisVertexOffset = m_module.opIMul(uint_t, vertexSize, primitiveId); + + + for (auto& element : pDecl->GetElements()) { + // Load the slot associated with this element + DxsoSemantic semantic = { DxsoUsage(element.Usage), element.UsageIndex }; + + uint32_t elementPtr; + uint32_t elementVar; + + elementPtr = m_module.newVar(m_module.defPointerType(vec4_singular_array_t, spv::StorageClassInput), spv::StorageClassInput); + if ((semantic.usage == DxsoUsage::Position || semantic.usage == DxsoUsage::PositionT) && element.UsageIndex == 0) { + // Load from builtin + m_module.decorateBuiltIn(elementPtr, spv::BuiltInPosition); + } + else { + // Load from slot + uint32_t slotIdx = RegisterLinkerSlot(semantic); + + m_module.decorateLocation(elementPtr, slotIdx); + m_inputMask |= 1u << slotIdx; + } + + uint32_t zero = m_module.constu32(0); + elementVar = m_module.opAccessChain(m_module.defPointerType(vec4_t, spv::StorageClassInput), elementPtr, 1, &zero); + elementVar = m_module.opLoad(vec4_t, elementVar); + + m_entryPointInterfaces.push_back(elementPtr); + + // The offset of this element from the beginning of any given vertex + uint32_t perVertexElementOffset = m_module.constu32(element.Offset / sizeof(uint32_t)); + + // The offset of this element from the beginning of the buffer for **THIS** vertex + uint32_t elementOffset = m_module.opIAdd(uint_t, thisVertexOffset, perVertexElementOffset); + + // Write to the buffer at the element offset for each part of the vector. + Decltype elementInfo = ClassifyDecltype(D3DDECLTYPE(element.Type)); + + if (elementInfo.Class == DecltypeClass::Dec) { + // TODO! + Logger::warn("Encountered DEC3/UDEC3N class, ignoring..."); + continue; + } + + uint32_t vecn_t = m_module.defVectorType(float_t, elementInfo.VectorCount); + uint32_t componentSet; + + // Modifiers... + if (elementInfo.Flags & DecltypeFlags::ReverseRGB) { + std::array indices = { 2, 1, 0, 3 }; + componentSet = m_module.opVectorShuffle(vecn_t, elementVar, elementVar, elementInfo.VectorCount, indices.data()); + } + else { + std::array indices = { 0, 1, 2, 3 }; + componentSet = m_module.opVectorShuffle(vecn_t, elementVar, elementVar, elementInfo.VectorCount, indices.data()); + } + + if (elementInfo.Flags & DecltypeFlags::Normalize) + componentSet = m_module.opVectorTimesScalar(vecn_t, componentSet, m_module.constf32(255.0f)); + + + bool isSigned = elementInfo.Flags & DecltypeFlags::Signed; + + // Convert the component to the correct type/value. + switch (elementInfo.Class) { + case DecltypeClass::Float: break; // Do nothing! + case DecltypeClass::Byte: { + m_module.enableCapability(spv::CapabilityInt8); + + uint32_t type = m_module.defIntType(8, isSigned); + type = m_module.defVectorType(type, elementInfo.VectorCount); + + componentSet = isSigned + ? m_module.opConvertFtoS(type, componentSet) + : m_module.opConvertFtoU(type, componentSet); + + break; + } + case DecltypeClass::Short: { + m_module.enableCapability(spv::CapabilityInt16); + + uint32_t type = m_module.defIntType(16, isSigned); + type = m_module.defVectorType(type, elementInfo.VectorCount); + + componentSet = isSigned + ? m_module.opConvertFtoS(type, componentSet) + : m_module.opConvertFtoU(type, componentSet); + + break; + } + case DecltypeClass::Half: { + m_module.enableCapability(spv::CapabilityFloat16); + + uint32_t type = m_module.defFloatType(16); + type = m_module.defVectorType(type, elementInfo.VectorCount); + componentSet = m_module.opFConvert(type, componentSet); + + break; + } + case DecltypeClass::Dec: { + // TODO! + break; + } + } + + // Bitcast to dwords before we write. + uint32_t dwordCount = GetDecltypeSize(D3DDECLTYPE(element.Type)) / sizeof(uint32_t); + uint32_t dwordVector = m_module.opBitcast( + m_module.defVectorType(uint_t, dwordCount), + componentSet); + + // Finally write each dword to the buffer! + for (uint32_t i = 0; i < dwordCount; i++) { + std::array bufferIndices = { m_module.constu32(0), elementOffset }; + + uint32_t writeDest = m_module.opAccessChain(m_module.defPointerType(uint_t, spv::StorageClassUniform), buffer, bufferIndices.size(), bufferIndices.data()); + uint32_t currentDword = m_module.opCompositeExtract(uint_t, dwordVector, 1, &i); + + m_module.opStore(writeDest, currentDword); + + elementOffset = m_module.opIAdd(uint_t, elementOffset, m_module.constu32(1)); + } + } + } + + Rc finalize() { + m_module.opReturn(); + m_module.functionEnd(); + + m_module.addEntryPoint(m_entryPointId, + spv::ExecutionModelGeometry, "main", + m_entryPointInterfaces.size(), + m_entryPointInterfaces.data()); + m_module.setDebugName(m_entryPointId, "main"); + + DxvkShaderCreateInfo info; + info.stage = VK_SHADER_STAGE_GEOMETRY_BIT; + info.resourceSlotCount = 1; + info.resourceSlots = &m_bufferResource; + info.inputMask = m_inputMask; + + return new DxvkShader(info, m_module.compile()); + } + + private: + + SpirvModule m_module; + + std::vector m_entryPointInterfaces; + uint32_t m_entryPointId = 0; + uint32_t m_inputMask = 0u; + DxvkResourceSlot m_bufferResource; + + }; + + Rc D3D9SWVPEmulator::GetShaderModule(D3D9DeviceEx* pDevice, const D3D9VertexDecl* pDecl) { + auto& elements = pDecl->GetElements(); + + // Use the shader's unique key for the lookup + { std::unique_lock lock(m_mutex); + + auto entry = m_modules.find(elements); + if (entry != m_modules.end()) + return entry->second; + } + + Sha1Hash hash = Sha1Hash::compute( + elements.data(), elements.size() * sizeof(elements[0])); + + DxvkShaderKey key = { VK_SHADER_STAGE_GEOMETRY_BIT , hash }; + std::string name = str::format("SWVP_", key.toString()); + + // This shader has not been compiled yet, so we have to create a + // new module. This takes a while, so we won't lock the structure. + D3D9SWVPEmulatorGenerator generator(name); + generator.compile(pDecl); + Rc shader = generator.finalize(); + + shader->setShaderKey(key); + pDevice->GetDXVKDevice()->registerShader(shader); + + const std::string dumpPath = env::getEnvVar("DXVK_SHADER_DUMP_PATH"); + + if (dumpPath.size() != 0) { + std::ofstream dumpStream( + str::format(dumpPath, "/", name, ".spv"), + std::ios_base::binary | std::ios_base::trunc); + + shader->dump(dumpStream); + } + + // Insert the new module into the lookup table. If another thread + // has compiled the same shader in the meantime, we should return + // that object instead and discard the newly created module. + { std::unique_lock lock(m_mutex); + + auto status = m_modules.insert({ elements, shader }); + if (!status.second) + return status.first->second; + } + + return shader; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_swvp_emu.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_swvp_emu.h new file mode 100644 index 00000000000..91aae4c2568 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_swvp_emu.h @@ -0,0 +1,38 @@ +#pragma once + +#include + +#include "d3d9_include.h" + +#include "../dxvk/dxvk_shader.h" + +namespace dxvk { + + class D3D9VertexDecl; + class D3D9DeviceEx; + + struct D3D9VertexDeclHash { + size_t operator () (const D3D9VertexElements& key) const; + }; + + struct D3D9VertexDeclEq { + bool operator () (const D3D9VertexElements& a, const D3D9VertexElements& b) const; + }; + + class D3D9SWVPEmulator { + + public: + + Rc GetShaderModule(D3D9DeviceEx* pDevice, const D3D9VertexDecl* pDecl); + + private: + + dxvk::mutex m_mutex; + + std::unordered_map< + D3D9VertexElements, Rc, + D3D9VertexDeclHash, D3D9VertexDeclEq> m_modules; + + }; + +} diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_texture.cpp b/utils/dxvk-1.10.3/src/d3d9/d3d9_texture.cpp new file mode 100644 index 00000000000..4b2371eaffa --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_texture.cpp @@ -0,0 +1,266 @@ +#include "d3d9_texture.h" + +#include "d3d9_util.h" + +namespace dxvk { + + // Direct3DTexture9 + + D3D9Texture2D::D3D9Texture2D( + D3D9DeviceEx* pDevice, + const D3D9_COMMON_TEXTURE_DESC* pDesc, + HANDLE* pSharedHandle) + : D3D9Texture2DBase( pDevice, pDesc, D3DRTYPE_TEXTURE, pSharedHandle ) { } + + + HRESULT STDMETHODCALLTYPE D3D9Texture2D::QueryInterface(REFIID riid, void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(IDirect3DResource9) + || riid == __uuidof(IDirect3DBaseTexture9) + || riid == __uuidof(IDirect3DTexture9)) { + *ppvObject = ref(this); + return S_OK; + } + + Logger::warn("D3D9Texture2D::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + D3DRESOURCETYPE STDMETHODCALLTYPE D3D9Texture2D::GetType() { + return D3DRTYPE_TEXTURE; + } + + + HRESULT STDMETHODCALLTYPE D3D9Texture2D::GetLevelDesc(UINT Level, D3DSURFACE_DESC *pDesc) { + if (unlikely(Level >= m_texture.ExposedMipLevels())) + return D3DERR_INVALIDCALL; + + return GetSubresource(Level)->GetDesc(pDesc); + } + + + HRESULT STDMETHODCALLTYPE D3D9Texture2D::GetSurfaceLevel(UINT Level, IDirect3DSurface9** ppSurfaceLevel) { + InitReturnPtr(ppSurfaceLevel); + + if (unlikely(Level >= m_texture.ExposedMipLevels())) + return D3DERR_INVALIDCALL; + + if (unlikely(ppSurfaceLevel == nullptr)) + return D3DERR_INVALIDCALL; + + *ppSurfaceLevel = ref(GetSubresource(Level)); + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9Texture2D::LockRect(UINT Level, D3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) { + if (unlikely(Level >= m_texture.ExposedMipLevels())) + return D3DERR_INVALIDCALL; + + return GetSubresource(Level)->LockRect(pLockedRect, pRect, Flags); + } + + + HRESULT STDMETHODCALLTYPE D3D9Texture2D::UnlockRect(UINT Level) { + if (unlikely(Level >= m_texture.ExposedMipLevels())) + return D3DERR_INVALIDCALL; + + return GetSubresource(Level)->UnlockRect(); + } + + + HRESULT STDMETHODCALLTYPE D3D9Texture2D::AddDirtyRect(CONST RECT* pDirtyRect) { + if (pDirtyRect) { + D3DBOX box = { UINT(pDirtyRect->left), UINT(pDirtyRect->top), UINT(pDirtyRect->right), UINT(pDirtyRect->bottom), 0, 1 }; + m_texture.AddDirtyBox(&box, 0); + } else { + m_texture.AddDirtyBox(nullptr, 0); + } + + // Some games keep using the pointer returned in LockRect() after calling Unlock() + // and purely rely on AddDirtyRect to notify D3D9 that contents have changed. + // We have no way of knowing which mip levels were actually changed. + m_texture.SetAllNeedUpload(); + return D3D_OK; + } + + + // Direct3DVolumeTexture9 + + + D3D9Texture3D::D3D9Texture3D( + D3D9DeviceEx* pDevice, + const D3D9_COMMON_TEXTURE_DESC* pDesc) + : D3D9Texture3DBase( pDevice, pDesc, D3DRTYPE_VOLUMETEXTURE, nullptr ) { } + + + HRESULT STDMETHODCALLTYPE D3D9Texture3D::QueryInterface(REFIID riid, void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(IDirect3DResource9) + || riid == __uuidof(IDirect3DBaseTexture9) + || riid == __uuidof(IDirect3DVolumeTexture9)) { + *ppvObject = ref(this); + return S_OK; + } + + Logger::warn("D3D9Texture3D::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + D3DRESOURCETYPE STDMETHODCALLTYPE D3D9Texture3D::GetType() { + return D3DRTYPE_VOLUMETEXTURE; + } + + + HRESULT STDMETHODCALLTYPE D3D9Texture3D::GetLevelDesc(UINT Level, D3DVOLUME_DESC *pDesc) { + if (unlikely(Level >= m_texture.ExposedMipLevels())) + return D3DERR_INVALIDCALL; + + return GetSubresource(Level)->GetDesc(pDesc); + } + + + HRESULT STDMETHODCALLTYPE D3D9Texture3D::GetVolumeLevel(UINT Level, IDirect3DVolume9** ppVolumeLevel) { + InitReturnPtr(ppVolumeLevel); + + if (unlikely(Level >= m_texture.ExposedMipLevels())) + return D3DERR_INVALIDCALL; + + if (unlikely(ppVolumeLevel == nullptr)) + return D3DERR_INVALIDCALL; + + *ppVolumeLevel = ref(GetSubresource(Level)); + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9Texture3D::LockBox(UINT Level, D3DLOCKED_BOX* pLockedBox, CONST D3DBOX* pBox, DWORD Flags) { + if (unlikely(Level >= m_texture.ExposedMipLevels())) + return D3DERR_INVALIDCALL; + + return GetSubresource(Level)->LockBox(pLockedBox, pBox, Flags); + } + + + HRESULT STDMETHODCALLTYPE D3D9Texture3D::UnlockBox(UINT Level) { + if (unlikely(Level >= m_texture.ExposedMipLevels())) + return D3DERR_INVALIDCALL; + + return GetSubresource(Level)->UnlockBox(); + } + + HRESULT STDMETHODCALLTYPE D3D9Texture3D::AddDirtyBox(CONST D3DBOX* pDirtyBox) { + m_texture.AddDirtyBox(pDirtyBox, 0); + + // Some games keep using the pointer returned in LockBox() after calling Unlock() + // and purely rely on AddDirtyBox to notify D3D9 that contents have changed. + // We have no way of knowing which mip levels were actually changed. + m_texture.SetAllNeedUpload(); + return D3D_OK; + } + + + // Direct3DCubeTexture9 + + + D3D9TextureCube::D3D9TextureCube( + D3D9DeviceEx* pDevice, + const D3D9_COMMON_TEXTURE_DESC* pDesc) + : D3D9TextureCubeBase( pDevice, pDesc, D3DRTYPE_CUBETEXTURE, nullptr ) { } + + + HRESULT STDMETHODCALLTYPE D3D9TextureCube::QueryInterface(REFIID riid, void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(IDirect3DResource9) + || riid == __uuidof(IDirect3DBaseTexture9) + || riid == __uuidof(IDirect3DCubeTexture9)) { + *ppvObject = ref(this); + return S_OK; + } + + Logger::warn("D3D9TextureCube::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + D3DRESOURCETYPE STDMETHODCALLTYPE D3D9TextureCube::GetType() { + return D3DRTYPE_CUBETEXTURE; + } + + + HRESULT STDMETHODCALLTYPE D3D9TextureCube::GetLevelDesc(UINT Level, D3DSURFACE_DESC *pDesc) { + if (unlikely(Level >= m_texture.ExposedMipLevels())) + return D3DERR_INVALIDCALL; + + return GetSubresource(Level)->GetDesc(pDesc); + } + + + HRESULT STDMETHODCALLTYPE D3D9TextureCube::GetCubeMapSurface(D3DCUBEMAP_FACES Face, UINT Level, IDirect3DSurface9** ppSurfaceLevel) { + InitReturnPtr(ppSurfaceLevel); + + if (unlikely(Level >= m_texture.ExposedMipLevels() || Face >= D3DCUBEMAP_FACES(6))) + return D3DERR_INVALIDCALL; + + if (unlikely(ppSurfaceLevel == nullptr)) + return D3DERR_INVALIDCALL; + + *ppSurfaceLevel = ref(GetSubresource(m_texture.CalcSubresource(UINT(Face), Level))); + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9TextureCube::LockRect(D3DCUBEMAP_FACES Face, UINT Level, D3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) { + if (unlikely(Face > D3DCUBEMAP_FACE_NEGATIVE_Z || Level >= m_texture.ExposedMipLevels())) + return D3DERR_INVALIDCALL; + + return GetSubresource(m_texture.CalcSubresource(UINT(Face), Level))->LockRect(pLockedRect, pRect, Flags); + } + + + HRESULT STDMETHODCALLTYPE D3D9TextureCube::UnlockRect(D3DCUBEMAP_FACES Face, UINT Level) { + if (unlikely(Face > D3DCUBEMAP_FACE_NEGATIVE_Z || Level >= m_texture.ExposedMipLevels())) + return D3DERR_INVALIDCALL; + + return GetSubresource(m_texture.CalcSubresource(UINT(Face), Level))->UnlockRect(); + } + + + HRESULT STDMETHODCALLTYPE D3D9TextureCube::AddDirtyRect(D3DCUBEMAP_FACES Face, CONST RECT* pDirtyRect) { + if (pDirtyRect) { + D3DBOX box = { UINT(pDirtyRect->left), UINT(pDirtyRect->top), UINT(pDirtyRect->right), UINT(pDirtyRect->bottom), 0, 1 }; + m_texture.AddDirtyBox(&box, Face); + } else { + m_texture.AddDirtyBox(nullptr, Face); + } + + // Some games keep using the pointer returned in LockRect() after calling Unlock() + // and purely rely on AddDirtyRect to notify D3D9 that contents have changed. + // We have no way of knowing which mip levels were actually changed. + for (uint32_t m = 0; m < m_texture.Desc()->MipLevels; m++) { + m_texture.SetNeedsUpload(m_texture.CalcSubresource(Face, m), true); + } + return D3D_OK; + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_texture.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_texture.h new file mode 100644 index 00000000000..317f72ee52d --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_texture.h @@ -0,0 +1,245 @@ +#pragma once + +#include "d3d9_device.h" +#include "d3d9_surface.h" +#include "d3d9_volume.h" +#include "d3d9_util.h" + +#include +#include +#include +#include +#include + +namespace dxvk { + + template + class D3D9BaseTexture : public D3D9Resource { + + public: + + using SubresourceData = std::aligned_storage_t; + + D3D9BaseTexture( + D3D9DeviceEx* pDevice, + const D3D9_COMMON_TEXTURE_DESC* pDesc, + D3DRESOURCETYPE ResourceType, + HANDLE* pSharedHandle) + : D3D9Resource ( pDevice ) + , m_texture ( pDevice, pDesc, ResourceType, pSharedHandle ) + , m_lod ( 0 ) { + const uint32_t arraySlices = m_texture.Desc()->ArraySize; + const uint32_t mipLevels = m_texture.Desc()->MipLevels; + + m_subresources.resize(arraySlices * mipLevels); + + for (uint32_t i = 0; i < arraySlices; i++) { + for (uint32_t j = 0; j < mipLevels; j++) { + const uint32_t subresource = m_texture.CalcSubresource(i, j); + + SubresourceType* subObj = this->GetSubresource(subresource); + + new (subObj) SubresourceType( + pDevice, + &m_texture, + i, j, + this); + } + } + } + + ~D3D9BaseTexture() { + for (uint32_t i = 0; i < m_subresources.size(); i++) { + SubresourceType* subObj = this->GetSubresource(i); + subObj->~SubresourceType(); + } + } + + DWORD STDMETHODCALLTYPE SetLOD(DWORD LODNew) final { + DWORD oldLod = m_lod; + m_lod = std::min(LODNew, m_texture.Desc()->MipLevels - 1); + + if (m_lod != oldLod) { + m_texture.CreateSampleView(m_lod); + if (this->GetPrivateRefCount() > 0) + this->m_parent->MarkTextureBindingDirty(this); + } + + return oldLod; + } + + DWORD STDMETHODCALLTYPE GetLOD() final { + return m_lod; + } + + DWORD STDMETHODCALLTYPE GetLevelCount() final { + return m_texture.ExposedMipLevels(); + } + + HRESULT STDMETHODCALLTYPE SetAutoGenFilterType(D3DTEXTUREFILTERTYPE FilterType) final { + if (unlikely(FilterType == D3DTEXF_NONE)) + return D3DERR_INVALIDCALL; + + auto lock = this->m_parent->LockDevice(); + + m_texture.SetMipFilter(FilterType); + if (m_texture.IsAutomaticMip()) + this->m_parent->MarkTextureMipsDirty(&m_texture); + return D3D_OK; + } + + D3DTEXTUREFILTERTYPE STDMETHODCALLTYPE GetAutoGenFilterType() final { + return m_texture.GetMipFilter(); + } + + void STDMETHODCALLTYPE GenerateMipSubLevels() final { + if (!m_texture.NeedsMipGen()) + return; + + auto lock = this->m_parent->LockDevice(); + + this->m_parent->MarkTextureMipsUnDirty(&m_texture); + this->m_parent->EmitGenerateMips(&m_texture); + } + + void STDMETHODCALLTYPE PreLoad() final { + m_texture.PreLoadAll(); + } + + D3D9CommonTexture* GetCommonTexture() { + return &m_texture; + } + + SubresourceType* GetSubresource(UINT Subresource) { + return reinterpret_cast(&m_subresources[Subresource]); + } + + protected: + + D3D9CommonTexture m_texture; + + std::vector m_subresources; + + DWORD m_lod; + + }; + + using D3D9Texture2DBase = D3D9BaseTexture; + class D3D9Texture2D final : public D3D9Texture2DBase { + + public: + + D3D9Texture2D( + D3D9DeviceEx* pDevice, + const D3D9_COMMON_TEXTURE_DESC* pDesc, + HANDLE* pSharedHandle); + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject); + + D3DRESOURCETYPE STDMETHODCALLTYPE GetType(); + + HRESULT STDMETHODCALLTYPE GetLevelDesc(UINT Level, D3DSURFACE_DESC *pDesc); + + HRESULT STDMETHODCALLTYPE GetSurfaceLevel(UINT Level, IDirect3DSurface9** ppSurfaceLevel); + + HRESULT STDMETHODCALLTYPE LockRect(UINT Level, D3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags); + + HRESULT STDMETHODCALLTYPE UnlockRect(UINT Level); + + HRESULT STDMETHODCALLTYPE AddDirtyRect(CONST RECT* pDirtyRect); + + }; + + using D3D9Texture3DBase = D3D9BaseTexture; + class D3D9Texture3D final : public D3D9Texture3DBase { + + public: + + D3D9Texture3D( + D3D9DeviceEx* pDevice, + const D3D9_COMMON_TEXTURE_DESC* pDesc); + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject); + + D3DRESOURCETYPE STDMETHODCALLTYPE GetType(); + + HRESULT STDMETHODCALLTYPE GetLevelDesc(UINT Level, D3DVOLUME_DESC *pDesc); + + HRESULT STDMETHODCALLTYPE GetVolumeLevel(UINT Level, IDirect3DVolume9** ppSurfaceLevel); + + HRESULT STDMETHODCALLTYPE LockBox(UINT Level, D3DLOCKED_BOX* pLockedBox, CONST D3DBOX* pBox, DWORD Flags); + + HRESULT STDMETHODCALLTYPE UnlockBox(UINT Level); + + HRESULT STDMETHODCALLTYPE AddDirtyBox(CONST D3DBOX* pDirtyBox); + + }; + + using D3D9TextureCubeBase = D3D9BaseTexture; + class D3D9TextureCube final : public D3D9TextureCubeBase { + + public: + + D3D9TextureCube( + D3D9DeviceEx* pDevice, + const D3D9_COMMON_TEXTURE_DESC* pDesc); + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject); + + D3DRESOURCETYPE STDMETHODCALLTYPE GetType(); + + HRESULT STDMETHODCALLTYPE GetLevelDesc(UINT Level, D3DSURFACE_DESC *pDesc); + + HRESULT STDMETHODCALLTYPE GetCubeMapSurface(D3DCUBEMAP_FACES Face, UINT Level, IDirect3DSurface9** ppSurfaceLevel); + + HRESULT STDMETHODCALLTYPE LockRect(D3DCUBEMAP_FACES Face, UINT Level, D3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags); + + HRESULT STDMETHODCALLTYPE UnlockRect(D3DCUBEMAP_FACES Face, UINT Level); + + HRESULT STDMETHODCALLTYPE AddDirtyRect(D3DCUBEMAP_FACES Face, CONST RECT* pDirtyRect); + + }; + + static_assert(sizeof(D3D9Texture2D) == sizeof(D3D9Texture3D) && + sizeof(D3D9Texture2D) == sizeof(D3D9TextureCube)); + + inline D3D9CommonTexture* GetCommonTexture(IDirect3DBaseTexture9* ptr) { + if (ptr == nullptr) + return nullptr; + + // We can avoid needing to get the type as m_texture has the same offset + // no matter the texture type. + // The compiler is not smart enough to eliminate the call to GetType as it is + // not marked const. + return static_cast(ptr)->GetCommonTexture(); + } + + inline D3D9CommonTexture* GetCommonTexture(D3D9Surface* ptr) { + if (ptr == nullptr) + return nullptr; + + return ptr->GetCommonTexture(); + } + + inline D3D9CommonTexture* GetCommonTexture(IDirect3DSurface9* ptr) { + return GetCommonTexture(static_cast(ptr)); + } + + inline void TextureRefPrivate(IDirect3DBaseTexture9* tex, bool AddRef) { + if (tex == nullptr) + return; + + // We can avoid needing to get the type as m_refCount has the same offset + // no matter the texture type. + // The compiler is not smart enough to eliminate the call to GetType as it is + // not marked const. + return CastRefPrivate(tex, AddRef); + } + + inline void TextureChangePrivate(IDirect3DBaseTexture9*& dst, IDirect3DBaseTexture9* src) { + TextureRefPrivate(dst, false); + TextureRefPrivate(src, true); + dst = src; + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_util.cpp b/utils/dxvk-1.10.3/src/d3d9/d3d9_util.cpp new file mode 100644 index 00000000000..b5d24f44c09 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_util.cpp @@ -0,0 +1,421 @@ +#include "d3d9_util.h" + +namespace dxvk { + + typedef HRESULT (STDMETHODCALLTYPE *D3DXDisassembleShader) ( + const void* pShader, + BOOL EnableColorCode, + char* pComments, + ID3DBlob** ppDisassembly); // ppDisassembly is actually a D3DXBUFFER, but it has the exact same vtable as a ID3DBlob at the start. + + D3DXDisassembleShader g_pfnDisassembleShader = nullptr; + + HRESULT DisassembleShader( + const void* pShader, + BOOL EnableColorCode, + char* pComments, + ID3DBlob** ppDisassembly) { + if (g_pfnDisassembleShader == nullptr) { + HMODULE d3d9x = LoadLibraryA("d3dx9.dll"); + + if (d3d9x == nullptr) + d3d9x = LoadLibraryA("d3dx9_43.dll"); + + g_pfnDisassembleShader = + reinterpret_cast(GetProcAddress(d3d9x, "D3DXDisassembleShader")); + } + + if (g_pfnDisassembleShader == nullptr) + return D3DERR_INVALIDCALL; + + return g_pfnDisassembleShader( + pShader, + EnableColorCode, + pComments, + ppDisassembly); + } + + + HRESULT DecodeMultiSampleType( + const Rc& pDevice, + D3DMULTISAMPLE_TYPE MultiSample, + DWORD MultisampleQuality, + VkSampleCountFlagBits* pSampleCount) { + uint32_t sampleCount = std::max(MultiSample, 1u); + + // Check if this is a power of two... + if (sampleCount & (sampleCount - 1)) + return D3DERR_INVALIDCALL; + + if (MultiSample == D3DMULTISAMPLE_NONMASKABLE) + sampleCount = 1u << MultisampleQuality; + + const auto& limits = pDevice->properties().core.properties.limits; + VkSampleCountFlags supportedSampleCounts = limits.framebufferColorSampleCounts & limits.framebufferDepthSampleCounts; + + while (sampleCount > supportedSampleCounts) + sampleCount >>= 1; + + if (pSampleCount) + *pSampleCount = VkSampleCountFlagBits(sampleCount); + + return D3D_OK; + } + + + VkFormat GetPackedDepthStencilFormat(D3D9Format Format) { + switch (Format) { + case D3D9Format::D15S1: + return VK_FORMAT_D16_UNORM_S8_UINT; // This should never happen! + + case D3D9Format::D16: + case D3D9Format::D16_LOCKABLE: + case D3D9Format::DF16: + return VK_FORMAT_D16_UNORM; + + case D3D9Format::D24X8: + case D3D9Format::DF24: + return VK_FORMAT_X8_D24_UNORM_PACK32; + + case D3D9Format::D24X4S4: + case D3D9Format::D24FS8: + case D3D9Format::D24S8: + case D3D9Format::INTZ: + return VK_FORMAT_D24_UNORM_S8_UINT; + + case D3D9Format::D32: + case D3D9Format::D32_LOCKABLE: + case D3D9Format::D32F_LOCKABLE: + return VK_FORMAT_D32_SFLOAT; + + case D3D9Format::S8_LOCKABLE: + return VK_FORMAT_S8_UINT; + + default: + return VK_FORMAT_UNDEFINED; + } + } + + + VkFormatFeatureFlags GetImageFormatFeatures(DWORD Usage) { + VkFormatFeatureFlags features = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT; + + if (Usage & D3DUSAGE_DEPTHSTENCIL) + features |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT; + + if (Usage & D3DUSAGE_RENDERTARGET) + features |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT; + + return features; + } + + + VkImageUsageFlags GetImageUsageFlags(DWORD Usage) { + VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT; + + if (Usage & D3DUSAGE_DEPTHSTENCIL) + usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + + if (Usage & D3DUSAGE_RENDERTARGET) + usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + + return usage; + } + + + uint32_t GetVertexCount(D3DPRIMITIVETYPE type, UINT count) { + switch (type) { + default: + case D3DPT_TRIANGLELIST: return count * 3; + case D3DPT_POINTLIST: return count; + case D3DPT_LINELIST: return count * 2; + case D3DPT_LINESTRIP: return count + 1; + case D3DPT_TRIANGLESTRIP: return count + 2; + case D3DPT_TRIANGLEFAN: return count + 2; + } + } + + + DxvkInputAssemblyState DecodeInputAssemblyState(D3DPRIMITIVETYPE type) { + switch (type) { + default: + case D3DPT_TRIANGLELIST: + return { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, VK_FALSE, 0 }; + + case D3DPT_POINTLIST: + return { VK_PRIMITIVE_TOPOLOGY_POINT_LIST, VK_FALSE, 0 }; + + case D3DPT_LINELIST: + return { VK_PRIMITIVE_TOPOLOGY_LINE_LIST, VK_FALSE, 0 }; + + case D3DPT_LINESTRIP: + return { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, VK_FALSE, 0 }; + + case D3DPT_TRIANGLESTRIP: + return { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, VK_FALSE, 0 }; + + case D3DPT_TRIANGLEFAN: + return { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, VK_FALSE, 0 }; + } + } + + + VkBlendFactor DecodeBlendFactor(D3DBLEND BlendFactor, bool IsAlpha) { + switch (BlendFactor) { + default: + case D3DBLEND_ZERO: return VK_BLEND_FACTOR_ZERO; + case D3DBLEND_ONE: return VK_BLEND_FACTOR_ONE; + case D3DBLEND_SRCCOLOR: return VK_BLEND_FACTOR_SRC_COLOR; + case D3DBLEND_INVSRCCOLOR: return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR; + case D3DBLEND_SRCALPHA: return VK_BLEND_FACTOR_SRC_ALPHA; + case D3DBLEND_INVSRCALPHA: return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + case D3DBLEND_DESTALPHA: return VK_BLEND_FACTOR_DST_ALPHA; + case D3DBLEND_INVDESTALPHA: return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA; + case D3DBLEND_DESTCOLOR: return VK_BLEND_FACTOR_DST_COLOR; + case D3DBLEND_INVDESTCOLOR: return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR; + case D3DBLEND_SRCALPHASAT: return VK_BLEND_FACTOR_SRC_ALPHA_SATURATE; + case D3DBLEND_BOTHSRCALPHA: return VK_BLEND_FACTOR_SRC_ALPHA; + case D3DBLEND_BOTHINVSRCALPHA: return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + case D3DBLEND_BLENDFACTOR: return IsAlpha ? VK_BLEND_FACTOR_CONSTANT_ALPHA : VK_BLEND_FACTOR_CONSTANT_COLOR; + case D3DBLEND_INVBLENDFACTOR: return IsAlpha ? VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA : VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR; + case D3DBLEND_SRCCOLOR2: return VK_BLEND_FACTOR_SRC1_COLOR; + case D3DBLEND_INVSRCCOLOR2: return VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR; + } + } + + + VkBlendOp DecodeBlendOp(D3DBLENDOP BlendOp) { + switch (BlendOp) { + default: + case D3DBLENDOP_ADD: return VK_BLEND_OP_ADD; + case D3DBLENDOP_SUBTRACT: return VK_BLEND_OP_SUBTRACT; + case D3DBLENDOP_REVSUBTRACT: return VK_BLEND_OP_REVERSE_SUBTRACT; + case D3DBLENDOP_MIN: return VK_BLEND_OP_MIN; + case D3DBLENDOP_MAX: return VK_BLEND_OP_MAX; + } + } + + + VkFilter DecodeFilter(D3DTEXTUREFILTERTYPE Filter) { + switch (Filter) { + case D3DTEXF_NONE: + case D3DTEXF_POINT: + return VK_FILTER_NEAREST; + default: + return VK_FILTER_LINEAR; + } + } + + + D3D9MipFilter DecodeMipFilter(D3DTEXTUREFILTERTYPE Filter) { + D3D9MipFilter filter; + filter.MipsEnabled = Filter != D3DTEXF_NONE; + + switch (Filter) { + case D3DTEXF_POINT: + case D3DTEXF_NONE: + filter.MipFilter = VK_SAMPLER_MIPMAP_MODE_NEAREST; break; + default: + filter.MipFilter = VK_SAMPLER_MIPMAP_MODE_LINEAR; break; + } + + return filter; + } + + + bool IsAnisotropic(D3DTEXTUREFILTERTYPE Filter) { + return Filter == D3DTEXF_ANISOTROPIC; + } + + + VkSamplerAddressMode DecodeAddressMode(D3DTEXTUREADDRESS Mode) { + switch (Mode) { + default: + case D3DTADDRESS_WRAP: + return VK_SAMPLER_ADDRESS_MODE_REPEAT; + case D3DTADDRESS_MIRROR: + return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT; + case D3DTADDRESS_CLAMP: + return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + case D3DTADDRESS_BORDER: + return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; + case D3DTADDRESS_MIRRORONCE: + return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE; + } + } + + + VkCompareOp DecodeCompareOp(D3DCMPFUNC Func) { + switch (Func) { + default: + case D3DCMP_NEVER: return VK_COMPARE_OP_NEVER; + case D3DCMP_LESS: return VK_COMPARE_OP_LESS; + case D3DCMP_EQUAL: return VK_COMPARE_OP_EQUAL; + case D3DCMP_LESSEQUAL: return VK_COMPARE_OP_LESS_OR_EQUAL; + case D3DCMP_GREATER: return VK_COMPARE_OP_GREATER; + case D3DCMP_NOTEQUAL: return VK_COMPARE_OP_NOT_EQUAL; + case D3DCMP_GREATEREQUAL: return VK_COMPARE_OP_GREATER_OR_EQUAL; + case D3DCMP_ALWAYS: return VK_COMPARE_OP_ALWAYS; + } + } + + + VkStencilOp DecodeStencilOp(D3DSTENCILOP Op) { + switch (Op) { + default: + case D3DSTENCILOP_KEEP: return VK_STENCIL_OP_KEEP; + case D3DSTENCILOP_ZERO: return VK_STENCIL_OP_ZERO; + case D3DSTENCILOP_REPLACE: return VK_STENCIL_OP_REPLACE; + case D3DSTENCILOP_INCRSAT: return VK_STENCIL_OP_INCREMENT_AND_CLAMP; + case D3DSTENCILOP_DECRSAT: return VK_STENCIL_OP_DECREMENT_AND_CLAMP; + case D3DSTENCILOP_INVERT: return VK_STENCIL_OP_INVERT; + case D3DSTENCILOP_INCR: return VK_STENCIL_OP_INCREMENT_AND_WRAP; + case D3DSTENCILOP_DECR: return VK_STENCIL_OP_DECREMENT_AND_WRAP; + } + } + + + VkCullModeFlags DecodeCullMode(D3DCULL Mode) { + switch (Mode) { + case D3DCULL_CW: return VK_CULL_MODE_FRONT_BIT; + case D3DCULL_CCW: return VK_CULL_MODE_BACK_BIT; + default: + case D3DCULL_NONE: return VK_CULL_MODE_NONE; + } + } + + + VkPolygonMode DecodeFillMode(D3DFILLMODE Mode) { + switch (Mode) { + case D3DFILL_POINT: return VK_POLYGON_MODE_POINT; + case D3DFILL_WIREFRAME: return VK_POLYGON_MODE_LINE; + default: + case D3DFILL_SOLID: return VK_POLYGON_MODE_FILL; + } + } + + + VkIndexType DecodeIndexType(D3D9Format Format) { + return Format == D3D9Format::INDEX16 + ? VK_INDEX_TYPE_UINT16 + : VK_INDEX_TYPE_UINT32; + } + + + VkFormat DecodeDecltype(D3DDECLTYPE Type) { + switch (Type) { + case D3DDECLTYPE_FLOAT1: return VK_FORMAT_R32_SFLOAT; + case D3DDECLTYPE_FLOAT2: return VK_FORMAT_R32G32_SFLOAT; + case D3DDECLTYPE_FLOAT3: return VK_FORMAT_R32G32B32_SFLOAT; + case D3DDECLTYPE_FLOAT4: return VK_FORMAT_R32G32B32A32_SFLOAT; + case D3DDECLTYPE_D3DCOLOR: return VK_FORMAT_B8G8R8A8_UNORM; + case D3DDECLTYPE_UBYTE4: return VK_FORMAT_R8G8B8A8_USCALED; + case D3DDECLTYPE_SHORT2: return VK_FORMAT_R16G16_SSCALED; + case D3DDECLTYPE_SHORT4: return VK_FORMAT_R16G16B16A16_SSCALED; + case D3DDECLTYPE_UBYTE4N: return VK_FORMAT_R8G8B8A8_UNORM; + case D3DDECLTYPE_SHORT2N: return VK_FORMAT_R16G16_SNORM; + case D3DDECLTYPE_SHORT4N: return VK_FORMAT_R16G16B16A16_SNORM; + case D3DDECLTYPE_USHORT2N: return VK_FORMAT_R16G16_UNORM; + case D3DDECLTYPE_USHORT4N: return VK_FORMAT_R16G16B16A16_UNORM; + case D3DDECLTYPE_UDEC3: return VK_FORMAT_A2B10G10R10_USCALED_PACK32; + case D3DDECLTYPE_FLOAT16_2: return VK_FORMAT_R16G16_SFLOAT; + case D3DDECLTYPE_FLOAT16_4: return VK_FORMAT_R16G16B16A16_SFLOAT; + case D3DDECLTYPE_DEC3N: return VK_FORMAT_A2B10G10R10_SNORM_PACK32; + case D3DDECLTYPE_UNUSED: + default: return VK_FORMAT_UNDEFINED; + } + } + + void ConvertBox(D3DBOX box, VkOffset3D& offset, VkExtent3D& extent) { + offset.x = box.Left; + offset.y = box.Top; + offset.z = box.Front; + + extent.width = box.Right - box.Left; + extent.height = box.Bottom - box.Top; + extent.depth = box.Back - box.Front; + } + + void ConvertRect(RECT rect, VkOffset3D& offset, VkExtent3D& extent) { + offset.x = rect.left; + offset.y = rect.top; + offset.z = 0; + + extent.width = rect.right - rect.left; + extent.height = rect.bottom - rect.top; + extent.depth = 1; + } + + void ConvertRect(RECT rect, VkOffset2D& offset, VkExtent2D& extent) { + offset.x = rect.left; + offset.y = rect.top; + + extent.width = rect.right - rect.left; + extent.height = rect.bottom - rect.top; + } + + uint32_t GetDecltypeSize(D3DDECLTYPE Type) { + switch (Type) { + case D3DDECLTYPE_FLOAT1: return 1 * sizeof(float); + case D3DDECLTYPE_FLOAT2: return 2 * sizeof(float); + case D3DDECLTYPE_FLOAT3: return 3 * sizeof(float); + case D3DDECLTYPE_FLOAT4: return 4 * sizeof(float); + case D3DDECLTYPE_D3DCOLOR: return 1 * sizeof(DWORD); + case D3DDECLTYPE_UBYTE4: return 4 * sizeof(BYTE); + case D3DDECLTYPE_SHORT2: return 2 * sizeof(short); + case D3DDECLTYPE_SHORT4: return 4 * sizeof(short); + case D3DDECLTYPE_UBYTE4N: return 4 * sizeof(BYTE); + case D3DDECLTYPE_SHORT2N: return 2 * sizeof(short); + case D3DDECLTYPE_SHORT4N: return 4 * sizeof(short); + case D3DDECLTYPE_USHORT2N: return 2 * sizeof(short); + case D3DDECLTYPE_USHORT4N: return 4 * sizeof(short); + case D3DDECLTYPE_UDEC3: return 4; + case D3DDECLTYPE_DEC3N: return 4; + case D3DDECLTYPE_FLOAT16_2: return 2 * 2; + case D3DDECLTYPE_FLOAT16_4: return 4 * 2; + default: return 0; + } + } + + + uint32_t GetDecltypeCount(D3DDECLTYPE Type) { + switch (Type) { + case D3DDECLTYPE_FLOAT1: return 1; + case D3DDECLTYPE_FLOAT2: return 2; + case D3DDECLTYPE_FLOAT3: return 3; + case D3DDECLTYPE_FLOAT4: return 4; + case D3DDECLTYPE_D3DCOLOR: return 4; + case D3DDECLTYPE_UBYTE4: return 4; + case D3DDECLTYPE_SHORT2: return 2; + case D3DDECLTYPE_SHORT4: return 4; + case D3DDECLTYPE_UBYTE4N: return 4; + case D3DDECLTYPE_SHORT2N: return 2; + case D3DDECLTYPE_SHORT4N: return 4; + case D3DDECLTYPE_USHORT2N: return 2; + case D3DDECLTYPE_USHORT4N: return 4; + case D3DDECLTYPE_UDEC3: return 3; + case D3DDECLTYPE_DEC3N: return 3; + case D3DDECLTYPE_FLOAT16_2: return 2; + case D3DDECLTYPE_FLOAT16_4: return 4; + default: return 0; + } + } + + + bool IsDepthFormat(D3D9Format Format) { + return Format == D3D9Format::D16_LOCKABLE + || Format == D3D9Format::D32 + || Format == D3D9Format::D15S1 + || Format == D3D9Format::D24S8 + || Format == D3D9Format::D24X8 + || Format == D3D9Format::D24X4S4 + || Format == D3D9Format::D16 + || Format == D3D9Format::D32F_LOCKABLE + || Format == D3D9Format::D24FS8 + || Format == D3D9Format::D32_LOCKABLE + || Format == D3D9Format::DF16 + || Format == D3D9Format::DF24 + || Format == D3D9Format::INTZ; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_util.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_util.h new file mode 100644 index 00000000000..5899cd4c5aa --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_util.h @@ -0,0 +1,298 @@ +#pragma once + +#define D3D11_NO_HELPERS + +#include "d3d9_include.h" +#include "d3d9_caps.h" + +#include "d3d9_format.h" + +#include "../dxso/dxso_common.h" +#include "../dxvk/dxvk_device.h" + +#include "../util/util_matrix.h" +#include "../util/util_misc.h" + +#include + +namespace dxvk { + + struct D3D9ShaderMasks { + uint32_t samplerMask; + uint32_t rtMask; + }; + + static constexpr D3D9ShaderMasks FixedFunctionMask = + { 0b1111111, 0b1 }; + + struct D3D9MipFilter { + bool MipsEnabled; + VkSamplerMipmapMode MipFilter; + }; + + struct D3D9BlendState { + D3DBLEND Src; + D3DBLEND Dst; + D3DBLENDOP Op; + }; + + inline void FixupBlendState(D3D9BlendState& State) { + // Old DirectX 6 HW feature that still exists... + // Yuck! + if (unlikely(State.Src == D3DBLEND_BOTHSRCALPHA)) { + State.Src = D3DBLEND_SRCALPHA; + State.Dst = D3DBLEND_INVSRCALPHA; + } + else if (unlikely(State.Src == D3DBLEND_BOTHINVSRCALPHA)) { + State.Src = D3DBLEND_INVSRCALPHA; + State.Dst = D3DBLEND_SRCALPHA; + } + } + + inline bool InvalidSampler(DWORD Sampler) { + if (Sampler >= caps::MaxTexturesPS && Sampler < D3DDMAPSAMPLER) + return true; + + if (Sampler > D3DVERTEXTEXTURESAMPLER3) + return true; + + return false; + } + + inline DWORD RemapSamplerState(DWORD Sampler) { + if (Sampler >= D3DDMAPSAMPLER) + Sampler = caps::MaxTexturesPS + (Sampler - D3DDMAPSAMPLER); + + return Sampler; + } + + inline std::pair RemapStateSamplerShader(DWORD Sampler) { + if (Sampler >= caps::MaxTexturesPS + 1) + return std::make_pair(DxsoProgramTypes::VertexShader, Sampler - caps::MaxTexturesPS - 1); + + return std::make_pair(DxsoProgramTypes::PixelShader, Sampler); + } + + inline std::pair RemapSamplerShader(DWORD Sampler) { + Sampler = RemapSamplerState(Sampler); + + return RemapStateSamplerShader(Sampler); + } + + template + void CastRefPrivate(J* ptr, bool AddRef) { + if (ptr == nullptr) + return; + + T* castedPtr = reinterpret_cast(ptr); + AddRef ? castedPtr->AddRefPrivate() : castedPtr->ReleasePrivate(); + } + + HRESULT DisassembleShader( + const void* pShader, + BOOL EnableColorCode, + char* pComments, + ID3DBlob** ppDisassembly); + + HRESULT DecodeMultiSampleType( + const Rc& pDevice, + D3DMULTISAMPLE_TYPE MultiSample, + DWORD MultisampleQuality, + VkSampleCountFlagBits* pSampleCount); + + VkFormat GetPackedDepthStencilFormat(D3D9Format Format); + + VkFormatFeatureFlags GetImageFormatFeatures(DWORD Usage); + + VkImageUsageFlags GetImageUsageFlags(DWORD Usage); + + inline VkFormat PickSRGB(VkFormat format, VkFormat srgbFormat, bool srgb) { + return srgb ? srgbFormat : format; + } + + inline VkShaderStageFlagBits GetShaderStage(DxsoProgramType ProgramType) { + switch (ProgramType) { + case DxsoProgramTypes::VertexShader: return VK_SHADER_STAGE_VERTEX_BIT; + case DxsoProgramTypes::PixelShader: return VK_SHADER_STAGE_FRAGMENT_BIT; + default: return VkShaderStageFlagBits(0); + } + } + + inline uint32_t GetTransformIndex(D3DTRANSFORMSTATETYPE Type) { + if (Type == D3DTS_VIEW) + return 0; + + if (Type == D3DTS_PROJECTION) + return 1; + + if (Type >= D3DTS_TEXTURE0 && Type <= D3DTS_TEXTURE7) + return 2 + (Type - D3DTS_TEXTURE0); + + return 10 + (Type - D3DTS_WORLD); + } + + inline Matrix4 ConvertMatrix(const D3DMATRIX* Matrix) { + if (Matrix == nullptr) // Identity. + return Matrix4(); + + return Matrix4(Matrix->m); + } + + uint32_t GetVertexCount(D3DPRIMITIVETYPE type, UINT count); + + DxvkInputAssemblyState DecodeInputAssemblyState(D3DPRIMITIVETYPE type); + + VkBlendFactor DecodeBlendFactor(D3DBLEND BlendFactor, bool IsAlpha); + + VkBlendOp DecodeBlendOp(D3DBLENDOP BlendOp); + + VkFilter DecodeFilter(D3DTEXTUREFILTERTYPE Filter); + + D3D9MipFilter DecodeMipFilter(D3DTEXTUREFILTERTYPE Filter); + + bool IsAnisotropic(D3DTEXTUREFILTERTYPE Filter); + + VkSamplerAddressMode DecodeAddressMode(D3DTEXTUREADDRESS Mode); + + VkCompareOp DecodeCompareOp(D3DCMPFUNC Func); + + VkStencilOp DecodeStencilOp(D3DSTENCILOP Op); + + VkCullModeFlags DecodeCullMode(D3DCULL Mode); + + VkPolygonMode DecodeFillMode(D3DFILLMODE Mode); + + VkIndexType DecodeIndexType(D3D9Format Format); + + VkFormat DecodeDecltype(D3DDECLTYPE Type); + + uint32_t GetDecltypeSize(D3DDECLTYPE Type); + + uint32_t GetDecltypeCount(D3DDECLTYPE Type); + + void ConvertBox(D3DBOX box, VkOffset3D& offset, VkExtent3D& extent); + + void ConvertRect(RECT rect, VkOffset3D& offset, VkExtent3D& extent); + + void ConvertRect(RECT rect, VkOffset2D& offset, VkExtent2D& extent); + + inline float GetDepthBufferRValue(VkFormat Format) { + switch (Format) { + case VK_FORMAT_D16_UNORM_S8_UINT: + case VK_FORMAT_D16_UNORM: + return float(1 << 16); + + case VK_FORMAT_D24_UNORM_S8_UINT: + return float(1 << 24); + + default: + case VK_FORMAT_D32_SFLOAT_S8_UINT: + case VK_FORMAT_D32_SFLOAT: + return float(1 << 23); + } + } + + template + UINT CompactSparseList(T* pData, UINT Mask) { + uint32_t count = 0; + + for (uint32_t id : bit::BitMask(Mask)) + pData[count++] = pData[id]; + + return count; + } + + bool IsDepthFormat(D3D9Format Format); + + inline bool operator == (const D3DVIEWPORT9& a, const D3DVIEWPORT9& b) { + return a.X == b.X && + a.Y == b.Y && + a.Width == b.Width && + a.Height == b.Height && + a.MinZ == b.MinZ && + a.MaxZ == b.MaxZ; + } + + inline bool operator != (const D3DVIEWPORT9& a, const D3DVIEWPORT9& b) { + return !(a == b); + } + + inline bool operator == (const RECT& a, const RECT& b) { + return a.left == b.left && + a.right == b.right && + a.top == b.top && + a.bottom == b.bottom; + } + + inline bool operator != (const RECT& a, const RECT& b) { + return !(a == b); + } + + inline bool operator == (const POINT& a, const POINT& b) { + return a.x == b.x && a.y == b.y; + } + + inline bool operator != (const POINT& a, const POINT& b) { + return !(a == b); + } + + inline bool IsPoolManaged(D3DPOOL Pool) { + return Pool == D3DPOOL_MANAGED || Pool == D3DPOOL_MANAGED_EX; + } + + inline D3DRENDERSTATETYPE ColorWriteIndex(uint32_t i) { + return D3DRENDERSTATETYPE(i ? D3DRS_COLORWRITEENABLE1 + i - 1 : D3DRS_COLORWRITEENABLE); + } + + inline bool AreFormatsSimilar(D3D9Format srcFormat, D3D9Format dstFormat) { + return (srcFormat == dstFormat) + || (srcFormat == D3D9Format::A8B8G8R8 && dstFormat == D3D9Format::X8B8G8R8) + || (srcFormat == D3D9Format::A8R8G8B8 && dstFormat == D3D9Format::X8R8G8B8) + || (srcFormat == D3D9Format::A1R5G5B5 && dstFormat == D3D9Format::X1R5G5B5) + || (srcFormat == D3D9Format::A4R4G4B4 && dstFormat == D3D9Format::X4R4G4B4); + } + + inline bool IsBlitRegionInvalid(VkOffset3D offsets[2], VkExtent3D extent) { + // Only bother checking x, y as we don't have 3D blits. + return offsets[1].x < offsets[0].x || + offsets[1].y < offsets[0].y || + offsets[0].x < 0 || + offsets[0].y < 0 || + uint32_t(offsets[1].x) > extent.width || + uint32_t(offsets[1].y) > extent.height; + } + + enum D3D9TextureStageStateTypes : uint32_t + { + DXVK_TSS_COLOROP = 0, + DXVK_TSS_COLORARG1 = 1, + DXVK_TSS_COLORARG2 = 2, + DXVK_TSS_ALPHAOP = 3, + DXVK_TSS_ALPHAARG1 = 4, + DXVK_TSS_ALPHAARG2 = 5, + DXVK_TSS_BUMPENVMAT00 = 6, + DXVK_TSS_BUMPENVMAT01 = 7, + DXVK_TSS_BUMPENVMAT10 = 8, + DXVK_TSS_BUMPENVMAT11 = 9, + DXVK_TSS_TEXCOORDINDEX = 10, + DXVK_TSS_BUMPENVLSCALE = 21, + DXVK_TSS_BUMPENVLOFFSET = 22, + DXVK_TSS_TEXTURETRANSFORMFLAGS = 23, + DXVK_TSS_COLORARG0 = 25, + DXVK_TSS_ALPHAARG0 = 26, + DXVK_TSS_RESULTARG = 27, + DXVK_TSS_CONSTANT = 31, + DXVK_TSS_COUNT = 32 + }; + + constexpr uint32_t DXVK_TSS_TCI_PASSTHRU = 0x00000000; + constexpr uint32_t DXVK_TSS_TCI_CAMERASPACENORMAL = 0x00010000; + constexpr uint32_t DXVK_TSS_TCI_CAMERASPACEPOSITION = 0x00020000; + constexpr uint32_t DXVK_TSS_TCI_CAMERASPACEREFLECTIONVECTOR = 0x00030000; + constexpr uint32_t DXVK_TSS_TCI_SPHEREMAP = 0x00040000; + + inline D3D9TextureStageStateTypes RemapTextureStageStateType(D3DTEXTURESTAGESTATETYPE Type) { + return D3D9TextureStageStateTypes(Type - 1); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_vertex_declaration.cpp b/utils/dxvk-1.10.3/src/d3d9/d3d9_vertex_declaration.cpp new file mode 100644 index 00000000000..9eb65d79c6a --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_vertex_declaration.cpp @@ -0,0 +1,234 @@ +#include "d3d9_vertex_declaration.h" +#include "d3d9_util.h" + +#include +#include + +namespace dxvk { + + D3D9VertexDecl::D3D9VertexDecl( + D3D9DeviceEx* pDevice, + DWORD FVF) + : D3D9VertexDeclBase(pDevice) { + this->SetFVF(FVF); + this->Classify(); + } + + + D3D9VertexDecl::D3D9VertexDecl( + D3D9DeviceEx* pDevice, + const D3DVERTEXELEMENT9* pVertexElements, + uint32_t DeclCount) + : D3D9VertexDeclBase( pDevice ) + , m_elements ( DeclCount ) + , m_fvf ( 0 ) { + std::copy(pVertexElements, pVertexElements + DeclCount, m_elements.begin()); + this->Classify(); + } + + + HRESULT STDMETHODCALLTYPE D3D9VertexDecl::QueryInterface( + REFIID riid, + void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(IDirect3DVertexDeclaration9)) { + *ppvObject = ref(this); + return S_OK; + } + + Logger::warn("D3D9VertexDecl::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + HRESULT STDMETHODCALLTYPE D3D9VertexDecl::GetDeclaration( + D3DVERTEXELEMENT9* pElement, + UINT* pNumElements) { + if (pNumElements == nullptr) + return D3DERR_INVALIDCALL; + + *pNumElements = UINT(m_elements.size()) + 1u; // Account for D3DDECL_END + + if (pElement == nullptr) + return D3D_OK; + + // The native runtime ignores pNumElements here... + std::copy(m_elements.begin(), m_elements.end(), pElement); + pElement[m_elements.size()] = D3DDECL_END(); + + return D3D_OK; + } + + + void D3D9VertexDecl::SetFVF(DWORD FVF) { + m_fvf = FVF; + + std::array elements; + uint32_t elemCount = 0; + uint32_t texCount = 0; + + uint32_t betas = 0; + uint8_t betaIdx = 0xFF; + + switch (FVF & D3DFVF_POSITION_MASK) { + case D3DFVF_XYZ: + case D3DFVF_XYZB1: + case D3DFVF_XYZB2: + case D3DFVF_XYZB3: + case D3DFVF_XYZB4: + case D3DFVF_XYZB5: + elements[elemCount].Type = D3DDECLTYPE_FLOAT3; + elements[elemCount].Usage = D3DDECLUSAGE_POSITION; + elements[elemCount].UsageIndex = 0; + elemCount++; + + if ((FVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) + break; + + betas = (((FVF & D3DFVF_XYZB5) - D3DFVF_XYZB1) >> 1) + 1; + if (FVF & D3DFVF_LASTBETA_D3DCOLOR) + betaIdx = D3DDECLTYPE_D3DCOLOR; + else if (FVF & D3DFVF_LASTBETA_UBYTE4) + betaIdx = D3DDECLTYPE_UBYTE4; + else if ((FVF & D3DFVF_XYZB5) == D3DFVF_XYZB5) + betaIdx = D3DDECLTYPE_FLOAT1; + + if (betaIdx != 0xFF) + betas--; + + if (betas > 0) { + switch (betas) { + case 1: elements[elemCount].Type = D3DDECLTYPE_FLOAT1; break; + case 2: elements[elemCount].Type = D3DDECLTYPE_FLOAT2; break; + case 3: elements[elemCount].Type = D3DDECLTYPE_FLOAT3; break; + case 4: elements[elemCount].Type = D3DDECLTYPE_FLOAT4; break; + default: break; + } + elements[elemCount].Usage = D3DDECLUSAGE_BLENDWEIGHT; + elements[elemCount].UsageIndex = 0; + elemCount++; + } + + if (betaIdx != 0xFF) { + elements[elemCount].Type = betaIdx; + elements[elemCount].Usage = D3DDECLUSAGE_BLENDINDICES; + elements[elemCount].UsageIndex = 0; + elemCount++; + } + break; + + case D3DFVF_XYZW: + case D3DFVF_XYZRHW: + elements[elemCount].Type = D3DDECLTYPE_FLOAT4; + elements[elemCount].Usage = + ((FVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZW) + ? D3DDECLUSAGE_POSITION + : D3DDECLUSAGE_POSITIONT; + elements[elemCount].UsageIndex = 0; + elemCount++; + break; + + default: + break; + } + + if (FVF & D3DFVF_NORMAL) { + elements[elemCount].Type = D3DDECLTYPE_FLOAT3; + elements[elemCount].Usage = D3DDECLUSAGE_NORMAL; + elements[elemCount].UsageIndex = 0; + elemCount++; + } + if (FVF & D3DFVF_PSIZE) { + elements[elemCount].Type = D3DDECLTYPE_FLOAT1; + elements[elemCount].Usage = D3DDECLUSAGE_PSIZE; + elements[elemCount].UsageIndex = 0; + elemCount++; + } + if (FVF & D3DFVF_DIFFUSE) { + elements[elemCount].Type = D3DDECLTYPE_D3DCOLOR; + elements[elemCount].Usage = D3DDECLUSAGE_COLOR; + elements[elemCount].UsageIndex = 0; + elemCount++; + } + if (FVF & D3DFVF_SPECULAR) { + elements[elemCount].Type = D3DDECLTYPE_D3DCOLOR; + elements[elemCount].Usage = D3DDECLUSAGE_COLOR; + elements[elemCount].UsageIndex = 1; + elemCount++; + } + + texCount = (FVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT; + texCount = std::min(texCount, 8u); + + for (uint32_t i = 0; i < texCount; i++) { + switch ((FVF >> (16 + i * 2)) & 0x3) { + case D3DFVF_TEXTUREFORMAT1: + elements[elemCount].Type = D3DDECLTYPE_FLOAT1; + break; + + case D3DFVF_TEXTUREFORMAT2: + elements[elemCount].Type = D3DDECLTYPE_FLOAT2; + break; + + case D3DFVF_TEXTUREFORMAT3: + elements[elemCount].Type = D3DDECLTYPE_FLOAT3; + break; + + case D3DFVF_TEXTUREFORMAT4: + elements[elemCount].Type = D3DDECLTYPE_FLOAT4; + break; + + default: + break; + } + elements[elemCount].Usage = D3DDECLUSAGE_TEXCOORD; + elements[elemCount].UsageIndex = i; + elemCount++; + } + + for (uint32_t i = 0; i < elemCount; i++) { + elements[i].Stream = 0; + elements[i].Offset = (i == 0) + ? 0 + : (elements[i - 1].Offset + GetDecltypeSize(D3DDECLTYPE(elements[i - 1].Type))); + + elements[i].Method = D3DDECLMETHOD_DEFAULT; + } + + m_elements.resize(elemCount); + std::copy(elements.begin(), elements.begin() + elemCount, m_elements.data()); + } + + + void D3D9VertexDecl::Classify() { + for (const auto& element : m_elements) { + if (element.Stream == 0 && element.Type != D3DDECLTYPE_UNUSED) + m_size = std::max(m_size, element.Offset + GetDecltypeSize(D3DDECLTYPE(element.Type))); + + if (element.Usage == D3DDECLUSAGE_COLOR && element.UsageIndex == 0) + m_flags.set(D3D9VertexDeclFlag::HasColor0); + else if (element.Usage == D3DDECLUSAGE_COLOR && element.UsageIndex == 1) + m_flags.set(D3D9VertexDeclFlag::HasColor1); + else if (element.Usage == D3DDECLUSAGE_POSITIONT) + m_flags.set(D3D9VertexDeclFlag::HasPositionT); + else if (element.Usage == D3DDECLUSAGE_PSIZE) + m_flags.set(D3D9VertexDeclFlag::HasPointSize); + else if (element.Usage == D3DDECLUSAGE_FOG) + m_flags.set(D3D9VertexDeclFlag::HasFog); + else if (element.Usage == D3DDECLUSAGE_BLENDWEIGHT) + m_flags.set(D3D9VertexDeclFlag::HasBlendWeight); + else if (element.Usage == D3DDECLUSAGE_BLENDINDICES) + m_flags.set(D3D9VertexDeclFlag::HasBlendIndices); + + if (element.Usage == D3DDECLUSAGE_TEXCOORD) + m_texcoordMask |= GetDecltypeCount(D3DDECLTYPE(element.Type)) << (element.UsageIndex * 3); + } + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_vertex_declaration.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_vertex_declaration.h new file mode 100644 index 00000000000..240aa6ed1a8 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_vertex_declaration.h @@ -0,0 +1,86 @@ +#pragma once + +#include "d3d9_device_child.h" +#include "d3d9_util.h" + +#include + +namespace dxvk { + + enum class D3D9VertexDeclFlag { + HasColor0, + HasColor1, + HasPositionT, + HasPointSize, + HasFog, + HasBlendWeight, + HasBlendIndices + }; + using D3D9VertexDeclFlags = Flags; + + using D3D9VertexDeclBase = D3D9DeviceChild; + class D3D9VertexDecl final : public D3D9VertexDeclBase { + + public: + + D3D9VertexDecl( + D3D9DeviceEx* pDevice, + DWORD FVF); + + D3D9VertexDecl( + D3D9DeviceEx* pDevice, + const D3DVERTEXELEMENT9* pVertexElements, + uint32_t DeclCount); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + HRESULT STDMETHODCALLTYPE GetDeclaration( + D3DVERTEXELEMENT9* pElement, + UINT* pNumElements); + + inline DWORD GetFVF() { + return m_fvf; + } + + void SetFVF(DWORD FVF); + + const D3D9VertexElements& GetElements() const { + return m_elements; + } + + UINT GetSize() const { + return m_size; + } + + bool TestFlag(D3D9VertexDeclFlag flag) const { + return m_flags.test(flag); + } + + D3D9VertexDeclFlags GetFlags() const { + return m_flags; + } + + uint32_t GetTexcoordMask() const { + return m_texcoordMask; + } + + private: + + void Classify(); + + D3D9VertexDeclFlags m_flags; + + D3D9VertexElements m_elements; + + DWORD m_fvf; + + uint32_t m_texcoordMask = 0; + + // The size of Stream 0. That's all we care about. + uint32_t m_size = 0; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_volume.cpp b/utils/dxvk-1.10.3/src/d3d9/d3d9_volume.cpp new file mode 100644 index 00000000000..52886d80bf2 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_volume.cpp @@ -0,0 +1,112 @@ +#include "d3d9_volume.h" + +#include "d3d9_device.h" +#include "d3d9_texture.h" + +namespace dxvk { + + D3D9Volume::D3D9Volume( + D3D9DeviceEx* pDevice, + const D3D9_COMMON_TEXTURE_DESC* pDesc) + : D3D9VolumeBase( + pDevice, + new D3D9CommonTexture( pDevice, pDesc, D3DRTYPE_VOLUMETEXTURE, nullptr ), + 0, 0, + nullptr, + nullptr) { } + + + D3D9Volume::D3D9Volume( + D3D9DeviceEx* pDevice, + D3D9CommonTexture* pTexture, + UINT Face, + UINT MipLevel, + IDirect3DBaseTexture9* pContainer) + : D3D9VolumeBase( + pDevice, + pTexture, + Face, MipLevel, + pContainer, + pContainer) { } + + + void D3D9Volume::AddRefPrivate() { + // Can't have a swapchain container for a volume. + if (m_baseTexture != nullptr) { + static_cast(m_baseTexture)->AddRefPrivate(); + return; + } + + D3D9VolumeBase::AddRefPrivate(); + } + + + void D3D9Volume::ReleasePrivate() { + // Can't have a swapchain container for a volume. + if (m_baseTexture != nullptr) { + static_cast(m_baseTexture)->ReleasePrivate(); + return; + } + + D3D9VolumeBase::ReleasePrivate(); + } + + + HRESULT STDMETHODCALLTYPE D3D9Volume::QueryInterface(REFIID riid, void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(IDirect3DResource9) + || riid == __uuidof(IDirect3DVolume9)) { + *ppvObject = ref(this); + return S_OK; + } + + Logger::warn("D3D9Volume::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + HRESULT STDMETHODCALLTYPE D3D9Volume::GetDesc(D3DVOLUME_DESC *pDesc) { + if (pDesc == nullptr) + return D3DERR_INVALIDCALL; + + auto& desc = *(m_texture->Desc()); + + pDesc->Format = static_cast(desc.Format); + pDesc->Type = D3DRTYPE_VOLUME; + pDesc->Usage = desc.Usage; + pDesc->Pool = desc.Pool; + + pDesc->Width = std::max(1u, desc.Width >> m_mipLevel); + pDesc->Height = std::max(1u, desc.Height >> m_mipLevel); + pDesc->Depth = std::max(1u, desc.Depth >> m_mipLevel); + + return D3D_OK; + } + + + HRESULT STDMETHODCALLTYPE D3D9Volume::LockBox(D3DLOCKED_BOX* pLockedBox, CONST D3DBOX* pBox, DWORD Flags) { + if (unlikely(pLockedBox == nullptr)) + return D3DERR_INVALIDCALL; + + return m_parent->LockImage( + m_texture, + m_face, m_mipLevel, + pLockedBox, + pBox, + Flags); + } + + + HRESULT STDMETHODCALLTYPE D3D9Volume::UnlockBox() { + return m_parent->UnlockImage( + m_texture, + m_face, m_mipLevel); + } + +} diff --git a/utils/dxvk-1.10.3/src/d3d9/d3d9_volume.h b/utils/dxvk-1.10.3/src/d3d9/d3d9_volume.h new file mode 100644 index 00000000000..9c33a788f6a --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/d3d9_volume.h @@ -0,0 +1,38 @@ +#pragma once + +#include "d3d9_subresource.h" + +#include "d3d9_common_texture.h" + +namespace dxvk { + + using D3D9VolumeBase = D3D9Subresource; + class D3D9Volume final : public D3D9VolumeBase { + + public: + + D3D9Volume( + D3D9DeviceEx* pDevice, + const D3D9_COMMON_TEXTURE_DESC* pDesc); + + D3D9Volume( + D3D9DeviceEx* pDevice, + D3D9CommonTexture* pTexture, + UINT Face, + UINT MipLevel, + IDirect3DBaseTexture9* pContainer); + + void AddRefPrivate(); + + void ReleasePrivate(); + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject); + + HRESULT STDMETHODCALLTYPE GetDesc(D3DVOLUME_DESC *pDesc) final; + + HRESULT STDMETHODCALLTYPE LockBox(D3DLOCKED_BOX* pLockedBox, CONST D3DBOX* pBox, DWORD Flags) final; + + HRESULT STDMETHODCALLTYPE UnlockBox() final; + + }; +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/meson.build b/utils/dxvk-1.10.3/src/d3d9/meson.build new file mode 100644 index 00000000000..2cd8951e2ab --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/meson.build @@ -0,0 +1,56 @@ +d3d9_res = wrc_generator.process('version.rc') + +d3d9_shaders = files([ + 'shaders/d3d9_convert_yuy2_uyvy.comp', + 'shaders/d3d9_convert_l6v5u5.comp', + 'shaders/d3d9_convert_x8l8v8u8.comp', + 'shaders/d3d9_convert_a2w10v10u10.comp', + 'shaders/d3d9_convert_nv12.comp', + 'shaders/d3d9_convert_yv12.comp' +]) + +d3d9_src = [ + 'd3d9_main.cpp', + 'd3d9_interface.cpp', + 'd3d9_adapter.cpp', + 'd3d9_monitor.cpp', + 'd3d9_device.cpp', + 'd3d9_state.cpp', + 'd3d9_cursor.cpp', + 'd3d9_swapchain.cpp', + 'd3d9_format.cpp', + 'd3d9_common_texture.cpp', + 'd3d9_texture.cpp', + 'd3d9_surface.cpp', + 'd3d9_volume.cpp', + 'd3d9_common_buffer.cpp', + 'd3d9_buffer.cpp', + 'd3d9_shader.cpp', + 'd3d9_vertex_declaration.cpp', + 'd3d9_query.cpp', + 'd3d9_multithread.cpp', + 'd3d9_options.cpp', + 'd3d9_stateblock.cpp', + 'd3d9_sampler.cpp', + 'd3d9_util.cpp', + 'd3d9_initializer.cpp', + 'd3d9_fixed_function.cpp', + 'd3d9_names.cpp', + 'd3d9_swvp_emu.cpp', + 'd3d9_format_helpers.cpp', + 'd3d9_hud.cpp', + 'd3d9_annotation.cpp' +] + +d3d9_dll = shared_library('d3d9'+dll_ext, d3d9_src, glsl_generator.process(d3d9_shaders), d3d9_res, + name_prefix : '', + dependencies : [ dxso_dep, dxvk_dep ], + include_directories : dxvk_include_path, + install : true, + vs_module_defs : 'd3d9'+def_spec_ext, +) + +d3d9_dep = declare_dependency( + link_with : [ d3d9_dll ], + include_directories : [ dxvk_include_path ], +) diff --git a/utils/dxvk-1.10.3/src/d3d9/shaders/d3d9_convert_a2w10v10u10.comp b/utils/dxvk-1.10.3/src/d3d9/shaders/d3d9_convert_a2w10v10u10.comp new file mode 100644 index 00000000000..2d489e3d3db --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/shaders/d3d9_convert_a2w10v10u10.comp @@ -0,0 +1,44 @@ +#version 450 +#extension GL_GOOGLE_include_directive : enable + +#include "d3d9_convert_common.h" + +layout( + local_size_x = 8, + local_size_y = 8, + local_size_z = 1) in; + +layout(binding = 0) +writeonly uniform image2D dst; + +layout(binding = 1) uniform usamplerBuffer src; + +layout(push_constant) +uniform u_info_t { + uvec2 extent; +} u_info; + +void main() { + ivec3 thread_id = ivec3(gl_GlobalInvocationID); + + if (all(lessThan(thread_id.xy, u_info.extent))) { + uint offset = thread_id.x + + thread_id.y * u_info.extent.x; + + uint value = texelFetch(src, int(offset)).r; + + // Sign-extend magic! + int u10 = bitfieldExtract(int (value), 0, 10); + int v10 = bitfieldExtract(int (value), 10, 10); + int w10 = bitfieldExtract(int (value), 20, 10); + uint a2 = bitfieldExtract(uint(value), 30, 2); + + vec4 color = vec4( + snormalize(u10, 10), + snormalize(v10, 10), + snormalize(w10, 10), + unormalize(a2, 2)); + + imageStore(dst, thread_id.xy, color); + } +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/shaders/d3d9_convert_common.h b/utils/dxvk-1.10.3/src/d3d9/shaders/d3d9_convert_common.h new file mode 100644 index 00000000000..daca40e18fe --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/shaders/d3d9_convert_common.h @@ -0,0 +1,44 @@ +float unormalize(uint value, int bits) { + const int range = (1 << bits) - 1; + + return float(value) / float(range); +} + +float snormalize(int value, int bits) { + const int range = (1 << (bits - 1)) - 1; + + // Min because, -32 and -31 map to -1.0f, and we + // divide by 31. + return max(float(value) / float(range), -1.0); +} + +float unpackUnorm(uint p) { + return float(p) / 255.0; +} + +vec2 unpackUnorm2x8(uint p) { + uvec2 value = uvec2(p & 0xFF, p >> 8); + return vec2(unpackUnorm(value.x), unpackUnorm(value.y)); +} + +mat3x4 g_yuv_to_rgb = { + { 298 / 256, 0, 409 / 256, 0.5 }, + { 298 / 256, -100 / 256, -208 / 256, 0.5 }, + { 298 / 256, 516 / 256, 0, 0.5 } +}; + +vec4 convertYUV(vec3 yuv) { + vec3 value = vec4(yuv, 1 / 255.0) * g_yuv_to_rgb; + + return vec4(clamp(value, 0, 1), 1); +} + +mat3x3 g_bt709_to_rgb = { + { 1.164, 0, 1.793 }, + { 1.164, -0.213, -0.533 }, + { 1.164, 2.112, 0 } +}; + +vec4 convertBT_709(vec3 cde) { + return vec4(clamp(cde * g_bt709_to_rgb, 0, 1), 1); +} diff --git a/utils/dxvk-1.10.3/src/d3d9/shaders/d3d9_convert_l6v5u5.comp b/utils/dxvk-1.10.3/src/d3d9/shaders/d3d9_convert_l6v5u5.comp new file mode 100644 index 00000000000..e7ee25a94e0 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/shaders/d3d9_convert_l6v5u5.comp @@ -0,0 +1,43 @@ +#version 450 +#extension GL_GOOGLE_include_directive : enable + +#include "d3d9_convert_common.h" + +layout( + local_size_x = 8, + local_size_y = 8, + local_size_z = 1) in; + +layout(binding = 0) +writeonly uniform image2D dst; + +layout(binding = 1) uniform usamplerBuffer src; + +layout(push_constant) +uniform u_info_t { + uvec2 extent; +} u_info; + +void main() { + ivec3 thread_id = ivec3(gl_GlobalInvocationID); + + if (all(lessThan(thread_id.xy, u_info.extent))) { + uint offset = thread_id.x + + thread_id.y * u_info.extent.x; + + uint value = texelFetch(src, int(offset)).r; + + // Sign-extend magic! + int u5 = bitfieldExtract(int (value), 0, 5); + int v5 = bitfieldExtract(int (value), 5, 5); + uint l6 = bitfieldExtract(uint(value), 10, 6); + + vec4 color = vec4( + snormalize(u5, 5), + snormalize(v5, 5), + unormalize(l6, 6), + 1.0f); + + imageStore(dst, thread_id.xy, color); + } +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/shaders/d3d9_convert_nv12.comp b/utils/dxvk-1.10.3/src/d3d9/shaders/d3d9_convert_nv12.comp new file mode 100644 index 00000000000..70f7998d6a1 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/shaders/d3d9_convert_nv12.comp @@ -0,0 +1,63 @@ +#version 450 +#extension GL_GOOGLE_include_directive : enable + +#include "d3d9_convert_common.h" + +layout( + local_size_x = 8, + local_size_y = 8, + local_size_z = 1) in; + +layout(binding = 0) +writeonly uniform image2D dst; + +layout(binding = 1) uniform usamplerBuffer src; + +layout(push_constant) +uniform u_info_t { + uvec2 extent; +} u_info; + +vec2 fetchUnorm2x8(usamplerBuffer source, uint offset) { + return unpackUnorm2x8(texelFetch(src, int(offset)).r); +} + +// Format is: +// YYYYYYYYYYYYYYY... +// YYYYYYYYYYYYYYY... +// UVUVUVUVUVUVUVU... + +void main() { + ivec3 thread_id = ivec3(gl_GlobalInvocationID); + + if (all(lessThan(thread_id.xy, u_info.extent))) { + uvec2 pitch = uvec2(u_info.extent.x, u_info.extent.y); + + uint offset = thread_id.x + + thread_id.y * pitch.x; + + // Fetch 2 luminance samples. + vec2 y = fetchUnorm2x8(src, offset) - (16 / 255.0); + + // Go into the second plane to get the chroma data. + // UV data is subsampled as [2, 2] + // So we need to divide thread_id.y by 2. + // thread_id.x is already accounted for as we read uint16 + offset = thread_id.x + + thread_id.y / 2 * pitch.x + + pitch.x * pitch.y; + + vec2 uv = fetchUnorm2x8(src, offset) - (128 / 255.0); + + // The NV12 format seems to use the BT.709 color space. + vec4 color0 = convertBT_709(vec3(y.x, uv.x, uv.y)); + vec4 color1 = convertBT_709(vec3(y.y, uv.x, uv.y)); + + // We write as a macropixel of [2, 1] + // So write out 2 pixels in this run. + ivec2 writePos = thread_id.xy * ivec2(2, 1); + + imageStore(dst, ivec2(writePos.x, writePos.y), color0); + imageStore(dst, ivec2(writePos.x + 1, writePos.y), color1); + } +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/shaders/d3d9_convert_x8l8v8u8.comp b/utils/dxvk-1.10.3/src/d3d9/shaders/d3d9_convert_x8l8v8u8.comp new file mode 100644 index 00000000000..a9257cb5a5c --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/shaders/d3d9_convert_x8l8v8u8.comp @@ -0,0 +1,43 @@ +#version 450 +#extension GL_GOOGLE_include_directive : enable + +#include "d3d9_convert_common.h" + +layout( + local_size_x = 8, + local_size_y = 8, + local_size_z = 1) in; + +layout(binding = 0) +writeonly uniform image2D dst; + +layout(binding = 1) uniform usamplerBuffer src; + +layout(push_constant) +uniform u_info_t { + uvec2 extent; +} u_info; + +void main() { + ivec3 thread_id = ivec3(gl_GlobalInvocationID); + + if (all(lessThan(thread_id.xy, u_info.extent))) { + uint offset = thread_id.x + + thread_id.y * u_info.extent.x; + + uint value = texelFetch(src, int(offset)).r; + + // Sign-extend magic! + int u8 = bitfieldExtract(int (value), 0, 8); + int v8 = bitfieldExtract(int (value), 8, 8); + uint l8 = bitfieldExtract(uint(value), 16, 8); + + vec4 color = vec4( + snormalize(u8, 8), + snormalize(v8, 8), + unormalize(l8, 8), + 1.0f); + + imageStore(dst, thread_id.xy, color); + } +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/shaders/d3d9_convert_yuy2_uyvy.comp b/utils/dxvk-1.10.3/src/d3d9/shaders/d3d9_convert_yuy2_uyvy.comp new file mode 100644 index 00000000000..8f38c9bacf0 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/shaders/d3d9_convert_yuy2_uyvy.comp @@ -0,0 +1,53 @@ +#version 450 +#extension GL_GOOGLE_include_directive : enable + +#include "d3d9_convert_common.h" + +layout(constant_id = 1225) const bool s_is_uyvy = false; + +layout( + local_size_x = 8, + local_size_y = 8, + local_size_z = 1) in; + +layout(binding = 0) +writeonly uniform image2D dst; + +layout(binding = 1) uniform usamplerBuffer src; + +layout(push_constant) +uniform u_info_t { + uvec2 extent; +} u_info; + +void main() { + ivec3 thread_id = ivec3(gl_GlobalInvocationID); + + if (all(lessThan(thread_id.xy, u_info.extent))) { + uint offset = thread_id.x + + thread_id.y * u_info.extent.x; + + uint value = texelFetch(src, int(offset)).r; + + vec4 data = unpackUnorm4x8(value); + + // Flip around stuff for UYVY + if (s_is_uyvy) + data = data.yxwz; + + float y0 = data.x - (16 / 255.0); + float u = data.y - (128 / 255.0); + float y1 = data.z - (16 / 255.0); + float v = data.w - (128 / 255.0); + + vec4 color0 = convertYUV(vec3(y0, u, v)); + vec4 color1 = convertYUV(vec3(y1, u, v)); + + // YUY2 has a macropixel of [2, 1] + // so we write 2 pixels in this run. + ivec2 writePos = thread_id.xy * ivec2(2, 1); + + imageStore(dst, ivec2(writePos.x, writePos.y), color0); + imageStore(dst, ivec2(writePos.x + 1, writePos.y), color1); + } +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/d3d9/shaders/d3d9_convert_yv12.comp b/utils/dxvk-1.10.3/src/d3d9/shaders/d3d9_convert_yv12.comp new file mode 100644 index 00000000000..ad3822abb75 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/shaders/d3d9_convert_yv12.comp @@ -0,0 +1,58 @@ +#version 450 +#extension GL_GOOGLE_include_directive : enable + +#include "d3d9_convert_common.h" + +layout( + local_size_x = 8, + local_size_y = 8, + local_size_z = 1) in; + +layout(binding = 0) +writeonly uniform image2D dst; + +layout(binding = 1) uniform usamplerBuffer src; + +layout(push_constant) +uniform u_info_t { + uvec2 extent; +} u_info; + +// Format is: +// YYYYYYYY... +// VVVV... +// UUUU... + +float fetchUnorm(usamplerBuffer source, uint offset) { + return unpackUnorm(texelFetch(src, int(offset)).r); +} + +void main() { + ivec3 thread_id = ivec3(gl_GlobalInvocationID); + + if (all(lessThan(thread_id.xy, u_info.extent))) { + uvec2 pitch = uvec2(u_info.extent.x, u_info.extent.y); + + uint offset = thread_id.x + + thread_id.y * pitch.x; + + // Fetch a Y, luminance sample. + float y = fetchUnorm(src, offset) - (16 / 255.0); + + // Go into the second plane to get a V, chroma sample + offset = (thread_id.x / 2) + + (thread_id.y / 2) * (pitch.x / 2) + + pitch.x * pitch.y; + + float v = fetchUnorm(src, offset) - (128 / 255.0); + + // Go into the third plane to get a U, chroma sample + offset += (pitch.x / 2) * (pitch.y / 2); + float u = fetchUnorm(src, offset) - (128 / 255.0); + + // TODO: Is this the right color space? + vec4 color = convertBT_709(vec3(y, u, v)); + + imageStore(dst, thread_id.xy, color); + } +} diff --git a/utils/dxvk-1.10.3/src/d3d9/version.rc b/utils/dxvk-1.10.3/src/d3d9/version.rc new file mode 100644 index 00000000000..b4027eee992 --- /dev/null +++ b/utils/dxvk-1.10.3/src/d3d9/version.rc @@ -0,0 +1,31 @@ +#include + +// DLL version information. +VS_VERSION_INFO VERSIONINFO +FILEVERSION 10,0,17763,1 +PRODUCTVERSION 10,0,17763,1 +FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +FILEFLAGS 0 +FILEOS VOS_NT_WINDOWS32 +FILETYPE VFT_DLL +FILESUBTYPE VFT2_UNKNOWN +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "080904b0" + BEGIN + VALUE "CompanyName", "DXVK" + VALUE "FileDescription", "Direct3D 9 Runtime" + VALUE "FileVersion", "10.0.17763.1 (WinBuild.160101.0800)" + VALUE "InternalName", "D3D9.dll" + VALUE "LegalCopyright", "zlib/libpng license" + VALUE "OriginalFilename", "D3D9.dll" + VALUE "ProductName", "DXVK" + VALUE "ProductVersion", "10.0.17763.1" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0809, 1200 + END +END diff --git a/utils/dxvk-1.10.3/src/dxbc/dxbc_analysis.cpp b/utils/dxvk-1.10.3/src/dxbc/dxbc_analysis.cpp new file mode 100644 index 00000000000..69922211bb1 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxbc/dxbc_analysis.cpp @@ -0,0 +1,110 @@ +#include "dxbc_analysis.h" + +namespace dxvk { + + DxbcAnalyzer::DxbcAnalyzer( + const DxbcModuleInfo& moduleInfo, + const DxbcProgramInfo& programInfo, + const Rc& isgn, + const Rc& osgn, + const Rc& psgn, + DxbcAnalysisInfo& analysis) + : m_isgn (isgn), + m_osgn (osgn), + m_psgn (psgn), + m_analysis(&analysis) { + // Get number of clipping and culling planes from the + // input and output signatures. We will need this to + // declare the shader input and output interfaces. + m_analysis->clipCullIn = getClipCullInfo(m_isgn); + m_analysis->clipCullOut = getClipCullInfo(m_osgn); + } + + + DxbcAnalyzer::~DxbcAnalyzer() { + + } + + + void DxbcAnalyzer::processInstruction(const DxbcShaderInstruction& ins) { + switch (ins.opClass) { + case DxbcInstClass::Atomic: { + const uint32_t operandId = ins.dstCount - 1; + + if (ins.dst[operandId].type == DxbcOperandType::UnorderedAccessView) { + const uint32_t registerId = ins.dst[operandId].idx[0].offset; + m_analysis->uavInfos[registerId].accessAtomicOp = true; + m_analysis->uavInfos[registerId].accessFlags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; + } + } break; + + case DxbcInstClass::TextureSample: + case DxbcInstClass::TextureGather: + case DxbcInstClass::TextureQueryLod: + case DxbcInstClass::VectorDeriv: { + m_analysis->usesDerivatives = true; + } break; + + case DxbcInstClass::ControlFlow: { + if (ins.op == DxbcOpcode::Discard) + m_analysis->usesKill = true; + } break; + + case DxbcInstClass::BufferLoad: { + uint32_t operandId = ins.op == DxbcOpcode::LdStructured ? 2 : 1; + + if (ins.src[operandId].type == DxbcOperandType::UnorderedAccessView) { + const uint32_t registerId = ins.src[operandId].idx[0].offset; + m_analysis->uavInfos[registerId].accessFlags |= VK_ACCESS_SHADER_READ_BIT; + } + } break; + + case DxbcInstClass::BufferStore: { + if (ins.dst[0].type == DxbcOperandType::UnorderedAccessView) { + const uint32_t registerId = ins.dst[0].idx[0].offset; + m_analysis->uavInfos[registerId].accessFlags |= VK_ACCESS_SHADER_WRITE_BIT; + } + } break; + + case DxbcInstClass::TypedUavLoad: { + const uint32_t registerId = ins.src[1].idx[0].offset; + m_analysis->uavInfos[registerId].accessTypedLoad = true; + m_analysis->uavInfos[registerId].accessFlags |= VK_ACCESS_SHADER_READ_BIT; + } break; + + case DxbcInstClass::TypedUavStore: { + const uint32_t registerId = ins.dst[0].idx[0].offset; + m_analysis->uavInfos[registerId].accessFlags |= VK_ACCESS_SHADER_WRITE_BIT; + } break; + + default: + break; + } + + for (uint32_t i = 0; i < ins.dstCount; i++) { + if (ins.dst[0].type == DxbcOperandType::IndexableTemp) { + uint32_t index = ins.dst[0].idx[0].offset; + m_analysis->xRegMasks[index] |= ins.dst[0].mask; + } + } + } + + + DxbcClipCullInfo DxbcAnalyzer::getClipCullInfo(const Rc& sgn) const { + DxbcClipCullInfo result; + + if (sgn != nullptr) { + for (auto e = sgn->begin(); e != sgn->end(); e++) { + const uint32_t componentCount = e->componentMask.popCount(); + + if (e->systemValue == DxbcSystemValue::ClipDistance) + result.numClipPlanes += componentCount; + if (e->systemValue == DxbcSystemValue::CullDistance) + result.numCullPlanes += componentCount; + } + } + + return result; + } + +} diff --git a/utils/dxvk-1.10.3/src/dxbc/dxbc_analysis.h b/utils/dxvk-1.10.3/src/dxbc/dxbc_analysis.h new file mode 100644 index 00000000000..b40cc94db2f --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxbc/dxbc_analysis.h @@ -0,0 +1,88 @@ +#pragma once + +#include "dxbc_chunk_isgn.h" +#include "dxbc_decoder.h" +#include "dxbc_defs.h" +#include "dxbc_names.h" +#include "dxbc_modinfo.h" +#include "dxbc_util.h" + +namespace dxvk { + + /** + * \brief Info about unordered access views + * + * Stores whether an UAV is accessed with typed + * read or atomic instructions. This information + * will be used to generate image types. + */ + struct DxbcUavInfo { + bool accessTypedLoad = false; + bool accessAtomicOp = false; + VkAccessFlags accessFlags = 0; + }; + + /** + * \brief Counts cull and clip distances + */ + struct DxbcClipCullInfo { + uint32_t numClipPlanes = 0; + uint32_t numCullPlanes = 0; + }; + + /** + * \brief Shader analysis info + */ + struct DxbcAnalysisInfo { + std::array uavInfos; + std::array xRegMasks; + + DxbcClipCullInfo clipCullIn; + DxbcClipCullInfo clipCullOut; + + bool usesDerivatives = false; + bool usesKill = false; + }; + + /** + * \brief DXBC shader analysis pass + * + * Collects information about the shader itself + * and the resources used by the shader, which + * will later be used by the actual compiler. + */ + class DxbcAnalyzer { + + public: + + DxbcAnalyzer( + const DxbcModuleInfo& moduleInfo, + const DxbcProgramInfo& programInfo, + const Rc& isgn, + const Rc& osgn, + const Rc& psgn, + DxbcAnalysisInfo& analysis); + + ~DxbcAnalyzer(); + + /** + * \brief Processes a single instruction + * \param [in] ins The instruction + */ + void processInstruction( + const DxbcShaderInstruction& ins); + + private: + + Rc m_isgn; + Rc m_osgn; + Rc m_psgn; + + DxbcAnalysisInfo* m_analysis = nullptr; + + DxbcClipCullInfo getClipCullInfo( + const Rc& sgn) const; + + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxbc/dxbc_chunk_isgn.cpp b/utils/dxvk-1.10.3/src/dxbc/dxbc_chunk_isgn.cpp new file mode 100644 index 00000000000..ce6617bd11f --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxbc/dxbc_chunk_isgn.cpp @@ -0,0 +1,114 @@ +#include "dxbc_chunk_isgn.h" + +namespace dxvk { + + DxbcIsgn::DxbcIsgn(DxbcReader reader, DxbcTag tag) { + uint32_t elementCount = reader.readu32(); + reader.skip(sizeof(uint32_t)); + + std::array componentTypes = { + DxbcScalarType::Uint32, DxbcScalarType::Uint32, + DxbcScalarType::Sint32, DxbcScalarType::Float32, + }; + + // https://github.com/DarkStarSword/3d-fixes/blob/master/dx11shaderanalyse.py#L101 + bool hasStream = (tag == "ISG1") || (tag == "OSG1") || (tag == "PSG1") || (tag == "OSG5"); + bool hasPrecision = (tag == "ISG1") || (tag == "OSG1") || (tag == "PSG1"); + + for (uint32_t i = 0; i < elementCount; i++) { + DxbcSgnEntry entry; + entry.streamId = hasStream ? reader.readu32() : 0; + entry.semanticName = reader.clone(reader.readu32()).readString(); + entry.semanticIndex = reader.readu32(); + entry.systemValue = static_cast(reader.readu32()); + entry.componentType = componentTypes.at(reader.readu32()); + entry.registerId = reader.readu32(); + entry.componentMask = bit::extract(reader.readu32(), 0, 3); + + if (hasPrecision) + reader.readu32(); + + m_entries.push_back(entry); + } + } + + + DxbcIsgn::~DxbcIsgn() { + + } + + + const DxbcSgnEntry* DxbcIsgn::findByRegister(uint32_t registerId) const { + for (auto e = this->begin(); e != this->end(); e++) { + if (e->registerId == registerId) + return &(*e); + } + + return nullptr; + } + + + const DxbcSgnEntry* DxbcIsgn::find( + const std::string& semanticName, + uint32_t semanticIndex, + uint32_t streamId) const { + for (auto e = this->begin(); e != this->end(); e++) { + if (e->semanticIndex == semanticIndex + && e->streamId == streamId + && compareSemanticNames(semanticName, e->semanticName)) + return &(*e); + } + + return nullptr; + } + + + DxbcRegMask DxbcIsgn::regMask( + uint32_t registerId) const { + DxbcRegMask mask; + + for (auto e = this->begin(); e != this->end(); e++) { + if (e->registerId == registerId) + mask |= e->componentMask; + } + + return mask; + } + + + uint32_t DxbcIsgn::maxRegisterCount() const { + uint32_t result = 0; + for (auto e = this->begin(); e != this->end(); e++) + result = std::max(result, e->registerId + 1); + return result; + } + + void DxbcIsgn::printEntries() const { + for (auto entry = this->begin(); entry != this->end(); entry++) { + Logger::debug(str::format("SGN Entry:\n\t", + "semanticName: ", entry->semanticName, "\n\t", + "semanticIndex: ", entry->semanticIndex, "\n\t", + "registerId: ", entry->registerId, "\n\t", + "componentMask: ", entry->componentMask.maskString(), "\n\t", + "componentType: ", entry->componentType, "\n\t", + "systemValue: ", entry->systemValue, "\n\t", + "streamId: ", entry->streamId, "\n", + "\n")); + } + } + + + bool DxbcIsgn::compareSemanticNames( + const std::string& a, const std::string& b) const { + if (a.size() != b.size()) + return false; + + for (size_t i = 0; i < a.size(); i++) { + if (std::toupper(a[i]) != std::toupper(b[i])) + return false; + } + + return true; + } + +} diff --git a/utils/dxvk-1.10.3/src/dxbc/dxbc_chunk_isgn.h b/utils/dxvk-1.10.3/src/dxbc/dxbc_chunk_isgn.h new file mode 100644 index 00000000000..030372f3f0c --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxbc/dxbc_chunk_isgn.h @@ -0,0 +1,69 @@ +#pragma once + +#include + +#include "dxbc_common.h" +#include "dxbc_decoder.h" +#include "dxbc_enums.h" +#include "dxbc_reader.h" + +namespace dxvk { + + /** + * \brief Signature entry + * + * Stores the semantic name of an input or + * output and the corresponding register. + */ + struct DxbcSgnEntry { + std::string semanticName; + uint32_t semanticIndex; + uint32_t registerId; + DxbcRegMask componentMask; + DxbcScalarType componentType; + DxbcSystemValue systemValue; + uint32_t streamId; + }; + + /** + * \brief Input/Output signature chunk + * + * Stores information about the input and + * output registers used by the shader stage. + */ + class DxbcIsgn : public RcObject { + + public: + + DxbcIsgn(DxbcReader reader, DxbcTag tag); + ~DxbcIsgn(); + + auto begin() const { return m_entries.cbegin(); } + auto end () const { return m_entries.cend(); } + + const DxbcSgnEntry* findByRegister( + uint32_t registerId) const; + + const DxbcSgnEntry* find( + const std::string& semanticName, + uint32_t semanticIndex, + uint32_t streamIndex) const; + + DxbcRegMask regMask( + uint32_t registerId) const; + + uint32_t maxRegisterCount() const; + + void printEntries() const; + + private: + + std::vector m_entries; + + bool compareSemanticNames( + const std::string& a, + const std::string& b) const; + + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxbc/dxbc_chunk_shex.cpp b/utils/dxvk-1.10.3/src/dxbc/dxbc_chunk_shex.cpp new file mode 100644 index 00000000000..552329b882b --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxbc/dxbc_chunk_shex.cpp @@ -0,0 +1,24 @@ +#include "dxbc_chunk_shex.h" + +namespace dxvk { + + DxbcShex::DxbcShex(DxbcReader reader) { + // The shader version and type are stored in a 32-bit unit, + // where the first byte contains the major and minor version + // numbers, and the high word contains the program type. + reader.skip(2); + auto pType = reader.readEnum(); + m_programInfo = DxbcProgramInfo(pType); + + // Read the actual shader code as an array of DWORDs. + auto codeLength = reader.readu32() - 2; + m_code.resize(codeLength); + reader.read(m_code.data(), codeLength * sizeof(uint32_t)); + } + + + DxbcShex::~DxbcShex() { + + } + +} diff --git a/utils/dxvk-1.10.3/src/dxbc/dxbc_chunk_shex.h b/utils/dxvk-1.10.3/src/dxbc/dxbc_chunk_shex.h new file mode 100644 index 00000000000..8deecc8675b --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxbc/dxbc_chunk_shex.h @@ -0,0 +1,39 @@ +#pragma once + +#include "dxbc_common.h" +#include "dxbc_decoder.h" +#include "dxbc_reader.h" + +namespace dxvk { + + /** + * \brief Shader code chunk + * + * Stores the DXBC shader code itself, as well + * as some meta info about the shader, i.e. what + * type of shader this is. + */ + class DxbcShex : public RcObject { + + public: + + DxbcShex(DxbcReader reader); + ~DxbcShex(); + + DxbcProgramInfo programInfo() const { + return m_programInfo; + } + + DxbcCodeSlice slice() const { + return DxbcCodeSlice(m_code.data(), + m_code.data() + m_code.size()); + } + + private: + + DxbcProgramInfo m_programInfo; + std::vector m_code; + + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxbc/dxbc_common.cpp b/utils/dxvk-1.10.3/src/dxbc/dxbc_common.cpp new file mode 100644 index 00000000000..d150c585b83 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxbc/dxbc_common.cpp @@ -0,0 +1,32 @@ +#include "dxbc_common.h" + +namespace dxvk { + + VkShaderStageFlagBits DxbcProgramInfo::shaderStage() const { + switch (m_type) { + case DxbcProgramType::PixelShader : return VK_SHADER_STAGE_FRAGMENT_BIT; + case DxbcProgramType::VertexShader : return VK_SHADER_STAGE_VERTEX_BIT; + case DxbcProgramType::GeometryShader : return VK_SHADER_STAGE_GEOMETRY_BIT; + case DxbcProgramType::HullShader : return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; + case DxbcProgramType::DomainShader : return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; + case DxbcProgramType::ComputeShader : return VK_SHADER_STAGE_COMPUTE_BIT; + } + + throw DxvkError("DxbcProgramInfo::shaderStage: Unsupported program type"); + } + + + spv::ExecutionModel DxbcProgramInfo::executionModel() const { + switch (m_type) { + case DxbcProgramType::PixelShader : return spv::ExecutionModelFragment; + case DxbcProgramType::VertexShader : return spv::ExecutionModelVertex; + case DxbcProgramType::GeometryShader : return spv::ExecutionModelGeometry; + case DxbcProgramType::HullShader : return spv::ExecutionModelTessellationControl; + case DxbcProgramType::DomainShader : return spv::ExecutionModelTessellationEvaluation; + case DxbcProgramType::ComputeShader : return spv::ExecutionModelGLCompute; + } + + throw DxvkError("DxbcProgramInfo::executionModel: Unsupported program type"); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxbc/dxbc_common.h b/utils/dxvk-1.10.3/src/dxbc/dxbc_common.h new file mode 100644 index 00000000000..9c490d62c68 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxbc/dxbc_common.h @@ -0,0 +1,68 @@ +#pragma once + +#include "dxbc_include.h" + +namespace dxvk { + + /** + * \brief DXBC Program type + * + * Defines the shader stage that a DXBC + * module has been compiled form. + */ + enum class DxbcProgramType : uint16_t { + PixelShader = 0, + VertexShader = 1, + GeometryShader = 2, + HullShader = 3, + DomainShader = 4, + ComputeShader = 5, + }; + + + /** + * \brief DXBC shader info + * + * Stores the shader program type. + */ + class DxbcProgramInfo { + + public: + + DxbcProgramInfo() { } + DxbcProgramInfo(DxbcProgramType type) + : m_type(type) { } + + /** + * \brief Program type + * \returns Program type + */ + DxbcProgramType type() const { + return m_type; + } + + /** + * \brief Vulkan shader stage + * + * The \c VkShaderStageFlagBits constant + * that corresponds to the program type. + * \returns Vulkan shaer stage + */ + VkShaderStageFlagBits shaderStage() const; + + /** + * \brief SPIR-V execution model + * + * The execution model that corresponds + * to the Vulkan shader stage. + * \returns SPIR-V execution model + */ + spv::ExecutionModel executionModel() const; + + private: + + DxbcProgramType m_type = DxbcProgramType::PixelShader; + + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxbc/dxbc_compiler.cpp b/utils/dxvk-1.10.3/src/dxbc/dxbc_compiler.cpp new file mode 100644 index 00000000000..01420c043fc --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxbc/dxbc_compiler.cpp @@ -0,0 +1,7981 @@ +#include "dxbc_compiler.h" + +namespace dxvk { + + constexpr uint32_t Icb_BindingSlotId = 14; + constexpr uint32_t Icb_MaxBakedDwords = 16; + + constexpr uint32_t PerVertex_Position = 0; + constexpr uint32_t PerVertex_CullDist = 1; + constexpr uint32_t PerVertex_ClipDist = 2; + + DxbcCompiler::DxbcCompiler( + const std::string& fileName, + const DxbcModuleInfo& moduleInfo, + const DxbcProgramInfo& programInfo, + const Rc& isgn, + const Rc& osgn, + const Rc& psgn, + const DxbcAnalysisInfo& analysis) + : m_moduleInfo (moduleInfo), + m_programInfo(programInfo), + m_module (spvVersion(1, 3)), + m_isgn (isgn), + m_osgn (osgn), + m_psgn (psgn), + m_analysis (&analysis) { + // Declare an entry point ID. We'll need it during the + // initialization phase where the execution mode is set. + m_entryPointId = m_module.allocateId(); + + // Set the shader name so that we recognize it in renderdoc + m_module.setDebugSource( + spv::SourceLanguageUnknown, 0, + m_module.addDebugString(fileName.c_str()), + nullptr); + + if (Logger::logLevel() <= LogLevel::Debug) { + if (m_isgn != nullptr) { + Logger::debug(str::format("Input Signature for - ", fileName.c_str(), "\n")); + m_isgn->printEntries(); + } + if (m_osgn != nullptr) { + Logger::debug(str::format("Output Signature for - ", fileName.c_str(), "\n")); + m_osgn->printEntries(); + } + if (m_psgn != nullptr) { + Logger::debug(str::format("Patch Constant Signature for - ", fileName.c_str(), "\n")); + m_psgn->printEntries(); + } + } + + // Set the memory model. This is the same for all shaders. + m_module.setMemoryModel( + spv::AddressingModelLogical, + spv::MemoryModelGLSL450); + + // Make sure our interface registers are clear + for (uint32_t i = 0; i < DxbcMaxInterfaceRegs; i++) { + m_vRegs.at(i) = DxbcRegisterPointer { }; + m_oRegs.at(i) = DxbcRegisterPointer { }; + } + + this->emitInit(); + } + + + DxbcCompiler::~DxbcCompiler() { + + } + + + void DxbcCompiler::processInstruction(const DxbcShaderInstruction& ins) { + m_lastOp = m_currOp; + m_currOp = ins.op; + + switch (ins.opClass) { + case DxbcInstClass::Declaration: + return this->emitDcl(ins); + + case DxbcInstClass::CustomData: + return this->emitCustomData(ins); + + case DxbcInstClass::Atomic: + return this->emitAtomic(ins); + + case DxbcInstClass::AtomicCounter: + return this->emitAtomicCounter(ins); + + case DxbcInstClass::Barrier: + return this->emitBarrier(ins); + + case DxbcInstClass::BitExtract: + return this->emitBitExtract(ins); + + case DxbcInstClass::BitInsert: + return this->emitBitInsert(ins); + + case DxbcInstClass::BitScan: + return this->emitBitScan(ins); + + case DxbcInstClass::BufferQuery: + return this->emitBufferQuery(ins); + + case DxbcInstClass::BufferLoad: + return this->emitBufferLoad(ins); + + case DxbcInstClass::BufferStore: + return this->emitBufferStore(ins); + + case DxbcInstClass::ConvertFloat16: + return this->emitConvertFloat16(ins); + + case DxbcInstClass::ConvertFloat64: + return this->emitConvertFloat64(ins); + + case DxbcInstClass::ControlFlow: + return this->emitControlFlow(ins); + + case DxbcInstClass::GeometryEmit: + return this->emitGeometryEmit(ins); + + case DxbcInstClass::HullShaderPhase: + return this->emitHullShaderPhase(ins); + + case DxbcInstClass::HullShaderInstCnt: + return this->emitHullShaderInstCnt(ins); + + case DxbcInstClass::Interpolate: + return this->emitInterpolate(ins); + + case DxbcInstClass::NoOperation: + return; + + case DxbcInstClass::TextureQuery: + return this->emitTextureQuery(ins); + + case DxbcInstClass::TextureQueryLod: + return this->emitTextureQueryLod(ins); + + case DxbcInstClass::TextureQueryMs: + return this->emitTextureQueryMs(ins); + + case DxbcInstClass::TextureQueryMsPos: + return this->emitTextureQueryMsPos(ins); + + case DxbcInstClass::TextureFetch: + return this->emitTextureFetch(ins); + + case DxbcInstClass::TextureGather: + return this->emitTextureGather(ins); + + case DxbcInstClass::TextureSample: + return this->emitTextureSample(ins); + + case DxbcInstClass::TypedUavLoad: + return this->emitTypedUavLoad(ins); + + case DxbcInstClass::TypedUavStore: + return this->emitTypedUavStore(ins); + + case DxbcInstClass::VectorAlu: + return this->emitVectorAlu(ins); + + case DxbcInstClass::VectorCmov: + return this->emitVectorCmov(ins); + + case DxbcInstClass::VectorCmp: + return this->emitVectorCmp(ins); + + case DxbcInstClass::VectorDeriv: + return this->emitVectorDeriv(ins); + + case DxbcInstClass::VectorDot: + return this->emitVectorDot(ins); + + case DxbcInstClass::VectorIdiv: + return this->emitVectorIdiv(ins); + + case DxbcInstClass::VectorImul: + return this->emitVectorImul(ins); + + case DxbcInstClass::VectorMsad: + return this->emitVectorMsad(ins); + + case DxbcInstClass::VectorShift: + return this->emitVectorShift(ins); + + case DxbcInstClass::VectorSinCos: + return this->emitVectorSinCos(ins); + + default: + Logger::warn( + str::format("DxbcCompiler: Unhandled opcode class: ", + ins.op)); + } + } + + + void DxbcCompiler::processXfbPassthrough() { + m_module.setExecutionMode (m_entryPointId, spv::ExecutionModeInputPoints); + m_module.setExecutionMode (m_entryPointId, spv::ExecutionModeOutputPoints); + m_module.setOutputVertices(m_entryPointId, 1); + m_module.setInvocations (m_entryPointId, 1); + + for (auto e = m_isgn->begin(); e != m_isgn->end(); e++) { + emitDclInput(e->registerId, 1, + e->componentMask, DxbcSystemValue::None, + DxbcInterpolationMode::Undefined); + } + + // Figure out which streams to enable + uint32_t streamMask = 0; + + for (size_t i = 0; i < m_xfbVars.size(); i++) + streamMask |= 1u << m_xfbVars[i].streamId; + + for (uint32_t streamId : bit::BitMask(streamMask)) { + emitXfbOutputSetup(streamId, true); + m_module.opEmitVertex(m_module.constu32(streamId)); + } + + // End the main function + emitFunctionEnd(); + } + + + Rc DxbcCompiler::finalize() { + // Depending on the shader type, this will prepare + // input registers, call various shader functions + // and write back the output registers. + switch (m_programInfo.type()) { + case DxbcProgramType::VertexShader: this->emitVsFinalize(); break; + case DxbcProgramType::HullShader: this->emitHsFinalize(); break; + case DxbcProgramType::DomainShader: this->emitDsFinalize(); break; + case DxbcProgramType::GeometryShader: this->emitGsFinalize(); break; + case DxbcProgramType::PixelShader: this->emitPsFinalize(); break; + case DxbcProgramType::ComputeShader: this->emitCsFinalize(); break; + } + + // Emit float control mode if the extension is supported + this->emitFloatControl(); + + // Declare the entry point, we now have all the + // information we need, including the interfaces + m_module.addEntryPoint(m_entryPointId, + m_programInfo.executionModel(), "main", + m_entryPointInterfaces.size(), + m_entryPointInterfaces.data()); + m_module.setDebugName(m_entryPointId, "main"); + + // Create the shader object + DxvkShaderCreateInfo info; + info.stage = m_programInfo.shaderStage(); + info.resourceSlotCount = m_resourceSlots.size(); + info.resourceSlots = m_resourceSlots.data(); + info.inputMask = m_inputMask; + info.outputMask = m_outputMask; + info.uniformSize = m_immConstData.size(); + info.uniformData = m_immConstData.data(); + + if (m_moduleInfo.xfb) { + info.xfbRasterizedStream = m_moduleInfo.xfb->rasterizedStream; + + for (uint32_t i = 0; i < 4; i++) + info.xfbStrides[i] = m_moduleInfo.xfb->strides[i]; + } + + return new DxvkShader(info, m_module.compile()); + } + + + void DxbcCompiler::emitDcl(const DxbcShaderInstruction& ins) { + switch (ins.op) { + case DxbcOpcode::DclGlobalFlags: + return this->emitDclGlobalFlags(ins); + + case DxbcOpcode::DclIndexRange: + return; // not needed for anything + + case DxbcOpcode::DclTemps: + return this->emitDclTemps(ins); + + case DxbcOpcode::DclIndexableTemp: + return this->emitDclIndexableTemp(ins); + + case DxbcOpcode::DclInput: + case DxbcOpcode::DclInputSgv: + case DxbcOpcode::DclInputSiv: + case DxbcOpcode::DclInputPs: + case DxbcOpcode::DclInputPsSgv: + case DxbcOpcode::DclInputPsSiv: + case DxbcOpcode::DclOutput: + case DxbcOpcode::DclOutputSgv: + case DxbcOpcode::DclOutputSiv: + return this->emitDclInterfaceReg(ins); + + case DxbcOpcode::DclConstantBuffer: + return this->emitDclConstantBuffer(ins); + + case DxbcOpcode::DclSampler: + return this->emitDclSampler(ins); + + case DxbcOpcode::DclStream: + return this->emitDclStream(ins); + + case DxbcOpcode::DclUavTyped: + case DxbcOpcode::DclResource: + return this->emitDclResourceTyped(ins); + + case DxbcOpcode::DclUavRaw: + case DxbcOpcode::DclResourceRaw: + case DxbcOpcode::DclUavStructured: + case DxbcOpcode::DclResourceStructured: + return this->emitDclResourceRawStructured(ins); + + case DxbcOpcode::DclThreadGroupSharedMemoryRaw: + case DxbcOpcode::DclThreadGroupSharedMemoryStructured: + return this->emitDclThreadGroupSharedMemory(ins); + + case DxbcOpcode::DclGsInputPrimitive: + return this->emitDclGsInputPrimitive(ins); + + case DxbcOpcode::DclGsOutputPrimitiveTopology: + return this->emitDclGsOutputTopology(ins); + + case DxbcOpcode::DclMaxOutputVertexCount: + return this->emitDclMaxOutputVertexCount(ins); + + case DxbcOpcode::DclInputControlPointCount: + return this->emitDclInputControlPointCount(ins); + + case DxbcOpcode::DclOutputControlPointCount: + return this->emitDclOutputControlPointCount(ins); + + case DxbcOpcode::DclHsMaxTessFactor: + return this->emitDclHsMaxTessFactor(ins); + + case DxbcOpcode::DclTessDomain: + return this->emitDclTessDomain(ins); + + case DxbcOpcode::DclTessPartitioning: + return this->emitDclTessPartitioning(ins); + + case DxbcOpcode::DclTessOutputPrimitive: + return this->emitDclTessOutputPrimitive(ins); + + case DxbcOpcode::DclThreadGroup: + return this->emitDclThreadGroup(ins); + + case DxbcOpcode::DclGsInstanceCount: + return this->emitDclGsInstanceCount(ins); + + default: + Logger::warn( + str::format("DxbcCompiler: Unhandled opcode: ", + ins.op)); + } + } + + + void DxbcCompiler::emitDclGlobalFlags(const DxbcShaderInstruction& ins) { + const DxbcGlobalFlags flags = ins.controls.globalFlags(); + + if (flags.test(DxbcGlobalFlag::RefactoringAllowed)) + m_precise = false; + + if (flags.test(DxbcGlobalFlag::EarlyFragmentTests)) + m_module.setExecutionMode(m_entryPointId, spv::ExecutionModeEarlyFragmentTests); + } + + + void DxbcCompiler::emitDclTemps(const DxbcShaderInstruction& ins) { + // dcl_temps has one operand: + // (imm0) Number of temp registers + + // Ignore this and declare temps on demand. + } + + + void DxbcCompiler::emitDclIndexableTemp(const DxbcShaderInstruction& ins) { + // dcl_indexable_temps has three operands: + // (imm0) Array register index (x#) + // (imm1) Number of vectors stored in the array + // (imm2) Component count of each individual vector. This is + // always 4 in fxc-generated binaries and therefore useless. + const uint32_t regId = ins.imm[0].u32; + + DxbcRegisterInfo info; + info.type.ctype = DxbcScalarType::Float32; + info.type.ccount = m_analysis->xRegMasks.at(regId).minComponents(); + info.type.alength = ins.imm[1].u32; + info.sclass = spv::StorageClassPrivate; + + if (regId >= m_xRegs.size()) + m_xRegs.resize(regId + 1); + + m_xRegs.at(regId).ccount = info.type.ccount; + m_xRegs.at(regId).alength = info.type.alength; + m_xRegs.at(regId).varId = emitNewVariable(info); + + m_module.setDebugName(m_xRegs.at(regId).varId, + str::format("x", regId).c_str()); + } + + + void DxbcCompiler::emitDclInterfaceReg(const DxbcShaderInstruction& ins) { + switch (ins.dst[0].type) { + case DxbcOperandType::InputControlPoint: + if (m_programInfo.type() != DxbcProgramType::HullShader) + break; + [[fallthrough]]; + + case DxbcOperandType::Input: + case DxbcOperandType::Output: { + // dcl_input and dcl_output instructions + // have the following operands: + // (dst0) The register to declare + // (imm0) The system value (optional) + uint32_t regDim = 0; + uint32_t regIdx = 0; + + // In the vertex and fragment shader stage, the + // operand indices will have the following format: + // (0) Register index + // + // In other stages, the input and output registers + // may be declared as arrays of a fixed size: + // (0) Array length + // (1) Register index + if (ins.dst[0].idxDim == 2) { + regDim = ins.dst[0].idx[0].offset; + regIdx = ins.dst[0].idx[1].offset; + } else if (ins.dst[0].idxDim == 1) { + regIdx = ins.dst[0].idx[0].offset; + } else { + Logger::err(str::format( + "DxbcCompiler: ", ins.op, + ": Invalid index dimension")); + return; + } + + // This declaration may map an output register to a system + // value. If that is the case, the system value type will + // be stored in the second operand. + const bool hasSv = + ins.op == DxbcOpcode::DclInputSgv + || ins.op == DxbcOpcode::DclInputSiv + || ins.op == DxbcOpcode::DclInputPsSgv + || ins.op == DxbcOpcode::DclInputPsSiv + || ins.op == DxbcOpcode::DclOutputSgv + || ins.op == DxbcOpcode::DclOutputSiv; + + DxbcSystemValue sv = DxbcSystemValue::None; + + if (hasSv) + sv = static_cast(ins.imm[0].u32); + + // In the pixel shader, inputs are declared with an + // interpolation mode that is part of the op token. + const bool hasInterpolationMode = + ins.op == DxbcOpcode::DclInputPs + || ins.op == DxbcOpcode::DclInputPsSiv; + + DxbcInterpolationMode im = DxbcInterpolationMode::Undefined; + + if (hasInterpolationMode) + im = ins.controls.interpolation(); + + // Declare the actual input/output variable + switch (ins.op) { + case DxbcOpcode::DclInput: + case DxbcOpcode::DclInputSgv: + case DxbcOpcode::DclInputSiv: + case DxbcOpcode::DclInputPs: + case DxbcOpcode::DclInputPsSgv: + case DxbcOpcode::DclInputPsSiv: + this->emitDclInput(regIdx, regDim, ins.dst[0].mask, sv, im); + break; + + case DxbcOpcode::DclOutput: + case DxbcOpcode::DclOutputSgv: + case DxbcOpcode::DclOutputSiv: + this->emitDclOutput(regIdx, regDim, ins.dst[0].mask, sv, im); + break; + + default: + Logger::err(str::format( + "DxbcCompiler: Unexpected opcode: ", + ins.op)); + } + } break; + + case DxbcOperandType::InputThreadId: { + m_cs.builtinGlobalInvocationId = emitNewBuiltinVariable({ + { DxbcScalarType::Uint32, 3, 0 }, + spv::StorageClassInput }, + spv::BuiltInGlobalInvocationId, + "vThreadId"); + } break; + + case DxbcOperandType::InputThreadGroupId: { + m_cs.builtinWorkgroupId = emitNewBuiltinVariable({ + { DxbcScalarType::Uint32, 3, 0 }, + spv::StorageClassInput }, + spv::BuiltInWorkgroupId, + "vThreadGroupId"); + } break; + + case DxbcOperandType::InputThreadIdInGroup: { + m_cs.builtinLocalInvocationId = emitNewBuiltinVariable({ + { DxbcScalarType::Uint32, 3, 0 }, + spv::StorageClassInput }, + spv::BuiltInLocalInvocationId, + "vThreadIdInGroup"); + } break; + + case DxbcOperandType::InputThreadIndexInGroup: { + m_cs.builtinLocalInvocationIndex = emitNewBuiltinVariable({ + { DxbcScalarType::Uint32, 1, 0 }, + spv::StorageClassInput }, + spv::BuiltInLocalInvocationIndex, + "vThreadIndexInGroup"); + } break; + + case DxbcOperandType::InputCoverageMask: { + m_ps.builtinSampleMaskIn = emitNewBuiltinVariable({ + { DxbcScalarType::Uint32, 1, 1 }, + spv::StorageClassInput }, + spv::BuiltInSampleMask, + "vCoverage"); + } break; + + case DxbcOperandType::OutputCoverageMask: { + m_ps.builtinSampleMaskOut = emitNewBuiltinVariable({ + { DxbcScalarType::Uint32, 1, 1 }, + spv::StorageClassOutput }, + spv::BuiltInSampleMask, + "oMask"); + } break; + + case DxbcOperandType::OutputDepth: { + m_module.setExecutionMode(m_entryPointId, + spv::ExecutionModeDepthReplacing); + m_ps.builtinDepth = emitNewBuiltinVariable({ + { DxbcScalarType::Float32, 1, 0 }, + spv::StorageClassOutput }, + spv::BuiltInFragDepth, + "oDepth"); + } break; + + case DxbcOperandType::OutputStencilRef: { + m_module.enableExtension("SPV_EXT_shader_stencil_export"); + m_module.enableCapability(spv::CapabilityStencilExportEXT); + m_module.setExecutionMode(m_entryPointId, + spv::ExecutionModeStencilRefReplacingEXT); + m_ps.builtinStencilRef = emitNewBuiltinVariable({ + { DxbcScalarType::Sint32, 1, 0 }, + spv::StorageClassOutput }, + spv::BuiltInFragStencilRefEXT, + "oStencilRef"); + } break; + + case DxbcOperandType::OutputDepthGe: { + m_module.setExecutionMode(m_entryPointId, spv::ExecutionModeDepthReplacing); + m_module.setExecutionMode(m_entryPointId, spv::ExecutionModeDepthGreater); + m_ps.builtinDepth = emitNewBuiltinVariable({ + { DxbcScalarType::Float32, 1, 0 }, + spv::StorageClassOutput }, + spv::BuiltInFragDepth, + "oDepthGe"); + } break; + + case DxbcOperandType::OutputDepthLe: { + m_module.setExecutionMode(m_entryPointId, spv::ExecutionModeDepthReplacing); + m_module.setExecutionMode(m_entryPointId, spv::ExecutionModeDepthLess); + m_ps.builtinDepth = emitNewBuiltinVariable({ + { DxbcScalarType::Float32, 1, 0 }, + spv::StorageClassOutput }, + spv::BuiltInFragDepth, + "oDepthLe"); + } break; + + case DxbcOperandType::InputPrimitiveId: { + m_primitiveIdIn = emitNewBuiltinVariable({ + { DxbcScalarType::Uint32, 1, 0 }, + spv::StorageClassInput }, + spv::BuiltInPrimitiveId, + "vPrim"); + } break; + + case DxbcOperandType::InputDomainPoint: { + m_ds.builtinTessCoord = emitNewBuiltinVariable({ + { DxbcScalarType::Float32, 3, 0 }, + spv::StorageClassInput }, + spv::BuiltInTessCoord, + "vDomain"); + } break; + + case DxbcOperandType::InputForkInstanceId: + case DxbcOperandType::InputJoinInstanceId: { + auto phase = this->getCurrentHsForkJoinPhase(); + + phase->instanceIdPtr = m_module.newVar( + m_module.defPointerType( + m_module.defIntType(32, 0), + spv::StorageClassFunction), + spv::StorageClassFunction); + + m_module.opStore(phase->instanceIdPtr, phase->instanceId); + m_module.setDebugName(phase->instanceIdPtr, + ins.dst[0].type == DxbcOperandType::InputForkInstanceId + ? "vForkInstanceId" : "vJoinInstanceId"); + } break; + + case DxbcOperandType::OutputControlPointId: { + // This system value map to the invocation + // ID, which has been declared already. + } break; + + case DxbcOperandType::InputPatchConstant: + case DxbcOperandType::OutputControlPoint: { + // These have been declared as global input and + // output arrays, so there's nothing left to do. + } break; + + case DxbcOperandType::InputGsInstanceId: { + m_gs.builtinInvocationId = emitNewBuiltinVariable({ + { DxbcScalarType::Uint32, 1, 0 }, + spv::StorageClassInput }, + spv::BuiltInInvocationId, + "vInstanceID"); + } break; + + default: + Logger::err(str::format( + "DxbcCompiler: Unsupported operand type declaration: ", + ins.dst[0].type)); + + } + } + + + void DxbcCompiler::emitDclInput( + uint32_t regIdx, + uint32_t regDim, + DxbcRegMask regMask, + DxbcSystemValue sv, + DxbcInterpolationMode im) { + // Avoid declaring the same variable multiple times. + // This may happen when multiple system values are + // mapped to different parts of the same register. + if (m_vRegs.at(regIdx).id == 0 && sv == DxbcSystemValue::None) { + const DxbcVectorType regType = getInputRegType(regIdx); + + DxbcRegisterInfo info; + info.type.ctype = regType.ctype; + info.type.ccount = regType.ccount; + info.type.alength = regDim; + info.sclass = spv::StorageClassInput; + + const uint32_t varId = emitNewVariable(info); + + m_module.decorateLocation(varId, regIdx); + m_module.setDebugName(varId, str::format("v", regIdx).c_str()); + m_entryPointInterfaces.push_back(varId); + + m_vRegs.at(regIdx) = { regType, varId }; + + // Interpolation mode, used in pixel shaders + if (im == DxbcInterpolationMode::Constant) + m_module.decorate(varId, spv::DecorationFlat); + + if (im == DxbcInterpolationMode::LinearCentroid + || im == DxbcInterpolationMode::LinearNoPerspectiveCentroid) + m_module.decorate(varId, spv::DecorationCentroid); + + if (im == DxbcInterpolationMode::LinearNoPerspective + || im == DxbcInterpolationMode::LinearNoPerspectiveCentroid + || im == DxbcInterpolationMode::LinearNoPerspectiveSample) + m_module.decorate(varId, spv::DecorationNoPerspective); + + if (im == DxbcInterpolationMode::LinearSample + || im == DxbcInterpolationMode::LinearNoPerspectiveSample) { + m_module.enableCapability(spv::CapabilitySampleRateShading); + m_module.decorate(varId, spv::DecorationSample); + } + + // Declare the input slot as defined + m_inputMask |= 1u << regIdx; + m_vArrayLength = std::max(m_vArrayLength, regIdx + 1); + } else if (sv != DxbcSystemValue::None) { + // Add a new system value mapping if needed + bool skipSv = sv == DxbcSystemValue::ClipDistance + || sv == DxbcSystemValue::CullDistance; + + if (!skipSv) + m_vMappings.push_back({ regIdx, regMask, sv }); + } + } + + + void DxbcCompiler::emitDclOutput( + uint32_t regIdx, + uint32_t regDim, + DxbcRegMask regMask, + DxbcSystemValue sv, + DxbcInterpolationMode im) { + // Add a new system value mapping if needed. Clip + // and cull distances are handled separately. + if (sv != DxbcSystemValue::None + && sv != DxbcSystemValue::ClipDistance + && sv != DxbcSystemValue::CullDistance) + m_oMappings.push_back({ regIdx, regMask, sv }); + + if (m_programInfo.type() == DxbcProgramType::HullShader) { + // Hull shaders don't use standard outputs + if (getCurrentHsForkJoinPhase() != nullptr) + m_hs.outputPerPatchMask |= 1 << regIdx; + } else if (m_oRegs.at(regIdx).id == 0) { + // Avoid declaring the same variable multiple times. + // This may happen when multiple system values are + // mapped to different parts of the same register. + const DxbcVectorType regType = getOutputRegType(regIdx); + + DxbcRegisterInfo info; + info.type.ctype = regType.ctype; + info.type.ccount = regType.ccount; + info.type.alength = regDim; + info.sclass = spv::StorageClassOutput; + + // In xfb mode, we set up the actual + // output vars when emitting a vertex + if (m_moduleInfo.xfb != nullptr) + info.sclass = spv::StorageClassPrivate; + + // In geometry shaders, don't duplicate system value outputs + // to stay within device limits. The pixel shader will read + // all GS system value outputs as system value inputs. + if (m_programInfo.type() == DxbcProgramType::GeometryShader && sv != DxbcSystemValue::None) + info.sclass = spv::StorageClassPrivate; + + const uint32_t varId = this->emitNewVariable(info); + m_module.setDebugName(varId, str::format("o", regIdx).c_str()); + + if (info.sclass == spv::StorageClassOutput) { + m_module.decorateLocation(varId, regIdx); + m_entryPointInterfaces.push_back(varId); + + // Add index decoration for potential dual-source blending + if (m_programInfo.type() == DxbcProgramType::PixelShader) + m_module.decorateIndex(varId, 0); + + // Declare vertex positions in all stages as invariant, even if + // this is not the last stage, to help with potential Z fighting. + if (sv == DxbcSystemValue::Position && m_moduleInfo.options.invariantPosition) + m_module.decorate(varId, spv::DecorationInvariant); + } + + m_oRegs.at(regIdx) = { regType, varId }; + + // Declare the output slot as defined + m_outputMask |= 1u << regIdx; + } + } + + + void DxbcCompiler::emitDclConstantBuffer(const DxbcShaderInstruction& ins) { + // dcl_constant_buffer has one operand with two indices: + // (0) Constant buffer register ID (cb#) + // (1) Number of constants in the buffer + const uint32_t bufferId = ins.dst[0].idx[0].offset; + const uint32_t elementCount = ins.dst[0].idx[1].offset; + + bool asSsbo = m_moduleInfo.options.dynamicIndexedConstantBufferAsSsbo + && ins.controls.accessType() == DxbcConstantBufferAccessType::DynamicallyIndexed; + + this->emitDclConstantBufferVar(bufferId, elementCount, + str::format("cb", bufferId).c_str(), asSsbo); + } + + + void DxbcCompiler::emitDclConstantBufferVar( + uint32_t regIdx, + uint32_t numConstants, + const char* name, + bool asSsbo) { + // Uniform buffer data is stored as a fixed-size array + // of 4x32-bit vectors. SPIR-V requires explicit strides. + const uint32_t arrayType = m_module.defArrayTypeUnique( + getVectorTypeId({ DxbcScalarType::Float32, 4 }), + m_module.constu32(numConstants)); + m_module.decorateArrayStride(arrayType, 16); + + // SPIR-V requires us to put that array into a + // struct and decorate that struct as a block. + const uint32_t structType = m_module.defStructTypeUnique(1, &arrayType); + + m_module.decorate(structType, asSsbo + ? spv::DecorationBufferBlock + : spv::DecorationBlock); + m_module.memberDecorateOffset(structType, 0, 0); + + m_module.setDebugName (structType, str::format(name, "_t").c_str()); + m_module.setDebugMemberName (structType, 0, "m"); + + // Variable that we'll use to access the buffer + const uint32_t varId = m_module.newVar( + m_module.defPointerType(structType, spv::StorageClassUniform), + spv::StorageClassUniform); + + m_module.setDebugName(varId, name); + + // Compute the DXVK binding slot index for the buffer. + // D3D11 needs to bind the actual buffers to this slot. + uint32_t bindingId = computeConstantBufferBinding( + m_programInfo.type(), regIdx); + + m_module.decorateDescriptorSet(varId, 0); + m_module.decorateBinding(varId, bindingId); + + if (asSsbo) + m_module.decorate(varId, spv::DecorationNonWritable); + + // Declare a specialization constant which will + // store whether or not the resource is bound. + const uint32_t specConstId = m_module.specConstBool(true); + m_module.decorateSpecId(specConstId, bindingId); + m_module.setDebugName(specConstId, + str::format(name, "_bound").c_str()); + + DxbcConstantBuffer buf; + buf.varId = varId; + buf.size = numConstants; + m_constantBuffers.at(regIdx) = buf; + + // Store descriptor info for the shader interface + DxvkResourceSlot resource; + resource.slot = bindingId; + resource.type = asSsbo + ? VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + : VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + resource.view = VK_IMAGE_VIEW_TYPE_MAX_ENUM; + resource.access = VK_ACCESS_UNIFORM_READ_BIT; + m_resourceSlots.push_back(resource); + } + + + void DxbcCompiler::emitDclSampler(const DxbcShaderInstruction& ins) { + // dclSampler takes one operand: + // (dst0) The sampler register to declare + const uint32_t samplerId = ins.dst[0].idx[0].offset; + + // The sampler type is opaque, but we still have to + // define a pointer and a variable in oder to use it + const uint32_t samplerType = m_module.defSamplerType(); + const uint32_t samplerPtrType = m_module.defPointerType( + samplerType, spv::StorageClassUniformConstant); + + // Define the sampler variable + const uint32_t varId = m_module.newVar(samplerPtrType, + spv::StorageClassUniformConstant); + m_module.setDebugName(varId, + str::format("s", samplerId).c_str()); + + m_samplers.at(samplerId).varId = varId; + m_samplers.at(samplerId).typeId = samplerType; + + // Compute binding slot index for the sampler + uint32_t bindingId = computeSamplerBinding( + m_programInfo.type(), samplerId); + + m_module.decorateDescriptorSet(varId, 0); + m_module.decorateBinding(varId, bindingId); + + // Store descriptor info for the shader interface + DxvkResourceSlot resource; + resource.slot = bindingId; + resource.type = VK_DESCRIPTOR_TYPE_SAMPLER; + resource.view = VK_IMAGE_VIEW_TYPE_MAX_ENUM; + resource.access = 0; + m_resourceSlots.push_back(resource); + } + + + void DxbcCompiler::emitDclStream(const DxbcShaderInstruction& ins) { + if (ins.dst[0].idx[0].offset != 0 && m_moduleInfo.xfb == nullptr) + Logger::err("Dxbc: Multiple streams not supported"); + } + + + void DxbcCompiler::emitDclResourceTyped(const DxbcShaderInstruction& ins) { + // dclResource takes two operands: + // (dst0) The resource register ID + // (imm0) The resource return type + const uint32_t registerId = ins.dst[0].idx[0].offset; + + // We also handle unordered access views here + const bool isUav = ins.op == DxbcOpcode::DclUavTyped; + + if (isUav) { + if (m_moduleInfo.options.useStorageImageReadWithoutFormat) + m_module.enableCapability(spv::CapabilityStorageImageReadWithoutFormat); + m_module.enableCapability(spv::CapabilityStorageImageWriteWithoutFormat); + } + + // Defines the type of the resource (texture2D, ...) + const DxbcResourceDim resourceType = ins.controls.resourceDim(); + + // Defines the type of a read operation. DXBC has the ability + // to define four different types whereas SPIR-V only allows + // one, but in practice this should not be much of a problem. + auto xType = static_cast( + bit::extract(ins.imm[0].u32, 0, 3)); + auto yType = static_cast( + bit::extract(ins.imm[0].u32, 4, 7)); + auto zType = static_cast( + bit::extract(ins.imm[0].u32, 8, 11)); + auto wType = static_cast( + bit::extract(ins.imm[0].u32, 12, 15)); + + if ((xType != yType) || (xType != zType) || (xType != wType)) + Logger::warn("DxbcCompiler: dcl_resource: Ignoring resource return types"); + + // Declare the actual sampled type + const DxbcScalarType sampledType = [xType] { + switch (xType) { + // FIXME is this correct? There's no documentation about it + case DxbcResourceReturnType::Mixed: return DxbcScalarType::Uint32; + // FIXME do we have to manually clamp writes to SNORM/UNORM resources? + case DxbcResourceReturnType::Snorm: return DxbcScalarType::Float32; + case DxbcResourceReturnType::Unorm: return DxbcScalarType::Float32; + case DxbcResourceReturnType::Float: return DxbcScalarType::Float32; + case DxbcResourceReturnType::Sint: return DxbcScalarType::Sint32; + case DxbcResourceReturnType::Uint: return DxbcScalarType::Uint32; + default: throw DxvkError(str::format("DxbcCompiler: Invalid sampled type: ", xType)); + } + }(); + + // Declare the resource type + const uint32_t sampledTypeId = getScalarTypeId(sampledType); + const DxbcImageInfo typeInfo = getResourceType(resourceType, isUav); + + // Declare additional capabilities if necessary + switch (resourceType) { + case DxbcResourceDim::Buffer: + m_module.enableCapability(isUav + ? spv::CapabilityImageBuffer + : spv::CapabilitySampledBuffer); + break; + + case DxbcResourceDim::Texture1D: + case DxbcResourceDim::Texture1DArr: + m_module.enableCapability(isUav + ? spv::CapabilityImage1D + : spv::CapabilitySampled1D); + break; + + case DxbcResourceDim::TextureCubeArr: + m_module.enableCapability( + spv::CapabilitySampledCubeArray); + break; + + default: + // No additional capabilities required + break; + } + + // If the read-without-format capability is not set and this + // image is access via a typed load, or if atomic operations + // are used,, we must define the image format explicitly. + spv::ImageFormat imageFormat = spv::ImageFormatUnknown; + + if (isUav) { + if ((m_analysis->uavInfos[registerId].accessAtomicOp) + || (m_analysis->uavInfos[registerId].accessTypedLoad + && !m_moduleInfo.options.useStorageImageReadWithoutFormat)) + imageFormat = getScalarImageFormat(sampledType); + } + + // We do not know whether the image is going to be used as + // a color image or a depth image yet, but we can pick the + // correct type when creating a sampled image object. + const uint32_t imageTypeId = m_module.defImageType(sampledTypeId, + typeInfo.dim, 0, typeInfo.array, typeInfo.ms, typeInfo.sampled, + imageFormat); + + // We'll declare the texture variable with the color type + // and decide which one to use when the texture is sampled. + const uint32_t resourcePtrType = m_module.defPointerType( + imageTypeId, spv::StorageClassUniformConstant); + + const uint32_t varId = m_module.newVar(resourcePtrType, + spv::StorageClassUniformConstant); + + m_module.setDebugName(varId, + str::format(isUav ? "u" : "t", registerId).c_str()); + + // Compute the DXVK binding slot index for the resource. + // D3D11 needs to bind the actual resource to this slot. + uint32_t bindingId = isUav + ? computeUavBinding(m_programInfo.type(), registerId) + : computeSrvBinding(m_programInfo.type(), registerId); + + m_module.decorateDescriptorSet(varId, 0); + m_module.decorateBinding(varId, bindingId); + + if (ins.controls.uavFlags().test(DxbcUavFlag::GloballyCoherent)) + m_module.decorate(varId, spv::DecorationCoherent); + + // Declare a specialization constant which will + // store whether or not the resource is bound. + const uint32_t specConstId = m_module.specConstBool(true); + m_module.decorateSpecId(specConstId, bindingId); + m_module.setDebugName(specConstId, + str::format(isUav ? "u" : "t", registerId, "_bound").c_str()); + + if (isUav) { + DxbcUav uav; + uav.type = DxbcResourceType::Typed; + uav.imageInfo = typeInfo; + uav.varId = varId; + uav.ctrId = 0; + uav.specId = specConstId; + uav.sampledType = sampledType; + uav.sampledTypeId = sampledTypeId; + uav.imageTypeId = imageTypeId; + uav.structStride = 0; + uav.structAlign = 0; + m_uavs.at(registerId) = uav; + } else { + DxbcShaderResource res; + res.type = DxbcResourceType::Typed; + res.imageInfo = typeInfo; + res.varId = varId; + res.specId = specConstId; + res.sampledType = sampledType; + res.sampledTypeId = sampledTypeId; + res.imageTypeId = imageTypeId; + res.colorTypeId = imageTypeId; + res.depthTypeId = 0; + res.structStride = 0; + res.structAlign = 0; + + if ((sampledType == DxbcScalarType::Float32) + && (resourceType == DxbcResourceDim::Texture2D + || resourceType == DxbcResourceDim::Texture2DArr + || resourceType == DxbcResourceDim::TextureCube + || resourceType == DxbcResourceDim::TextureCubeArr)) { + res.depthTypeId = m_module.defImageType(sampledTypeId, + typeInfo.dim, 1, typeInfo.array, typeInfo.ms, typeInfo.sampled, + spv::ImageFormatUnknown); + } + + m_textures.at(registerId) = res; + } + + // Store descriptor info for the shader interface + DxvkResourceSlot resource; + resource.slot = bindingId; + resource.view = typeInfo.vtype; + + if (isUav) { + resource.type = resourceType == DxbcResourceDim::Buffer + ? VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER + : VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + resource.access = m_analysis->uavInfos[registerId].accessFlags; + + if (!(resource.access & VK_ACCESS_SHADER_WRITE_BIT)) + m_module.decorate(varId, spv::DecorationNonWritable); + if (!(resource.access & VK_ACCESS_SHADER_READ_BIT)) + m_module.decorate(varId, spv::DecorationNonReadable); + } else { + resource.type = resourceType == DxbcResourceDim::Buffer + ? VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER + : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + resource.access = VK_ACCESS_SHADER_READ_BIT; + } + + m_resourceSlots.push_back(resource); + } + + + void DxbcCompiler::emitDclResourceRawStructured(const DxbcShaderInstruction& ins) { + // dcl_resource_raw and dcl_uav_raw take one argument: + // (dst0) The resource register ID + // dcl_resource_structured and dcl_uav_structured take two arguments: + // (dst0) The resource register ID + // (imm0) Structure stride, in bytes + const uint32_t registerId = ins.dst[0].idx[0].offset; + + const bool isUav = ins.op == DxbcOpcode::DclUavRaw + || ins.op == DxbcOpcode::DclUavStructured; + + const bool isStructured = ins.op == DxbcOpcode::DclUavStructured + || ins.op == DxbcOpcode::DclResourceStructured; + + const DxbcScalarType sampledType = DxbcScalarType::Uint32; + const uint32_t sampledTypeId = getScalarTypeId(sampledType); + + const DxbcImageInfo typeInfo = { spv::DimBuffer, 0, 0, isUav ? 2u : 1u, VK_IMAGE_VIEW_TYPE_MAX_ENUM }; + + // Declare the resource type + uint32_t resTypeId = 0; + uint32_t varId = 0; + + // Write back resource info + DxbcResourceType resType = isStructured + ? DxbcResourceType::Structured + : DxbcResourceType::Raw; + + uint32_t resStride = isStructured + ? ins.imm[0].u32 + : 0; + + uint32_t resAlign = isStructured + ? (resStride & -resStride) + : 16; + + // Compute the DXVK binding slot index for the resource. + uint32_t bindingId = isUav + ? computeUavBinding(m_programInfo.type(), registerId) + : computeSrvBinding(m_programInfo.type(), registerId); + + // Test whether we should use a raw SSBO for this resource + bool useRawSsbo = m_moduleInfo.options.minSsboAlignment <= resAlign; + + if (useRawSsbo) { + uint32_t elemType = getScalarTypeId(DxbcScalarType::Uint32); + uint32_t arrayType = m_module.defRuntimeArrayTypeUnique(elemType); + uint32_t structType = m_module.defStructTypeUnique(1, &arrayType); + uint32_t ptrType = m_module.defPointerType(structType, spv::StorageClassUniform); + + resTypeId = m_module.defPointerType(elemType, spv::StorageClassUniform); + varId = m_module.newVar(ptrType, spv::StorageClassUniform); + + m_module.decorateArrayStride(arrayType, sizeof(uint32_t)); + m_module.decorate(structType, spv::DecorationBufferBlock); + m_module.memberDecorateOffset(structType, 0, 0); + + m_module.setDebugName(structType, + str::format(isUav ? "u" : "t", registerId, "_t").c_str()); + m_module.setDebugMemberName(structType, 0, "m"); + } else { + // Structured and raw buffers are represented as + // texel buffers consisting of 32-bit integers. + m_module.enableCapability(isUav + ? spv::CapabilityImageBuffer + : spv::CapabilitySampledBuffer); + + resTypeId = m_module.defImageType(sampledTypeId, + typeInfo.dim, 0, typeInfo.array, typeInfo.ms, typeInfo.sampled, + spv::ImageFormatR32ui); + + varId = m_module.newVar( + m_module.defPointerType(resTypeId, spv::StorageClassUniformConstant), + spv::StorageClassUniformConstant); + } + + m_module.setDebugName(varId, + str::format(isUav ? "u" : "t", registerId).c_str()); + + m_module.decorateDescriptorSet(varId, 0); + m_module.decorateBinding(varId, bindingId); + + if (ins.controls.uavFlags().test(DxbcUavFlag::GloballyCoherent)) + m_module.decorate(varId, spv::DecorationCoherent); + + // Declare a specialization constant which will + // store whether or not the resource is bound. + const uint32_t specConstId = m_module.specConstBool(true); + m_module.decorateSpecId(specConstId, bindingId); + m_module.setDebugName(specConstId, + str::format(isUav ? "u" : "t", registerId, "_bound").c_str()); + + if (isUav) { + DxbcUav uav; + uav.type = resType; + uav.imageInfo = typeInfo; + uav.varId = varId; + uav.ctrId = 0; + uav.specId = specConstId; + uav.sampledType = sampledType; + uav.sampledTypeId = sampledTypeId; + uav.imageTypeId = resTypeId; + uav.structStride = resStride; + uav.structAlign = resAlign; + m_uavs.at(registerId) = uav; + } else { + DxbcShaderResource res; + res.type = resType; + res.imageInfo = typeInfo; + res.varId = varId; + res.specId = specConstId; + res.sampledType = sampledType; + res.sampledTypeId = sampledTypeId; + res.imageTypeId = resTypeId; + res.colorTypeId = resTypeId; + res.depthTypeId = 0; + res.structStride = resStride; + res.structAlign = resAlign; + m_textures.at(registerId) = res; + } + + // Store descriptor info for the shader interface + DxvkResourceSlot resource; + resource.slot = bindingId; + resource.type = useRawSsbo + ? VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + : (isUav + ? VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER + : VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER); + resource.view = VK_IMAGE_VIEW_TYPE_MAX_ENUM; + resource.access = isUav + ? m_analysis->uavInfos[registerId].accessFlags + : VK_ACCESS_SHADER_READ_BIT; + + if (useRawSsbo || isUav) { + if (!(resource.access & VK_ACCESS_SHADER_WRITE_BIT)) + m_module.decorate(varId, spv::DecorationNonWritable); + if (!(resource.access & VK_ACCESS_SHADER_READ_BIT)) + m_module.decorate(varId, spv::DecorationNonReadable); + } + + m_resourceSlots.push_back(resource); + } + + + void DxbcCompiler::emitDclThreadGroupSharedMemory(const DxbcShaderInstruction& ins) { + // dcl_tgsm_raw takes two arguments: + // (dst0) The resource register ID + // (imm0) Block size, in bytes + // dcl_tgsm_structured takes three arguments: + // (dst0) The resource register ID + // (imm0) Structure stride, in bytes + // (imm1) Structure count + const bool isStructured = ins.op == DxbcOpcode::DclThreadGroupSharedMemoryStructured; + + const uint32_t regId = ins.dst[0].idx[0].offset; + + if (regId >= m_gRegs.size()) + m_gRegs.resize(regId + 1); + + const uint32_t elementStride = isStructured ? ins.imm[0].u32 : 0; + const uint32_t elementCount = isStructured ? ins.imm[1].u32 : ins.imm[0].u32; + + DxbcRegisterInfo varInfo; + varInfo.type.ctype = DxbcScalarType::Uint32; + varInfo.type.ccount = 1; + varInfo.type.alength = isStructured + ? elementCount * elementStride / 4 + : elementCount / 4; + varInfo.sclass = spv::StorageClassWorkgroup; + + m_gRegs[regId].type = isStructured + ? DxbcResourceType::Structured + : DxbcResourceType::Raw; + m_gRegs[regId].elementStride = elementStride; + m_gRegs[regId].elementCount = elementCount; + m_gRegs[regId].varId = emitNewVariable(varInfo); + + m_module.setDebugName(m_gRegs[regId].varId, + str::format("g", regId).c_str()); + } + + + void DxbcCompiler::emitDclGsInputPrimitive(const DxbcShaderInstruction& ins) { + // The input primitive type is stored within in the + // control bits of the opcode token. In SPIR-V, we + // have to define an execution mode. + const spv::ExecutionMode mode = [&] { + switch (ins.controls.primitive()) { + case DxbcPrimitive::Point: return spv::ExecutionModeInputPoints; + case DxbcPrimitive::Line: return spv::ExecutionModeInputLines; + case DxbcPrimitive::Triangle: return spv::ExecutionModeTriangles; + case DxbcPrimitive::LineAdj: return spv::ExecutionModeInputLinesAdjacency; + case DxbcPrimitive::TriangleAdj: return spv::ExecutionModeInputTrianglesAdjacency; + default: throw DxvkError("DxbcCompiler: Unsupported primitive type"); + } + }(); + + m_gs.inputPrimitive = ins.controls.primitive(); + m_module.setExecutionMode(m_entryPointId, mode); + + const uint32_t vertexCount + = primitiveVertexCount(m_gs.inputPrimitive); + + emitDclInputArray(vertexCount); + emitDclInputPerVertex(vertexCount, "gs_vertex_in"); + } + + + void DxbcCompiler::emitDclGsOutputTopology(const DxbcShaderInstruction& ins) { + // The input primitive topology is stored within in the + // control bits of the opcode token. In SPIR-V, we have + // to define an execution mode. + const spv::ExecutionMode mode = [&] { + switch (ins.controls.primitiveTopology()) { + case DxbcPrimitiveTopology::PointList: return spv::ExecutionModeOutputPoints; + case DxbcPrimitiveTopology::LineStrip: return spv::ExecutionModeOutputLineStrip; + case DxbcPrimitiveTopology::TriangleStrip: return spv::ExecutionModeOutputTriangleStrip; + default: throw DxvkError("DxbcCompiler: Unsupported primitive topology"); + } + }(); + + m_module.setExecutionMode(m_entryPointId, mode); + } + + + void DxbcCompiler::emitDclMaxOutputVertexCount(const DxbcShaderInstruction& ins) { + // dcl_max_output_vertex_count has one operand: + // (imm0) The maximum number of vertices + m_gs.outputVertexCount = ins.imm[0].u32; + + m_module.setOutputVertices(m_entryPointId, m_gs.outputVertexCount); + } + + + void DxbcCompiler::emitDclInputControlPointCount(const DxbcShaderInstruction& ins) { + // dcl_input_control_points has the control point + // count embedded within the opcode token. + if (m_programInfo.type() == DxbcProgramType::HullShader) { + m_hs.vertexCountIn = ins.controls.controlPointCount(); + + emitDclInputArray(m_hs.vertexCountIn); + } else { + m_ds.vertexCountIn = ins.controls.controlPointCount(); + + m_ds.inputPerPatch = emitTessInterfacePerPatch (spv::StorageClassInput); + m_ds.inputPerVertex = emitTessInterfacePerVertex(spv::StorageClassInput, m_ds.vertexCountIn); + } + } + + + void DxbcCompiler::emitDclOutputControlPointCount(const DxbcShaderInstruction& ins) { + // dcl_output_control_points has the control point + // count embedded within the opcode token. + m_hs.vertexCountOut = ins.controls.controlPointCount(); + + m_hs.outputPerPatch = emitTessInterfacePerPatch(spv::StorageClassPrivate); + m_hs.outputPerVertex = emitTessInterfacePerVertex(spv::StorageClassOutput, m_hs.vertexCountOut); + + m_module.setOutputVertices(m_entryPointId, m_hs.vertexCountOut); + } + + + void DxbcCompiler::emitDclHsMaxTessFactor(const DxbcShaderInstruction& ins) { + m_hs.maxTessFactor = ins.imm[0].f32; + } + + + void DxbcCompiler::emitDclTessDomain(const DxbcShaderInstruction& ins) { + const spv::ExecutionMode executionMode = [&] { + switch (ins.controls.tessDomain()) { + case DxbcTessDomain::Isolines: return spv::ExecutionModeIsolines; + case DxbcTessDomain::Triangles: return spv::ExecutionModeTriangles; + case DxbcTessDomain::Quads: return spv::ExecutionModeQuads; + default: throw DxvkError("Dxbc: Invalid tess domain"); + } + }(); + + m_module.setExecutionMode(m_entryPointId, executionMode); + } + + + void DxbcCompiler::emitDclTessPartitioning(const DxbcShaderInstruction& ins) { + const spv::ExecutionMode executionMode = [&] { + switch (ins.controls.tessPartitioning()) { + case DxbcTessPartitioning::Pow2: + case DxbcTessPartitioning::Integer: return spv::ExecutionModeSpacingEqual; + case DxbcTessPartitioning::FractOdd: return spv::ExecutionModeSpacingFractionalOdd; + case DxbcTessPartitioning::FractEven: return spv::ExecutionModeSpacingFractionalEven; + default: throw DxvkError("Dxbc: Invalid tess partitioning"); + } + }(); + + m_module.setExecutionMode(m_entryPointId, executionMode); + } + + + void DxbcCompiler::emitDclTessOutputPrimitive(const DxbcShaderInstruction& ins) { + switch (ins.controls.tessOutputPrimitive()) { + case DxbcTessOutputPrimitive::Point: + m_module.setExecutionMode(m_entryPointId, spv::ExecutionModePointMode); + break; + + case DxbcTessOutputPrimitive::Line: + break; + + case DxbcTessOutputPrimitive::TriangleCw: + m_module.setExecutionMode(m_entryPointId, spv::ExecutionModeVertexOrderCw); + break; + + case DxbcTessOutputPrimitive::TriangleCcw: + m_module.setExecutionMode(m_entryPointId, spv::ExecutionModeVertexOrderCcw); + break; + + default: + throw DxvkError("Dxbc: Invalid tess output primitive"); + } + } + + + void DxbcCompiler::emitDclThreadGroup(const DxbcShaderInstruction& ins) { + // dcl_thread_group has three operands: + // (imm0) Number of threads in X dimension + // (imm1) Number of threads in Y dimension + // (imm2) Number of threads in Z dimension + m_cs.workgroupSizeX = ins.imm[0].u32; + m_cs.workgroupSizeY = ins.imm[1].u32; + m_cs.workgroupSizeZ = ins.imm[2].u32; + + m_module.setLocalSize(m_entryPointId, + ins.imm[0].u32, ins.imm[1].u32, ins.imm[2].u32); + } + + + void DxbcCompiler::emitDclGsInstanceCount(const DxbcShaderInstruction& ins) { + // dcl_gs_instance_count has one operand: + // (imm0) Number of geometry shader invocations + m_module.setInvocations(m_entryPointId, ins.imm[0].u32); + m_gs.invocationCount = ins.imm[0].u32; + } + + + uint32_t DxbcCompiler::emitDclUavCounter(uint32_t regId) { + // Declare a structure type which holds the UAV counter + if (m_uavCtrStructType == 0) { + const uint32_t t_u32 = m_module.defIntType(32, 0); + const uint32_t t_struct = m_module.defStructTypeUnique(1, &t_u32); + + m_module.decorate(t_struct, spv::DecorationBufferBlock); + m_module.memberDecorateOffset(t_struct, 0, 0); + + m_module.setDebugName (t_struct, "uav_meta"); + m_module.setDebugMemberName(t_struct, 0, "ctr"); + + m_uavCtrStructType = t_struct; + m_uavCtrPointerType = m_module.defPointerType( + t_struct, spv::StorageClassUniform); + } + + // Declare the buffer variable + const uint32_t varId = m_module.newVar( + m_uavCtrPointerType, spv::StorageClassUniform); + + m_module.setDebugName(varId, + str::format("u", regId, "_meta").c_str()); + + uint32_t bindingId = computeUavCounterBinding( + m_programInfo.type(), regId); + + m_module.decorateDescriptorSet(varId, 0); + m_module.decorateBinding(varId, bindingId); + + // Declare the storage buffer binding + DxvkResourceSlot resource; + resource.slot = bindingId; + resource.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + resource.view = VK_IMAGE_VIEW_TYPE_MAX_ENUM; + resource.access = VK_ACCESS_SHADER_READ_BIT + | VK_ACCESS_SHADER_WRITE_BIT; + m_resourceSlots.push_back(resource); + + return varId; + } + + + void DxbcCompiler::emitDclImmediateConstantBuffer(const DxbcShaderInstruction& ins) { + if (m_immConstBuf != 0) + throw DxvkError("DxbcCompiler: Immediate constant buffer already declared"); + + if ((ins.customDataSize & 0x3) != 0) + throw DxvkError("DxbcCompiler: Immediate constant buffer size not a multiple of four DWORDs"); + + if (ins.customDataSize <= Icb_MaxBakedDwords) { + this->emitDclImmediateConstantBufferBaked( + ins.customDataSize, ins.customData); + } else { + this->emitDclImmediateConstantBufferUbo( + ins.customDataSize, ins.customData); + } + } + + + void DxbcCompiler::emitDclImmediateConstantBufferBaked( + uint32_t dwordCount, + const uint32_t* dwordArray) { + // Declare individual vector constants as 4x32-bit vectors + std::array vectorIds; + + DxbcVectorType vecType; + vecType.ctype = DxbcScalarType::Uint32; + vecType.ccount = 4; + + const uint32_t vectorTypeId = getVectorTypeId(vecType); + const uint32_t vectorCount = dwordCount / 4; + + for (uint32_t i = 0; i < vectorCount; i++) { + std::array scalarIds = { + m_module.constu32(dwordArray[4 * i + 0]), + m_module.constu32(dwordArray[4 * i + 1]), + m_module.constu32(dwordArray[4 * i + 2]), + m_module.constu32(dwordArray[4 * i + 3]), + }; + + vectorIds.at(i) = m_module.constComposite( + vectorTypeId, scalarIds.size(), scalarIds.data()); + } + + // Declare the array that contains all the vectors + DxbcArrayType arrInfo; + arrInfo.ctype = DxbcScalarType::Uint32; + arrInfo.ccount = 4; + arrInfo.alength = vectorCount; + + const uint32_t arrayTypeId = getArrayTypeId(arrInfo); + const uint32_t arrayId = m_module.constComposite( + arrayTypeId, vectorCount, vectorIds.data()); + + // Declare the variable that will hold the constant + // data and initialize it with the constant array. + const uint32_t pointerTypeId = m_module.defPointerType( + arrayTypeId, spv::StorageClassPrivate); + + m_immConstBuf = m_module.newVarInit( + pointerTypeId, spv::StorageClassPrivate, + arrayId); + m_module.setDebugName(m_immConstBuf, "icb"); + } + + + void DxbcCompiler::emitDclImmediateConstantBufferUbo( + uint32_t dwordCount, + const uint32_t* dwordArray) { + this->emitDclConstantBufferVar(Icb_BindingSlotId, dwordCount / 4, "icb", + m_moduleInfo.options.dynamicIndexedConstantBufferAsSsbo); + m_immConstData.resize(dwordCount * sizeof(uint32_t)); + std::memcpy(m_immConstData.data(), dwordArray, m_immConstData.size()); + } + + + void DxbcCompiler::emitCustomData(const DxbcShaderInstruction& ins) { + switch (ins.customDataType) { + case DxbcCustomDataClass::ImmConstBuf: + return emitDclImmediateConstantBuffer(ins); + + default: + Logger::warn(str::format( + "DxbcCompiler: Unsupported custom data block: ", + ins.customDataType)); + } + } + + + void DxbcCompiler::emitVectorAlu(const DxbcShaderInstruction& ins) { + std::array src; + + for (uint32_t i = 0; i < ins.srcCount; i++) + src.at(i) = emitRegisterLoad(ins.src[i], ins.dst[0].mask); + + DxbcRegisterValue dst; + dst.type.ctype = ins.dst[0].dataType; + dst.type.ccount = ins.dst[0].mask.popCount(); + + if (isDoubleType(ins.dst[0].dataType)) + dst.type.ccount /= 2; + + const uint32_t typeId = getVectorTypeId(dst.type); + + switch (ins.op) { + ///////////////////// + // Move instructions + case DxbcOpcode::Mov: + case DxbcOpcode::DMov: + dst.id = src.at(0).id; + break; + + ///////////////////////////////////// + // ALU operations on float32 numbers + case DxbcOpcode::Add: + case DxbcOpcode::DAdd: + dst.id = m_module.opFAdd(typeId, + src.at(0).id, src.at(1).id); + break; + + case DxbcOpcode::Div: + case DxbcOpcode::DDiv: + dst.id = m_module.opFDiv(typeId, + src.at(0).id, src.at(1).id); + break; + + case DxbcOpcode::Exp: + dst.id = m_module.opExp2( + typeId, src.at(0).id); + break; + + case DxbcOpcode::Frc: + dst.id = m_module.opFract( + typeId, src.at(0).id); + break; + + case DxbcOpcode::Log: + dst.id = m_module.opLog2( + typeId, src.at(0).id); + break; + + case DxbcOpcode::Mad: + case DxbcOpcode::DFma: + dst.id = m_module.opFFma(typeId, + src.at(0).id, src.at(1).id, src.at(2).id); + break; + + case DxbcOpcode::Max: + case DxbcOpcode::DMax: + dst.id = m_module.opNMax(typeId, + src.at(0).id, src.at(1).id); + break; + + case DxbcOpcode::Min: + case DxbcOpcode::DMin: + dst.id = m_module.opNMin(typeId, + src.at(0).id, src.at(1).id); + break; + + case DxbcOpcode::Mul: + case DxbcOpcode::DMul: + dst.id = m_module.opFMul(typeId, + src.at(0).id, src.at(1).id); + break; + + case DxbcOpcode::Rcp: + dst.id = m_module.opFDiv(typeId, + emitBuildConstVecf32( + 1.0f, 1.0f, 1.0f, 1.0f, + ins.dst[0].mask).id, + src.at(0).id); + break; + + case DxbcOpcode::DRcp: + dst.id = m_module.opFDiv(typeId, + emitBuildConstVecf64(1.0, 1.0, + ins.dst[0].mask).id, + src.at(0).id); + break; + + case DxbcOpcode::RoundNe: + dst.id = m_module.opRoundEven( + typeId, src.at(0).id); + break; + + case DxbcOpcode::RoundNi: + dst.id = m_module.opFloor( + typeId, src.at(0).id); + break; + + case DxbcOpcode::RoundPi: + dst.id = m_module.opCeil( + typeId, src.at(0).id); + break; + + case DxbcOpcode::RoundZ: + dst.id = m_module.opTrunc( + typeId, src.at(0).id); + break; + + case DxbcOpcode::Rsq: + dst.id = m_module.opInverseSqrt( + typeId, src.at(0).id); + break; + + case DxbcOpcode::Sqrt: + dst.id = m_module.opSqrt( + typeId, src.at(0).id); + break; + + ///////////////////////////////////// + // ALU operations on signed integers + case DxbcOpcode::IAdd: + dst.id = m_module.opIAdd(typeId, + src.at(0).id, src.at(1).id); + break; + + case DxbcOpcode::IMad: + case DxbcOpcode::UMad: + dst.id = m_module.opIAdd(typeId, + m_module.opIMul(typeId, + src.at(0).id, src.at(1).id), + src.at(2).id); + break; + + case DxbcOpcode::IMax: + dst.id = m_module.opSMax(typeId, + src.at(0).id, src.at(1).id); + break; + + case DxbcOpcode::IMin: + dst.id = m_module.opSMin(typeId, + src.at(0).id, src.at(1).id); + break; + + case DxbcOpcode::INeg: + dst.id = m_module.opSNegate( + typeId, src.at(0).id); + break; + + /////////////////////////////////////// + // ALU operations on unsigned integers + case DxbcOpcode::UMax: + dst.id = m_module.opUMax(typeId, + src.at(0).id, src.at(1).id); + break; + + case DxbcOpcode::UMin: + dst.id = m_module.opUMin(typeId, + src.at(0).id, src.at(1).id); + break; + + /////////////////////////////////////// + // Bit operations on unsigned integers + case DxbcOpcode::And: + dst.id = m_module.opBitwiseAnd(typeId, + src.at(0).id, src.at(1).id); + break; + + case DxbcOpcode::Not: + dst.id = m_module.opNot( + typeId, src.at(0).id); + break; + + case DxbcOpcode::Or: + dst.id = m_module.opBitwiseOr(typeId, + src.at(0).id, src.at(1).id); + break; + + case DxbcOpcode::Xor: + dst.id = m_module.opBitwiseXor(typeId, + src.at(0).id, src.at(1).id); + break; + + case DxbcOpcode::CountBits: + dst.id = m_module.opBitCount( + typeId, src.at(0).id); + break; + + case DxbcOpcode::BfRev: + dst.id = m_module.opBitReverse( + typeId, src.at(0).id); + break; + + /////////////////////////// + // Conversion instructions + case DxbcOpcode::ItoF: + dst.id = m_module.opConvertStoF( + typeId, src.at(0).id); + break; + + case DxbcOpcode::UtoF: + dst.id = m_module.opConvertUtoF( + typeId, src.at(0).id); + break; + + case DxbcOpcode::FtoI: + dst.id = m_module.opConvertFtoS( + typeId, src.at(0).id); + break; + + case DxbcOpcode::FtoU: + dst.id = m_module.opConvertFtoU( + typeId, src.at(0).id); + break; + + default: + Logger::warn(str::format( + "DxbcCompiler: Unhandled instruction: ", + ins.op)); + return; + } + + if (ins.controls.precise() || m_precise) + m_module.decorate(dst.id, spv::DecorationNoContraction); + + // Store computed value + dst = emitDstOperandModifiers(dst, ins.modifiers); + emitRegisterStore(ins.dst[0], dst); + } + + + void DxbcCompiler::emitVectorCmov(const DxbcShaderInstruction& ins) { + // movc and swapc have the following operands: + // (dst0) The first destination register + // (dst1) The second destination register (swapc only) + // (src0) The condition vector + // (src1) Vector to select from if the condition is not 0 + // (src2) Vector to select from if the condition is 0 + DxbcRegMask condMask = ins.dst[0].mask; + + if (ins.dst[0].dataType == DxbcScalarType::Float64) { + condMask = DxbcRegMask( + condMask[0] && condMask[1], + condMask[2] && condMask[3], + false, false); + } + + const DxbcRegisterValue condition = emitRegisterLoad(ins.src[0], condMask); + const DxbcRegisterValue selectTrue = emitRegisterLoad(ins.src[1], ins.dst[0].mask); + const DxbcRegisterValue selectFalse = emitRegisterLoad(ins.src[2], ins.dst[0].mask); + + uint32_t componentCount = condMask.popCount(); + + // We'll compare against a vector of zeroes to generate a + // boolean vector, which in turn will be used by OpSelect + uint32_t zeroType = m_module.defIntType(32, 0); + uint32_t boolType = m_module.defBoolType(); + + uint32_t zero = m_module.constu32(0); + + if (componentCount > 1) { + zeroType = m_module.defVectorType(zeroType, componentCount); + boolType = m_module.defVectorType(boolType, componentCount); + + const std::array zeroVec = { zero, zero, zero, zero }; + zero = m_module.constComposite(zeroType, componentCount, zeroVec.data()); + } + + // In case of swapc, the second destination operand receives + // the output that a cmov instruction would normally get + const uint32_t trueIndex = ins.op == DxbcOpcode::Swapc ? 1 : 0; + + for (uint32_t i = 0; i < ins.dstCount; i++) { + DxbcRegisterValue result; + result.type.ctype = ins.dst[i].dataType; + result.type.ccount = componentCount; + result.id = m_module.opSelect( + getVectorTypeId(result.type), + m_module.opINotEqual(boolType, condition.id, zero), + i == trueIndex ? selectTrue.id : selectFalse.id, + i != trueIndex ? selectTrue.id : selectFalse.id); + + result = emitDstOperandModifiers(result, ins.modifiers); + emitRegisterStore(ins.dst[i], result); + } + } + + void DxbcCompiler::emitVectorCmp(const DxbcShaderInstruction& ins) { + // Compare instructions have three operands: + // (dst0) The destination register + // (src0) The first vector to compare + // (src1) The second vector to compare + uint32_t componentCount = ins.dst[0].mask.popCount(); + + // For 64-bit operations, we'll return a 32-bit + // vector, so we have to adjust the read mask + DxbcRegMask srcMask = ins.dst[0].mask; + + if (isDoubleType(ins.src[0].dataType)) { + srcMask = DxbcRegMask( + componentCount > 0, componentCount > 0, + componentCount > 1, componentCount > 1); + } + + const std::array src = { + emitRegisterLoad(ins.src[0], srcMask), + emitRegisterLoad(ins.src[1], srcMask), + }; + + // Condition, which is a boolean vector used + // to select between the ~0u and 0u vectors. + uint32_t condition = 0; + uint32_t conditionType = m_module.defBoolType(); + + if (componentCount > 1) + conditionType = m_module.defVectorType(conditionType, componentCount); + + bool invert = false; + + switch (ins.op) { + case DxbcOpcode::Ne: + case DxbcOpcode::DNe: + invert = true; + [[fallthrough]]; + + case DxbcOpcode::Eq: + case DxbcOpcode::DEq: + condition = m_module.opFOrdEqual( + conditionType, src.at(0).id, src.at(1).id); + break; + + case DxbcOpcode::Ge: + case DxbcOpcode::DGe: + condition = m_module.opFOrdGreaterThanEqual( + conditionType, src.at(0).id, src.at(1).id); + break; + + case DxbcOpcode::Lt: + case DxbcOpcode::DLt: + condition = m_module.opFOrdLessThan( + conditionType, src.at(0).id, src.at(1).id); + break; + + case DxbcOpcode::IEq: + condition = m_module.opIEqual( + conditionType, src.at(0).id, src.at(1).id); + break; + + case DxbcOpcode::IGe: + condition = m_module.opSGreaterThanEqual( + conditionType, src.at(0).id, src.at(1).id); + break; + + case DxbcOpcode::ILt: + condition = m_module.opSLessThan( + conditionType, src.at(0).id, src.at(1).id); + break; + + case DxbcOpcode::INe: + condition = m_module.opINotEqual( + conditionType, src.at(0).id, src.at(1).id); + break; + + case DxbcOpcode::UGe: + condition = m_module.opUGreaterThanEqual( + conditionType, src.at(0).id, src.at(1).id); + break; + + case DxbcOpcode::ULt: + condition = m_module.opULessThan( + conditionType, src.at(0).id, src.at(1).id); + break; + + default: + Logger::warn(str::format( + "DxbcCompiler: Unhandled instruction: ", + ins.op)); + return; + } + + // Generate constant vectors for selection + uint32_t sFalse = m_module.constu32( 0u); + uint32_t sTrue = m_module.constu32(~0u); + + DxbcRegisterValue result; + result.type.ctype = DxbcScalarType::Uint32; + result.type.ccount = componentCount; + + const uint32_t typeId = getVectorTypeId(result.type); + + if (componentCount > 1) { + const std::array vFalse = { sFalse, sFalse, sFalse, sFalse }; + const std::array vTrue = { sTrue, sTrue, sTrue, sTrue }; + + sFalse = m_module.constComposite(typeId, componentCount, vFalse.data()); + sTrue = m_module.constComposite(typeId, componentCount, vTrue .data()); + } + + if (invert) + std::swap(sFalse, sTrue); + + // Perform component-wise mask selection + // based on the condition evaluated above. + result.id = m_module.opSelect( + typeId, condition, sTrue, sFalse); + + emitRegisterStore(ins.dst[0], result); + } + + + void DxbcCompiler::emitVectorDeriv(const DxbcShaderInstruction& ins) { + // Derivative instructions have two operands: + // (dst0) Destination register for the derivative + // (src0) The operand to compute the derivative of + DxbcRegisterValue value = emitRegisterLoad(ins.src[0], ins.dst[0].mask); + const uint32_t typeId = getVectorTypeId(value.type); + + switch (ins.op) { + case DxbcOpcode::DerivRtx: + value.id = m_module.opDpdx(typeId, value.id); + break; + + case DxbcOpcode::DerivRty: + value.id = m_module.opDpdy(typeId, value.id); + break; + + case DxbcOpcode::DerivRtxCoarse: + value.id = m_module.opDpdxCoarse(typeId, value.id); + break; + + case DxbcOpcode::DerivRtyCoarse: + value.id = m_module.opDpdyCoarse(typeId, value.id); + break; + + case DxbcOpcode::DerivRtxFine: + value.id = m_module.opDpdxFine(typeId, value.id); + break; + + case DxbcOpcode::DerivRtyFine: + value.id = m_module.opDpdyFine(typeId, value.id); + break; + + default: + Logger::warn(str::format( + "DxbcCompiler: Unhandled instruction: ", + ins.op)); + return; + } + + value = emitDstOperandModifiers(value, ins.modifiers); + emitRegisterStore(ins.dst[0], value); + } + + + void DxbcCompiler::emitVectorDot(const DxbcShaderInstruction& ins) { + const DxbcRegMask srcMask(true, + ins.op >= DxbcOpcode::Dp2, + ins.op >= DxbcOpcode::Dp3, + ins.op >= DxbcOpcode::Dp4); + + const std::array src = { + emitRegisterLoad(ins.src[0], srcMask), + emitRegisterLoad(ins.src[1], srcMask), + }; + + DxbcRegisterValue dst; + dst.type.ctype = ins.dst[0].dataType; + dst.type.ccount = 1; + + dst.id = m_module.opDot( + getVectorTypeId(dst.type), + src.at(0).id, + src.at(1).id); + + if (ins.controls.precise() || m_precise) + m_module.decorate(dst.id, spv::DecorationNoContraction); + + dst = emitDstOperandModifiers(dst, ins.modifiers); + emitRegisterStore(ins.dst[0], dst); + } + + + void DxbcCompiler::emitVectorIdiv(const DxbcShaderInstruction& ins) { + // udiv has four operands: + // (dst0) Quotient destination register + // (dst1) Remainder destination register + // (src0) The first vector to compare + // (src1) The second vector to compare + if (ins.dst[0].type == DxbcOperandType::Null + && ins.dst[1].type == DxbcOperandType::Null) + return; + + // FIXME support this if applications require it + if (ins.dst[0].type != DxbcOperandType::Null + && ins.dst[1].type != DxbcOperandType::Null + && ins.dst[0].mask != ins.dst[1].mask) { + Logger::warn("DxbcCompiler: Idiv with different destination masks not supported"); + return; + } + + // Load source operands as integers with the + // mask of one non-NULL destination operand + const DxbcRegMask srcMask = + ins.dst[0].type != DxbcOperandType::Null + ? ins.dst[0].mask + : ins.dst[1].mask; + + const std::array src = { + emitRegisterLoad(ins.src[0], srcMask), + emitRegisterLoad(ins.src[1], srcMask), + }; + + // Division by zero will return 0xffffffff for both results + auto bvecId = getVectorTypeId({ DxbcScalarType::Bool, srcMask.popCount() }); + + DxbcRegisterValue const0 = emitBuildConstVecu32( 0u, 0u, 0u, 0u, srcMask); + DxbcRegisterValue constff = emitBuildConstVecu32(~0u, ~0u, ~0u, ~0u, srcMask); + + uint32_t cmpValue = m_module.opINotEqual(bvecId, src.at(1).id, const0.id); + + // Compute results only if the destination + // operands are not NULL. + if (ins.dst[0].type != DxbcOperandType::Null) { + DxbcRegisterValue quotient; + quotient.type.ctype = ins.dst[0].dataType; + quotient.type.ccount = ins.dst[0].mask.popCount(); + + quotient.id = m_module.opUDiv( + getVectorTypeId(quotient.type), + src.at(0).id, src.at(1).id); + + quotient.id = m_module.opSelect( + getVectorTypeId(quotient.type), + cmpValue, quotient.id, constff.id); + + quotient = emitDstOperandModifiers(quotient, ins.modifiers); + emitRegisterStore(ins.dst[0], quotient); + } + + if (ins.dst[1].type != DxbcOperandType::Null) { + DxbcRegisterValue remainder; + remainder.type.ctype = ins.dst[1].dataType; + remainder.type.ccount = ins.dst[1].mask.popCount(); + + remainder.id = m_module.opUMod( + getVectorTypeId(remainder.type), + src.at(0).id, src.at(1).id); + + remainder.id = m_module.opSelect( + getVectorTypeId(remainder.type), + cmpValue, remainder.id, constff.id); + + remainder = emitDstOperandModifiers(remainder, ins.modifiers); + emitRegisterStore(ins.dst[1], remainder); + } + } + + + void DxbcCompiler::emitVectorImul(const DxbcShaderInstruction& ins) { + // imul and umul have four operands: + // (dst0) High destination register + // (dst1) Low destination register + // (src0) The first vector to compare + // (src1) The second vector to compare + if (ins.dst[0].type == DxbcOperandType::Null) { + if (ins.dst[1].type == DxbcOperandType::Null) + return; + + // If dst0 is NULL, this instruction behaves just + // like any other three-operand ALU instruction + const std::array src = { + emitRegisterLoad(ins.src[0], ins.dst[1].mask), + emitRegisterLoad(ins.src[1], ins.dst[1].mask), + }; + + DxbcRegisterValue result; + result.type.ctype = ins.dst[1].dataType; + result.type.ccount = ins.dst[1].mask.popCount(); + result.id = m_module.opIMul( + getVectorTypeId(result.type), + src.at(0).id, src.at(1).id); + + result = emitDstOperandModifiers(result, ins.modifiers); + emitRegisterStore(ins.dst[1], result); + } else { + // TODO implement this + Logger::warn("DxbcCompiler: Extended Imul not yet supported"); + } + } + + + void DxbcCompiler::emitVectorMsad(const DxbcShaderInstruction& ins) { + // msad has four operands: + // (dst0) Destination + // (src0) Reference (packed uint8) + // (src1) Source (packed uint8) + // (src2) Accumulator + DxbcRegisterValue refReg = emitRegisterLoad(ins.src[0], ins.dst[0].mask); + DxbcRegisterValue srcReg = emitRegisterLoad(ins.src[1], ins.dst[0].mask); + DxbcRegisterValue result = emitRegisterLoad(ins.src[2], ins.dst[0].mask); + + auto typeId = getVectorTypeId(result.type); + auto bvecId = getVectorTypeId({ DxbcScalarType::Bool, result.type.ccount }); + + for (uint32_t i = 0; i < 4; i++) { + auto shift = m_module.constu32(8 * i); + auto count = m_module.constu32(8); + + auto ref = m_module.opBitFieldUExtract(typeId, refReg.id, shift, count); + auto src = m_module.opBitFieldUExtract(typeId, srcReg.id, shift, count); + + auto zero = emitBuildConstVecu32(0, 0, 0, 0, ins.dst[0].mask); + auto mask = m_module.opINotEqual(bvecId, ref, zero.id); + + auto diff = m_module.opSAbs(typeId, m_module.opISub(typeId, ref, src)); + result.id = m_module.opSelect(typeId, mask, m_module.opIAdd(typeId, result.id, diff), result.id); + } + + result = emitDstOperandModifiers(result, ins.modifiers); + emitRegisterStore(ins.dst[0], result); + } + + + void DxbcCompiler::emitVectorShift(const DxbcShaderInstruction& ins) { + // Shift operations have three operands: + // (dst0) The destination register + // (src0) The register to shift + // (src1) The shift amount (scalar) + DxbcRegisterValue shiftReg = emitRegisterLoad(ins.src[0], ins.dst[0].mask); + DxbcRegisterValue countReg = emitRegisterLoad(ins.src[1], ins.dst[0].mask); + + if (ins.src[1].type != DxbcOperandType::Imm32) + countReg = emitRegisterMaskBits(countReg, 0x1F); + + if (countReg.type.ccount == 1) + countReg = emitRegisterExtend(countReg, shiftReg.type.ccount); + + DxbcRegisterValue result; + result.type.ctype = ins.dst[0].dataType; + result.type.ccount = ins.dst[0].mask.popCount(); + + switch (ins.op) { + case DxbcOpcode::IShl: + result.id = m_module.opShiftLeftLogical( + getVectorTypeId(result.type), + shiftReg.id, countReg.id); + break; + + case DxbcOpcode::IShr: + result.id = m_module.opShiftRightArithmetic( + getVectorTypeId(result.type), + shiftReg.id, countReg.id); + break; + + case DxbcOpcode::UShr: + result.id = m_module.opShiftRightLogical( + getVectorTypeId(result.type), + shiftReg.id, countReg.id); + break; + + default: + Logger::warn(str::format( + "DxbcCompiler: Unhandled instruction: ", + ins.op)); + return; + } + + result = emitDstOperandModifiers(result, ins.modifiers); + emitRegisterStore(ins.dst[0], result); + } + + + void DxbcCompiler::emitVectorSinCos(const DxbcShaderInstruction& ins) { + // sincos has three operands: + // (dst0) Destination register for sin(x) + // (dst1) Destination register for cos(x) + // (src0) Source operand x + + // Load source operand as 32-bit float vector. + const DxbcRegisterValue srcValue = emitRegisterLoad( + ins.src[0], DxbcRegMask(true, true, true, true)); + + // Either output may be DxbcOperandType::Null, in + // which case we don't have to generate any code. + if (ins.dst[0].type != DxbcOperandType::Null) { + const DxbcRegisterValue sinInput = + emitRegisterExtract(srcValue, ins.dst[0].mask); + + DxbcRegisterValue sin; + sin.type = sinInput.type; + sin.id = m_module.opSin( + getVectorTypeId(sin.type), + sinInput.id); + + emitRegisterStore(ins.dst[0], sin); + } + + if (ins.dst[1].type != DxbcOperandType::Null) { + const DxbcRegisterValue cosInput = + emitRegisterExtract(srcValue, ins.dst[1].mask); + + DxbcRegisterValue cos; + cos.type = cosInput.type; + cos.id = m_module.opCos( + getVectorTypeId(cos.type), + cosInput.id); + + emitRegisterStore(ins.dst[1], cos); + } + } + + + void DxbcCompiler::emitGeometryEmit(const DxbcShaderInstruction& ins) { + // In xfb mode we might have multiple streams, so + // we have to figure out which stream to write to + uint32_t streamId = 0; + uint32_t streamVar = 0; + + if (m_moduleInfo.xfb != nullptr) { + streamId = ins.dstCount > 0 ? ins.dst[0].idx[0].offset : 0; + streamVar = m_module.constu32(streamId); + } + + // Checking the negation is easier for EmitThenCut/EmitThenCutStream + bool doEmit = ins.op != DxbcOpcode::Cut && ins.op != DxbcOpcode::CutStream; + bool doCut = ins.op != DxbcOpcode::Emit && ins.op != DxbcOpcode::EmitStream; + + if (doEmit) { + if (m_perVertexOut) + emitOutputSetup(); + emitClipCullStore(DxbcSystemValue::ClipDistance, m_clipDistances); + emitClipCullStore(DxbcSystemValue::CullDistance, m_cullDistances); + emitXfbOutputSetup(streamId, false); + m_module.opEmitVertex(streamVar); + } + + if (doCut) + m_module.opEndPrimitive(streamVar); + } + + + void DxbcCompiler::emitAtomic(const DxbcShaderInstruction& ins) { + // atomic_* operations have the following operands: + // (dst0) Destination u# or g# register + // (src0) Index into the texture or buffer + // (src1) The source value for the operation + // (src2) Second source operand (optional) + // imm_atomic_* operations have the following operands: + // (dst0) Register that receives the result + // (dst1) Destination u# or g# register + // (srcX) As above + const DxbcBufferInfo bufferInfo = getBufferInfo(ins.dst[ins.dstCount - 1]); + + bool isImm = ins.dstCount == 2; + bool isUav = ins.dst[ins.dstCount - 1].type == DxbcOperandType::UnorderedAccessView; + + bool isSsbo = m_moduleInfo.options.minSsboAlignment <= bufferInfo.align + && bufferInfo.type != DxbcResourceType::Typed + && isUav; + + // Perform atomic operations on UAVs only if the UAV + // is bound and if there is nothing else stopping us. + DxbcConditional cond; + + if (isUav) { + uint32_t writeTest = emitUavWriteTest(bufferInfo); + + cond.labelIf = m_module.allocateId(); + cond.labelEnd = m_module.allocateId(); + + m_module.opSelectionMerge(cond.labelEnd, spv::SelectionControlMaskNone); + m_module.opBranchConditional(writeTest, cond.labelIf, cond.labelEnd); + + m_module.opLabel(cond.labelIf); + } + + // Retrieve destination pointer for the atomic operation> + const DxbcRegisterPointer pointer = emitGetAtomicPointer( + ins.dst[ins.dstCount - 1], ins.src[0]); + + // Load source values + std::array src; + + for (uint32_t i = 1; i < ins.srcCount; i++) { + src[i - 1] = emitRegisterBitcast( + emitRegisterLoad(ins.src[i], DxbcRegMask(true, false, false, false)), + pointer.type.ctype); + } + + // Define memory scope and semantics based on the operands + uint32_t scope = 0; + uint32_t semantics = 0; + + if (isUav) { + scope = spv::ScopeDevice; + semantics = spv::MemorySemanticsAcquireReleaseMask; + + semantics |= isSsbo + ? spv::MemorySemanticsUniformMemoryMask + : spv::MemorySemanticsImageMemoryMask; + } else { + scope = spv::ScopeWorkgroup; + semantics = spv::MemorySemanticsWorkgroupMemoryMask + | spv::MemorySemanticsAcquireReleaseMask; + } + + const uint32_t scopeId = m_module.constu32(scope); + const uint32_t semanticsId = m_module.constu32(semantics); + + // Perform the atomic operation on the given pointer + DxbcRegisterValue value; + value.type = pointer.type; + value.id = 0; + + // The result type, which is a scalar integer + const uint32_t typeId = getVectorTypeId(value.type); + + switch (ins.op) { + case DxbcOpcode::AtomicCmpStore: + case DxbcOpcode::ImmAtomicCmpExch: + value.id = m_module.opAtomicCompareExchange( + typeId, pointer.id, scopeId, semanticsId, + m_module.constu32(spv::MemorySemanticsMaskNone), + src[1].id, src[0].id); + break; + + case DxbcOpcode::ImmAtomicExch: + value.id = m_module.opAtomicExchange(typeId, + pointer.id, scopeId, semanticsId, + src[0].id); + break; + + case DxbcOpcode::AtomicIAdd: + case DxbcOpcode::ImmAtomicIAdd: + value.id = m_module.opAtomicIAdd(typeId, + pointer.id, scopeId, semanticsId, + src[0].id); + break; + + case DxbcOpcode::AtomicAnd: + case DxbcOpcode::ImmAtomicAnd: + value.id = m_module.opAtomicAnd(typeId, + pointer.id, scopeId, semanticsId, + src[0].id); + break; + + case DxbcOpcode::AtomicOr: + case DxbcOpcode::ImmAtomicOr: + value.id = m_module.opAtomicOr(typeId, + pointer.id, scopeId, semanticsId, + src[0].id); + break; + + case DxbcOpcode::AtomicXor: + case DxbcOpcode::ImmAtomicXor: + value.id = m_module.opAtomicXor(typeId, + pointer.id, scopeId, semanticsId, + src[0].id); + break; + + case DxbcOpcode::AtomicIMin: + case DxbcOpcode::ImmAtomicIMin: + value.id = m_module.opAtomicSMin(typeId, + pointer.id, scopeId, semanticsId, + src[0].id); + break; + + case DxbcOpcode::AtomicIMax: + case DxbcOpcode::ImmAtomicIMax: + value.id = m_module.opAtomicSMax(typeId, + pointer.id, scopeId, semanticsId, + src[0].id); + break; + + case DxbcOpcode::AtomicUMin: + case DxbcOpcode::ImmAtomicUMin: + value.id = m_module.opAtomicUMin(typeId, + pointer.id, scopeId, semanticsId, + src[0].id); + break; + + case DxbcOpcode::AtomicUMax: + case DxbcOpcode::ImmAtomicUMax: + value.id = m_module.opAtomicUMax(typeId, + pointer.id, scopeId, semanticsId, + src[0].id); + break; + + default: + Logger::warn(str::format( + "DxbcCompiler: Unhandled instruction: ", + ins.op)); + return; + } + + // Write back the result to the destination + // register if this is an imm_atomic_* opcode. + if (isImm) + emitRegisterStore(ins.dst[0], value); + + // End conditional block + if (isUav) { + m_module.opBranch(cond.labelEnd); + m_module.opLabel (cond.labelEnd); + } + } + + + void DxbcCompiler::emitAtomicCounter(const DxbcShaderInstruction& ins) { + // imm_atomic_alloc and imm_atomic_consume have the following operands: + // (dst0) The register that will hold the old counter value + // (dst1) The UAV whose counter is going to be modified + const DxbcBufferInfo bufferInfo = getBufferInfo(ins.dst[1]); + + const uint32_t registerId = ins.dst[1].idx[0].offset; + + if (m_uavs.at(registerId).ctrId == 0) + m_uavs.at(registerId).ctrId = emitDclUavCounter(registerId); + + // Only perform the operation if the UAV is bound + uint32_t writeTest = emitUavWriteTest(bufferInfo); + + DxbcConditional cond; + cond.labelIf = m_module.allocateId(); + cond.labelEnd = m_module.allocateId(); + + m_module.opSelectionMerge(cond.labelEnd, spv::SelectionControlMaskNone); + m_module.opBranchConditional(writeTest, cond.labelIf, cond.labelEnd); + + m_module.opLabel(cond.labelIf); + + // Only use subgroup ops on compute to avoid having to + // deal with helper invocations or hardware limitations + bool useSubgroupOps = m_moduleInfo.options.useSubgroupOpsForAtomicCounters + && m_programInfo.type() == DxbcProgramType::ComputeShader; + + // In case we have subgroup ops enabled, we need to + // count the number of active lanes, the lane index, + // and we need to perform the atomic op conditionally + uint32_t laneCount = 0; + uint32_t laneIndex = 0; + + DxbcConditional elect; + + if (useSubgroupOps) { + m_module.enableCapability(spv::CapabilityGroupNonUniform); + m_module.enableCapability(spv::CapabilityGroupNonUniformBallot); + + uint32_t ballot = m_module.opGroupNonUniformBallot( + getVectorTypeId({ DxbcScalarType::Uint32, 4 }), + m_module.constu32(spv::ScopeSubgroup), + m_module.constBool(true)); + + laneCount = m_module.opGroupNonUniformBallotBitCount( + getScalarTypeId(DxbcScalarType::Uint32), + m_module.constu32(spv::ScopeSubgroup), + spv::GroupOperationReduce, ballot); + + laneIndex = m_module.opGroupNonUniformBallotBitCount( + getScalarTypeId(DxbcScalarType::Uint32), + m_module.constu32(spv::ScopeSubgroup), + spv::GroupOperationExclusiveScan, ballot); + + // Elect one lane to perform the atomic op + uint32_t election = m_module.opGroupNonUniformElect( + m_module.defBoolType(), + m_module.constu32(spv::ScopeSubgroup)); + + elect.labelIf = m_module.allocateId(); + elect.labelEnd = m_module.allocateId(); + + m_module.opSelectionMerge(elect.labelEnd, spv::SelectionControlMaskNone); + m_module.opBranchConditional(election, elect.labelIf, elect.labelEnd); + + m_module.opLabel(elect.labelIf); + } else { + // We're going to use this for the increment + laneCount = m_module.constu32(1); + } + + // Get a pointer to the atomic counter in question + DxbcRegisterInfo ptrType; + ptrType.type.ctype = DxbcScalarType::Uint32; + ptrType.type.ccount = 1; + ptrType.type.alength = 0; + ptrType.sclass = spv::StorageClassUniform; + + uint32_t zeroId = m_module.consti32(0); + uint32_t ptrId = m_module.opAccessChain( + getPointerTypeId(ptrType), + m_uavs.at(registerId).ctrId, + 1, &zeroId); + + // Define memory scope and semantics based on the operands + uint32_t scope = spv::ScopeDevice; + uint32_t semantics = spv::MemorySemanticsUniformMemoryMask + | spv::MemorySemanticsAcquireReleaseMask; + + uint32_t scopeId = m_module.constu32(scope); + uint32_t semanticsId = m_module.constu32(semantics); + + // Compute the result value + DxbcRegisterValue value; + value.type.ctype = DxbcScalarType::Uint32; + value.type.ccount = 1; + + uint32_t typeId = getVectorTypeId(value.type); + + switch (ins.op) { + case DxbcOpcode::ImmAtomicAlloc: + value.id = m_module.opAtomicIAdd(typeId, ptrId, + scopeId, semanticsId, laneCount); + break; + + case DxbcOpcode::ImmAtomicConsume: + value.id = m_module.opAtomicISub(typeId, ptrId, + scopeId, semanticsId, laneCount); + value.id = m_module.opISub(typeId, value.id, laneCount); + break; + + default: + Logger::warn(str::format( + "DxbcCompiler: Unhandled instruction: ", + ins.op)); + return; + } + + // If we're using subgroup ops, we have to broadcast + // the result of the atomic op and compute the index + if (useSubgroupOps) { + m_module.opBranch(elect.labelEnd); + m_module.opLabel (elect.labelEnd); + + uint32_t undef = m_module.constUndef(typeId); + + std::array phiLabels = {{ + { value.id, elect.labelIf }, + { undef, cond.labelIf }, + }}; + + value.id = m_module.opPhi(typeId, + phiLabels.size(), phiLabels.data()); + value.id = m_module.opGroupNonUniformBroadcastFirst(typeId, + m_module.constu32(spv::ScopeSubgroup), value.id); + value.id = m_module.opIAdd(typeId, value.id, laneIndex); + } + + // Store the result + emitRegisterStore(ins.dst[0], value); + + // End conditional block + m_module.opBranch(cond.labelEnd); + m_module.opLabel (cond.labelEnd); + } + + + void DxbcCompiler::emitBarrier(const DxbcShaderInstruction& ins) { + // sync takes no operands. Instead, the synchronization + // scope is defined by the operand control bits. + const DxbcSyncFlags flags = ins.controls.syncFlags(); + + uint32_t executionScope = spv::ScopeInvocation; + uint32_t memoryScope = spv::ScopeInvocation; + uint32_t memorySemantics = 0; + + if (flags.test(DxbcSyncFlag::ThreadsInGroup)) + executionScope = spv::ScopeWorkgroup; + + if (flags.test(DxbcSyncFlag::ThreadGroupSharedMemory)) { + memoryScope = spv::ScopeWorkgroup; + memorySemantics |= spv::MemorySemanticsWorkgroupMemoryMask + | spv::MemorySemanticsAcquireReleaseMask; + } + + if (flags.test(DxbcSyncFlag::UavMemoryGroup)) { + memoryScope = spv::ScopeWorkgroup; + memorySemantics |= spv::MemorySemanticsImageMemoryMask + | spv::MemorySemanticsUniformMemoryMask + | spv::MemorySemanticsAcquireReleaseMask; + } + + if (flags.test(DxbcSyncFlag::UavMemoryGlobal)) { + memoryScope = spv::ScopeDevice; + memorySemantics |= spv::MemorySemanticsImageMemoryMask + | spv::MemorySemanticsUniformMemoryMask + | spv::MemorySemanticsAcquireReleaseMask; + } + + if (executionScope != spv::ScopeInvocation) { + m_module.opControlBarrier( + m_module.constu32(executionScope), + m_module.constu32(memoryScope), + m_module.constu32(memorySemantics)); + } else if (memoryScope != spv::ScopeInvocation) { + m_module.opMemoryBarrier( + m_module.constu32(memoryScope), + m_module.constu32(memorySemantics)); + } else { + Logger::warn("DxbcCompiler: sync instruction has no effect"); + } + } + + + void DxbcCompiler::emitBitExtract(const DxbcShaderInstruction& ins) { + // ibfe and ubfe take the following arguments: + // (dst0) The destination register + // (src0) Number of bits to extact + // (src1) Offset of the bits to extract + // (src2) Register to extract bits from + const bool isSigned = ins.op == DxbcOpcode::IBfe; + + DxbcRegisterValue bitCnt = emitRegisterLoad(ins.src[0], ins.dst[0].mask); + DxbcRegisterValue bitOfs = emitRegisterLoad(ins.src[1], ins.dst[0].mask); + + if (ins.src[0].type != DxbcOperandType::Imm32) + bitCnt = emitRegisterMaskBits(bitCnt, 0x1F); + + if (ins.src[1].type != DxbcOperandType::Imm32) + bitOfs = emitRegisterMaskBits(bitOfs, 0x1F); + + const DxbcRegisterValue src = emitRegisterLoad(ins.src[2], ins.dst[0].mask); + + const uint32_t componentCount = src.type.ccount; + std::array componentIds = {{ 0, 0, 0, 0 }}; + + for (uint32_t i = 0; i < componentCount; i++) { + const DxbcRegisterValue currBitCnt = emitRegisterExtract(bitCnt, DxbcRegMask::select(i)); + const DxbcRegisterValue currBitOfs = emitRegisterExtract(bitOfs, DxbcRegMask::select(i)); + const DxbcRegisterValue currSrc = emitRegisterExtract(src, DxbcRegMask::select(i)); + + const uint32_t typeId = getVectorTypeId(currSrc.type); + + componentIds[i] = isSigned + ? m_module.opBitFieldSExtract(typeId, currSrc.id, currBitOfs.id, currBitCnt.id) + : m_module.opBitFieldUExtract(typeId, currSrc.id, currBitOfs.id, currBitCnt.id); + } + + DxbcRegisterValue result; + result.type = src.type; + result.id = componentCount > 1 + ? m_module.opCompositeConstruct( + getVectorTypeId(result.type), + componentCount, componentIds.data()) + : componentIds[0]; + emitRegisterStore(ins.dst[0], result); + } + + + void DxbcCompiler::emitBitInsert(const DxbcShaderInstruction& ins) { + // ibfe and ubfe take the following arguments: + // (dst0) The destination register + // (src0) Number of bits to extact + // (src1) Offset of the bits to extract + // (src2) Register to take bits from + // (src3) Register to replace bits in + DxbcRegisterValue bitCnt = emitRegisterLoad(ins.src[0], ins.dst[0].mask); + DxbcRegisterValue bitOfs = emitRegisterLoad(ins.src[1], ins.dst[0].mask); + + if (ins.src[0].type != DxbcOperandType::Imm32) + bitCnt = emitRegisterMaskBits(bitCnt, 0x1F); + + if (ins.src[1].type != DxbcOperandType::Imm32) + bitOfs = emitRegisterMaskBits(bitOfs, 0x1F); + + const DxbcRegisterValue insert = emitRegisterLoad(ins.src[2], ins.dst[0].mask); + const DxbcRegisterValue base = emitRegisterLoad(ins.src[3], ins.dst[0].mask); + + const uint32_t componentCount = base.type.ccount; + std::array componentIds = {{ 0, 0, 0, 0 }}; + + for (uint32_t i = 0; i < componentCount; i++) { + const DxbcRegisterValue currBitCnt = emitRegisterExtract(bitCnt, DxbcRegMask::select(i)); + const DxbcRegisterValue currBitOfs = emitRegisterExtract(bitOfs, DxbcRegMask::select(i)); + const DxbcRegisterValue currInsert = emitRegisterExtract(insert, DxbcRegMask::select(i)); + const DxbcRegisterValue currBase = emitRegisterExtract(base, DxbcRegMask::select(i)); + + componentIds[i] = m_module.opBitFieldInsert( + getVectorTypeId(currBase.type), + currBase.id, currInsert.id, + currBitOfs.id, currBitCnt.id); + } + + DxbcRegisterValue result; + result.type = base.type; + result.id = componentCount > 1 + ? m_module.opCompositeConstruct( + getVectorTypeId(result.type), + componentCount, componentIds.data()) + : componentIds[0]; + emitRegisterStore(ins.dst[0], result); + } + + + void DxbcCompiler::emitBitScan(const DxbcShaderInstruction& ins) { + // firstbit(lo|hi|shi) have two operands: + // (dst0) The destination operant + // (src0) Source operand to scan + DxbcRegisterValue src = emitRegisterLoad(ins.src[0], ins.dst[0].mask); + + DxbcRegisterValue dst; + dst.type.ctype = ins.dst[0].dataType; + dst.type.ccount = ins.dst[0].mask.popCount(); + + // Result type, should be an unsigned integer + const uint32_t typeId = getVectorTypeId(dst.type); + + switch (ins.op) { + case DxbcOpcode::FirstBitLo: dst.id = m_module.opFindILsb(typeId, src.id); break; + case DxbcOpcode::FirstBitHi: dst.id = m_module.opFindUMsb(typeId, src.id); break; + case DxbcOpcode::FirstBitShi: dst.id = m_module.opFindSMsb(typeId, src.id); break; + default: Logger::warn(str::format("DxbcCompiler: Unhandled instruction: ", ins.op)); return; + } + + // The 'Hi' variants are counted from the MSB in DXBC + // rather than the LSB, so we have to invert the number + if (ins.op == DxbcOpcode::FirstBitHi || ins.op == DxbcOpcode::FirstBitShi) { + uint32_t boolTypeId = m_module.defBoolType(); + + if (dst.type.ccount > 1) + boolTypeId = m_module.defVectorType(boolTypeId, dst.type.ccount); + + DxbcRegisterValue const31 = emitBuildConstVecu32(31u, 31u, 31u, 31u, ins.dst[0].mask); + DxbcRegisterValue constff = emitBuildConstVecu32(~0u, ~0u, ~0u, ~0u, ins.dst[0].mask); + + dst.id = m_module.opSelect(typeId, + m_module.opINotEqual(boolTypeId, dst.id, constff.id), + m_module.opISub(typeId, const31.id, dst.id), + constff.id); + } + + // No modifiers are supported + emitRegisterStore(ins.dst[0], dst); + } + + + void DxbcCompiler::emitBufferQuery(const DxbcShaderInstruction& ins) { + // bufinfo takes two arguments + // (dst0) The destination register + // (src0) The buffer register to query + const DxbcBufferInfo bufferInfo = getBufferInfo(ins.src[0]); + + bool isSsbo = m_moduleInfo.options.minSsboAlignment <= bufferInfo.align + && bufferInfo.type != DxbcResourceType::Typed; + + // We'll store this as a scalar unsigned integer + DxbcRegisterValue result = isSsbo + ? emitQueryBufferSize(ins.src[0]) + : emitQueryTexelBufferSize(ins.src[0]); + + uint32_t typeId = getVectorTypeId(result.type); + + // Adjust returned size if this is a raw or structured + // buffer, as emitQueryTexelBufferSize only returns the + // number of typed elements in the buffer. + if (bufferInfo.type == DxbcResourceType::Raw) { + result.id = m_module.opIMul(typeId, + result.id, m_module.constu32(4)); + } else if (bufferInfo.type == DxbcResourceType::Structured) { + result.id = m_module.opUDiv(typeId, result.id, + m_module.constu32(bufferInfo.stride / 4)); + } + + // Store the result. The scalar will be extended to a + // vector if the write mask consists of more than one + // component, which is the desired behaviour. + emitRegisterStore(ins.dst[0], result); + } + + + void DxbcCompiler::emitBufferLoad(const DxbcShaderInstruction& ins) { + // ld_raw takes three arguments: + // (dst0) Destination register + // (src0) Byte offset + // (src1) Source register + // ld_structured takes four arguments: + // (dst0) Destination register + // (src0) Structure index + // (src1) Byte offset + // (src2) Source register + const bool isStructured = ins.op == DxbcOpcode::LdStructured; + + // Source register. The exact way we access + // the data depends on the register type. + const DxbcRegister& dstReg = ins.dst[0]; + const DxbcRegister& srcReg = isStructured ? ins.src[2] : ins.src[1]; + + // Retrieve common info about the buffer + const DxbcBufferInfo bufferInfo = getBufferInfo(srcReg); + + // Compute element index + const DxbcRegisterValue elementIndex = isStructured + ? emitCalcBufferIndexStructured( + emitRegisterLoad(ins.src[0], DxbcRegMask(true, false, false, false)), + emitRegisterLoad(ins.src[1], DxbcRegMask(true, false, false, false)), + bufferInfo.stride) + : emitCalcBufferIndexRaw( + emitRegisterLoad(ins.src[0], DxbcRegMask(true, false, false, false))); + + emitRegisterStore(dstReg, + emitRawBufferLoad(srcReg, elementIndex, dstReg.mask)); + } + + + void DxbcCompiler::emitBufferStore(const DxbcShaderInstruction& ins) { + // store_raw takes three arguments: + // (dst0) Destination register + // (src0) Byte offset + // (src1) Source register + // store_structured takes four arguments: + // (dst0) Destination register + // (src0) Structure index + // (src1) Byte offset + // (src2) Source register + const bool isStructured = ins.op == DxbcOpcode::StoreStructured; + + // Source register. The exact way we access + // the data depends on the register type. + const DxbcRegister& dstReg = ins.dst[0]; + const DxbcRegister& srcReg = isStructured ? ins.src[2] : ins.src[1]; + + // Retrieve common info about the buffer + const DxbcBufferInfo bufferInfo = getBufferInfo(dstReg); + + // Compute element index + const DxbcRegisterValue elementIndex = isStructured + ? emitCalcBufferIndexStructured( + emitRegisterLoad(ins.src[0], DxbcRegMask(true, false, false, false)), + emitRegisterLoad(ins.src[1], DxbcRegMask(true, false, false, false)), + bufferInfo.stride) + : emitCalcBufferIndexRaw( + emitRegisterLoad(ins.src[0], DxbcRegMask(true, false, false, false))); + + emitRawBufferStore(dstReg, elementIndex, + emitRegisterLoad(srcReg, dstReg.mask)); + } + + + void DxbcCompiler::emitConvertFloat16(const DxbcShaderInstruction& ins) { + // f32tof16 takes two operands: + // (dst0) Destination register as a uint32 vector + // (src0) Source register as a float32 vector + // f16tof32 takes two operands: + // (dst0) Destination register as a float32 vector + // (src0) Source register as a uint32 vector + const DxbcRegisterValue src = emitRegisterLoad(ins.src[0], ins.dst[0].mask); + + // We handle both packing and unpacking here + const bool isPack = ins.op == DxbcOpcode::F32toF16; + + // The conversion instructions do not map very well to the + // SPIR-V pack instructions, which operate on 2D vectors. + std::array scalarIds = {{ 0, 0, 0, 0 }}; + + const uint32_t componentCount = src.type.ccount; + + // These types are used in both pack and unpack operations + const uint32_t t_u32 = getVectorTypeId({ DxbcScalarType::Uint32, 1 }); + const uint32_t t_f32 = getVectorTypeId({ DxbcScalarType::Float32, 1 }); + const uint32_t t_f32v2 = getVectorTypeId({ DxbcScalarType::Float32, 2 }); + + // Constant zero-bit pattern, used for packing + const uint32_t zerof32 = isPack ? m_module.constf32(0.0f) : 0; + + for (uint32_t i = 0; i < componentCount; i++) { + const DxbcRegisterValue componentValue + = emitRegisterExtract(src, DxbcRegMask::select(i)); + + if (isPack) { // f32tof16 + const std::array packIds = + {{ componentValue.id, zerof32 }}; + + scalarIds[i] = m_module.opPackHalf2x16(t_u32, + m_module.opCompositeConstruct(t_f32v2, packIds.size(), packIds.data())); + } else { // f16tof32 + const uint32_t zeroIndex = 0; + + scalarIds[i] = m_module.opCompositeExtract(t_f32, + m_module.opUnpackHalf2x16(t_f32v2, componentValue.id), + 1, &zeroIndex); + } + } + + DxbcRegisterValue result; + result.type.ctype = ins.dst[0].dataType; + result.type.ccount = componentCount; + + uint32_t typeId = getVectorTypeId(result.type); + result.id = componentCount > 1 + ? m_module.opCompositeConstruct(typeId, + componentCount, scalarIds.data()) + : scalarIds[0]; + + if (isPack) { + // Some drivers return infinity if the input value is above a certain + // threshold, but D3D wants us to return infinity only if the input is + // actually infinite. Fix this up to return the maximum representable + // 16-bit floating point number instead, but preserve input infinity. + uint32_t t_bvec = getVectorTypeId({ DxbcScalarType::Bool, componentCount }); + uint32_t f16Infinity = m_module.constuReplicant(0x7C00, componentCount); + uint32_t f16Unsigned = m_module.constuReplicant(0x7FFF, componentCount); + + uint32_t isInputInf = m_module.opIsInf(t_bvec, src.id); + uint32_t isValueInf = m_module.opIEqual(t_bvec, f16Infinity, + m_module.opBitwiseAnd(typeId, result.id, f16Unsigned)); + + result.id = m_module.opSelect(getVectorTypeId(result.type), + m_module.opLogicalAnd(t_bvec, isValueInf, m_module.opLogicalNot(t_bvec, isInputInf)), + m_module.opISub(typeId, result.id, m_module.constuReplicant(1, componentCount)), + result.id); + } + + // Store result in the destination register + emitRegisterStore(ins.dst[0], result); + } + + + void DxbcCompiler::emitConvertFloat64(const DxbcShaderInstruction& ins) { + // ftod and dtof take the following operands: + // (dst0) Destination operand + // (src0) Number to convert + uint32_t dstBits = ins.dst[0].mask.popCount(); + + DxbcRegMask srcMask = isDoubleType(ins.dst[0].dataType) + ? DxbcRegMask(dstBits >= 2, dstBits >= 4, false, false) + : DxbcRegMask(dstBits >= 1, dstBits >= 1, dstBits >= 2, dstBits >= 2); + + // Perform actual conversion, destination modifiers are not applied + DxbcRegisterValue val = emitRegisterLoad(ins.src[0], srcMask); + + DxbcRegisterValue result; + result.type.ctype = ins.dst[0].dataType; + result.type.ccount = val.type.ccount; + + switch (ins.op) { + case DxbcOpcode::DtoF: + case DxbcOpcode::FtoD: + result.id = m_module.opFConvert( + getVectorTypeId(result.type), val.id); + break; + + case DxbcOpcode::DtoI: + result.id = m_module.opConvertFtoS( + getVectorTypeId(result.type), val.id); + break; + + case DxbcOpcode::DtoU: + result.id = m_module.opConvertFtoU( + getVectorTypeId(result.type), val.id); + break; + + case DxbcOpcode::ItoD: + result.id = m_module.opConvertStoF( + getVectorTypeId(result.type), val.id); + break; + + case DxbcOpcode::UtoD: + result.id = m_module.opConvertUtoF( + getVectorTypeId(result.type), val.id); + break; + + default: + Logger::warn(str::format("DxbcCompiler: Unhandled instruction: ", ins.op)); + return; + } + + emitRegisterStore(ins.dst[0], result); + } + + + void DxbcCompiler::emitHullShaderInstCnt(const DxbcShaderInstruction& ins) { + this->getCurrentHsForkJoinPhase()->instanceCount = ins.imm[0].u32; + } + + + void DxbcCompiler::emitHullShaderPhase(const DxbcShaderInstruction& ins) { + switch (ins.op) { + case DxbcOpcode::HsDecls: { + if (m_hs.currPhaseType != DxbcCompilerHsPhase::None) + Logger::err("DXBC: HsDecls not the first phase in hull shader"); + + m_hs.currPhaseType = DxbcCompilerHsPhase::Decl; + } break; + + case DxbcOpcode::HsControlPointPhase: { + m_hs.cpPhase = this->emitNewHullShaderControlPointPhase(); + + m_hs.currPhaseType = DxbcCompilerHsPhase::ControlPoint; + m_hs.currPhaseId = 0; + + m_module.setDebugName(m_hs.cpPhase.functionId, "hs_control_point"); + } break; + + case DxbcOpcode::HsForkPhase: { + auto phase = this->emitNewHullShaderForkJoinPhase(); + m_hs.forkPhases.push_back(phase); + + m_hs.currPhaseType = DxbcCompilerHsPhase::Fork; + m_hs.currPhaseId = m_hs.forkPhases.size() - 1; + + m_module.setDebugName(phase.functionId, + str::format("hs_fork_", m_hs.currPhaseId).c_str()); + } break; + + case DxbcOpcode::HsJoinPhase: { + auto phase = this->emitNewHullShaderForkJoinPhase(); + m_hs.joinPhases.push_back(phase); + + m_hs.currPhaseType = DxbcCompilerHsPhase::Join; + m_hs.currPhaseId = m_hs.joinPhases.size() - 1; + + m_module.setDebugName(phase.functionId, + str::format("hs_join_", m_hs.currPhaseId).c_str()); + } break; + + default: + Logger::warn(str::format( + "DxbcCompiler: Unhandled instruction: ", + ins.op)); + } + } + + + void DxbcCompiler::emitInterpolate(const DxbcShaderInstruction& ins) { + m_module.enableCapability(spv::CapabilityInterpolationFunction); + + // The SPIR-V instructions operate on input variable pointers, + // which are all declared as four-component float vectors. + uint32_t registerId = ins.src[0].idx[0].offset; + + DxbcRegisterValue result; + result.type = getInputRegType(registerId); + + switch (ins.op) { + case DxbcOpcode::EvalCentroid: { + result.id = m_module.opInterpolateAtCentroid( + getVectorTypeId(result.type), + m_vRegs.at(registerId).id); + } break; + + case DxbcOpcode::EvalSampleIndex: { + const DxbcRegisterValue sampleIndex = emitRegisterLoad( + ins.src[1], DxbcRegMask(true, false, false, false)); + + result.id = m_module.opInterpolateAtSample( + getVectorTypeId(result.type), + m_vRegs.at(registerId).id, + sampleIndex.id); + } break; + + case DxbcOpcode::EvalSnapped: { + const DxbcRegisterValue offset = emitRegisterLoad( + ins.src[1], DxbcRegMask(true, true, false, false)); + + result.id = m_module.opInterpolateAtOffset( + getVectorTypeId(result.type), + m_vRegs.at(registerId).id, + offset.id); + } break; + + default: + Logger::warn(str::format( + "DxbcCompiler: Unhandled instruction: ", + ins.op)); + return; + } + + result = emitRegisterSwizzle(result, + ins.src[0].swizzle, ins.dst[0].mask); + emitRegisterStore(ins.dst[0], result); + } + + + void DxbcCompiler::emitTextureQuery(const DxbcShaderInstruction& ins) { + // resinfo has three operands: + // (dst0) The destination register + // (src0) Resource LOD to query + // (src1) Resource to query + const DxbcBufferInfo resourceInfo = getBufferInfo(ins.src[1]); + const DxbcResinfoType resinfoType = ins.controls.resinfoType(); + + // Read the exact LOD for the image query + const DxbcRegisterValue mipLod = emitRegisterLoad( + ins.src[0], DxbcRegMask(true, false, false, false)); + + const DxbcScalarType returnType = resinfoType == DxbcResinfoType::Uint + ? DxbcScalarType::Uint32 : DxbcScalarType::Float32; + + // Query the size of the selected mip level, as well as the + // total number of mip levels. We will have to combine the + // result into a four-component vector later. + DxbcRegisterValue imageSize = emitQueryTextureSize(ins.src[1], mipLod); + DxbcRegisterValue imageLevels = emitQueryTextureLods(ins.src[1]); + + // Convert intermediates to the requested type + if (returnType == DxbcScalarType::Float32) { + imageSize.type.ctype = DxbcScalarType::Float32; + imageSize.id = m_module.opConvertUtoF( + getVectorTypeId(imageSize.type), + imageSize.id); + + imageLevels.type.ctype = DxbcScalarType::Float32; + imageLevels.id = m_module.opConvertUtoF( + getVectorTypeId(imageLevels.type), + imageLevels.id); + } + + // If the selected return type is rcpFloat, we need + // to compute the reciprocal of the image dimensions, + // but not the array size, so we need to separate it. + const uint32_t imageCoordDim = imageSize.type.ccount; + + DxbcRegisterValue imageLayers; + imageLayers.type = imageSize.type; + imageLayers.id = 0; + + if (resinfoType == DxbcResinfoType::RcpFloat && resourceInfo.image.array) { + imageLayers = emitRegisterExtract(imageSize, DxbcRegMask::select(imageCoordDim - 1)); + imageSize = emitRegisterExtract(imageSize, DxbcRegMask::firstN(imageCoordDim - 1)); + } + + if (resinfoType == DxbcResinfoType::RcpFloat) { + imageSize.id = m_module.opFDiv( + getVectorTypeId(imageSize.type), + emitBuildConstVecf32(1.0f, 1.0f, 1.0f, 1.0f, + DxbcRegMask::firstN(imageSize.type.ccount)).id, + imageSize.id); + } + + // Concatenate result vectors and scalars to form a + // 4D vector. Unused components will be set to zero. + std::array vectorIds = { imageSize.id, 0, 0, 0 }; + uint32_t numVectorIds = 1; + + if (imageLayers.id != 0) + vectorIds[numVectorIds++] = imageLayers.id; + + if (imageCoordDim < 3) { + const uint32_t zero = returnType == DxbcScalarType::Uint32 + ? m_module.constu32(0) + : m_module.constf32(0.0f); + + for (uint32_t i = imageCoordDim; i < 3; i++) + vectorIds[numVectorIds++] = zero; + } + + vectorIds[numVectorIds++] = imageLevels.id; + + // Create the actual result vector + DxbcRegisterValue result; + result.type.ctype = returnType; + result.type.ccount = 4; + result.id = m_module.opCompositeConstruct( + getVectorTypeId(result.type), + numVectorIds, vectorIds.data()); + + // Swizzle components using the resource swizzle + // and the destination operand's write mask + result = emitRegisterSwizzle(result, + ins.src[1].swizzle, ins.dst[0].mask); + emitRegisterStore(ins.dst[0], result); + } + + + void DxbcCompiler::emitTextureQueryLod(const DxbcShaderInstruction& ins) { + // All sample instructions have at least these operands: + // (dst0) The destination register + // (src0) Texture coordinates + // (src1) The texture itself + // (src2) The sampler object + const DxbcRegister& texCoordReg = ins.src[0]; + const DxbcRegister& textureReg = ins.src[1]; + const DxbcRegister& samplerReg = ins.src[2]; + + // Texture and sampler register IDs + const auto& texture = m_textures.at(textureReg.idx[0].offset); + const auto& sampler = m_samplers.at(samplerReg.idx[0].offset); + + // Load texture coordinates + const DxbcRegisterValue coord = emitRegisterLoad(texCoordReg, + DxbcRegMask::firstN(getTexLayerDim(texture.imageInfo))); + + // Query the LOD. The result is a two-dimensional float32 + // vector containing the mip level and virtual LOD numbers. + const uint32_t sampledImageId = emitLoadSampledImage(texture, sampler, false); + const uint32_t queriedLodId = m_module.opImageQueryLod( + getVectorTypeId({ DxbcScalarType::Float32, 2 }), + sampledImageId, coord.id); + + // Build the result array vector by filling up + // the remaining two components with zeroes. + const uint32_t zero = m_module.constf32(0.0f); + const std::array resultIds + = {{ queriedLodId, zero, zero }}; + + DxbcRegisterValue result; + result.type = DxbcVectorType { DxbcScalarType::Float32, 4 }; + result.id = m_module.opCompositeConstruct( + getVectorTypeId(result.type), + resultIds.size(), resultIds.data()); + + result = emitRegisterSwizzle(result, ins.src[1].swizzle, ins.dst[0].mask); + emitRegisterStore(ins.dst[0], result); + } + + + void DxbcCompiler::emitTextureQueryMs(const DxbcShaderInstruction& ins) { + // sampleinfo has two operands: + // (dst0) The destination register + // (src0) Resource to query + DxbcRegisterValue sampleCount = emitQueryTextureSamples(ins.src[0]); + + if (ins.controls.returnType() != DxbcInstructionReturnType::Uint) { + sampleCount.type = { DxbcScalarType::Float32, 1 }; + sampleCount.id = m_module.opConvertUtoF( + getVectorTypeId(sampleCount.type), + sampleCount.id); + } + + emitRegisterStore(ins.dst[0], sampleCount); + } + + + void DxbcCompiler::emitTextureQueryMsPos(const DxbcShaderInstruction& ins) { + // samplepos has three operands: + // (dst0) The destination register + // (src0) Resource to query + // (src1) Sample index + if (m_samplePositions == 0) + m_samplePositions = emitSamplePosArray(); + + // The lookup index is qual to the sample count plus the + // sample index, or 0 if the resource cannot be queried. + DxbcRegisterValue sampleCount = emitQueryTextureSamples(ins.src[0]); + DxbcRegisterValue sampleIndex = emitRegisterLoad( + ins.src[1], DxbcRegMask(true, false, false, false)); + + uint32_t lookupIndex = m_module.opIAdd( + getVectorTypeId(sampleCount.type), + sampleCount.id, sampleIndex.id); + + // Validate the parameters + uint32_t sampleCountValid = m_module.opULessThanEqual( + m_module.defBoolType(), + sampleCount.id, + m_module.constu32(16)); + + uint32_t sampleIndexValid = m_module.opULessThan( + m_module.defBoolType(), + sampleIndex.id, + sampleCount.id); + + // If the lookup cannot be performed, set the lookup + // index to zero, which will return a zero vector. + lookupIndex = m_module.opSelect( + getVectorTypeId(sampleCount.type), + m_module.opLogicalAnd( + m_module.defBoolType(), + sampleCountValid, + sampleIndexValid), + lookupIndex, + m_module.constu32(0)); + + // Load sample pos vector and write the masked + // components to the destination register. + DxbcRegisterPointer samplePos; + samplePos.type.ctype = DxbcScalarType::Float32; + samplePos.type.ccount = 2; + samplePos.id = m_module.opAccessChain( + m_module.defPointerType( + getVectorTypeId(samplePos.type), + spv::StorageClassPrivate), + m_samplePositions, 1, &lookupIndex); + + // Expand to vec4 by appending zeroes + DxbcRegisterValue result = emitValueLoad(samplePos); + + DxbcRegisterValue zero; + zero.type.ctype = DxbcScalarType::Float32; + zero.type.ccount = 2; + zero.id = m_module.constvec2f32(0.0f, 0.0f); + + result = emitRegisterConcat(result, zero); + + emitRegisterStore(ins.dst[0], + emitRegisterSwizzle(result, + ins.src[0].swizzle, + ins.dst[0].mask)); + } + + + void DxbcCompiler::emitTextureFetch(const DxbcShaderInstruction& ins) { + // ld has three operands: + // (dst0) The destination register + // (src0) Source address + // (src1) Source texture + // ld2dms has four operands: + // (dst0) The destination register + // (src0) Source address + // (src1) Source texture + // (src2) Sample number + const auto& texture = m_textures.at(ins.src[1].idx[0].offset); + const uint32_t imageLayerDim = getTexLayerDim(texture.imageInfo); + + // Load the texture coordinates. The last component + // contains the LOD if the resource is an image. + const DxbcRegisterValue address = emitRegisterLoad( + ins.src[0], DxbcRegMask(true, true, true, true)); + + // Additional image operands. This will store + // the LOD and the address offset if present. + SpirvImageOperands imageOperands; + + if (ins.sampleControls.u != 0 || ins.sampleControls.v != 0 || ins.sampleControls.w != 0) { + const std::array offsetIds = { + imageLayerDim >= 1 ? m_module.consti32(ins.sampleControls.u) : 0, + imageLayerDim >= 2 ? m_module.consti32(ins.sampleControls.v) : 0, + imageLayerDim >= 3 ? m_module.consti32(ins.sampleControls.w) : 0, + }; + + imageOperands.flags |= spv::ImageOperandsConstOffsetMask; + imageOperands.sConstOffset = m_module.constComposite( + getVectorTypeId({ DxbcScalarType::Sint32, imageLayerDim }), + imageLayerDim, offsetIds.data()); + } + + // The LOD is not present when reading from + // a buffer or from a multisample texture. + if (texture.imageInfo.dim != spv::DimBuffer && texture.imageInfo.ms == 0) { + DxbcRegisterValue imageLod; + + if (ins.op != DxbcOpcode::LdMs) { + imageLod = emitRegisterExtract( + address, DxbcRegMask(false, false, false, true)); + } else { + // If we force-disabled MSAA, fetch from LOD 0 + imageLod.type = { DxbcScalarType::Uint32, 1 }; + imageLod.id = m_module.constu32(0); + } + + imageOperands.flags |= spv::ImageOperandsLodMask; + imageOperands.sLod = imageLod.id; + } + + // The ld2ms instruction has a sample index, but we + // are only allowed to set it for multisample views + if (ins.op == DxbcOpcode::LdMs && texture.imageInfo.ms == 1) { + DxbcRegisterValue sampleId = emitRegisterLoad( + ins.src[2], DxbcRegMask(true, false, false, false)); + + imageOperands.flags |= spv::ImageOperandsSampleMask; + imageOperands.sSampleId = sampleId.id; + } + + // Extract coordinates from address + const DxbcRegisterValue coord = emitCalcTexCoord(address, texture.imageInfo); + + // Reading a typed image or buffer view + // always returns a four-component vector. + const uint32_t imageId = m_module.opLoad(texture.imageTypeId, texture.varId); + + DxbcRegisterValue result; + result.type.ctype = texture.sampledType; + result.type.ccount = 4; + result.id = m_module.opImageFetch( + getVectorTypeId(result.type), imageId, + coord.id, imageOperands); + + // Swizzle components using the texture swizzle + // and the destination operand's write mask + result = emitRegisterSwizzle(result, + ins.src[1].swizzle, ins.dst[0].mask); + + // If the texture is not bound, return zeroes + DxbcRegisterValue bound; + bound.type = { DxbcScalarType::Bool, 1 }; + bound.id = texture.specId; + + DxbcRegisterValue mergedResult; + mergedResult.type = result.type; + mergedResult.id = m_module.opSelect(getVectorTypeId(mergedResult.type), + emitBuildVector(bound, result.type.ccount).id, result.id, + emitBuildZeroVector(result.type).id); + + emitRegisterStore(ins.dst[0], mergedResult); + } + + + void DxbcCompiler::emitTextureGather(const DxbcShaderInstruction& ins) { + // Gather4 takes the following operands: + // (dst0) The destination register + // (src0) Texture coordinates + // (src1) The texture itself + // (src2) The sampler, with a component selector + // Gather4C takes the following additional operand: + // (src3) The depth reference value + // The Gather4Po variants take an additional operand + // which defines an extended constant offset. + // TODO reduce code duplication by moving some common code + // in both sample() and gather() into separate methods + const bool isExtendedGather = ins.op == DxbcOpcode::Gather4Po + || ins.op == DxbcOpcode::Gather4PoC; + + const DxbcRegister& texCoordReg = ins.src[0]; + const DxbcRegister& textureReg = ins.src[1 + isExtendedGather]; + const DxbcRegister& samplerReg = ins.src[2 + isExtendedGather]; + + // Texture and sampler register IDs + const auto& texture = m_textures.at(textureReg.idx[0].offset); + const auto& sampler = m_samplers.at(samplerReg.idx[0].offset); + + // Image type, which stores the image dimensions etc. + const uint32_t imageLayerDim = getTexLayerDim(texture.imageInfo); + + // Load the texture coordinates. SPIR-V allows these + // to be float4 even if not all components are used. + DxbcRegisterValue coord = emitLoadTexCoord(texCoordReg, texture.imageInfo); + + // Load reference value for depth-compare operations + const bool isDepthCompare = ins.op == DxbcOpcode::Gather4C + || ins.op == DxbcOpcode::Gather4PoC; + + const DxbcRegisterValue referenceValue = isDepthCompare + ? emitRegisterLoad(ins.src[3 + isExtendedGather], + DxbcRegMask(true, false, false, false)) + : DxbcRegisterValue(); + + // Accumulate additional image operands. + SpirvImageOperands imageOperands; + + if (isExtendedGather) { + m_module.enableCapability(spv::CapabilityImageGatherExtended); + + DxbcRegisterValue gatherOffset = emitRegisterLoad( + ins.src[1], DxbcRegMask::firstN(imageLayerDim)); + + imageOperands.flags |= spv::ImageOperandsOffsetMask; + imageOperands.gOffset = gatherOffset.id; + } else if (ins.sampleControls.u != 0 || ins.sampleControls.v != 0 || ins.sampleControls.w != 0) { + const std::array offsetIds = { + imageLayerDim >= 1 ? m_module.consti32(ins.sampleControls.u) : 0, + imageLayerDim >= 2 ? m_module.consti32(ins.sampleControls.v) : 0, + imageLayerDim >= 3 ? m_module.consti32(ins.sampleControls.w) : 0, + }; + + imageOperands.flags |= spv::ImageOperandsConstOffsetMask; + imageOperands.sConstOffset = m_module.constComposite( + getVectorTypeId({ DxbcScalarType::Sint32, imageLayerDim }), + imageLayerDim, offsetIds.data()); + } + + // Gathering texels always returns a four-component + // vector, even for the depth-compare variants. + uint32_t sampledImageId = emitLoadSampledImage(texture, sampler, isDepthCompare); + + DxbcRegisterValue result; + result.type.ctype = texture.sampledType; + result.type.ccount = 4; + + switch (ins.op) { + // Simple image gather operation + case DxbcOpcode::Gather4: + case DxbcOpcode::Gather4Po: { + result.id = m_module.opImageGather( + getVectorTypeId(result.type), sampledImageId, coord.id, + m_module.consti32(samplerReg.swizzle[0]), + imageOperands); + } break; + + // Depth-compare operation + case DxbcOpcode::Gather4C: + case DxbcOpcode::Gather4PoC: { + result.id = m_module.opImageDrefGather( + getVectorTypeId(result.type), sampledImageId, coord.id, + referenceValue.id, imageOperands); + } break; + + default: + Logger::warn(str::format( + "DxbcCompiler: Unhandled instruction: ", + ins.op)); + return; + } + + // Swizzle components using the texture swizzle + // and the destination operand's write mask + result = emitRegisterSwizzle(result, + textureReg.swizzle, ins.dst[0].mask); + + DxbcRegisterValue bound; + bound.type = { DxbcScalarType::Bool, 1 }; + bound.id = texture.specId; + + result.id = m_module.opSelect(getVectorTypeId(result.type), + emitBuildVector(bound, result.type.ccount).id, result.id, + emitBuildZeroVector(result.type).id); + + emitRegisterStore(ins.dst[0], result); + } + + + void DxbcCompiler::emitTextureSample(const DxbcShaderInstruction& ins) { + // All sample instructions have at least these operands: + // (dst0) The destination register + // (src0) Texture coordinates + // (src1) The texture itself + // (src2) The sampler object + const DxbcRegister& texCoordReg = ins.src[0]; + const DxbcRegister& textureReg = ins.src[1]; + const DxbcRegister& samplerReg = ins.src[2]; + + // Texture and sampler register IDs + const auto& texture = m_textures.at(textureReg.idx[0].offset); + const auto& sampler = m_samplers.at(samplerReg.idx[0].offset); + const uint32_t imageLayerDim = getTexLayerDim(texture.imageInfo); + + // Load the texture coordinates. SPIR-V allows these + // to be float4 even if not all components are used. + DxbcRegisterValue coord = emitLoadTexCoord(texCoordReg, texture.imageInfo); + + // Load reference value for depth-compare operations + const bool isDepthCompare = ins.op == DxbcOpcode::SampleC + || ins.op == DxbcOpcode::SampleClz; + + const DxbcRegisterValue referenceValue = isDepthCompare + ? emitRegisterLoad(ins.src[3], DxbcRegMask(true, false, false, false)) + : DxbcRegisterValue(); + + // Load explicit gradients for sample operations that require them + const bool hasExplicitGradients = ins.op == DxbcOpcode::SampleD; + + const DxbcRegisterValue explicitGradientX = hasExplicitGradients + ? emitRegisterLoad(ins.src[3], DxbcRegMask::firstN(imageLayerDim)) + : DxbcRegisterValue(); + + const DxbcRegisterValue explicitGradientY = hasExplicitGradients + ? emitRegisterLoad(ins.src[4], DxbcRegMask::firstN(imageLayerDim)) + : DxbcRegisterValue(); + + // LOD for certain sample operations + const bool hasLod = ins.op == DxbcOpcode::SampleL + || ins.op == DxbcOpcode::SampleB; + + const DxbcRegisterValue lod = hasLod + ? emitRegisterLoad(ins.src[3], DxbcRegMask(true, false, false, false)) + : DxbcRegisterValue(); + + // Accumulate additional image operands. These are + // not part of the actual operand token in SPIR-V. + SpirvImageOperands imageOperands; + + if (ins.sampleControls.u != 0 || ins.sampleControls.v != 0 || ins.sampleControls.w != 0) { + const std::array offsetIds = { + imageLayerDim >= 1 ? m_module.consti32(ins.sampleControls.u) : 0, + imageLayerDim >= 2 ? m_module.consti32(ins.sampleControls.v) : 0, + imageLayerDim >= 3 ? m_module.consti32(ins.sampleControls.w) : 0, + }; + + imageOperands.flags |= spv::ImageOperandsConstOffsetMask; + imageOperands.sConstOffset = m_module.constComposite( + getVectorTypeId({ DxbcScalarType::Sint32, imageLayerDim }), + imageLayerDim, offsetIds.data()); + } + + // Combine the texture and the sampler into a sampled image + uint32_t sampledImageId = emitLoadSampledImage(texture, sampler, isDepthCompare); + + // Sampling an image always returns a four-component + // vector, whereas depth-compare ops return a scalar. + DxbcRegisterValue result; + result.type.ctype = texture.sampledType; + result.type.ccount = isDepthCompare ? 1 : 4; + + switch (ins.op) { + // Simple image sample operation + case DxbcOpcode::Sample: { + result.id = m_module.opImageSampleImplicitLod( + getVectorTypeId(result.type), + sampledImageId, coord.id, + imageOperands); + } break; + + // Depth-compare operation + case DxbcOpcode::SampleC: { + result.id = m_module.opImageSampleDrefImplicitLod( + getVectorTypeId(result.type), sampledImageId, coord.id, + referenceValue.id, imageOperands); + } break; + + // Depth-compare operation on mip level zero + case DxbcOpcode::SampleClz: { + imageOperands.flags |= spv::ImageOperandsLodMask; + imageOperands.sLod = m_module.constf32(0.0f); + + result.id = m_module.opImageSampleDrefExplicitLod( + getVectorTypeId(result.type), sampledImageId, coord.id, + referenceValue.id, imageOperands); + } break; + + // Sample operation with explicit gradients + case DxbcOpcode::SampleD: { + imageOperands.flags |= spv::ImageOperandsGradMask; + imageOperands.sGradX = explicitGradientX.id; + imageOperands.sGradY = explicitGradientY.id; + + result.id = m_module.opImageSampleExplicitLod( + getVectorTypeId(result.type), sampledImageId, coord.id, + imageOperands); + } break; + + // Sample operation with explicit LOD + case DxbcOpcode::SampleL: { + imageOperands.flags |= spv::ImageOperandsLodMask; + imageOperands.sLod = lod.id; + + result.id = m_module.opImageSampleExplicitLod( + getVectorTypeId(result.type), sampledImageId, coord.id, + imageOperands); + } break; + + // Sample operation with LOD bias + case DxbcOpcode::SampleB: { + imageOperands.flags |= spv::ImageOperandsBiasMask; + imageOperands.sLodBias = lod.id; + + result.id = m_module.opImageSampleImplicitLod( + getVectorTypeId(result.type), sampledImageId, coord.id, + imageOperands); + } break; + + default: + Logger::warn(str::format( + "DxbcCompiler: Unhandled instruction: ", + ins.op)); + return; + } + + // Swizzle components using the texture swizzle + // and the destination operand's write mask + if (result.type.ccount != 1) { + result = emitRegisterSwizzle(result, + textureReg.swizzle, ins.dst[0].mask); + } + + DxbcRegisterValue bound; + bound.type = { DxbcScalarType::Bool, 1 }; + bound.id = texture.specId; + + result.id = m_module.opSelect(getVectorTypeId(result.type), + emitBuildVector(bound, result.type.ccount).id, result.id, + emitBuildZeroVector(result.type).id); + + emitRegisterStore(ins.dst[0], result); + } + + + void DxbcCompiler::emitTypedUavLoad(const DxbcShaderInstruction& ins) { + // load_uav_typed has three operands: + // (dst0) The destination register + // (src0) The texture or buffer coordinates + // (src1) The UAV to load from + const uint32_t registerId = ins.src[1].idx[0].offset; + const DxbcUav uavInfo = m_uavs.at(registerId); + + // Load texture coordinates + DxbcRegisterValue texCoord = emitLoadTexCoord( + ins.src[0], uavInfo.imageInfo); + + // Load source value from the UAV + DxbcRegisterValue uavValue; + uavValue.type.ctype = uavInfo.sampledType; + uavValue.type.ccount = 4; + uavValue.id = m_module.opImageRead( + getVectorTypeId(uavValue.type), + m_module.opLoad(uavInfo.imageTypeId, uavInfo.varId), + texCoord.id, SpirvImageOperands()); + + // Apply component swizzle and mask + uavValue = emitRegisterSwizzle(uavValue, + ins.src[1].swizzle, ins.dst[0].mask); + + emitRegisterStore(ins.dst[0], uavValue); + } + + + void DxbcCompiler::emitTypedUavStore(const DxbcShaderInstruction& ins) { + // store_uav_typed has three operands: + // (dst0) The destination UAV + // (src0) The texture or buffer coordinates + // (src1) The value to store + const DxbcBufferInfo uavInfo = getBufferInfo(ins.dst[0]); + + // Execute write op only if the UAV is bound + uint32_t writeTest = emitUavWriteTest(uavInfo); + + DxbcConditional cond; + cond.labelIf = m_module.allocateId(); + cond.labelEnd = m_module.allocateId(); + + m_module.opSelectionMerge (cond.labelEnd, spv::SelectionControlMaskNone); + m_module.opBranchConditional(writeTest, cond.labelIf, cond.labelEnd); + + m_module.opLabel(cond.labelIf); + + // Load texture coordinates + DxbcRegisterValue texCoord = emitLoadTexCoord(ins.src[0], uavInfo.image); + + // Load the value that will be written to the image. We'll + // have to cast it to the component type of the image. + const DxbcRegisterValue texValue = emitRegisterBitcast( + emitRegisterLoad(ins.src[1], DxbcRegMask(true, true, true, true)), + uavInfo.stype); + + // Write the given value to the image + m_module.opImageWrite( + m_module.opLoad(uavInfo.typeId, uavInfo.varId), + texCoord.id, texValue.id, SpirvImageOperands()); + + // End conditional block + m_module.opBranch(cond.labelEnd); + m_module.opLabel (cond.labelEnd); + } + + + void DxbcCompiler::emitControlFlowIf(const DxbcShaderInstruction& ins) { + // Load the first component of the condition + // operand and perform a zero test on it. + const DxbcRegisterValue condition = emitRegisterLoad( + ins.src[0], DxbcRegMask(true, false, false, false)); + + // Declare the 'if' block. We do not know if there + // will be an 'else' block or not, so we'll assume + // that there is one and leave it empty otherwise. + DxbcCfgBlock block; + block.type = DxbcCfgBlockType::If; + block.b_if.ztestId = emitRegisterZeroTest(condition, ins.controls.zeroTest()).id; + block.b_if.labelIf = m_module.allocateId(); + block.b_if.labelElse = 0; + block.b_if.labelEnd = m_module.allocateId(); + block.b_if.headerPtr = m_module.getInsertionPtr(); + m_controlFlowBlocks.push_back(block); + + // We'll insert the branch instruction when closing + // the block, since we don't know whether or not an + // else block is needed right now. + m_module.opLabel(block.b_if.labelIf); + } + + + void DxbcCompiler::emitControlFlowElse(const DxbcShaderInstruction& ins) { + if (m_controlFlowBlocks.size() == 0 + || m_controlFlowBlocks.back().type != DxbcCfgBlockType::If + || m_controlFlowBlocks.back().b_if.labelElse != 0) + throw DxvkError("DxbcCompiler: 'Else' without 'If' found"); + + // Set the 'Else' flag so that we do + // not insert a dummy block on 'EndIf' + DxbcCfgBlock& block = m_controlFlowBlocks.back(); + block.b_if.labelElse = m_module.allocateId(); + + // Close the 'If' block by branching to + // the merge block we declared earlier + m_module.opBranch(block.b_if.labelEnd); + m_module.opLabel (block.b_if.labelElse); + } + + + void DxbcCompiler::emitControlFlowEndIf(const DxbcShaderInstruction& ins) { + if (m_controlFlowBlocks.size() == 0 + || m_controlFlowBlocks.back().type != DxbcCfgBlockType::If) + throw DxvkError("DxbcCompiler: 'EndIf' without 'If' found"); + + // Remove the block from the stack, it's closed + DxbcCfgBlock block = m_controlFlowBlocks.back(); + m_controlFlowBlocks.pop_back(); + + // Write out the 'if' header + m_module.beginInsertion(block.b_if.headerPtr); + + m_module.opSelectionMerge( + block.b_if.labelEnd, + spv::SelectionControlMaskNone); + + m_module.opBranchConditional( + block.b_if.ztestId, + block.b_if.labelIf, + block.b_if.labelElse != 0 + ? block.b_if.labelElse + : block.b_if.labelEnd); + + m_module.endInsertion(); + + // End the active 'if' or 'else' block + m_module.opBranch(block.b_if.labelEnd); + m_module.opLabel (block.b_if.labelEnd); + } + + + void DxbcCompiler::emitControlFlowSwitch(const DxbcShaderInstruction& ins) { + // Load the selector as a scalar unsigned integer + const DxbcRegisterValue selector = emitRegisterLoad( + ins.src[0], DxbcRegMask(true, false, false, false)); + + // Declare switch block. We cannot insert the switch + // instruction itself yet because the number of case + // statements and blocks is unknown at this point. + DxbcCfgBlock block; + block.type = DxbcCfgBlockType::Switch; + block.b_switch.insertPtr = m_module.getInsertionPtr(); + block.b_switch.selectorId = selector.id; + block.b_switch.labelBreak = m_module.allocateId(); + block.b_switch.labelCase = m_module.allocateId(); + block.b_switch.labelDefault = 0; + block.b_switch.labelCases = nullptr; + m_controlFlowBlocks.push_back(block); + + // Define the first 'case' label + m_module.opLabel(block.b_switch.labelCase); + } + + + void DxbcCompiler::emitControlFlowCase(const DxbcShaderInstruction& ins) { + if (m_controlFlowBlocks.size() == 0 + || m_controlFlowBlocks.back().type != DxbcCfgBlockType::Switch) + throw DxvkError("DxbcCompiler: 'Case' without 'Switch' found"); + + // The source operand must be a 32-bit immediate. + if (ins.src[0].type != DxbcOperandType::Imm32) + throw DxvkError("DxbcCompiler: Invalid operand type for 'Case'"); + + // Use the last label allocated for 'case'. + DxbcCfgBlockSwitch* block = &m_controlFlowBlocks.back().b_switch; + + if (caseBlockIsFallthrough()) { + block->labelCase = m_module.allocateId(); + + m_module.opBranch(block->labelCase); + m_module.opLabel (block->labelCase); + } + + DxbcSwitchLabel label; + label.desc.literal = ins.src[0].imm.u32_1; + label.desc.labelId = block->labelCase; + label.next = block->labelCases; + block->labelCases = new DxbcSwitchLabel(label); + } + + + void DxbcCompiler::emitControlFlowDefault(const DxbcShaderInstruction& ins) { + if (m_controlFlowBlocks.size() == 0 + || m_controlFlowBlocks.back().type != DxbcCfgBlockType::Switch) + throw DxvkError("DxbcCompiler: 'Default' without 'Switch' found"); + + DxbcCfgBlockSwitch* block = &m_controlFlowBlocks.back().b_switch; + + if (caseBlockIsFallthrough()) { + block->labelCase = m_module.allocateId(); + + m_module.opBranch(block->labelCase); + m_module.opLabel (block->labelCase); + } + + // Set the last label allocated for 'case' as the default label. + block->labelDefault = block->labelCase; + } + + + void DxbcCompiler::emitControlFlowEndSwitch(const DxbcShaderInstruction& ins) { + if (m_controlFlowBlocks.size() == 0 + || m_controlFlowBlocks.back().type != DxbcCfgBlockType::Switch) + throw DxvkError("DxbcCompiler: 'EndSwitch' without 'Switch' found"); + + // Remove the block from the stack, it's closed + DxbcCfgBlock block = m_controlFlowBlocks.back(); + m_controlFlowBlocks.pop_back(); + + if (!block.b_switch.labelDefault) { + block.b_switch.labelDefault = caseBlockIsFallthrough() + ? block.b_switch.labelBreak + : block.b_switch.labelCase; + } + + // Close the current 'case' block + m_module.opBranch(block.b_switch.labelBreak); + m_module.opLabel (block.b_switch.labelBreak); + + // Insert the 'switch' statement. For that, we need to + // gather all the literal-label pairs for the construct. + m_module.beginInsertion(block.b_switch.insertPtr); + m_module.opSelectionMerge( + block.b_switch.labelBreak, + spv::SelectionControlMaskNone); + + // We'll restore the original order of the case labels here + std::vector jumpTargets; + for (auto i = block.b_switch.labelCases; i != nullptr; i = i->next) + jumpTargets.insert(jumpTargets.begin(), i->desc); + + m_module.opSwitch( + block.b_switch.selectorId, + block.b_switch.labelDefault, + jumpTargets.size(), + jumpTargets.data()); + m_module.endInsertion(); + + // Destroy the list of case labels + // FIXME we're leaking memory if compilation fails. + DxbcSwitchLabel* caseLabel = block.b_switch.labelCases; + + while (caseLabel != nullptr) + delete std::exchange(caseLabel, caseLabel->next); + } + + + void DxbcCompiler::emitControlFlowLoop(const DxbcShaderInstruction& ins) { + // Declare the 'loop' block + DxbcCfgBlock block; + block.type = DxbcCfgBlockType::Loop; + block.b_loop.labelHeader = m_module.allocateId(); + block.b_loop.labelBegin = m_module.allocateId(); + block.b_loop.labelContinue = m_module.allocateId(); + block.b_loop.labelBreak = m_module.allocateId(); + m_controlFlowBlocks.push_back(block); + + m_module.opBranch(block.b_loop.labelHeader); + m_module.opLabel (block.b_loop.labelHeader); + + m_module.opLoopMerge( + block.b_loop.labelBreak, + block.b_loop.labelContinue, + spv::LoopControlMaskNone); + + m_module.opBranch(block.b_loop.labelBegin); + m_module.opLabel (block.b_loop.labelBegin); + } + + + void DxbcCompiler::emitControlFlowEndLoop(const DxbcShaderInstruction& ins) { + if (m_controlFlowBlocks.size() == 0 + || m_controlFlowBlocks.back().type != DxbcCfgBlockType::Loop) + throw DxvkError("DxbcCompiler: 'EndLoop' without 'Loop' found"); + + // Remove the block from the stack, it's closed + const DxbcCfgBlock block = m_controlFlowBlocks.back(); + m_controlFlowBlocks.pop_back(); + + // Declare the continue block + m_module.opBranch(block.b_loop.labelContinue); + m_module.opLabel (block.b_loop.labelContinue); + + // Declare the merge block + m_module.opBranch(block.b_loop.labelHeader); + m_module.opLabel (block.b_loop.labelBreak); + } + + + void DxbcCompiler::emitControlFlowBreak(const DxbcShaderInstruction& ins) { + const bool isBreak = ins.op == DxbcOpcode::Break; + + DxbcCfgBlock* cfgBlock = isBreak + ? cfgFindBlock({ DxbcCfgBlockType::Loop, DxbcCfgBlockType::Switch }) + : cfgFindBlock({ DxbcCfgBlockType::Loop }); + + if (cfgBlock == nullptr) + throw DxvkError("DxbcCompiler: 'Break' or 'Continue' outside 'Loop' or 'Switch' found"); + + if (cfgBlock->type == DxbcCfgBlockType::Loop) { + m_module.opBranch(isBreak + ? cfgBlock->b_loop.labelBreak + : cfgBlock->b_loop.labelContinue); + } else /* if (cfgBlock->type == DxbcCfgBlockType::Switch) */ { + m_module.opBranch(cfgBlock->b_switch.labelBreak); + } + + // Subsequent instructions assume that there is an open block + const uint32_t labelId = m_module.allocateId(); + m_module.opLabel(labelId); + + // If this is on the same level as a switch-case construct, + // rather than being nested inside an 'if' statement, close + // the current 'case' block. + if (m_controlFlowBlocks.back().type == DxbcCfgBlockType::Switch) + cfgBlock->b_switch.labelCase = labelId; + } + + + void DxbcCompiler::emitControlFlowBreakc(const DxbcShaderInstruction& ins) { + const bool isBreak = ins.op == DxbcOpcode::Breakc; + + DxbcCfgBlock* cfgBlock = isBreak + ? cfgFindBlock({ DxbcCfgBlockType::Loop, DxbcCfgBlockType::Switch }) + : cfgFindBlock({ DxbcCfgBlockType::Loop }); + + if (cfgBlock == nullptr) + throw DxvkError("DxbcCompiler: 'Breakc' or 'Continuec' outside 'Loop' or 'Switch' found"); + + // Perform zero test on the first component of the condition + const DxbcRegisterValue condition = emitRegisterLoad( + ins.src[0], DxbcRegMask(true, false, false, false)); + + const DxbcRegisterValue zeroTest = emitRegisterZeroTest( + condition, ins.controls.zeroTest()); + + // We basically have to wrap this into an 'if' block + const uint32_t breakBlock = m_module.allocateId(); + const uint32_t mergeBlock = m_module.allocateId(); + + m_module.opSelectionMerge(mergeBlock, + spv::SelectionControlMaskNone); + + m_module.opBranchConditional( + zeroTest.id, breakBlock, mergeBlock); + + m_module.opLabel(breakBlock); + + if (cfgBlock->type == DxbcCfgBlockType::Loop) { + m_module.opBranch(isBreak + ? cfgBlock->b_loop.labelBreak + : cfgBlock->b_loop.labelContinue); + } else /* if (cfgBlock->type == DxbcCfgBlockType::Switch) */ { + m_module.opBranch(cfgBlock->b_switch.labelBreak); + } + + m_module.opLabel(mergeBlock); + } + + + void DxbcCompiler::emitControlFlowRet(const DxbcShaderInstruction& ins) { + if (m_controlFlowBlocks.size() != 0) { + uint32_t labelId = m_module.allocateId(); + + m_module.opReturn(); + m_module.opLabel(labelId); + + // return can be used in place of break to terminate a case block + if (m_controlFlowBlocks.back().type == DxbcCfgBlockType::Switch) + m_controlFlowBlocks.back().b_switch.labelCase = labelId; + } else { + // Last instruction in the current function + this->emitFunctionEnd(); + } + } + + + void DxbcCompiler::emitControlFlowRetc(const DxbcShaderInstruction& ins) { + // Perform zero test on the first component of the condition + const DxbcRegisterValue condition = emitRegisterLoad( + ins.src[0], DxbcRegMask(true, false, false, false)); + + const DxbcRegisterValue zeroTest = emitRegisterZeroTest( + condition, ins.controls.zeroTest()); + + // We basically have to wrap this into an 'if' block + const uint32_t returnLabel = m_module.allocateId(); + const uint32_t continueLabel = m_module.allocateId(); + + m_module.opSelectionMerge(continueLabel, + spv::SelectionControlMaskNone); + + m_module.opBranchConditional( + zeroTest.id, returnLabel, continueLabel); + + m_module.opLabel(returnLabel); + m_module.opReturn(); + + m_module.opLabel(continueLabel); + } + + + void DxbcCompiler::emitControlFlowDiscard(const DxbcShaderInstruction& ins) { + // Discard actually has an operand that determines + // whether or not the fragment should be discarded + const DxbcRegisterValue condition = emitRegisterLoad( + ins.src[0], DxbcRegMask(true, false, false, false)); + + const DxbcRegisterValue zeroTest = emitRegisterZeroTest( + condition, ins.controls.zeroTest()); + + if (m_ps.killState == 0) { + DxbcConditional cond; + cond.labelIf = m_module.allocateId(); + cond.labelEnd = m_module.allocateId(); + + m_module.opSelectionMerge(cond.labelEnd, spv::SelectionControlMaskNone); + m_module.opBranchConditional(zeroTest.id, cond.labelIf, cond.labelEnd); + + m_module.opLabel(cond.labelIf); + + if (m_moduleInfo.options.useDemoteToHelperInvocation) { + m_module.opDemoteToHelperInvocation(); + m_module.opBranch(cond.labelEnd); + } else { + // OpKill terminates the block + m_module.opKill(); + } + + m_module.opLabel(cond.labelEnd); + } else { + uint32_t typeId = m_module.defBoolType(); + + uint32_t killState = m_module.opLoad (typeId, m_ps.killState); + killState = m_module.opLogicalOr(typeId, killState, zeroTest.id); + m_module.opStore(m_ps.killState, killState); + + if (m_moduleInfo.options.useSubgroupOpsForEarlyDiscard) { + uint32_t ballot = m_module.opGroupNonUniformBallot( + getVectorTypeId({ DxbcScalarType::Uint32, 4 }), + m_module.constu32(spv::ScopeSubgroup), + killState); + + uint32_t laneId = m_module.opLoad( + getScalarTypeId(DxbcScalarType::Uint32), + m_ps.builtinLaneId); + + uint32_t laneIdPart = m_module.opShiftRightLogical( + getScalarTypeId(DxbcScalarType::Uint32), + laneId, m_module.constu32(5)); + + uint32_t laneMask = m_module.opVectorExtractDynamic( + getScalarTypeId(DxbcScalarType::Uint32), + ballot, laneIdPart); + + uint32_t laneIdQuad = m_module.opBitwiseAnd( + getScalarTypeId(DxbcScalarType::Uint32), + laneId, m_module.constu32(0x1c)); + + laneMask = m_module.opShiftRightLogical( + getScalarTypeId(DxbcScalarType::Uint32), + laneMask, laneIdQuad); + + laneMask = m_module.opBitwiseAnd( + getScalarTypeId(DxbcScalarType::Uint32), + laneMask, m_module.constu32(0xf)); + + uint32_t killSubgroup = m_module.opIEqual( + m_module.defBoolType(), + laneMask, m_module.constu32(0xf)); + + DxbcConditional cond; + cond.labelIf = m_module.allocateId(); + cond.labelEnd = m_module.allocateId(); + + m_module.opSelectionMerge(cond.labelEnd, spv::SelectionControlMaskNone); + m_module.opBranchConditional(killSubgroup, cond.labelIf, cond.labelEnd); + + // OpKill terminates the block + m_module.opLabel(cond.labelIf); + m_module.opKill(); + + m_module.opLabel(cond.labelEnd); + } + } + } + + + void DxbcCompiler::emitControlFlowLabel(const DxbcShaderInstruction& ins) { + uint32_t functionNr = ins.dst[0].idx[0].offset; + uint32_t functionId = getFunctionId(functionNr); + + this->emitFunctionBegin( + functionId, + m_module.defVoidType(), + m_module.defFunctionType( + m_module.defVoidType(), 0, nullptr)); + + m_module.opLabel(m_module.allocateId()); + m_module.setDebugName(functionId, str::format("label", functionNr).c_str()); + + m_insideFunction = true; + } + + + void DxbcCompiler::emitControlFlowCall(const DxbcShaderInstruction& ins) { + uint32_t functionNr = ins.src[0].idx[0].offset; + uint32_t functionId = getFunctionId(functionNr); + + m_module.opFunctionCall( + m_module.defVoidType(), + functionId, 0, nullptr); + } + + + void DxbcCompiler::emitControlFlowCallc(const DxbcShaderInstruction& ins) { + uint32_t functionNr = ins.src[1].idx[0].offset; + uint32_t functionId = getFunctionId(functionNr); + + // Perform zero test on the first component of the condition + const DxbcRegisterValue condition = emitRegisterLoad( + ins.src[0], DxbcRegMask(true, false, false, false)); + + const DxbcRegisterValue zeroTest = emitRegisterZeroTest( + condition, ins.controls.zeroTest()); + + // We basically have to wrap this into an 'if' block + const uint32_t callLabel = m_module.allocateId(); + const uint32_t skipLabel = m_module.allocateId(); + + m_module.opSelectionMerge(skipLabel, + spv::SelectionControlMaskNone); + + m_module.opBranchConditional( + zeroTest.id, callLabel, skipLabel); + + m_module.opLabel(callLabel); + m_module.opFunctionCall( + m_module.defVoidType(), + functionId, 0, nullptr); + + m_module.opBranch(skipLabel); + m_module.opLabel(skipLabel); + } + + + void DxbcCompiler::emitControlFlow(const DxbcShaderInstruction& ins) { + switch (ins.op) { + case DxbcOpcode::If: + return this->emitControlFlowIf(ins); + + case DxbcOpcode::Else: + return this->emitControlFlowElse(ins); + + case DxbcOpcode::EndIf: + return this->emitControlFlowEndIf(ins); + + case DxbcOpcode::Switch: + return this->emitControlFlowSwitch(ins); + + case DxbcOpcode::Case: + return this->emitControlFlowCase(ins); + + case DxbcOpcode::Default: + return this->emitControlFlowDefault(ins); + + case DxbcOpcode::EndSwitch: + return this->emitControlFlowEndSwitch(ins); + + case DxbcOpcode::Loop: + return this->emitControlFlowLoop(ins); + + case DxbcOpcode::EndLoop: + return this->emitControlFlowEndLoop(ins); + + case DxbcOpcode::Break: + case DxbcOpcode::Continue: + return this->emitControlFlowBreak(ins); + + case DxbcOpcode::Breakc: + case DxbcOpcode::Continuec: + return this->emitControlFlowBreakc(ins); + + case DxbcOpcode::Ret: + return this->emitControlFlowRet(ins); + + case DxbcOpcode::Retc: + return this->emitControlFlowRetc(ins); + + case DxbcOpcode::Discard: + return this->emitControlFlowDiscard(ins); + + case DxbcOpcode::Label: + return this->emitControlFlowLabel(ins); + + case DxbcOpcode::Call: + return this->emitControlFlowCall(ins); + + case DxbcOpcode::Callc: + return this->emitControlFlowCallc(ins); + + default: + Logger::warn(str::format( + "DxbcCompiler: Unhandled instruction: ", + ins.op)); + } + } + + + DxbcRegisterValue DxbcCompiler::emitBuildConstVecf32( + float x, + float y, + float z, + float w, + const DxbcRegMask& writeMask) { + // TODO refactor these functions into one single template + std::array ids = { 0, 0, 0, 0 }; + uint32_t componentIndex = 0; + + if (writeMask[0]) ids[componentIndex++] = m_module.constf32(x); + if (writeMask[1]) ids[componentIndex++] = m_module.constf32(y); + if (writeMask[2]) ids[componentIndex++] = m_module.constf32(z); + if (writeMask[3]) ids[componentIndex++] = m_module.constf32(w); + + DxbcRegisterValue result; + result.type.ctype = DxbcScalarType::Float32; + result.type.ccount = componentIndex; + result.id = componentIndex > 1 + ? m_module.constComposite( + getVectorTypeId(result.type), + componentIndex, ids.data()) + : ids[0]; + return result; + } + + + DxbcRegisterValue DxbcCompiler::emitBuildConstVecu32( + uint32_t x, + uint32_t y, + uint32_t z, + uint32_t w, + const DxbcRegMask& writeMask) { + std::array ids = { 0, 0, 0, 0 }; + uint32_t componentIndex = 0; + + if (writeMask[0]) ids[componentIndex++] = m_module.constu32(x); + if (writeMask[1]) ids[componentIndex++] = m_module.constu32(y); + if (writeMask[2]) ids[componentIndex++] = m_module.constu32(z); + if (writeMask[3]) ids[componentIndex++] = m_module.constu32(w); + + DxbcRegisterValue result; + result.type.ctype = DxbcScalarType::Uint32; + result.type.ccount = componentIndex; + result.id = componentIndex > 1 + ? m_module.constComposite( + getVectorTypeId(result.type), + componentIndex, ids.data()) + : ids[0]; + return result; + } + + + DxbcRegisterValue DxbcCompiler::emitBuildConstVeci32( + int32_t x, + int32_t y, + int32_t z, + int32_t w, + const DxbcRegMask& writeMask) { + std::array ids = { 0, 0, 0, 0 }; + uint32_t componentIndex = 0; + + if (writeMask[0]) ids[componentIndex++] = m_module.consti32(x); + if (writeMask[1]) ids[componentIndex++] = m_module.consti32(y); + if (writeMask[2]) ids[componentIndex++] = m_module.consti32(z); + if (writeMask[3]) ids[componentIndex++] = m_module.consti32(w); + + DxbcRegisterValue result; + result.type.ctype = DxbcScalarType::Sint32; + result.type.ccount = componentIndex; + result.id = componentIndex > 1 + ? m_module.constComposite( + getVectorTypeId(result.type), + componentIndex, ids.data()) + : ids[0]; + return result; + } + + + DxbcRegisterValue DxbcCompiler::emitBuildConstVecf64( + double xy, + double zw, + const DxbcRegMask& writeMask) { + std::array ids = { 0, 0 }; + uint32_t componentIndex = 0; + + if (writeMask[0] && writeMask[1]) ids[componentIndex++] = m_module.constf64(xy); + if (writeMask[2] && writeMask[3]) ids[componentIndex++] = m_module.constf64(zw); + + DxbcRegisterValue result; + result.type.ctype = DxbcScalarType::Float64; + result.type.ccount = componentIndex; + result.id = componentIndex > 1 + ? m_module.constComposite( + getVectorTypeId(result.type), + componentIndex, ids.data()) + : ids[0]; + return result; + } + + + DxbcRegisterValue DxbcCompiler::emitBuildVector( + DxbcRegisterValue scalar, + uint32_t count) { + if (count == 1) + return scalar; + + std::array scalarIds = + { scalar.id, scalar.id, scalar.id, scalar.id }; + + DxbcRegisterValue result; + result.type.ctype = scalar.type.ctype; + result.type.ccount = count; + result.id = m_module.constComposite( + getVectorTypeId(result.type), + count, scalarIds.data()); + return result; + } + + + DxbcRegisterValue DxbcCompiler::emitBuildZeroVector( + DxbcVectorType type) { + DxbcRegisterValue result; + result.type.ctype = type.ctype; + result.type.ccount = 1; + + switch (type.ctype) { + case DxbcScalarType::Float32: result.id = m_module.constf32(0.0f); break; + case DxbcScalarType::Uint32: result.id = m_module.constu32(0u); break; + case DxbcScalarType::Sint32: result.id = m_module.consti32(0); break; + default: throw DxvkError("DxbcCompiler: Invalid scalar type"); + } + + return emitBuildVector(result, type.ccount); + } + + + DxbcRegisterValue DxbcCompiler::emitRegisterBitcast( + DxbcRegisterValue srcValue, + DxbcScalarType dstType) { + DxbcScalarType srcType = srcValue.type.ctype; + + if (srcType == dstType) + return srcValue; + + DxbcRegisterValue result; + result.type.ctype = dstType; + result.type.ccount = srcValue.type.ccount; + + if (isDoubleType(srcType)) result.type.ccount *= 2; + if (isDoubleType(dstType)) result.type.ccount /= 2; + + result.id = m_module.opBitcast( + getVectorTypeId(result.type), + srcValue.id); + return result; + } + + + DxbcRegisterValue DxbcCompiler::emitRegisterSwizzle( + DxbcRegisterValue value, + DxbcRegSwizzle swizzle, + DxbcRegMask writeMask) { + if (value.type.ccount == 1) + return emitRegisterExtend(value, writeMask.popCount()); + + std::array indices; + + uint32_t dstIndex = 0; + + for (uint32_t i = 0; i < 4; i++) { + if (writeMask[i]) + indices[dstIndex++] = swizzle[i]; + } + + // If the swizzle combined with the mask can be reduced + // to a no-op, we don't need to insert any instructions. + bool isIdentitySwizzle = dstIndex == value.type.ccount; + + for (uint32_t i = 0; i < dstIndex && isIdentitySwizzle; i++) + isIdentitySwizzle &= indices[i] == i; + + if (isIdentitySwizzle) + return value; + + // Use OpCompositeExtract if the resulting vector contains + // only one component, and OpVectorShuffle if it is a vector. + DxbcRegisterValue result; + result.type.ctype = value.type.ctype; + result.type.ccount = dstIndex; + + const uint32_t typeId = getVectorTypeId(result.type); + + if (dstIndex == 1) { + result.id = m_module.opCompositeExtract( + typeId, value.id, 1, indices.data()); + } else { + result.id = m_module.opVectorShuffle( + typeId, value.id, value.id, + dstIndex, indices.data()); + } + + return result; + } + + + DxbcRegisterValue DxbcCompiler::emitRegisterExtract( + DxbcRegisterValue value, + DxbcRegMask mask) { + return emitRegisterSwizzle(value, + DxbcRegSwizzle(0, 1, 2, 3), mask); + } + + + DxbcRegisterValue DxbcCompiler::emitRegisterInsert( + DxbcRegisterValue dstValue, + DxbcRegisterValue srcValue, + DxbcRegMask srcMask) { + DxbcRegisterValue result; + result.type = dstValue.type; + + const uint32_t typeId = getVectorTypeId(result.type); + + if (srcMask.popCount() == 0) { + // Nothing to do if the insertion mask is empty + result.id = dstValue.id; + } else if (dstValue.type.ccount == 1) { + // Both values are scalar, so the first component + // of the write mask decides which one to take. + result.id = srcMask[0] ? srcValue.id : dstValue.id; + } else if (srcValue.type.ccount == 1) { + // The source value is scalar. Since OpVectorShuffle + // requires both arguments to be vectors, we have to + // use OpCompositeInsert to modify the vector instead. + const uint32_t componentId = srcMask.firstSet(); + + result.id = m_module.opCompositeInsert(typeId, + srcValue.id, dstValue.id, 1, &componentId); + } else { + // Both arguments are vectors. We can determine which + // components to take from which vector and use the + // OpVectorShuffle instruction. + std::array components; + uint32_t srcComponentId = dstValue.type.ccount; + + for (uint32_t i = 0; i < dstValue.type.ccount; i++) + components.at(i) = srcMask[i] ? srcComponentId++ : i; + + result.id = m_module.opVectorShuffle( + typeId, dstValue.id, srcValue.id, + dstValue.type.ccount, components.data()); + } + + return result; + } + + + DxbcRegisterValue DxbcCompiler::emitRegisterConcat( + DxbcRegisterValue value1, + DxbcRegisterValue value2) { + std::array ids = + {{ value1.id, value2.id }}; + + DxbcRegisterValue result; + result.type.ctype = value1.type.ctype; + result.type.ccount = value1.type.ccount + value2.type.ccount; + result.id = m_module.opCompositeConstruct( + getVectorTypeId(result.type), + ids.size(), ids.data()); + return result; + } + + + DxbcRegisterValue DxbcCompiler::emitRegisterExtend( + DxbcRegisterValue value, + uint32_t size) { + if (size == 1) + return value; + + std::array ids = {{ + value.id, value.id, + value.id, value.id, + }}; + + DxbcRegisterValue result; + result.type.ctype = value.type.ctype; + result.type.ccount = size; + result.id = m_module.opCompositeConstruct( + getVectorTypeId(result.type), + size, ids.data()); + return result; + } + + + DxbcRegisterValue DxbcCompiler::emitRegisterAbsolute( + DxbcRegisterValue value) { + const uint32_t typeId = getVectorTypeId(value.type); + + switch (value.type.ctype) { + case DxbcScalarType::Float32: value.id = m_module.opFAbs(typeId, value.id); break; + case DxbcScalarType::Float64: value.id = m_module.opFAbs(typeId, value.id); break; + case DxbcScalarType::Sint32: value.id = m_module.opSAbs(typeId, value.id); break; + case DxbcScalarType::Sint64: value.id = m_module.opSAbs(typeId, value.id); break; + default: Logger::warn("DxbcCompiler: Cannot get absolute value for given type"); + } + + return value; + } + + + DxbcRegisterValue DxbcCompiler::emitRegisterNegate( + DxbcRegisterValue value) { + const uint32_t typeId = getVectorTypeId(value.type); + + switch (value.type.ctype) { + case DxbcScalarType::Float32: value.id = m_module.opFNegate(typeId, value.id); break; + case DxbcScalarType::Float64: value.id = m_module.opFNegate(typeId, value.id); break; + case DxbcScalarType::Sint32: value.id = m_module.opSNegate(typeId, value.id); break; + case DxbcScalarType::Sint64: value.id = m_module.opSNegate(typeId, value.id); break; + default: Logger::warn("DxbcCompiler: Cannot negate given type"); + } + + return value; + } + + + DxbcRegisterValue DxbcCompiler::emitRegisterZeroTest( + DxbcRegisterValue value, + DxbcZeroTest test) { + DxbcRegisterValue result; + result.type.ctype = DxbcScalarType::Bool; + result.type.ccount = 1; + + const uint32_t zeroId = m_module.constu32(0u); + const uint32_t typeId = getVectorTypeId(result.type); + + result.id = test == DxbcZeroTest::TestZ + ? m_module.opIEqual (typeId, value.id, zeroId) + : m_module.opINotEqual(typeId, value.id, zeroId); + return result; + } + + + DxbcRegisterValue DxbcCompiler::emitRegisterMaskBits( + DxbcRegisterValue value, + uint32_t mask) { + DxbcRegisterValue maskVector = emitBuildConstVecu32( + mask, mask, mask, mask, DxbcRegMask::firstN(value.type.ccount)); + + DxbcRegisterValue result; + result.type = value.type; + result.id = m_module.opBitwiseAnd( + getVectorTypeId(result.type), + value.id, maskVector.id); + return result; + } + + + DxbcRegisterValue DxbcCompiler::emitSrcOperandModifiers( + DxbcRegisterValue value, + DxbcRegModifiers modifiers) { + if (modifiers.test(DxbcRegModifier::Abs)) + value = emitRegisterAbsolute(value); + + if (modifiers.test(DxbcRegModifier::Neg)) + value = emitRegisterNegate(value); + return value; + } + + + DxbcRegisterValue DxbcCompiler::emitDstOperandModifiers( + DxbcRegisterValue value, + DxbcOpModifiers modifiers) { + const uint32_t typeId = getVectorTypeId(value.type); + + if (modifiers.saturate) { + DxbcRegMask mask; + DxbcRegisterValue vec0, vec1; + + if (value.type.ctype == DxbcScalarType::Float32) { + mask = DxbcRegMask::firstN(value.type.ccount); + vec0 = emitBuildConstVecf32(0.0f, 0.0f, 0.0f, 0.0f, mask); + vec1 = emitBuildConstVecf32(1.0f, 1.0f, 1.0f, 1.0f, mask); + } else if (value.type.ctype == DxbcScalarType::Float64) { + mask = DxbcRegMask::firstN(value.type.ccount * 2); + vec0 = emitBuildConstVecf64(0.0, 0.0, mask); + vec1 = emitBuildConstVecf64(1.0, 1.0, mask); + } + + if (mask) + value.id = m_module.opNClamp(typeId, value.id, vec0.id, vec1.id); + } + + return value; + } + + + DxbcRegisterPointer DxbcCompiler::emitArrayAccess( + DxbcRegisterPointer pointer, + spv::StorageClass sclass, + uint32_t index) { + uint32_t ptrTypeId = m_module.defPointerType( + getVectorTypeId(pointer.type), sclass); + + DxbcRegisterPointer result; + result.type = pointer.type; + result.id = m_module.opAccessChain( + ptrTypeId, pointer.id, 1, &index); + return result; + } + + + uint32_t DxbcCompiler::emitLoadSampledImage( + const DxbcShaderResource& textureResource, + const DxbcSampler& samplerResource, + bool isDepthCompare) { + const uint32_t sampledImageType = isDepthCompare + ? m_module.defSampledImageType(textureResource.depthTypeId) + : m_module.defSampledImageType(textureResource.colorTypeId); + + return m_module.opSampledImage(sampledImageType, + m_module.opLoad(textureResource.imageTypeId, textureResource.varId), + m_module.opLoad(samplerResource.typeId, samplerResource.varId)); + } + + + DxbcRegisterPointer DxbcCompiler::emitGetTempPtr( + const DxbcRegister& operand) { + // r# regs are indexed as follows: + // (0) register index (immediate) + uint32_t regIdx = operand.idx[0].offset; + + if (regIdx >= m_rRegs.size()) + m_rRegs.resize(regIdx + 1, 0u); + + if (!m_rRegs.at(regIdx)) { + DxbcRegisterInfo info; + info.type.ctype = DxbcScalarType::Float32; + info.type.ccount = 4; + info.type.alength = 0; + info.sclass = spv::StorageClassPrivate; + + uint32_t varId = emitNewVariable(info); + m_rRegs.at(regIdx) = varId; + + m_module.setDebugName(varId, + str::format("r", regIdx).c_str()); + } + + DxbcRegisterPointer result; + result.type.ctype = DxbcScalarType::Float32; + result.type.ccount = 4; + result.id = m_rRegs.at(regIdx); + return result; + } + + + DxbcRegisterPointer DxbcCompiler::emitGetIndexableTempPtr( + const DxbcRegister& operand) { + return getIndexableTempPtr(operand, emitIndexLoad(operand.idx[1])); + } + + + DxbcRegisterPointer DxbcCompiler::emitGetInputPtr( + const DxbcRegister& operand) { + // In the vertex and pixel stages, + // v# regs are indexed as follows: + // (0) register index (relative) + // + // In the tessellation and geometry + // stages, the index has two dimensions: + // (0) vertex index (relative) + // (1) register index (relative) + DxbcRegisterPointer result; + result.type.ctype = DxbcScalarType::Float32; + result.type.ccount = 4; + + std::array indices = {{ 0, 0 }}; + + for (uint32_t i = 0; i < operand.idxDim; i++) + indices.at(i) = emitIndexLoad(operand.idx[i]).id; + + // Pick the input array depending on + // the program type and operand type + struct InputArray { + uint32_t id; + spv::StorageClass sclass; + }; + + const InputArray array = [&] () -> InputArray { + switch (operand.type) { + case DxbcOperandType::InputControlPoint: + return m_programInfo.type() == DxbcProgramType::HullShader + ? InputArray { m_vArray, spv::StorageClassPrivate } + : InputArray { m_ds.inputPerVertex, spv::StorageClassInput }; + case DxbcOperandType::InputPatchConstant: + return m_programInfo.type() == DxbcProgramType::HullShader + ? InputArray { m_hs.outputPerPatch, spv::StorageClassPrivate } + : InputArray { m_ds.inputPerPatch, spv::StorageClassInput }; + case DxbcOperandType::OutputControlPoint: + return InputArray { m_hs.outputPerVertex, spv::StorageClassOutput }; + default: + return { m_vArray, spv::StorageClassPrivate }; + } + }(); + + DxbcRegisterInfo info; + info.type.ctype = result.type.ctype; + info.type.ccount = result.type.ccount; + info.type.alength = 0; + info.sclass = array.sclass; + + result.id = m_module.opAccessChain( + getPointerTypeId(info), array.id, + operand.idxDim, indices.data()); + + return result; + } + + + DxbcRegisterPointer DxbcCompiler::emitGetOutputPtr( + const DxbcRegister& operand) { + if (m_programInfo.type() == DxbcProgramType::HullShader) { + // Hull shaders are special in that they have two sets of + // output registers, one for per-patch values and one for + // per-vertex values. + DxbcRegisterPointer result; + result.type.ctype = DxbcScalarType::Float32; + result.type.ccount = 4; + + uint32_t registerId = emitIndexLoad(operand.idx[0]).id; + + if (m_hs.currPhaseType == DxbcCompilerHsPhase::ControlPoint) { + std::array indices = {{ + m_module.opLoad(m_module.defIntType(32, 0), m_hs.builtinInvocationId), + registerId, + }}; + + uint32_t ptrTypeId = m_module.defPointerType( + getVectorTypeId(result.type), + spv::StorageClassOutput); + + result.id = m_module.opAccessChain( + ptrTypeId, m_hs.outputPerVertex, + indices.size(), indices.data()); + } else { + uint32_t ptrTypeId = m_module.defPointerType( + getVectorTypeId(result.type), + spv::StorageClassPrivate); + + result.id = m_module.opAccessChain( + ptrTypeId, m_hs.outputPerPatch, + 1, ®isterId); + } + + return result; + } else { + // Regular shaders have their output + // registers set up at declaration time + return m_oRegs.at(operand.idx[0].offset); + } + } + + + DxbcRegisterPointer DxbcCompiler::emitGetImmConstBufPtr( + const DxbcRegister& operand) { + const DxbcRegisterValue constId + = emitIndexLoad(operand.idx[0]); + + if (m_immConstBuf != 0) { + DxbcRegisterInfo ptrInfo; + ptrInfo.type.ctype = DxbcScalarType::Uint32; + ptrInfo.type.ccount = 4; + ptrInfo.type.alength = 0; + ptrInfo.sclass = spv::StorageClassPrivate; + + DxbcRegisterPointer result; + result.type.ctype = ptrInfo.type.ctype; + result.type.ccount = ptrInfo.type.ccount; + result.id = m_module.opAccessChain( + getPointerTypeId(ptrInfo), + m_immConstBuf, 1, &constId.id); + return result; + } else if (m_constantBuffers.at(Icb_BindingSlotId).varId != 0) { + const std::array indices = + {{ m_module.consti32(0), constId.id }}; + + DxbcRegisterInfo ptrInfo; + ptrInfo.type.ctype = DxbcScalarType::Float32; + ptrInfo.type.ccount = 4; + ptrInfo.type.alength = 0; + ptrInfo.sclass = spv::StorageClassUniform; + + DxbcRegisterPointer result; + result.type.ctype = ptrInfo.type.ctype; + result.type.ccount = ptrInfo.type.ccount; + result.id = m_module.opAccessChain( + getPointerTypeId(ptrInfo), + m_constantBuffers.at(Icb_BindingSlotId).varId, + indices.size(), indices.data()); + return result; + } else { + throw DxvkError("DxbcCompiler: Immediate constant buffer not defined"); + } + } + + + DxbcRegisterPointer DxbcCompiler::emitGetOperandPtr( + const DxbcRegister& operand) { + switch (operand.type) { + case DxbcOperandType::Temp: + return emitGetTempPtr(operand); + + case DxbcOperandType::IndexableTemp: + return emitGetIndexableTempPtr(operand); + + case DxbcOperandType::Input: + case DxbcOperandType::InputControlPoint: + case DxbcOperandType::InputPatchConstant: + case DxbcOperandType::OutputControlPoint: + return emitGetInputPtr(operand); + + case DxbcOperandType::Output: + return emitGetOutputPtr(operand); + + case DxbcOperandType::ImmediateConstantBuffer: + return emitGetImmConstBufPtr(operand); + + case DxbcOperandType::InputThreadId: + return DxbcRegisterPointer { + { DxbcScalarType::Uint32, 3 }, + m_cs.builtinGlobalInvocationId }; + + case DxbcOperandType::InputThreadGroupId: + return DxbcRegisterPointer { + { DxbcScalarType::Uint32, 3 }, + m_cs.builtinWorkgroupId }; + + case DxbcOperandType::InputThreadIdInGroup: + return DxbcRegisterPointer { + { DxbcScalarType::Uint32, 3 }, + m_cs.builtinLocalInvocationId }; + + case DxbcOperandType::InputThreadIndexInGroup: + return DxbcRegisterPointer { + { DxbcScalarType::Uint32, 1 }, + m_cs.builtinLocalInvocationIndex }; + + case DxbcOperandType::InputCoverageMask: { + const std::array indices + = {{ m_module.constu32(0) }}; + + DxbcRegisterPointer result; + result.type.ctype = DxbcScalarType::Uint32; + result.type.ccount = 1; + result.id = m_module.opAccessChain( + m_module.defPointerType( + getVectorTypeId(result.type), + spv::StorageClassInput), + m_ps.builtinSampleMaskIn, + indices.size(), indices.data()); + return result; + } + + case DxbcOperandType::OutputCoverageMask: { + const std::array indices + = {{ m_module.constu32(0) }}; + + DxbcRegisterPointer result; + result.type.ctype = DxbcScalarType::Uint32; + result.type.ccount = 1; + result.id = m_module.opAccessChain( + m_module.defPointerType( + getVectorTypeId(result.type), + spv::StorageClassOutput), + m_ps.builtinSampleMaskOut, + indices.size(), indices.data()); + return result; + } + + case DxbcOperandType::OutputDepth: + case DxbcOperandType::OutputDepthGe: + case DxbcOperandType::OutputDepthLe: + return DxbcRegisterPointer { + { DxbcScalarType::Float32, 1 }, + m_ps.builtinDepth }; + + case DxbcOperandType::OutputStencilRef: + return DxbcRegisterPointer { + { DxbcScalarType::Sint32, 1 }, + m_ps.builtinStencilRef }; + + case DxbcOperandType::InputPrimitiveId: + return DxbcRegisterPointer { + { DxbcScalarType::Uint32, 1 }, + m_primitiveIdIn }; + + case DxbcOperandType::InputDomainPoint: + return DxbcRegisterPointer { + { DxbcScalarType::Float32, 3 }, + m_ds.builtinTessCoord }; + + case DxbcOperandType::OutputControlPointId: + return DxbcRegisterPointer { + { DxbcScalarType::Uint32, 1 }, + m_hs.builtinInvocationId }; + + case DxbcOperandType::InputForkInstanceId: + case DxbcOperandType::InputJoinInstanceId: + return DxbcRegisterPointer { + { DxbcScalarType::Uint32, 1 }, + getCurrentHsForkJoinPhase()->instanceIdPtr }; + + case DxbcOperandType::InputGsInstanceId: + return DxbcRegisterPointer { + { DxbcScalarType::Uint32, 1 }, + m_gs.builtinInvocationId }; + + default: + throw DxvkError(str::format( + "DxbcCompiler: Unhandled operand type: ", + operand.type)); + } + } + + + DxbcRegisterPointer DxbcCompiler::emitGetAtomicPointer( + const DxbcRegister& operand, + const DxbcRegister& address) { + // Query information about the resource itself + const uint32_t registerId = operand.idx[0].offset; + const DxbcBufferInfo resourceInfo = getBufferInfo(operand); + + // For UAVs and shared memory, different methods + // of obtaining the final pointer are used. + bool isTgsm = operand.type == DxbcOperandType::ThreadGroupSharedMemory; + bool isSsbo = m_moduleInfo.options.minSsboAlignment <= resourceInfo.align + && resourceInfo.type != DxbcResourceType::Typed + && !isTgsm; + + // Compute the actual address into the resource + const DxbcRegisterValue addressValue = [&] { + switch (resourceInfo.type) { + case DxbcResourceType::Raw: + return emitCalcBufferIndexRaw(emitRegisterLoad( + address, DxbcRegMask(true, false, false, false))); + + case DxbcResourceType::Structured: { + const DxbcRegisterValue addressComponents = emitRegisterLoad( + address, DxbcRegMask(true, true, false, false)); + + return emitCalcBufferIndexStructured( + emitRegisterExtract(addressComponents, DxbcRegMask(true, false, false, false)), + emitRegisterExtract(addressComponents, DxbcRegMask(false, true, false, false)), + resourceInfo.stride); + }; + + case DxbcResourceType::Typed: { + if (isTgsm) + throw DxvkError("DxbcCompiler: TGSM cannot be typed"); + + return emitLoadTexCoord(address, + m_uavs.at(registerId).imageInfo); + } + + default: + throw DxvkError("DxbcCompiler: Unhandled resource type"); + } + }(); + + // Compute the actual pointer + DxbcRegisterPointer result; + result.type.ctype = resourceInfo.stype; + result.type.ccount = 1; + + if (isTgsm) { + result.id = m_module.opAccessChain(resourceInfo.typeId, + resourceInfo.varId, 1, &addressValue.id); + } else if (isSsbo) { + uint32_t indices[2] = { m_module.constu32(0), addressValue.id }; + result.id = m_module.opAccessChain(resourceInfo.typeId, + resourceInfo.varId, 2, indices); + } else { + result.id = m_module.opImageTexelPointer( + m_module.defPointerType(getVectorTypeId(result.type), spv::StorageClassImage), + resourceInfo.varId, addressValue.id, m_module.constu32(0)); + } + + return result; + } + + + DxbcRegisterValue DxbcCompiler::emitRawBufferLoad( + const DxbcRegister& operand, + DxbcRegisterValue elementIndex, + DxbcRegMask writeMask) { + const DxbcBufferInfo bufferInfo = getBufferInfo(operand); + + // Shared memory is the only type of buffer that + // is not accessed through a texel buffer view + bool isTgsm = operand.type == DxbcOperandType::ThreadGroupSharedMemory; + bool isSsbo = m_moduleInfo.options.minSsboAlignment <= bufferInfo.align + && !isTgsm; + + // Common types and IDs used while loading the data + uint32_t bufferId = isTgsm || isSsbo ? 0 : m_module.opLoad(bufferInfo.typeId, bufferInfo.varId); + + uint32_t vectorTypeId = getVectorTypeId({ DxbcScalarType::Uint32, 4 }); + uint32_t scalarTypeId = getVectorTypeId({ DxbcScalarType::Uint32, 1 }); + + // Since all data is represented as a sequence of 32-bit + // integers, we have to load each component individually. + std::array ccomps = { 0, 0, 0, 0 }; + std::array scomps = { 0, 0, 0, 0 }; + uint32_t scount = 0; + + for (uint32_t i = 0; i < 4; i++) { + uint32_t sindex = operand.swizzle[i]; + + if (!writeMask[i]) + continue; + + if (ccomps[sindex] == 0) { + uint32_t elementIndexAdjusted = m_module.opIAdd( + getVectorTypeId(elementIndex.type), elementIndex.id, + m_module.consti32(sindex)); + + // Load requested component from the buffer + uint32_t zero = 0; + + if (isTgsm) { + ccomps[sindex] = m_module.opLoad(scalarTypeId, + m_module.opAccessChain(bufferInfo.typeId, + bufferInfo.varId, 1, &elementIndexAdjusted)); + } else if (isSsbo) { + uint32_t indices[2] = { m_module.constu32(0), elementIndexAdjusted }; + ccomps[sindex] = m_module.opLoad(scalarTypeId, + m_module.opAccessChain(bufferInfo.typeId, + bufferInfo.varId, 2, indices)); + } else if (operand.type == DxbcOperandType::Resource) { + ccomps[sindex] = m_module.opCompositeExtract(scalarTypeId, + m_module.opImageFetch(vectorTypeId, + bufferId, elementIndexAdjusted, + SpirvImageOperands()), 1, &zero); + } else if (operand.type == DxbcOperandType::UnorderedAccessView) { + ccomps[sindex] = m_module.opCompositeExtract(scalarTypeId, + m_module.opImageRead(vectorTypeId, + bufferId, elementIndexAdjusted, + SpirvImageOperands()), 1, &zero); + } else { + throw DxvkError("DxbcCompiler: Invalid operand type for strucured/raw load"); + } + } + } + + for (uint32_t i = 0; i < 4; i++) { + uint32_t sindex = operand.swizzle[i]; + + if (writeMask[i]) + scomps[scount++] = ccomps[sindex]; + } + + DxbcRegisterValue result; + result.type.ctype = DxbcScalarType::Uint32; + result.type.ccount = scount; + result.id = scomps[0]; + + if (scount > 1) { + result.id = m_module.opCompositeConstruct( + getVectorTypeId(result.type), + scount, scomps.data()); + } + + return result; + } + + + void DxbcCompiler::emitRawBufferStore( + const DxbcRegister& operand, + DxbcRegisterValue elementIndex, + DxbcRegisterValue value) { + const DxbcBufferInfo bufferInfo = getBufferInfo(operand); + + // Cast source value to the expected data type + value = emitRegisterBitcast(value, DxbcScalarType::Uint32); + + // Thread Group Shared Memory is not accessed through a texel buffer view + bool isTgsm = operand.type == DxbcOperandType::ThreadGroupSharedMemory; + bool isSsbo = m_moduleInfo.options.minSsboAlignment <= bufferInfo.align + && !isTgsm; + + // Perform UAV writes only if the UAV is bound and if there + // is nothing else preventing us from writing to it. + DxbcConditional cond; + + if (!isTgsm) { + uint32_t writeTest = emitUavWriteTest(bufferInfo); + + cond.labelIf = m_module.allocateId(); + cond.labelEnd = m_module.allocateId(); + + m_module.opSelectionMerge(cond.labelEnd, spv::SelectionControlMaskNone); + m_module.opBranchConditional(writeTest, cond.labelIf, cond.labelEnd); + + m_module.opLabel(cond.labelIf); + } + + // Perform the actual write operation + uint32_t bufferId = isTgsm || isSsbo ? 0 : m_module.opLoad(bufferInfo.typeId, bufferInfo.varId); + + uint32_t scalarTypeId = getVectorTypeId({ DxbcScalarType::Uint32, 1 }); + uint32_t vectorTypeId = getVectorTypeId({ DxbcScalarType::Uint32, 4 }); + + uint32_t srcComponentIndex = 0; + + for (uint32_t i = 0; i < 4; i++) { + if (operand.mask[i]) { + uint32_t srcComponentId = value.type.ccount > 1 + ? m_module.opCompositeExtract(scalarTypeId, + value.id, 1, &srcComponentIndex) + : value.id; + + // Add the component offset to the element index + uint32_t elementIndexAdjusted = i != 0 + ? m_module.opIAdd(getVectorTypeId(elementIndex.type), + elementIndex.id, m_module.consti32(i)) + : elementIndex.id; + + if (isTgsm) { + m_module.opStore( + m_module.opAccessChain(bufferInfo.typeId, + bufferInfo.varId, 1, &elementIndexAdjusted), + srcComponentId); + } else if (isSsbo) { + uint32_t indices[2] = { m_module.constu32(0), elementIndexAdjusted }; + m_module.opStore( + m_module.opAccessChain(bufferInfo.typeId, + bufferInfo.varId, 2, indices), + srcComponentId); + } else if (operand.type == DxbcOperandType::UnorderedAccessView) { + const std::array srcVectorIds = { + srcComponentId, srcComponentId, + srcComponentId, srcComponentId, + }; + + m_module.opImageWrite( + bufferId, elementIndexAdjusted, + m_module.opCompositeConstruct(vectorTypeId, + 4, srcVectorIds.data()), + SpirvImageOperands()); + } else { + throw DxvkError("DxbcCompiler: Invalid operand type for strucured/raw store"); + } + + // Write next component + srcComponentIndex += 1; + } + } + + // Make sure that shared memory stores are made visible in + // case the game does not synchronize invocations properly + if (isTgsm && m_moduleInfo.options.forceTgsmBarriers) { + m_module.opMemoryBarrier( + m_module.constu32(spv::ScopeWorkgroup), + m_module.constu32(spv::MemorySemanticsWorkgroupMemoryMask + | spv::MemorySemanticsAcquireReleaseMask)); + } + + // End conditional block + if (!isTgsm) { + m_module.opBranch(cond.labelEnd); + m_module.opLabel (cond.labelEnd); + } + } + + + DxbcRegisterValue DxbcCompiler::emitQueryBufferSize( + const DxbcRegister& resource) { + const DxbcBufferInfo bufferInfo = getBufferInfo(resource); + + DxbcRegisterValue result; + result.type.ctype = DxbcScalarType::Uint32; + result.type.ccount = 1; + result.id = m_module.opArrayLength( + getVectorTypeId(result.type), + bufferInfo.varId, 0); + + // Report a size of 0 if resource is not bound + result.id = m_module.opSelect(getVectorTypeId(result.type), + bufferInfo.specId, result.id, m_module.constu32(0)); + return result; + } + + + DxbcRegisterValue DxbcCompiler::emitQueryTexelBufferSize( + const DxbcRegister& resource) { + // Load the texel buffer object. This cannot be used with + // constant buffers or any other type of resource. + const DxbcBufferInfo bufferInfo = getBufferInfo(resource); + + const uint32_t bufferId = m_module.opLoad( + bufferInfo.typeId, bufferInfo.varId); + + // We'll store this as a scalar unsigned integer + DxbcRegisterValue result; + result.type.ctype = DxbcScalarType::Uint32; + result.type.ccount = 1; + result.id = m_module.opImageQuerySize( + getVectorTypeId(result.type), bufferId); + + // Report a size of 0 if resource is not bound + result.id = m_module.opSelect(getVectorTypeId(result.type), + bufferInfo.specId, result.id, m_module.constu32(0)); + return result; + } + + + DxbcRegisterValue DxbcCompiler::emitQueryTextureLods( + const DxbcRegister& resource) { + const DxbcBufferInfo info = getBufferInfo(resource); + + DxbcRegisterValue result; + result.type.ctype = DxbcScalarType::Uint32; + result.type.ccount = 1; + + if (info.image.sampled == 1) { + result.id = m_module.opImageQueryLevels( + getVectorTypeId(result.type), + m_module.opLoad(info.typeId, info.varId)); + } else { + // Report one LOD in case of UAVs + result.id = m_module.constu32(1); + } + + // Report zero LODs for unbound images + result.id = m_module.opSelect(getVectorTypeId(result.type), + info.specId, result.id, m_module.constu32(0)); + return result; + } + + + DxbcRegisterValue DxbcCompiler::emitQueryTextureSamples( + const DxbcRegister& resource) { + if (resource.type == DxbcOperandType::Rasterizer) { + // SPIR-V has no gl_NumSamples equivalent, so we have + // to work around it using a specialization constant + if (!m_ps.specRsSampleCount) { + m_ps.specRsSampleCount = emitNewSpecConstant( + DxvkSpecConstantId::RasterizerSampleCount, + DxbcScalarType::Uint32, 1, + "RasterizerSampleCount"); + } + + DxbcRegisterValue result; + result.type.ctype = DxbcScalarType::Uint32; + result.type.ccount = 1; + result.id = m_ps.specRsSampleCount; + return result; + } else { + DxbcBufferInfo info = getBufferInfo(resource); + + DxbcRegisterValue result; + result.type.ctype = DxbcScalarType::Uint32; + result.type.ccount = 1; + + if (info.image.ms) { + result.id = m_module.opImageQuerySamples( + getVectorTypeId(result.type), + m_module.opLoad(info.typeId, info.varId)); + } else { + // OpImageQuerySamples requires MSAA images + result.id = m_module.constu32(1); + } + + // Report a sample count of 0 for unbound images + result.id = m_module.opSelect(getVectorTypeId(result.type), + info.specId, result.id, m_module.constu32(0)); + return result; + } + } + + + DxbcRegisterValue DxbcCompiler::emitQueryTextureSize( + const DxbcRegister& resource, + DxbcRegisterValue lod) { + const DxbcBufferInfo info = getBufferInfo(resource); + + DxbcRegisterValue result; + result.type.ctype = DxbcScalarType::Uint32; + result.type.ccount = getTexSizeDim(info.image); + + if (info.image.ms == 0 && info.image.sampled == 1) { + result.id = m_module.opImageQuerySizeLod( + getVectorTypeId(result.type), + m_module.opLoad(info.typeId, info.varId), + lod.id); + } else { + result.id = m_module.opImageQuerySize( + getVectorTypeId(result.type), + m_module.opLoad(info.typeId, info.varId)); + } + + // Report a size of zero for unbound textures + uint32_t zero = m_module.constu32(0); + uint32_t cond = info.specId; + + if (result.type.ccount > 1) { + std::array zeroes = {{ zero, zero, zero, zero }}; + std::array conds = {{ cond, cond, cond, cond }}; + + zero = m_module.opCompositeConstruct( + getVectorTypeId(result.type), + result.type.ccount, zeroes.data()); + + cond = m_module.opCompositeConstruct( + m_module.defVectorType(m_module.defBoolType(), result.type.ccount), + result.type.ccount, conds.data()); + } + + result.id = m_module.opSelect( + getVectorTypeId(result.type), + cond, result.id, zero); + return result; + } + + + DxbcRegisterValue DxbcCompiler::emitCalcBufferIndexStructured( + DxbcRegisterValue structId, + DxbcRegisterValue structOffset, + uint32_t structStride) { + DxbcRegisterValue result; + result.type.ctype = DxbcScalarType::Sint32; + result.type.ccount = 1; + + const uint32_t typeId = getVectorTypeId(result.type); + + uint32_t offset = m_moduleInfo.options.useSdivForBufferIndex + ? m_module.opSDiv (typeId, structOffset.id, m_module.consti32(4)) + : m_module.opShiftRightLogical(typeId, structOffset.id, m_module.consti32(2)); + + result.id = m_module.opIAdd(typeId, + m_module.opIMul(typeId, structId.id, m_module.consti32(structStride / 4)), + offset); + return result; + } + + + DxbcRegisterValue DxbcCompiler::emitCalcBufferIndexRaw( + DxbcRegisterValue byteOffset) { + DxbcRegisterValue result; + result.type.ctype = DxbcScalarType::Sint32; + result.type.ccount = 1; + + uint32_t typeId = getVectorTypeId(result.type); + + result.id = m_moduleInfo.options.useSdivForBufferIndex + ? m_module.opSDiv (typeId, byteOffset.id, m_module.consti32(4)) + : m_module.opShiftRightLogical(typeId, byteOffset.id, m_module.consti32(2)); + return result; + } + + + DxbcRegisterValue DxbcCompiler::emitCalcTexCoord( + DxbcRegisterValue coordVector, + const DxbcImageInfo& imageInfo) { + const uint32_t dim = getTexCoordDim(imageInfo); + + if (dim != coordVector.type.ccount) { + coordVector = emitRegisterExtract( + coordVector, DxbcRegMask::firstN(dim)); + } + + return coordVector; + } + + + DxbcRegisterValue DxbcCompiler::emitLoadTexCoord( + const DxbcRegister& coordReg, + const DxbcImageInfo& imageInfo) { + return emitCalcTexCoord(emitRegisterLoad(coordReg, + DxbcRegMask(true, true, true, true)), imageInfo); + } + + + DxbcRegisterValue DxbcCompiler::emitIndexLoad( + DxbcRegIndex index) { + if (index.relReg != nullptr) { + DxbcRegisterValue result = emitRegisterLoad( + *index.relReg, DxbcRegMask(true, false, false, false)); + + if (index.offset != 0) { + result.id = m_module.opIAdd( + getVectorTypeId(result.type), result.id, + m_module.consti32(index.offset)); + } + + return result; + } else { + DxbcRegisterValue result; + result.type.ctype = DxbcScalarType::Sint32; + result.type.ccount = 1; + result.id = m_module.consti32(index.offset); + return result; + } + } + + + DxbcRegisterValue DxbcCompiler::emitValueLoad( + DxbcRegisterPointer ptr) { + DxbcRegisterValue result; + result.type = ptr.type; + result.id = m_module.opLoad( + getVectorTypeId(result.type), + ptr.id); + return result; + } + + + void DxbcCompiler::emitValueStore( + DxbcRegisterPointer ptr, + DxbcRegisterValue value, + DxbcRegMask writeMask) { + // If the component types are not compatible, + // we need to bit-cast the source variable. + if (value.type.ctype != ptr.type.ctype) + value = emitRegisterBitcast(value, ptr.type.ctype); + + // If the source value consists of only one component, + // it is stored in all components of the destination. + if (value.type.ccount == 1) + value = emitRegisterExtend(value, writeMask.popCount()); + + if (ptr.type.ccount == writeMask.popCount()) { + // Simple case: We write to the entire register + m_module.opStore(ptr.id, value.id); + } else { + // We only write to part of the destination + // register, so we need to load and modify it + DxbcRegisterValue tmp = emitValueLoad(ptr); + tmp = emitRegisterInsert(tmp, value, writeMask); + + m_module.opStore(ptr.id, tmp.id); + } + } + + + DxbcRegisterValue DxbcCompiler::emitRegisterLoadRaw( + const DxbcRegister& reg) { + if (reg.type == DxbcOperandType::IndexableTemp) { + bool doBoundsCheck = reg.idx[1].relReg != nullptr; + DxbcRegisterValue vectorId = emitIndexLoad(reg.idx[1]); + + if (doBoundsCheck) { + uint32_t boundsCheck = m_module.opULessThan( + m_module.defBoolType(), vectorId.id, + m_module.constu32(m_xRegs.at(reg.idx[0].offset).alength)); + + // Kind of ugly to have an empty else block here but there's no + // way for us to know the current block ID for the phi below + DxbcConditional cond; + cond.labelIf = m_module.allocateId(); + cond.labelElse = m_module.allocateId(); + cond.labelEnd = m_module.allocateId(); + + m_module.opSelectionMerge(cond.labelEnd, spv::SelectionControlMaskNone); + m_module.opBranchConditional(boundsCheck, cond.labelIf, cond.labelElse); + + m_module.opLabel(cond.labelIf); + + DxbcRegisterValue returnValue = emitValueLoad(emitGetOperandPtr(reg)); + + m_module.opBranch(cond.labelEnd); + m_module.opLabel (cond.labelElse); + + DxbcRegisterValue zeroValue = emitBuildZeroVector(returnValue.type); + + m_module.opBranch(cond.labelEnd); + m_module.opLabel (cond.labelEnd); + + std::array phiLabels = {{ + { returnValue.id, cond.labelIf }, + { zeroValue.id, cond.labelElse }, + }}; + + returnValue.id = m_module.opPhi( + getVectorTypeId(returnValue.type), + phiLabels.size(), phiLabels.data()); + return returnValue; + } + } + + return emitValueLoad(emitGetOperandPtr(reg)); + } + + + DxbcRegisterValue DxbcCompiler::emitConstantBufferLoad( + const DxbcRegister& reg, + DxbcRegMask writeMask) { + // Constant buffers take a two-dimensional index: + // (0) register index (immediate) + // (1) constant offset (relative) + DxbcRegisterInfo info; + info.type.ctype = DxbcScalarType::Float32; + info.type.ccount = 4; + info.type.alength = 0; + info.sclass = spv::StorageClassUniform; + + uint32_t regId = reg.idx[0].offset; + DxbcRegisterValue constId = emitIndexLoad(reg.idx[1]); + + uint32_t ptrTypeId = getPointerTypeId(info); + + const std::array indices = + {{ m_module.consti32(0), constId.id }}; + + DxbcRegisterPointer ptr; + ptr.type.ctype = info.type.ctype; + ptr.type.ccount = info.type.ccount; + ptr.id = m_module.opAccessChain(ptrTypeId, + m_constantBuffers.at(regId).varId, + indices.size(), indices.data()); + + // Load individual components from buffer + std::array ccomps = { 0, 0, 0, 0 }; + std::array scomps = { 0, 0, 0, 0 }; + uint32_t scount = 0; + + for (uint32_t i = 0; i < 4; i++) { + uint32_t sindex = reg.swizzle[i]; + + if (!writeMask[i] || ccomps[sindex]) + continue; + + uint32_t componentId = m_module.constu32(sindex); + uint32_t componentPtr = m_module.opAccessChain( + m_module.defPointerType( + getScalarTypeId(DxbcScalarType::Float32), + spv::StorageClassUniform), + ptr.id, 1, &componentId); + + ccomps[sindex] = m_module.opLoad( + getScalarTypeId(DxbcScalarType::Float32), + componentPtr); + } + + for (uint32_t i = 0; i < 4; i++) { + uint32_t sindex = reg.swizzle[i]; + + if (writeMask[i]) + scomps[scount++] = ccomps[sindex]; + } + + DxbcRegisterValue result; + result.type.ctype = DxbcScalarType::Float32; + result.type.ccount = scount; + result.id = scomps[0]; + + if (scount > 1) { + result.id = m_module.opCompositeConstruct( + getVectorTypeId(result.type), + scount, scomps.data()); + } + + // Apply any post-processing that might be necessary + result = emitRegisterBitcast(result, reg.dataType); + result = emitSrcOperandModifiers(result, reg.modifiers); + return result; + } + + + DxbcRegisterValue DxbcCompiler::emitRegisterLoad( + const DxbcRegister& reg, + DxbcRegMask writeMask) { + if (reg.type == DxbcOperandType::Imm32 + || reg.type == DxbcOperandType::Imm64) { + DxbcRegisterValue result; + + if (reg.componentCount == DxbcComponentCount::Component1) { + // Create one single u32 constant + result.type.ctype = DxbcScalarType::Uint32; + result.type.ccount = 1; + result.id = m_module.constu32(reg.imm.u32_1); + + result = emitRegisterExtend(result, writeMask.popCount()); + } else if (reg.componentCount == DxbcComponentCount::Component4) { + // Create a u32 vector with as many components as needed + std::array indices = { }; + uint32_t indexId = 0; + + for (uint32_t i = 0; i < indices.size(); i++) { + if (writeMask[i]) { + indices.at(indexId++) = + m_module.constu32(reg.imm.u32_4[i]); + } + } + + result.type.ctype = DxbcScalarType::Uint32; + result.type.ccount = writeMask.popCount(); + result.id = indices.at(0); + + if (indexId > 1) { + result.id = m_module.constComposite( + getVectorTypeId(result.type), + result.type.ccount, indices.data()); + } + + } else { + // Something went horribly wrong in the decoder or the shader is broken + throw DxvkError("DxbcCompiler: Invalid component count for immediate operand"); + } + + // Cast constants to the requested type + return emitRegisterBitcast(result, reg.dataType); + } else if (reg.type == DxbcOperandType::ConstantBuffer) { + return emitConstantBufferLoad(reg, writeMask); + } else { + // Load operand from the operand pointer + DxbcRegisterValue result = emitRegisterLoadRaw(reg); + + // Apply operand swizzle to the operand value + result = emitRegisterSwizzle(result, reg.swizzle, writeMask); + + // Cast it to the requested type. We need to do + // this after the swizzling for 64-bit types. + result = emitRegisterBitcast(result, reg.dataType); + + // Apply operand modifiers + result = emitSrcOperandModifiers(result, reg.modifiers); + return result; + } + } + + + void DxbcCompiler::emitRegisterStore( + const DxbcRegister& reg, + DxbcRegisterValue value) { + if (reg.type == DxbcOperandType::IndexableTemp) { + bool doBoundsCheck = reg.idx[1].relReg != nullptr; + DxbcRegisterValue vectorId = emitIndexLoad(reg.idx[1]); + + if (doBoundsCheck) { + uint32_t boundsCheck = m_module.opULessThan( + m_module.defBoolType(), vectorId.id, + m_module.constu32(m_xRegs.at(reg.idx[0].offset).alength)); + + DxbcConditional cond; + cond.labelIf = m_module.allocateId(); + cond.labelEnd = m_module.allocateId(); + + m_module.opSelectionMerge(cond.labelEnd, spv::SelectionControlMaskNone); + m_module.opBranchConditional(boundsCheck, cond.labelIf, cond.labelEnd); + + m_module.opLabel(cond.labelIf); + + emitValueStore(getIndexableTempPtr(reg, vectorId), value, reg.mask); + + m_module.opBranch(cond.labelEnd); + m_module.opLabel (cond.labelEnd); + } else { + emitValueStore(getIndexableTempPtr(reg, vectorId), value, reg.mask); + } + } else { + emitValueStore(emitGetOperandPtr(reg), value, reg.mask); + } + } + + + uint32_t DxbcCompiler::emitNewSpecConstant( + DxvkSpecConstantId specId, + DxbcScalarType type, + uint32_t value, + const char* name) { + uint32_t id = m_module.specConst32( + getScalarTypeId(type), value); + + m_module.decorateSpecId(id, uint32_t(specId)); + m_module.setDebugName(id, name); + return id; + } + + + void DxbcCompiler::emitInputSetup() { + m_module.setLateConst(m_vArrayLengthId, &m_vArrayLength); + + // Copy all defined v# registers into the input array + const uint32_t vecTypeId = m_module.defVectorType(m_module.defFloatType(32), 4); + const uint32_t ptrTypeId = m_module.defPointerType(vecTypeId, spv::StorageClassPrivate); + + for (uint32_t i = 0; i < m_vRegs.size(); i++) { + if (m_vRegs.at(i).id != 0) { + const uint32_t registerId = m_module.consti32(i); + + DxbcRegisterPointer srcPtr = m_vRegs.at(i); + DxbcRegisterValue srcValue = emitRegisterBitcast( + emitValueLoad(srcPtr), DxbcScalarType::Float32); + + DxbcRegisterPointer dstPtr; + dstPtr.type = { DxbcScalarType::Float32, 4 }; + dstPtr.id = m_module.opAccessChain( + ptrTypeId, m_vArray, 1, ®isterId); + + emitValueStore(dstPtr, srcValue, DxbcRegMask::firstN(srcValue.type.ccount)); + } + } + + // Copy all system value registers into the array, + // preserving any previously written contents. + for (const DxbcSvMapping& map : m_vMappings) { + const uint32_t registerId = m_module.consti32(map.regId); + + const DxbcRegisterValue value = [&] { + switch (m_programInfo.type()) { + case DxbcProgramType::VertexShader: return emitVsSystemValueLoad(map.sv, map.regMask); + case DxbcProgramType::PixelShader: return emitPsSystemValueLoad(map.sv, map.regMask); + default: throw DxvkError(str::format("DxbcCompiler: Unexpected stage: ", m_programInfo.type())); + } + }(); + + DxbcRegisterPointer inputReg; + inputReg.type.ctype = DxbcScalarType::Float32; + inputReg.type.ccount = 4; + inputReg.id = m_module.opAccessChain( + ptrTypeId, m_vArray, 1, ®isterId); + emitValueStore(inputReg, value, map.regMask); + } + } + + + void DxbcCompiler::emitInputSetup(uint32_t vertexCount) { + m_module.setLateConst(m_vArrayLengthId, &m_vArrayLength); + + // Copy all defined v# registers into the input array. Note + // that the outer index of the array is the vertex index. + const uint32_t vecTypeId = m_module.defVectorType(m_module.defFloatType(32), 4); + const uint32_t dstPtrTypeId = m_module.defPointerType(vecTypeId, spv::StorageClassPrivate); + + for (uint32_t i = 0; i < m_vRegs.size(); i++) { + if (m_vRegs.at(i).id != 0) { + const uint32_t registerId = m_module.consti32(i); + + for (uint32_t v = 0; v < vertexCount; v++) { + std::array indices + = {{ m_module.consti32(v), registerId }}; + + DxbcRegisterPointer srcPtr; + srcPtr.type = m_vRegs.at(i).type; + srcPtr.id = m_module.opAccessChain( + m_module.defPointerType(getVectorTypeId(srcPtr.type), spv::StorageClassInput), + m_vRegs.at(i).id, 1, indices.data()); + + DxbcRegisterValue srcValue = emitRegisterBitcast( + emitValueLoad(srcPtr), DxbcScalarType::Float32); + + DxbcRegisterPointer dstPtr; + dstPtr.type = { DxbcScalarType::Float32, 4 }; + dstPtr.id = m_module.opAccessChain( + dstPtrTypeId, m_vArray, 2, indices.data()); + + emitValueStore(dstPtr, srcValue, DxbcRegMask::firstN(srcValue.type.ccount)); + } + } + } + + // Copy all system value registers into the array, + // preserving any previously written contents. + for (const DxbcSvMapping& map : m_vMappings) { + const uint32_t registerId = m_module.consti32(map.regId); + + for (uint32_t v = 0; v < vertexCount; v++) { + const DxbcRegisterValue value = [&] { + switch (m_programInfo.type()) { + case DxbcProgramType::GeometryShader: return emitGsSystemValueLoad(map.sv, map.regMask, v); + default: throw DxvkError(str::format("DxbcCompiler: Unexpected stage: ", m_programInfo.type())); + } + }(); + + std::array indices = { + m_module.consti32(v), registerId, + }; + + DxbcRegisterPointer inputReg; + inputReg.type.ctype = DxbcScalarType::Float32; + inputReg.type.ccount = 4; + inputReg.id = m_module.opAccessChain(dstPtrTypeId, + m_vArray, indices.size(), indices.data()); + emitValueStore(inputReg, value, map.regMask); + } + } + } + + + void DxbcCompiler::emitOutputSetup() { + for (const DxbcSvMapping& svMapping : m_oMappings) { + DxbcRegisterPointer outputReg = m_oRegs.at(svMapping.regId); + + if (m_programInfo.type() == DxbcProgramType::HullShader) { + uint32_t registerIndex = m_module.constu32(svMapping.regId); + + outputReg.type = { DxbcScalarType::Float32, 4 }; + outputReg.id = m_module.opAccessChain( + m_module.defPointerType( + getVectorTypeId(outputReg.type), + spv::StorageClassPrivate), + m_hs.outputPerPatch, + 1, ®isterIndex); + } + + auto sv = svMapping.sv; + auto mask = svMapping.regMask; + auto value = emitValueLoad(outputReg); + + switch (m_programInfo.type()) { + case DxbcProgramType::VertexShader: emitVsSystemValueStore(sv, mask, value); break; + case DxbcProgramType::GeometryShader: emitGsSystemValueStore(sv, mask, value); break; + case DxbcProgramType::HullShader: emitHsSystemValueStore(sv, mask, value); break; + case DxbcProgramType::DomainShader: emitDsSystemValueStore(sv, mask, value); break; + case DxbcProgramType::PixelShader: emitPsSystemValueStore(sv, mask, value); break; + case DxbcProgramType::ComputeShader: break; + } + } + } + + + void DxbcCompiler::emitOutputMapping() { + // For pixel shaders, we need to swizzle the + // output vectors using some spec constants. + for (uint32_t i = 0; i < m_oRegs.size(); i++) { + if (m_oRegs[i].id == 0 || m_oRegs[i].type.ccount < 2) + continue; + + DxbcRegisterValue vector = emitValueLoad(m_oRegs[i]); + + uint32_t specTypeId = getScalarTypeId(DxbcScalarType::Uint32); + uint32_t compTypeId = getScalarTypeId(vector.type.ctype); + + uint32_t specId = m_module.specConst32(specTypeId, 0x3210); + m_module.decorateSpecId(specId, uint32_t(DxvkSpecConstantId::ColorComponentMappings) + i); + m_module.setDebugName(specId, str::format("omap", i).c_str()); + + std::array scalars; + for (uint32_t c = 0; c < vector.type.ccount; c++) { + scalars[c] = m_module.opVectorExtractDynamic(compTypeId, vector.id, + m_module.opBitFieldUExtract(specTypeId, specId, + m_module.constu32(4 * c), m_module.constu32(4))); + } + + uint32_t typeId = getVectorTypeId(vector.type); + vector.id = m_module.opCompositeConstruct(typeId, vector.type.ccount, scalars.data()); + + // Replace NaN by zero if requested + if (m_moduleInfo.options.enableRtOutputNanFixup && vector.type.ctype == DxbcScalarType::Float32) { + uint32_t boolType = m_module.defBoolType(); + + if (vector.type.ccount > 1) + boolType = m_module.defVectorType(boolType, vector.type.ccount); + + uint32_t zero = emitBuildConstVecf32(0.0f, 0.0f, 0.0f, 0.0f, + DxbcRegMask((1u << vector.type.ccount) - 1)).id; + uint32_t isNan = m_module.opIsNan(boolType, vector.id); + vector.id = m_module.opSelect(typeId, isNan, zero, vector.id); + } + + emitValueStore(m_oRegs[i], vector, + DxbcRegMask::firstN(vector.type.ccount)); + } + } + + + void DxbcCompiler::emitOutputDepthClamp() { + // HACK: Some drivers do not clamp FragDepth to [minDepth..maxDepth] + // before writing to the depth attachment, but we do not have acccess + // to those. Clamp to [0..1] instead. + if (m_ps.builtinDepth) { + DxbcRegisterPointer ptr; + ptr.type = { DxbcScalarType::Float32, 1 }; + ptr.id = m_ps.builtinDepth; + + DxbcRegisterValue value = emitValueLoad(ptr); + + value.id = m_module.opFClamp( + getVectorTypeId(ptr.type), + value.id, + m_module.constf32(0.0f), + m_module.constf32(1.0f)); + + emitValueStore(ptr, value, + DxbcRegMask::firstN(1)); + } + } + + + void DxbcCompiler::emitInitWorkgroupMemory() { + bool hasTgsm = false; + + for (uint32_t i = 0; i < m_gRegs.size(); i++) { + if (!m_gRegs[i].varId) + continue; + + if (!m_cs.builtinLocalInvocationIndex) { + m_cs.builtinLocalInvocationIndex = emitNewBuiltinVariable({ + { DxbcScalarType::Uint32, 1, 0 }, + spv::StorageClassInput }, + spv::BuiltInLocalInvocationIndex, + "vThreadIndexInGroup"); + } + + uint32_t intTypeId = getScalarTypeId(DxbcScalarType::Uint32); + uint32_t ptrTypeId = m_module.defPointerType( + intTypeId, spv::StorageClassWorkgroup); + + uint32_t numElements = m_gRegs[i].type == DxbcResourceType::Structured + ? m_gRegs[i].elementCount * m_gRegs[i].elementStride / 4 + : m_gRegs[i].elementCount / 4; + + uint32_t numThreads = m_cs.workgroupSizeX * + m_cs.workgroupSizeY * m_cs.workgroupSizeZ; + + uint32_t numElementsPerThread = numElements / numThreads; + uint32_t numElementsRemaining = numElements % numThreads; + + uint32_t threadId = m_module.opLoad( + intTypeId, m_cs.builtinLocalInvocationIndex); + + uint32_t strideId = m_module.constu32(numElementsPerThread); + uint32_t zeroId = m_module.constu32(0); + + for (uint32_t e = 0; e < numElementsPerThread; e++) { + uint32_t ofsId = m_module.opIAdd(intTypeId, + m_module.opIMul(intTypeId, strideId, threadId), + m_module.constu32(e)); + + uint32_t ptrId = m_module.opAccessChain( + ptrTypeId, m_gRegs[i].varId, 1, &ofsId); + + m_module.opStore(ptrId, zeroId); + } + + if (numElementsRemaining) { + uint32_t condition = m_module.opULessThan( + m_module.defBoolType(), threadId, + m_module.constu32(numElementsRemaining)); + + DxbcConditional cond; + cond.labelIf = m_module.allocateId(); + cond.labelEnd = m_module.allocateId(); + + m_module.opSelectionMerge(cond.labelEnd, spv::SelectionControlMaskNone); + m_module.opBranchConditional(condition, cond.labelIf, cond.labelEnd); + + m_module.opLabel(cond.labelIf); + + uint32_t ofsId = m_module.opIAdd(intTypeId, + m_module.constu32(numThreads * numElementsPerThread), + threadId); + + uint32_t ptrId = m_module.opAccessChain( + ptrTypeId, m_gRegs[i].varId, 1, &ofsId); + + m_module.opStore(ptrId, zeroId); + + m_module.opBranch(cond.labelEnd); + m_module.opLabel (cond.labelEnd); + } + + hasTgsm = true; + } + + if (hasTgsm) { + m_module.opControlBarrier( + m_module.constu32(spv::ScopeInvocation), + m_module.constu32(spv::ScopeWorkgroup), + m_module.constu32(spv::MemorySemanticsWorkgroupMemoryMask + | spv::MemorySemanticsAcquireReleaseMask)); + } + } + + + DxbcRegisterValue DxbcCompiler::emitVsSystemValueLoad( + DxbcSystemValue sv, + DxbcRegMask mask) { + switch (sv) { + case DxbcSystemValue::VertexId: { + const uint32_t typeId = getScalarTypeId(DxbcScalarType::Uint32); + + if (m_vs.builtinVertexId == 0) { + m_vs.builtinVertexId = emitNewBuiltinVariable({ + { DxbcScalarType::Uint32, 1, 0 }, + spv::StorageClassInput }, + spv::BuiltInVertexIndex, + "vs_vertex_index"); + } + + if (m_vs.builtinBaseVertex == 0) { + m_vs.builtinBaseVertex = emitNewBuiltinVariable({ + { DxbcScalarType::Uint32, 1, 0 }, + spv::StorageClassInput }, + spv::BuiltInBaseVertex, + "vs_base_vertex"); + } + + DxbcRegisterValue result; + result.type.ctype = DxbcScalarType::Uint32; + result.type.ccount = 1; + result.id = m_module.opISub(typeId, + m_module.opLoad(typeId, m_vs.builtinVertexId), + m_module.opLoad(typeId, m_vs.builtinBaseVertex)); + return result; + } break; + + case DxbcSystemValue::InstanceId: { + const uint32_t typeId = getScalarTypeId(DxbcScalarType::Uint32); + + if (m_vs.builtinInstanceId == 0) { + m_vs.builtinInstanceId = emitNewBuiltinVariable({ + { DxbcScalarType::Uint32, 1, 0 }, + spv::StorageClassInput }, + spv::BuiltInInstanceIndex, + "vs_instance_index"); + } + + if (m_vs.builtinBaseInstance == 0) { + m_vs.builtinBaseInstance = emitNewBuiltinVariable({ + { DxbcScalarType::Uint32, 1, 0 }, + spv::StorageClassInput }, + spv::BuiltInBaseInstance, + "vs_base_instance"); + } + + DxbcRegisterValue result; + result.type.ctype = DxbcScalarType::Uint32; + result.type.ccount = 1; + result.id = m_module.opISub(typeId, + m_module.opLoad(typeId, m_vs.builtinInstanceId), + m_module.opLoad(typeId, m_vs.builtinBaseInstance)); + return result; + } break; + + default: + throw DxvkError(str::format( + "DxbcCompiler: Unhandled VS SV input: ", sv)); + } + } + + + DxbcRegisterValue DxbcCompiler::emitGsSystemValueLoad( + DxbcSystemValue sv, + DxbcRegMask mask, + uint32_t vertexId) { + switch (sv) { + case DxbcSystemValue::Position: { + const std::array indices = { + m_module.consti32(vertexId), + m_module.consti32(PerVertex_Position), + }; + + DxbcRegisterPointer ptrIn; + ptrIn.type.ctype = DxbcScalarType::Float32; + ptrIn.type.ccount = 4; + + ptrIn.id = m_module.opAccessChain( + m_module.defPointerType( + getVectorTypeId(ptrIn.type), + spv::StorageClassInput), + m_perVertexIn, + indices.size(), + indices.data()); + + return emitRegisterExtract( + emitValueLoad(ptrIn), mask); + } break; + + default: + throw DxvkError(str::format( + "DxbcCompiler: Unhandled GS SV input: ", sv)); + } + } + + + DxbcRegisterValue DxbcCompiler::emitPsSystemValueLoad( + DxbcSystemValue sv, + DxbcRegMask mask) { + switch (sv) { + case DxbcSystemValue::Position: { + if (m_ps.builtinFragCoord == 0) { + m_ps.builtinFragCoord = emitNewBuiltinVariable({ + { DxbcScalarType::Float32, 4, 0 }, + spv::StorageClassInput }, + spv::BuiltInFragCoord, + "ps_frag_coord"); + } + + DxbcRegisterPointer ptrIn; + ptrIn.type = { DxbcScalarType::Float32, 4 }; + ptrIn.id = m_ps.builtinFragCoord; + + // The X, Y and Z components of the SV_POSITION semantic + // are identical to Vulkan's FragCoord builtin, but we + // need to compute the reciprocal of the W component. + DxbcRegisterValue fragCoord = emitValueLoad(ptrIn); + + uint32_t componentIndex = 3; + uint32_t t_f32 = m_module.defFloatType(32); + uint32_t v_wComp = m_module.opCompositeExtract(t_f32, fragCoord.id, 1, &componentIndex); + v_wComp = m_module.opFDiv(t_f32, m_module.constf32(1.0f), v_wComp); + + fragCoord.id = m_module.opCompositeInsert( + getVectorTypeId(fragCoord.type), + v_wComp, fragCoord.id, + 1, &componentIndex); + + return emitRegisterExtract(fragCoord, mask); + } break; + + case DxbcSystemValue::IsFrontFace: { + if (m_ps.builtinIsFrontFace == 0) { + m_ps.builtinIsFrontFace = emitNewBuiltinVariable({ + { DxbcScalarType::Bool, 1, 0 }, + spv::StorageClassInput }, + spv::BuiltInFrontFacing, + "ps_is_front_face"); + } + + DxbcRegisterValue result; + result.type.ctype = DxbcScalarType::Uint32; + result.type.ccount = 1; + result.id = m_module.opSelect( + getVectorTypeId(result.type), + m_module.opLoad( + m_module.defBoolType(), + m_ps.builtinIsFrontFace), + m_module.constu32(0xFFFFFFFF), + m_module.constu32(0x00000000)); + return result; + } break; + + case DxbcSystemValue::PrimitiveId: { + if (m_primitiveIdIn == 0) { + m_module.enableCapability(spv::CapabilityGeometry); + + m_primitiveIdIn = emitNewBuiltinVariable({ + { DxbcScalarType::Uint32, 1, 0 }, + spv::StorageClassInput }, + spv::BuiltInPrimitiveId, + "ps_primitive_id"); + } + + DxbcRegisterPointer ptrIn; + ptrIn.type = { DxbcScalarType::Uint32, 1 }; + ptrIn.id = m_primitiveIdIn; + + return emitValueLoad(ptrIn); + } break; + + case DxbcSystemValue::SampleIndex: { + if (m_ps.builtinSampleId == 0) { + m_module.enableCapability(spv::CapabilitySampleRateShading); + + m_ps.builtinSampleId = emitNewBuiltinVariable({ + { DxbcScalarType::Uint32, 1, 0 }, + spv::StorageClassInput }, + spv::BuiltInSampleId, + "ps_sample_id"); + } + + DxbcRegisterPointer ptrIn; + ptrIn.type.ctype = DxbcScalarType::Uint32; + ptrIn.type.ccount = 1; + ptrIn.id = m_ps.builtinSampleId; + + return emitValueLoad(ptrIn); + } break; + + case DxbcSystemValue::RenderTargetId: { + if (m_ps.builtinLayer == 0) { + m_module.enableCapability(spv::CapabilityGeometry); + + m_ps.builtinLayer = emitNewBuiltinVariable({ + { DxbcScalarType::Uint32, 1, 0 }, + spv::StorageClassInput }, + spv::BuiltInLayer, + "v_layer"); + } + + DxbcRegisterPointer ptr; + ptr.type.ctype = DxbcScalarType::Uint32; + ptr.type.ccount = 1; + ptr.id = m_ps.builtinLayer; + + return emitValueLoad(ptr); + } break; + + case DxbcSystemValue::ViewportId: { + if (m_ps.builtinViewportId == 0) { + m_module.enableCapability(spv::CapabilityMultiViewport); + + m_ps.builtinViewportId = emitNewBuiltinVariable({ + { DxbcScalarType::Uint32, 1, 0 }, + spv::StorageClassInput }, + spv::BuiltInViewportIndex, + "v_viewport"); + } + + DxbcRegisterPointer ptr; + ptr.type.ctype = DxbcScalarType::Uint32; + ptr.type.ccount = 1; + ptr.id = m_ps.builtinViewportId; + + return emitValueLoad(ptr); + } break; + + default: + throw DxvkError(str::format( + "DxbcCompiler: Unhandled PS SV input: ", sv)); + } + } + + + void DxbcCompiler::emitVsSystemValueStore( + DxbcSystemValue sv, + DxbcRegMask mask, + const DxbcRegisterValue& value) { + switch (sv) { + case DxbcSystemValue::Position: { + const uint32_t memberId = m_module.consti32(PerVertex_Position); + + DxbcRegisterPointer ptr; + ptr.type.ctype = DxbcScalarType::Float32; + ptr.type.ccount = 4; + + ptr.id = m_module.opAccessChain( + m_module.defPointerType( + getVectorTypeId(ptr.type), + spv::StorageClassOutput), + m_perVertexOut, 1, &memberId); + + emitValueStore(ptr, value, mask); + } break; + + case DxbcSystemValue::RenderTargetId: { + if (m_programInfo.type() != DxbcProgramType::GeometryShader) + enableShaderViewportIndexLayer(); + + if (m_gs.builtinLayer == 0) { + m_module.enableCapability(spv::CapabilityGeometry); + + m_gs.builtinLayer = emitNewBuiltinVariable({ + { DxbcScalarType::Uint32, 1, 0 }, + spv::StorageClassOutput }, + spv::BuiltInLayer, + "o_layer"); + } + + DxbcRegisterPointer ptr; + ptr.type = { DxbcScalarType::Uint32, 1 }; + ptr.id = m_gs.builtinLayer; + + emitValueStore( + ptr, emitRegisterExtract(value, mask), + DxbcRegMask(true, false, false, false)); + } break; + + case DxbcSystemValue::ViewportId: { + if (m_programInfo.type() != DxbcProgramType::GeometryShader) + enableShaderViewportIndexLayer(); + + if (m_gs.builtinViewportId == 0) { + m_module.enableCapability(spv::CapabilityMultiViewport); + + m_gs.builtinViewportId = emitNewBuiltinVariable({ + { DxbcScalarType::Uint32, 1, 0 }, + spv::StorageClassOutput }, + spv::BuiltInViewportIndex, + "o_viewport"); + } + + DxbcRegisterPointer ptr; + ptr.type = { DxbcScalarType::Uint32, 1}; + ptr.id = m_gs.builtinViewportId; + + emitValueStore( + ptr, emitRegisterExtract(value, mask), + DxbcRegMask(true, false, false, false)); + } break; + + default: + Logger::warn(str::format( + "DxbcCompiler: Unhandled VS SV output: ", sv)); + } + } + + + void DxbcCompiler::emitHsSystemValueStore( + DxbcSystemValue sv, + DxbcRegMask mask, + const DxbcRegisterValue& value) { + if (sv >= DxbcSystemValue::FinalQuadUeq0EdgeTessFactor + && sv <= DxbcSystemValue::FinalLineDensityTessFactor) { + struct TessFactor { + uint32_t array = 0; + uint32_t index = 0; + }; + + static const std::array s_tessFactors = {{ + { m_hs.builtinTessLevelOuter, 0 }, // FinalQuadUeq0EdgeTessFactor + { m_hs.builtinTessLevelOuter, 1 }, // FinalQuadVeq0EdgeTessFactor + { m_hs.builtinTessLevelOuter, 2 }, // FinalQuadUeq1EdgeTessFactor + { m_hs.builtinTessLevelOuter, 3 }, // FinalQuadVeq1EdgeTessFactor + { m_hs.builtinTessLevelInner, 0 }, // FinalQuadUInsideTessFactor + { m_hs.builtinTessLevelInner, 1 }, // FinalQuadVInsideTessFactor + { m_hs.builtinTessLevelOuter, 0 }, // FinalTriUeq0EdgeTessFactor + { m_hs.builtinTessLevelOuter, 1 }, // FinalTriVeq0EdgeTessFactor + { m_hs.builtinTessLevelOuter, 2 }, // FinalTriWeq0EdgeTessFactor + { m_hs.builtinTessLevelInner, 0 }, // FinalTriInsideTessFactor + { m_hs.builtinTessLevelOuter, 0 }, // FinalLineDensityTessFactor + { m_hs.builtinTessLevelOuter, 1 }, // FinalLineDetailTessFactor + }}; + + const TessFactor tessFactor = s_tessFactors.at(uint32_t(sv) + - uint32_t(DxbcSystemValue::FinalQuadUeq0EdgeTessFactor)); + + const uint32_t tessFactorArrayIndex + = m_module.constu32(tessFactor.index); + + // Apply global tess factor limit + float maxTessFactor = m_hs.maxTessFactor; + + if (m_moduleInfo.tess != nullptr) { + if (m_moduleInfo.tess->maxTessFactor < maxTessFactor) + maxTessFactor = m_moduleInfo.tess->maxTessFactor; + } + + DxbcRegisterValue tessValue = emitRegisterExtract(value, mask); + tessValue.id = m_module.opFClamp(getVectorTypeId(tessValue.type), + tessValue.id, m_module.constf32(0.0f), + m_module.constf32(maxTessFactor)); + + DxbcRegisterPointer ptr; + ptr.type.ctype = DxbcScalarType::Float32; + ptr.type.ccount = 1; + ptr.id = m_module.opAccessChain( + m_module.defPointerType( + getVectorTypeId(ptr.type), + spv::StorageClassOutput), + tessFactor.array, 1, + &tessFactorArrayIndex); + + emitValueStore(ptr, tessValue, + DxbcRegMask(true, false, false, false)); + } else { + Logger::warn(str::format( + "DxbcCompiler: Unhandled HS SV output: ", sv)); + } + } + + + void DxbcCompiler::emitGsSystemValueStore( + DxbcSystemValue sv, + DxbcRegMask mask, + const DxbcRegisterValue& value) { + switch (sv) { + case DxbcSystemValue::Position: + case DxbcSystemValue::CullDistance: + case DxbcSystemValue::ClipDistance: + case DxbcSystemValue::RenderTargetId: + case DxbcSystemValue::ViewportId: + emitVsSystemValueStore(sv, mask, value); + break; + + case DxbcSystemValue::PrimitiveId: { + if (m_primitiveIdOut == 0) { + m_primitiveIdOut = emitNewBuiltinVariable({ + { DxbcScalarType::Uint32, 1, 0 }, + spv::StorageClassOutput }, + spv::BuiltInPrimitiveId, + "gs_primitive_id"); + } + + DxbcRegisterPointer ptr; + ptr.type = { DxbcScalarType::Uint32, 1}; + ptr.id = m_primitiveIdOut; + + emitValueStore( + ptr, emitRegisterExtract(value, mask), + DxbcRegMask(true, false, false, false)); + } break; + + default: + Logger::warn(str::format( + "DxbcCompiler: Unhandled GS SV output: ", sv)); + } + } + + + void DxbcCompiler::emitPsSystemValueStore( + DxbcSystemValue sv, + DxbcRegMask mask, + const DxbcRegisterValue& value) { + Logger::warn(str::format( + "DxbcCompiler: Unhandled PS SV output: ", sv)); + } + + + void DxbcCompiler::emitDsSystemValueStore( + DxbcSystemValue sv, + DxbcRegMask mask, + const DxbcRegisterValue& value) { + switch (sv) { + case DxbcSystemValue::Position: + case DxbcSystemValue::CullDistance: + case DxbcSystemValue::ClipDistance: + case DxbcSystemValue::RenderTargetId: + case DxbcSystemValue::ViewportId: + emitVsSystemValueStore(sv, mask, value); + break; + + default: + Logger::warn(str::format( + "DxbcCompiler: Unhandled DS SV output: ", sv)); + } + } + + + void DxbcCompiler::emitClipCullStore( + DxbcSystemValue sv, + uint32_t dstArray) { + uint32_t offset = 0; + + if (dstArray == 0) + return; + + for (auto e = m_osgn->begin(); e != m_osgn->end(); e++) { + if (e->systemValue == sv) { + DxbcRegisterPointer srcPtr = m_oRegs.at(e->registerId); + DxbcRegisterValue srcValue = emitValueLoad(srcPtr); + + for (uint32_t i = 0; i < 4; i++) { + if (e->componentMask[i]) { + uint32_t offsetId = m_module.consti32(offset++); + + DxbcRegisterValue component = emitRegisterExtract( + srcValue, DxbcRegMask::select(i)); + + DxbcRegisterPointer dstPtr; + dstPtr.type = { DxbcScalarType::Float32, 1 }; + dstPtr.id = m_module.opAccessChain( + m_module.defPointerType( + getVectorTypeId(dstPtr.type), + spv::StorageClassOutput), + dstArray, 1, &offsetId); + + emitValueStore(dstPtr, component, + DxbcRegMask(true, false, false, false)); + } + } + } + } + } + + + void DxbcCompiler::emitClipCullLoad( + DxbcSystemValue sv, + uint32_t srcArray) { + uint32_t offset = 0; + + if (srcArray == 0) + return; + + for (auto e = m_isgn->begin(); e != m_isgn->end(); e++) { + if (e->systemValue == sv) { + // Load individual components from the source array + uint32_t componentIndex = 0; + std::array componentIds = {{ 0, 0, 0, 0 }}; + + for (uint32_t i = 0; i < 4; i++) { + if (e->componentMask[i]) { + uint32_t offsetId = m_module.consti32(offset++); + + DxbcRegisterPointer srcPtr; + srcPtr.type = { DxbcScalarType::Float32, 1 }; + srcPtr.id = m_module.opAccessChain( + m_module.defPointerType( + getVectorTypeId(srcPtr.type), + spv::StorageClassInput), + srcArray, 1, &offsetId); + + componentIds[componentIndex++] + = emitValueLoad(srcPtr).id; + } + } + + // Put everything into one vector + DxbcRegisterValue dstValue; + dstValue.type = { DxbcScalarType::Float32, componentIndex }; + dstValue.id = componentIds[0]; + + if (componentIndex > 1) { + dstValue.id = m_module.opCompositeConstruct( + getVectorTypeId(dstValue.type), + componentIndex, componentIds.data()); + } + + // Store vector to the input array + uint32_t registerId = m_module.consti32(e->registerId); + + DxbcRegisterPointer dstInput; + dstInput.type = { DxbcScalarType::Float32, 4 }; + dstInput.id = m_module.opAccessChain( + m_module.defPointerType( + getVectorTypeId(dstInput.type), + spv::StorageClassPrivate), + m_vArray, 1, ®isterId); + + emitValueStore(dstInput, dstValue, e->componentMask); + } + } + } + + + uint32_t DxbcCompiler::emitUavWriteTest(const DxbcBufferInfo& uav) { + uint32_t typeId = m_module.defBoolType(); + uint32_t testId = uav.specId; + + if (m_ps.killState != 0) { + uint32_t killState = m_module.opLoad(typeId, m_ps.killState); + + testId = m_module.opLogicalAnd(typeId, testId, + m_module.opLogicalNot(typeId, killState)); + } + + return testId; + } + + + void DxbcCompiler::emitInit() { + // Set up common capabilities for all shaders + m_module.enableCapability(spv::CapabilityShader); + m_module.enableCapability(spv::CapabilityImageQuery); + + // Initialize the shader module with capabilities + // etc. Each shader type has its own peculiarities. + switch (m_programInfo.type()) { + case DxbcProgramType::VertexShader: emitVsInit(); break; + case DxbcProgramType::HullShader: emitHsInit(); break; + case DxbcProgramType::DomainShader: emitDsInit(); break; + case DxbcProgramType::GeometryShader: emitGsInit(); break; + case DxbcProgramType::PixelShader: emitPsInit(); break; + case DxbcProgramType::ComputeShader: emitCsInit(); break; + } + } + + + void DxbcCompiler::emitFunctionBegin( + uint32_t entryPoint, + uint32_t returnType, + uint32_t funcType) { + this->emitFunctionEnd(); + + m_module.functionBegin( + returnType, entryPoint, funcType, + spv::FunctionControlMaskNone); + + m_insideFunction = true; + } + + + void DxbcCompiler::emitFunctionEnd() { + if (m_insideFunction) { + m_module.opReturn(); + m_module.functionEnd(); + } + + m_insideFunction = false; + } + + + void DxbcCompiler::emitFunctionLabel() { + m_module.opLabel(m_module.allocateId()); + } + + + void DxbcCompiler::emitMainFunctionBegin() { + this->emitFunctionBegin( + m_entryPointId, + m_module.defVoidType(), + m_module.defFunctionType( + m_module.defVoidType(), 0, nullptr)); + this->emitFunctionLabel(); + } + + + void DxbcCompiler::emitVsInit() { + m_module.enableCapability(spv::CapabilityClipDistance); + m_module.enableCapability(spv::CapabilityCullDistance); + m_module.enableCapability(spv::CapabilityDrawParameters); + + // Declare the per-vertex output block. This is where + // the vertex shader will write the vertex position. + const uint32_t perVertexStruct = this->getPerVertexBlockId(); + const uint32_t perVertexPointer = m_module.defPointerType( + perVertexStruct, spv::StorageClassOutput); + + m_perVertexOut = m_module.newVar( + perVertexPointer, spv::StorageClassOutput); + m_entryPointInterfaces.push_back(m_perVertexOut); + m_module.setDebugName(m_perVertexOut, "vs_vertex_out"); + + // Standard input array + emitDclInputArray(0); + + // Cull/clip distances as outputs + m_clipDistances = emitDclClipCullDistanceArray( + m_analysis->clipCullOut.numClipPlanes, + spv::BuiltInClipDistance, + spv::StorageClassOutput); + + m_cullDistances = emitDclClipCullDistanceArray( + m_analysis->clipCullOut.numCullPlanes, + spv::BuiltInCullDistance, + spv::StorageClassOutput); + + // Main function of the vertex shader + m_vs.functionId = m_module.allocateId(); + m_module.setDebugName(m_vs.functionId, "vs_main"); + + this->emitFunctionBegin( + m_vs.functionId, + m_module.defVoidType(), + m_module.defFunctionType( + m_module.defVoidType(), 0, nullptr)); + this->emitFunctionLabel(); + } + + + void DxbcCompiler::emitHsInit() { + m_module.enableCapability(spv::CapabilityTessellation); + m_module.enableCapability(spv::CapabilityClipDistance); + m_module.enableCapability(spv::CapabilityCullDistance); + + m_hs.builtinInvocationId = emitNewBuiltinVariable( + DxbcRegisterInfo { + { DxbcScalarType::Uint32, 1, 0 }, + spv::StorageClassInput }, + spv::BuiltInInvocationId, + "vOutputControlPointId"); + + m_hs.builtinTessLevelOuter = emitBuiltinTessLevelOuter(spv::StorageClassOutput); + m_hs.builtinTessLevelInner = emitBuiltinTessLevelInner(spv::StorageClassOutput); + } + + + void DxbcCompiler::emitDsInit() { + m_module.enableCapability(spv::CapabilityTessellation); + m_module.enableCapability(spv::CapabilityClipDistance); + m_module.enableCapability(spv::CapabilityCullDistance); + + m_ds.builtinTessLevelOuter = emitBuiltinTessLevelOuter(spv::StorageClassInput); + m_ds.builtinTessLevelInner = emitBuiltinTessLevelInner(spv::StorageClassInput); + + // Declare the per-vertex output block + const uint32_t perVertexStruct = this->getPerVertexBlockId(); + const uint32_t perVertexPointer = m_module.defPointerType( + perVertexStruct, spv::StorageClassOutput); + + // Cull/clip distances as outputs + m_clipDistances = emitDclClipCullDistanceArray( + m_analysis->clipCullOut.numClipPlanes, + spv::BuiltInClipDistance, + spv::StorageClassOutput); + + m_cullDistances = emitDclClipCullDistanceArray( + m_analysis->clipCullOut.numCullPlanes, + spv::BuiltInCullDistance, + spv::StorageClassOutput); + + m_perVertexOut = m_module.newVar( + perVertexPointer, spv::StorageClassOutput); + m_entryPointInterfaces.push_back(m_perVertexOut); + m_module.setDebugName(m_perVertexOut, "ds_vertex_out"); + + // Main function of the domain shader + m_ds.functionId = m_module.allocateId(); + m_module.setDebugName(m_ds.functionId, "ds_main"); + + this->emitFunctionBegin( + m_ds.functionId, + m_module.defVoidType(), + m_module.defFunctionType( + m_module.defVoidType(), 0, nullptr)); + this->emitFunctionLabel(); + } + + + void DxbcCompiler::emitGsInit() { + m_module.enableCapability(spv::CapabilityGeometry); + m_module.enableCapability(spv::CapabilityClipDistance); + m_module.enableCapability(spv::CapabilityCullDistance); + + // Enable capabilities for xfb mode if necessary + if (m_moduleInfo.xfb != nullptr) { + m_module.enableCapability(spv::CapabilityGeometryStreams); + m_module.enableCapability(spv::CapabilityTransformFeedback); + + m_module.setExecutionMode(m_entryPointId, spv::ExecutionModeXfb); + } + + // Declare the per-vertex output block. Outputs are not + // declared as arrays, instead they will be flushed when + // calling EmitVertex. + if (!m_moduleInfo.xfb || m_moduleInfo.xfb->rasterizedStream >= 0) { + const uint32_t perVertexStruct = this->getPerVertexBlockId(); + const uint32_t perVertexPointer = m_module.defPointerType( + perVertexStruct, spv::StorageClassOutput); + + m_perVertexOut = m_module.newVar( + perVertexPointer, spv::StorageClassOutput); + m_entryPointInterfaces.push_back(m_perVertexOut); + m_module.setDebugName(m_perVertexOut, "gs_vertex_out"); + } + + // Cull/clip distances as outputs + m_clipDistances = emitDclClipCullDistanceArray( + m_analysis->clipCullOut.numClipPlanes, + spv::BuiltInClipDistance, + spv::StorageClassOutput); + + m_cullDistances = emitDclClipCullDistanceArray( + m_analysis->clipCullOut.numCullPlanes, + spv::BuiltInCullDistance, + spv::StorageClassOutput); + + // Emit Xfb variables if necessary + if (m_moduleInfo.xfb != nullptr) + emitXfbOutputDeclarations(); + + // Main function of the vertex shader + m_gs.functionId = m_module.allocateId(); + m_module.setDebugName(m_gs.functionId, "gs_main"); + + this->emitFunctionBegin( + m_gs.functionId, + m_module.defVoidType(), + m_module.defFunctionType( + m_module.defVoidType(), 0, nullptr)); + this->emitFunctionLabel(); + } + + + void DxbcCompiler::emitPsInit() { + m_module.enableCapability(spv::CapabilityDerivativeControl); + + m_module.setExecutionMode(m_entryPointId, + spv::ExecutionModeOriginUpperLeft); + + // Standard input array + emitDclInputArray(0); + + // Cull/clip distances as inputs + m_clipDistances = emitDclClipCullDistanceArray( + m_analysis->clipCullIn.numClipPlanes, + spv::BuiltInClipDistance, + spv::StorageClassInput); + + m_cullDistances = emitDclClipCullDistanceArray( + m_analysis->clipCullIn.numCullPlanes, + spv::BuiltInCullDistance, + spv::StorageClassInput); + + // Main function of the pixel shader + m_ps.functionId = m_module.allocateId(); + m_module.setDebugName(m_ps.functionId, "ps_main"); + + this->emitFunctionBegin( + m_ps.functionId, + m_module.defVoidType(), + m_module.defFunctionType( + m_module.defVoidType(), 0, nullptr)); + this->emitFunctionLabel(); + + if (m_analysis->usesKill && m_moduleInfo.options.useDemoteToHelperInvocation) { + // This extension basically implements D3D-style discard + m_module.enableExtension("SPV_EXT_demote_to_helper_invocation"); + m_module.enableCapability(spv::CapabilityDemoteToHelperInvocationEXT); + } else if (m_analysis->usesKill && m_analysis->usesDerivatives) { + // We may have to defer kill operations to the end of + // the shader in order to keep derivatives correct. + m_ps.killState = m_module.newVarInit( + m_module.defPointerType(m_module.defBoolType(), spv::StorageClassPrivate), + spv::StorageClassPrivate, m_module.constBool(false)); + + m_module.setDebugName(m_ps.killState, "ps_kill"); + + if (m_moduleInfo.options.useSubgroupOpsForEarlyDiscard) { + m_module.enableCapability(spv::CapabilityGroupNonUniform); + m_module.enableCapability(spv::CapabilityGroupNonUniformBallot); + + DxbcRegisterInfo laneId; + laneId.type = { DxbcScalarType::Uint32, 1, 0 }; + laneId.sclass = spv::StorageClassInput; + + m_ps.builtinLaneId = emitNewBuiltinVariable( + laneId, spv::BuiltInSubgroupLocalInvocationId, + "fLaneId"); + } + } + } + + + void DxbcCompiler::emitCsInit() { + // Main function of the compute shader + m_cs.functionId = m_module.allocateId(); + m_module.setDebugName(m_cs.functionId, "cs_main"); + + this->emitFunctionBegin( + m_cs.functionId, + m_module.defVoidType(), + m_module.defFunctionType( + m_module.defVoidType(), 0, nullptr)); + this->emitFunctionLabel(); + } + + + void DxbcCompiler::emitVsFinalize() { + this->emitMainFunctionBegin(); + this->emitInputSetup(); + m_module.opFunctionCall( + m_module.defVoidType(), + m_vs.functionId, 0, nullptr); + this->emitOutputSetup(); + this->emitClipCullStore(DxbcSystemValue::ClipDistance, m_clipDistances); + this->emitClipCullStore(DxbcSystemValue::CullDistance, m_cullDistances); + this->emitFunctionEnd(); + } + + + void DxbcCompiler::emitHsFinalize() { + if (m_hs.cpPhase.functionId == 0) + m_hs.cpPhase = this->emitNewHullShaderPassthroughPhase(); + + // Control point phase + this->emitMainFunctionBegin(); + this->emitInputSetup(m_hs.vertexCountIn); + this->emitHsControlPointPhase(m_hs.cpPhase); + this->emitHsPhaseBarrier(); + + // Fork-join phases and output setup + this->emitHsInvocationBlockBegin(1); + + for (const auto& phase : m_hs.forkPhases) + this->emitHsForkJoinPhase(phase); + + for (const auto& phase : m_hs.joinPhases) + this->emitHsForkJoinPhase(phase); + + this->emitOutputSetup(); + this->emitHsOutputSetup(); + this->emitHsInvocationBlockEnd(); + this->emitFunctionEnd(); + } + + + void DxbcCompiler::emitDsFinalize() { + this->emitMainFunctionBegin(); + m_module.opFunctionCall( + m_module.defVoidType(), + m_ds.functionId, 0, nullptr); + this->emitOutputSetup(); + this->emitClipCullStore(DxbcSystemValue::ClipDistance, m_clipDistances); + this->emitClipCullStore(DxbcSystemValue::CullDistance, m_cullDistances); + this->emitFunctionEnd(); + } + + + void DxbcCompiler::emitGsFinalize() { + if (!m_gs.invocationCount) + m_module.setInvocations(m_entryPointId, 1); + + this->emitMainFunctionBegin(); + this->emitInputSetup( + primitiveVertexCount(m_gs.inputPrimitive)); + m_module.opFunctionCall( + m_module.defVoidType(), + m_gs.functionId, 0, nullptr); + // No output setup at this point as that was + // already done during the EmitVertex step + this->emitFunctionEnd(); + } + + + void DxbcCompiler::emitPsFinalize() { + this->emitMainFunctionBegin(); + this->emitInputSetup(); + this->emitClipCullLoad(DxbcSystemValue::ClipDistance, m_clipDistances); + this->emitClipCullLoad(DxbcSystemValue::CullDistance, m_cullDistances); + + m_module.opFunctionCall( + m_module.defVoidType(), + m_ps.functionId, 0, nullptr); + + if (m_ps.killState != 0) { + DxbcConditional cond; + cond.labelIf = m_module.allocateId(); + cond.labelEnd = m_module.allocateId(); + + uint32_t killTest = m_module.opLoad(m_module.defBoolType(), m_ps.killState); + + m_module.opSelectionMerge(cond.labelEnd, spv::SelectionControlMaskNone); + m_module.opBranchConditional(killTest, cond.labelIf, cond.labelEnd); + + m_module.opLabel(cond.labelIf); + m_module.opKill(); + + m_module.opLabel(cond.labelEnd); + } + + this->emitOutputSetup(); + this->emitOutputMapping(); + + if (m_moduleInfo.options.useDepthClipWorkaround) + this->emitOutputDepthClamp(); + + this->emitFunctionEnd(); + } + + + void DxbcCompiler::emitCsFinalize() { + this->emitMainFunctionBegin(); + + if (m_moduleInfo.options.zeroInitWorkgroupMemory) + this->emitInitWorkgroupMemory(); + + m_module.opFunctionCall( + m_module.defVoidType(), + m_cs.functionId, 0, nullptr); + + this->emitFunctionEnd(); + } + + + void DxbcCompiler::emitXfbOutputDeclarations() { + for (uint32_t i = 0; i < m_moduleInfo.xfb->entryCount; i++) { + const DxbcXfbEntry* xfbEntry = m_moduleInfo.xfb->entries + i; + const DxbcSgnEntry* sigEntry = m_osgn->find( + xfbEntry->semanticName, + xfbEntry->semanticIndex, + xfbEntry->streamId); + + if (sigEntry == nullptr) + continue; + + DxbcRegisterInfo varInfo; + varInfo.type.ctype = DxbcScalarType::Float32; + varInfo.type.ccount = xfbEntry->componentCount; + varInfo.type.alength = 0; + varInfo.sclass = spv::StorageClassOutput; + + uint32_t dstComponentMask = (1 << xfbEntry->componentCount) - 1; + uint32_t srcComponentMask = dstComponentMask + << sigEntry->componentMask.firstSet() + << xfbEntry->componentIndex; + + DxbcXfbVar xfbVar; + xfbVar.varId = emitNewVariable(varInfo); + xfbVar.streamId = xfbEntry->streamId; + xfbVar.outputId = sigEntry->registerId; + xfbVar.srcMask = DxbcRegMask(srcComponentMask); + xfbVar.dstMask = DxbcRegMask(dstComponentMask); + m_xfbVars.push_back(xfbVar); + + m_entryPointInterfaces.push_back(xfbVar.varId); + m_module.setDebugName(xfbVar.varId, + str::format("xfb", i).c_str()); + + m_module.decorateXfb(xfbVar.varId, + xfbEntry->streamId, xfbEntry->bufferId, xfbEntry->offset, + m_moduleInfo.xfb->strides[xfbEntry->bufferId]); + } + + // TODO Compact location/component assignment + for (uint32_t i = 0; i < m_xfbVars.size(); i++) { + m_xfbVars[i].location = i; + m_xfbVars[i].component = 0; + } + + for (uint32_t i = 0; i < m_xfbVars.size(); i++) { + const DxbcXfbVar* var = &m_xfbVars[i]; + + m_module.decorateLocation (var->varId, var->location); + m_module.decorateComponent(var->varId, var->component); + } + } + + + void DxbcCompiler::emitXfbOutputSetup( + uint32_t streamId, + bool passthrough) { + for (size_t i = 0; i < m_xfbVars.size(); i++) { + if (m_xfbVars[i].streamId == streamId) { + DxbcRegisterPointer srcPtr = passthrough + ? m_vRegs[m_xfbVars[i].outputId] + : m_oRegs[m_xfbVars[i].outputId]; + + if (passthrough) { + srcPtr = emitArrayAccess(srcPtr, + spv::StorageClassInput, + m_module.constu32(0)); + } + + DxbcRegisterPointer dstPtr; + dstPtr.type.ctype = DxbcScalarType::Float32; + dstPtr.type.ccount = m_xfbVars[i].dstMask.popCount(); + dstPtr.id = m_xfbVars[i].varId; + + DxbcRegisterValue value = emitRegisterExtract( + emitValueLoad(srcPtr), m_xfbVars[i].srcMask); + emitValueStore(dstPtr, value, m_xfbVars[i].dstMask); + } + } + } + + + void DxbcCompiler::emitHsControlPointPhase( + const DxbcCompilerHsControlPointPhase& phase) { + m_module.opFunctionCall( + m_module.defVoidType(), + phase.functionId, 0, nullptr); + } + + + void DxbcCompiler::emitHsForkJoinPhase( + const DxbcCompilerHsForkJoinPhase& phase) { + for (uint32_t i = 0; i < phase.instanceCount; i++) { + uint32_t invocationId = m_module.constu32(i); + + m_module.opFunctionCall( + m_module.defVoidType(), + phase.functionId, 1, + &invocationId); + } + } + + + void DxbcCompiler::emitDclInputArray(uint32_t vertexCount) { + DxbcVectorType info; + info.ctype = DxbcScalarType::Float32; + info.ccount = 4; + + // Define the array type. This will be two-dimensional + // in some shaders, with the outer index representing + // the vertex ID within an invocation. + m_vArrayLength = m_isgn != nullptr ? std::max(1u, m_isgn->maxRegisterCount()) : 1; + m_vArrayLengthId = m_module.lateConst32(getScalarTypeId(DxbcScalarType::Uint32)); + + uint32_t vectorTypeId = getVectorTypeId(info); + uint32_t arrayTypeId = m_module.defArrayType(vectorTypeId, m_vArrayLengthId); + + if (vertexCount != 0) { + arrayTypeId = m_module.defArrayType( + arrayTypeId, m_module.constu32(vertexCount)); + } + + // Define the actual variable. Note that this is private + // because we will copy input registers and some system + // variables to the array during the setup phase. + const uint32_t ptrTypeId = m_module.defPointerType( + arrayTypeId, spv::StorageClassPrivate); + + const uint32_t varId = m_module.newVar( + ptrTypeId, spv::StorageClassPrivate); + + m_module.setDebugName(varId, "shader_in"); + m_vArray = varId; + } + + + void DxbcCompiler::emitDclInputPerVertex( + uint32_t vertexCount, + const char* varName) { + uint32_t typeId = getPerVertexBlockId(); + + if (vertexCount != 0) { + typeId = m_module.defArrayType(typeId, + m_module.constu32(vertexCount)); + } + + const uint32_t ptrTypeId = m_module.defPointerType( + typeId, spv::StorageClassInput); + + m_perVertexIn = m_module.newVar( + ptrTypeId, spv::StorageClassInput); + m_module.setDebugName(m_perVertexIn, varName); + + m_entryPointInterfaces.push_back(m_perVertexIn); + } + + + uint32_t DxbcCompiler::emitDclClipCullDistanceArray( + uint32_t length, + spv::BuiltIn builtIn, + spv::StorageClass storageClass) { + if (length == 0) + return 0; + + uint32_t t_f32 = m_module.defFloatType(32); + uint32_t t_arr = m_module.defArrayType(t_f32, m_module.constu32(length)); + uint32_t t_ptr = m_module.defPointerType(t_arr, storageClass); + uint32_t varId = m_module.newVar(t_ptr, storageClass); + + m_module.decorateBuiltIn(varId, builtIn); + m_module.setDebugName(varId, + builtIn == spv::BuiltInClipDistance + ? "clip_distances" + : "cull_distances"); + + m_entryPointInterfaces.push_back(varId); + return varId; + } + + + DxbcCompilerHsControlPointPhase DxbcCompiler::emitNewHullShaderControlPointPhase() { + uint32_t funTypeId = m_module.defFunctionType( + m_module.defVoidType(), 0, nullptr); + + uint32_t funId = m_module.allocateId(); + + this->emitFunctionBegin(funId, + m_module.defVoidType(), + funTypeId); + this->emitFunctionLabel(); + + DxbcCompilerHsControlPointPhase result; + result.functionId = funId; + return result; + } + + + DxbcCompilerHsControlPointPhase DxbcCompiler::emitNewHullShaderPassthroughPhase() { + uint32_t funTypeId = m_module.defFunctionType( + m_module.defVoidType(), 0, nullptr); + + // Begin passthrough function + uint32_t funId = m_module.allocateId(); + m_module.setDebugName(funId, "hs_passthrough"); + + this->emitFunctionBegin(funId, + m_module.defVoidType(), + funTypeId); + this->emitFunctionLabel(); + + // We'll basically copy each input variable to the corresponding + // output, using the shader's invocation ID as the array index. + const uint32_t invocationId = m_module.opLoad( + getScalarTypeId(DxbcScalarType::Uint32), + m_hs.builtinInvocationId); + + for (auto i = m_isgn->begin(); i != m_isgn->end(); i++) { + this->emitDclInput( + i->registerId, m_hs.vertexCountIn, + i->componentMask, + DxbcSystemValue::None, + DxbcInterpolationMode::Undefined); + + // Vector type index + const std::array dstIndices + = {{ invocationId, m_module.constu32(i->registerId) }}; + + DxbcRegisterPointer srcPtr; + srcPtr.type = m_vRegs.at(i->registerId).type; + srcPtr.id = m_module.opAccessChain( + m_module.defPointerType(getVectorTypeId(srcPtr.type), spv::StorageClassInput), + m_vRegs.at(i->registerId).id, 1, &invocationId); + + DxbcRegisterValue srcValue = emitRegisterBitcast( + emitValueLoad(srcPtr), DxbcScalarType::Float32); + + DxbcRegisterPointer dstPtr; + dstPtr.type = { DxbcScalarType::Float32, 4 }; + dstPtr.id = m_module.opAccessChain( + m_module.defPointerType(getVectorTypeId(dstPtr.type), spv::StorageClassOutput), + m_hs.outputPerVertex, dstIndices.size(), dstIndices.data()); + + emitValueStore(dstPtr, srcValue, DxbcRegMask::firstN(srcValue.type.ccount)); + } + + // End function + this->emitFunctionEnd(); + + DxbcCompilerHsControlPointPhase result; + result.functionId = funId; + return result; + } + + + DxbcCompilerHsForkJoinPhase DxbcCompiler::emitNewHullShaderForkJoinPhase() { + uint32_t argTypeId = m_module.defIntType(32, 0); + uint32_t funTypeId = m_module.defFunctionType( + m_module.defVoidType(), 1, &argTypeId); + + uint32_t funId = m_module.allocateId(); + + this->emitFunctionBegin(funId, + m_module.defVoidType(), + funTypeId); + + uint32_t argId = m_module.functionParameter(argTypeId); + this->emitFunctionLabel(); + + DxbcCompilerHsForkJoinPhase result; + result.functionId = funId; + result.instanceId = argId; + return result; + } + + + void DxbcCompiler::emitHsPhaseBarrier() { + uint32_t exeScopeId = m_module.constu32(spv::ScopeWorkgroup); + uint32_t memScopeId = m_module.constu32(spv::ScopeInvocation); + uint32_t semanticId = m_module.constu32(spv::MemorySemanticsMaskNone); + + m_module.opControlBarrier(exeScopeId, memScopeId, semanticId); + } + + + void DxbcCompiler::emitHsInvocationBlockBegin(uint32_t count) { + uint32_t invocationId = m_module.opLoad( + getScalarTypeId(DxbcScalarType::Uint32), + m_hs.builtinInvocationId); + + uint32_t condition = m_module.opULessThan( + m_module.defBoolType(), invocationId, + m_module.constu32(count)); + + m_hs.invocationBlockBegin = m_module.allocateId(); + m_hs.invocationBlockEnd = m_module.allocateId(); + + m_module.opSelectionMerge( + m_hs.invocationBlockEnd, + spv::SelectionControlMaskNone); + + m_module.opBranchConditional( + condition, + m_hs.invocationBlockBegin, + m_hs.invocationBlockEnd); + + m_module.opLabel( + m_hs.invocationBlockBegin); + } + + + void DxbcCompiler::emitHsInvocationBlockEnd() { + m_module.opBranch (m_hs.invocationBlockEnd); + m_module.opLabel (m_hs.invocationBlockEnd); + + m_hs.invocationBlockBegin = 0; + m_hs.invocationBlockEnd = 0; + } + + + void DxbcCompiler::emitHsOutputSetup() { + uint32_t outputPerPatch = emitTessInterfacePerPatch(spv::StorageClassOutput); + + if (!outputPerPatch) + return; + + uint32_t vecType = getVectorTypeId({ DxbcScalarType::Float32, 4 }); + + uint32_t srcPtrType = m_module.defPointerType(vecType, spv::StorageClassPrivate); + uint32_t dstPtrType = m_module.defPointerType(vecType, spv::StorageClassOutput); + + for (uint32_t i = 0; i < 32; i++) { + if (m_hs.outputPerPatchMask & (1 << i)) { + uint32_t index = m_module.constu32(i); + + uint32_t srcPtr = m_module.opAccessChain(srcPtrType, m_hs.outputPerPatch, 1, &index); + uint32_t dstPtr = m_module.opAccessChain(dstPtrType, outputPerPatch, 1, &index); + + m_module.opStore(dstPtr, m_module.opLoad(vecType, srcPtr)); + } + } + } + + + uint32_t DxbcCompiler::emitTessInterfacePerPatch(spv::StorageClass storageClass) { + const char* name = "vPatch"; + + if (storageClass == spv::StorageClassPrivate) + name = "rPatch"; + if (storageClass == spv::StorageClassOutput) + name = "oPatch"; + + uint32_t arrLen = m_psgn != nullptr ? m_psgn->maxRegisterCount() : 0; + + if (!arrLen) + return 0; + + uint32_t vecType = m_module.defVectorType (m_module.defFloatType(32), 4); + uint32_t arrType = m_module.defArrayType (vecType, m_module.constu32(arrLen)); + uint32_t ptrType = m_module.defPointerType(arrType, storageClass); + uint32_t varId = m_module.newVar (ptrType, storageClass); + + m_module.setDebugName (varId, name); + + if (storageClass != spv::StorageClassPrivate) { + m_module.decorate (varId, spv::DecorationPatch); + m_module.decorateLocation (varId, 0); + + m_entryPointInterfaces.push_back(varId); + } + + return varId; + } + + + uint32_t DxbcCompiler::emitTessInterfacePerVertex(spv::StorageClass storageClass, uint32_t vertexCount) { + const bool isInput = storageClass == spv::StorageClassInput; + + uint32_t arrLen = isInput + ? (m_isgn != nullptr ? m_isgn->maxRegisterCount() : 0) + : (m_osgn != nullptr ? m_osgn->maxRegisterCount() : 0); + + if (!arrLen) + return 0; + + uint32_t locIdx = m_psgn != nullptr + ? m_psgn->maxRegisterCount() + : 0; + + uint32_t vecType = m_module.defVectorType (m_module.defFloatType(32), 4); + uint32_t arrTypeInner = m_module.defArrayType (vecType, m_module.constu32(arrLen)); + uint32_t arrTypeOuter = m_module.defArrayType (arrTypeInner, m_module.constu32(vertexCount)); + uint32_t ptrType = m_module.defPointerType(arrTypeOuter, storageClass); + uint32_t varId = m_module.newVar (ptrType, storageClass); + + m_module.setDebugName (varId, isInput ? "vVertex" : "oVertex"); + m_module.decorateLocation (varId, locIdx); + + if (storageClass != spv::StorageClassPrivate) + m_entryPointInterfaces.push_back(varId); + return varId; + } + + + uint32_t DxbcCompiler::emitSamplePosArray() { + const std::array samplePosVectors = {{ + // Invalid sample count / unbound resource + m_module.constvec2f32( 0.0f, 0.0f), + // VK_SAMPLE_COUNT_1_BIT + m_module.constvec2f32( 0.0f, 0.0f), + // VK_SAMPLE_COUNT_2_BIT + m_module.constvec2f32( 0.25f, 0.25f), + m_module.constvec2f32(-0.25f,-0.25f), + // VK_SAMPLE_COUNT_4_BIT + m_module.constvec2f32(-0.125f,-0.375f), + m_module.constvec2f32( 0.375f,-0.125f), + m_module.constvec2f32(-0.375f, 0.125f), + m_module.constvec2f32( 0.125f, 0.375f), + // VK_SAMPLE_COUNT_8_BIT + m_module.constvec2f32( 0.0625f,-0.1875f), + m_module.constvec2f32(-0.0625f, 0.1875f), + m_module.constvec2f32( 0.3125f, 0.0625f), + m_module.constvec2f32(-0.1875f,-0.3125f), + m_module.constvec2f32(-0.3125f, 0.3125f), + m_module.constvec2f32(-0.4375f,-0.0625f), + m_module.constvec2f32( 0.1875f, 0.4375f), + m_module.constvec2f32( 0.4375f,-0.4375f), + // VK_SAMPLE_COUNT_16_BIT + m_module.constvec2f32( 0.0625f, 0.0625f), + m_module.constvec2f32(-0.0625f,-0.1875f), + m_module.constvec2f32(-0.1875f, 0.1250f), + m_module.constvec2f32( 0.2500f,-0.0625f), + m_module.constvec2f32(-0.3125f,-0.1250f), + m_module.constvec2f32( 0.1250f, 0.3125f), + m_module.constvec2f32( 0.3125f, 0.1875f), + m_module.constvec2f32( 0.1875f,-0.3125f), + m_module.constvec2f32(-0.1250f, 0.3750f), + m_module.constvec2f32( 0.0000f,-0.4375f), + m_module.constvec2f32(-0.2500f,-0.3750f), + m_module.constvec2f32(-0.3750f, 0.2500f), + m_module.constvec2f32(-0.5000f, 0.0000f), + m_module.constvec2f32( 0.4375f,-0.2500f), + m_module.constvec2f32( 0.3750f, 0.4375f), + m_module.constvec2f32(-0.4375f,-0.5000f), + }}; + + uint32_t arrayTypeId = getArrayTypeId({ + DxbcScalarType::Float32, 2, + static_cast(samplePosVectors.size()) }); + + uint32_t samplePosArray = m_module.constComposite( + arrayTypeId, + samplePosVectors.size(), + samplePosVectors.data()); + + uint32_t varId = m_module.newVarInit( + m_module.defPointerType(arrayTypeId, spv::StorageClassPrivate), + spv::StorageClassPrivate, samplePosArray); + + m_module.setDebugName(varId, "g_sample_pos"); + return varId; + } + + + void DxbcCompiler::emitFloatControl() { + DxbcFloatControlFlags flags = m_moduleInfo.options.floatControl; + + if (flags.isClear()) + return; + + const uint32_t width32 = 32; + const uint32_t width64 = 64; + + m_module.enableExtension("SPV_KHR_float_controls"); + + if (flags.test(DxbcFloatControlFlag::DenormFlushToZero32)) { + m_module.enableCapability(spv::CapabilityDenormFlushToZero); + m_module.setExecutionMode(m_entryPointId, spv::ExecutionModeDenormFlushToZero, 1, &width32); + } + + if (flags.test(DxbcFloatControlFlag::PreserveNan32)) { + m_module.enableCapability(spv::CapabilitySignedZeroInfNanPreserve); + m_module.setExecutionMode(m_entryPointId, spv::ExecutionModeSignedZeroInfNanPreserve, 1, &width32); + } + + if (m_module.hasCapability(spv::CapabilityFloat64)) { + if (flags.test(DxbcFloatControlFlag::DenormPreserve64)) { + m_module.enableCapability(spv::CapabilityDenormPreserve); + m_module.setExecutionMode(m_entryPointId, spv::ExecutionModeDenormPreserve, 1, &width64); + } + + if (flags.test(DxbcFloatControlFlag::PreserveNan64)) { + m_module.enableCapability(spv::CapabilitySignedZeroInfNanPreserve); + m_module.setExecutionMode(m_entryPointId, spv::ExecutionModeSignedZeroInfNanPreserve, 1, &width64); + } + } + } + + + uint32_t DxbcCompiler::emitNewVariable(const DxbcRegisterInfo& info) { + const uint32_t ptrTypeId = this->getPointerTypeId(info); + return m_module.newVar(ptrTypeId, info.sclass); + } + + + uint32_t DxbcCompiler::emitNewBuiltinVariable( + const DxbcRegisterInfo& info, + spv::BuiltIn builtIn, + const char* name) { + const uint32_t varId = emitNewVariable(info); + + m_module.setDebugName(varId, name); + m_module.decorateBuiltIn(varId, builtIn); + + if (m_programInfo.type() == DxbcProgramType::PixelShader + && info.type.ctype != DxbcScalarType::Float32 + && info.type.ctype != DxbcScalarType::Bool + && info.sclass == spv::StorageClassInput) + m_module.decorate(varId, spv::DecorationFlat); + + m_entryPointInterfaces.push_back(varId); + return varId; + } + + + uint32_t DxbcCompiler::emitBuiltinTessLevelOuter(spv::StorageClass storageClass) { + uint32_t id = emitNewBuiltinVariable( + DxbcRegisterInfo { + { DxbcScalarType::Float32, 0, 4 }, + storageClass }, + spv::BuiltInTessLevelOuter, + "bTessLevelOuter"); + + m_module.decorate(id, spv::DecorationPatch); + return id; + } + + + uint32_t DxbcCompiler::emitBuiltinTessLevelInner(spv::StorageClass storageClass) { + uint32_t id = emitNewBuiltinVariable( + DxbcRegisterInfo { + { DxbcScalarType::Float32, 0, 2 }, + storageClass }, + spv::BuiltInTessLevelInner, + "bTessLevelInner"); + + m_module.decorate(id, spv::DecorationPatch); + return id; + } + + + void DxbcCompiler::enableShaderViewportIndexLayer() { + if (!m_extensions.shaderViewportIndexLayer) { + m_extensions.shaderViewportIndexLayer = true; + + m_module.enableExtension("SPV_EXT_shader_viewport_index_layer"); + m_module.enableCapability(spv::CapabilityShaderViewportIndexLayerEXT); + } + } + + + DxbcCfgBlock* DxbcCompiler::cfgFindBlock( + const std::initializer_list& types) { + for (auto cur = m_controlFlowBlocks.rbegin(); + cur != m_controlFlowBlocks.rend(); cur++) { + for (auto type : types) { + if (cur->type == type) + return &(*cur); + } + } + + return nullptr; + } + + + DxbcBufferInfo DxbcCompiler::getBufferInfo(const DxbcRegister& reg) { + const uint32_t registerId = reg.idx[0].offset; + + switch (reg.type) { + case DxbcOperandType::Resource: { + const auto& texture = m_textures.at(registerId); + + DxbcBufferInfo result; + result.image = texture.imageInfo; + result.stype = texture.sampledType; + result.type = texture.type; + result.typeId = texture.imageTypeId; + result.varId = texture.varId; + result.specId = texture.specId; + result.stride = texture.structStride; + result.align = texture.structAlign; + return result; + } break; + + case DxbcOperandType::UnorderedAccessView: { + const auto& uav = m_uavs.at(registerId); + + DxbcBufferInfo result; + result.image = uav.imageInfo; + result.stype = uav.sampledType; + result.type = uav.type; + result.typeId = uav.imageTypeId; + result.varId = uav.varId; + result.specId = uav.specId; + result.stride = uav.structStride; + result.align = uav.structAlign; + return result; + } break; + + case DxbcOperandType::ThreadGroupSharedMemory: { + DxbcBufferInfo result; + result.image = { spv::DimBuffer, 0, 0, 0 }; + result.stype = DxbcScalarType::Uint32; + result.type = m_gRegs.at(registerId).type; + result.typeId = m_module.defPointerType( + getScalarTypeId(DxbcScalarType::Uint32), + spv::StorageClassWorkgroup); + result.varId = m_gRegs.at(registerId).varId; + result.specId = 0; + result.stride = m_gRegs.at(registerId).elementStride; + result.align = 0; + return result; + } break; + + default: + throw DxvkError(str::format("DxbcCompiler: Invalid operand type for buffer: ", reg.type)); + } + } + + + uint32_t DxbcCompiler::getTexSizeDim(const DxbcImageInfo& imageType) const { + switch (imageType.dim) { + case spv::DimBuffer: return 1 + imageType.array; + case spv::Dim1D: return 1 + imageType.array; + case spv::Dim2D: return 2 + imageType.array; + case spv::Dim3D: return 3 + imageType.array; + case spv::DimCube: return 2 + imageType.array; + default: throw DxvkError("DxbcCompiler: getTexLayerDim: Unsupported image dimension"); + } + } + + + uint32_t DxbcCompiler::getTexLayerDim(const DxbcImageInfo& imageType) const { + switch (imageType.dim) { + case spv::DimBuffer: return 1; + case spv::Dim1D: return 1; + case spv::Dim2D: return 2; + case spv::Dim3D: return 3; + case spv::DimCube: return 3; + default: throw DxvkError("DxbcCompiler: getTexLayerDim: Unsupported image dimension"); + } + } + + + uint32_t DxbcCompiler::getTexCoordDim(const DxbcImageInfo& imageType) const { + return getTexLayerDim(imageType) + imageType.array; + } + + + DxbcRegMask DxbcCompiler::getTexCoordMask(const DxbcImageInfo& imageType) const { + return DxbcRegMask::firstN(getTexCoordDim(imageType)); + } + + + DxbcVectorType DxbcCompiler::getInputRegType(uint32_t regIdx) const { + switch (m_programInfo.type()) { + case DxbcProgramType::VertexShader: { + const DxbcSgnEntry* entry = m_isgn->findByRegister(regIdx); + + DxbcVectorType result; + result.ctype = DxbcScalarType::Float32; + result.ccount = 4; + + if (entry != nullptr) { + result.ctype = entry->componentType; + result.ccount = entry->componentMask.popCount(); + } + + return result; + } + + case DxbcProgramType::DomainShader: { + DxbcVectorType result; + result.ctype = DxbcScalarType::Float32; + result.ccount = 4; + return result; + } + + default: { + DxbcVectorType result; + result.ctype = DxbcScalarType::Float32; + result.ccount = 4; + + if (m_isgn->findByRegister(regIdx)) + result.ccount = m_isgn->regMask(regIdx).minComponents(); + return result; + } + } + } + + + DxbcVectorType DxbcCompiler::getOutputRegType(uint32_t regIdx) const { + switch (m_programInfo.type()) { + case DxbcProgramType::PixelShader: { + const DxbcSgnEntry* entry = m_osgn->findByRegister(regIdx); + + DxbcVectorType result; + result.ctype = DxbcScalarType::Float32; + result.ccount = 4; + + if (entry != nullptr) { + result.ctype = entry->componentType; + result.ccount = entry->componentMask.popCount(); + } + + return result; + } + + case DxbcProgramType::HullShader: { + DxbcVectorType result; + result.ctype = DxbcScalarType::Float32; + result.ccount = 4; + return result; + } + + default: { + DxbcVectorType result; + result.ctype = DxbcScalarType::Float32; + result.ccount = 4; + + if (m_osgn->findByRegister(regIdx)) + result.ccount = m_osgn->regMask(regIdx).minComponents(); + return result; + } + } + } + + + DxbcImageInfo DxbcCompiler::getResourceType( + DxbcResourceDim resourceType, + bool isUav) const { + uint32_t ms = m_moduleInfo.options.disableMsaa ? 0 : 1; + + DxbcImageInfo typeInfo = [resourceType, isUav, ms] () -> DxbcImageInfo { + switch (resourceType) { + case DxbcResourceDim::Buffer: return { spv::DimBuffer, 0, 0, isUav ? 2u : 1u, VK_IMAGE_VIEW_TYPE_MAX_ENUM }; + case DxbcResourceDim::Texture1D: return { spv::Dim1D, 0, 0, isUav ? 2u : 1u, VK_IMAGE_VIEW_TYPE_1D }; + case DxbcResourceDim::Texture1DArr: return { spv::Dim1D, 1, 0, isUav ? 2u : 1u, VK_IMAGE_VIEW_TYPE_1D_ARRAY }; + case DxbcResourceDim::Texture2D: return { spv::Dim2D, 0, 0, isUav ? 2u : 1u, VK_IMAGE_VIEW_TYPE_2D }; + case DxbcResourceDim::Texture2DArr: return { spv::Dim2D, 1, 0, isUav ? 2u : 1u, VK_IMAGE_VIEW_TYPE_2D_ARRAY }; + case DxbcResourceDim::Texture2DMs: return { spv::Dim2D, 0, ms,isUav ? 2u : 1u, VK_IMAGE_VIEW_TYPE_2D }; + case DxbcResourceDim::Texture2DMsArr: return { spv::Dim2D, 1, ms,isUav ? 2u : 1u, VK_IMAGE_VIEW_TYPE_2D_ARRAY }; + case DxbcResourceDim::Texture3D: return { spv::Dim3D, 0, 0, isUav ? 2u : 1u, VK_IMAGE_VIEW_TYPE_3D }; + case DxbcResourceDim::TextureCube: return { spv::DimCube, 0, 0, isUav ? 2u : 1u, VK_IMAGE_VIEW_TYPE_CUBE }; + case DxbcResourceDim::TextureCubeArr: return { spv::DimCube, 1, 0, isUav ? 2u : 1u, VK_IMAGE_VIEW_TYPE_CUBE_ARRAY }; + default: throw DxvkError(str::format("DxbcCompiler: Unsupported resource type: ", resourceType)); + } + }(); + + return typeInfo; + } + + + spv::ImageFormat DxbcCompiler::getScalarImageFormat(DxbcScalarType type) const { + switch (type) { + case DxbcScalarType::Float32: return spv::ImageFormatR32f; + case DxbcScalarType::Sint32: return spv::ImageFormatR32i; + case DxbcScalarType::Uint32: return spv::ImageFormatR32ui; + default: throw DxvkError("DxbcCompiler: Unhandled scalar resource type"); + } + } + + + bool DxbcCompiler::isDoubleType(DxbcScalarType type) const { + return type == DxbcScalarType::Sint64 + || type == DxbcScalarType::Uint64 + || type == DxbcScalarType::Float64; + } + + DxbcRegisterPointer DxbcCompiler::getIndexableTempPtr( + const DxbcRegister& operand, + DxbcRegisterValue vectorId) { + // x# regs are indexed as follows: + // (0) register index (immediate) + // (1) element index (relative) + const uint32_t regId = operand.idx[0].offset; + + DxbcRegisterInfo info; + info.type.ctype = DxbcScalarType::Float32; + info.type.ccount = m_xRegs[regId].ccount; + info.type.alength = 0; + info.sclass = spv::StorageClassPrivate; + + DxbcRegisterPointer result; + result.type.ctype = info.type.ctype; + result.type.ccount = info.type.ccount; + result.id = m_module.opAccessChain( + getPointerTypeId(info), + m_xRegs.at(regId).varId, + 1, &vectorId.id); + + return result; + } + + bool DxbcCompiler::caseBlockIsFallthrough() const { + return m_lastOp != DxbcOpcode::Case + && m_lastOp != DxbcOpcode::Default + && m_lastOp != DxbcOpcode::Break + && m_lastOp != DxbcOpcode::Ret; + } + + + uint32_t DxbcCompiler::getScalarTypeId(DxbcScalarType type) { + if (type == DxbcScalarType::Float64) + m_module.enableCapability(spv::CapabilityFloat64); + + if (type == DxbcScalarType::Sint64 || type == DxbcScalarType::Uint64) + m_module.enableCapability(spv::CapabilityInt64); + + switch (type) { + case DxbcScalarType::Uint32: return m_module.defIntType(32, 0); + case DxbcScalarType::Uint64: return m_module.defIntType(64, 0); + case DxbcScalarType::Sint32: return m_module.defIntType(32, 1); + case DxbcScalarType::Sint64: return m_module.defIntType(64, 1); + case DxbcScalarType::Float32: return m_module.defFloatType(32); + case DxbcScalarType::Float64: return m_module.defFloatType(64); + case DxbcScalarType::Bool: return m_module.defBoolType(); + } + + throw DxvkError("DxbcCompiler: Invalid scalar type"); + } + + + uint32_t DxbcCompiler::getVectorTypeId(const DxbcVectorType& type) { + uint32_t typeId = this->getScalarTypeId(type.ctype); + + if (type.ccount > 1) + typeId = m_module.defVectorType(typeId, type.ccount); + + return typeId; + } + + + uint32_t DxbcCompiler::getArrayTypeId(const DxbcArrayType& type) { + DxbcVectorType vtype; + vtype.ctype = type.ctype; + vtype.ccount = type.ccount; + + uint32_t typeId = this->getVectorTypeId(vtype); + + if (type.alength != 0) { + typeId = m_module.defArrayType(typeId, + m_module.constu32(type.alength)); + } + + return typeId; + } + + + uint32_t DxbcCompiler::getPointerTypeId(const DxbcRegisterInfo& type) { + return m_module.defPointerType( + this->getArrayTypeId(type.type), + type.sclass); + } + + + uint32_t DxbcCompiler::getPerVertexBlockId() { + uint32_t t_f32 = m_module.defFloatType(32); + uint32_t t_f32_v4 = m_module.defVectorType(t_f32, 4); +// uint32_t t_f32_a4 = m_module.defArrayType(t_f32, m_module.constu32(4)); + + std::array members; + members[PerVertex_Position] = t_f32_v4; +// members[PerVertex_CullDist] = t_f32_a4; +// members[PerVertex_ClipDist] = t_f32_a4; + + uint32_t typeId = m_module.defStructTypeUnique( + members.size(), members.data()); + + m_module.memberDecorateBuiltIn(typeId, PerVertex_Position, spv::BuiltInPosition); +// m_module.memberDecorateBuiltIn(typeId, PerVertex_CullDist, spv::BuiltInCullDistance); +// m_module.memberDecorateBuiltIn(typeId, PerVertex_ClipDist, spv::BuiltInClipDistance); + m_module.decorateBlock(typeId); + + m_module.setDebugName(typeId, "s_per_vertex"); + m_module.setDebugMemberName(typeId, PerVertex_Position, "position"); +// m_module.setDebugMemberName(typeId, PerVertex_CullDist, "cull_dist"); +// m_module.setDebugMemberName(typeId, PerVertex_ClipDist, "clip_dist"); + return typeId; + } + + + uint32_t DxbcCompiler::getFunctionId( + uint32_t functionNr) { + auto entry = m_subroutines.find(functionNr); + if (entry != m_subroutines.end()) + return entry->second; + + uint32_t functionId = m_module.allocateId(); + m_subroutines.insert({ functionNr, functionId }); + return functionId; + } + + + DxbcCompilerHsForkJoinPhase* DxbcCompiler::getCurrentHsForkJoinPhase() { + switch (m_hs.currPhaseType) { + case DxbcCompilerHsPhase::Fork: return &m_hs.forkPhases.at(m_hs.currPhaseId); + case DxbcCompilerHsPhase::Join: return &m_hs.joinPhases.at(m_hs.currPhaseId); + default: return nullptr; + } + } + +} diff --git a/utils/dxvk-1.10.3/src/dxbc/dxbc_compiler.h b/utils/dxvk-1.10.3/src/dxbc/dxbc_compiler.h new file mode 100644 index 00000000000..2216642caf7 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxbc/dxbc_compiler.h @@ -0,0 +1,1271 @@ +#pragma once + +#include +#include + +#include "../spirv/spirv_module.h" + +#include "dxbc_analysis.h" +#include "dxbc_chunk_isgn.h" +#include "dxbc_decoder.h" +#include "dxbc_defs.h" +#include "dxbc_modinfo.h" +#include "dxbc_names.h" +#include "dxbc_util.h" + +namespace dxvk { + + /** + * \brief Vector type + * + * Convenience struct that stores a scalar + * type and a component count. The compiler + * can use this to generate SPIR-V types. + */ + struct DxbcVectorType { + DxbcScalarType ctype; + uint32_t ccount; + }; + + + /** + * \brief Array type + * + * Convenience struct that stores a scalar type, a + * component count and an array size. An array of + * length 0 will be evaluated to a vector type. The + * compiler can use this to generate SPIR-V types. + */ + struct DxbcArrayType { + DxbcScalarType ctype; + uint32_t ccount; + uint32_t alength; + }; + + + /** + * \brief Register info + * + * Stores the array type of a register and + * its storage class. The compiler can use + * this to generate SPIR-V pointer types. + */ + struct DxbcRegisterInfo { + DxbcArrayType type; + spv::StorageClass sclass; + }; + + + /** + * \brief Register value + * + * Stores a vector type and a SPIR-V ID that + * represents an intermediate value. This is + * used to track the type of such values. + */ + struct DxbcRegisterValue { + DxbcVectorType type; + uint32_t id; + }; + + + /** + * \brief Register pointer + * + * Stores a vector type and a SPIR-V ID that + * represents a pointer to such a vector. This + * can be used to load registers conveniently. + */ + struct DxbcRegisterPointer { + DxbcVectorType type; + uint32_t id; + }; + + + struct DxbcXreg { + uint32_t ccount = 0; + uint32_t alength = 0; + uint32_t varId = 0; + }; + + + struct DxbcGreg { + DxbcResourceType type = DxbcResourceType::Raw; + uint32_t elementStride = 0; + uint32_t elementCount = 0; + uint32_t varId = 0; + }; + + + /** + * \brief Specialization constant properties + * + * Stores the name, data type and initial + * value of a specialization constant. + */ + struct DxbcSpecConstant { + DxbcScalarType ctype; + uint32_t ccount; + uint32_t value; + const char* name; + }; + + + /** + * \brief Helper struct for conditional execution + * + * Stores a set of labels required to implement either + * an if-then block or an if-then-else block. This is + * not used to implement control flow instructions. + */ + struct DxbcConditional { + uint32_t labelIf = 0; + uint32_t labelElse = 0; + uint32_t labelEnd = 0; + }; + + + struct DxbcXfbVar { + uint32_t varId = 0; + uint32_t streamId = 0; + uint32_t outputId = 0; + DxbcRegMask srcMask = 0; + DxbcRegMask dstMask = 0; + uint32_t location = 0; + uint32_t component = 0; + }; + + + /** + * \brief Vertex shader-specific structure + */ + struct DxbcCompilerVsPart { + uint32_t functionId = 0; + + uint32_t builtinVertexId = 0; + uint32_t builtinInstanceId = 0; + uint32_t builtinBaseVertex = 0; + uint32_t builtinBaseInstance = 0; + }; + + + /** + * \brief Geometry shader-specific structure + */ + struct DxbcCompilerGsPart { + DxbcPrimitive inputPrimitive = DxbcPrimitive::Undefined; + DxbcPrimitiveTopology outputTopology = DxbcPrimitiveTopology::Undefined; + uint32_t outputVertexCount = 0; + uint32_t functionId = 0; + + uint32_t builtinLayer = 0; + uint32_t builtinViewportId = 0; + uint32_t builtinInvocationId = 0; + uint32_t invocationCount = 0; + }; + + + /** + * \brief Pixel shader-specific structure + */ + struct DxbcCompilerPsPart { + uint32_t functionId = 0; + + uint32_t builtinFragCoord = 0; + uint32_t builtinDepth = 0; + uint32_t builtinStencilRef = 0; + uint32_t builtinIsFrontFace = 0; + uint32_t builtinSampleId = 0; + uint32_t builtinSampleMaskIn = 0; + uint32_t builtinSampleMaskOut = 0; + uint32_t builtinLayer = 0; + uint32_t builtinViewportId = 0; + + uint32_t builtinLaneId = 0; + uint32_t killState = 0; + + uint32_t specRsSampleCount = 0; + }; + + + /** + * \brief Compute shader-specific structure + */ + struct DxbcCompilerCsPart { + uint32_t functionId = 0; + + uint32_t workgroupSizeX = 0; + uint32_t workgroupSizeY = 0; + uint32_t workgroupSizeZ = 0; + + uint32_t builtinGlobalInvocationId = 0; + uint32_t builtinLocalInvocationId = 0; + uint32_t builtinLocalInvocationIndex = 0; + uint32_t builtinWorkgroupId = 0; + }; + + + /** + * \brief Hull shader fork/join phase + * + * Defines a function and built-in variables + * for a single fork or join phase sub-program. + */ + struct DxbcCompilerHsForkJoinPhase { + uint32_t functionId = 0; + uint32_t instanceCount = 1; + + uint32_t instanceId = 0; + uint32_t instanceIdPtr = 0; + }; + + + /** + * \brief Hull shader control point phase + * + * Defines the function for the control + * point phase program of a hull shader. + */ + struct DxbcCompilerHsControlPointPhase { + uint32_t functionId = 0; + }; + + + /** + * \brief Hull shader phase + * + * Used to identify the current + * phase and function ID. + */ + enum class DxbcCompilerHsPhase : uint32_t { + None, ///< No active phase + Decl, ///< \c hs_decls + ControlPoint, ///< \c hs_control_point_phase + Fork, ///< \c hs_fork_phase + Join, ///< \c hs_join_phase + }; + + + /** + * \brief Hull shader-specific structure + */ + struct DxbcCompilerHsPart { + DxbcCompilerHsPhase currPhaseType = DxbcCompilerHsPhase::None; + size_t currPhaseId = 0; + + float maxTessFactor = 64.0f; + + uint32_t vertexCountIn = 0; + uint32_t vertexCountOut = 0; + + uint32_t builtinInvocationId = 0; + uint32_t builtinTessLevelOuter = 0; + uint32_t builtinTessLevelInner = 0; + + uint32_t outputPerPatch = 0; + uint32_t outputPerVertex = 0; + + uint32_t invocationBlockBegin = 0; + uint32_t invocationBlockEnd = 0; + + uint32_t outputPerPatchMask = 0; + + DxbcCompilerHsControlPointPhase cpPhase; + std::vector forkPhases; + std::vector joinPhases; + }; + + + /** + * \brief Domain shader-specific structure + */ + struct DxbcCompilerDsPart { + uint32_t functionId = 0; + + uint32_t builtinTessCoord = 0; + uint32_t builtinTessLevelOuter = 0; + uint32_t builtinTessLevelInner = 0; + + uint32_t vertexCountIn = 0; + + uint32_t inputPerPatch = 0; + uint32_t inputPerVertex = 0; + }; + + + enum class DxbcCfgBlockType : uint32_t { + If, Loop, Switch, + }; + + + struct DxbcCfgBlockIf { + uint32_t ztestId; + uint32_t labelIf; + uint32_t labelElse; + uint32_t labelEnd; + size_t headerPtr; + }; + + + struct DxbcCfgBlockLoop { + uint32_t labelHeader; + uint32_t labelBegin; + uint32_t labelContinue; + uint32_t labelBreak; + }; + + + struct DxbcSwitchLabel { + SpirvSwitchCaseLabel desc; + DxbcSwitchLabel* next; + }; + + + struct DxbcCfgBlockSwitch { + size_t insertPtr; + uint32_t selectorId; + uint32_t labelBreak; + uint32_t labelCase; + uint32_t labelDefault; + DxbcSwitchLabel* labelCases; + }; + + + struct DxbcCfgBlock { + DxbcCfgBlockType type; + + union { + DxbcCfgBlockIf b_if; + DxbcCfgBlockLoop b_loop; + DxbcCfgBlockSwitch b_switch; + }; + }; + + + struct DxbcBufferInfo { + DxbcImageInfo image; + DxbcScalarType stype; + DxbcResourceType type; + uint32_t typeId; + uint32_t varId; + uint32_t specId; + uint32_t stride; + uint32_t align; + }; + + + /** + * \brief SPIR-V extension set + * + * Keeps track of which optional SPIR-V extensions + * are enabled so that any required setup code is + * only run once. + */ + struct DxbcSpirvExtensions { + bool shaderViewportIndexLayer = false; + }; + + + /** + * \brief DXBC to SPIR-V shader compiler + * + * Processes instructions from a DXBC shader and creates + * a DXVK shader object, which contains the SPIR-V module + * and information about the shader resource bindings. + */ + class DxbcCompiler { + + public: + + DxbcCompiler( + const std::string& fileName, + const DxbcModuleInfo& moduleInfo, + const DxbcProgramInfo& programInfo, + const Rc& isgn, + const Rc& osgn, + const Rc& psgn, + const DxbcAnalysisInfo& analysis); + ~DxbcCompiler(); + + /** + * \brief Processes a single instruction + * \param [in] ins The instruction + */ + void processInstruction( + const DxbcShaderInstruction& ins); + + /** + * \brief Emits transform feedback passthrough + * + * Writes all captured input variables to the + * corresponding xfb outputs, and sets up the + * geometry shader for point-to-point mode. + */ + void processXfbPassthrough(); + + /** + * \brief Finalizes the shader + * \returns The final shader object + */ + Rc finalize(); + + private: + + DxbcModuleInfo m_moduleInfo; + DxbcProgramInfo m_programInfo; + SpirvModule m_module; + + Rc m_isgn; + Rc m_osgn; + Rc m_psgn; + + const DxbcAnalysisInfo* m_analysis; + + /////////////////////////////////////////////////////// + // Resource slot description for the shader. This will + // be used to map D3D11 bindings to DXVK bindings. + std::vector m_resourceSlots; + + //////////////////////////////////////////////// + // Temporary r# vector registers with immediate + // indexing, and x# vector array registers. + std::vector m_rRegs; + std::vector m_xRegs; + + ///////////////////////////////////////////// + // Thread group shared memory (g#) registers + std::vector m_gRegs; + + /////////////////////////////////////////////////////////// + // v# registers as defined by the shader. The type of each + // of these inputs is either float4 or an array of float4. + std::array< + DxbcRegisterPointer, + DxbcMaxInterfaceRegs> m_vRegs; + std::vector m_vMappings; + + ////////////////////////////////////////////////////////// + // o# registers as defined by the shader. In the fragment + // shader stage, these registers are typed by the signature, + // in all other stages, they are float4 registers or arrays. + std::array< + DxbcRegisterPointer, + DxbcMaxInterfaceRegs> m_oRegs; + std::vector m_oMappings; + + ///////////////////////////////////////////// + // xfb output registers for geometry shaders + std::vector m_xfbVars; + + ////////////////////////////////////////////////////// + // Shader resource variables. These provide access to + // constant buffers, samplers, textures, and UAVs. + std::array m_constantBuffers; + std::array m_samplers; + std::array m_textures; + std::array m_uavs; + + /////////////////////////////////////////////// + // Control flow information. Stores labels for + // currently active if-else blocks and loops. + std::vector m_controlFlowBlocks; + + ////////////////////////////////////////////// + // Function state tracking. Required in order + // to properly end functions in some cases. + bool m_insideFunction = false; + + /////////////////////////////////////////////////////////// + // Array of input values. Since v# registers are indexable + // in DXBC, we need to copy them into an array first. + uint32_t m_vArrayLength = 0; + uint32_t m_vArrayLengthId = 0; + + uint32_t m_vArray = 0; + + //////////////////////////////////////////////////// + // Per-vertex input and output blocks. Depending on + // the shader stage, these may be declared as arrays. + uint32_t m_perVertexIn = 0; + uint32_t m_perVertexOut = 0; + + uint32_t m_clipDistances = 0; + uint32_t m_cullDistances = 0; + + uint32_t m_primitiveIdIn = 0; + uint32_t m_primitiveIdOut = 0; + + ////////////////////////////////////////////////// + // Immediate constant buffer. If defined, this is + // an array of four-component uint32 vectors. + uint32_t m_immConstBuf = 0; + std::vector m_immConstData; + + /////////////////////////////////////////////////// + // Sample pos array. If defined, this iis an array + // of 32 four-component float vectors. + uint32_t m_samplePositions = 0; + + //////////////////////////////////////////// + // Struct type used for UAV counter buffers + uint32_t m_uavCtrStructType = 0; + uint32_t m_uavCtrPointerType = 0; + + //////////////////////////////// + // Function IDs for subroutines + std::unordered_map m_subroutines; + + /////////////////////////////////////////////////// + // Entry point description - we'll need to declare + // the function ID and all input/output variables. + std::vector m_entryPointInterfaces; + uint32_t m_entryPointId = 0; + + //////////////////////////////////////////// + // Inter-stage shader interface slots. Also + // covers vertex input and fragment output. + uint32_t m_inputMask = 0u; + uint32_t m_outputMask = 0u; + + /////////////////////////////////// + // Shader-specific data structures + DxbcCompilerVsPart m_vs; + DxbcCompilerHsPart m_hs; + DxbcCompilerDsPart m_ds; + DxbcCompilerGsPart m_gs; + DxbcCompilerPsPart m_ps; + DxbcCompilerCsPart m_cs; + + ///////////////////////////// + // Enabled SPIR-V extensions + DxbcSpirvExtensions m_extensions; + + ////////////////////// + // Global state stuff + bool m_precise = true; + + DxbcOpcode m_lastOp = DxbcOpcode::Nop; + DxbcOpcode m_currOp = DxbcOpcode::Nop; + + ///////////////////////////////////////////////////// + // Shader interface and metadata declaration methods + void emitDcl( + const DxbcShaderInstruction& ins); + + void emitDclGlobalFlags( + const DxbcShaderInstruction& ins); + + void emitDclTemps( + const DxbcShaderInstruction& ins); + + void emitDclIndexableTemp( + const DxbcShaderInstruction& ins); + + void emitDclInterfaceReg( + const DxbcShaderInstruction& ins); + + void emitDclInput( + uint32_t regIdx, + uint32_t regDim, + DxbcRegMask regMask, + DxbcSystemValue sv, + DxbcInterpolationMode im); + + void emitDclOutput( + uint32_t regIdx, + uint32_t regDim, + DxbcRegMask regMask, + DxbcSystemValue sv, + DxbcInterpolationMode im); + + void emitDclConstantBuffer( + const DxbcShaderInstruction& ins); + + void emitDclConstantBufferVar( + uint32_t regIdx, + uint32_t numConstants, + const char* name, + bool asSsbo); + + void emitDclSampler( + const DxbcShaderInstruction& ins); + + void emitDclStream( + const DxbcShaderInstruction& ins); + + void emitDclResourceTyped( + const DxbcShaderInstruction& ins); + + void emitDclResourceRawStructured( + const DxbcShaderInstruction& ins); + + void emitDclThreadGroupSharedMemory( + const DxbcShaderInstruction& ins); + + void emitDclGsInputPrimitive( + const DxbcShaderInstruction& ins); + + void emitDclGsOutputTopology( + const DxbcShaderInstruction& ins); + + void emitDclMaxOutputVertexCount( + const DxbcShaderInstruction& ins); + + void emitDclInputControlPointCount( + const DxbcShaderInstruction& ins); + + void emitDclOutputControlPointCount( + const DxbcShaderInstruction& ins); + + void emitDclHsMaxTessFactor( + const DxbcShaderInstruction& ins); + + void emitDclTessDomain( + const DxbcShaderInstruction& ins); + + void emitDclTessPartitioning( + const DxbcShaderInstruction& ins); + + void emitDclTessOutputPrimitive( + const DxbcShaderInstruction& ins); + + void emitDclThreadGroup( + const DxbcShaderInstruction& ins); + + void emitDclGsInstanceCount( + const DxbcShaderInstruction& ins); + + uint32_t emitDclUavCounter( + uint32_t regId); + + //////////////////////// + // Custom data handlers + void emitDclImmediateConstantBuffer( + const DxbcShaderInstruction& ins); + + void emitDclImmediateConstantBufferBaked( + uint32_t dwordCount, + const uint32_t* dwordArray); + + void emitDclImmediateConstantBufferUbo( + uint32_t dwordCount, + const uint32_t* dwordArray); + + void emitCustomData( + const DxbcShaderInstruction& ins); + + ////////////////////////////// + // Instruction class handlers + void emitVectorAlu( + const DxbcShaderInstruction& ins); + + void emitVectorCmov( + const DxbcShaderInstruction& ins); + + void emitVectorCmp( + const DxbcShaderInstruction& ins); + + void emitVectorDeriv( + const DxbcShaderInstruction& ins); + + void emitVectorDot( + const DxbcShaderInstruction& ins); + + void emitVectorIdiv( + const DxbcShaderInstruction& ins); + + void emitVectorImul( + const DxbcShaderInstruction& ins); + + void emitVectorMsad( + const DxbcShaderInstruction& ins); + + void emitVectorShift( + const DxbcShaderInstruction& ins); + + void emitVectorSinCos( + const DxbcShaderInstruction& ins); + + void emitGeometryEmit( + const DxbcShaderInstruction& ins); + + void emitAtomic( + const DxbcShaderInstruction& ins); + + void emitAtomicCounter( + const DxbcShaderInstruction& ins); + + void emitBarrier( + const DxbcShaderInstruction& ins); + + void emitBitExtract( + const DxbcShaderInstruction& ins); + + void emitBitInsert( + const DxbcShaderInstruction& ins); + + void emitBitScan( + const DxbcShaderInstruction& ins); + + void emitBufferQuery( + const DxbcShaderInstruction& ins); + + void emitBufferLoad( + const DxbcShaderInstruction& ins); + + void emitBufferStore( + const DxbcShaderInstruction& ins); + + void emitConvertFloat16( + const DxbcShaderInstruction& ins); + + void emitConvertFloat64( + const DxbcShaderInstruction& ins); + + void emitHullShaderPhase( + const DxbcShaderInstruction& ins); + + void emitHullShaderInstCnt( + const DxbcShaderInstruction& ins); + + void emitInterpolate( + const DxbcShaderInstruction& ins); + + void emitTextureQuery( + const DxbcShaderInstruction& ins); + + void emitTextureQueryLod( + const DxbcShaderInstruction& ins); + + void emitTextureQueryMs( + const DxbcShaderInstruction& ins); + + void emitTextureQueryMsPos( + const DxbcShaderInstruction& ins); + + void emitTextureFetch( + const DxbcShaderInstruction& ins); + + void emitTextureGather( + const DxbcShaderInstruction& ins); + + void emitTextureSample( + const DxbcShaderInstruction& ins); + + void emitTypedUavLoad( + const DxbcShaderInstruction& ins); + + void emitTypedUavStore( + const DxbcShaderInstruction& ins); + + ///////////////////////////////////// + // Control flow instruction handlers + void emitControlFlowIf( + const DxbcShaderInstruction& ins); + + void emitControlFlowElse( + const DxbcShaderInstruction& ins); + + void emitControlFlowEndIf( + const DxbcShaderInstruction& ins); + + void emitControlFlowSwitch( + const DxbcShaderInstruction& ins); + + void emitControlFlowCase( + const DxbcShaderInstruction& ins); + + void emitControlFlowDefault( + const DxbcShaderInstruction& ins); + + void emitControlFlowEndSwitch( + const DxbcShaderInstruction& ins); + + void emitControlFlowLoop( + const DxbcShaderInstruction& ins); + + void emitControlFlowEndLoop( + const DxbcShaderInstruction& ins); + + void emitControlFlowBreak( + const DxbcShaderInstruction& ins); + + void emitControlFlowBreakc( + const DxbcShaderInstruction& ins); + + void emitControlFlowRet( + const DxbcShaderInstruction& ins); + + void emitControlFlowRetc( + const DxbcShaderInstruction& ins); + + void emitControlFlowDiscard( + const DxbcShaderInstruction& ins); + + void emitControlFlowLabel( + const DxbcShaderInstruction& ins); + + void emitControlFlowCall( + const DxbcShaderInstruction& ins); + + void emitControlFlowCallc( + const DxbcShaderInstruction& ins); + + void emitControlFlow( + const DxbcShaderInstruction& ins); + + //////////////////////////////////////////////// + // Constant building methods. These are used to + // generate constant vectors that store the same + // value in each component. + DxbcRegisterValue emitBuildConstVecf32( + float x, + float y, + float z, + float w, + const DxbcRegMask& writeMask); + + DxbcRegisterValue emitBuildConstVecu32( + uint32_t x, + uint32_t y, + uint32_t z, + uint32_t w, + const DxbcRegMask& writeMask); + + DxbcRegisterValue emitBuildConstVeci32( + int32_t x, + int32_t y, + int32_t z, + int32_t w, + const DxbcRegMask& writeMask); + + DxbcRegisterValue emitBuildConstVecf64( + double xy, + double zw, + const DxbcRegMask& writeMask); + + DxbcRegisterValue emitBuildVector( + DxbcRegisterValue scalar, + uint32_t count); + + DxbcRegisterValue emitBuildZeroVector( + DxbcVectorType type); + + ///////////////////////////////////////// + // Generic register manipulation methods + DxbcRegisterValue emitRegisterBitcast( + DxbcRegisterValue srcValue, + DxbcScalarType dstType); + + DxbcRegisterValue emitRegisterSwizzle( + DxbcRegisterValue value, + DxbcRegSwizzle swizzle, + DxbcRegMask writeMask); + + DxbcRegisterValue emitRegisterExtract( + DxbcRegisterValue value, + DxbcRegMask mask); + + DxbcRegisterValue emitRegisterInsert( + DxbcRegisterValue dstValue, + DxbcRegisterValue srcValue, + DxbcRegMask srcMask); + + DxbcRegisterValue emitRegisterConcat( + DxbcRegisterValue value1, + DxbcRegisterValue value2); + + DxbcRegisterValue emitRegisterExtend( + DxbcRegisterValue value, + uint32_t size); + + DxbcRegisterValue emitRegisterAbsolute( + DxbcRegisterValue value); + + DxbcRegisterValue emitRegisterNegate( + DxbcRegisterValue value); + + DxbcRegisterValue emitRegisterZeroTest( + DxbcRegisterValue value, + DxbcZeroTest test); + + DxbcRegisterValue emitRegisterMaskBits( + DxbcRegisterValue value, + uint32_t mask); + + DxbcRegisterValue emitSrcOperandModifiers( + DxbcRegisterValue value, + DxbcRegModifiers modifiers); + + DxbcRegisterValue emitDstOperandModifiers( + DxbcRegisterValue value, + DxbcOpModifiers modifiers); + + //////////////////////////////// + // Pointer manipulation methods + DxbcRegisterPointer emitArrayAccess( + DxbcRegisterPointer pointer, + spv::StorageClass sclass, + uint32_t index); + + /////////////////////////////////////// + // Image register manipulation methods + uint32_t emitLoadSampledImage( + const DxbcShaderResource& textureResource, + const DxbcSampler& samplerResource, + bool isDepthCompare); + + //////////////////////// + // Address load methods + DxbcRegisterPointer emitGetTempPtr( + const DxbcRegister& operand); + + DxbcRegisterPointer emitGetIndexableTempPtr( + const DxbcRegister& operand); + + DxbcRegisterPointer emitGetInputPtr( + const DxbcRegister& operand); + + DxbcRegisterPointer emitGetOutputPtr( + const DxbcRegister& operand); + + DxbcRegisterPointer emitGetConstBufPtr( + const DxbcRegister& operand); + + DxbcRegisterPointer emitGetImmConstBufPtr( + const DxbcRegister& operand); + + DxbcRegisterPointer emitGetOperandPtr( + const DxbcRegister& operand); + + DxbcRegisterPointer emitGetAtomicPointer( + const DxbcRegister& operand, + const DxbcRegister& address); + + /////////////////////////////// + // Resource load/store methods + DxbcRegisterValue emitRawBufferLoad( + const DxbcRegister& operand, + DxbcRegisterValue elementIndex, + DxbcRegMask writeMask); + + void emitRawBufferStore( + const DxbcRegister& operand, + DxbcRegisterValue elementIndex, + DxbcRegisterValue value); + + ////////////////////////// + // Resource query methods + DxbcRegisterValue emitQueryBufferSize( + const DxbcRegister& resource); + + DxbcRegisterValue emitQueryTexelBufferSize( + const DxbcRegister& resource); + + DxbcRegisterValue emitQueryTextureLods( + const DxbcRegister& resource); + + DxbcRegisterValue emitQueryTextureSamples( + const DxbcRegister& resource); + + DxbcRegisterValue emitQueryTextureSize( + const DxbcRegister& resource, + DxbcRegisterValue lod); + + //////////////////////////////////// + // Buffer index calculation methods + DxbcRegisterValue emitCalcBufferIndexStructured( + DxbcRegisterValue structId, + DxbcRegisterValue structOffset, + uint32_t structStride); + + DxbcRegisterValue emitCalcBufferIndexRaw( + DxbcRegisterValue byteOffset); + + DxbcRegisterValue emitCalcTexCoord( + DxbcRegisterValue coordVector, + const DxbcImageInfo& imageInfo); + + DxbcRegisterValue emitLoadTexCoord( + const DxbcRegister& coordReg, + const DxbcImageInfo& imageInfo); + + ////////////////////////////// + // Operand load/store methods + DxbcRegisterValue emitIndexLoad( + DxbcRegIndex index); + + DxbcRegisterValue emitValueLoad( + DxbcRegisterPointer ptr); + + void emitValueStore( + DxbcRegisterPointer ptr, + DxbcRegisterValue value, + DxbcRegMask writeMask); + + DxbcRegisterValue emitRegisterLoadRaw( + const DxbcRegister& reg); + + DxbcRegisterValue emitConstantBufferLoad( + const DxbcRegister& reg, + DxbcRegMask writeMask); + + DxbcRegisterValue emitRegisterLoad( + const DxbcRegister& reg, + DxbcRegMask writeMask); + + void emitRegisterStore( + const DxbcRegister& reg, + DxbcRegisterValue value); + + //////////////////////////////////////// + // Spec constant declaration and access + uint32_t emitNewSpecConstant( + DxvkSpecConstantId specId, + DxbcScalarType type, + uint32_t value, + const char* name); + + //////////////////////////// + // Input/output preparation + void emitInputSetup(); + void emitInputSetup(uint32_t vertexCount); + + void emitOutputSetup(); + void emitOutputMapping(); + void emitOutputDepthClamp(); + + void emitInitWorkgroupMemory(); + + ////////////////////////////////////////// + // System value load methods (per shader) + DxbcRegisterValue emitVsSystemValueLoad( + DxbcSystemValue sv, + DxbcRegMask mask); + + DxbcRegisterValue emitGsSystemValueLoad( + DxbcSystemValue sv, + DxbcRegMask mask, + uint32_t vertexId); + + DxbcRegisterValue emitPsSystemValueLoad( + DxbcSystemValue sv, + DxbcRegMask mask); + + /////////////////////////////////////////// + // System value store methods (per shader) + void emitVsSystemValueStore( + DxbcSystemValue sv, + DxbcRegMask mask, + const DxbcRegisterValue& value); + + void emitHsSystemValueStore( + DxbcSystemValue sv, + DxbcRegMask mask, + const DxbcRegisterValue& value); + + void emitDsSystemValueStore( + DxbcSystemValue sv, + DxbcRegMask mask, + const DxbcRegisterValue& value); + + void emitGsSystemValueStore( + DxbcSystemValue sv, + DxbcRegMask mask, + const DxbcRegisterValue& value); + + void emitPsSystemValueStore( + DxbcSystemValue sv, + DxbcRegMask mask, + const DxbcRegisterValue& value); + + /////////////////////////////// + // Special system value stores + void emitClipCullStore( + DxbcSystemValue sv, + uint32_t dstArray); + + void emitClipCullLoad( + DxbcSystemValue sv, + uint32_t srcArray); + + /////////////////////////////// + // Some state checking methods + uint32_t emitUavWriteTest( + const DxbcBufferInfo& uav); + + ////////////////////////////////////// + // Common function definition methods + void emitInit(); + + void emitFunctionBegin( + uint32_t entryPoint, + uint32_t returnType, + uint32_t funcType); + + void emitFunctionEnd(); + + void emitFunctionLabel(); + + void emitMainFunctionBegin(); + + ///////////////////////////////// + // Shader initialization methods + void emitVsInit(); + void emitHsInit(); + void emitDsInit(); + void emitGsInit(); + void emitPsInit(); + void emitCsInit(); + + /////////////////////////////// + // Shader finalization methods + void emitVsFinalize(); + void emitHsFinalize(); + void emitDsFinalize(); + void emitGsFinalize(); + void emitPsFinalize(); + void emitCsFinalize(); + + /////////////////////// + // Xfb related methods + void emitXfbOutputDeclarations(); + + void emitXfbOutputSetup( + uint32_t streamId, + bool passthrough); + + /////////////////////////////// + // Hull shader phase methods + void emitHsControlPointPhase( + const DxbcCompilerHsControlPointPhase& phase); + + void emitHsForkJoinPhase( + const DxbcCompilerHsForkJoinPhase& phase); + + void emitHsPhaseBarrier(); + + void emitHsInvocationBlockBegin( + uint32_t count); + + void emitHsInvocationBlockEnd(); + + void emitHsOutputSetup(); + + uint32_t emitTessInterfacePerPatch( + spv::StorageClass storageClass); + + uint32_t emitTessInterfacePerVertex( + spv::StorageClass storageClass, + uint32_t vertexCount); + + ////////////// + // Misc stuff + void emitDclInputArray( + uint32_t vertexCount); + + void emitDclInputPerVertex( + uint32_t vertexCount, + const char* varName); + + uint32_t emitDclClipCullDistanceArray( + uint32_t length, + spv::BuiltIn builtIn, + spv::StorageClass storageClass); + + DxbcCompilerHsControlPointPhase emitNewHullShaderControlPointPhase(); + + DxbcCompilerHsControlPointPhase emitNewHullShaderPassthroughPhase(); + + DxbcCompilerHsForkJoinPhase emitNewHullShaderForkJoinPhase(); + + uint32_t emitSamplePosArray(); + + void emitFloatControl(); + + /////////////////////////////// + // Variable definition methods + uint32_t emitNewVariable( + const DxbcRegisterInfo& info); + + uint32_t emitNewBuiltinVariable( + const DxbcRegisterInfo& info, + spv::BuiltIn builtIn, + const char* name); + + uint32_t emitBuiltinTessLevelOuter( + spv::StorageClass storageClass); + + uint32_t emitBuiltinTessLevelInner( + spv::StorageClass storageClass); + + //////////////////////////////// + // Extension enablement methods + void enableShaderViewportIndexLayer(); + + //////////////// + // Misc methods + DxbcCfgBlock* cfgFindBlock( + const std::initializer_list& types); + + DxbcBufferInfo getBufferInfo( + const DxbcRegister& reg); + + uint32_t getTexSizeDim( + const DxbcImageInfo& imageType) const; + + uint32_t getTexLayerDim( + const DxbcImageInfo& imageType) const; + + uint32_t getTexCoordDim( + const DxbcImageInfo& imageType) const; + + DxbcRegMask getTexCoordMask( + const DxbcImageInfo& imageType) const; + + DxbcVectorType getInputRegType( + uint32_t regIdx) const; + + DxbcVectorType getOutputRegType( + uint32_t regIdx) const; + + DxbcImageInfo getResourceType( + DxbcResourceDim resourceType, + bool isUav) const; + + spv::ImageFormat getScalarImageFormat( + DxbcScalarType type) const; + + bool isDoubleType( + DxbcScalarType type) const; + + DxbcRegisterPointer getIndexableTempPtr( + const DxbcRegister& operand, + DxbcRegisterValue vectorId); + + bool caseBlockIsFallthrough() const; + + /////////////////////////// + // Type definition methods + uint32_t getScalarTypeId( + DxbcScalarType type); + + uint32_t getVectorTypeId( + const DxbcVectorType& type); + + uint32_t getArrayTypeId( + const DxbcArrayType& type); + + uint32_t getPointerTypeId( + const DxbcRegisterInfo& type); + + uint32_t getPerVertexBlockId(); + + uint32_t getFunctionId( + uint32_t functionNr); + + DxbcCompilerHsForkJoinPhase* getCurrentHsForkJoinPhase(); + + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxbc/dxbc_decoder.cpp b/utils/dxvk-1.10.3/src/dxbc/dxbc_decoder.cpp new file mode 100644 index 00000000000..0de7ddad17a --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxbc/dxbc_decoder.cpp @@ -0,0 +1,360 @@ +#include "dxbc_decoder.h" + +namespace dxvk { + + const uint32_t* DxbcCodeSlice::ptrAt(uint32_t id) const { + if (m_ptr + id >= m_end) + throw DxvkError("DxbcCodeSlice: End of stream"); + return m_ptr + id; + } + + + uint32_t DxbcCodeSlice::at(uint32_t id) const { + if (m_ptr + id >= m_end) + throw DxvkError("DxbcCodeSlice: End of stream"); + return m_ptr[id]; + } + + + uint32_t DxbcCodeSlice::read() { + if (m_ptr >= m_end) + throw DxvkError("DxbcCodeSlice: End of stream"); + return *(m_ptr++); + } + + + DxbcCodeSlice DxbcCodeSlice::take(uint32_t n) const { + if (m_ptr + n > m_end) + throw DxvkError("DxbcCodeSlice: End of stream"); + return DxbcCodeSlice(m_ptr, m_ptr + n); + } + + + DxbcCodeSlice DxbcCodeSlice::skip(uint32_t n) const { + if (m_ptr + n > m_end) + throw DxvkError("DxbcCodeSlice: End of stream"); + return DxbcCodeSlice(m_ptr + n, m_end); + } + + + + void DxbcDecodeContext::decodeInstruction(DxbcCodeSlice& code) { + const uint32_t token0 = code.at(0); + + // Initialize the instruction structure. Some of these values + // may not get written otherwise while decoding the instruction. + m_instruction.op = static_cast(bit::extract(token0, 0, 10)); + m_instruction.opClass = DxbcInstClass::Undefined; + m_instruction.sampleControls = { 0, 0, 0 }; + m_instruction.dstCount = 0; + m_instruction.srcCount = 0; + m_instruction.immCount = 0; + m_instruction.dst = m_dstOperands.data(); + m_instruction.src = m_srcOperands.data(); + m_instruction.imm = m_immOperands.data(); + m_instruction.customDataType = DxbcCustomDataClass::Comment; + m_instruction.customDataSize = 0; + m_instruction.customData = nullptr; + + // Reset the index pointer, which may still contain + // a non-zero value from the previous iteration + m_indexId = 0; + + // Instruction length, in DWORDs. This includes the token + // itself and any other prefix that an instruction may have. + uint32_t length = 0; + + if (m_instruction.op == DxbcOpcode::CustomData) { + length = code.at(1); + this->decodeCustomData(code.take(length)); + } else { + length = bit::extract(token0, 24, 30); + this->decodeOperation(code.take(length)); + } + + // Advance the caller's slice to the next token so that + // they can make consecutive calls to decodeInstruction() + code = code.skip(length); + } + + + void DxbcDecodeContext::decodeCustomData(DxbcCodeSlice code) { + const uint32_t blockLength = code.at(1); + + if (blockLength < 2) { + Logger::err("DxbcDecodeContext: Invalid custom data block"); + return; + } + + // Custom data blocks have their own instruction class + m_instruction.op = DxbcOpcode::CustomData; + m_instruction.opClass = DxbcInstClass::CustomData; + + // We'll point into the code buffer rather than making a copy + m_instruction.customDataType = static_cast( + bit::extract(code.at(0), 11, 31)); + m_instruction.customDataSize = blockLength - 2; + m_instruction.customData = code.ptrAt(2); + } + + + void DxbcDecodeContext::decodeOperation(DxbcCodeSlice code) { + uint32_t token = code.read(); + + // Result modifiers, which are applied to common ALU ops + m_instruction.modifiers.saturate = !!bit::extract(token, 13, 13); + m_instruction.modifiers.precise = !!bit::extract(token, 19, 22); + + // Opcode controls. It will depend on the + // opcode itself which ones are valid. + m_instruction.controls = DxbcShaderOpcodeControls(token); + + // Process extended opcode tokens + while (bit::extract(token, 31, 31)) { + token = code.read(); + + const DxbcExtOpcode extOpcode + = static_cast(bit::extract(token, 0, 5)); + + switch (extOpcode) { + case DxbcExtOpcode::SampleControls: { + struct { + int u : 4; + int v : 4; + int w : 4; + } aoffimmi; + + aoffimmi.u = bit::extract(token, 9, 12); + aoffimmi.v = bit::extract(token, 13, 16); + aoffimmi.w = bit::extract(token, 17, 20); + + // Four-bit signed numbers, sign-extend them + m_instruction.sampleControls.u = aoffimmi.u; + m_instruction.sampleControls.v = aoffimmi.v; + m_instruction.sampleControls.w = aoffimmi.w; + } break; + + case DxbcExtOpcode::ResourceDim: + case DxbcExtOpcode::ResourceReturnType: + break; // part of resource description + + default: + Logger::warn(str::format( + "DxbcDecodeContext: Unhandled extended opcode: ", + extOpcode)); + } + } + + // Retrieve the instruction format in order to parse the + // operands. Doing this mostly automatically means that + // the compiler can rely on the operands being valid. + const DxbcInstFormat format = dxbcInstructionFormat(m_instruction.op); + m_instruction.opClass = format.instructionClass; + + for (uint32_t i = 0; i < format.operandCount; i++) + this->decodeOperand(code, format.operands[i]); + } + + + void DxbcDecodeContext::decodeComponentSelection(DxbcRegister& reg, uint32_t token) { + // Pick the correct component selection mode based on the + // component count. We'll simplify this here so that the + // compiler can assume that everything is a 4D vector. + reg.componentCount = static_cast(bit::extract(token, 0, 1)); + + switch (reg.componentCount) { + // No components - used for samplers etc. + case DxbcComponentCount::Component0: + reg.mask = DxbcRegMask(false, false, false, false); + reg.swizzle = DxbcRegSwizzle(0, 0, 0, 0); + break; + + // One component - used for immediates + // and a few built-in registers. + case DxbcComponentCount::Component1: + reg.mask = DxbcRegMask(true, false, false, false); + reg.swizzle = DxbcRegSwizzle(0, 0, 0, 0); + break; + + // Four components - everything else. This requires us + // to actually parse the component selection mode. + case DxbcComponentCount::Component4: { + const DxbcRegMode componentMode = + static_cast(bit::extract(token, 2, 3)); + + switch (componentMode) { + // Write mask for destination operands + case DxbcRegMode::Mask: + reg.mask = bit::extract(token, 4, 7); + reg.swizzle = DxbcRegSwizzle(0, 1, 2, 3); + break; + + // Swizzle for source operands (including resources) + case DxbcRegMode::Swizzle: + reg.mask = DxbcRegMask(true, true, true, true); + reg.swizzle = DxbcRegSwizzle( + bit::extract(token, 4, 5), + bit::extract(token, 6, 7), + bit::extract(token, 8, 9), + bit::extract(token, 10, 11)); + break; + + // Selection of one component. We can generate both a + // mask and a swizzle for this so that the compiler + // won't have to deal with this case specifically. + case DxbcRegMode::Select1: { + const uint32_t n = bit::extract(token, 4, 5); + reg.mask = DxbcRegMask(n == 0, n == 1, n == 2, n == 3); + reg.swizzle = DxbcRegSwizzle(n, n, n, n); + } break; + + default: + Logger::warn("DxbcDecodeContext: Invalid component selection mode"); + } + } break; + + default: + Logger::warn("DxbcDecodeContext: Invalid component count"); + } + } + + + void DxbcDecodeContext::decodeOperandExtensions(DxbcCodeSlice& code, DxbcRegister& reg, uint32_t token) { + while (bit::extract(token, 31, 31)) { + token = code.read(); + + // Type of the extended operand token + const DxbcOperandExt extTokenType = + static_cast(bit::extract(token, 0, 5)); + + switch (extTokenType) { + // Operand modifiers, which are used to manipulate the + // value of a source operand during the load operation + case DxbcOperandExt::OperandModifier: + reg.modifiers = bit::extract(token, 6, 13); + break; + + default: + Logger::warn(str::format( + "DxbcDecodeContext: Unhandled extended operand token: ", + extTokenType)); + } + } + } + + + void DxbcDecodeContext::decodeOperandImmediates(DxbcCodeSlice& code, DxbcRegister& reg) { + if (reg.type == DxbcOperandType::Imm32 + || reg.type == DxbcOperandType::Imm64) { + switch (reg.componentCount) { + // This is commonly used if only one vector + // component is involved in an operation + case DxbcComponentCount::Component1: { + reg.imm.u32_1 = code.read(); + } break; + + // Typical four-component vector + case DxbcComponentCount::Component4: { + reg.imm.u32_4[0] = code.read(); + reg.imm.u32_4[1] = code.read(); + reg.imm.u32_4[2] = code.read(); + reg.imm.u32_4[3] = code.read(); + } break; + + default: + Logger::warn("DxbcDecodeContext: Invalid component count for immediate operand"); + } + } + } + + + void DxbcDecodeContext::decodeOperandIndex(DxbcCodeSlice& code, DxbcRegister& reg, uint32_t token) { + reg.idxDim = bit::extract(token, 20, 21); + + for (uint32_t i = 0; i < reg.idxDim; i++) { + // An index can be encoded in various different ways + const DxbcOperandIndexRepresentation repr = + static_cast( + bit::extract(token, 22 + 3 * i, 24 + 3 * i)); + + switch (repr) { + case DxbcOperandIndexRepresentation::Imm32: + reg.idx[i].offset = static_cast(code.read()); + reg.idx[i].relReg = nullptr; + break; + + case DxbcOperandIndexRepresentation::Relative: + reg.idx[i].offset = 0; + reg.idx[i].relReg = &m_indices.at(m_indexId); + + this->decodeRegister(code, + m_indices.at(m_indexId++), + DxbcScalarType::Sint32); + break; + + case DxbcOperandIndexRepresentation::Imm32Relative: + reg.idx[i].offset = static_cast(code.read()); + reg.idx[i].relReg = &m_indices.at(m_indexId); + + this->decodeRegister(code, + m_indices.at(m_indexId++), + DxbcScalarType::Sint32); + break; + + default: + Logger::warn(str::format( + "DxbcDecodeContext: Unhandled index representation: ", + repr)); + } + } + } + + + void DxbcDecodeContext::decodeRegister(DxbcCodeSlice& code, DxbcRegister& reg, DxbcScalarType type) { + const uint32_t token = code.read(); + + reg.type = static_cast(bit::extract(token, 12, 19)); + reg.dataType = type; + reg.modifiers = 0; + reg.idxDim = 0; + + for (uint32_t i = 0; i < DxbcMaxRegIndexDim; i++) { + reg.idx[i].relReg = nullptr; + reg.idx[i].offset = 0; + } + + this->decodeComponentSelection(reg, token); + this->decodeOperandExtensions(code, reg, token); + this->decodeOperandImmediates(code, reg); + this->decodeOperandIndex(code, reg, token); + } + + + void DxbcDecodeContext::decodeImm32(DxbcCodeSlice& code, DxbcImmediate& imm, DxbcScalarType type) { + imm.u32 = code.read(); + } + + + void DxbcDecodeContext::decodeOperand(DxbcCodeSlice& code, const DxbcInstOperandFormat& format) { + switch (format.kind) { + case DxbcOperandKind::DstReg: { + const uint32_t operandId = m_instruction.dstCount++; + this->decodeRegister(code, m_dstOperands.at(operandId), format.type); + } break; + + case DxbcOperandKind::SrcReg: { + const uint32_t operandId = m_instruction.srcCount++; + this->decodeRegister(code, m_srcOperands.at(operandId), format.type); + } break; + + case DxbcOperandKind::Imm32: { + const uint32_t operandId = m_instruction.immCount++; + this->decodeImm32(code, m_immOperands.at(operandId), format.type); + } break; + + default: + throw DxvkError("DxbcDecodeContext: Invalid operand format"); + } + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxbc/dxbc_decoder.h b/utils/dxvk-1.10.3/src/dxbc/dxbc_decoder.h new file mode 100644 index 00000000000..72b4e961f3e --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxbc/dxbc_decoder.h @@ -0,0 +1,504 @@ +#pragma once + +#include + +#include "dxbc_common.h" +#include "dxbc_decoder.h" +#include "dxbc_defs.h" +#include "dxbc_enums.h" +#include "dxbc_names.h" + +namespace dxvk { + + constexpr size_t DxbcMaxRegIndexDim = 3; + + struct DxbcRegister; + + /** + * \brief Source operand modifiers + * + * These are applied after loading + * an operand register. + */ + enum class DxbcRegModifier : uint32_t { + Neg = 0, + Abs = 1, + }; + + using DxbcRegModifiers = Flags; + + + /** + * \brief Constant buffer binding + * + * Stores information required to + * access a constant buffer. + */ + struct DxbcConstantBuffer { + uint32_t varId = 0; + uint32_t size = 0; + }; + + /** + * \brief Sampler binding + * + * Stores a sampler variable that can be + * used together with a texture resource. + */ + struct DxbcSampler { + uint32_t varId = 0; + uint32_t typeId = 0; + }; + + + /** + * \brief Image type information + */ + struct DxbcImageInfo { + spv::Dim dim = spv::Dim1D; + uint32_t array = 0; + uint32_t ms = 0; + uint32_t sampled = 0; + VkImageViewType vtype = VK_IMAGE_VIEW_TYPE_MAX_ENUM; + }; + + + /** + * \brief Shader resource binding + * + * Stores a resource variable + * and associated type IDs. + */ + struct DxbcShaderResource { + DxbcResourceType type = DxbcResourceType::Typed; + DxbcImageInfo imageInfo; + uint32_t varId = 0; + uint32_t specId = 0; + DxbcScalarType sampledType = DxbcScalarType::Float32; + uint32_t sampledTypeId = 0; + uint32_t imageTypeId = 0; + uint32_t colorTypeId = 0; + uint32_t depthTypeId = 0; + uint32_t structStride = 0; + uint32_t structAlign = 0; + }; + + + /** + * \brief Unordered access binding + * + * Stores a resource variable that is provided + * by a UAV, as well as associated type IDs. + */ + struct DxbcUav { + DxbcResourceType type = DxbcResourceType::Typed; + DxbcImageInfo imageInfo; + uint32_t varId = 0; + uint32_t ctrId = 0; + uint32_t specId = 0; + DxbcScalarType sampledType = DxbcScalarType::Float32; + uint32_t sampledTypeId = 0; + uint32_t imageTypeId = 0; + uint32_t structStride = 0; + uint32_t structAlign = 0; + }; + + + /** + * \brief Component swizzle + * + * Maps vector components to + * other vector components. + */ + class DxbcRegSwizzle { + + public: + + DxbcRegSwizzle() { } + DxbcRegSwizzle(uint32_t x, uint32_t y, uint32_t z, uint32_t w) + : m_mask((x << 0) | (y << 2) | (z << 4) | (w << 6)) { } + + uint32_t operator [] (uint32_t id) const { + return (m_mask >> (id + id)) & 0x3; + } + + bool operator == (const DxbcRegSwizzle& other) const { return m_mask == other.m_mask; } + bool operator != (const DxbcRegSwizzle& other) const { return m_mask != other.m_mask; } + + private: + + uint8_t m_mask = 0; + + }; + + + /** + * \brief Component mask + * + * Enables access to certain + * subset of vector components. + */ + class DxbcRegMask { + + public: + + DxbcRegMask() { } + DxbcRegMask(uint32_t mask) : m_mask(mask) { } + DxbcRegMask(bool x, bool y, bool z, bool w) + : m_mask((x ? 0x1 : 0) | (y ? 0x2 : 0) + | (z ? 0x4 : 0) | (w ? 0x8 : 0)) { } + + bool operator [] (uint32_t id) const { + return (m_mask >> id) & 1; + } + + uint32_t popCount() const { + const uint8_t n[16] = { 0, 1, 1, 2, 1, 2, 2, 3, + 1, 2, 2, 3, 2, 3, 3, 4 }; + return n[m_mask & 0xF]; + } + + uint32_t firstSet() const { + const uint8_t n[16] = { 4, 0, 1, 0, 2, 0, 1, 0, + 3, 0, 1, 0, 2, 0, 1, 0 }; + return n[m_mask & 0xF]; + } + + uint32_t minComponents() const { + const uint8_t n[16] = { 0, 1, 2, 2, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4 }; + return n[m_mask & 0xF]; + } + + bool operator == (const DxbcRegMask& other) const { return m_mask == other.m_mask; } + bool operator != (const DxbcRegMask& other) const { return m_mask != other.m_mask; } + + DxbcRegMask& operator |= (const DxbcRegMask& other) { + m_mask |= other.m_mask; + return *this; + } + + static DxbcRegMask firstN(uint32_t n) { + return DxbcRegMask(n >= 1, n >= 2, n >= 3, n >= 4); + } + + static DxbcRegMask select(uint32_t n) { + return DxbcRegMask(n == 0, n == 1, n == 2, n == 3); + } + + std::string maskString() const { + std::string out = ""; + out += (m_mask & 0x1) ? "x" : ""; + out += (m_mask & 0x2) ? "y" : ""; + out += (m_mask & 0x4) ? "z" : ""; + out += (m_mask & 0x8) ? "w" : ""; + return out; + } + + operator bool () const { + return m_mask != 0; + } + + private: + + uint8_t m_mask = 0; + + }; + + + /** + * \brief System value mapping + * + * Maps a system value to a given set of + * components of an input or output register. + */ + struct DxbcSvMapping { + uint32_t regId; + DxbcRegMask regMask; + DxbcSystemValue sv; + }; + + + struct DxbcRegIndex { + DxbcRegister* relReg; + int32_t offset; + }; + + + /** + * \brief Instruction operand + */ + struct DxbcRegister { + DxbcOperandType type; + DxbcScalarType dataType; + DxbcComponentCount componentCount; + + uint32_t idxDim; + DxbcRegIndex idx[DxbcMaxRegIndexDim]; + + DxbcRegMask mask; + DxbcRegSwizzle swizzle; + DxbcRegModifiers modifiers; + + union { + uint32_t u32_4[4]; + uint32_t u32_1; + } imm; + }; + + + /** + * \brief Instruction result modifiers + * + * Modifiers that are applied + * to all destination operands. + */ + struct DxbcOpModifiers { + bool saturate; + bool precise; + }; + + + /** + * \brief Opcode controls + * + * Instruction-specific controls. Usually, + * only one of the members will be valid. + */ + class DxbcShaderOpcodeControls { + + public: + + DxbcShaderOpcodeControls() + : m_bits(0) { } + + DxbcShaderOpcodeControls(uint32_t bits) + : m_bits(bits) { } + + DxbcInstructionReturnType returnType() const { + return DxbcInstructionReturnType(bit::extract(m_bits, 11, 11)); + } + + DxbcGlobalFlags globalFlags() const { + return DxbcGlobalFlags(bit::extract(m_bits, 11, 14)); + } + + DxbcZeroTest zeroTest() const { + return DxbcZeroTest(bit::extract(m_bits, 18, 18)); + } + + DxbcSyncFlags syncFlags() const { + return DxbcSyncFlags(bit::extract(m_bits, 11, 14)); + } + + DxbcResourceDim resourceDim() const { + return DxbcResourceDim(bit::extract(m_bits, 11, 15)); + } + + DxbcResinfoType resinfoType() const { + return DxbcResinfoType(bit::extract(m_bits, 11, 12)); + } + + DxbcInterpolationMode interpolation() const { + return DxbcInterpolationMode(bit::extract(m_bits, 11, 14)); + } + + DxbcSamplerMode samplerMode() const { + return DxbcSamplerMode(bit::extract(m_bits, 11, 14)); + } + + DxbcPrimitiveTopology primitiveTopology() const { + return DxbcPrimitiveTopology(bit::extract(m_bits, 11, 17)); + } + + DxbcPrimitive primitive() const { + return DxbcPrimitive(bit::extract(m_bits, 11, 16)); + } + + DxbcTessDomain tessDomain() const { + return DxbcTessDomain(bit::extract(m_bits, 11, 12)); + } + + DxbcTessOutputPrimitive tessOutputPrimitive() const { + return DxbcTessOutputPrimitive(bit::extract(m_bits, 11, 13)); + } + + DxbcTessPartitioning tessPartitioning() const { + return DxbcTessPartitioning(bit::extract(m_bits, 11, 13)); + } + + DxbcUavFlags uavFlags() const { + return DxbcUavFlags(bit::extract(m_bits, 16, 16)); + } + + DxbcConstantBufferAccessType accessType() const { + return DxbcConstantBufferAccessType(bit::extract(m_bits, 11, 11)); + } + + uint32_t controlPointCount() const { + return bit::extract(m_bits, 11, 16); + } + + bool precise() const { + return bit::extract(m_bits, 19, 22) != 0; + } + + private: + + uint32_t m_bits; + + }; + + + /** + * \brief Sample controls + * + * Constant texel offset with + * values raning from -8 to 7. + */ + struct DxbcShaderSampleControls { + int u, v, w; + }; + + + /** + * \brief Immediate value + * + * Immediate argument represented either + * as a 32-bit or 64-bit unsigned integer, + * or a 32-bit or 32-bit floating point number. + */ + union DxbcImmediate { + float f32; + double f64; + uint32_t u32; + uint64_t u64; + }; + + + /** + * \brief Shader instruction + * + * Note that this structure may store pointer to + * external structures, such as the original code + * buffer. This is safe to use if and only if: + * - The \ref DxbcDecodeContext that created it + * still exists and was not moved + * - The code buffer that was being decoded + * still exists and was not moved. + */ + struct DxbcShaderInstruction { + DxbcOpcode op; + DxbcInstClass opClass; + DxbcOpModifiers modifiers; + DxbcShaderOpcodeControls controls; + DxbcShaderSampleControls sampleControls; + + uint32_t dstCount; + uint32_t srcCount; + uint32_t immCount; + + const DxbcRegister* dst; + const DxbcRegister* src; + const DxbcImmediate* imm; + + DxbcCustomDataClass customDataType; + uint32_t customDataSize; + const uint32_t* customData; + }; + + + /** + * \brief DXBC code slice + * + * Convenient pointer pair that allows + * reading the code word stream safely. + */ + class DxbcCodeSlice { + + public: + + DxbcCodeSlice( + const uint32_t* ptr, + const uint32_t* end) + : m_ptr(ptr), m_end(end) { } + + const uint32_t* ptrAt(uint32_t id) const; + + uint32_t at(uint32_t id) const; + uint32_t read(); + + DxbcCodeSlice take(uint32_t n) const; + DxbcCodeSlice skip(uint32_t n) const; + + bool atEnd() const { + return m_ptr == m_end; + } + + private: + + const uint32_t* m_ptr = nullptr; + const uint32_t* m_end = nullptr; + + }; + + + /** + * \brief Decode context + * + * Stores data that is required to decode a single + * instruction. This data is not persistent, so it + * should be forwarded to the compiler right away. + */ + class DxbcDecodeContext { + + public: + + /** + * \brief Retrieves current instruction + * + * This is only valid after a call to \ref decode. + * \returns Reference to last decoded instruction + */ + const DxbcShaderInstruction& getInstruction() const { + return m_instruction; + } + + /** + * \brief Decodes an instruction + * + * This also advances the given code slice by the + * number of dwords consumed by the instruction. + * \param [in] code Code slice + */ + void decodeInstruction(DxbcCodeSlice& code); + + private: + + DxbcShaderInstruction m_instruction; + + std::array m_dstOperands; + std::array m_srcOperands; + std::array m_immOperands; + std::array m_indices; + + // Index into the indices array. Used when decoding + // instruction operands with relative indexing. + uint32_t m_indexId = 0; + + void decodeCustomData(DxbcCodeSlice code); + void decodeOperation(DxbcCodeSlice code); + + void decodeComponentSelection(DxbcRegister& reg, uint32_t token); + void decodeOperandExtensions(DxbcCodeSlice& code, DxbcRegister& reg, uint32_t token); + void decodeOperandImmediates(DxbcCodeSlice& code, DxbcRegister& reg); + void decodeOperandIndex(DxbcCodeSlice& code, DxbcRegister& reg, uint32_t token); + + void decodeRegister(DxbcCodeSlice& code, DxbcRegister& reg, DxbcScalarType type); + void decodeImm32(DxbcCodeSlice& code, DxbcImmediate& imm, DxbcScalarType type); + + void decodeOperand(DxbcCodeSlice& code, const DxbcInstOperandFormat& format); + + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxbc/dxbc_defs.cpp b/utils/dxvk-1.10.3/src/dxbc/dxbc_defs.cpp new file mode 100644 index 00000000000..4e383d8a659 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxbc/dxbc_defs.cpp @@ -0,0 +1,1117 @@ +#include "dxbc_defs.h" + +namespace dxvk { + + const std::array g_instructionFormats = {{ + /* Add */ + { 3, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* And */ + { 3, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* Break */ + { 0, DxbcInstClass::ControlFlow }, + /* Breakc */ + { 1, DxbcInstClass::ControlFlow, { + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* Call */ + { 1, DxbcInstClass::ControlFlow, { + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* Callc */ + { 2, DxbcInstClass::ControlFlow, { + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* Case */ + { 1, DxbcInstClass::ControlFlow, { + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* Continue */ + { 0, DxbcInstClass::ControlFlow }, + /* Continuec */ + { 1, DxbcInstClass::ControlFlow, { + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* Cut */ + { 0, DxbcInstClass::GeometryEmit }, + /* Default */ + { 0, DxbcInstClass::ControlFlow }, + /* DerivRtx */ + { 2, DxbcInstClass::VectorDeriv, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* DerivRty */ + { 2, DxbcInstClass::VectorDeriv, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* Discard */ + { 1, DxbcInstClass::ControlFlow, { + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* Div */ + { 3, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* Dp2 */ + { 3, DxbcInstClass::VectorDot, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* Dp3 */ + { 3, DxbcInstClass::VectorDot, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* Dp4 */ + { 3, DxbcInstClass::VectorDot, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* Else */ + { 0, DxbcInstClass::ControlFlow }, + /* Emit */ + { 0, DxbcInstClass::GeometryEmit }, + /* EmitThenCut */ + { 0, DxbcInstClass::GeometryEmit }, + /* EndIf */ + { 0, DxbcInstClass::ControlFlow }, + /* EndLoop */ + { 0, DxbcInstClass::ControlFlow }, + /* EndSwitch */ + { 0, DxbcInstClass::ControlFlow }, + /* Eq */ + { 3, DxbcInstClass::VectorCmp, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* Exp */ + { 2, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* Frc */ + { 2, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* FtoI */ + { 2, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* FtoU */ + { 2, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* Ge */ + { 3, DxbcInstClass::VectorCmp, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* IAdd */ + { 3, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + } }, + /* If */ + { 1, DxbcInstClass::ControlFlow, { + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* IEq */ + { 3, DxbcInstClass::VectorCmp, { + { DxbcOperandKind::DstReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + } }, + /* IGe */ + { 3, DxbcInstClass::VectorCmp, { + { DxbcOperandKind::DstReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + } }, + /* ILt */ + { 3, DxbcInstClass::VectorCmp, { + { DxbcOperandKind::DstReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + } }, + /* IMad */ + { 4, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + } }, + /* IMax */ + { 3, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + } }, + /* IMin */ + { 3, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + } }, + /* IMul */ + { 4, DxbcInstClass::VectorImul, { + { DxbcOperandKind::DstReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::DstReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + } }, + /* INe */ + { 3, DxbcInstClass::VectorCmp, { + { DxbcOperandKind::DstReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + } }, + /* INeg */ + { 2, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + } }, + /* IShl */ + { 3, DxbcInstClass::VectorShift, { + { DxbcOperandKind::DstReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* IShr */ + { 3, DxbcInstClass::VectorShift, { + { DxbcOperandKind::DstReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* ItoF */ + { 2, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + } }, + /* Label */ + { 1, DxbcInstClass::ControlFlow, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + } }, + /* Ld */ + { 3, DxbcInstClass::TextureFetch, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* LdMs */ + { 4, DxbcInstClass::TextureFetch, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + } }, + /* Log */ + { 2, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* Loop */ + { 0, DxbcInstClass::ControlFlow }, + /* Lt */ + { 3, DxbcInstClass::VectorCmp, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* Mad */ + { 4, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* Min */ + { 3, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* Max */ + { 3, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* CustomData */ + { 0, DxbcInstClass::CustomData }, + /* Mov */ + { 2, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* Movc */ + { 4, DxbcInstClass::VectorCmov, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* Mul */ + { 3, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* Ne */ + { 3, DxbcInstClass::VectorCmp, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* Nop */ + { 0, DxbcInstClass::NoOperation }, + /* Not */ + { 2, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* Or */ + { 3, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* ResInfo */ + { 3, DxbcInstClass::TextureQuery, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* Ret */ + { 0, DxbcInstClass::ControlFlow }, + /* Retc */ + { 1, DxbcInstClass::ControlFlow, { + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* RoundNe */ + { 2, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* RoundNi */ + { 2, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* RoundPi */ + { 2, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* RoundZ */ + { 2, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* Rsq */ + { 2, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* Sample */ + { 4, DxbcInstClass::TextureSample, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* SampleC */ + { 5, DxbcInstClass::TextureSample, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* SampleClz */ + { 5, DxbcInstClass::TextureSample, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* SampleL */ + { 5, DxbcInstClass::TextureSample, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* SampleD */ + { 6, DxbcInstClass::TextureSample, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* SampleB */ + { 5, DxbcInstClass::TextureSample, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* Sqrt */ + { 2, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* Switch */ + { 1, DxbcInstClass::ControlFlow, { + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* SinCos */ + { 3, DxbcInstClass::VectorSinCos, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* UDiv */ + { 4, DxbcInstClass::VectorIdiv, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* ULt */ + { 3, DxbcInstClass::VectorCmp, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* UGe */ + { 3, DxbcInstClass::VectorCmp, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* UMul */ + { 4, DxbcInstClass::VectorImul, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* UMad */ + { 4, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* UMax */ + { 3, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* UMin */ + { 3, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* UShr */ + { 3, DxbcInstClass::VectorShift, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* UtoF */ + { 2, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* Xor */ + { 3, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* DclResource */ + { 2, DxbcInstClass::Declaration, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::Imm32, DxbcScalarType::Uint32 }, + } }, + /* DclConstantBuffer */ + { 1, DxbcInstClass::Declaration, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + } }, + /* DclSampler */ + { 1, DxbcInstClass::Declaration, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + } }, + /* DclIndexRange */ + { 2, DxbcInstClass::Declaration, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::Imm32, DxbcScalarType::Uint32 }, + } }, + /* DclGsOutputPrimitiveTopology */ + { 0, DxbcInstClass::Declaration }, + /* DclGsInputPrimitive */ + { 0, DxbcInstClass::Declaration }, + /* DclMaxOutputVertexCount */ + { 1, DxbcInstClass::Declaration, { + { DxbcOperandKind::Imm32, DxbcScalarType::Uint32 }, + } }, + /* DclInput */ + { 1, DxbcInstClass::Declaration, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + } }, + /* DclInputSgv */ + { 2, DxbcInstClass::Declaration, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::Imm32, DxbcScalarType::Uint32 }, + } }, + /* DclInputSiv */ + { 2, DxbcInstClass::Declaration, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::Imm32, DxbcScalarType::Uint32 }, + } }, + /* DclInputPs */ + { 1, DxbcInstClass::Declaration, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + } }, + /* DclInputPsSgv */ + { 2, DxbcInstClass::Declaration, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::Imm32, DxbcScalarType::Uint32 }, + } }, + /* DclInputPsSiv */ + { 2, DxbcInstClass::Declaration, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::Imm32, DxbcScalarType::Uint32 }, + } }, + /* DclOutput */ + { 1, DxbcInstClass::Declaration, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + } }, + /* DclOutputSgv */ + { 2, DxbcInstClass::Declaration, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::Imm32, DxbcScalarType::Uint32 }, + } }, + /* DclOutputSiv */ + { 2, DxbcInstClass::Declaration, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::Imm32, DxbcScalarType::Uint32 }, + } }, + /* DclTemps */ + { 1, DxbcInstClass::Declaration, { + { DxbcOperandKind::Imm32, DxbcScalarType::Uint32 }, + } }, + /* DclIndexableTemp */ + { 3, DxbcInstClass::Declaration, { + { DxbcOperandKind::Imm32, DxbcScalarType::Uint32 }, + { DxbcOperandKind::Imm32, DxbcScalarType::Uint32 }, + { DxbcOperandKind::Imm32, DxbcScalarType::Uint32 }, + } }, + /* DclGlobalFlags */ + { 0, DxbcInstClass::Declaration }, + /* Reserved0 */ + { 0, DxbcInstClass::Undefined }, + /* Lod */ + { 4, DxbcInstClass::TextureQueryLod, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* Gather4 */ + { 4, DxbcInstClass::TextureGather, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* SamplePos */ + { 3, DxbcInstClass::TextureQueryMsPos, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* SampleInfo */ + { 2, DxbcInstClass::TextureQueryMs, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* Reserved1 */ + { }, + /* HsDecls */ + { 0, DxbcInstClass::HullShaderPhase }, + /* HsControlPointPhase */ + { 0, DxbcInstClass::HullShaderPhase }, + /* HsForkPhase */ + { 0, DxbcInstClass::HullShaderPhase }, + /* HsJoinPhase */ + { 0, DxbcInstClass::HullShaderPhase }, + /* EmitStream */ + { 1, DxbcInstClass::GeometryEmit, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + } }, + /* CutStream */ + { 1, DxbcInstClass::GeometryEmit, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + } }, + /* EmitThenCutStream */ + { 1, DxbcInstClass::GeometryEmit, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + } }, + /* InterfaceCall */ + { }, + /* BufInfo */ + { 2, DxbcInstClass::BufferQuery, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + } }, + /* DerivRtxCoarse */ + { 2, DxbcInstClass::VectorDeriv, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* DerivRtxFine */ + { 2, DxbcInstClass::VectorDeriv, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* DerivRtyCoarse */ + { 2, DxbcInstClass::VectorDeriv, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* DerivRtyFine */ + { 2, DxbcInstClass::VectorDeriv, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* Gather4C */ + { 5, DxbcInstClass::TextureGather, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* Gather4Po */ + { 5, DxbcInstClass::TextureGather, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* Gather4PoC */ + { 6, DxbcInstClass::TextureGather, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* Rcp */ + { 2, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* F32toF16 */ + { 2, DxbcInstClass::ConvertFloat16, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* F16toF32 */ + { 2, DxbcInstClass::ConvertFloat16, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* UAddc */ + { }, + /* USubb */ + { }, + /* CountBits */ + { 2, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* FirstBitHi */ + { 2, DxbcInstClass::BitScan, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* FirstBitLo */ + { 2, DxbcInstClass::BitScan, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* FirstBitShi */ + { 2, DxbcInstClass::BitScan, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* UBfe */ + { 4, DxbcInstClass::BitExtract, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* IBfe */ + { 4, DxbcInstClass::BitExtract, { + { DxbcOperandKind::DstReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + } }, + /* Bfi */ + { 5, DxbcInstClass::BitInsert, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* BfRev */ + { 2, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* Swapc */ + { 5, DxbcInstClass::VectorCmov, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* DclStream */ + { 1, DxbcInstClass::Declaration, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + } }, + /* DclFunctionBody */ + { }, + /* DclFunctionTable */ + { }, + /* DclInterface */ + { }, + /* DclInputControlPointCount */ + { 0, DxbcInstClass::Declaration }, + /* DclOutputControlPointCount */ + { 0, DxbcInstClass::Declaration }, + /* DclTessDomain */ + { 0, DxbcInstClass::Declaration }, + /* DclTessPartitioning */ + { 0, DxbcInstClass::Declaration }, + /* DclTessOutputPrimitive */ + { 0, DxbcInstClass::Declaration }, + /* DclHsMaxTessFactor */ + { 1, DxbcInstClass::Declaration, { + { DxbcOperandKind::Imm32, DxbcScalarType::Float32 }, + } }, + /* DclHsForkPhaseInstanceCount */ + { 1, DxbcInstClass::HullShaderInstCnt, { + { DxbcOperandKind::Imm32, DxbcScalarType::Uint32 }, + } }, + /* DclHsJoinPhaseInstanceCount */ + { 1, DxbcInstClass::HullShaderInstCnt, { + { DxbcOperandKind::Imm32, DxbcScalarType::Uint32 }, + } }, + /* DclThreadGroup */ + { 3, DxbcInstClass::Declaration, { + { DxbcOperandKind::Imm32, DxbcScalarType::Uint32 }, + { DxbcOperandKind::Imm32, DxbcScalarType::Uint32 }, + { DxbcOperandKind::Imm32, DxbcScalarType::Uint32 }, + } }, + /* DclUavTyped */ + { 2, DxbcInstClass::Declaration, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::Imm32, DxbcScalarType::Uint32 }, + } }, + /* DclUavRaw */ + { 1, DxbcInstClass::Declaration, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + } }, + /* DclUavStructured */ + { 2, DxbcInstClass::Declaration, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::Imm32, DxbcScalarType::Uint32 }, + } }, + /* DclThreadGroupSharedMemoryRaw */ + { 2, DxbcInstClass::Declaration, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::Imm32, DxbcScalarType::Uint32 }, + } }, + /* DclThreadGroupSharedMemoryStructured */ + { 3, DxbcInstClass::Declaration, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::Imm32, DxbcScalarType::Uint32 }, + { DxbcOperandKind::Imm32, DxbcScalarType::Uint32 }, + } }, + /* DclResourceRaw */ + { 1, DxbcInstClass::Declaration, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + } }, + /* DclResourceStructured */ + { 2, DxbcInstClass::Declaration, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::Imm32, DxbcScalarType::Uint32 }, + } }, + /* LdUavTyped */ + { 3, DxbcInstClass::TypedUavLoad, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* StoreUavTyped */ + { 3, DxbcInstClass::TypedUavStore, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* LdRaw */ + { 3, DxbcInstClass::BufferLoad, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* StoreRaw */ + { 3, DxbcInstClass::BufferStore, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* LdStructured */ + { 4, DxbcInstClass::BufferLoad, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* StoreStructured */ + { 4, DxbcInstClass::BufferStore, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* AtomicAnd */ + { 3, DxbcInstClass::Atomic, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* AtomicOr */ + { 3, DxbcInstClass::Atomic, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* AtomicXor */ + { 3, DxbcInstClass::Atomic, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* AtomicCmpStore */ + { 4, DxbcInstClass::Atomic, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* AtomicIAdd */ + { 3, DxbcInstClass::Atomic, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* AtomicIMax */ + { 3, DxbcInstClass::Atomic, { + { DxbcOperandKind::DstReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + } }, + /* AtomicIMin */ + { 3, DxbcInstClass::Atomic, { + { DxbcOperandKind::DstReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + } }, + /* AtomicUMax */ + { 3, DxbcInstClass::Atomic, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* AtomicUMin */ + { 3, DxbcInstClass::Atomic, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* ImmAtomicAlloc */ + { 2, DxbcInstClass::AtomicCounter, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + } }, + /* ImmAtomicConsume */ + { 2, DxbcInstClass::AtomicCounter, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + } }, + /* ImmAtomicIAdd */ + { 4, DxbcInstClass::Atomic, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* ImmAtomicAnd */ + { 4, DxbcInstClass::Atomic, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* ImmAtomicOr */ + { 4, DxbcInstClass::Atomic, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* ImmAtomicXor */ + { 4, DxbcInstClass::Atomic, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* ImmAtomicExch */ + { 4, DxbcInstClass::Atomic, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* ImmAtomicCmpExch */ + { 5, DxbcInstClass::Atomic, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* ImmAtomicIMax */ + { 4, DxbcInstClass::Atomic, { + { DxbcOperandKind::DstReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::DstReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + } }, + /* ImmAtomicIMin */ + { 4, DxbcInstClass::Atomic, { + { DxbcOperandKind::DstReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::DstReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + } }, + /* ImmAtomicUMax */ + { 4, DxbcInstClass::Atomic, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* ImmAtomicUMin */ + { 4, DxbcInstClass::Atomic, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* Sync */ + { 0, DxbcInstClass::Barrier }, + /* DAdd */ + { 3, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float64 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float64 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float64 }, + } }, + /* DMax */ + { 3, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float64 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float64 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float64 }, + } }, + /* DMin */ + { 3, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float64 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float64 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float64 }, + } }, + /* DMul */ + { 3, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float64 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float64 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float64 }, + } }, + /* DEq */ + { 3, DxbcInstClass::VectorCmp, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float64 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float64 }, + } }, + /* DGe */ + { 3, DxbcInstClass::VectorCmp, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float64 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float64 }, + } }, + /* DLt */ + { 3, DxbcInstClass::VectorCmp, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float64 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float64 }, + } }, + /* DNe */ + { 3, DxbcInstClass::VectorCmp, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float64 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float64 }, + } }, + /* DMov */ + { 2, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float64 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float64 }, + } }, + /* DMovc */ + { 4, DxbcInstClass::VectorCmov, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float64 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float64 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float64 }, + } }, + /* DtoF */ + { 2, DxbcInstClass::ConvertFloat64, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float64 }, + } }, + /* FtoD */ + { 2, DxbcInstClass::ConvertFloat64, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float64 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* EvalSnapped */ + { 3, DxbcInstClass::Interpolate, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* EvalSampleIndex */ + { 3, DxbcInstClass::Interpolate, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + } }, + /* EvalCentroid */ + { 2, DxbcInstClass::Interpolate, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, + /* DclGsInstanceCount */ + { 1, DxbcInstClass::Declaration, { + { DxbcOperandKind::Imm32, DxbcScalarType::Uint32 }, + } }, + /* Abort */ + { }, + /* DebugBreak */ + { }, + /* ReservedBegin11_1 */ + { }, + /* DDiv */ + { 3, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float64 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float64 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float64 }, + } }, + /* DFma */ + { 4, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float64 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float64 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float64 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float64 }, + } }, + /* DRcp */ + { 2, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float64 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float64 }, + } }, + /* Msad */ + { 4, DxbcInstClass::VectorMsad, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + /* DtoI */ + { 2, DxbcInstClass::ConvertFloat64, { + { DxbcOperandKind::DstReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float64 }, + } }, + /* DtoU */ + { 2, DxbcInstClass::ConvertFloat64, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float64 }, + } }, + /* ItoD */ + { 2, DxbcInstClass::ConvertFloat64, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float64 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + } }, + /* UtoD */ + { 2, DxbcInstClass::ConvertFloat64, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float64 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, + }}; + + + DxbcInstFormat dxbcInstructionFormat(DxbcOpcode opcode) { + const uint32_t idx = static_cast(opcode); + + return (idx < g_instructionFormats.size()) + ? g_instructionFormats.at(idx) + : DxbcInstFormat(); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxbc/dxbc_defs.h b/utils/dxvk-1.10.3/src/dxbc/dxbc_defs.h new file mode 100644 index 00000000000..decd76707d7 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxbc/dxbc_defs.h @@ -0,0 +1,103 @@ +#pragma once + +#include "dxbc_enums.h" + +namespace dxvk { + + constexpr size_t DxbcMaxInterfaceRegs = 32; + constexpr size_t DxbcMaxOperandCount = 8; + + /** + * \brief Operand kind + * + * In the instruction format definition, this specified + * whether an operand uses an actual operand token, or + * whether it is stored as an immediate value. + */ + enum class DxbcOperandKind { + DstReg, ///< Destination register + SrcReg, ///< Source register + Imm32, ///< Constant number + }; + + /** + * \brief Instruction class + * + * Instructions with a similar format are grouped into + * instruction classes in order to make implementing + * new instructions easier. + */ + enum class DxbcInstClass { + Declaration, ///< Interface or resource declaration + CustomData, ///< Immediate constant buffer + ControlFlow, ///< Control flow instructions + GeometryEmit, ///< Special geometry shader instructions + Atomic, ///< Atomic operations + AtomicCounter, ///< Atomic counter operations + Barrier, ///< Execution or memory barrier + BitExtract, ///< Bit field extract operations + BitInsert, ///< Bit field insert operations + BitScan, ///< Bit scan operations + BufferQuery, ///< Buffer query instruction + BufferLoad, ///< Structured or raw buffer load + BufferStore, ///< Structured or raw buffer store + ConvertFloat16, ///< 16-bit float packing/unpacking + ConvertFloat64, ///< 64-bit float conversion + HullShaderPhase, ///< Hull shader phase declaration + HullShaderInstCnt, ///< Hull shader phase instance count + Interpolate, ///< Input attribute interpolation + NoOperation, ///< The most useful instruction class + TextureQuery, ///< Texture query instruction + TextureQueryLod, ///< Texture LOD query instruction + TextureQueryMs, ///< Multisample texture query + TextureQueryMsPos, ///< Sample position query + TextureFetch, ///< Texture fetch instruction + TextureGather, ///< Texture gather instruction + TextureSample, ///< Texture sampling instruction + TypedUavLoad, ///< Typed UAV load + TypedUavStore, ///< Typed UAV store + VectorAlu, ///< Component-wise vector instructions + VectorCmov, ///< Component-wise conditional move + VectorCmp, ///< Component-wise vector comparison + VectorDeriv, ///< Vector derivatives + VectorDot, ///< Dot product instruction + VectorIdiv, ///< Component-wise integer division + VectorImul, ///< Component-wise integer multiplication + VectorMsad, ///< Component-wise sum of absolute difference + VectorShift, ///< Bit shift operations on vectors + VectorSinCos, ///< Sine and Cosine instruction + Undefined, ///< Instruction code not defined + }; + + /** + * \brief Instruction operand format + * + * Stores the kind and the expected data type + * of an operand. Used when parsing instructions. + */ + struct DxbcInstOperandFormat { + DxbcOperandKind kind; + DxbcScalarType type; + }; + + /** + * \brief Instruction format + * + * Defines the instruction class as well as + * the format of the insttruction operands. + */ + struct DxbcInstFormat { + uint32_t operandCount = 0; + DxbcInstClass instructionClass = DxbcInstClass::Undefined; + DxbcInstOperandFormat operands[DxbcMaxOperandCount]; + }; + + /** + * \brief Retrieves instruction format info + * + * \param [in] opcode The opcode to retrieve + * \returns Instruction format info + */ + DxbcInstFormat dxbcInstructionFormat(DxbcOpcode opcode); + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxbc/dxbc_enums.h b/utils/dxvk-1.10.3/src/dxbc/dxbc_enums.h new file mode 100644 index 00000000000..214780d07e5 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxbc/dxbc_enums.h @@ -0,0 +1,635 @@ +#pragma once + +#include "dxbc_include.h" + +namespace dxvk { + + /** + * \brief Instruction code listing + */ + enum class DxbcOpcode : uint32_t { + Add = 0, + And = 1, + Break = 2, + Breakc = 3, + Call = 4, + Callc = 5, + Case = 6, + Continue = 7, + Continuec = 8, + Cut = 9, + Default = 10, + DerivRtx = 11, + DerivRty = 12, + Discard = 13, + Div = 14, + Dp2 = 15, + Dp3 = 16, + Dp4 = 17, + Else = 18, + Emit = 19, + EmitThenCut = 20, + EndIf = 21, + EndLoop = 22, + EndSwitch = 23, + Eq = 24, + Exp = 25, + Frc = 26, + FtoI = 27, + FtoU = 28, + Ge = 29, + IAdd = 30, + If = 31, + IEq = 32, + IGe = 33, + ILt = 34, + IMad = 35, + IMax = 36, + IMin = 37, + IMul = 38, + INe = 39, + INeg = 40, + IShl = 41, + IShr = 42, + ItoF = 43, + Label = 44, + Ld = 45, + LdMs = 46, + Log = 47, + Loop = 48, + Lt = 49, + Mad = 50, + Min = 51, + Max = 52, + CustomData = 53, + Mov = 54, + Movc = 55, + Mul = 56, + Ne = 57, + Nop = 58, + Not = 59, + Or = 60, + ResInfo = 61, + Ret = 62, + Retc = 63, + RoundNe = 64, + RoundNi = 65, + RoundPi = 66, + RoundZ = 67, + Rsq = 68, + Sample = 69, + SampleC = 70, + SampleClz = 71, + SampleL = 72, + SampleD = 73, + SampleB = 74, + Sqrt = 75, + Switch = 76, + SinCos = 77, + UDiv = 78, + ULt = 79, + UGe = 80, + UMul = 81, + UMad = 82, + UMax = 83, + UMin = 84, + UShr = 85, + UtoF = 86, + Xor = 87, + DclResource = 88, + DclConstantBuffer = 89, + DclSampler = 90, + DclIndexRange = 91, + DclGsOutputPrimitiveTopology = 92, + DclGsInputPrimitive = 93, + DclMaxOutputVertexCount = 94, + DclInput = 95, + DclInputSgv = 96, + DclInputSiv = 97, + DclInputPs = 98, + DclInputPsSgv = 99, + DclInputPsSiv = 100, + DclOutput = 101, + DclOutputSgv = 102, + DclOutputSiv = 103, + DclTemps = 104, + DclIndexableTemp = 105, + DclGlobalFlags = 106, + Reserved0 = 107, + Lod = 108, + Gather4 = 109, + SamplePos = 110, + SampleInfo = 111, + Reserved1 = 112, + HsDecls = 113, + HsControlPointPhase = 114, + HsForkPhase = 115, + HsJoinPhase = 116, + EmitStream = 117, + CutStream = 118, + EmitThenCutStream = 119, + InterfaceCall = 120, + BufInfo = 121, + DerivRtxCoarse = 122, + DerivRtxFine = 123, + DerivRtyCoarse = 124, + DerivRtyFine = 125, + Gather4C = 126, + Gather4Po = 127, + Gather4PoC = 128, + Rcp = 129, + F32toF16 = 130, + F16toF32 = 131, + UAddc = 132, + USubb = 133, + CountBits = 134, + FirstBitHi = 135, + FirstBitLo = 136, + FirstBitShi = 137, + UBfe = 138, + IBfe = 139, + Bfi = 140, + BfRev = 141, + Swapc = 142, + DclStream = 143, + DclFunctionBody = 144, + DclFunctionTable = 145, + DclInterface = 146, + DclInputControlPointCount = 147, + DclOutputControlPointCount = 148, + DclTessDomain = 149, + DclTessPartitioning = 150, + DclTessOutputPrimitive = 151, + DclHsMaxTessFactor = 152, + DclHsForkPhaseInstanceCount = 153, + DclHsJoinPhaseInstanceCount = 154, + DclThreadGroup = 155, + DclUavTyped = 156, + DclUavRaw = 157, + DclUavStructured = 158, + DclThreadGroupSharedMemoryRaw = 159, + DclThreadGroupSharedMemoryStructured = 160, + DclResourceRaw = 161, + DclResourceStructured = 162, + LdUavTyped = 163, + StoreUavTyped = 164, + LdRaw = 165, + StoreRaw = 166, + LdStructured = 167, + StoreStructured = 168, + AtomicAnd = 169, + AtomicOr = 170, + AtomicXor = 171, + AtomicCmpStore = 172, + AtomicIAdd = 173, + AtomicIMax = 174, + AtomicIMin = 175, + AtomicUMax = 176, + AtomicUMin = 177, + ImmAtomicAlloc = 178, + ImmAtomicConsume = 179, + ImmAtomicIAdd = 180, + ImmAtomicAnd = 181, + ImmAtomicOr = 182, + ImmAtomicXor = 183, + ImmAtomicExch = 184, + ImmAtomicCmpExch = 185, + ImmAtomicIMax = 186, + ImmAtomicIMin = 187, + ImmAtomicUMax = 188, + ImmAtomicUMin = 189, + Sync = 190, + DAdd = 191, + DMax = 192, + DMin = 193, + DMul = 194, + DEq = 195, + DGe = 196, + DLt = 197, + DNe = 198, + DMov = 199, + DMovc = 200, + DtoF = 201, + FtoD = 202, + EvalSnapped = 203, + EvalSampleIndex = 204, + EvalCentroid = 205, + DclGsInstanceCount = 206, + Abort = 207, + DebugBreak = 208, + ReservedBegin11_1 = 209, + DDiv = 210, + DFma = 211, + DRcp = 212, + Msad = 213, + DtoI = 214, + DtoU = 215, + ItoD = 216, + UtoD = 217, + }; + + + /** + * \brief Extended opcode + */ + enum class DxbcExtOpcode : uint32_t { + Empty = 0, + SampleControls = 1, + ResourceDim = 2, + ResourceReturnType = 3, + }; + + + /** + * \brief Operand type + * + * Selects the 'register file' from which + * to retrieve an operand's value. + */ + enum class DxbcOperandType : uint32_t { + Temp = 0, + Input = 1, + Output = 2, + IndexableTemp = 3, + Imm32 = 4, + Imm64 = 5, + Sampler = 6, + Resource = 7, + ConstantBuffer = 8, + ImmediateConstantBuffer = 9, + Label = 10, + InputPrimitiveId = 11, + OutputDepth = 12, + Null = 13, + Rasterizer = 14, + OutputCoverageMask = 15, + Stream = 16, + FunctionBody = 17, + FunctionTable = 18, + Interface = 19, + FunctionInput = 20, + FunctionOutput = 21, + OutputControlPointId = 22, + InputForkInstanceId = 23, + InputJoinInstanceId = 24, + InputControlPoint = 25, + OutputControlPoint = 26, + InputPatchConstant = 27, + InputDomainPoint = 28, + ThisPointer = 29, + UnorderedAccessView = 30, + ThreadGroupSharedMemory = 31, + InputThreadId = 32, + InputThreadGroupId = 33, + InputThreadIdInGroup = 34, + InputCoverageMask = 35, + InputThreadIndexInGroup = 36, + InputGsInstanceId = 37, + OutputDepthGe = 38, + OutputDepthLe = 39, + CycleCounter = 40, + OutputStencilRef = 41, + }; + + + /** + * \brief Number of components + * + * Used by operands to determine whether the + * operand has one, four or zero components. + */ + enum class DxbcComponentCount : uint32_t { + Component0 = 0, + Component1 = 1, + Component4 = 2, + }; + + + /** + * \brief Component selection mode + * + * When an operand has four components, the + * component selection mode deterines which + * components are used for the operation. + */ + enum class DxbcRegMode : uint32_t { + Mask = 0, + Swizzle = 1, + Select1 = 2, + }; + + + /** + * \brief Index representation + * + * Determines how an operand + * register index is stored. + */ + enum class DxbcOperandIndexRepresentation : uint32_t { + Imm32 = 0, + Imm64 = 1, + Relative = 2, + Imm32Relative = 3, + Imm64Relative = 4, + }; + + + /** + * \brief Extended operand type + */ + enum class DxbcOperandExt : uint32_t { + OperandModifier = 1, + }; + + + /** + * \brief Resource dimension + * The type of a resource. + */ + enum class DxbcResourceDim : uint32_t { + Unknown = 0, + Buffer = 1, + Texture1D = 2, + Texture2D = 3, + Texture2DMs = 4, + Texture3D = 5, + TextureCube = 6, + Texture1DArr = 7, + Texture2DArr = 8, + Texture2DMsArr = 9, + TextureCubeArr = 10, + RawBuffer = 11, + StructuredBuffer = 12, + }; + + + /** + * \brief Resource return type + * Data type for resource read ops. + */ + enum class DxbcResourceReturnType : uint32_t { + Unorm = 1, + Snorm = 2, + Sint = 3, + Uint = 4, + Float = 5, + Mixed = 6, /// ? + Double = 7, + Continued = 8, /// ? + Unused = 9, /// ? + }; + + + /** + * \brief Register component type + * Data type of a register component. + */ + enum class DxbcRegisterComponentType : uint32_t { + Unknown = 0, + Uint32 = 1, + Sint32 = 2, + Float32 = 3, + }; + + + /** + * \brief Instruction return type + */ + enum class DxbcInstructionReturnType : uint32_t { + Float = 0, + Uint = 1, + }; + + + enum class DxbcSystemValue : uint32_t { + None = 0, + Position = 1, + ClipDistance = 2, + CullDistance = 3, + RenderTargetId = 4, + ViewportId = 5, + VertexId = 6, + PrimitiveId = 7, + InstanceId = 8, + IsFrontFace = 9, + SampleIndex = 10, + FinalQuadUeq0EdgeTessFactor = 11, + FinalQuadVeq0EdgeTessFactor = 12, + FinalQuadUeq1EdgeTessFactor = 13, + FinalQuadVeq1EdgeTessFactor = 14, + FinalQuadUInsideTessFactor = 15, + FinalQuadVInsideTessFactor = 16, + FinalTriUeq0EdgeTessFactor = 17, + FinalTriVeq0EdgeTessFactor = 18, + FinalTriWeq0EdgeTessFactor = 19, + FinalTriInsideTessFactor = 20, + FinalLineDetailTessFactor = 21, + FinalLineDensityTessFactor = 22, + Target = 64, + Depth = 65, + Coverage = 66, + DepthGe = 67, + DepthLe = 68 + }; + + + enum class DxbcInterpolationMode : uint32_t { + Undefined = 0, + Constant = 1, + Linear = 2, + LinearCentroid = 3, + LinearNoPerspective = 4, + LinearNoPerspectiveCentroid = 5, + LinearSample = 6, + LinearNoPerspectiveSample = 7, + }; + + + enum class DxbcGlobalFlag : uint32_t { + RefactoringAllowed = 0, + DoublePrecision = 1, + EarlyFragmentTests = 2, + RawStructuredBuffers = 3, + }; + + using DxbcGlobalFlags = Flags; + + enum class DxbcZeroTest : uint32_t { + TestZ = 0, + TestNz = 1, + }; + + enum class DxbcResinfoType : uint32_t { + Float = 0, + RcpFloat = 1, + Uint = 2, + }; + + enum class DxbcSyncFlag : uint32_t { + ThreadsInGroup = 0, + ThreadGroupSharedMemory = 1, + UavMemoryGroup = 2, + UavMemoryGlobal = 3, + }; + + using DxbcSyncFlags = Flags; + + + /** + * \brief Geometry shader input primitive + */ + enum class DxbcPrimitive : uint32_t { + Undefined = 0, + Point = 1, + Line = 2, + Triangle = 3, + LineAdj = 6, + TriangleAdj = 7, + Patch1 = 8, + Patch2 = 9, + Patch3 = 10, + Patch4 = 11, + Patch5 = 12, + Patch6 = 13, + Patch7 = 14, + Patch8 = 15, + Patch9 = 16, + Patch10 = 17, + Patch11 = 18, + Patch12 = 19, + Patch13 = 20, + Patch14 = 21, + Patch15 = 22, + Patch16 = 23, + Patch17 = 24, + Patch18 = 25, + Patch19 = 26, + Patch20 = 27, + Patch21 = 28, + Patch22 = 29, + Patch23 = 30, + Patch24 = 31, + Patch25 = 32, + Patch26 = 33, + Patch27 = 34, + Patch28 = 35, + Patch29 = 36, + Patch30 = 37, + Patch31 = 38, + Patch32 = 39, + }; + + + /** + * \brief Geometry shader output topology + */ + enum class DxbcPrimitiveTopology : uint32_t { + Undefined = 0, + PointList = 1, + LineList = 2, + LineStrip = 3, + TriangleList = 4, + TriangleStrip = 5, + LineListAdj = 10, + LineStripAdj = 11, + TriangleListAdj = 12, + TriangleStripAdj = 13, + }; + + + /** + * \brief Sampler operation mode + */ + enum class DxbcSamplerMode : uint32_t { + Default = 0, + Comparison = 1, + Mono = 2, + }; + + + /** + * \brief Scalar value type + * + * Enumerates possible register component + * types. Scalar types are represented as + * a one-component vector type. + */ + enum class DxbcScalarType : uint32_t { + Uint32 = 0, + Uint64 = 1, + Sint32 = 2, + Sint64 = 3, + Float32 = 4, + Float64 = 5, + Bool = 6, + }; + + + /** + * \brief Tessellator domain + */ + enum class DxbcTessDomain : uint32_t { + Undefined = 0, + Isolines = 1, + Triangles = 2, + Quads = 3, + }; + + /** + * \brief Tessellator partitioning + */ + enum class DxbcTessPartitioning : uint32_t { + Undefined = 0, + Integer = 1, + Pow2 = 2, + FractOdd = 3, + FractEven = 4, + }; + + /** + * \brief UAV definition flags + */ + enum class DxbcUavFlag : uint32_t { + GloballyCoherent = 0, + }; + + using DxbcUavFlags = Flags; + + /** + * \brief Tessellator output primitive + */ + enum class DxbcTessOutputPrimitive : uint32_t { + Undefined = 0, + Point = 1, + Line = 2, + TriangleCw = 3, + TriangleCcw = 4, + }; + + /** + * \brief Custom data class + * + * Stores which type of custom data is + * referenced by the instruction. + */ + enum class DxbcCustomDataClass : uint32_t { + Comment = 0, + DebugInfo = 1, + Opaque = 2, + ImmConstBuf = 3, + }; + + + enum class DxbcResourceType : uint32_t { + Typed = 0, + Raw = 1, + Structured = 2, + }; + + + enum class DxbcConstantBufferAccessType : uint32_t { + StaticallyIndexed = 0, + DynamicallyIndexed = 1, + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxbc/dxbc_header.cpp b/utils/dxvk-1.10.3/src/dxbc/dxbc_header.cpp new file mode 100644 index 00000000000..9b5f6989572 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxbc/dxbc_header.cpp @@ -0,0 +1,30 @@ +#include "dxbc_header.h" + +namespace dxvk { + + DxbcHeader::DxbcHeader(DxbcReader& reader) { + // FourCC at the start of the file, must be 'DXBC' + DxbcTag fourcc = reader.readTag(); + + if (fourcc != "DXBC") + throw DxvkError("DxbcHeader::DxbcHeader: Invalid fourcc, expected 'DXBC'"); + + // Stuff we don't actually need to store + reader.skip(4 * sizeof(uint32_t)); // Check sum + reader.skip(1 * sizeof(uint32_t)); // Constant 1 + reader.skip(1 * sizeof(uint32_t)); // Bytecode length + + // Number of chunks in the file + uint32_t chunkCount = reader.readu32(); + + // Chunk offsets are stored immediately after + for (uint32_t i = 0; i < chunkCount; i++) + m_chunkOffsets.push_back(reader.readu32()); + } + + + DxbcHeader::~DxbcHeader() { + + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxbc/dxbc_header.h b/utils/dxvk-1.10.3/src/dxbc/dxbc_header.h new file mode 100644 index 00000000000..8eca0d499c1 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxbc/dxbc_header.h @@ -0,0 +1,48 @@ +#pragma once + +#include + +#include "dxbc_reader.h" + +namespace dxvk { + + /** + * \brief DXBC header + * + * Stores information about the shader file itself + * and the data chunks stored inside the file. + */ + class DxbcHeader { + + public: + + DxbcHeader(DxbcReader& reader); + ~DxbcHeader(); + + /** + * \brief Number of chunks + * \returns Chunk count + */ + uint32_t numChunks() const { + return m_chunkOffsets.size(); + } + + /** + * \brief Chunk offset + * + * Retrieves the offset of a chunk, in + * bytes, from the start of the file. + * \param [in] chunkId Chunk index + * \returns Byte offset of that chunk + */ + uint32_t chunkOffset(uint32_t chunkId) const { + return m_chunkOffsets.at(chunkId); + } + + private: + + std::vector m_chunkOffsets; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxbc/dxbc_include.h b/utils/dxvk-1.10.3/src/dxbc/dxbc_include.h new file mode 100644 index 00000000000..9b86ade63bd --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxbc/dxbc_include.h @@ -0,0 +1,18 @@ +#pragma once + +#include "../dxvk/dxvk_shader.h" + +#include "../util/com/com_guid.h" +#include "../util/com/com_object.h" +#include "../util/com/com_pointer.h" + +#include "../util/log/log.h" +#include "../util/log/log_debug.h" + +#include "../util/rc/util_rc.h" +#include "../util/rc/util_rc_ptr.h" + +#include "../util/util_bit.h" +#include "../util/util_enum.h" +#include "../util/util_error.h" +#include "../util/util_string.h" diff --git a/utils/dxvk-1.10.3/src/dxbc/dxbc_modinfo.h b/utils/dxvk-1.10.3/src/dxbc/dxbc_modinfo.h new file mode 100644 index 00000000000..13e733dde2b --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxbc/dxbc_modinfo.h @@ -0,0 +1,59 @@ +#pragma once + +#include "dxbc_options.h" + +namespace dxvk { + + /** + * \brief Tessellation info + * + * Stores the maximum tessellation factor + * to export from tessellation shaders. + */ + struct DxbcTessInfo { + float maxTessFactor; + }; + + /** + * \brief Xfb capture entry + * + * Stores an output variable to capture, + * as well as the buffer to write it to. + */ + struct DxbcXfbEntry { + const char* semanticName; + uint32_t semanticIndex; + uint32_t componentIndex; + uint32_t componentCount; + uint32_t streamId; + uint32_t bufferId; + uint32_t offset; + }; + + /** + * \brief Xfb info + * + * Stores capture entries and output buffer + * strides. This structure must only be + * defined if \c entryCount is non-zero. + */ + struct DxbcXfbInfo { + uint32_t entryCount; + DxbcXfbEntry entries[128]; + uint32_t strides[4]; + int32_t rasterizedStream; + }; + + /** + * \brief Shader module info + * + * Stores information which may affect shader compilation. + * This data can be supplied by the client API implementation. + */ + struct DxbcModuleInfo { + DxbcOptions options; + DxbcTessInfo* tess; + DxbcXfbInfo* xfb; + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxbc/dxbc_module.cpp b/utils/dxvk-1.10.3/src/dxbc/dxbc_module.cpp new file mode 100644 index 00000000000..d406bf2925a --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxbc/dxbc_module.cpp @@ -0,0 +1,116 @@ +#include "dxbc_analysis.h" +#include "dxbc_compiler.h" +#include "dxbc_module.h" + +namespace dxvk { + + DxbcModule::DxbcModule(DxbcReader& reader) + : m_header(reader) { + for (uint32_t i = 0; i < m_header.numChunks(); i++) { + + // The chunk tag is stored at the beginning of each chunk + auto chunkReader = reader.clone(m_header.chunkOffset(i)); + auto tag = chunkReader.readTag(); + + // The chunk size follows right after the four-character + // code. This does not include the eight bytes that are + // consumed by the FourCC and chunk length entry. + auto chunkLength = chunkReader.readu32(); + + chunkReader = chunkReader.clone(8); + chunkReader = chunkReader.resize(chunkLength); + + if ((tag == "SHDR") || (tag == "SHEX")) + m_shexChunk = new DxbcShex(chunkReader); + + if ((tag == "ISGN") || (tag == "ISG1")) + m_isgnChunk = new DxbcIsgn(chunkReader, tag); + + if ((tag == "OSGN") || (tag == "OSG5") || (tag == "OSG1")) + m_osgnChunk = new DxbcIsgn(chunkReader, tag); + + if ((tag == "PCSG") || (tag == "PSG1")) + m_psgnChunk = new DxbcIsgn(chunkReader, tag); + } + } + + + DxbcModule::~DxbcModule() { + + } + + + Rc DxbcModule::compile( + const DxbcModuleInfo& moduleInfo, + const std::string& fileName) const { + if (m_shexChunk == nullptr) + throw DxvkError("DxbcModule::compile: No SHDR/SHEX chunk"); + + DxbcAnalysisInfo analysisInfo; + + DxbcAnalyzer analyzer(moduleInfo, + m_shexChunk->programInfo(), + m_isgnChunk, m_osgnChunk, + m_psgnChunk, analysisInfo); + + this->runAnalyzer(analyzer, m_shexChunk->slice()); + + DxbcCompiler compiler( + fileName, moduleInfo, + m_shexChunk->programInfo(), + m_isgnChunk, m_osgnChunk, + m_psgnChunk, analysisInfo); + + this->runCompiler(compiler, m_shexChunk->slice()); + + return compiler.finalize(); + } + + + Rc DxbcModule::compilePassthroughShader( + const DxbcModuleInfo& moduleInfo, + const std::string& fileName) const { + if (m_shexChunk == nullptr) + throw DxvkError("DxbcModule::compile: No SHDR/SHEX chunk"); + + DxbcAnalysisInfo analysisInfo; + + DxbcCompiler compiler( + fileName, moduleInfo, + DxbcProgramType::GeometryShader, + m_osgnChunk, m_osgnChunk, + m_psgnChunk, analysisInfo); + + compiler.processXfbPassthrough(); + return compiler.finalize(); + } + + + void DxbcModule::runAnalyzer( + DxbcAnalyzer& analyzer, + DxbcCodeSlice slice) const { + DxbcDecodeContext decoder; + + while (!slice.atEnd()) { + decoder.decodeInstruction(slice); + + analyzer.processInstruction( + decoder.getInstruction()); + } + } + + + void DxbcModule::runCompiler( + DxbcCompiler& compiler, + DxbcCodeSlice slice) const { + DxbcDecodeContext decoder; + + while (!slice.atEnd()) { + decoder.decodeInstruction(slice); + + compiler.processInstruction( + decoder.getInstruction()); + } + } + +} diff --git a/utils/dxvk-1.10.3/src/dxbc/dxbc_module.h b/utils/dxvk-1.10.3/src/dxbc/dxbc_module.h new file mode 100644 index 00000000000..d785d959950 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxbc/dxbc_module.h @@ -0,0 +1,96 @@ +#pragma once + +#include "../dxvk/dxvk_shader.h" + +#include "dxbc_chunk_isgn.h" +#include "dxbc_chunk_shex.h" +#include "dxbc_header.h" +#include "dxbc_modinfo.h" +#include "dxbc_reader.h" + +// References used for figuring out DXBC: +// - https://github.com/tgjones/slimshader-cpp +// - Wine + +namespace dxvk { + + class DxbcAnalyzer; + class DxbcCompiler; + + /** + * \brief DXBC shader module + * + * Reads the DXBC byte code and extracts information + * about the resource bindings and the instruction + * stream. A module can then be compiled to SPIR-V. + */ + class DxbcModule { + + public: + + DxbcModule(DxbcReader& reader); + ~DxbcModule(); + + /** + * \brief Shader type + * \returns Shader type + */ + DxbcProgramInfo programInfo() const { + return m_shexChunk->programInfo(); + } + + /** + * \brief Input and output signature chunks + * + * Parts of the D3D11 API need access to the + * input or output signature of the shader. + */ + Rc isgn() const { return m_isgnChunk; } + Rc osgn() const { return m_osgnChunk; } + + /** + * \brief Compiles DXBC shader to SPIR-V module + * + * \param [in] moduleInfo DXBC module info + * \param [in] fileName File name, will be added to + * the compiled SPIR-V for debugging purposes. + * \returns The compiled shader object + */ + Rc compile( + const DxbcModuleInfo& moduleInfo, + const std::string& fileName) const; + + /** + * \brief Compiles a pass-through geometry shader + * + * Applications can pass a vertex shader to create + * a geometry shader with stream output. In this + * case, we have to create a passthrough geometry + * shader, which operates in point to point mode. + * \param [in] moduleInfo DXBC module info + * \param [in] fileName SPIR-V shader name + */ + Rc compilePassthroughShader( + const DxbcModuleInfo& moduleInfo, + const std::string& fileName) const; + + private: + + DxbcHeader m_header; + + Rc m_isgnChunk; + Rc m_osgnChunk; + Rc m_psgnChunk; + Rc m_shexChunk; + + void runAnalyzer( + DxbcAnalyzer& analyzer, + DxbcCodeSlice slice) const; + + void runCompiler( + DxbcCompiler& compiler, + DxbcCodeSlice slice) const; + + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxbc/dxbc_names.cpp b/utils/dxvk-1.10.3/src/dxbc/dxbc_names.cpp new file mode 100644 index 00000000000..c6a00eccca0 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxbc/dxbc_names.cpp @@ -0,0 +1,445 @@ +#include "dxbc_names.h" + +namespace dxvk { + + std::ostream& operator << (std::ostream& os, DxbcOpcode e) { + switch (e) { + ENUM_NAME(DxbcOpcode::Add); + ENUM_NAME(DxbcOpcode::And); + ENUM_NAME(DxbcOpcode::Break); + ENUM_NAME(DxbcOpcode::Breakc); + ENUM_NAME(DxbcOpcode::Call); + ENUM_NAME(DxbcOpcode::Callc); + ENUM_NAME(DxbcOpcode::Case); + ENUM_NAME(DxbcOpcode::Continue); + ENUM_NAME(DxbcOpcode::Continuec); + ENUM_NAME(DxbcOpcode::Cut); + ENUM_NAME(DxbcOpcode::Default); + ENUM_NAME(DxbcOpcode::DerivRtx); + ENUM_NAME(DxbcOpcode::DerivRty); + ENUM_NAME(DxbcOpcode::Discard); + ENUM_NAME(DxbcOpcode::Div); + ENUM_NAME(DxbcOpcode::Dp2); + ENUM_NAME(DxbcOpcode::Dp3); + ENUM_NAME(DxbcOpcode::Dp4); + ENUM_NAME(DxbcOpcode::Else); + ENUM_NAME(DxbcOpcode::Emit); + ENUM_NAME(DxbcOpcode::EmitThenCut); + ENUM_NAME(DxbcOpcode::EndIf); + ENUM_NAME(DxbcOpcode::EndLoop); + ENUM_NAME(DxbcOpcode::EndSwitch); + ENUM_NAME(DxbcOpcode::Eq); + ENUM_NAME(DxbcOpcode::Exp); + ENUM_NAME(DxbcOpcode::Frc); + ENUM_NAME(DxbcOpcode::FtoI); + ENUM_NAME(DxbcOpcode::FtoU); + ENUM_NAME(DxbcOpcode::Ge); + ENUM_NAME(DxbcOpcode::IAdd); + ENUM_NAME(DxbcOpcode::If); + ENUM_NAME(DxbcOpcode::IEq); + ENUM_NAME(DxbcOpcode::IGe); + ENUM_NAME(DxbcOpcode::ILt); + ENUM_NAME(DxbcOpcode::IMad); + ENUM_NAME(DxbcOpcode::IMax); + ENUM_NAME(DxbcOpcode::IMin); + ENUM_NAME(DxbcOpcode::IMul); + ENUM_NAME(DxbcOpcode::INe); + ENUM_NAME(DxbcOpcode::INeg); + ENUM_NAME(DxbcOpcode::IShl); + ENUM_NAME(DxbcOpcode::IShr); + ENUM_NAME(DxbcOpcode::ItoF); + ENUM_NAME(DxbcOpcode::Label); + ENUM_NAME(DxbcOpcode::Ld); + ENUM_NAME(DxbcOpcode::LdMs); + ENUM_NAME(DxbcOpcode::Log); + ENUM_NAME(DxbcOpcode::Loop); + ENUM_NAME(DxbcOpcode::Lt); + ENUM_NAME(DxbcOpcode::Mad); + ENUM_NAME(DxbcOpcode::Min); + ENUM_NAME(DxbcOpcode::Max); + ENUM_NAME(DxbcOpcode::CustomData); + ENUM_NAME(DxbcOpcode::Mov); + ENUM_NAME(DxbcOpcode::Movc); + ENUM_NAME(DxbcOpcode::Mul); + ENUM_NAME(DxbcOpcode::Ne); + ENUM_NAME(DxbcOpcode::Nop); + ENUM_NAME(DxbcOpcode::Not); + ENUM_NAME(DxbcOpcode::Or); + ENUM_NAME(DxbcOpcode::ResInfo); + ENUM_NAME(DxbcOpcode::Ret); + ENUM_NAME(DxbcOpcode::Retc); + ENUM_NAME(DxbcOpcode::RoundNe); + ENUM_NAME(DxbcOpcode::RoundNi); + ENUM_NAME(DxbcOpcode::RoundPi); + ENUM_NAME(DxbcOpcode::RoundZ); + ENUM_NAME(DxbcOpcode::Rsq); + ENUM_NAME(DxbcOpcode::Sample); + ENUM_NAME(DxbcOpcode::SampleC); + ENUM_NAME(DxbcOpcode::SampleClz); + ENUM_NAME(DxbcOpcode::SampleL); + ENUM_NAME(DxbcOpcode::SampleD); + ENUM_NAME(DxbcOpcode::SampleB); + ENUM_NAME(DxbcOpcode::Sqrt); + ENUM_NAME(DxbcOpcode::Switch); + ENUM_NAME(DxbcOpcode::SinCos); + ENUM_NAME(DxbcOpcode::UDiv); + ENUM_NAME(DxbcOpcode::ULt); + ENUM_NAME(DxbcOpcode::UGe); + ENUM_NAME(DxbcOpcode::UMul); + ENUM_NAME(DxbcOpcode::UMad); + ENUM_NAME(DxbcOpcode::UMax); + ENUM_NAME(DxbcOpcode::UMin); + ENUM_NAME(DxbcOpcode::UShr); + ENUM_NAME(DxbcOpcode::UtoF); + ENUM_NAME(DxbcOpcode::Xor); + ENUM_NAME(DxbcOpcode::DclResource); + ENUM_NAME(DxbcOpcode::DclConstantBuffer); + ENUM_NAME(DxbcOpcode::DclSampler); + ENUM_NAME(DxbcOpcode::DclIndexRange); + ENUM_NAME(DxbcOpcode::DclGsOutputPrimitiveTopology); + ENUM_NAME(DxbcOpcode::DclGsInputPrimitive); + ENUM_NAME(DxbcOpcode::DclMaxOutputVertexCount); + ENUM_NAME(DxbcOpcode::DclInput); + ENUM_NAME(DxbcOpcode::DclInputSgv); + ENUM_NAME(DxbcOpcode::DclInputSiv); + ENUM_NAME(DxbcOpcode::DclInputPs); + ENUM_NAME(DxbcOpcode::DclInputPsSgv); + ENUM_NAME(DxbcOpcode::DclInputPsSiv); + ENUM_NAME(DxbcOpcode::DclOutput); + ENUM_NAME(DxbcOpcode::DclOutputSgv); + ENUM_NAME(DxbcOpcode::DclOutputSiv); + ENUM_NAME(DxbcOpcode::DclTemps); + ENUM_NAME(DxbcOpcode::DclIndexableTemp); + ENUM_NAME(DxbcOpcode::DclGlobalFlags); + ENUM_NAME(DxbcOpcode::Reserved0); + ENUM_NAME(DxbcOpcode::Lod); + ENUM_NAME(DxbcOpcode::Gather4); + ENUM_NAME(DxbcOpcode::SamplePos); + ENUM_NAME(DxbcOpcode::SampleInfo); + ENUM_NAME(DxbcOpcode::Reserved1); + ENUM_NAME(DxbcOpcode::HsDecls); + ENUM_NAME(DxbcOpcode::HsControlPointPhase); + ENUM_NAME(DxbcOpcode::HsForkPhase); + ENUM_NAME(DxbcOpcode::HsJoinPhase); + ENUM_NAME(DxbcOpcode::EmitStream); + ENUM_NAME(DxbcOpcode::CutStream); + ENUM_NAME(DxbcOpcode::EmitThenCutStream); + ENUM_NAME(DxbcOpcode::InterfaceCall); + ENUM_NAME(DxbcOpcode::BufInfo); + ENUM_NAME(DxbcOpcode::DerivRtxCoarse); + ENUM_NAME(DxbcOpcode::DerivRtxFine); + ENUM_NAME(DxbcOpcode::DerivRtyCoarse); + ENUM_NAME(DxbcOpcode::DerivRtyFine); + ENUM_NAME(DxbcOpcode::Gather4C); + ENUM_NAME(DxbcOpcode::Gather4Po); + ENUM_NAME(DxbcOpcode::Gather4PoC); + ENUM_NAME(DxbcOpcode::Rcp); + ENUM_NAME(DxbcOpcode::F32toF16); + ENUM_NAME(DxbcOpcode::F16toF32); + ENUM_NAME(DxbcOpcode::UAddc); + ENUM_NAME(DxbcOpcode::USubb); + ENUM_NAME(DxbcOpcode::CountBits); + ENUM_NAME(DxbcOpcode::FirstBitHi); + ENUM_NAME(DxbcOpcode::FirstBitLo); + ENUM_NAME(DxbcOpcode::FirstBitShi); + ENUM_NAME(DxbcOpcode::UBfe); + ENUM_NAME(DxbcOpcode::IBfe); + ENUM_NAME(DxbcOpcode::Bfi); + ENUM_NAME(DxbcOpcode::BfRev); + ENUM_NAME(DxbcOpcode::Swapc); + ENUM_NAME(DxbcOpcode::DclStream); + ENUM_NAME(DxbcOpcode::DclFunctionBody); + ENUM_NAME(DxbcOpcode::DclFunctionTable); + ENUM_NAME(DxbcOpcode::DclInterface); + ENUM_NAME(DxbcOpcode::DclInputControlPointCount); + ENUM_NAME(DxbcOpcode::DclOutputControlPointCount); + ENUM_NAME(DxbcOpcode::DclTessDomain); + ENUM_NAME(DxbcOpcode::DclTessPartitioning); + ENUM_NAME(DxbcOpcode::DclTessOutputPrimitive); + ENUM_NAME(DxbcOpcode::DclHsMaxTessFactor); + ENUM_NAME(DxbcOpcode::DclHsForkPhaseInstanceCount); + ENUM_NAME(DxbcOpcode::DclHsJoinPhaseInstanceCount); + ENUM_NAME(DxbcOpcode::DclThreadGroup); + ENUM_NAME(DxbcOpcode::DclUavTyped); + ENUM_NAME(DxbcOpcode::DclUavRaw); + ENUM_NAME(DxbcOpcode::DclUavStructured); + ENUM_NAME(DxbcOpcode::DclThreadGroupSharedMemoryRaw); + ENUM_NAME(DxbcOpcode::DclThreadGroupSharedMemoryStructured); + ENUM_NAME(DxbcOpcode::DclResourceRaw); + ENUM_NAME(DxbcOpcode::DclResourceStructured); + ENUM_NAME(DxbcOpcode::LdUavTyped); + ENUM_NAME(DxbcOpcode::StoreUavTyped); + ENUM_NAME(DxbcOpcode::LdRaw); + ENUM_NAME(DxbcOpcode::StoreRaw); + ENUM_NAME(DxbcOpcode::LdStructured); + ENUM_NAME(DxbcOpcode::StoreStructured); + ENUM_NAME(DxbcOpcode::AtomicAnd); + ENUM_NAME(DxbcOpcode::AtomicOr); + ENUM_NAME(DxbcOpcode::AtomicXor); + ENUM_NAME(DxbcOpcode::AtomicCmpStore); + ENUM_NAME(DxbcOpcode::AtomicIAdd); + ENUM_NAME(DxbcOpcode::AtomicIMax); + ENUM_NAME(DxbcOpcode::AtomicIMin); + ENUM_NAME(DxbcOpcode::AtomicUMax); + ENUM_NAME(DxbcOpcode::AtomicUMin); + ENUM_NAME(DxbcOpcode::ImmAtomicAlloc); + ENUM_NAME(DxbcOpcode::ImmAtomicConsume); + ENUM_NAME(DxbcOpcode::ImmAtomicIAdd); + ENUM_NAME(DxbcOpcode::ImmAtomicAnd); + ENUM_NAME(DxbcOpcode::ImmAtomicOr); + ENUM_NAME(DxbcOpcode::ImmAtomicXor); + ENUM_NAME(DxbcOpcode::ImmAtomicExch); + ENUM_NAME(DxbcOpcode::ImmAtomicCmpExch); + ENUM_NAME(DxbcOpcode::ImmAtomicIMax); + ENUM_NAME(DxbcOpcode::ImmAtomicIMin); + ENUM_NAME(DxbcOpcode::ImmAtomicUMax); + ENUM_NAME(DxbcOpcode::ImmAtomicUMin); + ENUM_NAME(DxbcOpcode::Sync); + ENUM_NAME(DxbcOpcode::DAdd); + ENUM_NAME(DxbcOpcode::DMax); + ENUM_NAME(DxbcOpcode::DMin); + ENUM_NAME(DxbcOpcode::DMul); + ENUM_NAME(DxbcOpcode::DEq); + ENUM_NAME(DxbcOpcode::DGe); + ENUM_NAME(DxbcOpcode::DLt); + ENUM_NAME(DxbcOpcode::DNe); + ENUM_NAME(DxbcOpcode::DMov); + ENUM_NAME(DxbcOpcode::DMovc); + ENUM_NAME(DxbcOpcode::DtoF); + ENUM_NAME(DxbcOpcode::FtoD); + ENUM_NAME(DxbcOpcode::EvalSnapped); + ENUM_NAME(DxbcOpcode::EvalSampleIndex); + ENUM_NAME(DxbcOpcode::EvalCentroid); + ENUM_NAME(DxbcOpcode::DclGsInstanceCount); + ENUM_DEFAULT(e); + } + } + + + std::ostream& operator << (std::ostream& os, DxbcExtOpcode e) { + switch (e) { + ENUM_NAME(DxbcExtOpcode::Empty); + ENUM_NAME(DxbcExtOpcode::SampleControls); + ENUM_NAME(DxbcExtOpcode::ResourceDim); + ENUM_NAME(DxbcExtOpcode::ResourceReturnType); + ENUM_DEFAULT(e); + } + } + + + std::ostream& operator << (std::ostream& os, DxbcOperandType e) { + switch (e) { + ENUM_NAME(DxbcOperandType::Temp); + ENUM_NAME(DxbcOperandType::Input); + ENUM_NAME(DxbcOperandType::Output); + ENUM_NAME(DxbcOperandType::IndexableTemp); + ENUM_NAME(DxbcOperandType::Imm32); + ENUM_NAME(DxbcOperandType::Imm64); + ENUM_NAME(DxbcOperandType::Sampler); + ENUM_NAME(DxbcOperandType::Resource); + ENUM_NAME(DxbcOperandType::ConstantBuffer); + ENUM_NAME(DxbcOperandType::ImmediateConstantBuffer); + ENUM_NAME(DxbcOperandType::Label); + ENUM_NAME(DxbcOperandType::InputPrimitiveId); + ENUM_NAME(DxbcOperandType::OutputDepth); + ENUM_NAME(DxbcOperandType::Null); + ENUM_NAME(DxbcOperandType::Rasterizer); + ENUM_NAME(DxbcOperandType::OutputCoverageMask); + ENUM_NAME(DxbcOperandType::Stream); + ENUM_NAME(DxbcOperandType::FunctionBody); + ENUM_NAME(DxbcOperandType::FunctionTable); + ENUM_NAME(DxbcOperandType::Interface); + ENUM_NAME(DxbcOperandType::FunctionInput); + ENUM_NAME(DxbcOperandType::FunctionOutput); + ENUM_NAME(DxbcOperandType::OutputControlPointId); + ENUM_NAME(DxbcOperandType::InputForkInstanceId); + ENUM_NAME(DxbcOperandType::InputJoinInstanceId); + ENUM_NAME(DxbcOperandType::InputControlPoint); + ENUM_NAME(DxbcOperandType::OutputControlPoint); + ENUM_NAME(DxbcOperandType::InputPatchConstant); + ENUM_NAME(DxbcOperandType::InputDomainPoint); + ENUM_NAME(DxbcOperandType::ThisPointer); + ENUM_NAME(DxbcOperandType::UnorderedAccessView); + ENUM_NAME(DxbcOperandType::ThreadGroupSharedMemory); + ENUM_NAME(DxbcOperandType::InputThreadId); + ENUM_NAME(DxbcOperandType::InputThreadGroupId); + ENUM_NAME(DxbcOperandType::InputThreadIdInGroup); + ENUM_NAME(DxbcOperandType::InputCoverageMask); + ENUM_NAME(DxbcOperandType::InputThreadIndexInGroup); + ENUM_NAME(DxbcOperandType::InputGsInstanceId); + ENUM_NAME(DxbcOperandType::OutputDepthGe); + ENUM_NAME(DxbcOperandType::OutputDepthLe); + ENUM_NAME(DxbcOperandType::CycleCounter); + ENUM_DEFAULT(e); + } + } + + + std::ostream& operator << (std::ostream& os, dxvk::DxbcOperandExt e) { + switch (e) { + ENUM_NAME(DxbcOperandExt::OperandModifier); + ENUM_DEFAULT(e); + } + } + + + std::ostream& operator << (std::ostream& os, DxbcComponentCount e) { + switch (e) { + ENUM_NAME(DxbcComponentCount::Component0); + ENUM_NAME(DxbcComponentCount::Component1); + ENUM_NAME(DxbcComponentCount::Component4); + ENUM_DEFAULT(e); + } + } + + + std::ostream& operator << (std::ostream& os, DxbcRegMode e) { + switch (e) { + ENUM_NAME(DxbcRegMode::Mask); + ENUM_NAME(DxbcRegMode::Swizzle); + ENUM_NAME(DxbcRegMode::Select1); + ENUM_DEFAULT(e); + } + } + + + std::ostream& operator << (std::ostream& os, DxbcOperandIndexRepresentation e) { + switch (e) { + ENUM_NAME(DxbcOperandIndexRepresentation::Imm32); + ENUM_NAME(DxbcOperandIndexRepresentation::Imm64); + ENUM_NAME(DxbcOperandIndexRepresentation::Relative); + ENUM_NAME(DxbcOperandIndexRepresentation::Imm32Relative); + ENUM_NAME(DxbcOperandIndexRepresentation::Imm64Relative); + ENUM_DEFAULT(e); + } + } + + + std::ostream& operator << (std::ostream& os, DxbcResourceDim e) { + switch (e) { + ENUM_NAME(DxbcResourceDim::Unknown); + ENUM_NAME(DxbcResourceDim::Buffer); + ENUM_NAME(DxbcResourceDim::Texture1D); + ENUM_NAME(DxbcResourceDim::Texture2D); + ENUM_NAME(DxbcResourceDim::Texture2DMs); + ENUM_NAME(DxbcResourceDim::Texture3D); + ENUM_NAME(DxbcResourceDim::TextureCube); + ENUM_NAME(DxbcResourceDim::Texture1DArr); + ENUM_NAME(DxbcResourceDim::Texture2DArr); + ENUM_NAME(DxbcResourceDim::Texture2DMsArr); + ENUM_NAME(DxbcResourceDim::TextureCubeArr); + ENUM_NAME(DxbcResourceDim::RawBuffer); + ENUM_NAME(DxbcResourceDim::StructuredBuffer); + ENUM_DEFAULT(e); + } + } + + + std::ostream& operator << (std::ostream& os, DxbcResourceReturnType e) { + switch (e) { + ENUM_NAME(DxbcResourceReturnType::Unorm); + ENUM_NAME(DxbcResourceReturnType::Snorm); + ENUM_NAME(DxbcResourceReturnType::Sint); + ENUM_NAME(DxbcResourceReturnType::Uint); + ENUM_NAME(DxbcResourceReturnType::Float); + ENUM_NAME(DxbcResourceReturnType::Mixed); + ENUM_NAME(DxbcResourceReturnType::Double); + ENUM_NAME(DxbcResourceReturnType::Continued); + ENUM_NAME(DxbcResourceReturnType::Unused); + ENUM_DEFAULT(e); + } + } + + + std::ostream& operator << (std::ostream& os, DxbcRegisterComponentType e) { + switch (e) { + ENUM_NAME(DxbcRegisterComponentType::Unknown); + ENUM_NAME(DxbcRegisterComponentType::Uint32); + ENUM_NAME(DxbcRegisterComponentType::Sint32); + ENUM_NAME(DxbcRegisterComponentType::Float32); + ENUM_DEFAULT(e); + } + } + + + std::ostream& operator << (std::ostream& os, DxbcInstructionReturnType e) { + switch (e) { + ENUM_NAME(DxbcInstructionReturnType::Float); + ENUM_NAME(DxbcInstructionReturnType::Uint); + ENUM_DEFAULT(e); + } + } + + + std::ostream& operator << (std::ostream& os, DxbcSystemValue e) { + switch (e) { + ENUM_NAME(DxbcSystemValue::None); + ENUM_NAME(DxbcSystemValue::Position); + ENUM_NAME(DxbcSystemValue::ClipDistance); + ENUM_NAME(DxbcSystemValue::CullDistance); + ENUM_NAME(DxbcSystemValue::RenderTargetId); + ENUM_NAME(DxbcSystemValue::ViewportId); + ENUM_NAME(DxbcSystemValue::VertexId); + ENUM_NAME(DxbcSystemValue::PrimitiveId); + ENUM_NAME(DxbcSystemValue::InstanceId); + ENUM_NAME(DxbcSystemValue::IsFrontFace); + ENUM_NAME(DxbcSystemValue::SampleIndex); + ENUM_NAME(DxbcSystemValue::FinalQuadUeq0EdgeTessFactor); + ENUM_NAME(DxbcSystemValue::FinalQuadVeq0EdgeTessFactor); + ENUM_NAME(DxbcSystemValue::FinalQuadUeq1EdgeTessFactor); + ENUM_NAME(DxbcSystemValue::FinalQuadVeq1EdgeTessFactor); + ENUM_NAME(DxbcSystemValue::FinalQuadUInsideTessFactor); + ENUM_NAME(DxbcSystemValue::FinalQuadVInsideTessFactor); + ENUM_NAME(DxbcSystemValue::FinalTriUeq0EdgeTessFactor); + ENUM_NAME(DxbcSystemValue::FinalTriVeq0EdgeTessFactor); + ENUM_NAME(DxbcSystemValue::FinalTriWeq0EdgeTessFactor); + ENUM_NAME(DxbcSystemValue::FinalTriInsideTessFactor); + ENUM_NAME(DxbcSystemValue::FinalLineDetailTessFactor); + ENUM_NAME(DxbcSystemValue::FinalLineDensityTessFactor); + ENUM_NAME(DxbcSystemValue::Target); + ENUM_NAME(DxbcSystemValue::Depth); + ENUM_NAME(DxbcSystemValue::Coverage); + ENUM_NAME(DxbcSystemValue::DepthGe); + ENUM_NAME(DxbcSystemValue::DepthLe); + ENUM_DEFAULT(e); + } + } + + + std::ostream& operator << (std::ostream& os, dxvk::DxbcProgramType e) { + switch (e) { + ENUM_NAME(DxbcProgramType::PixelShader); + ENUM_NAME(DxbcProgramType::VertexShader); + ENUM_NAME(DxbcProgramType::GeometryShader); + ENUM_NAME(DxbcProgramType::HullShader); + ENUM_NAME(DxbcProgramType::DomainShader); + ENUM_NAME(DxbcProgramType::ComputeShader); + ENUM_DEFAULT(e); + } + } + + std::ostream& operator << (std::ostream& os, dxvk::DxbcCustomDataClass e) { + switch (e) { + ENUM_NAME(DxbcCustomDataClass::Comment); + ENUM_NAME(DxbcCustomDataClass::DebugInfo); + ENUM_NAME(DxbcCustomDataClass::Opaque); + ENUM_NAME(DxbcCustomDataClass::ImmConstBuf); + ENUM_DEFAULT(e); + } + } + + std::ostream& operator << (std::ostream& os, dxvk::DxbcScalarType e) { + switch (e) { + ENUM_NAME(DxbcScalarType::Uint32); + ENUM_NAME(DxbcScalarType::Uint64); + ENUM_NAME(DxbcScalarType::Sint32); + ENUM_NAME(DxbcScalarType::Sint64); + ENUM_NAME(DxbcScalarType::Float32); + ENUM_NAME(DxbcScalarType::Float64); + ENUM_NAME(DxbcScalarType::Bool); + ENUM_DEFAULT(e); + } + } + + +} //namespace dxvk diff --git a/utils/dxvk-1.10.3/src/dxbc/dxbc_names.h b/utils/dxvk-1.10.3/src/dxbc/dxbc_names.h new file mode 100644 index 00000000000..52235ae5932 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxbc/dxbc_names.h @@ -0,0 +1,26 @@ +#pragma once + +#include + +#include "dxbc_common.h" +#include "dxbc_enums.h" + +namespace dxvk { + + std::ostream& operator << (std::ostream& os, DxbcOpcode e); + std::ostream& operator << (std::ostream& os, DxbcExtOpcode e); + std::ostream& operator << (std::ostream& os, DxbcOperandType e); + std::ostream& operator << (std::ostream& os, DxbcOperandExt e); + std::ostream& operator << (std::ostream& os, DxbcComponentCount e); + std::ostream& operator << (std::ostream& os, DxbcRegMode e); + std::ostream& operator << (std::ostream& os, DxbcOperandIndexRepresentation e); + std::ostream& operator << (std::ostream& os, DxbcResourceDim e); + std::ostream& operator << (std::ostream& os, DxbcResourceReturnType e); + std::ostream& operator << (std::ostream& os, DxbcRegisterComponentType e); + std::ostream& operator << (std::ostream& os, DxbcInstructionReturnType e); + std::ostream& operator << (std::ostream& os, DxbcSystemValue e); + std::ostream& operator << (std::ostream& os, DxbcProgramType e); + std::ostream& operator << (std::ostream& os, DxbcCustomDataClass e); + std::ostream& operator << (std::ostream& os, DxbcScalarType e); + +} // namespace dxvk diff --git a/utils/dxvk-1.10.3/src/dxbc/dxbc_options.cpp b/utils/dxvk-1.10.3/src/dxbc/dxbc_options.cpp new file mode 100644 index 00000000000..fc89f74b73a --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxbc/dxbc_options.cpp @@ -0,0 +1,71 @@ +#include "../d3d11/d3d11_options.h" + +#include "dxbc_options.h" + +namespace dxvk { + + DxbcOptions::DxbcOptions() { + + } + + + DxbcOptions::DxbcOptions(const Rc& device, const D3D11Options& options) { + const Rc adapter = device->adapter(); + + const DxvkDeviceFeatures& devFeatures = device->features(); + const DxvkDeviceInfo& devInfo = adapter->devicePropertiesExt(); + + useDepthClipWorkaround + = !devFeatures.extDepthClipEnable.depthClipEnable; + useStorageImageReadWithoutFormat + = devFeatures.core.features.shaderStorageImageReadWithoutFormat; + useSubgroupOpsForAtomicCounters + = (devInfo.coreSubgroup.supportedStages & VK_SHADER_STAGE_COMPUTE_BIT) + && (devInfo.coreSubgroup.supportedOperations & VK_SUBGROUP_FEATURE_BALLOT_BIT); + useDemoteToHelperInvocation + = (devFeatures.extShaderDemoteToHelperInvocation.shaderDemoteToHelperInvocation); + useSubgroupOpsForEarlyDiscard + = (devInfo.coreSubgroup.subgroupSize >= 4) + && (devInfo.coreSubgroup.supportedStages & VK_SHADER_STAGE_FRAGMENT_BIT) + && (devInfo.coreSubgroup.supportedOperations & VK_SUBGROUP_FEATURE_BALLOT_BIT); + useSdivForBufferIndex + = adapter->matchesDriver(DxvkGpuVendor::Nvidia, VK_DRIVER_ID_NVIDIA_PROPRIETARY_KHR, 0, 0); + + switch (device->config().useRawSsbo) { + case Tristate::Auto: minSsboAlignment = devInfo.core.properties.limits.minStorageBufferOffsetAlignment; break; + case Tristate::True: minSsboAlignment = 4u; break; + case Tristate::False: minSsboAlignment = ~0u; break; + } + + invariantPosition = options.invariantPosition; + enableRtOutputNanFixup = options.enableRtOutputNanFixup; + zeroInitWorkgroupMemory = options.zeroInitWorkgroupMemory; + forceTgsmBarriers = options.forceTgsmBarriers; + disableMsaa = options.disableMsaa; + dynamicIndexedConstantBufferAsSsbo = options.constantBufferRangeCheck; + + // Disable subgroup early discard on Nvidia because it may hurt performance + if (adapter->matchesDriver(DxvkGpuVendor::Nvidia, VK_DRIVER_ID_NVIDIA_PROPRIETARY_KHR, 0, 0)) + useSubgroupOpsForEarlyDiscard = false; + + // Figure out float control flags to match D3D11 rules + if (options.floatControls) { + if (devInfo.khrShaderFloatControls.shaderSignedZeroInfNanPreserveFloat32) + floatControl.set(DxbcFloatControlFlag::PreserveNan32); + if (devInfo.khrShaderFloatControls.shaderSignedZeroInfNanPreserveFloat64) + floatControl.set(DxbcFloatControlFlag::PreserveNan64); + + if (devInfo.khrShaderFloatControls.denormBehaviorIndependence != VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE) { + if (devInfo.khrShaderFloatControls.shaderDenormFlushToZeroFloat32) + floatControl.set(DxbcFloatControlFlag::DenormFlushToZero32); + if (devInfo.khrShaderFloatControls.shaderDenormPreserveFloat64) + floatControl.set(DxbcFloatControlFlag::DenormPreserve64); + } + } + + if (!devInfo.khrShaderFloatControls.shaderSignedZeroInfNanPreserveFloat32 + || adapter->matchesDriver(DxvkGpuVendor::Amd, VK_DRIVER_ID_MESA_RADV_KHR, 0, VK_MAKE_VERSION(20, 3, 0))) + enableRtOutputNanFixup = true; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxbc/dxbc_options.h b/utils/dxvk-1.10.3/src/dxbc/dxbc_options.h new file mode 100644 index 00000000000..d21f3b1a415 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxbc/dxbc_options.h @@ -0,0 +1,70 @@ +#pragma once + +#include "../dxvk/dxvk_device.h" + +namespace dxvk { + + struct D3D11Options; + + enum class DxbcFloatControlFlag : uint32_t { + DenormFlushToZero32, + DenormPreserve64, + PreserveNan32, + PreserveNan64, + }; + + using DxbcFloatControlFlags = Flags; + + struct DxbcOptions { + DxbcOptions(); + DxbcOptions(const Rc& device, const D3D11Options& options); + + // Clamp oDepth in fragment shaders if the depth + // clip device feature is not supported + bool useDepthClipWorkaround = false; + + /// Use the ShaderImageReadWithoutFormat capability. + bool useStorageImageReadWithoutFormat = false; + + /// Use subgroup operations to reduce the number of + /// atomic operations for append/consume buffers. + bool useSubgroupOpsForAtomicCounters = false; + + /// Use a SPIR-V extension to implement D3D-style discards + bool useDemoteToHelperInvocation = false; + + /// Use subgroup operations to discard fragment + /// shader invocations if derivatives remain valid. + bool useSubgroupOpsForEarlyDiscard = false; + + /// Use SDiv instead of SHR to converte byte offsets to + /// dword offsets. Fixes RE2 and DMC5 on Nvidia drivers. + bool useSdivForBufferIndex = false; + + /// Enables NaN fixup for render target outputs + bool enableRtOutputNanFixup = false; + + /// Implement dynamically indexed uniform buffers + /// with storage buffers for tight bounds checking + bool dynamicIndexedConstantBufferAsSsbo = false; + + /// Clear thread-group shared memory to zero + bool zeroInitWorkgroupMemory = false; + + /// Declare vertex positions as invariant + bool invariantPosition = false; + + /// Insert memory barriers after TGSM stoes + bool forceTgsmBarriers = false; + + /// Replace ld_ms with ld + bool disableMsaa = false; + + /// Float control flags + DxbcFloatControlFlags floatControl; + + /// Minimum storage buffer alignment + VkDeviceSize minSsboAlignment = 0; + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxbc/dxbc_reader.cpp b/utils/dxvk-1.10.3/src/dxbc/dxbc_reader.cpp new file mode 100644 index 00000000000..9b9a340a387 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxbc/dxbc_reader.cpp @@ -0,0 +1,58 @@ +#include + +#include "dxbc_reader.h" + +namespace dxvk { + + DxbcTag DxbcReader::readTag() { + DxbcTag tag; + this->read(&tag, 4); + return tag; + } + + + std::string DxbcReader::readString() { + std::string result; + + while (m_data[m_pos] != '\0') + result.push_back(m_data[m_pos++]); + + m_pos++; + return result; + } + + + void DxbcReader::read(void* dst, size_t n) { + if (m_pos + n > m_size) + throw DxvkError("DxbcReader::read: Unexpected end of file"); + std::memcpy(dst, m_data + m_pos, n); + m_pos += n; + } + + + void DxbcReader::skip(size_t n) { + if (m_pos + n > m_size) + throw DxvkError("DxbcReader::skip: Unexpected end of file"); + m_pos += n; + } + + + DxbcReader DxbcReader::clone(size_t pos) const { + if (pos > m_size) + throw DxvkError("DxbcReader::clone: Invalid offset"); + return DxbcReader(m_data + pos, m_size - pos); + } + + + DxbcReader DxbcReader::resize(size_t size) const { + if (size > m_size) + throw DxvkError("DxbcReader::resize: Invalid size"); + return DxbcReader(m_data, size, m_pos); + } + + + void DxbcReader::store(std::ostream&& stream) const { + stream.write(m_data, m_size); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxbc/dxbc_reader.h b/utils/dxvk-1.10.3/src/dxbc/dxbc_reader.h new file mode 100644 index 00000000000..a16000179bf --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxbc/dxbc_reader.h @@ -0,0 +1,78 @@ +#pragma once + +#include +#include + +#include "dxbc_tag.h" + +namespace dxvk { + + /** + * \brief DXBC bytecode reader + * + * Holds references to the shader byte code and + * provides methods to read + */ + class DxbcReader { + + public: + + DxbcReader(const char* data, size_t size) + : DxbcReader(data, size, 0) { } + + auto readu8 () { return this->readNum (); } + auto readu16() { return this->readNum(); } + auto readu32() { return this->readNum(); } + auto readu64() { return this->readNum(); } + + auto readi8 () { return this->readNum (); } + auto readi16() { return this->readNum (); } + auto readi32() { return this->readNum (); } + auto readi64() { return this->readNum (); } + + auto readf32() { return this->readNum (); } + auto readf64() { return this->readNum (); } + + template + auto readEnum() { + using Tx = std::underlying_type_t; + return static_cast(this->readNum()); + } + + DxbcTag readTag(); + + std::string readString(); + + void read(void* dst, size_t n); + + void skip(size_t n); + + DxbcReader clone(size_t pos) const; + + DxbcReader resize(size_t size) const; + + bool eof() const { + return m_pos >= m_size; + } + + void store(std::ostream&& stream) const; + + private: + + DxbcReader(const char* data, size_t size, size_t pos) + : m_data(data), m_size(size), m_pos(pos) { } + + const char* m_data = nullptr; + size_t m_size = 0; + size_t m_pos = 0; + + template + T readNum() { + T result; + this->read(&result, sizeof(result)); + return result; + } + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxbc/dxbc_tag.h b/utils/dxvk-1.10.3/src/dxbc/dxbc_tag.h new file mode 100644 index 00000000000..2ba17509c51 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxbc/dxbc_tag.h @@ -0,0 +1,47 @@ +#pragma once + +#include "dxbc_include.h" + +namespace dxvk { + + /** + * \brief Four-character tag + * + * Used to identify chunks in the + * compiled DXBC file by name. + */ + class DxbcTag { + + public: + + DxbcTag() { + for (size_t i = 0; i < 4; i++) + m_chars[i] = '\0'; + } + + DxbcTag(const char* tag) { + for (size_t i = 0; i < 4; i++) + m_chars[i] = tag[i]; + } + + bool operator == (const DxbcTag& other) const { + bool result = true; + for (size_t i = 0; i < 4; i++) + result &= m_chars[i] == other.m_chars[i]; + return result; + } + + bool operator != (const DxbcTag& other) const { + return !this->operator == (other); + } + + const char* operator & () const { return m_chars; } + char* operator & () { return m_chars; } + + private: + + char m_chars[4]; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxbc/dxbc_util.cpp b/utils/dxvk-1.10.3/src/dxbc/dxbc_util.cpp new file mode 100644 index 00000000000..848f8ad78e4 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxbc/dxbc_util.cpp @@ -0,0 +1,26 @@ +#include "dxbc_util.h" + +namespace dxvk { + + uint32_t primitiveVertexCount(DxbcPrimitive primitive) { + static const std::array s_vertexCounts = { + 0, // Undefined + 1, // Point + 2, // Line + 3, // Triangle + 0, // Undefined + 0, // Undefined + 4, // Line with adjacency + 6, // Triangle with adjacency + }; + + if (primitive >= DxbcPrimitive::Patch1) { + return static_cast(primitive) + - static_cast(DxbcPrimitive::Patch1); + } else { + return s_vertexCounts.at( + static_cast(primitive)); + } + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxbc/dxbc_util.h b/utils/dxvk-1.10.3/src/dxbc/dxbc_util.h new file mode 100644 index 00000000000..4bc49620d07 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxbc/dxbc_util.h @@ -0,0 +1,119 @@ +#pragma once + +#include "dxbc_common.h" +#include "dxbc_enums.h" + +namespace dxvk { + + /** + * \brief Binding numbers and properties + */ + enum DxbcBindingProperties : uint32_t { + DxbcConstBufBindingIndex = 0, + DxbcConstBufBindingCount = 16, + DxbcSamplerBindingIndex = DxbcConstBufBindingIndex + + DxbcConstBufBindingCount, + DxbcSamplerBindingCount = 16, + DxbcResourceBindingIndex = DxbcSamplerBindingIndex + + DxbcSamplerBindingCount, + DxbcResourceBindingCount = 128, + DxbcStageBindingCount = DxbcConstBufBindingCount + + DxbcSamplerBindingCount + + DxbcResourceBindingCount, + DxbcUavBindingIndex = DxbcStageBindingCount * 6, + DxbcUavBindingCount = 64, + }; + + + /** + * \brief Computes first binding index for a given stage + * + * \param [in] stage The shader stage + * \returns Index of first binding + */ + inline uint32_t computeStageBindingOffset(DxbcProgramType stage) { + return DxbcStageBindingCount * uint32_t(stage); + } + + + /** + * \brief Computes first UAV binding index offset for a given stage + * + * \param [in] stage The shader stage + * \returns Index of first UAV binding + */ + inline uint32_t computeStageUavBindingOffset(DxbcProgramType stage) { + return DxbcUavBindingIndex + + DxbcUavBindingCount * (stage == DxbcProgramType::ComputeShader ? 2 : 0); + } + + + /** + * \brief Computes constant buffer binding index + * + * \param [in] stage Shader stage + * \param [in] index Constant buffer index + * \returns Binding index + */ + inline uint32_t computeConstantBufferBinding(DxbcProgramType stage, uint32_t index) { + return computeStageBindingOffset(stage) + DxbcConstBufBindingIndex + index; + } + + + /** + * \brief Computes sampler binding index + * + * \param [in] stage Shader stage + * \param [in] index Sampler index + * \returns Binding index + */ + inline uint32_t computeSamplerBinding(DxbcProgramType stage, uint32_t index) { + return computeStageBindingOffset(stage) + DxbcSamplerBindingIndex + index; + } + + + /** + * \brief Computes resource binding index + * + * \param [in] stage Shader stage + * \param [in] index Resource index + * \returns Binding index + */ + inline uint32_t computeSrvBinding(DxbcProgramType stage, uint32_t index) { + return computeStageBindingOffset(stage) + DxbcResourceBindingIndex + index; + } + + + /** + * \brief Computes UAV binding offset + * + * \param [in] stage Shader stage + * \param [in] index UAV index + * \returns Binding index + */ + inline uint32_t computeUavBinding(DxbcProgramType stage, uint32_t index) { + return computeStageUavBindingOffset(stage) + index; + } + + + /** + * \brief Computes UAV counter binding offset + * + * \param [in] stage Shader stage + * \param [in] index UAV index + * \returns Binding index + */ + inline uint32_t computeUavCounterBinding(DxbcProgramType stage, uint32_t index) { + return computeStageUavBindingOffset(stage) + DxbcUavBindingCount + index; + } + + /** + * \brief Primitive vertex count + * + * Calculates the number of vertices + * for a given primitive type. + */ + uint32_t primitiveVertexCount( + DxbcPrimitive primitive); + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxbc/meson.build b/utils/dxvk-1.10.3/src/dxbc/meson.build new file mode 100644 index 00000000000..daaf0ece9ec --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxbc/meson.build @@ -0,0 +1,24 @@ +dxbc_src = files([ + 'dxbc_analysis.cpp', + 'dxbc_chunk_isgn.cpp', + 'dxbc_chunk_shex.cpp', + 'dxbc_common.cpp', + 'dxbc_compiler.cpp', + 'dxbc_defs.cpp', + 'dxbc_decoder.cpp', + 'dxbc_header.cpp', + 'dxbc_module.cpp', + 'dxbc_names.cpp', + 'dxbc_options.cpp', + 'dxbc_reader.cpp', + 'dxbc_util.cpp', +]) + +dxbc_lib = static_library('dxbc', dxbc_src, + include_directories : [ dxvk_include_path ], +) + +dxbc_dep = declare_dependency( + link_with : [ dxbc_lib ], + include_directories : [ dxvk_include_path ], +) diff --git a/utils/dxvk-1.10.3/src/dxgi/dxgi.def b/utils/dxvk-1.10.3/src/dxgi/dxgi.def new file mode 100644 index 00000000000..c5509571b2d --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxgi/dxgi.def @@ -0,0 +1,7 @@ +LIBRARY DXGI.DLL +EXPORTS + CreateDXGIFactory @9 + CreateDXGIFactory1 @10 + CreateDXGIFactory2 @11 + DXGIDeclareAdapterRemovalSupport @16 + DXGIGetDebugInterface1 @17 diff --git a/utils/dxvk-1.10.3/src/dxgi/dxgi_adapter.cpp b/utils/dxvk-1.10.3/src/dxgi/dxgi_adapter.cpp new file mode 100644 index 00000000000..3e8f6307e3c --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxgi/dxgi_adapter.cpp @@ -0,0 +1,494 @@ +#include +#include + +#include + +#include "dxgi_adapter.h" +#include "dxgi_enums.h" +#include "dxgi_factory.h" +#include "dxgi_format.h" +#include "dxgi_options.h" +#include "dxgi_output.h" + +#include "../util/util_luid.h" + +namespace dxvk { + + DxgiVkAdapter::DxgiVkAdapter(DxgiAdapter* pAdapter) + : m_adapter(pAdapter) { + + } + + + ULONG STDMETHODCALLTYPE DxgiVkAdapter::AddRef() { + return m_adapter->AddRef(); + } + + + ULONG STDMETHODCALLTYPE DxgiVkAdapter::Release() { + return m_adapter->Release(); + } + + + HRESULT STDMETHODCALLTYPE DxgiVkAdapter::QueryInterface( + REFIID riid, + void** ppvObject) { + return m_adapter->QueryInterface(riid, ppvObject); + } + + + void STDMETHODCALLTYPE DxgiVkAdapter::GetVulkanHandles( + VkInstance* pInstance, + VkPhysicalDevice* pPhysDev) { + auto adapter = m_adapter->GetDXVKAdapter(); + auto instance = m_adapter->GetDXVKInstance(); + + if (pInstance) + *pInstance = instance->handle(); + + if (pPhysDev) + *pPhysDev = adapter->handle(); + } + + + + + DxgiAdapter::DxgiAdapter( + DxgiFactory* factory, + const Rc& adapter, + UINT index) + : m_factory (factory), + m_adapter (adapter), + m_interop (this), + m_index (index) { + + } + + + DxgiAdapter::~DxgiAdapter() { + if (m_eventThread.joinable()) { + std::unique_lock lock(m_mutex); + m_eventCookie = ~0u; + m_cond.notify_one(); + + lock.unlock(); + m_eventThread.join(); + } + } + + + HRESULT STDMETHODCALLTYPE DxgiAdapter::QueryInterface(REFIID riid, void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(IDXGIObject) + || riid == __uuidof(IDXGIAdapter) + || riid == __uuidof(IDXGIAdapter1) + || riid == __uuidof(IDXGIAdapter2) + || riid == __uuidof(IDXGIAdapter3) + || riid == __uuidof(IDXGIAdapter4) + || riid == __uuidof(IDXGIDXVKAdapter)) { + *ppvObject = ref(this); + return S_OK; + } + + if (riid == __uuidof(IDXGIVkInteropAdapter)) { + *ppvObject = ref(&m_interop); + return S_OK; + } + + Logger::warn("DxgiAdapter::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + HRESULT STDMETHODCALLTYPE DxgiAdapter::GetParent(REFIID riid, void** ppParent) { + return m_factory->QueryInterface(riid, ppParent); + } + + + HRESULT STDMETHODCALLTYPE DxgiAdapter::CheckInterfaceSupport( + REFGUID InterfaceName, + LARGE_INTEGER* pUMDVersion) { + HRESULT hr = DXGI_ERROR_UNSUPPORTED; + + if (InterfaceName == __uuidof(IDXGIDevice) + || InterfaceName == __uuidof(ID3D10Device) + || InterfaceName == __uuidof(ID3D10Device1)) + hr = S_OK; + + // We can't really reconstruct the version numbers + // returned by Windows drivers from Vulkan data + if (SUCCEEDED(hr) && pUMDVersion) + pUMDVersion->QuadPart = ~0ull; + + if (FAILED(hr)) { + Logger::err("DXGI: CheckInterfaceSupport: Unsupported interface"); + Logger::err(str::format(InterfaceName)); + } + + return hr; + } + + + HRESULT STDMETHODCALLTYPE DxgiAdapter::EnumOutputs( + UINT Output, + IDXGIOutput** ppOutput) { + InitReturnPtr(ppOutput); + + if (ppOutput == nullptr) + return E_INVALIDARG; + + MonitorEnumInfo info; + info.iMonitorId = Output; + info.oMonitor = nullptr; + + ::EnumDisplayMonitors( + nullptr, nullptr, &MonitorEnumProc, + reinterpret_cast(&info)); + + if (info.oMonitor == nullptr) + return DXGI_ERROR_NOT_FOUND; + + *ppOutput = ref(new DxgiOutput(m_factory, this, info.oMonitor)); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE DxgiAdapter::GetDesc(DXGI_ADAPTER_DESC* pDesc) { + if (pDesc == nullptr) + return E_INVALIDARG; + + DXGI_ADAPTER_DESC3 desc; + HRESULT hr = GetDesc3(&desc); + + if (SUCCEEDED(hr)) { + std::memcpy(pDesc->Description, desc.Description, sizeof(pDesc->Description)); + + pDesc->VendorId = desc.VendorId; + pDesc->DeviceId = desc.DeviceId; + pDesc->SubSysId = desc.SubSysId; + pDesc->Revision = desc.Revision; + pDesc->DedicatedVideoMemory = desc.DedicatedVideoMemory; + pDesc->DedicatedSystemMemory = desc.DedicatedSystemMemory; + pDesc->SharedSystemMemory = desc.SharedSystemMemory; + pDesc->AdapterLuid = desc.AdapterLuid; + } + + return hr; + } + + + HRESULT STDMETHODCALLTYPE DxgiAdapter::GetDesc1(DXGI_ADAPTER_DESC1* pDesc) { + if (pDesc == nullptr) + return E_INVALIDARG; + + DXGI_ADAPTER_DESC3 desc; + HRESULT hr = GetDesc3(&desc); + + if (SUCCEEDED(hr)) { + std::memcpy(pDesc->Description, desc.Description, sizeof(pDesc->Description)); + + pDesc->VendorId = desc.VendorId; + pDesc->DeviceId = desc.DeviceId; + pDesc->SubSysId = desc.SubSysId; + pDesc->Revision = desc.Revision; + pDesc->DedicatedVideoMemory = desc.DedicatedVideoMemory; + pDesc->DedicatedSystemMemory = desc.DedicatedSystemMemory; + pDesc->SharedSystemMemory = desc.SharedSystemMemory; + pDesc->AdapterLuid = desc.AdapterLuid; + pDesc->Flags = desc.Flags; + } + + return hr; + } + + + HRESULT STDMETHODCALLTYPE DxgiAdapter::GetDesc2(DXGI_ADAPTER_DESC2* pDesc) { + if (pDesc == nullptr) + return E_INVALIDARG; + + DXGI_ADAPTER_DESC3 desc; + HRESULT hr = GetDesc3(&desc); + + if (SUCCEEDED(hr)) { + std::memcpy(pDesc->Description, desc.Description, sizeof(pDesc->Description)); + + pDesc->VendorId = desc.VendorId; + pDesc->DeviceId = desc.DeviceId; + pDesc->SubSysId = desc.SubSysId; + pDesc->Revision = desc.Revision; + pDesc->DedicatedVideoMemory = desc.DedicatedVideoMemory; + pDesc->DedicatedSystemMemory = desc.DedicatedSystemMemory; + pDesc->SharedSystemMemory = desc.SharedSystemMemory; + pDesc->AdapterLuid = desc.AdapterLuid; + pDesc->Flags = desc.Flags; + pDesc->GraphicsPreemptionGranularity = desc.GraphicsPreemptionGranularity; + pDesc->ComputePreemptionGranularity = desc.ComputePreemptionGranularity; + } + + return hr; + } + + + HRESULT STDMETHODCALLTYPE DxgiAdapter::GetDesc3( + DXGI_ADAPTER_DESC3* pDesc) { + if (pDesc == nullptr) + return E_INVALIDARG; + + const DxgiOptions* options = m_factory->GetOptions(); + + auto deviceProp = m_adapter->deviceProperties(); + auto memoryProp = m_adapter->memoryProperties(); + auto deviceId = m_adapter->devicePropertiesExt().coreDeviceId; + + // Custom Vendor / Device ID + if (options->customVendorId >= 0) + deviceProp.vendorID = options->customVendorId; + + if (options->customDeviceId >= 0) + deviceProp.deviceID = options->customDeviceId; + + const char* description = deviceProp.deviceName; + // Custom device description + if (!options->customDeviceDesc.empty()) + description = options->customDeviceDesc.c_str(); + + // XXX nvapi workaround for a lot of Unreal Engine 4 games + if (options->customVendorId < 0 && options->customDeviceId < 0 + && options->nvapiHack && deviceProp.vendorID == uint16_t(DxvkGpuVendor::Nvidia)) { + Logger::info("DXGI: NvAPI workaround enabled, reporting AMD GPU"); + deviceProp.vendorID = uint16_t(DxvkGpuVendor::Amd); + deviceProp.deviceID = 0x67df; /* RX 480 */ + } + + // Convert device name + std::memset(pDesc->Description, 0, sizeof(pDesc->Description)); + str::tows(description, pDesc->Description); + + // Get amount of video memory + // based on the Vulkan heaps + VkDeviceSize deviceMemory = 0; + VkDeviceSize sharedMemory = 0; + + for (uint32_t i = 0; i < memoryProp.memoryHeapCount; i++) { + VkMemoryHeap heap = memoryProp.memoryHeaps[i]; + + if (heap.flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) + deviceMemory += heap.size; + else + sharedMemory += heap.size; + } + + // Some games think we are on Intel given a lack of + // NVAPI or AGS/atiadlxx support. + // Report our device memory as shared memory, + // and some small amount for the carveout. + if (options->emulateUMA && !m_adapter->isUnifiedMemoryArchitecture()) { + sharedMemory = deviceMemory; + deviceMemory = 128 * (1 << 20); + } + + // Some games are silly and need their memory limited + if (options->maxDeviceMemory > 0 + && options->maxDeviceMemory < deviceMemory) + deviceMemory = options->maxDeviceMemory; + + if (options->maxSharedMemory > 0 + && options->maxSharedMemory < sharedMemory) + sharedMemory = options->maxSharedMemory; + + if (env::is32BitHostPlatform()) { + // The value returned by DXGI is a 32-bit value + // on 32-bit platforms, so we need to clamp it + VkDeviceSize maxMemory = 0xC0000000; + deviceMemory = std::min(deviceMemory, maxMemory); + sharedMemory = std::min(sharedMemory, maxMemory); + } + + pDesc->VendorId = deviceProp.vendorID; + pDesc->DeviceId = deviceProp.deviceID; + pDesc->SubSysId = 0; + pDesc->Revision = 0; + pDesc->DedicatedVideoMemory = deviceMemory; + pDesc->DedicatedSystemMemory = 0; + pDesc->SharedSystemMemory = sharedMemory; + pDesc->AdapterLuid = LUID { 0, 0 }; + pDesc->Flags = DXGI_ADAPTER_FLAG3_NONE; + pDesc->GraphicsPreemptionGranularity = DXGI_GRAPHICS_PREEMPTION_DMA_BUFFER_BOUNDARY; + pDesc->ComputePreemptionGranularity = DXGI_COMPUTE_PREEMPTION_DMA_BUFFER_BOUNDARY; + + if (deviceId.deviceLUIDValid) + std::memcpy(&pDesc->AdapterLuid, deviceId.deviceLUID, VK_LUID_SIZE); + else + pDesc->AdapterLuid = GetAdapterLUID(m_index); + + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE DxgiAdapter::QueryVideoMemoryInfo( + UINT NodeIndex, + DXGI_MEMORY_SEGMENT_GROUP MemorySegmentGroup, + DXGI_QUERY_VIDEO_MEMORY_INFO* pVideoMemoryInfo) { + if (NodeIndex > 0 || !pVideoMemoryInfo) + return E_INVALIDARG; + + if (MemorySegmentGroup != DXGI_MEMORY_SEGMENT_GROUP_LOCAL + && MemorySegmentGroup != DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL) + return E_INVALIDARG; + + DxvkAdapterMemoryInfo memInfo = m_adapter->getMemoryHeapInfo(); + + VkMemoryHeapFlags heapFlagMask = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT; + VkMemoryHeapFlags heapFlags = 0; + + if (MemorySegmentGroup == DXGI_MEMORY_SEGMENT_GROUP_LOCAL) + heapFlags |= VK_MEMORY_HEAP_DEVICE_LOCAL_BIT; + + pVideoMemoryInfo->Budget = 0; + pVideoMemoryInfo->CurrentUsage = 0; + + for (uint32_t i = 0; i < memInfo.heapCount; i++) { + if ((memInfo.heaps[i].heapFlags & heapFlagMask) != heapFlags) + continue; + + pVideoMemoryInfo->Budget += memInfo.heaps[i].memoryBudget; + pVideoMemoryInfo->CurrentUsage += memInfo.heaps[i].memoryAllocated; + } + + // We don't implement reservation, but the observable + // behaviour should match that of Windows drivers + uint32_t segmentId = uint32_t(MemorySegmentGroup); + + pVideoMemoryInfo->AvailableForReservation = pVideoMemoryInfo->Budget / 2; + pVideoMemoryInfo->CurrentReservation = m_memReservation[segmentId]; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE DxgiAdapter::SetVideoMemoryReservation( + UINT NodeIndex, + DXGI_MEMORY_SEGMENT_GROUP MemorySegmentGroup, + UINT64 Reservation) { + DXGI_QUERY_VIDEO_MEMORY_INFO info; + + HRESULT hr = QueryVideoMemoryInfo( + NodeIndex, MemorySegmentGroup, &info); + + if (FAILED(hr)) + return hr; + + if (Reservation > info.AvailableForReservation) + return DXGI_ERROR_INVALID_CALL; + + uint32_t segmentId = uint32_t(MemorySegmentGroup); + m_memReservation[segmentId] = Reservation; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE DxgiAdapter::RegisterHardwareContentProtectionTeardownStatusEvent( + HANDLE hEvent, + DWORD* pdwCookie) { + Logger::err("DxgiAdapter::RegisterHardwareContentProtectionTeardownStatusEvent: Not implemented"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE DxgiAdapter::RegisterVideoMemoryBudgetChangeNotificationEvent( + HANDLE hEvent, + DWORD* pdwCookie) { + if (!hEvent || !pdwCookie) + return DXGI_ERROR_INVALID_CALL; + + std::unique_lock lock(m_mutex); + DWORD cookie = ++m_eventCookie; + + m_eventMap.insert({ cookie, hEvent }); + + if (!m_eventThread.joinable()) + m_eventThread = dxvk::thread([this] { runEventThread(); }); + + // This method seems to fire the + // event immediately on Windows + SetEvent(hEvent); + + *pdwCookie = cookie; + return S_OK; + } + + + void STDMETHODCALLTYPE DxgiAdapter::UnregisterHardwareContentProtectionTeardownStatus( + DWORD dwCookie) { + Logger::err("DxgiAdapter::UnregisterHardwareContentProtectionTeardownStatus: Not implemented"); + } + + + void STDMETHODCALLTYPE DxgiAdapter::UnregisterVideoMemoryBudgetChangeNotification( + DWORD dwCookie) { + std::unique_lock lock(m_mutex); + m_eventMap.erase(dwCookie); + } + + + Rc STDMETHODCALLTYPE DxgiAdapter::GetDXVKAdapter() { + return m_adapter; + } + + + Rc STDMETHODCALLTYPE DxgiAdapter::GetDXVKInstance() { + return m_factory->GetDXVKInstance(); + } + + + void DxgiAdapter::runEventThread() { + env::setThreadName(str::format("dxvk-adapter-", m_index)); + + std::unique_lock lock(m_mutex); + DxvkAdapterMemoryInfo memoryInfoOld = m_adapter->getMemoryHeapInfo(); + + while (true) { + m_cond.wait_for(lock, std::chrono::milliseconds(1500), + [this] { return m_eventCookie == ~0u; }); + + if (m_eventCookie == ~0u) + return; + + auto memoryInfoNew = m_adapter->getMemoryHeapInfo(); + bool budgetChanged = false; + + for (uint32_t i = 0; i < memoryInfoNew.heapCount; i++) { + budgetChanged |= memoryInfoNew.heaps[i].memoryBudget + != memoryInfoOld.heaps[i].memoryBudget; + } + + if (budgetChanged) { + memoryInfoOld = memoryInfoNew; + + for (const auto& pair : m_eventMap) + SetEvent(pair.second); + } + } + } + + + BOOL CALLBACK DxgiAdapter::MonitorEnumProc( + HMONITOR hmon, + HDC hdc, + LPRECT rect, + LPARAM lp) { + auto data = reinterpret_cast(lp); + + if (data->iMonitorId--) + return TRUE; /* continue */ + + data->oMonitor = hmon; + return FALSE; /* stop */ + } + +} diff --git a/utils/dxvk-1.10.3/src/dxgi/dxgi_adapter.h b/utils/dxvk-1.10.3/src/dxgi/dxgi_adapter.h new file mode 100644 index 00000000000..a9a0d2dfb80 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxgi/dxgi_adapter.h @@ -0,0 +1,140 @@ +#pragma once + +#include +#include + +#include "dxgi_format.h" +#include "dxgi_interfaces.h" +#include "dxgi_output.h" + +namespace dxvk { + + class DxgiAdapter; + class DxgiFactory; + class DxgiOutput; + + + class DxgiVkAdapter : public IDXGIVkInteropAdapter { + + public: + + DxgiVkAdapter(DxgiAdapter* pAdapter); + + ULONG STDMETHODCALLTYPE AddRef(); + + ULONG STDMETHODCALLTYPE Release(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + void STDMETHODCALLTYPE GetVulkanHandles( + VkInstance* pInstance, + VkPhysicalDevice* pPhysDev); + + private: + + DxgiAdapter* m_adapter; + + }; + + + class DxgiAdapter : public DxgiObject { + + public: + + DxgiAdapter( + DxgiFactory* factory, + const Rc& adapter, + UINT index); + + ~DxgiAdapter(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject) final; + + HRESULT STDMETHODCALLTYPE GetParent( + REFIID riid, + void** ppParent) final; + + HRESULT STDMETHODCALLTYPE CheckInterfaceSupport( + REFGUID InterfaceName, + LARGE_INTEGER* pUMDVersion) final; + + HRESULT STDMETHODCALLTYPE EnumOutputs( + UINT Output, + IDXGIOutput** ppOutput) final; + + HRESULT STDMETHODCALLTYPE GetDesc( + DXGI_ADAPTER_DESC* pDesc) final; + + HRESULT STDMETHODCALLTYPE GetDesc1( + DXGI_ADAPTER_DESC1* pDesc) final; + + HRESULT STDMETHODCALLTYPE GetDesc2( + DXGI_ADAPTER_DESC2* pDesc) final; + + HRESULT STDMETHODCALLTYPE GetDesc3( + DXGI_ADAPTER_DESC3* pDesc) final; + + HRESULT STDMETHODCALLTYPE QueryVideoMemoryInfo( + UINT NodeIndex, + DXGI_MEMORY_SEGMENT_GROUP MemorySegmentGroup, + DXGI_QUERY_VIDEO_MEMORY_INFO* pVideoMemoryInfo) final; + + HRESULT STDMETHODCALLTYPE SetVideoMemoryReservation( + UINT NodeIndex, + DXGI_MEMORY_SEGMENT_GROUP MemorySegmentGroup, + UINT64 Reservation) final; + + HRESULT STDMETHODCALLTYPE RegisterHardwareContentProtectionTeardownStatusEvent( + HANDLE hEvent, + DWORD* pdwCookie) final; + + HRESULT STDMETHODCALLTYPE RegisterVideoMemoryBudgetChangeNotificationEvent( + HANDLE hEvent, + DWORD* pdwCookie) final; + + void STDMETHODCALLTYPE UnregisterHardwareContentProtectionTeardownStatus( + DWORD dwCookie) final; + + void STDMETHODCALLTYPE UnregisterVideoMemoryBudgetChangeNotification( + DWORD dwCookie) final; + + Rc STDMETHODCALLTYPE GetDXVKAdapter() final; + + Rc STDMETHODCALLTYPE GetDXVKInstance() final; + + private: + + Com m_factory; + Rc m_adapter; + DxgiVkAdapter m_interop; + + UINT m_index; + UINT64 m_memReservation[2] = { 0, 0 }; + + dxvk::mutex m_mutex; + dxvk::condition_variable m_cond; + + DWORD m_eventCookie = 0; + std::unordered_map m_eventMap; + dxvk::thread m_eventThread; + + void runEventThread(); + + struct MonitorEnumInfo { + UINT iMonitorId; + HMONITOR oMonitor; + }; + + static BOOL CALLBACK MonitorEnumProc( + HMONITOR hmon, + HDC hdc, + LPRECT rect, + LPARAM lp); + + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxgi/dxgi_enums.cpp b/utils/dxvk-1.10.3/src/dxgi/dxgi_enums.cpp new file mode 100644 index 00000000000..5d9e75d1117 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxgi/dxgi_enums.cpp @@ -0,0 +1,123 @@ +#include "dxgi_enums.h" + +std::ostream& operator << (std::ostream& os, DXGI_FORMAT e) { + switch (e) { + ENUM_NAME(DXGI_FORMAT_UNKNOWN); + ENUM_NAME(DXGI_FORMAT_R32G32B32A32_TYPELESS); + ENUM_NAME(DXGI_FORMAT_R32G32B32A32_FLOAT); + ENUM_NAME(DXGI_FORMAT_R32G32B32A32_UINT); + ENUM_NAME(DXGI_FORMAT_R32G32B32A32_SINT); + ENUM_NAME(DXGI_FORMAT_R32G32B32_TYPELESS); + ENUM_NAME(DXGI_FORMAT_R32G32B32_FLOAT); + ENUM_NAME(DXGI_FORMAT_R32G32B32_UINT); + ENUM_NAME(DXGI_FORMAT_R32G32B32_SINT); + ENUM_NAME(DXGI_FORMAT_R16G16B16A16_TYPELESS); + ENUM_NAME(DXGI_FORMAT_R16G16B16A16_FLOAT); + ENUM_NAME(DXGI_FORMAT_R16G16B16A16_UNORM); + ENUM_NAME(DXGI_FORMAT_R16G16B16A16_UINT); + ENUM_NAME(DXGI_FORMAT_R16G16B16A16_SNORM); + ENUM_NAME(DXGI_FORMAT_R16G16B16A16_SINT); + ENUM_NAME(DXGI_FORMAT_R32G32_TYPELESS); + ENUM_NAME(DXGI_FORMAT_R32G32_FLOAT); + ENUM_NAME(DXGI_FORMAT_R32G32_UINT); + ENUM_NAME(DXGI_FORMAT_R32G32_SINT); + ENUM_NAME(DXGI_FORMAT_R32G8X24_TYPELESS); + ENUM_NAME(DXGI_FORMAT_D32_FLOAT_S8X24_UINT); + ENUM_NAME(DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS); + ENUM_NAME(DXGI_FORMAT_X32_TYPELESS_G8X24_UINT); + ENUM_NAME(DXGI_FORMAT_R10G10B10A2_TYPELESS); + ENUM_NAME(DXGI_FORMAT_R10G10B10A2_UNORM); + ENUM_NAME(DXGI_FORMAT_R10G10B10A2_UINT); + ENUM_NAME(DXGI_FORMAT_R11G11B10_FLOAT); + ENUM_NAME(DXGI_FORMAT_R8G8B8A8_TYPELESS); + ENUM_NAME(DXGI_FORMAT_R8G8B8A8_UNORM); + ENUM_NAME(DXGI_FORMAT_R8G8B8A8_UNORM_SRGB); + ENUM_NAME(DXGI_FORMAT_R8G8B8A8_UINT); + ENUM_NAME(DXGI_FORMAT_R8G8B8A8_SNORM); + ENUM_NAME(DXGI_FORMAT_R8G8B8A8_SINT); + ENUM_NAME(DXGI_FORMAT_R16G16_TYPELESS); + ENUM_NAME(DXGI_FORMAT_R16G16_FLOAT); + ENUM_NAME(DXGI_FORMAT_R16G16_UNORM); + ENUM_NAME(DXGI_FORMAT_R16G16_UINT); + ENUM_NAME(DXGI_FORMAT_R16G16_SNORM); + ENUM_NAME(DXGI_FORMAT_R16G16_SINT); + ENUM_NAME(DXGI_FORMAT_R32_TYPELESS); + ENUM_NAME(DXGI_FORMAT_D32_FLOAT); + ENUM_NAME(DXGI_FORMAT_R32_FLOAT); + ENUM_NAME(DXGI_FORMAT_R32_UINT); + ENUM_NAME(DXGI_FORMAT_R32_SINT); + ENUM_NAME(DXGI_FORMAT_R24G8_TYPELESS); + ENUM_NAME(DXGI_FORMAT_D24_UNORM_S8_UINT); + ENUM_NAME(DXGI_FORMAT_R24_UNORM_X8_TYPELESS); + ENUM_NAME(DXGI_FORMAT_X24_TYPELESS_G8_UINT); + ENUM_NAME(DXGI_FORMAT_R8G8_TYPELESS); + ENUM_NAME(DXGI_FORMAT_R8G8_UNORM); + ENUM_NAME(DXGI_FORMAT_R8G8_UINT); + ENUM_NAME(DXGI_FORMAT_R8G8_SNORM); + ENUM_NAME(DXGI_FORMAT_R8G8_SINT); + ENUM_NAME(DXGI_FORMAT_R16_TYPELESS); + ENUM_NAME(DXGI_FORMAT_R16_FLOAT); + ENUM_NAME(DXGI_FORMAT_D16_UNORM); + ENUM_NAME(DXGI_FORMAT_R16_UNORM); + ENUM_NAME(DXGI_FORMAT_R16_UINT); + ENUM_NAME(DXGI_FORMAT_R16_SNORM); + ENUM_NAME(DXGI_FORMAT_R16_SINT); + ENUM_NAME(DXGI_FORMAT_R8_TYPELESS); + ENUM_NAME(DXGI_FORMAT_R8_UNORM); + ENUM_NAME(DXGI_FORMAT_R8_UINT); + ENUM_NAME(DXGI_FORMAT_R8_SNORM); + ENUM_NAME(DXGI_FORMAT_R8_SINT); + ENUM_NAME(DXGI_FORMAT_A8_UNORM); + ENUM_NAME(DXGI_FORMAT_R1_UNORM); + ENUM_NAME(DXGI_FORMAT_R9G9B9E5_SHAREDEXP); + ENUM_NAME(DXGI_FORMAT_R8G8_B8G8_UNORM); + ENUM_NAME(DXGI_FORMAT_G8R8_G8B8_UNORM); + ENUM_NAME(DXGI_FORMAT_BC1_TYPELESS); + ENUM_NAME(DXGI_FORMAT_BC1_UNORM); + ENUM_NAME(DXGI_FORMAT_BC1_UNORM_SRGB); + ENUM_NAME(DXGI_FORMAT_BC2_TYPELESS); + ENUM_NAME(DXGI_FORMAT_BC2_UNORM); + ENUM_NAME(DXGI_FORMAT_BC2_UNORM_SRGB); + ENUM_NAME(DXGI_FORMAT_BC3_TYPELESS); + ENUM_NAME(DXGI_FORMAT_BC3_UNORM); + ENUM_NAME(DXGI_FORMAT_BC3_UNORM_SRGB); + ENUM_NAME(DXGI_FORMAT_BC4_TYPELESS); + ENUM_NAME(DXGI_FORMAT_BC4_UNORM); + ENUM_NAME(DXGI_FORMAT_BC4_SNORM); + ENUM_NAME(DXGI_FORMAT_BC5_TYPELESS); + ENUM_NAME(DXGI_FORMAT_BC5_UNORM); + ENUM_NAME(DXGI_FORMAT_BC5_SNORM); + ENUM_NAME(DXGI_FORMAT_B5G6R5_UNORM); + ENUM_NAME(DXGI_FORMAT_B5G5R5A1_UNORM); + ENUM_NAME(DXGI_FORMAT_B8G8R8A8_UNORM); + ENUM_NAME(DXGI_FORMAT_B8G8R8X8_UNORM); + ENUM_NAME(DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM); + ENUM_NAME(DXGI_FORMAT_B8G8R8A8_TYPELESS); + ENUM_NAME(DXGI_FORMAT_B8G8R8A8_UNORM_SRGB); + ENUM_NAME(DXGI_FORMAT_B8G8R8X8_TYPELESS); + ENUM_NAME(DXGI_FORMAT_B8G8R8X8_UNORM_SRGB); + ENUM_NAME(DXGI_FORMAT_BC6H_TYPELESS); + ENUM_NAME(DXGI_FORMAT_BC6H_UF16); + ENUM_NAME(DXGI_FORMAT_BC6H_SF16); + ENUM_NAME(DXGI_FORMAT_BC7_TYPELESS); + ENUM_NAME(DXGI_FORMAT_BC7_UNORM); + ENUM_NAME(DXGI_FORMAT_BC7_UNORM_SRGB); + ENUM_NAME(DXGI_FORMAT_AYUV); + ENUM_NAME(DXGI_FORMAT_Y410); + ENUM_NAME(DXGI_FORMAT_Y416); + ENUM_NAME(DXGI_FORMAT_NV12); + ENUM_NAME(DXGI_FORMAT_P010); + ENUM_NAME(DXGI_FORMAT_P016); + ENUM_NAME(DXGI_FORMAT_420_OPAQUE); + ENUM_NAME(DXGI_FORMAT_YUY2); + ENUM_NAME(DXGI_FORMAT_Y210); + ENUM_NAME(DXGI_FORMAT_Y216); + ENUM_NAME(DXGI_FORMAT_NV11); + ENUM_NAME(DXGI_FORMAT_AI44); + ENUM_NAME(DXGI_FORMAT_IA44); + ENUM_NAME(DXGI_FORMAT_P8); + ENUM_NAME(DXGI_FORMAT_A8P8); + ENUM_NAME(DXGI_FORMAT_B4G4R4A4_UNORM); + ENUM_DEFAULT(e); + } +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxgi/dxgi_enums.h b/utils/dxvk-1.10.3/src/dxgi/dxgi_enums.h new file mode 100644 index 00000000000..2a48427ebea --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxgi/dxgi_enums.h @@ -0,0 +1,5 @@ +#pragma once + +#include "dxgi_include.h" + +std::ostream& operator << (std::ostream& os, DXGI_FORMAT e); diff --git a/utils/dxvk-1.10.3/src/dxgi/dxgi_factory.cpp b/utils/dxvk-1.10.3/src/dxgi/dxgi_factory.cpp new file mode 100644 index 00000000000..f159999ddb3 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxgi/dxgi_factory.cpp @@ -0,0 +1,401 @@ +#include "dxgi_factory.h" +#include "dxgi_swapchain.h" +#include "dxgi_swapchain_dispatcher.h" + +namespace dxvk { + + DxgiFactory::DxgiFactory(UINT Flags) + : m_instance (new DxvkInstance()), + m_monitorInfo (this), + m_options (m_instance->config()), + m_flags (Flags) { + for (uint32_t i = 0; m_instance->enumAdapters(i) != nullptr; i++) + m_instance->enumAdapters(i)->logAdapterInfo(); + } + + + DxgiFactory::~DxgiFactory() { + + } + + + HRESULT STDMETHODCALLTYPE DxgiFactory::QueryInterface(REFIID riid, void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(IDXGIObject) + || riid == __uuidof(IDXGIFactory) + || riid == __uuidof(IDXGIFactory1) + || riid == __uuidof(IDXGIFactory2) + || riid == __uuidof(IDXGIFactory3) + || riid == __uuidof(IDXGIFactory4) + || riid == __uuidof(IDXGIFactory5) + || riid == __uuidof(IDXGIFactory6) + || riid == __uuidof(IDXGIFactory7)) { + *ppvObject = ref(this); + return S_OK; + } + + if (riid == __uuidof(IDXGIVkMonitorInfo)) { + *ppvObject = ref(&m_monitorInfo); + return S_OK; + } + + Logger::warn("DxgiFactory::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + HRESULT STDMETHODCALLTYPE DxgiFactory::GetParent(REFIID riid, void** ppParent) { + InitReturnPtr(ppParent); + + Logger::warn("DxgiFactory::GetParent: Unknown interface query"); + return E_NOINTERFACE; + } + + + BOOL STDMETHODCALLTYPE DxgiFactory::IsWindowedStereoEnabled() { + // We don't support Stereo 3D at the moment + return FALSE; + } + + + HRESULT STDMETHODCALLTYPE DxgiFactory::CreateSoftwareAdapter( + HMODULE Module, + IDXGIAdapter** ppAdapter) { + InitReturnPtr(ppAdapter); + + if (ppAdapter == nullptr) + return DXGI_ERROR_INVALID_CALL; + + Logger::err("DXGI: CreateSoftwareAdapter: Software adapters not supported"); + return DXGI_ERROR_UNSUPPORTED; + } + + + HRESULT STDMETHODCALLTYPE DxgiFactory::CreateSwapChain( + IUnknown* pDevice, + DXGI_SWAP_CHAIN_DESC* pDesc, + IDXGISwapChain** ppSwapChain) { + if (ppSwapChain == nullptr || pDesc == nullptr || pDevice == nullptr) + return DXGI_ERROR_INVALID_CALL; + + DXGI_SWAP_CHAIN_DESC1 desc; + desc.Width = pDesc->BufferDesc.Width; + desc.Height = pDesc->BufferDesc.Height; + desc.Format = pDesc->BufferDesc.Format; + desc.Stereo = FALSE; + desc.SampleDesc = pDesc->SampleDesc; + desc.BufferUsage = pDesc->BufferUsage; + desc.BufferCount = pDesc->BufferCount; + desc.Scaling = DXGI_SCALING_STRETCH; + desc.SwapEffect = pDesc->SwapEffect; + desc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + desc.Flags = pDesc->Flags; + + DXGI_SWAP_CHAIN_FULLSCREEN_DESC descFs; + descFs.RefreshRate = pDesc->BufferDesc.RefreshRate; + descFs.ScanlineOrdering = pDesc->BufferDesc.ScanlineOrdering; + descFs.Scaling = pDesc->BufferDesc.Scaling; + descFs.Windowed = pDesc->Windowed; + + IDXGISwapChain1* swapChain = nullptr; + HRESULT hr = CreateSwapChainForHwnd( + pDevice, pDesc->OutputWindow, + &desc, &descFs, nullptr, + &swapChain); + + *ppSwapChain = swapChain; + return hr; + } + + + HRESULT STDMETHODCALLTYPE DxgiFactory::CreateSwapChainForHwnd( + IUnknown* pDevice, + HWND hWnd, + const DXGI_SWAP_CHAIN_DESC1* pDesc, + const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc, + IDXGIOutput* pRestrictToOutput, + IDXGISwapChain1** ppSwapChain) { + InitReturnPtr(ppSwapChain); + + if (!ppSwapChain || !pDesc || !hWnd || !pDevice) + return DXGI_ERROR_INVALID_CALL; + + Com wineDevice; + + if (SUCCEEDED(pDevice->QueryInterface( + __uuidof(IWineDXGISwapChainFactory), + reinterpret_cast(&wineDevice)))) { + IDXGISwapChain4* frontendSwapChain; + + HRESULT hr = wineDevice->CreateSwapChainForHwnd( + this, hWnd, pDesc, pFullscreenDesc, + pRestrictToOutput, reinterpret_cast(&frontendSwapChain)); + + // No ref as that's handled by the object we're wrapping + // which was ref'ed on creation. + if (SUCCEEDED(hr)) + *ppSwapChain = new DxgiSwapChainDispatcher(frontendSwapChain); + + return hr; + } + + Logger::err("DXGI: CreateSwapChainForHwnd: Unsupported device type"); + return DXGI_ERROR_UNSUPPORTED; + } + + + HRESULT STDMETHODCALLTYPE DxgiFactory::CreateSwapChainForCoreWindow( + IUnknown* pDevice, + IUnknown* pWindow, + const DXGI_SWAP_CHAIN_DESC1* pDesc, + IDXGIOutput* pRestrictToOutput, + IDXGISwapChain1** ppSwapChain) { + InitReturnPtr(ppSwapChain); + + Logger::err("DxgiFactory::CreateSwapChainForCoreWindow: Not implemented"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE DxgiFactory::CreateSwapChainForComposition( + IUnknown* pDevice, + const DXGI_SWAP_CHAIN_DESC1* pDesc, + IDXGIOutput* pRestrictToOutput, + IDXGISwapChain1** ppSwapChain) { + InitReturnPtr(ppSwapChain); + + Logger::err("DxgiFactory::CreateSwapChainForComposition: Not implemented"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE DxgiFactory::EnumAdapters( + UINT Adapter, + IDXGIAdapter** ppAdapter) { + InitReturnPtr(ppAdapter); + + if (ppAdapter == nullptr) + return DXGI_ERROR_INVALID_CALL; + + IDXGIAdapter1* handle = nullptr; + HRESULT hr = this->EnumAdapters1(Adapter, &handle); + *ppAdapter = handle; + return hr; + } + + + HRESULT STDMETHODCALLTYPE DxgiFactory::EnumAdapters1( + UINT Adapter, + IDXGIAdapter1** ppAdapter) { + InitReturnPtr(ppAdapter); + + if (ppAdapter == nullptr) + return DXGI_ERROR_INVALID_CALL; + + Rc dxvkAdapter + = m_instance->enumAdapters(Adapter); + + if (dxvkAdapter == nullptr) + return DXGI_ERROR_NOT_FOUND; + + *ppAdapter = ref(new DxgiAdapter(this, dxvkAdapter, Adapter)); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE DxgiFactory::EnumAdapterByLuid( + LUID AdapterLuid, + REFIID riid, + void** ppvAdapter) { + InitReturnPtr(ppvAdapter); + uint32_t adapterId = 0; + + while (true) { + Com adapter; + HRESULT hr = EnumAdapters(adapterId++, &adapter); + + if (FAILED(hr)) + return hr; + + DXGI_ADAPTER_DESC desc; + adapter->GetDesc(&desc); + + if (!std::memcmp(&AdapterLuid, &desc.AdapterLuid, sizeof(LUID))) + return adapter->QueryInterface(riid, ppvAdapter); + } + + // This should be unreachable + return DXGI_ERROR_NOT_FOUND; + } + + + HRESULT STDMETHODCALLTYPE DxgiFactory::EnumAdapterByGpuPreference( + UINT Adapter, + DXGI_GPU_PREFERENCE GpuPreference, + REFIID riid, + void** ppvAdapter) { + InitReturnPtr(ppvAdapter); + uint32_t adapterCount = m_instance->adapterCount(); + + if (Adapter >= adapterCount) + return DXGI_ERROR_NOT_FOUND; + + // We know that the backend lists dedicated GPUs before + // any integrated ones, so just list adapters in reverse + // order. We have no other way to estimate performance. + if (GpuPreference == DXGI_GPU_PREFERENCE_MINIMUM_POWER) + Adapter = adapterCount - Adapter - 1; + + Com adapter; + HRESULT hr = this->EnumAdapters(Adapter, &adapter); + + if (FAILED(hr)) + return hr; + + return adapter->QueryInterface(riid, ppvAdapter); + } + + + HRESULT STDMETHODCALLTYPE DxgiFactory::EnumWarpAdapter( + REFIID riid, + void** ppvAdapter) { + InitReturnPtr(ppvAdapter); + + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::warn("DxgiFactory::EnumWarpAdapter: WARP not supported, returning first hardware adapter"); + + Com adapter; + HRESULT hr = EnumAdapters1(0, &adapter); + + if (FAILED(hr)) + return hr; + + return adapter->QueryInterface(riid, ppvAdapter); + } + + + HRESULT STDMETHODCALLTYPE DxgiFactory::GetWindowAssociation(HWND *pWindowHandle) { + if (pWindowHandle == nullptr) + return DXGI_ERROR_INVALID_CALL; + + *pWindowHandle = m_associatedWindow; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE DxgiFactory::GetSharedResourceAdapterLuid( + HANDLE hResource, + LUID* pLuid) { + Logger::err("DxgiFactory::GetSharedResourceAdapterLuid: Not implemented"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE DxgiFactory::MakeWindowAssociation(HWND WindowHandle, UINT Flags) { + Logger::warn("DXGI: MakeWindowAssociation: Ignoring flags"); + m_associatedWindow = WindowHandle; + return S_OK; + } + + + BOOL STDMETHODCALLTYPE DxgiFactory::IsCurrent() { + return TRUE; + } + + + HRESULT STDMETHODCALLTYPE DxgiFactory::RegisterOcclusionStatusWindow( + HWND WindowHandle, + UINT wMsg, + DWORD* pdwCookie) { + Logger::err("DxgiFactory::RegisterOcclusionStatusWindow: Not implemented"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE DxgiFactory::RegisterStereoStatusEvent( + HANDLE hEvent, + DWORD* pdwCookie) { + Logger::err("DxgiFactory::RegisterStereoStatusEvent: Not implemented"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE DxgiFactory::RegisterStereoStatusWindow( + HWND WindowHandle, + UINT wMsg, + DWORD* pdwCookie) { + Logger::err("DxgiFactory::RegisterStereoStatusWindow: Not implemented"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE DxgiFactory::RegisterOcclusionStatusEvent( + HANDLE hEvent, + DWORD* pdwCookie) { + Logger::err("DxgiFactory::RegisterOcclusionStatusEvent: Not implemented"); + return E_NOTIMPL; + } + + + void STDMETHODCALLTYPE DxgiFactory::UnregisterStereoStatus( + DWORD dwCookie) { + Logger::err("DxgiFactory::UnregisterStereoStatus: Not implemented"); + } + + + void STDMETHODCALLTYPE DxgiFactory::UnregisterOcclusionStatus( + DWORD dwCookie) { + Logger::err("DxgiFactory::UnregisterOcclusionStatus: Not implemented"); + } + + + UINT STDMETHODCALLTYPE DxgiFactory::GetCreationFlags() { + return m_flags; + } + + + HRESULT STDMETHODCALLTYPE DxgiFactory::CheckFeatureSupport( + DXGI_FEATURE Feature, + void* pFeatureSupportData, + UINT FeatureSupportDataSize) { + switch (Feature) { + case DXGI_FEATURE_PRESENT_ALLOW_TEARING: { + auto info = static_cast(pFeatureSupportData); + + if (FeatureSupportDataSize != sizeof(*info)) + return E_INVALIDARG; + + *info = TRUE; + } return S_OK; + + default: + Logger::err(str::format("DxgiFactory: CheckFeatureSupport: Unknown feature: ", uint32_t(Feature))); + return E_INVALIDARG; + } + } + + + HRESULT STDMETHODCALLTYPE DxgiFactory::RegisterAdaptersChangedEvent( + HANDLE hEvent, + DWORD* pdwCookie) { + Logger::err("DxgiFactory: RegisterAdaptersChangedEvent: Stub"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE DxgiFactory::UnregisterAdaptersChangedEvent( + DWORD Cookie) { + Logger::err("DxgiFactory: UnregisterAdaptersChangedEvent: Stub"); + return E_NOTIMPL; + } + + +} diff --git a/utils/dxvk-1.10.3/src/dxgi/dxgi_factory.h b/utils/dxvk-1.10.3/src/dxgi/dxgi_factory.h new file mode 100644 index 00000000000..f398c78d9a1 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxgi/dxgi_factory.h @@ -0,0 +1,157 @@ +#pragma once + +#include + +#include "dxgi_adapter.h" +#include "dxgi_monitor.h" +#include "dxgi_options.h" + +#include "../dxvk/dxvk_instance.h" + +namespace dxvk { + + class DxgiFactory : public DxgiObject { + + public: + + DxgiFactory(UINT Flags); + ~DxgiFactory(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject) final; + + HRESULT STDMETHODCALLTYPE GetParent( + REFIID riid, + void** ppParent) final; + + BOOL STDMETHODCALLTYPE IsWindowedStereoEnabled() final; + + HRESULT STDMETHODCALLTYPE CreateSoftwareAdapter( + HMODULE Module, + IDXGIAdapter** ppAdapter) final; + + HRESULT STDMETHODCALLTYPE CreateSwapChain( + IUnknown* pDevice, + DXGI_SWAP_CHAIN_DESC* pDesc, + IDXGISwapChain** ppSwapChain) final; + + HRESULT STDMETHODCALLTYPE CreateSwapChainForHwnd( + IUnknown* pDevice, + HWND hWnd, + const DXGI_SWAP_CHAIN_DESC1* pDesc, + const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc, + IDXGIOutput* pRestrictToOutput, + IDXGISwapChain1** ppSwapChain) final; + + HRESULT STDMETHODCALLTYPE CreateSwapChainForCoreWindow( + IUnknown* pDevice, + IUnknown* pWindow, + const DXGI_SWAP_CHAIN_DESC1* pDesc, + IDXGIOutput* pRestrictToOutput, + IDXGISwapChain1** ppSwapChain) final; + + HRESULT STDMETHODCALLTYPE CreateSwapChainForComposition( + IUnknown* pDevice, + const DXGI_SWAP_CHAIN_DESC1* pDesc, + IDXGIOutput* pRestrictToOutput, + IDXGISwapChain1** ppSwapChain) final; + + HRESULT STDMETHODCALLTYPE EnumAdapters( + UINT Adapter, + IDXGIAdapter** ppAdapter) final; + + HRESULT STDMETHODCALLTYPE EnumAdapters1( + UINT Adapter, + IDXGIAdapter1** ppAdapter) final; + + HRESULT STDMETHODCALLTYPE EnumAdapterByLuid( + LUID AdapterLuid, + REFIID riid, + void** ppvAdapter) final; + + HRESULT STDMETHODCALLTYPE EnumAdapterByGpuPreference( + UINT Adapter, + DXGI_GPU_PREFERENCE GpuPreference, + REFIID riid, + void** ppvAdapter); + + HRESULT STDMETHODCALLTYPE EnumWarpAdapter( + REFIID riid, + void** ppvAdapter) final; + + HRESULT STDMETHODCALLTYPE GetWindowAssociation( + HWND* pWindowHandle) final; + + HRESULT STDMETHODCALLTYPE GetSharedResourceAdapterLuid( + HANDLE hResource, + LUID* pLuid) final; + + HRESULT STDMETHODCALLTYPE MakeWindowAssociation( + HWND WindowHandle, + UINT Flags) final; + + BOOL STDMETHODCALLTYPE IsCurrent() final; + + HRESULT STDMETHODCALLTYPE RegisterOcclusionStatusWindow( + HWND WindowHandle, + UINT wMsg, + DWORD* pdwCookie) final; + + HRESULT STDMETHODCALLTYPE RegisterStereoStatusEvent( + HANDLE hEvent, + DWORD* pdwCookie) final; + + HRESULT STDMETHODCALLTYPE RegisterStereoStatusWindow( + HWND WindowHandle, + UINT wMsg, + DWORD* pdwCookie) final; + + HRESULT STDMETHODCALLTYPE RegisterOcclusionStatusEvent( + HANDLE hEvent, + DWORD* pdwCookie) final; + + void STDMETHODCALLTYPE UnregisterStereoStatus( + DWORD dwCookie) final; + + void STDMETHODCALLTYPE UnregisterOcclusionStatus( + DWORD dwCookie) final; + + UINT STDMETHODCALLTYPE GetCreationFlags() final; + + HRESULT STDMETHODCALLTYPE CheckFeatureSupport( + DXGI_FEATURE Feature, + void* pFeatureSupportData, + UINT FeatureSupportDataSize) final; + + HRESULT STDMETHODCALLTYPE RegisterAdaptersChangedEvent( + HANDLE hEvent, + DWORD* pdwCookie); + + HRESULT STDMETHODCALLTYPE UnregisterAdaptersChangedEvent( + DWORD Cookie); + + Rc GetDXVKInstance() const { + return m_instance; + } + + const DxgiOptions* GetOptions() const { + return &m_options; + } + + DxgiMonitorInfo* GetMonitorInfo() { + return &m_monitorInfo; + } + + private: + + Rc m_instance; + DxgiMonitorInfo m_monitorInfo; + DxgiOptions m_options; + UINT m_flags; + + HWND m_associatedWindow = nullptr; + + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxgi/dxgi_format.cpp b/utils/dxvk-1.10.3/src/dxgi/dxgi_format.cpp new file mode 100644 index 00000000000..a8551da6fad --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxgi/dxgi_format.cpp @@ -0,0 +1,977 @@ +#include "dxgi_format.h" + +#include + +namespace dxvk { + + const std::array g_dxgiFormats = {{ + // DXGI_FORMAT_UNKNOWN + { }, + // DXGI_FORMAT_R32G32B32A32_TYPELESS + { VK_FORMAT_R32G32B32A32_UINT, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R32G32B32A32_UINT }, + // DXGI_FORMAT_R32G32B32A32_FLOAT + { VK_FORMAT_R32G32B32A32_SFLOAT, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R32G32B32A32_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R32G32B32A32_UINT + { VK_FORMAT_R32G32B32A32_UINT, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R32G32B32A32_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R32G32B32A32_SINT + { VK_FORMAT_R32G32B32A32_SINT, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R32G32B32A32_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R32G32B32_TYPELESS + { VK_FORMAT_R32G32B32_UINT, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R32G32B32_UINT }, + // DXGI_FORMAT_R32G32B32_FLOAT + { VK_FORMAT_R32G32B32_SFLOAT, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R32G32B32_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R32G32B32_UINT + { VK_FORMAT_R32G32B32_UINT, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R32G32B32_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R32G32B32_SINT + { VK_FORMAT_R32G32B32_SINT, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R32G32B32_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R16G16B16A16_TYPELESS + { VK_FORMAT_R16G16B16A16_UNORM, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R16G16B16A16_UINT }, + // DXGI_FORMAT_R16G16B16A16_FLOAT + { VK_FORMAT_R16G16B16A16_SFLOAT, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R16G16B16A16_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R16G16B16A16_UNORM + { VK_FORMAT_R16G16B16A16_UNORM, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R16G16B16A16_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R16G16B16A16_UINT + { VK_FORMAT_R16G16B16A16_UINT, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R16G16B16A16_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R16G16B16A16_SNORM + { VK_FORMAT_R16G16B16A16_SNORM, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R16G16B16A16_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R16G16B16A16_SINT + { VK_FORMAT_R16G16B16A16_SINT, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R16G16B16A16_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R32G32_TYPELESS + { VK_FORMAT_R32G32_UINT, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R32G32_UINT }, + // DXGI_FORMAT_R32G32_FLOAT + { VK_FORMAT_R32G32_SFLOAT, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R32G32_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R32G32_UINT + { VK_FORMAT_R32G32_UINT, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R32G32_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R32G32_SINT + { VK_FORMAT_R32G32_SINT, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R32G32_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R32G8X24_TYPELESS + { VK_FORMAT_UNDEFINED, + VK_FORMAT_D32_SFLOAT_S8_UINT, + VK_FORMAT_UNDEFINED }, + // DXGI_FORMAT_D32_FLOAT_S8X24_UINT + { VK_FORMAT_UNDEFINED, + VK_FORMAT_D32_SFLOAT_S8_UINT, + VK_FORMAT_UNDEFINED, + 0, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT }, + // DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS + { VK_FORMAT_UNDEFINED, + VK_FORMAT_D32_SFLOAT_S8_UINT, + VK_FORMAT_UNDEFINED, + 0, VK_IMAGE_ASPECT_DEPTH_BIT }, + // DXGI_FORMAT_X32_TYPELESS_G8X24_UINT + { VK_FORMAT_UNDEFINED, + VK_FORMAT_D32_SFLOAT_S8_UINT, + VK_FORMAT_UNDEFINED, + 0, VK_IMAGE_ASPECT_STENCIL_BIT }, + // DXGI_FORMAT_R10G10B10A2_TYPELESS + { VK_FORMAT_A2B10G10R10_UNORM_PACK32, + VK_FORMAT_UNDEFINED, + VK_FORMAT_A2B10G10R10_UINT_PACK32 }, + // DXGI_FORMAT_R10G10B10A2_UNORM + { VK_FORMAT_A2B10G10R10_UNORM_PACK32, + VK_FORMAT_UNDEFINED, + VK_FORMAT_A2B10G10R10_UINT_PACK32, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R10G10B10A2_UINT + { VK_FORMAT_A2B10G10R10_UINT_PACK32, + VK_FORMAT_UNDEFINED, + VK_FORMAT_A2B10G10R10_UINT_PACK32, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R11G11B10_FLOAT + { VK_FORMAT_B10G11R11_UFLOAT_PACK32, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R32_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R8G8B8A8_TYPELESS + { VK_FORMAT_R8G8B8A8_UNORM, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R8G8B8A8_UINT }, + // DXGI_FORMAT_R8G8B8A8_UNORM + { VK_FORMAT_R8G8B8A8_UNORM, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R8G8B8A8_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R8G8B8A8_UNORM_SRGB + { VK_FORMAT_R8G8B8A8_SRGB, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R8G8B8A8_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R8G8B8A8_UINT + { VK_FORMAT_R8G8B8A8_UINT, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R8G8B8A8_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R8G8B8A8_SNORM + { VK_FORMAT_R8G8B8A8_SNORM, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R8G8B8A8_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R8G8B8A8_SINT + { VK_FORMAT_R8G8B8A8_SINT, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R8G8B8A8_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R16G16_TYPELESS + { VK_FORMAT_R16G16_UNORM, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R16G16_UINT }, + // DXGI_FORMAT_R16G16_FLOAT + { VK_FORMAT_R16G16_SFLOAT, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R16G16_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R16G16_UNORM + { VK_FORMAT_R16G16_UNORM, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R16G16_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R16G16_UINT + { VK_FORMAT_R16G16_UINT, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R16G16_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R16G16_SNORM + { VK_FORMAT_R16G16_SNORM, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R16G16_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R16G16_SINT + { VK_FORMAT_R16G16_SINT, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R16G16_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R32_TYPELESS + { VK_FORMAT_R32_UINT, + VK_FORMAT_D32_SFLOAT, + VK_FORMAT_R32_UINT }, + // DXGI_FORMAT_D32_FLOAT + { VK_FORMAT_UNDEFINED, + VK_FORMAT_D32_SFLOAT, + VK_FORMAT_UNDEFINED, + 0, VK_IMAGE_ASPECT_DEPTH_BIT }, + // DXGI_FORMAT_R32_FLOAT + { VK_FORMAT_R32_SFLOAT, + VK_FORMAT_D32_SFLOAT, + VK_FORMAT_R32_UINT, + VK_IMAGE_ASPECT_COLOR_BIT, + VK_IMAGE_ASPECT_DEPTH_BIT }, + // DXGI_FORMAT_R32_UINT + { VK_FORMAT_R32_UINT, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R32_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R32_SINT + { VK_FORMAT_R32_SINT, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R32_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R24G8_TYPELESS + { VK_FORMAT_UNDEFINED, + VK_FORMAT_D24_UNORM_S8_UINT, + VK_FORMAT_UNDEFINED }, + // DXGI_FORMAT_D24_UNORM_S8_UINT + { VK_FORMAT_UNDEFINED, + VK_FORMAT_D24_UNORM_S8_UINT, + VK_FORMAT_UNDEFINED, + 0, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT }, + // DXGI_FORMAT_R24_UNORM_X8_TYPELESS + { VK_FORMAT_UNDEFINED, + VK_FORMAT_D24_UNORM_S8_UINT, + VK_FORMAT_UNDEFINED, + 0, VK_IMAGE_ASPECT_DEPTH_BIT }, + // DXGI_FORMAT_X24_TYPELESS_G8_UINT + { VK_FORMAT_UNDEFINED, + VK_FORMAT_D24_UNORM_S8_UINT, + VK_FORMAT_UNDEFINED, + 0, VK_IMAGE_ASPECT_STENCIL_BIT }, + // DXGI_FORMAT_R8G8_TYPELESS + { VK_FORMAT_R8G8_UNORM, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R8G8_UINT }, + // DXGI_FORMAT_R8G8_UNORM + { VK_FORMAT_R8G8_UNORM, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R8G8_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R8G8_UINT + { VK_FORMAT_R8G8_UINT, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R8G8_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R8G8_SNORM + { VK_FORMAT_R8G8_SNORM, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R8G8_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R8G8_SINT + { VK_FORMAT_R8G8_SINT, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R8G8_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R16_TYPELESS + { VK_FORMAT_R16_UNORM, + VK_FORMAT_D16_UNORM, + VK_FORMAT_R16_UINT }, + // DXGI_FORMAT_R16_FLOAT + { VK_FORMAT_R16_SFLOAT, + VK_FORMAT_D16_UNORM, + VK_FORMAT_R16_UINT, + VK_IMAGE_ASPECT_COLOR_BIT, + VK_IMAGE_ASPECT_DEPTH_BIT }, + // DXGI_FORMAT_D16_UNORM + { VK_FORMAT_UNDEFINED, + VK_FORMAT_D16_UNORM, + VK_FORMAT_UNDEFINED, + 0, VK_IMAGE_ASPECT_DEPTH_BIT }, + // DXGI_FORMAT_R16_UNORM + { VK_FORMAT_R16_UNORM, + VK_FORMAT_D16_UNORM, + VK_FORMAT_R16_UINT, + VK_IMAGE_ASPECT_COLOR_BIT, + VK_IMAGE_ASPECT_DEPTH_BIT }, + // DXGI_FORMAT_R16_UINT + { VK_FORMAT_R16_UINT, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R16_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R16_SNORM + { VK_FORMAT_R16_SNORM, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R16_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R16_SINT + { VK_FORMAT_R16_SINT, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R16_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R8_TYPELESS + { VK_FORMAT_R8_UNORM, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R8_UINT }, + // DXGI_FORMAT_R8_UNORM + { VK_FORMAT_R8_UNORM, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R8_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R8_UINT + { VK_FORMAT_R8_UINT, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R8_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R8_SNORM + { VK_FORMAT_R8_SNORM, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R8_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R8_SINT + { VK_FORMAT_R8_SINT, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R8_UINT, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_A8_UNORM + { VK_FORMAT_R8_UNORM, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT, 0, + { VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO, + VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_R }}, + // DXGI_FORMAT_R1_UNORM + { }, // Unsupported + // DXGI_FORMAT_R9G9B9E5_SHAREDEXP + { VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_R8G8_B8G8_UNORM + { VK_FORMAT_B8G8R8G8_422_UNORM, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_G8R8_G8B8_UNORM + { VK_FORMAT_G8B8G8R8_422_UNORM, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_BC1_TYPELESS + { VK_FORMAT_BC1_RGBA_UNORM_BLOCK, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED }, + // DXGI_FORMAT_BC1_UNORM + { VK_FORMAT_BC1_RGBA_UNORM_BLOCK, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_BC1_UNORM_SRGB + { VK_FORMAT_BC1_RGBA_SRGB_BLOCK, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_BC2_TYPELESS + { VK_FORMAT_BC2_UNORM_BLOCK, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED }, + // DXGI_FORMAT_BC2_UNORM + { VK_FORMAT_BC2_UNORM_BLOCK, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_BC2_UNORM_SRGB + { VK_FORMAT_BC2_SRGB_BLOCK, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_BC3_TYPELESS + { VK_FORMAT_BC3_UNORM_BLOCK, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED }, + // DXGI_FORMAT_BC3_UNORM + { VK_FORMAT_BC3_UNORM_BLOCK, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_BC3_UNORM_SRGB + { VK_FORMAT_BC3_SRGB_BLOCK, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_BC4_TYPELESS + { VK_FORMAT_BC4_UNORM_BLOCK, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED }, + // DXGI_FORMAT_BC4_UNORM + { VK_FORMAT_BC4_UNORM_BLOCK, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_BC4_SNORM + { VK_FORMAT_BC4_SNORM_BLOCK, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_BC5_TYPELESS + { VK_FORMAT_BC5_UNORM_BLOCK, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED }, + // DXGI_FORMAT_BC5_UNORM + { VK_FORMAT_BC5_UNORM_BLOCK, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_BC5_SNORM + { VK_FORMAT_BC5_SNORM_BLOCK, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_B5G6R5_UNORM + { VK_FORMAT_R5G6B5_UNORM_PACK16, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_B5G5R5A1_UNORM + { VK_FORMAT_A1R5G5B5_UNORM_PACK16, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_B8G8R8A8_UNORM + { VK_FORMAT_B8G8R8A8_UNORM, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_B8G8R8X8_UNORM + { VK_FORMAT_B8G8R8A8_UNORM, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT, 0, + { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, + VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_ONE }}, + // DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM + { }, // Unsupported + // DXGI_FORMAT_B8G8R8A8_TYPELESS + { VK_FORMAT_B8G8R8A8_UNORM, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED }, + // DXGI_FORMAT_B8G8R8A8_UNORM_SRGB + { VK_FORMAT_B8G8R8A8_SRGB, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_B8G8R8X8_TYPELESS + { VK_FORMAT_B8G8R8A8_UNORM, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_B8G8R8X8_UNORM_SRGB + { VK_FORMAT_B8G8R8A8_SRGB, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT, 0, + { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, + VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_ONE }}, + // DXGI_FORMAT_BC6H_TYPELESS + { VK_FORMAT_BC6H_UFLOAT_BLOCK, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED }, + // DXGI_FORMAT_BC6H_UF16 + { VK_FORMAT_BC6H_UFLOAT_BLOCK, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_BC6H_SF16 + { VK_FORMAT_BC6H_SFLOAT_BLOCK, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_BC7_TYPELESS + { VK_FORMAT_BC7_UNORM_BLOCK, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED }, + // DXGI_FORMAT_BC7_UNORM + { VK_FORMAT_BC7_UNORM_BLOCK, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_BC7_UNORM_SRGB + { VK_FORMAT_BC7_SRGB_BLOCK, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_AYUV + { VK_FORMAT_R8G8B8A8_UNORM, + VK_FORMAT_UNDEFINED, + VK_FORMAT_R8G8B8A8_UINT, + VK_IMAGE_ASPECT_COLOR_BIT, 0, + { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_B, + VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_A } }, + // DXGI_FORMAT_Y410 + { }, // Unsupported + // DXGI_FORMAT_Y416 + { }, // Unsupported + // DXGI_FORMAT_NV12 + { VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT }, + // DXGI_FORMAT_P010 + { }, // Unsupported + // DXGI_FORMAT_P016 + { }, // Unsupported + // DXGI_FORMAT_420_OPAQUE + { VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT }, + // DXGI_FORMAT_YUY2 + { VK_FORMAT_G8B8G8R8_422_UNORM, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_Y210 + { }, // Unsupported + // DXGI_FORMAT_Y216 + { }, // Unsupported + // DXGI_FORMAT_NV11 + { }, // Unsupported + // DXGI_FORMAT_AI44 + { }, // Unsupported + // DXGI_FORMAT_IA44 + { }, // Unsupported + // DXGI_FORMAT_P8 + { }, // Unsupported + // DXGI_FORMAT_A8P8 + { }, // Unsupported + // DXGI_FORMAT_B4G4R4A4_UNORM + { VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT, + VK_FORMAT_UNDEFINED, + VK_FORMAT_UNDEFINED, + VK_IMAGE_ASPECT_COLOR_BIT }, + // DXGI_FORMAT_P208 + { }, // Unsupported + // DXGI_FORMAT_V208 + { }, // Unsupported + // DXGI_FORMAT_V408 + { }, // Unsupported + }}; + + + const std::array g_dxgiFamilies = {{ + // DXGI_FORMAT_UNKNOWN + { }, + // DXGI_FORMAT_R32G32B32A32_TYPELESS + { VK_FORMAT_R32G32B32A32_UINT, + VK_FORMAT_R32G32B32A32_SINT, + VK_FORMAT_R32G32B32A32_SFLOAT }, + // DXGI_FORMAT_R32G32B32A32_FLOAT + { }, + // DXGI_FORMAT_R32G32B32A32_UINT + { }, + // DXGI_FORMAT_R32G32B32A32_SINT + { }, + // DXGI_FORMAT_R32G32B32_TYPELESS + { VK_FORMAT_R32G32B32_UINT, + VK_FORMAT_R32G32B32_SINT, + VK_FORMAT_R32G32B32_SFLOAT }, + // DXGI_FORMAT_R32G32B32_FLOAT + { }, + // DXGI_FORMAT_R32G32B32_UINT + { }, + // DXGI_FORMAT_R32G32B32_SINT + { }, + // DXGI_FORMAT_R16G16B16A16_TYPELESS + { VK_FORMAT_R16G16B16A16_UNORM, + VK_FORMAT_R16G16B16A16_SNORM, + VK_FORMAT_R16G16B16A16_UINT, + VK_FORMAT_R16G16B16A16_SINT, + VK_FORMAT_R16G16B16A16_SFLOAT }, + // DXGI_FORMAT_R16G16B16A16_FLOAT + { }, + // DXGI_FORMAT_R16G16B16A16_UNORM + { }, + // DXGI_FORMAT_R16G16B16A16_UINT + { }, + // DXGI_FORMAT_R16G16B16A16_SNORM + { }, + // DXGI_FORMAT_R16G16B16A16_SINT + { }, + // DXGI_FORMAT_R32G32_TYPELESS + { VK_FORMAT_R32G32_UINT, + VK_FORMAT_R32G32_SINT, + VK_FORMAT_R32G32_SFLOAT }, + // DXGI_FORMAT_R32G32_FLOAT + { }, + // DXGI_FORMAT_R32G32_UINT + { }, + // DXGI_FORMAT_R32G32_SINT + { }, + // DXGI_FORMAT_R32G8X24_TYPELESS + { }, + // DXGI_FORMAT_D32_FLOAT_S8X24_UINT + { }, + // DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS + { }, + // DXGI_FORMAT_X32_TYPELESS_G8X24_UINT + { }, + // DXGI_FORMAT_R10G10B10A2_TYPELESS + { VK_FORMAT_A2B10G10R10_UNORM_PACK32, + VK_FORMAT_A2B10G10R10_UINT_PACK32 }, + // DXGI_FORMAT_R10G10B10A2_UNORM + { }, + // DXGI_FORMAT_R10G10B10A2_UINT + { }, + // DXGI_FORMAT_R11G11B10_FLOAT + { }, + // DXGI_FORMAT_R8G8B8A8_TYPELESS + { VK_FORMAT_R8G8B8A8_UNORM, + VK_FORMAT_R8G8B8A8_SNORM, + VK_FORMAT_R8G8B8A8_SRGB, + VK_FORMAT_R8G8B8A8_UINT, + VK_FORMAT_R8G8B8A8_SINT }, + // DXGI_FORMAT_R8G8B8A8_UNORM + { VK_FORMAT_R8G8B8A8_UNORM, + VK_FORMAT_R8G8B8A8_SRGB }, + // DXGI_FORMAT_R8G8B8A8_UNORM_SRGB + { VK_FORMAT_R8G8B8A8_UNORM, + VK_FORMAT_R8G8B8A8_SRGB }, + // DXGI_FORMAT_R8G8B8A8_UINT + { }, + // DXGI_FORMAT_R8G8B8A8_SNORM + { }, + // DXGI_FORMAT_R8G8B8A8_SINT + { }, + // DXGI_FORMAT_R16G16_TYPELESS + { VK_FORMAT_R16G16_UNORM, + VK_FORMAT_R16G16_SNORM, + VK_FORMAT_R16G16_UINT, + VK_FORMAT_R16G16_SINT, + VK_FORMAT_R16G16_SFLOAT }, + // DXGI_FORMAT_R16G16_FLOAT + { }, + // DXGI_FORMAT_R16G16_UNORM + { }, + // DXGI_FORMAT_R16G16_UINT + { }, + // DXGI_FORMAT_R16G16_SNORM + { }, + // DXGI_FORMAT_R16G16_SINT + { }, + // DXGI_FORMAT_R32_TYPELESS + { VK_FORMAT_R32_UINT, + VK_FORMAT_R32_SINT, + VK_FORMAT_R32_SFLOAT }, + // DXGI_FORMAT_D32_FLOAT + { }, + // DXGI_FORMAT_R32_FLOAT + { }, + // DXGI_FORMAT_R32_UINT + { }, + // DXGI_FORMAT_R32_SINT + { }, + // DXGI_FORMAT_R24G8_TYPELESS + { }, + // DXGI_FORMAT_D24_UNORM_S8_UINT + { }, + // DXGI_FORMAT_R24_UNORM_X8_TYPELESS + { }, + // DXGI_FORMAT_X24_TYPELESS_G8_UINT + { }, + // DXGI_FORMAT_R8G8_TYPELESS + { VK_FORMAT_R8G8_UNORM, + VK_FORMAT_R8G8_SNORM, + VK_FORMAT_R8G8_UINT, + VK_FORMAT_R8G8_SINT }, + // DXGI_FORMAT_R8G8_UNORM + { }, + // DXGI_FORMAT_R8G8_UINT + { }, + // DXGI_FORMAT_R8G8_SNORM + { }, + // DXGI_FORMAT_R8G8_SINT + { }, + // DXGI_FORMAT_R16_TYPELESS + { VK_FORMAT_R16_UNORM, + VK_FORMAT_R16_SNORM, + VK_FORMAT_R16_UINT, + VK_FORMAT_R16_SINT, + VK_FORMAT_R16_SFLOAT }, + // DXGI_FORMAT_R16_FLOAT + { }, + // DXGI_FORMAT_D16_UNORM + { }, + // DXGI_FORMAT_R16_UNORM + { }, + // DXGI_FORMAT_R16_UINT + { }, + // DXGI_FORMAT_R16_SNORM + { }, + // DXGI_FORMAT_R16_SINT + { }, + // DXGI_FORMAT_R8_TYPELESS + { VK_FORMAT_R8_UNORM, + VK_FORMAT_R8_SNORM, + VK_FORMAT_R8_UINT, + VK_FORMAT_R8_SINT }, + // DXGI_FORMAT_R8_UNORM + { }, + // DXGI_FORMAT_R8_UINT + { }, + // DXGI_FORMAT_R8_SNORM + { }, + // DXGI_FORMAT_R8_SINT + { }, + // DXGI_FORMAT_A8_UNORM + { }, + // DXGI_FORMAT_R1_UNORM + { }, // Unsupported + // DXGI_FORMAT_R9G9B9E5_SHAREDEXP + { }, + // DXGI_FORMAT_R8G8_B8G8_UNORM + { }, + // DXGI_FORMAT_G8R8_G8B8_UNORM + { }, + // DXGI_FORMAT_BC1_TYPELESS + { VK_FORMAT_BC1_RGBA_UNORM_BLOCK, + VK_FORMAT_BC1_RGBA_SRGB_BLOCK }, + // DXGI_FORMAT_BC1_UNORM + { VK_FORMAT_BC1_RGBA_UNORM_BLOCK, + VK_FORMAT_BC1_RGBA_SRGB_BLOCK }, + // DXGI_FORMAT_BC1_UNORM_SRGB + { VK_FORMAT_BC1_RGBA_UNORM_BLOCK, + VK_FORMAT_BC1_RGBA_SRGB_BLOCK }, + // DXGI_FORMAT_BC2_TYPELESS + { VK_FORMAT_BC2_UNORM_BLOCK, + VK_FORMAT_BC2_SRGB_BLOCK }, + // DXGI_FORMAT_BC2_UNORM + { VK_FORMAT_BC2_UNORM_BLOCK, + VK_FORMAT_BC2_SRGB_BLOCK }, + // DXGI_FORMAT_BC2_UNORM_SRGB + { VK_FORMAT_BC2_UNORM_BLOCK, + VK_FORMAT_BC2_SRGB_BLOCK }, + // DXGI_FORMAT_BC3_TYPELESS + { VK_FORMAT_BC3_UNORM_BLOCK, + VK_FORMAT_BC3_SRGB_BLOCK }, + // DXGI_FORMAT_BC3_UNORM + { VK_FORMAT_BC3_UNORM_BLOCK, + VK_FORMAT_BC3_SRGB_BLOCK }, + // DXGI_FORMAT_BC3_UNORM_SRGB + { VK_FORMAT_BC3_UNORM_BLOCK, + VK_FORMAT_BC3_SRGB_BLOCK }, + // DXGI_FORMAT_BC4_TYPELESS + { VK_FORMAT_BC4_UNORM_BLOCK, + VK_FORMAT_BC4_SNORM_BLOCK }, + // DXGI_FORMAT_BC4_UNORM + { }, + // DXGI_FORMAT_BC4_SNORM + { }, + // DXGI_FORMAT_BC5_TYPELESS + { VK_FORMAT_BC5_UNORM_BLOCK, + VK_FORMAT_BC5_SNORM_BLOCK }, + // DXGI_FORMAT_BC5_UNORM + { }, + // DXGI_FORMAT_BC5_SNORM + { }, + // DXGI_FORMAT_B5G6R5_UNORM + { }, + // DXGI_FORMAT_B5G5R5A1_UNORM + { }, + // DXGI_FORMAT_B8G8R8A8_UNORM + { VK_FORMAT_B8G8R8A8_UNORM, + VK_FORMAT_B8G8R8A8_SRGB }, + // DXGI_FORMAT_B8G8R8X8_UNORM + { VK_FORMAT_B8G8R8A8_UNORM, + VK_FORMAT_B8G8R8A8_SRGB }, + // DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM + { }, // Unsupported + // DXGI_FORMAT_B8G8R8A8_TYPELESS + { VK_FORMAT_B8G8R8A8_UNORM, + VK_FORMAT_B8G8R8A8_SRGB }, + // DXGI_FORMAT_B8G8R8A8_UNORM_SRGB + { VK_FORMAT_B8G8R8A8_UNORM, + VK_FORMAT_B8G8R8A8_SRGB }, + // DXGI_FORMAT_B8G8R8X8_TYPELESS + { VK_FORMAT_B8G8R8A8_UNORM, + VK_FORMAT_B8G8R8A8_SRGB }, + // DXGI_FORMAT_B8G8R8X8_UNORM_SRGB + { VK_FORMAT_B8G8R8A8_UNORM, + VK_FORMAT_B8G8R8A8_SRGB }, + // DXGI_FORMAT_BC6H_TYPELESS + { VK_FORMAT_BC6H_UFLOAT_BLOCK, + VK_FORMAT_BC6H_SFLOAT_BLOCK }, + // DXGI_FORMAT_BC6H_UF16 + { }, + // DXGI_FORMAT_BC6H_SF16 + { }, + // DXGI_FORMAT_BC7_TYPELESS + { VK_FORMAT_BC7_UNORM_BLOCK, + VK_FORMAT_BC7_SRGB_BLOCK }, + // DXGI_FORMAT_BC7_UNORM + { VK_FORMAT_BC7_UNORM_BLOCK, + VK_FORMAT_BC7_SRGB_BLOCK }, + // DXGI_FORMAT_BC7_UNORM_SRGB + { VK_FORMAT_BC7_UNORM_BLOCK, + VK_FORMAT_BC7_SRGB_BLOCK }, + // DXGI_FORMAT_AYUV + { VK_FORMAT_R8G8B8A8_UNORM, + VK_FORMAT_R8G8B8A8_UINT }, + // DXGI_FORMAT_Y410 + { }, // Unsupported + // DXGI_FORMAT_Y416 + { }, // Unsupported + // DXGI_FORMAT_NV12 + { VK_FORMAT_R8_UNORM, + VK_FORMAT_R8G8_UNORM, + VK_FORMAT_R8_UINT, + VK_FORMAT_R8G8_UINT }, + // DXGI_FORMAT_P010 + { }, // Unsupported + // DXGI_FORMAT_P016 + { }, // Unsupported + // DXGI_FORMAT_420_OPAQUE + { VK_FORMAT_R8_UNORM, + VK_FORMAT_R8G8_UNORM, + VK_FORMAT_R8_UINT, + VK_FORMAT_R8G8_UINT }, + // DXGI_FORMAT_YUY2 + { VK_FORMAT_G8B8G8R8_422_UNORM, + VK_FORMAT_R8G8B8A8_UNORM, + VK_FORMAT_R8G8B8A8_UINT }, + // DXGI_FORMAT_Y210 + { }, // Unsupported + // DXGI_FORMAT_Y216 + { }, // Unsupported + // DXGI_FORMAT_NV11 + { }, // Unsupported + // DXGI_FORMAT_AI44 + { }, // Unsupported + // DXGI_FORMAT_IA44 + { }, // Unsupported + // DXGI_FORMAT_P8 + { }, // Unsupported + // DXGI_FORMAT_A8P8 + { }, // Unsupported + // DXGI_FORMAT_B4G4R4A4_UNORM + { }, // Unsupported + // DXGI_FORMAT_P208 + { }, // Unsupported + // DXGI_FORMAT_V208 + { }, // Unsupported + // DXGI_FORMAT_V408 + { }, // Unsupported + }}; + + + DXGIVkFormatTable::DXGIVkFormatTable(const Rc& adapter) + : m_dxgiFormats (g_dxgiFormats), m_dxgiFamilies(g_dxgiFamilies) { + // AMD do not support 24-bit depth buffers on Vulkan, + // so we have to fall back to a 32-bit depth format. + if (!CheckImageFormatSupport(adapter, VK_FORMAT_D24_UNORM_S8_UINT, + VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | + VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) { + Logger::info("DXGI: VK_FORMAT_D24_UNORM_S8_UINT -> VK_FORMAT_D32_SFLOAT_S8_UINT"); + RemapDepthFormat(DXGI_FORMAT_R24G8_TYPELESS, VK_FORMAT_D32_SFLOAT_S8_UINT); + RemapDepthFormat(DXGI_FORMAT_R24_UNORM_X8_TYPELESS, VK_FORMAT_D32_SFLOAT_S8_UINT); + RemapDepthFormat(DXGI_FORMAT_X24_TYPELESS_G8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT); + RemapDepthFormat(DXGI_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT); + } + + if (!adapter->features().ext4444Formats.formatA4R4G4B4) { + RemapColorFormat(DXGI_FORMAT_B4G4R4A4_UNORM, VK_FORMAT_B4G4R4A4_UNORM_PACK16, + { VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R, + VK_COMPONENT_SWIZZLE_A, VK_COMPONENT_SWIZZLE_B }); + } + } + + + DXGIVkFormatTable::~DXGIVkFormatTable() { + + } + + + DXGI_VK_FORMAT_INFO DXGIVkFormatTable::GetFormatInfo( + DXGI_FORMAT Format, + DXGI_VK_FORMAT_MODE Mode) const { + return GetFormatInfoFromMapping( + GetFormatMapping(Format), Mode); + } + + + DXGI_VK_FORMAT_INFO DXGIVkFormatTable::GetPackedFormatInfo( + DXGI_FORMAT Format, + DXGI_VK_FORMAT_MODE Mode) const { + return GetFormatInfoFromMapping( + GetPackedFormatMapping(Format), Mode); + } + + + DXGI_VK_FORMAT_FAMILY DXGIVkFormatTable::GetFormatFamily( + DXGI_FORMAT Format, + DXGI_VK_FORMAT_MODE Mode) const { + if (Mode == DXGI_VK_FORMAT_MODE_DEPTH) + return DXGI_VK_FORMAT_FAMILY(); + + const size_t formatId = size_t(Format); + + return formatId < m_dxgiFamilies.size() + ? m_dxgiFamilies[formatId] + : m_dxgiFamilies[0]; + } + + + DXGI_VK_FORMAT_INFO DXGIVkFormatTable::GetFormatInfoFromMapping( + const DXGI_VK_FORMAT_MAPPING* pMapping, + DXGI_VK_FORMAT_MODE Mode) const { + switch (Mode) { + case DXGI_VK_FORMAT_MODE_ANY: + return pMapping->FormatColor != VK_FORMAT_UNDEFINED + ? DXGI_VK_FORMAT_INFO { pMapping->FormatColor, pMapping->AspectColor, pMapping->Swizzle } + : DXGI_VK_FORMAT_INFO { pMapping->FormatDepth, pMapping->AspectDepth }; + + case DXGI_VK_FORMAT_MODE_COLOR: + return { pMapping->FormatColor, pMapping->AspectColor, pMapping->Swizzle }; + + case DXGI_VK_FORMAT_MODE_DEPTH: + return { pMapping->FormatDepth, pMapping->AspectDepth }; + + case DXGI_VK_FORMAT_MODE_RAW: + return { pMapping->FormatRaw, pMapping->AspectColor }; + } + + Logger::err("DXGI: GetFormatInfoFromMapping: Internal error"); + return DXGI_VK_FORMAT_INFO(); + } + + + const DXGI_VK_FORMAT_MAPPING* DXGIVkFormatTable::GetFormatMapping( + DXGI_FORMAT Format) const { + const size_t formatId = size_t(Format); + + return formatId < m_dxgiFormats.size() + ? &m_dxgiFormats[formatId] + : &m_dxgiFormats[0]; + } + + + const DXGI_VK_FORMAT_MAPPING* DXGIVkFormatTable::GetPackedFormatMapping( + DXGI_FORMAT Format) const { + const size_t formatId = size_t(Format); + + return formatId < g_dxgiFormats.size() + ? &g_dxgiFormats[formatId] + : &g_dxgiFormats[0]; + } + + + bool DXGIVkFormatTable::CheckImageFormatSupport( + const Rc& Adapter, + VkFormat Format, + VkFormatFeatureFlags Features) const { + VkFormatProperties supported = Adapter->formatProperties(Format); + + return (supported.linearTilingFeatures & Features) == Features + || (supported.optimalTilingFeatures & Features) == Features; + } + + + void DXGIVkFormatTable::RemapDepthFormat( + DXGI_FORMAT Format, + VkFormat Target) { + m_dxgiFormats[uint32_t(Format)].FormatDepth = Target; + } + + + void DXGIVkFormatTable::RemapColorFormat( + DXGI_FORMAT Format, + VkFormat Target, + VkComponentMapping Swizzle) { + m_dxgiFormats[uint32_t(Format)].FormatColor = Target; + m_dxgiFormats[uint32_t(Format)].Swizzle = Swizzle; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxgi/dxgi_format.h b/utils/dxvk-1.10.3/src/dxgi/dxgi_format.h new file mode 100644 index 00000000000..59e64937f69 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxgi/dxgi_format.h @@ -0,0 +1,173 @@ +#pragma once + +#include "dxgi_include.h" + +#include "../dxvk/dxvk_adapter.h" +#include "../dxvk/dxvk_format.h" + +namespace dxvk { + + /** + * \brief Format mapping + * + * Maps a DXGI format to a set of Vulkan formats. + */ + struct DXGI_VK_FORMAT_MAPPING { + VkFormat FormatColor = VK_FORMAT_UNDEFINED; ///< Corresponding color format + VkFormat FormatDepth = VK_FORMAT_UNDEFINED; ///< Corresponding depth format + VkFormat FormatRaw = VK_FORMAT_UNDEFINED; ///< Bit-compatible integer format + VkImageAspectFlags AspectColor = 0; ///< Defined aspects for the color format + VkImageAspectFlags AspectDepth = 0; ///< Defined aspects for the depth format + VkComponentMapping Swizzle = { ///< Color component swizzle + VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, + VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY }; + }; + + /** + * \brief Format info + * + * Stores a Vulkan image format for a given + * DXGI format and some additional information + * on how resources with the particular format + * are supposed to be used. + */ + struct DXGI_VK_FORMAT_INFO { + VkFormat Format = VK_FORMAT_UNDEFINED; ///< Corresponding color format + VkImageAspectFlags Aspect = 0; ///< Defined image aspect mask + VkComponentMapping Swizzle = { ///< Component swizzle + VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, + VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY }; + }; + + /** + * \brief Format lookup mode + * + * When looking up an image format, additional information + * might be needed on how the image is going to be used. + * This is used to properly map typeless formats and color + * formats to depth formats if they are used on depth images. + */ + enum DXGI_VK_FORMAT_MODE { + DXGI_VK_FORMAT_MODE_ANY = 0, ///< Color first, then depth + DXGI_VK_FORMAT_MODE_COLOR = 1, ///< Color only + DXGI_VK_FORMAT_MODE_DEPTH = 2, ///< Depth only + DXGI_VK_FORMAT_MODE_RAW = 3, ///< Unsigned integer format + }; + + + /** + * \brief Format family + * + * Stores a set of compatible formats. This can + * be used to aggregate formats for the image + * format list extension. + */ + struct DXGI_VK_FORMAT_FAMILY { + constexpr static size_t MaxSize = 8; + + DXGI_VK_FORMAT_FAMILY() { } + DXGI_VK_FORMAT_FAMILY(const std::initializer_list& FormatList) { + for (VkFormat f : FormatList) + Add(f); + } + + BOOL Add(VkFormat Format) { + for (UINT i = 0; i < FormatCount; i++) { + if (Formats[i] == Format) + return TRUE; + } + + if (FormatCount < MaxSize) { + Formats[FormatCount++] = Format; + return TRUE; + } return FALSE; + } + + UINT FormatCount = 0; + VkFormat Formats[MaxSize]; + }; + + + /** + * \brief Format table + * + * Initializes a format table for a specific + * device and provides methods to look up + * formats. + */ + class DXGIVkFormatTable { + + public: + + DXGIVkFormatTable( + const Rc& adapter); + ~DXGIVkFormatTable(); + + /** + * \brief Retrieves info for a given DXGI format + * + * \param [in] Format The DXGI format to look up + * \param [in] Mode the format lookup mode + * \returns Format info + */ + DXGI_VK_FORMAT_INFO GetFormatInfo( + DXGI_FORMAT Format, + DXGI_VK_FORMAT_MODE Mode) const; + + /** + * \brief Retrieves original info for a given DXGI format + * + * Doesn't perform any format adjustment, so this + * can be used to determine the packed data format + * of a DXGI format for things like data uploads. + * \param [in] Format The DXGI format to look up + * \param [in] Mode the format lookup mode + * \returns Format info + */ + DXGI_VK_FORMAT_INFO GetPackedFormatInfo( + DXGI_FORMAT Format, + DXGI_VK_FORMAT_MODE Mode) const; + + /** + * \brief Retrieves a format family + * + * \param [in] Format The format to query + * \param [in] Mode Image format mode + * \returns Image format family + */ + DXGI_VK_FORMAT_FAMILY GetFormatFamily( + DXGI_FORMAT Format, + DXGI_VK_FORMAT_MODE Mode) const; + + private: + + std::array m_dxgiFormats; + std::array m_dxgiFamilies; + + DXGI_VK_FORMAT_INFO GetFormatInfoFromMapping( + const DXGI_VK_FORMAT_MAPPING* pMapping, + DXGI_VK_FORMAT_MODE Mode) const; + + const DXGI_VK_FORMAT_MAPPING* GetFormatMapping( + DXGI_FORMAT Format) const; + + const DXGI_VK_FORMAT_MAPPING* GetPackedFormatMapping( + DXGI_FORMAT Format) const; + + bool CheckImageFormatSupport( + const Rc& Adapter, + VkFormat Format, + VkFormatFeatureFlags Features) const; + + void RemapDepthFormat( + DXGI_FORMAT Format, + VkFormat Target); + + void RemapColorFormat( + DXGI_FORMAT Format, + VkFormat Target, + VkComponentMapping Swizzle); + + }; + +}; \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxgi/dxgi_include.h b/utils/dxvk-1.10.3/src/dxgi/dxgi_include.h new file mode 100644 index 00000000000..14dc138aaf9 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxgi/dxgi_include.h @@ -0,0 +1,48 @@ +#pragma once + +//for some reason we need to specify __declspec(dllexport) for MinGW +#if defined(__WINE__) + #define DLLEXPORT __attribute__((visibility("default"))) +#elif defined(_MSC_VER) + #define DLLEXPORT +#else + #define DLLEXPORT __declspec(dllexport) +#endif + +#include "../util/com/com_guid.h" +#include "../util/com/com_object.h" +#include "../util/com/com_pointer.h" + +#include "../util/log/log.h" +#include "../util/log/log_debug.h" + +#include "../util/rc/util_rc.h" +#include "../util/rc/util_rc_ptr.h" + +#include "../util/util_env.h" +#include "../util/util_enum.h" +#include "../util/util_error.h" +#include "../util/util_flags.h" +#include "../util/util_likely.h" +#include "../util/util_math.h" +#include "../util/util_monitor.h" +#include "../util/util_string.h" + +#include + +// For some reason, these are not exposed +#ifndef DXGI_RESOURCE_PRIORITY_NORMAL + #define DXGI_RESOURCE_PRIORITY_MINIMUM (0x28000000) + #define DXGI_RESOURCE_PRIORITY_LOW (0x50000000) + #define DXGI_RESOURCE_PRIORITY_NORMAL (0x78000000) + #define DXGI_RESOURCE_PRIORITY_HIGH (0xa0000000) + #define DXGI_RESOURCE_PRIORITY_MAXIMUM (0xc8000000) +#endif + +#ifndef DXGI_CPU_ACCESS_NONE + #define DXGI_CPU_ACCESS_NONE (0) + #define DXGI_CPU_ACCESS_DYNAMIC (1) + #define DXGI_CPU_ACCESS_READ_WRITE (2) + #define DXGI_CPU_ACCESS_SCRATCH (3) + #define DXGI_CPU_ACCESS_FIELD (0xf) +#endif \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxgi/dxgi_interfaces.h b/utils/dxvk-1.10.3/src/dxgi/dxgi_interfaces.h new file mode 100644 index 00000000000..f7a93950376 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxgi/dxgi_interfaces.h @@ -0,0 +1,378 @@ +#pragma once + +#include "../dxvk/dxvk_include.h" + +#include "dxgi_format.h" +#include "dxgi_include.h" + +namespace dxvk { + class DxgiAdapter; + class DxgiSwapChain; + class DxvkAdapter; + class DxvkBuffer; + class DxvkDevice; + class DxvkImage; +} + +struct IDXGIVkInteropDevice; + + +/** + * \brief Per-monitor data + */ +struct DXGI_VK_MONITOR_DATA { + dxvk::DxgiSwapChain* pSwapChain; + DXGI_FRAME_STATISTICS FrameStats; + DXGI_GAMMA_CONTROL GammaCurve; +}; + + +/** + * \brief Private DXGI presenter + * + * Presenter interface that allows the DXGI swap + * chain implementation to remain API-agnostic, + * so that common code can stay in one class. + */ +MIDL_INTERFACE("104001a6-7f36-4957-b932-86ade9567d91") +IDXGIVkSwapChain : public IUnknown { + virtual HRESULT STDMETHODCALLTYPE GetDesc( + DXGI_SWAP_CHAIN_DESC1* pDesc) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAdapter( + REFIID riid, + void** ppvObject) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDevice( + REFIID riid, + void** ppDevice) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetImage( + UINT BufferId, + REFIID riid, + void** ppBuffer) = 0; + + virtual UINT STDMETHODCALLTYPE GetImageIndex() = 0; + + virtual UINT STDMETHODCALLTYPE GetFrameLatency() = 0; + + virtual HANDLE STDMETHODCALLTYPE GetFrameLatencyEvent() = 0; + + virtual HRESULT STDMETHODCALLTYPE ChangeProperties( + const DXGI_SWAP_CHAIN_DESC1* pDesc) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetPresentRegion( + const RECT* pRegion) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetGammaControl( + UINT NumControlPoints, + const DXGI_RGB* pControlPoints) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetFrameLatency( + UINT MaxLatency) = 0; + + virtual HRESULT STDMETHODCALLTYPE Present( + UINT SyncInterval, + UINT PresentFlags, + const DXGI_PRESENT_PARAMETERS* pPresentParameters) = 0; + + virtual void STDMETHODCALLTYPE NotifyModeChange( + BOOL Windowed, + const DXGI_MODE_DESC* pDisplayMode) = 0; +}; + + +/** + * \brief Private DXGI adapter interface + * + * The implementation of \c IDXGIAdapter holds a + * \ref DxvkAdapter which can be retrieved using + * this interface. + */ +MIDL_INTERFACE("907bf281-ea3c-43b4-a8e4-9f231107b4ff") +IDXGIDXVKAdapter : public IDXGIAdapter4 { + virtual dxvk::Rc STDMETHODCALLTYPE GetDXVKAdapter() = 0; + + virtual dxvk::Rc STDMETHODCALLTYPE GetDXVKInstance() = 0; + +}; + + +/** + * \brief Private DXGI device interface + */ +MIDL_INTERFACE("92a5d77b-b6e1-420a-b260-fdd701272827") +IDXGIDXVKDevice : public IUnknown { + virtual void STDMETHODCALLTYPE SetAPIVersion( + UINT Version) = 0; + + virtual UINT STDMETHODCALLTYPE GetAPIVersion() = 0; + +}; + + +/** + * \brief Private DXGI monitor info interface + * + * Can be queried from the DXGI factory to store monitor + * info globally, with a lifetime that exceeds that of + * the \c IDXGIOutput or \c IDXGIAdapter objects. + */ +MIDL_INTERFACE("c06a236f-5be3-448a-8943-89c611c0c2c1") +IDXGIVkMonitorInfo : public IUnknown { + /** + * \brief Initializes monitor data + * + * Fails if data for the given monitor already exists. + * \param [in] hMonitor The monitor handle + * \param [in] pData Initial data + */ + virtual HRESULT STDMETHODCALLTYPE InitMonitorData( + HMONITOR hMonitor, + const DXGI_VK_MONITOR_DATA* pData) = 0; + + /** + * \brief Retrieves and locks monitor data + * + * Fails if no data for the given monitor exists. + * \param [in] hMonitor The monitor handle + * \param [out] Pointer to monitor data + * \returns S_OK on success + */ + virtual HRESULT STDMETHODCALLTYPE AcquireMonitorData( + HMONITOR hMonitor, + DXGI_VK_MONITOR_DATA** ppData) = 0; + + /** + * \brief Unlocks monitor data + * + * Must be called after each successful + * call to \ref AcquireMonitorData. + * \param [in] hMonitor The monitor handle + */ + virtual void STDMETHODCALLTYPE ReleaseMonitorData() = 0; + +}; + + +/** + * \brief DXGI surface interface for Vulkan interop + * + * Provides access to the backing resource of a + * DXGI surface, which is typically a D3D texture. + */ +MIDL_INTERFACE("5546cf8c-77e7-4341-b05d-8d4d5000e77d") +IDXGIVkInteropSurface : public IUnknown { + /** + * \brief Retrieves device interop interfaceSlots + * + * Queries the device that owns the surface for + * the \ref IDXGIVkInteropDevice interface. + * \param [out] ppDevice The device interface + * \returns \c S_OK on success + */ + virtual HRESULT STDMETHODCALLTYPE GetDevice( + IDXGIVkInteropDevice** ppDevice) = 0; + + /** + * \brief Retrieves Vulkan image info + * + * Retrieves both the image handle as well as the image's + * properties. Any of the given pointers may be \c nullptr. + * + * If \c pInfo is not \c nullptr, the following rules apply: + * - \c pInfo->sType \e must be \c VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO + * - \c pInfo->pNext \e must be \c nullptr or point to a supported + * extension-specific structure (currently none) + * - \c pInfo->queueFamilyIndexCount must be the length of the + * \c pInfo->pQueueFamilyIndices array, in \c uint32_t units. + * - \c pInfo->pQueueFamilyIndices must point to a pre-allocated + * array of \c uint32_t of size \c pInfo->pQueueFamilyIndices. + * + * \note As of now, the sharing mode will always be + * \c VK_SHARING_MODE_EXCLUSIVE and no queue + * family indices will be written to the array. + * + * After the call, the structure pointed to by \c pInfo can + * be used to create an image with identical properties. + * + * If \c pLayout is not \c nullptr, it will receive the + * layout that the image will be in after flushing any + * outstanding commands on the device. + * \param [out] pHandle The image handle + * \param [out] pLayout Image layout + * \param [out] pInfo Image properties + * \returns \c S_OK on success, or \c E_INVALIDARG + */ + virtual HRESULT STDMETHODCALLTYPE GetVulkanImageInfo( + VkImage* pHandle, + VkImageLayout* pLayout, + VkImageCreateInfo* pInfo) = 0; +}; + + +/** + * \brief DXGI device interface for Vulkan interop + * + * Provides access to the device and instance handles + * as well as the queue that is used for rendering. + */ +MIDL_INTERFACE("e2ef5fa5-dc21-4af7-90c4-f67ef6a09323") +IDXGIVkInteropDevice : public IUnknown { + /** + * \brief Queries Vulkan handles used by DXVK + * + * \param [out] pInstance The Vulkan instance + * \param [out] pPhysDev The physical device + * \param [out] pDevide The device handle + */ + virtual void STDMETHODCALLTYPE GetVulkanHandles( + VkInstance* pInstance, + VkPhysicalDevice* pPhysDev, + VkDevice* pDevice) = 0; + + /** + * \brief Queries the rendering queue used by DXVK + * + * \param [out] pQueue The Vulkan queue handle + * \param [out] pQueueFamilyIndex Queue family index + */ + virtual void STDMETHODCALLTYPE GetSubmissionQueue( + VkQueue* pQueue, + uint32_t* pQueueFamilyIndex) = 0; + + /** + * \brief Transitions a surface to a given layout + * + * Executes an explicit image layout transition on the + * D3D device. Note that the image subresources \e must + * be transitioned back to its original layout before + * using it again from D3D11. + * \param [in] pSurface The image to transform + * \param [in] pSubresources Subresources to transform + * \param [in] OldLayout Current image layout + * \param [in] NewLayout Desired image layout + */ + virtual void STDMETHODCALLTYPE TransitionSurfaceLayout( + IDXGIVkInteropSurface* pSurface, + const VkImageSubresourceRange* pSubresources, + VkImageLayout OldLayout, + VkImageLayout NewLayout) = 0; + + /** + * \brief Flushes outstanding D3D rendering commands + * + * Must be called before submitting Vulkan commands + * to the rendering queue if those commands use the + * backing resource of a D3D11 object. + */ + virtual void STDMETHODCALLTYPE FlushRenderingCommands() = 0; + + /** + * \brief Locks submission queue + * + * Should be called immediately before submitting + * Vulkan commands to the rendering queue in order + * to prevent DXVK from using the queue. + * + * While the submission queue is locked, no D3D11 + * methods must be called from the locking thread, + * or otherwise a deadlock might occur. + */ + virtual void STDMETHODCALLTYPE LockSubmissionQueue() = 0; + + /** + * \brief Releases submission queue + * + * Should be called immediately after submitting + * Vulkan commands to the rendering queue in order + * to allow DXVK to submit new commands. + */ + virtual void STDMETHODCALLTYPE ReleaseSubmissionQueue() = 0; +}; + +struct D3D11_TEXTURE2D_DESC1; +struct ID3D11Texture2D; + +/** + * \brief See IDXGIVkInteropDevice. + */ +MIDL_INTERFACE("e2ef5fa5-dc21-4af7-90c4-f67ef6a09324") +IDXGIVkInteropDevice1 : public IDXGIVkInteropDevice { + /** + * \brief Queries the rendering queue used by DXVK + * + * \param [out] pQueue The Vulkan queue handle + * \param [out] pQueueIndex Queue index + * \param [out] pQueueFamilyIndex Queue family index + */ + virtual void STDMETHODCALLTYPE GetSubmissionQueue1( + VkQueue* pQueue, + uint32_t* pQueueIndex, + uint32_t* pQueueFamilyIndex) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateTexture2DFromVkImage( + const D3D11_TEXTURE2D_DESC1 *pDesc, + VkImage vkImage, + ID3D11Texture2D **ppTexture2D) = 0; +}; + +/** + * \brief DXGI adapter interface for Vulkan interop + * + * Provides access to the physical device and + * instance handles for the given DXGI adapter. + */ +MIDL_INTERFACE("3a6d8f2c-b0e8-4ab4-b4dc-4fd24891bfa5") +IDXGIVkInteropAdapter : public IUnknown { + /** + * \brief Queries Vulkan handles used by DXVK + * + * \param [out] pInstance The Vulkan instance + * \param [out] pPhysDev The physical device + */ + virtual void STDMETHODCALLTYPE GetVulkanHandles( + VkInstance* pInstance, + VkPhysicalDevice* pPhysDev) = 0; +}; + + +/** + * \brief IWineDXGISwapChainFactory device interface + * + * Allows a swap chain to be created from a device. + * See include/wine/winedxgi.idl for definition. + */ +MIDL_INTERFACE("53cb4ff0-c25a-4164-a891-0e83db0a7aac") +IWineDXGISwapChainFactory : public IUnknown { + virtual HRESULT STDMETHODCALLTYPE CreateSwapChainForHwnd( + IDXGIFactory* pFactory, + HWND hWnd, + const DXGI_SWAP_CHAIN_DESC1* pDesc, + const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc, + IDXGIOutput* pRestrictToOutput, + IDXGISwapChain1** ppSwapChain) = 0; +}; + + +#ifdef _MSC_VER +struct __declspec(uuid("907bf281-ea3c-43b4-a8e4-9f231107b4ff")) IDXGIDXVKAdapter; +struct __declspec(uuid("92a5d77b-b6e1-420a-b260-fdd701272827")) IDXGIDXVKDevice; +struct __declspec(uuid("c06a236f-5be3-448a-8943-89c611c0c2c1")) IDXGIVkMonitorInfo; +struct __declspec(uuid("3a6d8f2c-b0e8-4ab4-b4dc-4fd24891bfa5")) IDXGIVkInteropAdapter; +struct __declspec(uuid("e2ef5fa5-dc21-4af7-90c4-f67ef6a09323")) IDXGIVkInteropDevice; +struct __declspec(uuid("e2ef5fa5-dc21-4af7-90c4-f67ef6a09324")) IDXGIVkInteropDevice1; +struct __declspec(uuid("5546cf8c-77e7-4341-b05d-8d4d5000e77d")) IDXGIVkInteropSurface; +struct __declspec(uuid("104001a6-7f36-4957-b932-86ade9567d91")) IDXGIVkSwapChain; +struct __declspec(uuid("53cb4ff0-c25a-4164-a891-0e83db0a7aac")) IWineDXGISwapChainFactory; +#else +__CRT_UUID_DECL(IDXGIDXVKAdapter, 0x907bf281,0xea3c,0x43b4,0xa8,0xe4,0x9f,0x23,0x11,0x07,0xb4,0xff); +__CRT_UUID_DECL(IDXGIDXVKDevice, 0x92a5d77b,0xb6e1,0x420a,0xb2,0x60,0xfd,0xf7,0x01,0x27,0x28,0x27); +__CRT_UUID_DECL(IDXGIVkMonitorInfo, 0xc06a236f,0x5be3,0x448a,0x89,0x43,0x89,0xc6,0x11,0xc0,0xc2,0xc1); +__CRT_UUID_DECL(IDXGIVkInteropAdapter, 0x3a6d8f2c,0xb0e8,0x4ab4,0xb4,0xdc,0x4f,0xd2,0x48,0x91,0xbf,0xa5); +__CRT_UUID_DECL(IDXGIVkInteropDevice, 0xe2ef5fa5,0xdc21,0x4af7,0x90,0xc4,0xf6,0x7e,0xf6,0xa0,0x93,0x23); +__CRT_UUID_DECL(IDXGIVkInteropDevice1, 0xe2ef5fa5,0xdc21,0x4af7,0x90,0xc4,0xf6,0x7e,0xf6,0xa0,0x93,0x24); +__CRT_UUID_DECL(IDXGIVkInteropSurface, 0x5546cf8c,0x77e7,0x4341,0xb0,0x5d,0x8d,0x4d,0x50,0x00,0xe7,0x7d); +__CRT_UUID_DECL(IDXGIVkSwapChain, 0x104001a6,0x7f36,0x4957,0xb9,0x32,0x86,0xad,0xe9,0x56,0x7d,0x91); +__CRT_UUID_DECL(IWineDXGISwapChainFactory, 0x53cb4ff0,0xc25a,0x4164,0xa8,0x91,0x0e,0x83,0xdb,0x0a,0x7a,0xac); +#endif diff --git a/utils/dxvk-1.10.3/src/dxgi/dxgi_main.cpp b/utils/dxvk-1.10.3/src/dxgi/dxgi_main.cpp new file mode 100644 index 00000000000..17530f53e3e --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxgi/dxgi_main.cpp @@ -0,0 +1,57 @@ +#include "dxgi_factory.h" +#include "dxgi_include.h" + +namespace dxvk { + + Logger Logger::s_instance("dxgi.log"); + + HRESULT createDxgiFactory(UINT Flags, REFIID riid, void **ppFactory) { + try { + Com factory = new DxgiFactory(Flags); + HRESULT hr = factory->QueryInterface(riid, ppFactory); + + if (FAILED(hr)) + return hr; + + return S_OK; + } catch (const DxvkError& e) { + Logger::err(e.message()); + return E_FAIL; + } + } +} + +extern "C" { + DLLEXPORT HRESULT __stdcall CreateDXGIFactory2(UINT Flags, REFIID riid, void **ppFactory) { + dxvk::Logger::warn("CreateDXGIFactory2: Ignoring flags"); + return dxvk::createDxgiFactory(Flags, riid, ppFactory); + } + + DLLEXPORT HRESULT __stdcall CreateDXGIFactory1(REFIID riid, void **ppFactory) { + return dxvk::createDxgiFactory(0, riid, ppFactory); + } + + DLLEXPORT HRESULT __stdcall CreateDXGIFactory(REFIID riid, void **ppFactory) { + return dxvk::createDxgiFactory(0, riid, ppFactory); + } + + DLLEXPORT HRESULT __stdcall DXGIDeclareAdapterRemovalSupport() { + static bool enabled = false; + + if (std::exchange(enabled, true)) + return 0x887a0036; // DXGI_ERROR_ALREADY_EXISTS; + + dxvk::Logger::warn("DXGIDeclareAdapterRemovalSupport: Stub"); + return S_OK; + } + + DLLEXPORT HRESULT __stdcall DXGIGetDebugInterface1(UINT Flags, REFIID riid, void **ppDebug) { + static bool errorShown = false; + + if (!std::exchange(errorShown, true)) + dxvk::Logger::warn("DXGIGetDebugInterface1: Stub"); + + return E_NOINTERFACE; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxgi/dxgi_monitor.cpp b/utils/dxvk-1.10.3/src/dxgi/dxgi_monitor.cpp new file mode 100644 index 00000000000..09959a6279f --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxgi/dxgi_monitor.cpp @@ -0,0 +1,94 @@ +#include "dxgi_monitor.h" + +namespace dxvk { + + DxgiMonitorInfo::DxgiMonitorInfo(IUnknown* pParent) + : m_parent(pParent) { + + } + + + DxgiMonitorInfo::~DxgiMonitorInfo() { + + } + + + ULONG STDMETHODCALLTYPE DxgiMonitorInfo::AddRef() { + return m_parent->AddRef(); + } + + + ULONG STDMETHODCALLTYPE DxgiMonitorInfo::Release() { + return m_parent->Release(); + } + + + HRESULT STDMETHODCALLTYPE DxgiMonitorInfo::QueryInterface( + REFIID riid, + void** ppvObject) { + return m_parent->QueryInterface(riid, ppvObject); + } + + + HRESULT STDMETHODCALLTYPE DxgiMonitorInfo::InitMonitorData( + HMONITOR hMonitor, + const DXGI_VK_MONITOR_DATA* pData) { + if (!hMonitor || !pData) + return E_INVALIDARG; + + std::lock_guard lock(m_monitorMutex); + auto result = m_monitorData.insert({ hMonitor, *pData }); + + return result.second ? S_OK : E_INVALIDARG; + } + + + HRESULT STDMETHODCALLTYPE DxgiMonitorInfo::AcquireMonitorData( + HMONITOR hMonitor, + DXGI_VK_MONITOR_DATA** ppData) { + InitReturnPtr(ppData); + + if (!hMonitor || !ppData) + return E_INVALIDARG; + + m_monitorMutex.lock(); + + auto entry = m_monitorData.find(hMonitor); + if (entry == m_monitorData.end()) { + m_monitorMutex.unlock(); + return DXGI_ERROR_NOT_FOUND; + } + + *ppData = &entry->second; + return S_OK; + } + + + void STDMETHODCALLTYPE DxgiMonitorInfo::ReleaseMonitorData() { + m_monitorMutex.unlock(); + } + + + uint32_t GetMonitorFormatBpp(DXGI_FORMAT Format) { + switch (Format) { + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8X8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + case DXGI_FORMAT_R10G10B10A2_UNORM: + return 32; + + case DXGI_FORMAT_R16G16B16A16_FLOAT: + return 64; + + default: + Logger::warn(str::format( + "GetMonitorFormatBpp: Unknown format: ", + Format)); + return 32; + } + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxgi/dxgi_monitor.h b/utils/dxvk-1.10.3/src/dxgi/dxgi_monitor.h new file mode 100644 index 00000000000..0c70101b267 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxgi/dxgi_monitor.h @@ -0,0 +1,58 @@ +#pragma once + +#include +#include + +#include "dxgi_interfaces.h" + +namespace dxvk { + + class DxgiSwapChain; + + class DxgiMonitorInfo : public IDXGIVkMonitorInfo { + + public: + + DxgiMonitorInfo(IUnknown* pParent); + + ~DxgiMonitorInfo(); + + ULONG STDMETHODCALLTYPE AddRef(); + + ULONG STDMETHODCALLTYPE Release(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + HRESULT STDMETHODCALLTYPE InitMonitorData( + HMONITOR hMonitor, + const DXGI_VK_MONITOR_DATA* pData); + + HRESULT STDMETHODCALLTYPE AcquireMonitorData( + HMONITOR hMonitor, + DXGI_VK_MONITOR_DATA** ppData); + + void STDMETHODCALLTYPE ReleaseMonitorData(); + + private: + + IUnknown* m_parent; + + dxvk::mutex m_monitorMutex; + std::unordered_map m_monitorData; + + }; + + + /** + * \brief Queries bits per pixel for a format + * + * The format must be a valid swap chain format. + * \param [in] Format The DXGI format to query + * \returns Bits per pixel for this format + */ + uint32_t GetMonitorFormatBpp( + DXGI_FORMAT Format); + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxgi/dxgi_object.h b/utils/dxvk-1.10.3/src/dxgi/dxgi_object.h new file mode 100644 index 00000000000..aac2bb4cc82 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxgi/dxgi_object.h @@ -0,0 +1,43 @@ +#pragma once + +#include "dxgi_include.h" + +#include "../util/com/com_private_data.h" + +namespace dxvk { + + template + class DxgiObject : public ComObject { + + public: + + HRESULT STDMETHODCALLTYPE GetPrivateData( + REFGUID Name, + UINT* pDataSize, + void* pData) final { + return m_privateData.getData( + Name, pDataSize, pData); + } + + HRESULT STDMETHODCALLTYPE SetPrivateData( + REFGUID Name, + UINT DataSize, + const void* pData) final { + return m_privateData.setData( + Name, DataSize, pData); + } + + HRESULT STDMETHODCALLTYPE SetPrivateDataInterface( + REFGUID Name, + const IUnknown* pUnknown) final { + return m_privateData.setInterface( + Name, pUnknown); + } + + private: + + ComPrivateData m_privateData; + + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxgi/dxgi_options.cpp b/utils/dxvk-1.10.3/src/dxgi/dxgi_options.cpp new file mode 100644 index 00000000000..469692d1906 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxgi/dxgi_options.cpp @@ -0,0 +1,50 @@ +#include "dxgi_options.h" + +#include + +namespace dxvk { + + static int32_t parsePciId(const std::string& str) { + if (str.size() != 4) + return -1; + + int32_t id = 0; + + for (size_t i = 0; i < str.size(); i++) { + id *= 16; + + if (str[i] >= '0' && str[i] <= '9') + id += str[i] - '0'; + else if (str[i] >= 'A' && str[i] <= 'F') + id += str[i] - 'A' + 10; + else if (str[i] >= 'a' && str[i] <= 'f') + id += str[i] - 'a' + 10; + else + return -1; + } + + return id; + } + + + DxgiOptions::DxgiOptions(const Config& config) { + // Fetch these as a string representing a hexadecimal number and parse it. + this->customVendorId = parsePciId(config.getOption("dxgi.customVendorId")); + this->customDeviceId = parsePciId(config.getOption("dxgi.customDeviceId")); + this->customDeviceDesc = config.getOption("dxgi.customDeviceDesc", ""); + + // Emulate a UMA device + this->emulateUMA = config.getOption("dxgi.emulateUMA", false); + + // Interpret the memory limits as Megabytes + this->maxDeviceMemory = VkDeviceSize(config.getOption("dxgi.maxDeviceMemory", 0)) << 20; + this->maxSharedMemory = VkDeviceSize(config.getOption("dxgi.maxSharedMemory", 0)) << 20; + + // Force nvapiHack to be disabled if NvAPI is enabled in environment + if (env::getEnvVar("DXVK_ENABLE_NVAPI") == "1") + this->nvapiHack = false; + else + this->nvapiHack = config.getOption("dxgi.nvapiHack", true); + } + +} diff --git a/utils/dxvk-1.10.3/src/dxgi/dxgi_options.h b/utils/dxvk-1.10.3/src/dxgi/dxgi_options.h new file mode 100644 index 00000000000..8eb19d0848f --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxgi/dxgi_options.h @@ -0,0 +1,40 @@ +#pragma once + +#include "../util/config/config.h" + +#include "../dxvk/dxvk_include.h" + +#include "dxgi_include.h" + +namespace dxvk { + + /** + * \brief DXGI options + * + * Per-app options that control the + * behaviour of some DXGI classes. + */ + struct DxgiOptions { + DxgiOptions(const Config& config); + + /// Override PCI vendor and device IDs reported to the + /// application. This may make apps think they are running + /// on a different GPU than they do and behave differently. + int32_t customVendorId; + int32_t customDeviceId; + std::string customDeviceDesc; + + /// Override maximum reported VRAM size. This may be + /// useful for some 64-bit games which do not support + /// more than 4 GiB of VRAM. + VkDeviceSize maxDeviceMemory; + VkDeviceSize maxSharedMemory; + + /// Emulate UMA + bool emulateUMA; + + /// Enables nvapi workaround + bool nvapiHack; + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxgi/dxgi_output.cpp b/utils/dxvk-1.10.3/src/dxgi/dxgi_output.cpp new file mode 100644 index 00000000000..ffa5b5dc275 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxgi/dxgi_output.cpp @@ -0,0 +1,606 @@ +#include +#include + +#include +#include + +#include +#include + +#include "dxgi_adapter.h" +#include "dxgi_factory.h" +#include "dxgi_output.h" +#include "dxgi_swapchain.h" + +#include "../dxvk/dxvk_format.h" + +namespace dxvk { + + DxgiOutput::DxgiOutput( + const Com& factory, + const Com& adapter, + HMONITOR monitor) + : m_monitorInfo(factory->GetMonitorInfo()), + m_adapter(adapter), + m_monitor(monitor) { + // Init monitor info if necessary + DXGI_VK_MONITOR_DATA monitorData; + monitorData.pSwapChain = nullptr; + monitorData.FrameStats = DXGI_FRAME_STATISTICS(); + monitorData.GammaCurve.Scale = { 1.0f, 1.0f, 1.0f }; + monitorData.GammaCurve.Offset = { 0.0f, 0.0f, 0.0f }; + + for (uint32_t i = 0; i < DXGI_VK_GAMMA_CP_COUNT; i++) { + const float value = GammaControlPointLocation(i); + monitorData.GammaCurve.GammaCurve[i] = { value, value, value }; + } + + m_monitorInfo->InitMonitorData(monitor, &monitorData); + } + + + DxgiOutput::~DxgiOutput() { + + } + + + HRESULT STDMETHODCALLTYPE DxgiOutput::QueryInterface(REFIID riid, void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(IDXGIObject) + || riid == __uuidof(IDXGIOutput) + || riid == __uuidof(IDXGIOutput1) + || riid == __uuidof(IDXGIOutput2) + || riid == __uuidof(IDXGIOutput3) + || riid == __uuidof(IDXGIOutput4) + || riid == __uuidof(IDXGIOutput5) + || riid == __uuidof(IDXGIOutput6)) { + *ppvObject = ref(this); + return S_OK; + } + + Logger::warn("DxgiOutput::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + HRESULT STDMETHODCALLTYPE DxgiOutput::GetParent(REFIID riid, void **ppParent) { + return m_adapter->QueryInterface(riid, ppParent); + } + + + HRESULT STDMETHODCALLTYPE DxgiOutput::FindClosestMatchingMode( + const DXGI_MODE_DESC *pModeToMatch, + DXGI_MODE_DESC *pClosestMatch, + IUnknown *pConcernedDevice) { + if (!pModeToMatch || !pClosestMatch) + return DXGI_ERROR_INVALID_CALL; + + DXGI_MODE_DESC1 modeToMatch; + modeToMatch.Width = pModeToMatch->Width; + modeToMatch.Height = pModeToMatch->Height; + modeToMatch.RefreshRate = pModeToMatch->RefreshRate; + modeToMatch.Format = pModeToMatch->Format; + modeToMatch.ScanlineOrdering = pModeToMatch->ScanlineOrdering; + modeToMatch.Scaling = pModeToMatch->Scaling; + modeToMatch.Stereo = FALSE; + + DXGI_MODE_DESC1 closestMatch = { }; + + HRESULT hr = FindClosestMatchingMode1( + &modeToMatch, &closestMatch, pConcernedDevice); + + if (FAILED(hr)) + return hr; + + pClosestMatch->Width = closestMatch.Width; + pClosestMatch->Height = closestMatch.Height; + pClosestMatch->RefreshRate = closestMatch.RefreshRate; + pClosestMatch->Format = closestMatch.Format; + pClosestMatch->ScanlineOrdering = closestMatch.ScanlineOrdering; + pClosestMatch->Scaling = closestMatch.Scaling; + return hr; + } + + + HRESULT STDMETHODCALLTYPE DxgiOutput::FindClosestMatchingMode1( + const DXGI_MODE_DESC1* pModeToMatch, + DXGI_MODE_DESC1* pClosestMatch, + IUnknown* pConcernedDevice) { + if (!pModeToMatch || !pClosestMatch) + return DXGI_ERROR_INVALID_CALL; + + if (pModeToMatch->Format == DXGI_FORMAT_UNKNOWN && !pConcernedDevice) + return DXGI_ERROR_INVALID_CALL; + + // Both or neither must be zero + if ((pModeToMatch->Width == 0) ^ (pModeToMatch->Height == 0)) + return DXGI_ERROR_INVALID_CALL; + + DEVMODEW devMode; + devMode.dmSize = sizeof(devMode); + + if (!GetMonitorDisplayMode(m_monitor, ENUM_CURRENT_SETTINGS, &devMode)) + return DXGI_ERROR_NOT_CURRENTLY_AVAILABLE; + + DXGI_MODE_DESC activeMode = { }; + activeMode.Width = devMode.dmPelsWidth; + activeMode.Height = devMode.dmPelsHeight; + activeMode.RefreshRate = { devMode.dmDisplayFrequency, 1 }; + activeMode.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; // FIXME + activeMode.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE; + activeMode.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + + DXGI_MODE_DESC1 defaultMode; + defaultMode.Width = 0; + defaultMode.Height = 0; + defaultMode.RefreshRate = { 0, 0 }; + defaultMode.Format = DXGI_FORMAT_UNKNOWN; + defaultMode.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; + defaultMode.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + defaultMode.Stereo = pModeToMatch->Stereo; + + if (pModeToMatch->ScanlineOrdering == DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED) + defaultMode.ScanlineOrdering = activeMode.ScanlineOrdering; + + if (pModeToMatch->Scaling == DXGI_MODE_SCALING_UNSPECIFIED) + defaultMode.Scaling = activeMode.Scaling; + + DXGI_FORMAT targetFormat = pModeToMatch->Format; + + if (pModeToMatch->Format == DXGI_FORMAT_UNKNOWN) { + defaultMode.Format = activeMode.Format; + targetFormat = activeMode.Format; + } + + if (!pModeToMatch->Width) { + defaultMode.Width = activeMode.Width; + defaultMode.Height = activeMode.Height; + } + + if (!pModeToMatch->RefreshRate.Numerator || !pModeToMatch->RefreshRate.Denominator) { + defaultMode.RefreshRate.Numerator = activeMode.RefreshRate.Numerator; + defaultMode.RefreshRate.Denominator = activeMode.RefreshRate.Denominator; + } + + UINT modeCount = 0; + GetDisplayModeList1(targetFormat, DXGI_ENUM_MODES_SCALING, &modeCount, nullptr); + + if (modeCount == 0) { + Logger::err("DXGI: FindClosestMatchingMode: No modes found"); + return DXGI_ERROR_NOT_FOUND; + } + + std::vector modes(modeCount); + GetDisplayModeList1(targetFormat, DXGI_ENUM_MODES_SCALING, &modeCount, modes.data()); + + FilterModesByDesc(modes, *pModeToMatch); + FilterModesByDesc(modes, defaultMode); + + if (modes.empty()) + return DXGI_ERROR_NOT_FOUND; + + *pClosestMatch = modes[0]; + + Logger::debug(str::format( + "DXGI: For mode ", + pModeToMatch->Width, "x", pModeToMatch->Height, "@", + pModeToMatch->RefreshRate.Denominator ? (pModeToMatch->RefreshRate.Numerator / pModeToMatch->RefreshRate.Denominator) : 0, + " found closest mode ", + pClosestMatch->Width, "x", pClosestMatch->Height, "@", + pClosestMatch->RefreshRate.Denominator ? (pClosestMatch->RefreshRate.Numerator / pClosestMatch->RefreshRate.Denominator) : 0)); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE DxgiOutput::GetDesc(DXGI_OUTPUT_DESC *pDesc) { + if (pDesc == nullptr) + return DXGI_ERROR_INVALID_CALL; + + DXGI_OUTPUT_DESC1 desc; + HRESULT hr = GetDesc1(&desc); + + if (SUCCEEDED(hr)) { + std::memcpy(pDesc->DeviceName, desc.DeviceName, sizeof(pDesc->DeviceName)); + pDesc->DesktopCoordinates = desc.DesktopCoordinates; + pDesc->AttachedToDesktop = desc.AttachedToDesktop; + pDesc->Rotation = desc.Rotation; + pDesc->Monitor = desc.Monitor; + } + + return hr; + } + + + HRESULT STDMETHODCALLTYPE DxgiOutput::GetDesc1( + DXGI_OUTPUT_DESC1* pDesc) { + if (pDesc == nullptr) + return DXGI_ERROR_INVALID_CALL; + + ::MONITORINFOEXW monInfo; + monInfo.cbSize = sizeof(monInfo); + + if (!::GetMonitorInfoW(m_monitor, reinterpret_cast(&monInfo))) { + Logger::err("DXGI: Failed to query monitor info"); + return E_FAIL; + } + + std::memcpy(pDesc->DeviceName, monInfo.szDevice, std::size(pDesc->DeviceName)); + + pDesc->DesktopCoordinates = monInfo.rcMonitor; + pDesc->AttachedToDesktop = 1; + pDesc->Rotation = DXGI_MODE_ROTATION_UNSPECIFIED; + pDesc->Monitor = m_monitor; + pDesc->BitsPerColor = 8; + pDesc->ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; + + // We don't really have a way to get these + for (uint32_t i = 0; i < 2; i++) { + pDesc->RedPrimary[i] = 0.0f; + pDesc->GreenPrimary[i] = 0.0f; + pDesc->BluePrimary[i] = 0.0f; + pDesc->WhitePoint[i] = 0.0f; + } + + pDesc->MinLuminance = 0.0f; + pDesc->MaxLuminance = 0.0f; + pDesc->MaxFullFrameLuminance = 0.0f; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE DxgiOutput::GetDisplayModeList( + DXGI_FORMAT EnumFormat, + UINT Flags, + UINT* pNumModes, + DXGI_MODE_DESC* pDesc) { + if (pNumModes == nullptr) + return DXGI_ERROR_INVALID_CALL; + + std::vector modes; + + if (pDesc) + modes.resize(std::max(1u, *pNumModes)); + + HRESULT hr = GetDisplayModeList1( + EnumFormat, Flags, pNumModes, + pDesc ? modes.data() : nullptr); + + for (uint32_t i = 0; i < *pNumModes && i < modes.size(); i++) { + pDesc[i].Width = modes[i].Width; + pDesc[i].Height = modes[i].Height; + pDesc[i].RefreshRate = modes[i].RefreshRate; + pDesc[i].Format = modes[i].Format; + pDesc[i].ScanlineOrdering = modes[i].ScanlineOrdering; + pDesc[i].Scaling = modes[i].Scaling; + } + + return hr; + } + + + HRESULT STDMETHODCALLTYPE DxgiOutput::GetDisplayModeList1( + DXGI_FORMAT EnumFormat, + UINT Flags, + UINT* pNumModes, + DXGI_MODE_DESC1* pDesc) { + if (pNumModes == nullptr) + return DXGI_ERROR_INVALID_CALL; + + // Special case, just return zero modes + if (EnumFormat == DXGI_FORMAT_UNKNOWN) { + *pNumModes = 0; + return S_OK; + } + + // Walk over all modes that the display supports and + // return those that match the requested format etc. + DEVMODEW devMode = { }; + devMode.dmSize = sizeof(DEVMODEW); + + uint32_t srcModeId = 0; + uint32_t dstModeId = 0; + + std::vector modeList; + + while (GetMonitorDisplayMode(m_monitor, srcModeId++, &devMode)) { + // Skip interlaced modes altogether + if (devMode.dmDisplayFlags & DM_INTERLACED) + continue; + + // Skip modes with incompatible formats + if (devMode.dmBitsPerPel != GetMonitorFormatBpp(EnumFormat)) + continue; + + if (pDesc != nullptr) { + DXGI_MODE_DESC1 mode; + mode.Width = devMode.dmPelsWidth; + mode.Height = devMode.dmPelsHeight; + mode.RefreshRate = { devMode.dmDisplayFrequency * 1000, 1000 }; + mode.Format = EnumFormat; + mode.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE; + mode.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + mode.Stereo = FALSE; + modeList.push_back(mode); + } + + dstModeId += 1; + } + + // Sort display modes by width, height and refresh rate, + // in that order. Some games rely on correct ordering. + std::sort(modeList.begin(), modeList.end(), + [] (const DXGI_MODE_DESC1& a, const DXGI_MODE_DESC1& b) { + if (a.Width < b.Width) return true; + if (a.Width > b.Width) return false; + + if (a.Height < b.Height) return true; + if (a.Height > b.Height) return false; + + return (a.RefreshRate.Numerator / a.RefreshRate.Denominator) + < (b.RefreshRate.Numerator / b.RefreshRate.Denominator); + }); + + // If requested, write out the first set of display + // modes to the destination array. + if (pDesc != nullptr) { + for (uint32_t i = 0; i < *pNumModes && i < dstModeId; i++) + pDesc[i] = modeList[i]; + + if (dstModeId > *pNumModes) + return DXGI_ERROR_MORE_DATA; + } + + *pNumModes = dstModeId; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE DxgiOutput::GetDisplaySurfaceData(IDXGISurface* pDestination) { + Logger::err("DxgiOutput::GetDisplaySurfaceData: Not implemented"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE DxgiOutput::GetFrameStatistics(DXGI_FRAME_STATISTICS* pStats) { + DXGI_VK_MONITOR_DATA* monitorInfo = nullptr; + HRESULT hr = m_monitorInfo->AcquireMonitorData(m_monitor, &monitorInfo); + + if (FAILED(hr)) + return hr; + + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::warn("DxgiOutput::GetFrameStatistics: Stub"); + + *pStats = monitorInfo->FrameStats; + m_monitorInfo->ReleaseMonitorData(); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE DxgiOutput::GetGammaControl(DXGI_GAMMA_CONTROL* pArray) { + DXGI_VK_MONITOR_DATA* monitorInfo = nullptr; + HRESULT hr = m_monitorInfo->AcquireMonitorData(m_monitor, &monitorInfo); + + if (FAILED(hr)) + return hr; + + *pArray = monitorInfo->GammaCurve; + m_monitorInfo->ReleaseMonitorData(); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE DxgiOutput::GetGammaControlCapabilities(DXGI_GAMMA_CONTROL_CAPABILITIES* pGammaCaps) { + pGammaCaps->ScaleAndOffsetSupported = FALSE; + pGammaCaps->MaxConvertedValue = 1.0f; + pGammaCaps->MinConvertedValue = 0.0f; + pGammaCaps->NumGammaControlPoints = DXGI_VK_GAMMA_CP_COUNT; + + for (uint32_t i = 0; i < pGammaCaps->NumGammaControlPoints; i++) + pGammaCaps->ControlPointPositions[i] = GammaControlPointLocation(i); + return S_OK; + } + + + void STDMETHODCALLTYPE DxgiOutput::ReleaseOwnership() { + Logger::warn("DxgiOutput::ReleaseOwnership: Stub"); + } + + + HRESULT STDMETHODCALLTYPE DxgiOutput::SetDisplaySurface(IDXGISurface* pScanoutSurface) { + Logger::err("DxgiOutput::SetDisplaySurface: Not implemented"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE DxgiOutput::GetDisplaySurfaceData1(IDXGIResource* pDestination) { + Logger::err("DxgiOutput::SetDisplaySurface1: Not implemented"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE DxgiOutput::SetGammaControl(const DXGI_GAMMA_CONTROL* pArray) { + DXGI_VK_MONITOR_DATA* monitorInfo = nullptr; + HRESULT hr = m_monitorInfo->AcquireMonitorData(m_monitor, &monitorInfo); + + if (FAILED(hr)) + return hr; + + monitorInfo->GammaCurve = *pArray; + + if (monitorInfo->pSwapChain) { + hr = monitorInfo->pSwapChain->SetGammaControl( + DXGI_VK_GAMMA_CP_COUNT, pArray->GammaCurve); + } + + m_monitorInfo->ReleaseMonitorData(); + return hr; + } + + + HRESULT STDMETHODCALLTYPE DxgiOutput::TakeOwnership( + IUnknown *pDevice, + BOOL Exclusive) { + Logger::warn("DxgiOutput::TakeOwnership: Stub"); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE DxgiOutput::WaitForVBlank() { + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::warn("DxgiOutput::WaitForVBlank: Stub"); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE DxgiOutput::DuplicateOutput( + IUnknown* pDevice, + IDXGIOutputDuplication** ppOutputDuplication) { + return DuplicateOutput1(pDevice, 0, 0, nullptr, ppOutputDuplication); + } + + + HRESULT STDMETHODCALLTYPE DxgiOutput::DuplicateOutput1( + IUnknown* pDevice, + UINT Flags, + UINT SupportedFormatsCount, + const DXGI_FORMAT* pSupportedFormats, + IDXGIOutputDuplication** ppOutputDuplication) { + InitReturnPtr(ppOutputDuplication); + + if (!pDevice) + return E_INVALIDARG; + + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::err("DxgiOutput::DuplicateOutput1: Not implemented"); + + // At least return a valid error code + return DXGI_ERROR_UNSUPPORTED; + } + + + BOOL DxgiOutput::SupportsOverlays() { + return FALSE; + } + + + HRESULT STDMETHODCALLTYPE DxgiOutput::CheckOverlaySupport( + DXGI_FORMAT EnumFormat, + IUnknown* pConcernedDevice, + UINT* pFlags) { + Logger::warn("DxgiOutput: CheckOverlaySupport: Stub"); + return DXGI_ERROR_UNSUPPORTED; + } + + + HRESULT STDMETHODCALLTYPE DxgiOutput::CheckOverlayColorSpaceSupport( + DXGI_FORMAT Format, + DXGI_COLOR_SPACE_TYPE ColorSpace, + IUnknown* pConcernedDevice, + UINT* pFlags) { + Logger::warn("DxgiOutput: CheckOverlayColorSpaceSupport: Stub"); + return DXGI_ERROR_UNSUPPORTED; + } + + + HRESULT STDMETHODCALLTYPE DxgiOutput::CheckHardwareCompositionSupport( + UINT* pFlags) { + Logger::warn("DxgiOutput: CheckHardwareCompositionSupport: Stub"); + + *pFlags = 0; + return S_OK; + } + + + void DxgiOutput::FilterModesByDesc( + std::vector& Modes, + const DXGI_MODE_DESC1& TargetMode) { + // Filter modes based on format properties + bool testScanlineOrder = false; + bool testScaling = false; + bool testFormat = false; + + for (const auto& mode : Modes) { + testScanlineOrder |= TargetMode.ScanlineOrdering != DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED + && TargetMode.ScanlineOrdering == mode.ScanlineOrdering; + testScaling |= TargetMode.Scaling != DXGI_MODE_SCALING_UNSPECIFIED + && TargetMode.Scaling == mode.Scaling; + testFormat |= TargetMode.Format != DXGI_FORMAT_UNKNOWN + && TargetMode.Format == mode.Format; + } + + for (auto it = Modes.begin(); it != Modes.end(); ) { + bool skipMode = it->Stereo != TargetMode.Stereo; + + if (testScanlineOrder) + skipMode |= it->ScanlineOrdering != TargetMode.ScanlineOrdering; + + if (testScaling) + skipMode |= it->Scaling != TargetMode.Scaling; + + if (testFormat) + skipMode |= it->Format != TargetMode.Format; + + it = skipMode ? Modes.erase(it) : ++it; + } + + // Filter by closest resolution + uint32_t minDiffResolution = 0; + + if (TargetMode.Width) { + minDiffResolution = std::accumulate( + Modes.begin(), Modes.end(), std::numeric_limits::max(), + [&TargetMode] (uint32_t current, const DXGI_MODE_DESC1& mode) { + uint32_t diff = std::abs(int32_t(TargetMode.Width - mode.Width)) + + std::abs(int32_t(TargetMode.Height - mode.Height)); + return std::min(current, diff); + }); + + for (auto it = Modes.begin(); it != Modes.end(); ) { + uint32_t diff = std::abs(int32_t(TargetMode.Width - it->Width)) + + std::abs(int32_t(TargetMode.Height - it->Height)); + + bool skipMode = diff != minDiffResolution; + it = skipMode ? Modes.erase(it) : ++it; + } + } + + // Filter by closest refresh rate + uint32_t minDiffRefreshRate = 0; + + if (TargetMode.RefreshRate.Numerator && TargetMode.RefreshRate.Denominator) { + minDiffRefreshRate = std::accumulate( + Modes.begin(), Modes.end(), std::numeric_limits::max(), + [&TargetMode] (uint64_t current, const DXGI_MODE_DESC1& mode) { + uint64_t rate = uint64_t(mode.RefreshRate.Numerator) + * uint64_t(TargetMode.RefreshRate.Denominator) + / uint64_t(mode.RefreshRate.Denominator); + uint64_t diff = std::abs(int64_t(rate - uint64_t(TargetMode.RefreshRate.Numerator))); + return std::min(current, diff); + }); + + for (auto it = Modes.begin(); it != Modes.end(); ) { + uint64_t rate = uint64_t(it->RefreshRate.Numerator) + * uint64_t(TargetMode.RefreshRate.Denominator) + / uint64_t(it->RefreshRate.Denominator); + uint64_t diff = std::abs(int64_t(rate - uint64_t(TargetMode.RefreshRate.Numerator))); + + bool skipMode = diff != minDiffRefreshRate; + it = skipMode ? Modes.erase(it) : ++it; + } + } + } + +} diff --git a/utils/dxvk-1.10.3/src/dxgi/dxgi_output.h b/utils/dxvk-1.10.3/src/dxgi/dxgi_output.h new file mode 100644 index 00000000000..0dc30868d75 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxgi/dxgi_output.h @@ -0,0 +1,142 @@ +#pragma once + +#include "dxgi_monitor.h" +#include "dxgi_object.h" + +namespace dxvk { + + class DxgiAdapter; + class DxgiFactory; + + /** + * \brief Number of gamma control points + */ + constexpr uint32_t DXGI_VK_GAMMA_CP_COUNT = 1024; + + /** + * \brief Computes gamma control point location + * + * \param [in] CpIndex Control point ID + * \returns Location of the control point + */ + inline float GammaControlPointLocation(uint32_t CpIndex) { + return float(CpIndex) / float(DXGI_VK_GAMMA_CP_COUNT - 1); + } + + + class DxgiOutput : public DxgiObject { + + public: + + DxgiOutput( + const Com& factory, + const Com& adapter, + HMONITOR monitor); + + ~DxgiOutput(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject) final; + + HRESULT STDMETHODCALLTYPE GetParent( + REFIID riid, + void** ppParent) final; + + HRESULT STDMETHODCALLTYPE FindClosestMatchingMode( + const DXGI_MODE_DESC* pModeToMatch, + DXGI_MODE_DESC* pClosestMatch, + IUnknown* pConcernedDevice) final; + + HRESULT STDMETHODCALLTYPE FindClosestMatchingMode1( + const DXGI_MODE_DESC1* pModeToMatch, + DXGI_MODE_DESC1* pClosestMatch, + IUnknown* pConcernedDevice) final; + + HRESULT STDMETHODCALLTYPE GetDesc( + DXGI_OUTPUT_DESC* pDesc) final; + + HRESULT STDMETHODCALLTYPE GetDesc1( + DXGI_OUTPUT_DESC1* pDesc) final; + + HRESULT STDMETHODCALLTYPE GetDisplayModeList( + DXGI_FORMAT EnumFormat, + UINT Flags, + UINT* pNumModes, + DXGI_MODE_DESC* pDesc) final; + + HRESULT STDMETHODCALLTYPE GetDisplayModeList1( + DXGI_FORMAT EnumFormat, + UINT Flags, + UINT* pNumModes, + DXGI_MODE_DESC1* pDesc) final; + + HRESULT STDMETHODCALLTYPE GetDisplaySurfaceData( + IDXGISurface* pDestination) final; + + HRESULT STDMETHODCALLTYPE GetDisplaySurfaceData1( + IDXGIResource* pDestination) final; + + HRESULT STDMETHODCALLTYPE GetFrameStatistics( + DXGI_FRAME_STATISTICS* pStats) final; + + HRESULT STDMETHODCALLTYPE GetGammaControl( + DXGI_GAMMA_CONTROL* pArray) final; + + HRESULT STDMETHODCALLTYPE GetGammaControlCapabilities( + DXGI_GAMMA_CONTROL_CAPABILITIES *pGammaCaps) final; + + void STDMETHODCALLTYPE ReleaseOwnership() final; + + HRESULT STDMETHODCALLTYPE SetDisplaySurface( + IDXGISurface* pScanoutSurface) final; + + HRESULT STDMETHODCALLTYPE SetGammaControl( + const DXGI_GAMMA_CONTROL* pArray) final; + + HRESULT STDMETHODCALLTYPE TakeOwnership( + IUnknown* pDevice, + BOOL Exclusive) final; + + HRESULT STDMETHODCALLTYPE WaitForVBlank() final; + + HRESULT STDMETHODCALLTYPE DuplicateOutput( + IUnknown* pDevice, + IDXGIOutputDuplication** ppOutputDuplication) final; + + HRESULT STDMETHODCALLTYPE DuplicateOutput1( + IUnknown* pDevice, + UINT Flags, + UINT SupportedFormatsCount, + const DXGI_FORMAT* pSupportedFormats, + IDXGIOutputDuplication** ppOutputDuplication) final; + + BOOL STDMETHODCALLTYPE SupportsOverlays() final; + + HRESULT STDMETHODCALLTYPE CheckOverlaySupport( + DXGI_FORMAT EnumFormat, + IUnknown* pConcernedDevice, + UINT* pFlags) final; + + HRESULT STDMETHODCALLTYPE CheckOverlayColorSpaceSupport( + DXGI_FORMAT Format, + DXGI_COLOR_SPACE_TYPE ColorSpace, + IUnknown* pConcernedDevice, + UINT* pFlags) final; + + HRESULT STDMETHODCALLTYPE CheckHardwareCompositionSupport( + UINT* pFlags) final; + + private: + + DxgiMonitorInfo* m_monitorInfo = nullptr; + Com m_adapter = nullptr; + HMONITOR m_monitor = nullptr; + + static void FilterModesByDesc( + std::vector& Modes, + const DXGI_MODE_DESC1& TargetMode); + + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxgi/dxgi_swapchain.cpp b/utils/dxvk-1.10.3/src/dxgi/dxgi_swapchain.cpp new file mode 100644 index 00000000000..09ebd697248 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxgi/dxgi_swapchain.cpp @@ -0,0 +1,809 @@ +#include "dxgi_factory.h" +#include "dxgi_output.h" +#include "dxgi_swapchain.h" + +namespace dxvk { + + DxgiSwapChain::DxgiSwapChain( + IDXGIFactory* pFactory, + IDXGIVkSwapChain* pPresenter, + HWND hWnd, + const DXGI_SWAP_CHAIN_DESC1* pDesc, + const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc) + : m_factory (pFactory), + m_window (hWnd), + m_desc (*pDesc), + m_descFs (*pFullscreenDesc), + m_presentCount(0u), + m_presenter (pPresenter), + m_monitor (nullptr) { + if (FAILED(m_presenter->GetAdapter(__uuidof(IDXGIAdapter), reinterpret_cast(&m_adapter)))) + throw DxvkError("DXGI: Failed to get adapter for present device"); + + // Query monitor info form DXVK's DXGI factory, if available + m_factory->QueryInterface(__uuidof(IDXGIVkMonitorInfo), reinterpret_cast(&m_monitorInfo)); + + // Apply initial window mode and fullscreen state + if (!m_descFs.Windowed && FAILED(EnterFullscreenMode(nullptr))) + throw DxvkError("DXGI: Failed to set initial fullscreen state"); + } + + + DxgiSwapChain::~DxgiSwapChain() { + RestoreDisplayMode(m_monitor); + + // Decouple swap chain from monitor if necessary + DXGI_VK_MONITOR_DATA* monitorInfo = nullptr; + + if (SUCCEEDED(AcquireMonitorData(m_monitor, &monitorInfo))) { + if (monitorInfo->pSwapChain == this) + monitorInfo->pSwapChain = nullptr; + + ReleaseMonitorData(); + } + } + + + HRESULT STDMETHODCALLTYPE DxgiSwapChain::QueryInterface(REFIID riid, void** ppvObject) { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(IDXGIObject) + || riid == __uuidof(IDXGIDeviceSubObject) + || riid == __uuidof(IDXGISwapChain) + || riid == __uuidof(IDXGISwapChain1) + || riid == __uuidof(IDXGISwapChain2) + || riid == __uuidof(IDXGISwapChain3) + || riid == __uuidof(IDXGISwapChain4)) { + *ppvObject = ref(this); + return S_OK; + } + + Logger::warn("DxgiSwapChain::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return E_NOINTERFACE; + } + + + HRESULT STDMETHODCALLTYPE DxgiSwapChain::GetParent(REFIID riid, void** ppParent) { + return m_factory->QueryInterface(riid, ppParent); + } + + + HRESULT STDMETHODCALLTYPE DxgiSwapChain::GetDevice(REFIID riid, void** ppDevice) { + return m_presenter->GetDevice(riid, ppDevice); + } + + + HRESULT STDMETHODCALLTYPE DxgiSwapChain::GetBuffer(UINT Buffer, REFIID riid, void** ppSurface) { + return m_presenter->GetImage(Buffer, riid, ppSurface); + } + + + UINT STDMETHODCALLTYPE DxgiSwapChain::GetCurrentBackBufferIndex() { + return m_presenter->GetImageIndex(); + } + + + HRESULT STDMETHODCALLTYPE DxgiSwapChain::GetContainingOutput(IDXGIOutput** ppOutput) { + InitReturnPtr(ppOutput); + + if (!IsWindow(m_window)) + return DXGI_ERROR_INVALID_CALL; + + if (m_target != nullptr) { + *ppOutput = m_target.ref(); + return S_OK; + } + + RECT windowRect = { 0, 0, 0, 0 }; + ::GetWindowRect(m_window, &windowRect); + + HMONITOR monitor = ::MonitorFromPoint( + { (windowRect.left + windowRect.right) / 2, + (windowRect.top + windowRect.bottom) / 2 }, + MONITOR_DEFAULTTOPRIMARY); + + return GetOutputFromMonitor(monitor, ppOutput); + } + + + HRESULT STDMETHODCALLTYPE DxgiSwapChain::GetDesc(DXGI_SWAP_CHAIN_DESC* pDesc) { + if (!pDesc) + return E_INVALIDARG; + + pDesc->BufferDesc.Width = m_desc.Width; + pDesc->BufferDesc.Height = m_desc.Height; + pDesc->BufferDesc.RefreshRate = m_descFs.RefreshRate; + pDesc->BufferDesc.Format = m_desc.Format; + pDesc->BufferDesc.ScanlineOrdering = m_descFs.ScanlineOrdering; + pDesc->BufferDesc.Scaling = m_descFs.Scaling; + pDesc->SampleDesc = m_desc.SampleDesc; + pDesc->BufferUsage = m_desc.BufferUsage; + pDesc->BufferCount = m_desc.BufferCount; + pDesc->OutputWindow = m_window; + pDesc->Windowed = m_descFs.Windowed; + pDesc->SwapEffect = m_desc.SwapEffect; + pDesc->Flags = m_desc.Flags; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE DxgiSwapChain::GetDesc1(DXGI_SWAP_CHAIN_DESC1* pDesc) { + if (pDesc == nullptr) + return E_INVALIDARG; + + *pDesc = m_desc; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE DxgiSwapChain::GetBackgroundColor( + DXGI_RGBA* pColor) { + Logger::err("DxgiSwapChain::GetBackgroundColor: Not implemented"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE DxgiSwapChain::GetRotation( + DXGI_MODE_ROTATION* pRotation) { + Logger::err("DxgiSwapChain::GetRotation: Not implemented"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE DxgiSwapChain::GetRestrictToOutput( + IDXGIOutput** ppRestrictToOutput) { + InitReturnPtr(ppRestrictToOutput); + + Logger::err("DxgiSwapChain::GetRestrictToOutput: Not implemented"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE DxgiSwapChain::GetFrameStatistics(DXGI_FRAME_STATISTICS* pStats) { + std::lock_guard lock(m_lockWindow); + + if (!pStats) + return E_INVALIDARG; + + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::warn("DxgiSwapChain::GetFrameStatistics: Semi-stub"); + + // TODO deal with the refresh counts at some point + pStats->PresentCount = m_presentCount; + pStats->PresentRefreshCount = 0; + pStats->SyncRefreshCount = 0; + QueryPerformanceCounter(&pStats->SyncQPCTime); + pStats->SyncGPUTime.QuadPart = 0; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE DxgiSwapChain::GetFullscreenState( + BOOL* pFullscreen, + IDXGIOutput** ppTarget) { + HRESULT hr = S_OK; + + if (pFullscreen != nullptr) + *pFullscreen = !m_descFs.Windowed; + + if (ppTarget != nullptr) + *ppTarget = m_target.ref(); + + return hr; + } + + + HRESULT STDMETHODCALLTYPE DxgiSwapChain::GetFullscreenDesc( + DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pDesc) { + if (pDesc == nullptr) + return E_INVALIDARG; + + *pDesc = m_descFs; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE DxgiSwapChain::GetHwnd( + HWND* pHwnd) { + if (pHwnd == nullptr) + return E_INVALIDARG; + + *pHwnd = m_window; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE DxgiSwapChain::GetCoreWindow( + REFIID refiid, + void** ppUnk) { + InitReturnPtr(ppUnk); + + Logger::err("DxgiSwapChain::GetCoreWindow: Not implemented"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE DxgiSwapChain::GetLastPresentCount(UINT* pLastPresentCount) { + if (pLastPresentCount == nullptr) + return E_INVALIDARG; + + *pLastPresentCount = m_presentCount; + return S_OK; + } + + + BOOL STDMETHODCALLTYPE DxgiSwapChain::IsTemporaryMonoSupported() { + // This seems to be related to stereo 3D display + // modes, which we don't support at the moment + return FALSE; + } + + + HRESULT STDMETHODCALLTYPE DxgiSwapChain::Present(UINT SyncInterval, UINT Flags) { + return Present1(SyncInterval, Flags, nullptr); + } + + + HRESULT STDMETHODCALLTYPE DxgiSwapChain::Present1( + UINT SyncInterval, + UINT PresentFlags, + const DXGI_PRESENT_PARAMETERS* pPresentParameters) { + + if (!IsWindow(m_window)) + return S_OK; + + if (SyncInterval > 4) + return DXGI_ERROR_INVALID_CALL; + + std::lock_guard lockWin(m_lockWindow); + std::lock_guard lockBuf(m_lockBuffer); + + try { + HRESULT hr = m_presenter->Present(SyncInterval, PresentFlags, nullptr); + if (hr == S_OK && !(PresentFlags & DXGI_PRESENT_TEST)) + m_presentCount++; + return hr; + } catch (const DxvkError& err) { + Logger::err(err.message()); + return DXGI_ERROR_DRIVER_INTERNAL_ERROR; + } + } + + + HRESULT STDMETHODCALLTYPE DxgiSwapChain::ResizeBuffers( + UINT BufferCount, + UINT Width, + UINT Height, + DXGI_FORMAT NewFormat, + UINT SwapChainFlags) { + if (!IsWindow(m_window)) + return DXGI_ERROR_INVALID_CALL; + + constexpr UINT PreserveFlags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; + + if ((m_desc.Flags & PreserveFlags) != (SwapChainFlags & PreserveFlags)) + return DXGI_ERROR_INVALID_CALL; + + std::lock_guard lock(m_lockBuffer); + m_desc.Width = Width; + m_desc.Height = Height; + + GetWindowClientSize(m_window, + m_desc.Width ? nullptr : &m_desc.Width, + m_desc.Height ? nullptr : &m_desc.Height); + + if (BufferCount != 0) + m_desc.BufferCount = BufferCount; + + if (NewFormat != DXGI_FORMAT_UNKNOWN) + m_desc.Format = NewFormat; + + return m_presenter->ChangeProperties(&m_desc); + } + + + HRESULT STDMETHODCALLTYPE DxgiSwapChain::ResizeBuffers1( + UINT BufferCount, + UINT Width, + UINT Height, + DXGI_FORMAT Format, + UINT SwapChainFlags, + const UINT* pCreationNodeMask, + IUnknown* const* ppPresentQueue) { + static bool s_errorShown = false; + + if (!std::exchange(s_errorShown, true)) + Logger::warn("DxgiSwapChain::ResizeBuffers1: Stub"); + + return ResizeBuffers(BufferCount, + Width, Height, Format, SwapChainFlags); + } + + + HRESULT STDMETHODCALLTYPE DxgiSwapChain::ResizeTarget(const DXGI_MODE_DESC* pNewTargetParameters) { + std::lock_guard lock(m_lockWindow); + + if (pNewTargetParameters == nullptr) + return DXGI_ERROR_INVALID_CALL; + + if (!IsWindow(m_window)) + return DXGI_ERROR_INVALID_CALL; + + // Update the swap chain description + if (pNewTargetParameters->RefreshRate.Numerator != 0) + m_descFs.RefreshRate = pNewTargetParameters->RefreshRate; + + m_descFs.ScanlineOrdering = pNewTargetParameters->ScanlineOrdering; + m_descFs.Scaling = pNewTargetParameters->Scaling; + + if (m_descFs.Windowed) { + // Adjust window position and size + RECT newRect = { 0, 0, 0, 0 }; + RECT oldRect = { 0, 0, 0, 0 }; + + ::GetWindowRect(m_window, &oldRect); + ::SetRect(&newRect, 0, 0, pNewTargetParameters->Width, pNewTargetParameters->Height); + ::AdjustWindowRectEx(&newRect, + ::GetWindowLongW(m_window, GWL_STYLE), FALSE, + ::GetWindowLongW(m_window, GWL_EXSTYLE)); + ::SetRect(&newRect, 0, 0, newRect.right - newRect.left, newRect.bottom - newRect.top); + ::OffsetRect(&newRect, oldRect.left, oldRect.top); + ::MoveWindow(m_window, newRect.left, newRect.top, + newRect.right - newRect.left, newRect.bottom - newRect.top, TRUE); + } else { + Com output; + + if (FAILED(GetOutputFromMonitor(m_monitor, &output))) { + Logger::err("DXGI: ResizeTarget: Failed to query containing output"); + return E_FAIL; + } + + // If the swap chain allows it, change the display mode + if (m_desc.Flags & DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH) { + ChangeDisplayMode(output.ptr(), pNewTargetParameters); + NotifyModeChange(m_monitor, FALSE); + } + + // Resize and reposition the window to + DXGI_OUTPUT_DESC desc; + output->GetDesc(&desc); + + RECT newRect = desc.DesktopCoordinates; + + ::MoveWindow(m_window, newRect.left, newRect.top, + newRect.right - newRect.left, newRect.bottom - newRect.top, TRUE); + } + + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE DxgiSwapChain::SetFullscreenState( + BOOL Fullscreen, + IDXGIOutput* pTarget) { + std::lock_guard lock(m_lockWindow); + + if (!Fullscreen && pTarget) + return DXGI_ERROR_INVALID_CALL; + + if (m_descFs.Windowed && Fullscreen) + return this->EnterFullscreenMode(pTarget); + else if (!m_descFs.Windowed && !Fullscreen) + return this->LeaveFullscreenMode(); + + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE DxgiSwapChain::SetBackgroundColor( + const DXGI_RGBA* pColor) { + Logger::err("DxgiSwapChain::SetBackgroundColor: Not implemented"); + return E_NOTIMPL; + } + + + HRESULT STDMETHODCALLTYPE DxgiSwapChain::SetRotation( + DXGI_MODE_ROTATION Rotation) { + Logger::err("DxgiSwapChain::SetRotation: Not implemented"); + return E_NOTIMPL; + } + + + HANDLE STDMETHODCALLTYPE DxgiSwapChain::GetFrameLatencyWaitableObject() { + if (!(m_desc.Flags & DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT)) + return nullptr; + + return m_presenter->GetFrameLatencyEvent(); + } + + + HRESULT STDMETHODCALLTYPE DxgiSwapChain::GetMatrixTransform( + DXGI_MATRIX_3X2_F* pMatrix) { + // We don't support composition swap chains + Logger::err("DxgiSwapChain::GetMatrixTransform: Not supported"); + return DXGI_ERROR_INVALID_CALL; + } + + + HRESULT STDMETHODCALLTYPE DxgiSwapChain::GetMaximumFrameLatency( + UINT* pMaxLatency) { + if (!(m_desc.Flags & DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT)) + return DXGI_ERROR_INVALID_CALL; + + std::lock_guard lock(m_lockWindow); + *pMaxLatency = m_presenter->GetFrameLatency(); + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE DxgiSwapChain::GetSourceSize( + UINT* pWidth, + UINT* pHeight) { + // TODO implement properly once supported + if (pWidth) *pWidth = m_desc.Width; + if (pHeight) *pHeight = m_desc.Height; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE DxgiSwapChain::SetMatrixTransform( + const DXGI_MATRIX_3X2_F* pMatrix) { + // We don't support composition swap chains + Logger::err("DxgiSwapChain::SetMatrixTransform: Not supported"); + return DXGI_ERROR_INVALID_CALL; + } + + + HRESULT STDMETHODCALLTYPE DxgiSwapChain::SetMaximumFrameLatency( + UINT MaxLatency) { + if (!(m_desc.Flags & DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT)) + return DXGI_ERROR_INVALID_CALL; + + std::lock_guard lock(m_lockWindow); + return m_presenter->SetFrameLatency(MaxLatency); + } + + + HRESULT STDMETHODCALLTYPE DxgiSwapChain::SetSourceSize( + UINT Width, + UINT Height) { + if (Width == 0 || Width > m_desc.Width + || Height == 0 || Height > m_desc.Height) + return E_INVALIDARG; + + RECT region; + region.left = 0; + region.top = 0; + region.right = Width; + region.bottom = Height; + return m_presenter->SetPresentRegion(®ion); + } + + + HRESULT STDMETHODCALLTYPE DxgiSwapChain::CheckColorSpaceSupport( + DXGI_COLOR_SPACE_TYPE ColorSpace, + UINT* pColorSpaceSupport) { + if (!pColorSpaceSupport) + return E_INVALIDARG; + + UINT supportFlags = 0; + + if (ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709) + supportFlags |= DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT; + + *pColorSpaceSupport = supportFlags; + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE DxgiSwapChain::SetColorSpace1(DXGI_COLOR_SPACE_TYPE ColorSpace) { + UINT support = 0; + + HRESULT hr = CheckColorSpaceSupport(ColorSpace, &support); + + if (FAILED(hr)) + return hr; + + if (!support) + return E_INVALIDARG; + + return S_OK; + } + + + HRESULT STDMETHODCALLTYPE DxgiSwapChain::SetHDRMetaData( + DXGI_HDR_METADATA_TYPE Type, + UINT Size, + void* pMetaData) { + if (Size && !pMetaData) + return E_INVALIDARG; + + switch (Type) { + case DXGI_HDR_METADATA_TYPE_NONE: + return S_OK; + + case DXGI_HDR_METADATA_TYPE_HDR10: + if (Size != sizeof(DXGI_HDR_METADATA_HDR10)) + return E_INVALIDARG; + + // For some reason this always seems to succeed on Windows + Logger::warn("DXGI: HDR not supported"); + return S_OK; + + default: + Logger::err(str::format("DXGI: Invalid HDR metadata type: ", Type)); + return E_INVALIDARG; + } + } + + + HRESULT STDMETHODCALLTYPE DxgiSwapChain::SetGammaControl( + UINT NumPoints, + const DXGI_RGB* pGammaCurve) { + std::lock_guard lockBuf(m_lockBuffer); + return m_presenter->SetGammaControl(NumPoints, pGammaCurve); + } + + + HRESULT DxgiSwapChain::EnterFullscreenMode(IDXGIOutput* pTarget) { + Com output = pTarget; + + if (!IsWindow(m_window)) + return DXGI_ERROR_NOT_CURRENTLY_AVAILABLE; + + if (output == nullptr) { + if (FAILED(GetContainingOutput(&output))) { + Logger::err("DXGI: EnterFullscreenMode: Cannot query containing output"); + return E_FAIL; + } + } + + // Find a display mode that matches what we need + ::GetWindowRect(m_window, &m_windowState.rect); + + if (m_desc.Flags & DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH) { + DXGI_MODE_DESC displayMode; + displayMode.Width = m_desc.Width; + displayMode.Height = m_desc.Height; + displayMode.RefreshRate = m_descFs.RefreshRate; + displayMode.Format = m_desc.Format; + // Ignore these two, games usually use them wrong and we don't + // support any scaling modes except UNSPECIFIED anyway. + displayMode.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; + displayMode.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + + if (FAILED(ChangeDisplayMode(output.ptr(), &displayMode))) { + Logger::err("DXGI: EnterFullscreenMode: Failed to change display mode"); + return DXGI_ERROR_NOT_CURRENTLY_AVAILABLE; + } + } + + // Update swap chain description + m_descFs.Windowed = FALSE; + + // Change the window flags to remove the decoration etc. + LONG style = ::GetWindowLongW(m_window, GWL_STYLE); + LONG exstyle = ::GetWindowLongW(m_window, GWL_EXSTYLE); + + m_windowState.style = style; + m_windowState.exstyle = exstyle; + + style &= ~WS_OVERLAPPEDWINDOW; + exstyle &= ~WS_EX_OVERLAPPEDWINDOW; + + ::SetWindowLongW(m_window, GWL_STYLE, style); + ::SetWindowLongW(m_window, GWL_EXSTYLE, exstyle); + + // Move the window so that it covers the entire output + DXGI_OUTPUT_DESC desc; + output->GetDesc(&desc); + + const RECT rect = desc.DesktopCoordinates; + + ::SetWindowPos(m_window, HWND_TOPMOST, + rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, + SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOACTIVATE); + + m_monitor = desc.Monitor; + m_target = std::move(output); + + // Apply current gamma curve of the output + DXGI_VK_MONITOR_DATA* monitorInfo = nullptr; + + if (SUCCEEDED(AcquireMonitorData(m_monitor, &monitorInfo))) { + if (!monitorInfo->pSwapChain) + monitorInfo->pSwapChain = this; + + SetGammaControl(DXGI_VK_GAMMA_CP_COUNT, monitorInfo->GammaCurve.GammaCurve); + ReleaseMonitorData(); + } + + NotifyModeChange(m_monitor, FALSE); + return S_OK; + } + + + HRESULT DxgiSwapChain::LeaveFullscreenMode() { + if (FAILED(RestoreDisplayMode(m_monitor))) + Logger::warn("DXGI: LeaveFullscreenMode: Failed to restore display mode"); + + // Reset gamma control and decouple swap chain from monitor + DXGI_VK_MONITOR_DATA* monitorInfo = nullptr; + + if (SUCCEEDED(AcquireMonitorData(m_monitor, &monitorInfo))) { + if (monitorInfo->pSwapChain == this) + monitorInfo->pSwapChain = nullptr; + + SetGammaControl(0, nullptr); + ReleaseMonitorData(); + } + + // Restore internal state + HMONITOR monitor = m_monitor; + + m_descFs.Windowed = TRUE; + m_monitor = nullptr; + m_target = nullptr; + + if (!IsWindow(m_window)) + return S_OK; + + // Only restore the window style if the application hasn't + // changed them. This is in line with what native DXGI does. + LONG curStyle = ::GetWindowLongW(m_window, GWL_STYLE) & ~WS_VISIBLE; + LONG curExstyle = ::GetWindowLongW(m_window, GWL_EXSTYLE) & ~WS_EX_TOPMOST; + + if (curStyle == (m_windowState.style & ~(WS_VISIBLE | WS_OVERLAPPEDWINDOW)) + && curExstyle == (m_windowState.exstyle & ~(WS_EX_TOPMOST | WS_EX_OVERLAPPEDWINDOW))) { + ::SetWindowLongW(m_window, GWL_STYLE, m_windowState.style); + ::SetWindowLongW(m_window, GWL_EXSTYLE, m_windowState.exstyle); + } + + // Restore window position and apply the style + const RECT rect = m_windowState.rect; + + ::SetWindowPos(m_window, (m_windowState.exstyle & WS_EX_TOPMOST) ? HWND_TOPMOST : HWND_NOTOPMOST, + rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, + SWP_FRAMECHANGED | SWP_NOACTIVATE); + + NotifyModeChange(monitor, TRUE); + return S_OK; + } + + + HRESULT DxgiSwapChain::ChangeDisplayMode( + IDXGIOutput* pOutput, + const DXGI_MODE_DESC* pDisplayMode) { + if (!pOutput) + return DXGI_ERROR_INVALID_CALL; + + // Find a mode that the output supports + DXGI_OUTPUT_DESC outputDesc; + pOutput->GetDesc(&outputDesc); + + DXGI_MODE_DESC preferredMode = *pDisplayMode; + DXGI_MODE_DESC selectedMode; + + if (preferredMode.Format == DXGI_FORMAT_UNKNOWN) + preferredMode.Format = m_desc.Format; + + HRESULT hr = pOutput->FindClosestMatchingMode( + &preferredMode, &selectedMode, nullptr); + + if (FAILED(hr)) { + Logger::err(str::format( + "DXGI: Failed to query closest mode:", + "\n Format: ", preferredMode.Format, + "\n Mode: ", preferredMode.Width, "x", preferredMode.Height, + "@", preferredMode.RefreshRate.Numerator / preferredMode.RefreshRate.Denominator)); + return hr; + } + + DEVMODEW devMode = { }; + devMode.dmSize = sizeof(devMode); + devMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL; + devMode.dmPelsWidth = selectedMode.Width; + devMode.dmPelsHeight = selectedMode.Height; + devMode.dmBitsPerPel = GetMonitorFormatBpp(selectedMode.Format); + + if (selectedMode.RefreshRate.Numerator != 0) { + devMode.dmFields |= DM_DISPLAYFREQUENCY; + devMode.dmDisplayFrequency = selectedMode.RefreshRate.Numerator + / selectedMode.RefreshRate.Denominator; + } + + return SetMonitorDisplayMode(outputDesc.Monitor, &devMode) + ? S_OK + : DXGI_ERROR_NOT_CURRENTLY_AVAILABLE; + } + + + HRESULT DxgiSwapChain::RestoreDisplayMode(HMONITOR hMonitor) { + if (!hMonitor) + return DXGI_ERROR_INVALID_CALL; + + return RestoreMonitorDisplayMode() + ? S_OK + : DXGI_ERROR_NOT_CURRENTLY_AVAILABLE; + } + + + HRESULT DxgiSwapChain::GetSampleCount(UINT Count, VkSampleCountFlagBits* pCount) const { + switch (Count) { + case 1: *pCount = VK_SAMPLE_COUNT_1_BIT; return S_OK; + case 2: *pCount = VK_SAMPLE_COUNT_2_BIT; return S_OK; + case 4: *pCount = VK_SAMPLE_COUNT_4_BIT; return S_OK; + case 8: *pCount = VK_SAMPLE_COUNT_8_BIT; return S_OK; + case 16: *pCount = VK_SAMPLE_COUNT_16_BIT; return S_OK; + } + + return E_INVALIDARG; + } + + + HRESULT DxgiSwapChain::GetOutputFromMonitor( + HMONITOR Monitor, + IDXGIOutput** ppOutput) { + if (!ppOutput) + return DXGI_ERROR_INVALID_CALL; + + for (uint32_t i = 0; SUCCEEDED(m_adapter->EnumOutputs(i, ppOutput)); i++) { + DXGI_OUTPUT_DESC outputDesc; + (*ppOutput)->GetDesc(&outputDesc); + + if (outputDesc.Monitor == Monitor) + return S_OK; + + (*ppOutput)->Release(); + (*ppOutput) = nullptr; + } + + return DXGI_ERROR_NOT_FOUND; + } + + + HRESULT DxgiSwapChain::AcquireMonitorData( + HMONITOR hMonitor, + DXGI_VK_MONITOR_DATA** ppData) { + return m_monitorInfo != nullptr + ? m_monitorInfo->AcquireMonitorData(hMonitor, ppData) + : E_NOINTERFACE; + } + + + void DxgiSwapChain::ReleaseMonitorData() { + if (m_monitorInfo != nullptr) + m_monitorInfo->ReleaseMonitorData(); + } + + + void DxgiSwapChain::NotifyModeChange( + HMONITOR hMonitor, + BOOL Windowed) { + DEVMODEW devMode = { }; + devMode.dmSize = sizeof(devMode); + devMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY; + + if (GetMonitorDisplayMode(hMonitor, ENUM_CURRENT_SETTINGS, &devMode)) { + DXGI_MODE_DESC displayMode = { }; + displayMode.Width = devMode.dmPelsWidth; + displayMode.Height = devMode.dmPelsHeight; + displayMode.RefreshRate = { devMode.dmDisplayFrequency, 1 }; + displayMode.Format = m_desc.Format; + displayMode.ScanlineOrdering = m_descFs.ScanlineOrdering; + displayMode.Scaling = m_descFs.Scaling; + m_presenter->NotifyModeChange(Windowed, &displayMode); + } else { + Logger::warn("Failed to query current display mode"); + m_presenter->NotifyModeChange(Windowed, nullptr); + } + } + +} diff --git a/utils/dxvk-1.10.3/src/dxgi/dxgi_swapchain.h b/utils/dxvk-1.10.3/src/dxgi/dxgi_swapchain.h new file mode 100644 index 00000000000..62adf0e8afe --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxgi/dxgi_swapchain.h @@ -0,0 +1,228 @@ +#pragma once + +#include +#include + +#include "dxgi_interfaces.h" +#include "dxgi_monitor.h" +#include "dxgi_object.h" + +#include "../d3d11/d3d11_interfaces.h" + +#include "../spirv/spirv_module.h" + +#include "../util/util_time.h" + +namespace dxvk { + + class DxgiDevice; + class DxgiFactory; + class DxgiOutput; + + class DxgiSwapChain : public DxgiObject { + + public: + + DxgiSwapChain( + IDXGIFactory* pFactory, + IDXGIVkSwapChain* pPresenter, + HWND hWnd, + const DXGI_SWAP_CHAIN_DESC1* pDesc, + const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc); + + ~DxgiSwapChain(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject) final; + + HRESULT STDMETHODCALLTYPE GetParent( + REFIID riid, + void** ppParent) final; + + HRESULT STDMETHODCALLTYPE GetDevice( + REFIID riid, + void** ppDevice) final; + + HRESULT STDMETHODCALLTYPE GetBuffer( + UINT Buffer, + REFIID riid, + void** ppSurface) final; + + UINT STDMETHODCALLTYPE GetCurrentBackBufferIndex() final; + + HRESULT STDMETHODCALLTYPE GetContainingOutput( + IDXGIOutput** ppOutput) final; + + HRESULT STDMETHODCALLTYPE GetDesc( + DXGI_SWAP_CHAIN_DESC* pDesc) final; + + HRESULT STDMETHODCALLTYPE GetDesc1( + DXGI_SWAP_CHAIN_DESC1* pDesc) final; + + HRESULT STDMETHODCALLTYPE GetFullscreenState( + BOOL* pFullscreen, + IDXGIOutput** ppTarget) final; + + HRESULT STDMETHODCALLTYPE GetFullscreenDesc( + DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pDesc) final; + + HRESULT STDMETHODCALLTYPE GetHwnd( + HWND* pHwnd) final; + + HRESULT STDMETHODCALLTYPE GetCoreWindow( + REFIID refiid, + void** ppUnk) final; + + HRESULT STDMETHODCALLTYPE GetBackgroundColor( + DXGI_RGBA* pColor) final; + + HRESULT STDMETHODCALLTYPE GetRotation( + DXGI_MODE_ROTATION* pRotation) final; + + HRESULT STDMETHODCALLTYPE GetRestrictToOutput( + IDXGIOutput** ppRestrictToOutput) final; + + HRESULT STDMETHODCALLTYPE GetFrameStatistics( + DXGI_FRAME_STATISTICS* pStats) final; + + HRESULT STDMETHODCALLTYPE GetLastPresentCount( + UINT* pLastPresentCount) final; + + BOOL STDMETHODCALLTYPE IsTemporaryMonoSupported() final; + + HRESULT STDMETHODCALLTYPE Present( + UINT SyncInterval, + UINT Flags) final; + + HRESULT STDMETHODCALLTYPE Present1( + UINT SyncInterval, + UINT PresentFlags, + const DXGI_PRESENT_PARAMETERS* pPresentParameters) final; + + HRESULT STDMETHODCALLTYPE ResizeBuffers( + UINT BufferCount, + UINT Width, + UINT Height, + DXGI_FORMAT NewFormat, + UINT SwapChainFlags) final; + + HRESULT STDMETHODCALLTYPE ResizeBuffers1( + UINT BufferCount, + UINT Width, + UINT Height, + DXGI_FORMAT Format, + UINT SwapChainFlags, + const UINT* pCreationNodeMask, + IUnknown* const* ppPresentQueue) final; + + HRESULT STDMETHODCALLTYPE ResizeTarget( + const DXGI_MODE_DESC* pNewTargetParameters) final; + + HRESULT STDMETHODCALLTYPE SetFullscreenState( + BOOL Fullscreen, + IDXGIOutput* pTarget) final; + + HRESULT STDMETHODCALLTYPE SetBackgroundColor( + const DXGI_RGBA* pColor) final; + + HRESULT STDMETHODCALLTYPE SetRotation( + DXGI_MODE_ROTATION Rotation) final; + + HANDLE STDMETHODCALLTYPE GetFrameLatencyWaitableObject() final; + + HRESULT STDMETHODCALLTYPE GetMatrixTransform( + DXGI_MATRIX_3X2_F* pMatrix) final; + + HRESULT STDMETHODCALLTYPE GetMaximumFrameLatency( + UINT* pMaxLatency) final; + + HRESULT STDMETHODCALLTYPE GetSourceSize( + UINT* pWidth, + UINT* pHeight) final; + + HRESULT STDMETHODCALLTYPE SetMatrixTransform( + const DXGI_MATRIX_3X2_F* pMatrix) final; + + HRESULT STDMETHODCALLTYPE SetMaximumFrameLatency( + UINT MaxLatency) final; + + HRESULT STDMETHODCALLTYPE SetSourceSize( + UINT Width, + UINT Height) final; + + HRESULT STDMETHODCALLTYPE CheckColorSpaceSupport( + DXGI_COLOR_SPACE_TYPE ColorSpace, + UINT* pColorSpaceSupport) final; + + HRESULT STDMETHODCALLTYPE SetColorSpace1( + DXGI_COLOR_SPACE_TYPE ColorSpace) final; + + HRESULT STDMETHODCALLTYPE SetHDRMetaData( + DXGI_HDR_METADATA_TYPE Type, + UINT Size, + void* pMetaData) final; + + HRESULT STDMETHODCALLTYPE SetGammaControl( + UINT NumPoints, + const DXGI_RGB* pGammaCurve); + + private: + + struct WindowState { + LONG style = 0; + LONG exstyle = 0; + RECT rect = { 0, 0, 0, 0 }; + }; + + dxvk::recursive_mutex m_lockWindow; + dxvk::mutex m_lockBuffer; + + Com m_factory; + Com m_adapter; + Com m_target; + Com m_monitorInfo; + + HWND m_window; + DXGI_SWAP_CHAIN_DESC1 m_desc; + DXGI_SWAP_CHAIN_FULLSCREEN_DESC m_descFs; + UINT m_presentCount; + + Com m_presenter; + + HMONITOR m_monitor; + WindowState m_windowState; + + HRESULT EnterFullscreenMode( + IDXGIOutput *pTarget); + + HRESULT LeaveFullscreenMode(); + + HRESULT ChangeDisplayMode( + IDXGIOutput* pOutput, + const DXGI_MODE_DESC* pDisplayMode); + + HRESULT RestoreDisplayMode( + HMONITOR hMonitor); + + HRESULT GetSampleCount( + UINT Count, + VkSampleCountFlagBits* pCount) const; + + HRESULT GetOutputFromMonitor( + HMONITOR Monitor, + IDXGIOutput** ppOutput); + + HRESULT AcquireMonitorData( + HMONITOR hMonitor, + DXGI_VK_MONITOR_DATA** ppData); + + void ReleaseMonitorData(); + + void NotifyModeChange( + HMONITOR hMonitor, + BOOL Windowed); + + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxgi/dxgi_swapchain_dispatcher.h b/utils/dxvk-1.10.3/src/dxgi/dxgi_swapchain_dispatcher.h new file mode 100644 index 00000000000..4ef50d0461f --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxgi/dxgi_swapchain_dispatcher.h @@ -0,0 +1,301 @@ +#pragma once + +#include "dxgi_swapchain.h" + +namespace dxvk { + + class DxgiSwapChainDispatcher : public IDXGISwapChain4 { + + public: + + DxgiSwapChainDispatcher(IDXGISwapChain4* dispatch) + : m_dispatch(dispatch) { + } + + virtual ~DxgiSwapChainDispatcher() { + } + + ULONG STDMETHODCALLTYPE AddRef() { + if (likely(m_dispatch != nullptr)) + return m_dispatch->AddRef(); + + return 0; + } + + ULONG STDMETHODCALLTYPE Release() { + if (likely(m_dispatch != nullptr)) { + ULONG refCount = m_dispatch->Release(); + + if (unlikely(!refCount)) { + // Clear the underlying swap chain pointer. Helps in + // use-after-free situations encountered in Divinity + // Original Sin Enhanced Edition. + m_dispatch = nullptr; + delete this; + } + + return refCount; + } + + return ~0u; + } + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject) final { + if (ppvObject == nullptr) + return E_POINTER; + + *ppvObject = nullptr; + + if (riid == __uuidof(IUnknown) + || riid == __uuidof(IDXGIObject) + || riid == __uuidof(IDXGIDeviceSubObject) + || riid == __uuidof(IDXGISwapChain) + || riid == __uuidof(IDXGISwapChain1) + || riid == __uuidof(IDXGISwapChain2) + || riid == __uuidof(IDXGISwapChain3) + || riid == __uuidof(IDXGISwapChain4)) { + *ppvObject = ref(this); + return S_OK; + } + + Logger::warn("DxgiSwapChainDispatcher::QueryInterface: Unknown interface query"); + Logger::warn(str::format(riid)); + return m_dispatch->QueryInterface(riid, ppvObject); + } + + HRESULT STDMETHODCALLTYPE GetPrivateData( + REFGUID Name, + UINT* pDataSize, + void* pData) final { + return m_dispatch->GetPrivateData(Name, pDataSize, pData); + } + + HRESULT STDMETHODCALLTYPE SetPrivateData( + REFGUID Name, + UINT DataSize, + const void* pData) final { + return m_dispatch->SetPrivateData(Name, DataSize, pData); + } + + HRESULT STDMETHODCALLTYPE SetPrivateDataInterface( + REFGUID Name, + const IUnknown* pUnknown) final { + return m_dispatch->SetPrivateDataInterface(Name, pUnknown); + } + + HRESULT STDMETHODCALLTYPE GetParent( + REFIID riid, + void** ppParent) final { + return m_dispatch->GetParent(riid, ppParent); + } + + HRESULT STDMETHODCALLTYPE GetDevice( + REFIID riid, + void** ppDevice) final { + return m_dispatch->GetDevice(riid, ppDevice); + } + + HRESULT STDMETHODCALLTYPE GetBuffer( + UINT Buffer, + REFIID riid, + void** ppSurface) final { + return m_dispatch->GetBuffer(Buffer, riid, ppSurface); + } + + UINT STDMETHODCALLTYPE GetCurrentBackBufferIndex() final { + return m_dispatch->GetCurrentBackBufferIndex(); + } + + HRESULT STDMETHODCALLTYPE GetContainingOutput( + IDXGIOutput** ppOutput) final { + return m_dispatch->GetContainingOutput(ppOutput); + } + + HRESULT STDMETHODCALLTYPE GetDesc( + DXGI_SWAP_CHAIN_DESC* pDesc) final { + return m_dispatch->GetDesc(pDesc); + } + + HRESULT STDMETHODCALLTYPE GetDesc1( + DXGI_SWAP_CHAIN_DESC1* pDesc) final { + return m_dispatch->GetDesc1(pDesc); + } + + HRESULT STDMETHODCALLTYPE GetFullscreenState( + BOOL* pFullscreen, + IDXGIOutput** ppTarget) final { + if (likely(m_dispatch != nullptr)) + return m_dispatch->GetFullscreenState(pFullscreen, ppTarget); + + if (pFullscreen) + *pFullscreen = FALSE; + + if (ppTarget) + *ppTarget = nullptr; + + return S_OK; + } + + HRESULT STDMETHODCALLTYPE GetFullscreenDesc( + DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pDesc) final { + return m_dispatch->GetFullscreenDesc(pDesc); + } + + HRESULT STDMETHODCALLTYPE GetHwnd( + HWND* pHwnd) final { + return m_dispatch->GetHwnd(pHwnd); + } + + HRESULT STDMETHODCALLTYPE GetCoreWindow( + REFIID refiid, + void** ppUnk) final { + return m_dispatch->GetCoreWindow(refiid, ppUnk); + } + + HRESULT STDMETHODCALLTYPE GetBackgroundColor( + DXGI_RGBA* pColor) final { + return m_dispatch->GetBackgroundColor(pColor); + } + + HRESULT STDMETHODCALLTYPE GetRotation( + DXGI_MODE_ROTATION* pRotation) final { + return m_dispatch->GetRotation(pRotation); + } + + HRESULT STDMETHODCALLTYPE GetRestrictToOutput( + IDXGIOutput** ppRestrictToOutput) final { + return m_dispatch->GetRestrictToOutput(ppRestrictToOutput); + } + + HRESULT STDMETHODCALLTYPE GetFrameStatistics( + DXGI_FRAME_STATISTICS* pStats) final { + return m_dispatch->GetFrameStatistics(pStats); + } + + HRESULT STDMETHODCALLTYPE GetLastPresentCount( + UINT* pLastPresentCount) final { + return m_dispatch->GetLastPresentCount(pLastPresentCount); + } + + BOOL STDMETHODCALLTYPE IsTemporaryMonoSupported() final { + return m_dispatch->IsTemporaryMonoSupported(); + } + + HRESULT STDMETHODCALLTYPE Present( + UINT SyncInterval, + UINT Flags) final { + return m_dispatch->Present(SyncInterval, Flags); + } + + HRESULT STDMETHODCALLTYPE Present1( + UINT SyncInterval, + UINT PresentFlags, + const DXGI_PRESENT_PARAMETERS* pPresentParameters) final { + return m_dispatch->Present1(SyncInterval, PresentFlags, pPresentParameters); + } + + HRESULT STDMETHODCALLTYPE ResizeBuffers( + UINT BufferCount, + UINT Width, + UINT Height, + DXGI_FORMAT NewFormat, + UINT SwapChainFlags) final { + return m_dispatch->ResizeBuffers(BufferCount, Width, Height, NewFormat, SwapChainFlags); + } + + HRESULT STDMETHODCALLTYPE ResizeBuffers1( + UINT BufferCount, + UINT Width, + UINT Height, + DXGI_FORMAT Format, + UINT SwapChainFlags, + const UINT* pCreationNodeMask, + IUnknown* const* ppPresentQueue) final { + return m_dispatch->ResizeBuffers1(BufferCount, Width, Height, Format, SwapChainFlags, pCreationNodeMask, ppPresentQueue); + } + + HRESULT STDMETHODCALLTYPE ResizeTarget( + const DXGI_MODE_DESC* pNewTargetParameters) final { + return m_dispatch->ResizeTarget(pNewTargetParameters); + } + + HRESULT STDMETHODCALLTYPE SetFullscreenState( + BOOL Fullscreen, + IDXGIOutput* pTarget) final { + return m_dispatch->SetFullscreenState(Fullscreen, pTarget); + } + + + HRESULT STDMETHODCALLTYPE SetBackgroundColor( + const DXGI_RGBA* pColor) final { + return m_dispatch->SetBackgroundColor(pColor); + } + + HRESULT STDMETHODCALLTYPE SetRotation( + DXGI_MODE_ROTATION Rotation) final { + return m_dispatch->SetRotation(Rotation); + } + + HANDLE STDMETHODCALLTYPE GetFrameLatencyWaitableObject() final { + return m_dispatch->GetFrameLatencyWaitableObject(); + } + + HRESULT STDMETHODCALLTYPE GetMatrixTransform( + DXGI_MATRIX_3X2_F* pMatrix) final { + return m_dispatch->GetMatrixTransform(pMatrix); + } + + HRESULT STDMETHODCALLTYPE GetMaximumFrameLatency( + UINT* pMaxLatency) final { + return m_dispatch->GetMaximumFrameLatency(pMaxLatency); + } + + HRESULT STDMETHODCALLTYPE GetSourceSize( + UINT* pWidth, + UINT* pHeight) final { + return m_dispatch->GetSourceSize(pWidth, pHeight); + } + + HRESULT STDMETHODCALLTYPE SetMatrixTransform( + const DXGI_MATRIX_3X2_F* pMatrix) final { + return m_dispatch->SetMatrixTransform(pMatrix); + } + + HRESULT STDMETHODCALLTYPE SetMaximumFrameLatency( + UINT MaxLatency) final { + return m_dispatch->SetMaximumFrameLatency(MaxLatency); + } + + HRESULT STDMETHODCALLTYPE SetSourceSize( + UINT Width, + UINT Height) final { + return m_dispatch->SetSourceSize(Width, Height); + } + + HRESULT STDMETHODCALLTYPE CheckColorSpaceSupport( + DXGI_COLOR_SPACE_TYPE ColorSpace, + UINT* pColorSpaceSupport) final { + return m_dispatch->CheckColorSpaceSupport(ColorSpace, pColorSpaceSupport); + } + + HRESULT STDMETHODCALLTYPE SetColorSpace1( + DXGI_COLOR_SPACE_TYPE ColorSpace) final { + return m_dispatch->SetColorSpace1(ColorSpace); + } + + HRESULT STDMETHODCALLTYPE SetHDRMetaData( + DXGI_HDR_METADATA_TYPE Type, + UINT Size, + void* pMetaData) final { + return m_dispatch->SetHDRMetaData(Type, Size, pMetaData); + } + + private: + + IDXGISwapChain4* m_dispatch; + + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxgi/meson.build b/utils/dxvk-1.10.3/src/dxgi/meson.build new file mode 100644 index 00000000000..daa790f47d2 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxgi/meson.build @@ -0,0 +1,26 @@ +dxgi_res = wrc_generator.process('version.rc') + +dxgi_src = [ + 'dxgi_adapter.cpp', + 'dxgi_enums.cpp', + 'dxgi_factory.cpp', + 'dxgi_format.cpp', + 'dxgi_main.cpp', + 'dxgi_monitor.cpp', + 'dxgi_options.cpp', + 'dxgi_output.cpp', + 'dxgi_swapchain.cpp', +] + +dxgi_dll = shared_library('dxgi'+dll_ext, dxgi_src, dxgi_res, + name_prefix : '', + dependencies : [ dxvk_dep ], + include_directories : dxvk_include_path, + install : true, + vs_module_defs : 'dxgi'+def_spec_ext, +) + +dxgi_dep = declare_dependency( + link_with : [ dxgi_dll ], + include_directories : [ dxvk_include_path ], +) diff --git a/utils/dxvk-1.10.3/src/dxgi/version.rc b/utils/dxvk-1.10.3/src/dxgi/version.rc new file mode 100644 index 00000000000..9461d71839e --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxgi/version.rc @@ -0,0 +1,32 @@ +#include + +// DLL version information. +VS_VERSION_INFO VERSIONINFO +FILEVERSION 10,0,17763,1 +PRODUCTVERSION 10,0,17763,1 +FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +FILEFLAGS 0 +FILEOS VOS_NT_WINDOWS32 +FILETYPE VFT_DLL +FILESUBTYPE VFT2_UNKNOWN +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "080904b0" + BEGIN + VALUE "CompanyName", "DXVK" + VALUE "FileDescription", "DirectX Graphics Infrastructure" + VALUE "FileVersion", "10.0.17763.1 (WinBuild.160101.0800)" + VALUE "InternalName", "dxgi.dll" + VALUE "LegalCopyright", "zlib/libpng license" + VALUE "OriginalFilename", "dxgi.dll" + VALUE "ProductName", "DXVK" + VALUE "ProductVersion", "10.0.17763.1" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0809, 1200 + END +END + diff --git a/utils/dxvk-1.10.3/src/dxso/dxso_analysis.cpp b/utils/dxvk-1.10.3/src/dxso/dxso_analysis.cpp new file mode 100644 index 00000000000..553f84c4474 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxso/dxso_analysis.cpp @@ -0,0 +1,57 @@ +#include "dxso_analysis.h" + +namespace dxvk { + + DxsoAnalyzer::DxsoAnalyzer( + DxsoAnalysisInfo& analysis) + : m_analysis(&analysis) { } + + void DxsoAnalyzer::processInstruction( + const DxsoInstructionContext& ctx) { + DxsoOpcode opcode = ctx.instruction.opcode; + + // Co-issued CNDs are issued before their parents, + // except when the parent is a CND. + if (opcode == DxsoOpcode::Cnd && + m_parentOpcode != DxsoOpcode::Cnd && + ctx.instruction.coissue) { + m_analysis->coissues.push_back(ctx); + } + + if (opcode == DxsoOpcode::TexKill) + m_analysis->usesKill = true; + + if (opcode == DxsoOpcode::DsX + || opcode == DxsoOpcode::DsY + + || opcode == DxsoOpcode::Tex + || opcode == DxsoOpcode::TexCoord + || opcode == DxsoOpcode::TexBem + || opcode == DxsoOpcode::TexBemL + || opcode == DxsoOpcode::TexReg2Ar + || opcode == DxsoOpcode::TexReg2Gb + || opcode == DxsoOpcode::TexM3x2Pad + || opcode == DxsoOpcode::TexM3x2Tex + || opcode == DxsoOpcode::TexM3x3Pad + || opcode == DxsoOpcode::TexM3x3Tex + || opcode == DxsoOpcode::TexM3x3Spec + || opcode == DxsoOpcode::TexM3x3VSpec + || opcode == DxsoOpcode::TexReg2Rgb + || opcode == DxsoOpcode::TexDp3Tex + || opcode == DxsoOpcode::TexM3x2Depth + || opcode == DxsoOpcode::TexDp3 + || opcode == DxsoOpcode::TexM3x3 + // Explicit LOD. + //|| opcode == DxsoOpcode::TexLdd + //|| opcode == DxsoOpcode::TexLdl + || opcode == DxsoOpcode::TexDepth) + m_analysis->usesDerivatives = true; + + m_parentOpcode = ctx.instruction.opcode; + } + + void DxsoAnalyzer::finalize(size_t tokenCount) { + m_analysis->bytecodeByteLength = tokenCount * sizeof(uint32_t); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxso/dxso_analysis.h b/utils/dxvk-1.10.3/src/dxso/dxso_analysis.h new file mode 100644 index 00000000000..c1321e09a1a --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxso/dxso_analysis.h @@ -0,0 +1,41 @@ +#pragma once + +#include "dxso_modinfo.h" +#include "dxso_decoder.h" + +namespace dxvk { + + struct DxsoAnalysisInfo { + uint32_t bytecodeByteLength; + + bool usesDerivatives = false; + bool usesKill = false; + + std::vector coissues; + }; + + class DxsoAnalyzer { + + public: + + DxsoAnalyzer( + DxsoAnalysisInfo& analysis); + + /** + * \brief Processes a single instruction + * \param [in] ins The instruction + */ + void processInstruction( + const DxsoInstructionContext& ctx); + + void finalize(size_t tokenCount); + + private: + + DxsoAnalysisInfo* m_analysis = nullptr; + + DxsoOpcode m_parentOpcode; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxso/dxso_code.cpp b/utils/dxvk-1.10.3/src/dxso/dxso_code.cpp new file mode 100644 index 00000000000..9fd73d933c1 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxso/dxso_code.cpp @@ -0,0 +1,28 @@ +#include "dxso_code.h" + +namespace dxvk { + + DxsoCode::DxsoCode(DxsoReader& reader) { + m_code = + reinterpret_cast(reader.currentPtr()); + } + + const uint32_t* DxsoCodeIter::ptrAt(uint32_t id) const { + return m_ptr + id; + } + + + uint32_t DxsoCodeIter::at(uint32_t id) const { + return m_ptr[id]; + } + + + uint32_t DxsoCodeIter::read() { + return *(m_ptr++); + } + + DxsoCodeIter DxsoCodeIter::skip(uint32_t n) const { + return DxsoCodeIter(m_ptr + n); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxso/dxso_code.h b/utils/dxvk-1.10.3/src/dxso/dxso_code.h new file mode 100644 index 00000000000..51fdab78e0b --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxso/dxso_code.h @@ -0,0 +1,54 @@ +#pragma once + +#include "dxso_include.h" +#include "dxso_reader.h" + +#include +#include + +namespace dxvk { + + /** + * \brief DXBC code iterator + * + * Convenient pointer wrapper that allows + * reading the code token stream. + */ + class DxsoCodeIter { + + public: + + DxsoCodeIter( + const uint32_t* ptr) + : m_ptr(ptr) { } + + const uint32_t* ptrAt(uint32_t id) const; + + uint32_t at(uint32_t id) const; + uint32_t read(); + + DxsoCodeIter skip(uint32_t n) const; + + private: + + const uint32_t* m_ptr = nullptr; + + }; + + class DxsoCode { + + public: + + DxsoCode(DxsoReader& reader); + + DxsoCodeIter iter() const { + return DxsoCodeIter(m_code); + } + + private: + + const uint32_t* m_code; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxso/dxso_common.cpp b/utils/dxvk-1.10.3/src/dxso/dxso_common.cpp new file mode 100644 index 00000000000..0709fa2204b --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxso/dxso_common.cpp @@ -0,0 +1,26 @@ +#include "dxso_common.h" + +namespace dxvk { + + VkShaderStageFlagBits DxsoProgramInfo::shaderStage() const { + switch (m_type) { + case DxsoProgramTypes::PixelShader: return VK_SHADER_STAGE_FRAGMENT_BIT; + case DxsoProgramTypes::VertexShader: return VK_SHADER_STAGE_VERTEX_BIT; + default: break; + } + + throw DxvkError("DxsoProgramInfo::shaderStage: Unsupported program type"); + } + + + spv::ExecutionModel DxsoProgramInfo::executionModel() const { + switch (m_type) { + case DxsoProgramTypes::PixelShader: return spv::ExecutionModelFragment; + case DxsoProgramTypes::VertexShader: return spv::ExecutionModelVertex; + default: break; + } + + throw DxvkError("DxsoProgramInfo::executionModel: Unsupported program type"); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxso/dxso_common.h b/utils/dxvk-1.10.3/src/dxso/dxso_common.h new file mode 100644 index 00000000000..fcc57cd858e --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxso/dxso_common.h @@ -0,0 +1,88 @@ +#pragma once + +#include "dxso_include.h" + +#include + +namespace dxvk { + + /** + * \brief DXSO Program type + * + * Defines the shader stage that a DXSO + * module has been compiled for. + */ + namespace DxsoProgramTypes { + enum DxsoProgramType : uint16_t { + VertexShader = 0, + PixelShader = 1, + Count = 2, + }; + } + using DxsoProgramType = DxsoProgramTypes::DxsoProgramType; + + class DxsoProgramInfo { + + public: + + DxsoProgramInfo() { } + DxsoProgramInfo( + DxsoProgramType type, + uint32_t minorVersion, + uint32_t majorVersion) + : m_type{ type } + , m_minorVersion{ minorVersion } + , m_majorVersion{ majorVersion } {} + + /** + * \brief Program type + * \returns Program type + */ + DxsoProgramType type() const { + return m_type; + } + + /** + * \brief Vulkan shader stage + * + * The \c VkShaderStageFlagBits constant + * that corresponds to the program type. + * \returns Vulkan shader stage + */ + VkShaderStageFlagBits shaderStage() const; + + /** + * \brief SPIR-V execution model + * + * The execution model that corresponds + * to the Vulkan shader stage. + * \returns SPIR-V execution model + */ + spv::ExecutionModel executionModel() const; + + /** + * \brief Minor version + * \returns The minor version of the shader model. + */ + uint32_t minorVersion() const { + return m_minorVersion; + } + + /** + * \brief Major version + * \returns The major version of the shader model. + */ + uint32_t majorVersion() const { + return m_majorVersion; + } + + private: + + DxsoProgramType m_type; + + uint32_t m_minorVersion; + uint32_t m_majorVersion; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxso/dxso_compiler.cpp b/utils/dxvk-1.10.3/src/dxso/dxso_compiler.cpp new file mode 100644 index 00000000000..b68608a007f --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxso/dxso_compiler.cpp @@ -0,0 +1,4048 @@ +#include "dxso_compiler.h" + +#include "dxso_analysis.h" + +#include "../d3d9/d3d9_caps.h" +#include "../d3d9/d3d9_constant_set.h" +#include "../d3d9/d3d9_state.h" +#include "../d3d9/d3d9_spec_constants.h" +#include "../d3d9/d3d9_fixed_function.h" +#include "dxso_util.h" + +#include "../dxvk/dxvk_spec_const.h" + +#include + +namespace dxvk { + + DxsoCompiler::DxsoCompiler( + const std::string& fileName, + const DxsoModuleInfo& moduleInfo, + const DxsoProgramInfo& programInfo, + const DxsoAnalysisInfo& analysis, + const D3D9ConstantLayout& layout) + : m_moduleInfo ( moduleInfo ) + , m_programInfo( programInfo ) + , m_analysis ( &analysis ) + , m_layout ( &layout ) + , m_module ( spvVersion(1, 3) ) { + // Declare an entry point ID. We'll need it during the + // initialization phase where the execution mode is set. + m_entryPointId = m_module.allocateId(); + + // Set the shader name so that we recognize it in renderdoc + m_module.setDebugSource( + spv::SourceLanguageUnknown, 0, + m_module.addDebugString(fileName.c_str()), + nullptr); + + // Set the memory model. This is the same for all shaders. + m_module.setMemoryModel( + spv::AddressingModelLogical, + spv::MemoryModelGLSL450); + + m_usedSamplers = 0; + m_usedRTs = 0; + + for (uint32_t i = 0; i < m_rRegs.size(); i++) + m_rRegs.at(i) = DxsoRegisterPointer{ }; + + for (uint32_t i = 0; i < m_cFloat.size(); i++) + m_cFloat.at(i) = 0; + + for (uint32_t i = 0; i < m_cInt.size(); i++) + m_cInt.at(i) = 0; + + for (uint32_t i = 0; i < m_cBool.size(); i++) + m_cBool.at(i) = 0; + + m_vs.addr = DxsoRegisterPointer{ }; + m_vs.oPos = DxsoRegisterPointer{ }; + m_fog = DxsoRegisterPointer{ }; + m_vs.oPSize = DxsoRegisterPointer{ }; + + for (uint32_t i = 0; i < m_ps.oColor.size(); i++) + m_ps.oColor.at(i) = DxsoRegisterPointer{ }; + m_ps.oDepth = DxsoRegisterPointer{ }; + m_ps.vFace = DxsoRegisterPointer{ }; + m_ps.vPos = DxsoRegisterPointer{ }; + + m_loopCounter = DxsoRegisterPointer{ }; + + this->emitInit(); + } + + + void DxsoCompiler::processInstruction( + const DxsoInstructionContext& ctx, + uint32_t currentCoissueIdx) { + const DxsoOpcode opcode = ctx.instruction.opcode; + + for (const auto& coissue : m_analysis->coissues) { + if (coissue.instructionIdx == ctx.instructionIdx && + coissue.instructionIdx != currentCoissueIdx) + return; + + if (coissue.instructionIdx == ctx.instructionIdx + 1) + processInstruction(coissue, coissue.instructionIdx); + } + + switch (opcode) { + case DxsoOpcode::Nop: + return; + + case DxsoOpcode::Dcl: + return this->emitDcl(ctx); + + case DxsoOpcode::Def: + case DxsoOpcode::DefI: + case DxsoOpcode::DefB: + return this->emitDef(ctx); + + case DxsoOpcode::Mov: + case DxsoOpcode::Mova: + return this->emitMov(ctx); + + case DxsoOpcode::Add: + case DxsoOpcode::Sub: + case DxsoOpcode::Mad: + case DxsoOpcode::Mul: + case DxsoOpcode::Rcp: + case DxsoOpcode::Rsq: + case DxsoOpcode::Dp3: + case DxsoOpcode::Dp4: + case DxsoOpcode::Slt: + case DxsoOpcode::Sge: + case DxsoOpcode::Min: + case DxsoOpcode::ExpP: + case DxsoOpcode::Exp: + case DxsoOpcode::Max: + case DxsoOpcode::Pow: + case DxsoOpcode::Crs: + case DxsoOpcode::Abs: + case DxsoOpcode::Sgn: + case DxsoOpcode::Nrm: + case DxsoOpcode::SinCos: + case DxsoOpcode::Lit: + case DxsoOpcode::Dst: + case DxsoOpcode::LogP: + case DxsoOpcode::Log: + case DxsoOpcode::Lrp: + case DxsoOpcode::Frc: + case DxsoOpcode::Cmp: + case DxsoOpcode::Cnd: + case DxsoOpcode::Dp2Add: + case DxsoOpcode::DsX: + case DxsoOpcode::DsY: + return this->emitVectorAlu(ctx); + + case DxsoOpcode::SetP: + return this->emitPredicateOp(ctx); + + case DxsoOpcode::M3x2: + case DxsoOpcode::M3x3: + case DxsoOpcode::M3x4: + case DxsoOpcode::M4x3: + case DxsoOpcode::M4x4: + return this->emitMatrixAlu(ctx); + + case DxsoOpcode::Loop: + return this->emitControlFlowLoop(ctx); + case DxsoOpcode::EndLoop: + return this->emitControlFlowEndLoop(ctx); + + case DxsoOpcode::Rep: + return this->emitControlFlowRep(ctx); + case DxsoOpcode::EndRep: + return this->emitControlFlowEndRep(ctx); + + case DxsoOpcode::Break: + return this->emitControlFlowBreak(ctx); + case DxsoOpcode::BreakC: + return this->emitControlFlowBreakC(ctx); + + case DxsoOpcode::If: + case DxsoOpcode::Ifc: + return this->emitControlFlowIf(ctx); + case DxsoOpcode::Else: + return this->emitControlFlowElse(ctx); + case DxsoOpcode::EndIf: + return this->emitControlFlowEndIf(ctx); + + case DxsoOpcode::TexCoord: + return this->emitTexCoord(ctx); + + case DxsoOpcode::Tex: + case DxsoOpcode::TexLdl: + case DxsoOpcode::TexLdd: + case DxsoOpcode::TexDp3Tex: + case DxsoOpcode::TexReg2Ar: + case DxsoOpcode::TexReg2Gb: + case DxsoOpcode::TexReg2Rgb: + case DxsoOpcode::TexBem: + case DxsoOpcode::TexBemL: + case DxsoOpcode::TexM3x2Tex: + case DxsoOpcode::TexM3x3Tex: + case DxsoOpcode::TexM3x3Spec: + case DxsoOpcode::TexM3x3VSpec: + return this->emitTextureSample(ctx); + case DxsoOpcode::TexKill: + return this->emitTextureKill(ctx); + case DxsoOpcode::TexDepth: + return this->emitTextureDepth(ctx); + + case DxsoOpcode::TexM3x3Pad: + case DxsoOpcode::TexM3x2Pad: + // We don't need to do anything here, these are just padding instructions + break; + + case DxsoOpcode::End: + case DxsoOpcode::Comment: + case DxsoOpcode::Phase: + break; + + default: + Logger::warn(str::format("DxsoCompiler::processInstruction: unhandled opcode: ", opcode)); + break; + } + } + + void DxsoCompiler::finalize() { + if (m_programInfo.type() == DxsoProgramTypes::VertexShader) + this->emitVsFinalize(); + else + this->emitPsFinalize(); + + // Declare the entry point, we now have all the + // information we need, including the interfaces + m_module.addEntryPoint(m_entryPointId, + m_programInfo.executionModel(), "main", + m_entryPointInterfaces.size(), + m_entryPointInterfaces.data()); + m_module.setDebugName(m_entryPointId, "main"); + } + + + DxsoPermutations DxsoCompiler::compile() { + DxsoPermutations permutations = { }; + + // Create the shader module object + permutations[D3D9ShaderPermutations::None] = compileShader(); + + // If we need to add more permuations, might be worth making a copy of module + // before we do anything more. :-) + if (m_programInfo.type() == DxsoProgramType::PixelShader) { + if (m_ps.diffuseColorIn) + m_module.decorate(m_ps.diffuseColorIn, spv::DecorationFlat); + + if (m_ps.specularColorIn) + m_module.decorate(m_ps.specularColorIn, spv::DecorationFlat); + + permutations[D3D9ShaderPermutations::FlatShade] = compileShader(); + } + + return permutations; + } + + + Rc DxsoCompiler::compileShader() { + DxvkShaderCreateInfo info; + info.stage = m_programInfo.shaderStage(); + info.resourceSlotCount = m_resourceSlots.size(); + info.resourceSlots = m_resourceSlots.data(); + info.inputMask = m_inputMask; + info.outputMask = m_outputMask; + info.pushConstOffset = m_pushConstOffset; + info.pushConstSize = m_pushConstOffset; + + return new DxvkShader(info, m_module.compile()); + } + + void DxsoCompiler::emitInit() { + // Set up common capabilities for all shaders + m_module.enableCapability(spv::CapabilityShader); + m_module.enableCapability(spv::CapabilityImageQuery); + + if (isSwvp()) { + m_cFloatBuffer = this->emitDclSwvpConstantBuffer(); + m_cIntBuffer = this->emitDclSwvpConstantBuffer(); + m_cBoolBuffer = this->emitDclSwvpConstantBuffer(); + } else { + this->emitDclConstantBuffer(); + } + + m_depthSpecConstant = m_module.specConst32(m_module.defIntType(32, 0), 0); + m_module.decorateSpecId(m_depthSpecConstant, getSpecId(D3D9SpecConstantId::SamplerDepthMode)); + m_module.setDebugName(m_depthSpecConstant, "depthSamplers"); + + this->emitDclInputArray(); + + // Initialize the shader module with capabilities + // etc. Each shader type has its own peculiarities. + switch (m_programInfo.type()) { + case DxsoProgramTypes::VertexShader: return this->emitVsInit(); + case DxsoProgramTypes::PixelShader: return this->emitPsInit(); + default: break; + } + } + + void DxsoCompiler::emitDclConstantBuffer() { + std::array members = { + // int i[16 or 2048] + m_module.defArrayTypeUnique( + getVectorTypeId({ DxsoScalarType::Sint32, 4 }), + m_module.constu32(m_layout->intCount)), + + // float f[256 or 224 or 8192] + m_module.defArrayTypeUnique( + getVectorTypeId({ DxsoScalarType::Float32, 4 }), + m_module.constu32(m_layout->floatCount)) + }; + + // Decorate array strides, this is required. + m_module.decorateArrayStride(members[0], 16); + m_module.decorateArrayStride(members[1], 16); + + const uint32_t structType = + m_module.defStructType(members.size(), members.data()); + + m_module.decorate(structType, false + ? spv::DecorationBufferBlock + : spv::DecorationBlock); + + m_module.memberDecorateOffset(structType, 0, m_layout->intOffset()); + m_module.memberDecorateOffset(structType, 1, m_layout->floatOffset()); + + m_module.setDebugName(structType, "cbuffer_t"); + m_module.setDebugMemberName(structType, 0, "i"); + m_module.setDebugMemberName(structType, 1, "f"); + + m_cBuffer = m_module.newVar( + m_module.defPointerType(structType, spv::StorageClassUniform), + spv::StorageClassUniform); + + m_module.setDebugName(m_cBuffer, "c"); + + const uint32_t bindingId = computeResourceSlotId( + m_programInfo.type(), DxsoBindingType::ConstantBuffer, + 0); + + m_module.decorateDescriptorSet(m_cBuffer, 0); + m_module.decorateBinding(m_cBuffer, bindingId); + + DxvkResourceSlot resource; + resource.slot = bindingId; + resource.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + resource.view = VK_IMAGE_VIEW_TYPE_MAX_ENUM; + resource.access = VK_ACCESS_UNIFORM_READ_BIT; + m_resourceSlots.push_back(resource); + + m_boolSpecConstant = m_module.specConst32(m_module.defIntType(32, 0), 0); + m_module.decorateSpecId(m_boolSpecConstant, getSpecId( + m_programInfo.type() == DxsoProgramType::VertexShader + ? D3D9SpecConstantId::VertexShaderBools + : D3D9SpecConstantId::PixelShaderBools)); + m_module.setDebugName(m_boolSpecConstant, "boolConstants"); + } + + template + int DxsoCompiler::emitDclSwvpConstantBuffer() { + uint32_t member; + bool asSsbo; + if constexpr (ConstantBufferType == DxsoConstantBufferType::Float) { + asSsbo = m_moduleInfo.options.vertexFloatConstantBufferAsSSBO; + + // float f[8192] + member = m_module.defArrayTypeUnique( + getVectorTypeId({ DxsoScalarType::Float32, 4 }), + m_module.constu32(m_layout->floatCount)); + m_module.decorateArrayStride(member, 16); + } else if constexpr (ConstantBufferType == DxsoConstantBufferType::Int) { + asSsbo = false; + + // int i[2048] + member = m_module.defArrayTypeUnique( + getVectorTypeId({ DxsoScalarType::Sint32, 4 }), + m_module.constu32(m_layout->intCount)); + m_module.decorateArrayStride(member, 16); + } else { + asSsbo = false; + + // int i[256] (bitmasks for 2048 bools) + member = m_module.defArrayTypeUnique( + getVectorTypeId({ DxsoScalarType::Uint32, 4 }), + m_module.constu32(m_layout->bitmaskCount / 4)); + // Must be a multiple of 4 otherwise. + m_module.decorateArrayStride(member, 16); + } + + const uint32_t structType = + m_module.defStructType(1, &member); + + m_module.decorate(structType, asSsbo + ? spv::DecorationBufferBlock + : spv::DecorationBlock); + + m_module.memberDecorateOffset(structType, 0, 0); + + if constexpr (ConstantBufferType == DxsoConstantBufferType::Float) { + m_module.setDebugName(structType, "cbuffer_float_t"); + m_module.setDebugMemberName(structType, 0, "f"); + } else if constexpr (ConstantBufferType == DxsoConstantBufferType::Int) { + m_module.setDebugName(structType, "cbuffer_int_t"); + m_module.setDebugMemberName(structType, 0, "i"); + } else { + m_module.setDebugName(structType, "cbuffer_bool_t"); + m_module.setDebugMemberName(structType, 0, "b"); + } + + uint32_t constantBufferId = m_module.newVar( + m_module.defPointerType(structType, spv::StorageClassUniform), + spv::StorageClassUniform); + + uint32_t bindingId; + if constexpr (ConstantBufferType == DxsoConstantBufferType::Float) { + m_module.setDebugName(constantBufferId, "cF"); + bindingId = computeResourceSlotId( + m_programInfo.type(), DxsoBindingType::ConstantBuffer, + 0); + } else if constexpr (ConstantBufferType == DxsoConstantBufferType::Int) { + m_module.setDebugName(constantBufferId, "cI"); + bindingId = computeResourceSlotId( + m_programInfo.type(), DxsoBindingType::ConstantBuffer, + 1); + } else { + m_module.setDebugName(constantBufferId, "cB"); + bindingId = computeResourceSlotId( + m_programInfo.type(), DxsoBindingType::ConstantBuffer, + 2); + } + + m_module.decorateDescriptorSet(constantBufferId, 0); + m_module.decorateBinding(constantBufferId, bindingId); + + if (asSsbo) + m_module.decorate(constantBufferId, spv::DecorationNonWritable); + + DxvkResourceSlot resource; + resource.slot = bindingId; + resource.type = asSsbo + ? VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + : VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + resource.view = VK_IMAGE_VIEW_TYPE_MAX_ENUM; + resource.access = asSsbo ? VK_ACCESS_MEMORY_READ_BIT : VK_ACCESS_UNIFORM_READ_BIT; + m_resourceSlots.push_back(resource); + + return constantBufferId; + } + + + void DxsoCompiler::emitDclInputArray() { + DxsoArrayType info; + info.ctype = DxsoScalarType::Float32; + info.ccount = 4; + info.alength = DxsoMaxInterfaceRegs; + + uint32_t arrayTypeId = getArrayTypeId(info); + + // Define the actual variable. Note that this is private + // because we will copy input registers + // to the array during the setup phase. + const uint32_t ptrTypeId = m_module.defPointerType( + arrayTypeId, spv::StorageClassPrivate); + + m_vArray = m_module.newVar( + ptrTypeId, spv::StorageClassPrivate); + m_module.setDebugName(m_vArray, "v"); + } + + void DxsoCompiler::emitDclOutputArray() { + DxsoArrayType info; + info.ctype = DxsoScalarType::Float32; + info.ccount = 4; + info.alength = m_programInfo.type() == DxsoProgramTypes::VertexShader + ? DxsoMaxInterfaceRegs + : caps::MaxSimultaneousRenderTargets; + + uint32_t arrayTypeId = getArrayTypeId(info); + + // Define the actual variable. Note that this is private + // because we will copy input registers + // to the array during the setup phase. + const uint32_t ptrTypeId = m_module.defPointerType( + arrayTypeId, spv::StorageClassPrivate); + + m_oArray = m_module.newVar( + ptrTypeId, spv::StorageClassPrivate); + m_module.setDebugName(m_oArray, "o"); + } + + + void DxsoCompiler::emitVsInit() { + m_module.enableCapability(spv::CapabilityClipDistance); + + // Only VS needs this, because PS has + // non-indexable specialized output regs + this->emitDclOutputArray(); + + // Main function of the vertex shader + m_vs.functionId = m_module.allocateId(); + m_module.setDebugName(m_vs.functionId, "vs_main"); + + this->setupRenderStateInfo(); + + this->emitFunctionBegin( + m_vs.functionId, + m_module.defVoidType(), + m_module.defFunctionType( + m_module.defVoidType(), 0, nullptr)); + this->emitFunctionLabel(); + } + + + void DxsoCompiler::emitPsSharedConstants() { + m_ps.sharedState = GetSharedConstants(m_module); + + const uint32_t bindingId = computeResourceSlotId( + m_programInfo.type(), DxsoBindingType::ConstantBuffer, + PSShared); + + m_module.decorateDescriptorSet(m_ps.sharedState, 0); + m_module.decorateBinding(m_ps.sharedState, bindingId); + + DxvkResourceSlot resource; + resource.slot = bindingId; + resource.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + resource.view = VK_IMAGE_VIEW_TYPE_MAX_ENUM; + resource.access = VK_ACCESS_UNIFORM_READ_BIT; + m_resourceSlots.push_back(resource); + } + + + void DxsoCompiler::emitPsInit() { + m_module.enableCapability(spv::CapabilityDerivativeControl); + + m_module.setExecutionMode(m_entryPointId, + spv::ExecutionModeOriginUpperLeft); + + + // Main function of the pixel shader + m_ps.functionId = m_module.allocateId(); + m_module.setDebugName(m_ps.functionId, "ps_main"); + + if (m_programInfo.majorVersion() < 2 || m_moduleInfo.options.forceSamplerTypeSpecConstants) { + m_ps.samplerTypeSpec = m_module.specConst32(m_module.defIntType(32, 0), 0); + m_module.decorateSpecId(m_ps.samplerTypeSpec, getSpecId(D3D9SpecConstantId::SamplerType)); + m_module.setDebugName(m_ps.samplerTypeSpec, "s_sampler_types"); + + if (m_programInfo.majorVersion() < 2) { + m_ps.projectionSpec = m_module.specConst32(m_module.defIntType(32, 0), 0); + m_module.decorateSpecId(m_ps.projectionSpec, getSpecId(D3D9SpecConstantId::ProjectionType)); + m_module.setDebugName(m_ps.projectionSpec, "s_projections"); + } + } + + m_ps.fetch4Spec = m_module.specConst32(m_module.defIntType(32, 0), 0); + m_module.decorateSpecId(m_ps.fetch4Spec, getSpecId(D3D9SpecConstantId::Fetch4)); + m_module.setDebugName(m_ps.fetch4Spec, "s_fetch4"); + + this->setupRenderStateInfo(); + this->emitPsSharedConstants(); + + this->emitFunctionBegin( + m_ps.functionId, + m_module.defVoidType(), + m_module.defFunctionType( + m_module.defVoidType(), 0, nullptr)); + this->emitFunctionLabel(); + + // We may have to defer kill operations to the end of + // the shader in order to keep derivatives correct. + if (m_analysis->usesKill && m_moduleInfo.options.useDemoteToHelperInvocation) { + // This extension basically implements D3D-style discard + m_module.enableExtension("SPV_EXT_demote_to_helper_invocation"); + m_module.enableCapability(spv::CapabilityDemoteToHelperInvocationEXT); + } + else if (m_analysis->usesKill && m_analysis->usesDerivatives) { + m_ps.killState = m_module.newVarInit( + m_module.defPointerType(m_module.defBoolType(), spv::StorageClassPrivate), + spv::StorageClassPrivate, m_module.constBool(false)); + + m_module.setDebugName(m_ps.killState, "ps_kill"); + + if (m_moduleInfo.options.useSubgroupOpsForEarlyDiscard) { + m_module.enableCapability(spv::CapabilityGroupNonUniform); + m_module.enableCapability(spv::CapabilityGroupNonUniformBallot); + + DxsoRegisterInfo laneId; + laneId.type = { DxsoScalarType::Uint32, 1, 0 }; + laneId.sclass = spv::StorageClassInput; + + m_ps.builtinLaneId = emitNewBuiltinVariable( + laneId, spv::BuiltInSubgroupLocalInvocationId, + "fLaneId", 0); + } + } + } + + + void DxsoCompiler::emitFunctionBegin( + uint32_t entryPoint, + uint32_t returnType, + uint32_t funcType) { + this->emitFunctionEnd(); + + m_module.functionBegin( + returnType, entryPoint, funcType, + spv::FunctionControlMaskNone); + + m_insideFunction = true; + } + + + void DxsoCompiler::emitFunctionEnd() { + if (m_insideFunction) { + m_module.opReturn(); + m_module.functionEnd(); + } + + m_insideFunction = false; + } + + + uint32_t DxsoCompiler::emitFunctionLabel() { + uint32_t labelId = m_module.allocateId(); + m_module.opLabel(labelId); + return labelId; + } + + + void DxsoCompiler::emitMainFunctionBegin() { + this->emitFunctionBegin( + m_entryPointId, + m_module.defVoidType(), + m_module.defFunctionType( + m_module.defVoidType(), 0, nullptr)); + m_mainFuncLabel = this->emitFunctionLabel(); + } + + + uint32_t DxsoCompiler::emitNewVariable(const DxsoRegisterInfo& info) { + const uint32_t ptrTypeId = this->getPointerTypeId(info); + return m_module.newVar(ptrTypeId, info.sclass); + } + + + uint32_t DxsoCompiler::emitNewVariableDefault( + const DxsoRegisterInfo& info, + uint32_t value) { + const uint32_t ptrTypeId = this->getPointerTypeId(info); + if (value == 0) + return m_module.newVar(ptrTypeId, info.sclass); + else + return m_module.newVarInit(ptrTypeId, info.sclass, value); + } + + + uint32_t DxsoCompiler::emitNewBuiltinVariable( + const DxsoRegisterInfo& info, + spv::BuiltIn builtIn, + const char* name, + uint32_t value) { + const uint32_t varId = emitNewVariableDefault(info, value); + + m_module.setDebugName(varId, name); + m_module.decorateBuiltIn(varId, builtIn); + + if (m_programInfo.type() == DxsoProgramTypes::PixelShader + && info.type.ctype != DxsoScalarType::Float32 + && info.type.ctype != DxsoScalarType::Bool + && info.sclass == spv::StorageClassInput) + m_module.decorate(varId, spv::DecorationFlat); + + m_entryPointInterfaces.push_back(varId); + return varId; + } + + DxsoCfgBlock* DxsoCompiler::cfgFindBlock( + const std::initializer_list& types) { + for (auto cur = m_controlFlowBlocks.rbegin(); + cur != m_controlFlowBlocks.rend(); cur++) { + for (auto type : types) { + if (cur->type == type) + return &(*cur); + } + } + + return nullptr; + } + + spv::BuiltIn semanticToBuiltIn(bool input, DxsoSemantic semantic) { + if (input) + return spv::BuiltInMax; + + if (semantic == DxsoSemantic{ DxsoUsage::Position, 0 }) + return spv::BuiltInPosition; + + if (semantic == DxsoSemantic{ DxsoUsage::PointSize, 0 }) + return spv::BuiltInPointSize; + + return spv::BuiltInMax; + } + + void DxsoCompiler::emitDclInterface( + bool input, + uint32_t regNumber, + DxsoSemantic semantic, + DxsoRegMask mask, + bool centroid) { + auto& sgn = input + ? m_isgn : m_osgn; + + const bool pixel = m_programInfo.type() == DxsoProgramTypes::PixelShader; + const bool vertex = !pixel; + + if (pixel && input && semantic.usage == DxsoUsage::Color && m_programInfo.majorVersion() < 3) + centroid = true; + + uint32_t slot = 0; + + uint32_t& slots = input + ? m_inputMask + : m_outputMask; + + uint16_t& explicits = input + ? m_explicitInputs + : m_explicitOutputs; + + // Some things we consider builtins could be packed in an output reg. + bool builtin = semanticToBuiltIn(input, semantic) != spv::BuiltInMax; + + uint32_t i = sgn.elemCount++; + + if (input && vertex) { + // Any slot will do! Let's chose the next one + slot = i; + } + else if ( (!input && vertex) + || (input && pixel ) ) { + // Don't register the slot if it belongs to a builtin + if (!builtin) + slot = RegisterLinkerSlot(semantic); + } + else { //if (!input && pixel) + // We want to make the output slot the same as the + // output register for pixel shaders so they go to + // the right render target. + slot = regNumber; + } + + // Don't want to mark down any of these builtins. + if (!builtin) + slots |= 1u << slot; + explicits |= 1u << regNumber; + + auto& elem = sgn.elems[i]; + elem.slot = slot; + elem.regNumber = regNumber; + elem.semantic = semantic; + elem.mask = mask; + elem.centroid = centroid; + } + + void DxsoCompiler::emitDclSampler( + uint32_t idx, + DxsoTextureType type) { + m_usedSamplers |= (1u << idx); + + VkImageViewType viewType = VK_IMAGE_VIEW_TYPE_MAX_ENUM; + + auto DclSampler = [this, &viewType]( + uint32_t idx, + uint32_t bindingId, + DxsoSamplerType type, + bool depth, + bool implicit) { + // Setup our combines sampler. + DxsoSamplerInfo& sampler = !depth + ? m_samplers[idx].color[type] + : m_samplers[idx].depth[type]; + + spv::Dim dimensionality; + + const char* suffix = "_2d"; + + switch (type) { + default: + case SamplerTypeTexture2D: + sampler.dimensions = 2; + dimensionality = spv::Dim2D; + viewType = VK_IMAGE_VIEW_TYPE_2D; + break; + + case SamplerTypeTextureCube: + suffix = "_cube"; + sampler.dimensions = 3; + dimensionality = spv::DimCube; + viewType = VK_IMAGE_VIEW_TYPE_CUBE; + break; + + case SamplerTypeTexture3D: + suffix = "_3d"; + sampler.dimensions = 3; + dimensionality = spv::Dim3D; + viewType = VK_IMAGE_VIEW_TYPE_3D; + break; + } + + sampler.imageTypeId = m_module.defImageType( + m_module.defFloatType(32), + dimensionality, depth ? 1 : 0, 0, 0, 1, + spv::ImageFormatUnknown); + + sampler.typeId = m_module.defSampledImageType(sampler.imageTypeId); + + sampler.varId = m_module.newVar( + m_module.defPointerType( + sampler.typeId, spv::StorageClassUniformConstant), + spv::StorageClassUniformConstant); + + std::string name = str::format("s", idx, suffix, depth ? "_shadow" : ""); + m_module.setDebugName(sampler.varId, name.c_str()); + + m_module.decorateDescriptorSet(sampler.varId, 0); + m_module.decorateBinding (sampler.varId, bindingId); + }; + + const uint32_t binding = computeResourceSlotId(m_programInfo.type(), + DxsoBindingType::Image, + idx); + + const bool implicit = m_programInfo.majorVersion() < 2 || m_moduleInfo.options.forceSamplerTypeSpecConstants; + + if (!implicit) { + DxsoSamplerType samplerType = + SamplerTypeFromTextureType(type); + + DclSampler(idx, binding, samplerType, false, implicit); + + if (samplerType != SamplerTypeTexture3D) { + // We could also be depth compared! + DclSampler(idx, binding, samplerType, true, implicit); + } + } + else { + // Could be any of these! + // We will check with the spec constant at sample time. + for (uint32_t i = 0; i < SamplerTypeCount; i++) { + auto samplerType = static_cast(i); + + DclSampler(idx, binding, samplerType, false, implicit); + + if (samplerType != SamplerTypeTexture3D) + DclSampler(idx, binding, samplerType, true, implicit); + } + } + + DxsoSampler& sampler = m_samplers[idx]; + sampler.boundConst = m_module.specConstBool(true); + sampler.type = type; + m_module.decorateSpecId(sampler.boundConst, binding); + m_module.setDebugName(sampler.boundConst, + str::format("s", idx, "_bound").c_str()); + + // Store descriptor info for the shader interface + DxvkResourceSlot resource; + resource.slot = binding; + resource.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + resource.view = implicit ? VK_IMAGE_VIEW_TYPE_MAX_ENUM : viewType; + resource.access = VK_ACCESS_SHADER_READ_BIT; + m_resourceSlots.push_back(resource); + } + + + uint32_t DxsoCompiler::emitArrayIndex( + uint32_t idx, + const DxsoBaseRegister* relative) { + uint32_t result = m_module.consti32(idx); + + if (relative != nullptr) { + DxsoRegisterValue offset = emitRegisterLoad(*relative, DxsoRegMask(true, false, false, false), nullptr); + + result = m_module.opIAdd( + getVectorTypeId(offset.type), + result, offset.id); + } + + return result; + } + + + DxsoRegisterPointer DxsoCompiler::emitInputPtr( + bool texture, + const DxsoBaseRegister& reg, + const DxsoBaseRegister* relative) { + uint32_t idx = reg.id.num; + + // Account for the two color regs. + if (texture) + idx += 2; + + DxsoRegisterPointer input; + + input.type = DxsoVectorType{ DxsoScalarType::Float32, 4 }; + + uint32_t index = this->emitArrayIndex(idx, relative); + + const uint32_t typeId = getVectorTypeId(input.type); + input.id = m_module.opAccessChain( + m_module.defPointerType(typeId, spv::StorageClassPrivate), + m_vArray, + 1, &index); + + return input; + } + + DxsoRegisterPointer DxsoCompiler::emitRegisterPtr( + const char* name, + DxsoScalarType ctype, + uint32_t ccount, + uint32_t defaultVal, + spv::StorageClass storageClass, + spv::BuiltIn builtIn) { + DxsoRegisterPointer result; + + DxsoRegisterInfo info; + info.type.ctype = ctype; + info.type.ccount = ccount; + info.type.alength = 1; + info.sclass = storageClass; + + result.type = DxsoVectorType{ ctype, ccount }; + if (builtIn == spv::BuiltInMax) { + result.id = this->emitNewVariableDefault(info, defaultVal); + m_module.setDebugName(result.id, name); + } + else { + result.id = this->emitNewBuiltinVariable( + info, builtIn, name, defaultVal); + } + + return result; + } + + + DxsoRegisterValue DxsoCompiler::emitLoadConstant( + const DxsoBaseRegister& reg, + const DxsoBaseRegister* relative) { + // struct cBuffer_t { + // + // Type Member Index + // + // float f[256 or 224]; 0 + // int32_t i[16]; 1 + // uint32_t boolBitmask; 2 + // } + DxsoRegisterValue result = { }; + + switch (reg.id.type) { + case DxsoRegisterType::Const: + result.type = { DxsoScalarType::Float32, 4 }; + + if (!relative) + result.id = m_cFloat.at(reg.id.num); + break; + + case DxsoRegisterType::ConstInt: + result.type = { DxsoScalarType::Sint32, 4 }; + result.id = m_cInt.at(reg.id.num); + break; + + case DxsoRegisterType::ConstBool: + result.type = { DxsoScalarType::Bool, 1 }; + result.id = m_cBool.at(reg.id.num); + break; + + default: break; + } + + if (result.id) + return result; + + switch (reg.id.type) { + case DxsoRegisterType::Const: + if (!relative) { + m_meta.maxConstIndexF = std::max(m_meta.maxConstIndexF, reg.id.num + 1); + m_meta.maxConstIndexF = std::min(m_meta.maxConstIndexF, m_layout->floatCount); + } else { + m_meta.maxConstIndexF = m_layout->floatCount; + m_meta.needsConstantCopies |= m_moduleInfo.options.strictConstantCopies + || m_cFloat.at(reg.id.num) != 0; + } + break; + + case DxsoRegisterType::ConstInt: + m_meta.maxConstIndexI = std::max(m_meta.maxConstIndexI, reg.id.num + 1); + m_meta.maxConstIndexI = std::min(m_meta.maxConstIndexI, m_layout->intCount); + break; + + case DxsoRegisterType::ConstBool: + m_meta.maxConstIndexB = std::max(m_meta.maxConstIndexB, reg.id.num + 1); + m_meta.maxConstIndexB = std::min(m_meta.maxConstIndexB, m_layout->boolCount); + m_meta.boolConstantMask |= 1 << reg.id.num; + break; + + default: break; + } + + uint32_t relativeIdx = this->emitArrayIndex(reg.id.num, relative); + + if (reg.id.type != DxsoRegisterType::ConstBool) { + uint32_t structIdx; + uint32_t cBufferId; + + if (reg.id.type == DxsoRegisterType::Const) { + if (isSwvp()) { + structIdx = m_module.constu32(0); + cBufferId = m_cFloatBuffer; + } else { + structIdx = m_module.constu32(1); + cBufferId = m_cBuffer; + } + } else { + if (isSwvp()) { + structIdx = m_module.constu32(0); + cBufferId = m_cIntBuffer; + } else { + structIdx = m_module.constu32(0); + cBufferId = m_cBuffer; + } + } + + std::array indices = { structIdx, relativeIdx }; + + uint32_t typeId = getVectorTypeId(result.type); + uint32_t ptrId = m_module.opAccessChain( + m_module.defPointerType(typeId, spv::StorageClassUniform), + cBufferId, indices.size(), indices.data()); + + result.id = m_module.opLoad(typeId, ptrId); + + if (relative && !m_moduleInfo.options.robustness2Supported) { + uint32_t constCount = m_module.constu32(m_layout->floatCount); + + // Expand condition to bvec4 since the result has four components + uint32_t cond = m_module.opULessThan(m_module.defBoolType(), relativeIdx, constCount); + std::array condIds = { cond, cond, cond, cond }; + + cond = m_module.opCompositeConstruct( + m_module.defVectorType(m_module.defBoolType(), 4), + condIds.size(), condIds.data()); + + result.id = m_module.opSelect(typeId, cond, result.id, + m_module.constvec4f32(0.0f, 0.0f, 0.0f, 0.0f)); + } + } else { + // Bool constants have no relative indexing, so we can do the bitfield + // magic for SWVP at compile time. + + uint32_t uintType = getScalarTypeId(DxsoScalarType::Uint32); + uint32_t uvec4Type = getVectorTypeId({ DxsoScalarType::Uint32, 4 }); + + // If not SWVP, spec const this + uint32_t bitfield; + if (m_layout->bitmaskCount != 1) { + std::array indices = { m_module.constu32(0), m_module.constu32(reg.id.num / 128) }; + + uint32_t indexCount = m_layout->bitmaskCount == 1 ? 1 : 2; + uint32_t accessType = m_layout->bitmaskCount == 1 ? uintType : uvec4Type; + + uint32_t ptrId = m_module.opAccessChain( + m_module.defPointerType(accessType, spv::StorageClassUniform), + m_cBoolBuffer, indexCount, indices.data()); + + bitfield = m_module.opLoad(accessType, ptrId); + } + else + bitfield = m_boolSpecConstant; + + uint32_t bitIdx = m_module.consti32(reg.id.num % 32); + + if (m_layout->bitmaskCount != 1) { + uint32_t index = (reg.id.num % 128) / 32; + bitfield = m_module.opCompositeExtract(uintType, bitfield, 1, &index); + } + uint32_t bit = m_module.opBitFieldUExtract( + uintType, bitfield, bitIdx, m_module.consti32(1)); + + result.id = m_module.opINotEqual( + getVectorTypeId(result.type), + bit, m_module.constu32(0)); + } + + return result; + } + + + DxsoRegisterPointer DxsoCompiler::emitOutputPtr( + bool texcrdOut, + const DxsoBaseRegister& reg, + const DxsoBaseRegister* relative) { + uint32_t idx = reg.id.num; + + // Account for the two color regs. + if (texcrdOut) + idx += 2; + + DxsoRegisterPointer input; + + input.type = DxsoVectorType{ DxsoScalarType::Float32, 4 }; + + uint32_t index = this->emitArrayIndex(idx, relative); + + const uint32_t typeId = getVectorTypeId(input.type); + input.id = m_module.opAccessChain( + m_module.defPointerType(typeId, spv::StorageClassPrivate), + m_oArray, + 1, &index); + + return input; + } + + + DxsoRegisterPointer DxsoCompiler::emitGetOperandPtr( + const DxsoBaseRegister& reg, + const DxsoBaseRegister* relative) { + switch (reg.id.type) { + case DxsoRegisterType::Temp: { + DxsoRegisterPointer& ptr = m_rRegs.at(reg.id.num); + if (ptr.id == 0) { + std::string name = str::format("r", reg.id.num); + ptr = this->emitRegisterPtr( + name.c_str(), DxsoScalarType::Float32, 4, + m_module.constvec4f32(0.0f, 0.0f, 0.0f, 0.0f)); + } + return ptr; + } + + case DxsoRegisterType::Input: { + if (!(m_explicitInputs & 1u << reg.id.num)) { + this->emitDclInterface( + true, reg.id.num, + DxsoSemantic{ DxsoUsage::Color, reg.id.num }, + IdentityWriteMask, false); + } + + return this->emitInputPtr(false, reg, relative); + } + + case DxsoRegisterType::PixelTexcoord: + case DxsoRegisterType::Texture: { + if (m_programInfo.type() == DxsoProgramTypes::PixelShader) { + // Texture register + + // SM2, or SM 1.4 + if (reg.id.type == DxsoRegisterType::PixelTexcoord + || m_programInfo.majorVersion() >= 2 + || (m_programInfo.majorVersion() == 1 + && m_programInfo.minorVersion() == 4)) { + uint32_t adjustedNumber = reg.id.num + 2; + if (!(m_explicitInputs & 1u << adjustedNumber)) { + this->emitDclInterface( + true, adjustedNumber, + DxsoSemantic{ DxsoUsage::Texcoord, reg.id.num }, + IdentityWriteMask, false); + } + + return this->emitInputPtr(true, reg, relative); + } + else { + // User must use tex/texcoord to put data in this private register. + // We use the an oob id which fxc never generates for the texcoord data. + DxsoRegisterPointer& ptr = m_tRegs.at(reg.id.num); + if (ptr.id == 0) { + std::string name = str::format("t", reg.id.num); + ptr = this->emitRegisterPtr( + name.c_str(), DxsoScalarType::Float32, 4, + m_module.constvec4f32(0.0f, 0.0f, 0.0f, 0.0f)); + } + return ptr; + } + } + else { + // Address register + if (m_vs.addr.id == 0) { + m_vs.addr = this->emitRegisterPtr( + "a0", DxsoScalarType::Sint32, 4, + m_module.constvec4i32(0, 0, 0, 0)); + } + return m_vs.addr; + } + } + + case DxsoRegisterType::RasterizerOut: + switch (reg.id.num) { + case RasterOutPosition: + if (m_vs.oPos.id == 0) { + m_vs.oPos = this->emitRegisterPtr( + "oPos", DxsoScalarType::Float32, 4, + m_module.constvec4f32(0.0f, 0.0f, 0.0f, 0.0f), + spv::StorageClassOutput, spv::BuiltInPosition); + } + return m_vs.oPos; + + case RasterOutFog: + if (m_fog.id == 0) { + bool input = m_programInfo.type() == DxsoProgramType::PixelShader; + DxsoSemantic semantic = DxsoSemantic{ DxsoUsage::Fog, 0 }; + + uint32_t slot = RegisterLinkerSlot(semantic); + + uint32_t& slots = input + ? m_inputMask + : m_outputMask; + + slots |= 1u << slot; + + m_fog = this->emitRegisterPtr( + input ? "vFog" : "oFog", + DxsoScalarType::Float32, 1, + input ? 0 : m_module.constf32(1.0f), + input ? spv::StorageClassInput : spv::StorageClassOutput); + + m_entryPointInterfaces.push_back(m_fog.id); + + m_module.decorateLocation(m_fog.id, slot); + } + return m_fog; + + case RasterOutPointSize: + if (m_vs.oPSize.id == 0) { + m_vs.oPSize = this->emitRegisterPtr( + "oPSize", DxsoScalarType::Float32, 1, + m_module.constf32(0.0f), + spv::StorageClassOutput, spv::BuiltInPointSize); + } + return m_vs.oPSize; + + default: { + DxsoRegisterPointer nullPointer; + nullPointer.id = 0; + return nullPointer; + } + } + + case DxsoRegisterType::ColorOut: { + uint32_t idx = std::min(reg.id.num, 4u); + + if (m_ps.oColor[idx].id == 0) { + std::string name = str::format("oC", idx); + m_ps.oColor[idx] = this->emitRegisterPtr( + name.c_str(), DxsoScalarType::Float32, 4, + m_module.constvec4f32(0.0f, 0.0f, 0.0f, 0.0f), + spv::StorageClassOutput); + + m_outputMask |= 1u << idx; + m_module.decorateLocation(m_ps.oColor[idx].id, idx); + m_module.decorateIndex(m_ps.oColor[idx].id, 0); + + m_entryPointInterfaces.push_back(m_ps.oColor[idx].id); + m_usedRTs |= (1u << idx); + } + return m_ps.oColor[idx]; + } + + case DxsoRegisterType::AttributeOut: { + auto ptr = this->emitOutputPtr(false, reg, nullptr); + + if (!(m_explicitOutputs & 1u << reg.id.num)) { + this->emitDclInterface( + false, reg.id.num, + DxsoSemantic{ DxsoUsage::Color, reg.id.num }, + IdentityWriteMask, false); + + m_module.opStore(ptr.id, m_module.constfReplicant(0, ptr.type.ccount)); + } + + return ptr; + } + + case DxsoRegisterType::Output: { + bool texcrdOut = m_programInfo.type() == DxsoProgramTypes::VertexShader + && m_programInfo.majorVersion() != 3; + + auto ptr = this->emitOutputPtr(texcrdOut, reg, !texcrdOut ? relative : nullptr); + + if (texcrdOut) { + uint32_t adjustedNumber = reg.id.num + 2; + if (!(m_explicitOutputs & 1u << adjustedNumber)) { + this->emitDclInterface( + false, adjustedNumber, + DxsoSemantic{ DxsoUsage::Texcoord, reg.id.num }, + IdentityWriteMask, false); + + m_module.opStore(ptr.id, m_module.constfReplicant(0, ptr.type.ccount)); + } + } + + return ptr; + } + + case DxsoRegisterType::DepthOut: + if (m_ps.oDepth.id == 0) { + m_module.setExecutionMode(m_entryPointId, + spv::ExecutionModeDepthReplacing); + + m_ps.oDepth = this->emitRegisterPtr( + "oDepth", DxsoScalarType::Float32, 1, + m_module.constf32(0.0f), + spv::StorageClassOutput, spv::BuiltInFragDepth); + } + return m_ps.oDepth; + + case DxsoRegisterType::Loop: + if (m_loopCounter.id == 0) { + m_loopCounter = this->emitRegisterPtr( + "aL", DxsoScalarType::Sint32, 1, + m_module.consti32(0)); + } + return m_loopCounter; + + case DxsoRegisterType::MiscType: + if (reg.id.num == MiscTypePosition) { + if (m_ps.vPos.id == 0) { + m_ps.vPos = this->emitRegisterPtr( + "vPos", DxsoScalarType::Float32, 4, 0); + } + return m_ps.vPos; + } + else { // MiscTypeFace + if (m_ps.vFace.id == 0) { + m_ps.vFace = this->emitRegisterPtr( + "vFace", DxsoScalarType::Float32, 4, 0); + } + return m_ps.vFace; + } + + case DxsoRegisterType::Predicate: { + DxsoRegisterPointer& ptr = m_pRegs.at(reg.id.num); + if (ptr.id == 0) { + std::string name = str::format("p", reg.id.num); + ptr = this->emitRegisterPtr( + name.c_str(), DxsoScalarType::Bool, 4, + m_module.constvec4b32(false, false, false, false)); + } + return ptr; + } + + default: { + //Logger::warn(str::format("emitGetOperandPtr: unhandled reg type: ", reg.id.type)); + + DxsoRegisterPointer nullPointer; + nullPointer.id = 0; + return nullPointer; + } + } + } + + + uint32_t DxsoCompiler::emitBoolComparison(DxsoVectorType type, DxsoComparison cmp, uint32_t a, uint32_t b) { + const uint32_t typeId = getVectorTypeId(type); + switch (cmp) { + default: + case DxsoComparison::Never: return m_module.constbReplicant(false, type.ccount); break; + case DxsoComparison::GreaterThan: return m_module.opFOrdGreaterThan (typeId, a, b); break; + case DxsoComparison::Equal: return m_module.opFOrdEqual (typeId, a, b); break; + case DxsoComparison::GreaterEqual: return m_module.opFOrdGreaterThanEqual(typeId, a, b); break; + case DxsoComparison::LessThan: return m_module.opFOrdLessThan (typeId, a, b); break; + case DxsoComparison::NotEqual: return m_module.opFOrdNotEqual (typeId, a, b); break; + case DxsoComparison::LessEqual: return m_module.opFOrdLessThanEqual (typeId, a, b); break; + case DxsoComparison::Always: return m_module.constbReplicant(true, type.ccount); break; + } +} + + + DxsoRegisterValue DxsoCompiler::emitValueLoad( + DxsoRegisterPointer ptr) { + DxsoRegisterValue result; + result.type = ptr.type; + result.id = m_module.opLoad( + getVectorTypeId(result.type), + ptr.id); + return result; + } + + + DxsoRegisterValue DxsoCompiler::applyPredicate(DxsoRegisterValue pred, DxsoRegisterValue dst, DxsoRegisterValue src) { + if (dst.type.ccount != pred.type.ccount) { + DxsoRegMask mask = DxsoRegMask( + pred.type.ccount > 0, + pred.type.ccount > 1, + pred.type.ccount > 2, + pred.type.ccount > 3); + + pred = emitRegisterSwizzle(pred, IdentitySwizzle, mask); + } + + dst.id = m_module.opSelect( + getVectorTypeId(dst.type), + pred.id, + src.id, dst.id); + + return dst; + } + + + void DxsoCompiler::emitValueStore( + DxsoRegisterPointer ptr, + DxsoRegisterValue value, + DxsoRegMask writeMask, + DxsoRegisterValue predicate) { + // If the source value consists of only one component, + // it is stored in all components of the destination. + if (value.type.ccount == 1) + value = emitRegisterExtend(value, writeMask.popCount()); + + if (ptr.type.ccount == writeMask.popCount()) { + if (predicate.id) + value = applyPredicate(predicate, emitValueLoad(ptr), value); + + // Simple case: We write to the entire register + m_module.opStore(ptr.id, value.id); + } else { + // We only write to part of the destination + // register, so we need to load and modify it + DxsoRegisterValue tmp = emitValueLoad(ptr); + tmp = emitRegisterInsert(tmp, value, writeMask); + + if (predicate.id) + value = applyPredicate(predicate, emitValueLoad(ptr), tmp); + + m_module.opStore(ptr.id, tmp.id); + } + } + + + DxsoRegisterValue DxsoCompiler::emitClampBoundReplicant( + DxsoRegisterValue srcValue, + float lb, + float ub) { + srcValue.id = m_module.opFClamp(getVectorTypeId(srcValue.type), srcValue.id, + m_module.constfReplicant(lb, srcValue.type.ccount), + m_module.constfReplicant(ub, srcValue.type.ccount)); + + return srcValue; + } + + + DxsoRegisterValue DxsoCompiler::emitSaturate( + DxsoRegisterValue srcValue) { + return emitClampBoundReplicant(srcValue, 0.0f, 1.0f); + } + + + DxsoRegisterValue DxsoCompiler::emitMulOperand( + DxsoRegisterValue operand, + DxsoRegisterValue other) { + if (m_moduleInfo.options.d3d9FloatEmulation != D3D9FloatEmulation::Strict) + return operand; + + uint32_t boolId = getVectorTypeId({ DxsoScalarType::Bool, other.type.ccount }); + uint32_t zeroId = m_module.constfReplicant(0.0f, other.type.ccount); + + DxsoRegisterValue result; + result.type = operand.type; + result.id = m_module.opSelect(getVectorTypeId(result.type), + m_module.opFOrdEqual(boolId, other.id, zeroId), zeroId, operand.id); + return result; + } + + + DxsoRegisterValue DxsoCompiler::emitMul( + DxsoRegisterValue a, + DxsoRegisterValue b) { + auto az = emitMulOperand(a, b); + auto bz = emitMulOperand(b, a); + + DxsoRegisterValue result; + result.type = a.type; + result.id = m_module.opFMul(getVectorTypeId(result.type), az.id, bz.id); + return result; + } + + + DxsoRegisterValue DxsoCompiler::emitFma( + DxsoRegisterValue a, + DxsoRegisterValue b, + DxsoRegisterValue c) { + auto az = emitMulOperand(a, b); + auto bz = emitMulOperand(b, a); + + DxsoRegisterValue result; + result.type = a.type; + result.id = m_module.opFFma(getVectorTypeId(result.type), az.id, bz.id, c.id); + return result; + } + + + DxsoRegisterValue DxsoCompiler::emitDot( + DxsoRegisterValue a, + DxsoRegisterValue b) { + auto az = emitMulOperand(a, b); + auto bz = emitMulOperand(b, a); + + DxsoRegisterValue dot; + dot.type = a.type; + dot.type.ccount = 1; + + dot.id = m_module.opDot(getVectorTypeId(dot.type), az.id, bz.id); + return dot; + } + + DxsoRegisterValue DxsoCompiler::emitMix( + DxsoRegisterValue x, + DxsoRegisterValue y, + DxsoRegisterValue a) { + uint32_t typeId = getVectorTypeId(x.type); + + if (m_moduleInfo.options.d3d9FloatEmulation != D3D9FloatEmulation::Strict) + return {x.type, m_module.opFMix(typeId, x.id, y.id, a.id)}; + + uint32_t oneId = m_module.constfReplicant(1.0f, a.type.ccount); + + DxsoRegisterValue revA; + revA.type = a.type; + revA.id = m_module.opFSub(typeId, oneId, a.id); + + DxsoRegisterValue xRevA = emitMul(x, revA); + return emitFma(a, y, xRevA); + } + + + DxsoRegisterValue DxsoCompiler::emitCross( + DxsoRegisterValue a, + DxsoRegisterValue b) { + uint32_t typeId = getVectorTypeId(a.type); + + if (m_moduleInfo.options.d3d9FloatEmulation != D3D9FloatEmulation::Strict) + return {a.type, m_module.opCross(typeId, a.id, b.id)}; + + const std::array shiftIndices = { 1, 2, 0, 1 }; + + DxsoRegisterValue result; + result.type = { DxsoScalarType::Float32, 3 }; + + std::array products; + + for (uint32_t i = 0; i < 2; i++) { + DxsoRegisterValue ashift; + ashift.type = result.type; + ashift.id = m_module.opVectorShuffle(typeId, + a.id, a.id, 3, &shiftIndices[i]); + + DxsoRegisterValue bshift; + bshift.type = result.type; + bshift.id = m_module.opVectorShuffle(typeId, + b.id, b.id, 3, &shiftIndices[1 - i]); + + products[i] = emitMul(ashift, bshift); + } + + result.id = m_module.opFSub(typeId, products[0].id, products[1].id); + return result; + } + + + DxsoRegisterValue DxsoCompiler::emitRegisterInsert( + DxsoRegisterValue dstValue, + DxsoRegisterValue srcValue, + DxsoRegMask srcMask) { + DxsoRegisterValue result; + result.type = dstValue.type; + + const uint32_t typeId = getVectorTypeId(result.type); + + if (srcMask.popCount() == 0) { + // Nothing to do if the insertion mask is empty + result.id = dstValue.id; + } else if (dstValue.type.ccount == 1) { + // Both values are scalar, so the first component + // of the write mask decides which one to take. + result.id = srcMask[0] ? srcValue.id : dstValue.id; + } else if (srcValue.type.ccount == 1) { + // The source value is scalar. Since OpVectorShuffle + // requires both arguments to be vectors, we have to + // use OpCompositeInsert to modify the vector instead. + const uint32_t componentId = srcMask.firstSet(); + + result.id = m_module.opCompositeInsert(typeId, + srcValue.id, dstValue.id, 1, &componentId); + } else { + // Both arguments are vectors. We can determine which + // components to take from which vector and use the + // OpVectorShuffle instruction. + std::array components; + uint32_t srcComponentId = dstValue.type.ccount; + + for (uint32_t i = 0; i < dstValue.type.ccount; i++) + components.at(i) = srcMask[i] ? srcComponentId++ : i; + + result.id = m_module.opVectorShuffle( + typeId, dstValue.id, srcValue.id, + dstValue.type.ccount, components.data()); + } + + return result; + } + + + DxsoRegisterValue DxsoCompiler::emitRegisterLoadRaw( + const DxsoBaseRegister& reg, + const DxsoBaseRegister* relative) { + switch (reg.id.type) { + case DxsoRegisterType::Const: + case DxsoRegisterType::ConstInt: + case DxsoRegisterType::ConstBool: + return emitLoadConstant(reg, relative); + + default: + return emitValueLoad(emitGetOperandPtr(reg, relative)); + } + } + + + DxsoRegisterValue DxsoCompiler::emitRegisterExtend( + DxsoRegisterValue value, + uint32_t size) { + if (size == 1) + return value; + + std::array ids = {{ + value.id, value.id, + value.id, value.id, + }}; + + DxsoRegisterValue result; + result.type.ctype = value.type.ctype; + result.type.ccount = size; + result.id = m_module.opCompositeConstruct( + getVectorTypeId(result.type), + size, ids.data()); + return result; + } + + + DxsoRegisterValue DxsoCompiler::emitRegisterSwizzle( + DxsoRegisterValue value, + DxsoRegSwizzle swizzle, + DxsoRegMask writeMask) { + if (value.type.ccount == 1) + return emitRegisterExtend(value, writeMask.popCount()); + + std::array indices; + + uint32_t dstIndex = 0; + + for (uint32_t i = 0; i < 4; i++) { + if (writeMask[i]) + indices[dstIndex++] = swizzle[i]; + } + + // If the swizzle combined with the mask can be reduced + // to a no-op, we don't need to insert any instructions. + bool isIdentitySwizzle = dstIndex == value.type.ccount; + + for (uint32_t i = 0; i < dstIndex && isIdentitySwizzle; i++) + isIdentitySwizzle &= indices[i] == i; + + if (isIdentitySwizzle) + return value; + + // Use OpCompositeExtract if the resulting vector contains + // only one component, and OpVectorShuffle if it is a vector. + DxsoRegisterValue result; + result.type.ctype = value.type.ctype; + result.type.ccount = dstIndex; + + const uint32_t typeId = getVectorTypeId(result.type); + + if (dstIndex == 1) { + result.id = m_module.opCompositeExtract( + typeId, value.id, 1, indices.data()); + } else { + result.id = m_module.opVectorShuffle( + typeId, value.id, value.id, + dstIndex, indices.data()); + } + + return result; + } + + + DxsoRegisterValue DxsoCompiler::emitSrcOperandPreSwizzleModifiers( + DxsoRegisterValue value, + DxsoRegModifier modifier) { + // r / r.z + // r / r.w + if (modifier == DxsoRegModifier::Dz + || modifier == DxsoRegModifier::Dw) { + const uint32_t index = modifier == DxsoRegModifier::Dz ? 2 : 3; + + std::array indices = { index, index, index, index }; + + uint32_t component = m_module.opVectorShuffle( + getVectorTypeId(value.type), value.id, value.id, value.type.ccount, indices.data()); + + value.id = m_module.opFDiv( + getVectorTypeId(value.type), value.id, component); + } + + return value; + } + + + DxsoRegisterValue DxsoCompiler::emitSrcOperandPostSwizzleModifiers( + DxsoRegisterValue value, + DxsoRegModifier modifier) { + // r - 0.5 + if (modifier == DxsoRegModifier::Bias + || modifier == DxsoRegModifier::BiasNeg) { + uint32_t halfVec = m_module.constfReplicant( + 0.5f, value.type.ccount); + + value.id = m_module.opFSub( + getVectorTypeId(value.type), value.id, halfVec); + } + + // fma(r, 2.0f, -1.0f) + if (modifier == DxsoRegModifier::Sign + || modifier == DxsoRegModifier::SignNeg) { + uint32_t twoVec = m_module.constfReplicant( + 2.0f, value.type.ccount); + + uint32_t minusOneVec = m_module.constfReplicant( + -1.0f, value.type.ccount); + + value.id = m_module.opFFma( + getVectorTypeId(value.type), value.id, twoVec, minusOneVec); + } + + // 1 - r + if (modifier == DxsoRegModifier::Comp) { + uint32_t oneVec = m_module.constfReplicant( + 1.0f, value.type.ccount); + + value.id = m_module.opFSub( + getVectorTypeId(value.type), oneVec, value.id); + } + + // r * 2 + if (modifier == DxsoRegModifier::X2 + || modifier == DxsoRegModifier::X2Neg) { + uint32_t twoVec = m_module.constfReplicant( + 2.0f, value.type.ccount); + + value.id = m_module.opFMul( + getVectorTypeId(value.type), value.id, twoVec); + } + + // abs( r ) + if (modifier == DxsoRegModifier::Abs + || modifier == DxsoRegModifier::AbsNeg) { + value.id = m_module.opFAbs( + getVectorTypeId(value.type), value.id); + } + + // !r + if (modifier == DxsoRegModifier::Not) { + value.id = + m_module.opLogicalNot(getVectorTypeId(value.type), value.id); + } + + // -r + // Treating as -r + // Treating as -r + // -r * 2 + // -abs(r) + if (modifier == DxsoRegModifier::Neg + || modifier == DxsoRegModifier::BiasNeg + || modifier == DxsoRegModifier::SignNeg + || modifier == DxsoRegModifier::X2Neg + || modifier == DxsoRegModifier::AbsNeg) { + value.id = m_module.opFNegate( + getVectorTypeId(value.type), value.id); + } + + return value; + } + + DxsoRegisterValue DxsoCompiler::emitRegisterLoad( + const DxsoBaseRegister& reg, + DxsoRegMask writeMask, + const DxsoBaseRegister* relative) { + // Load operand from the operand pointer + DxsoRegisterValue result = emitRegisterLoadRaw(reg, relative); + + // PS 1.x clamps float constants + if (m_programInfo.type() == DxsoProgramType::PixelShader && m_programInfo.majorVersion() == 1 + && reg.id.type == DxsoRegisterType::Const) + result = emitClampBoundReplicant(result, -1.0f, 1.0f); + + // Apply operand modifiers + result = emitSrcOperandPreSwizzleModifiers(result, reg.modifier); + + // Apply operand swizzle to the operand value + result = emitRegisterSwizzle(result, reg.swizzle, writeMask); + + // Apply operand modifiers + result = emitSrcOperandPostSwizzleModifiers(result, reg.modifier); + return result; + } + + void DxsoCompiler::emitDcl(const DxsoInstructionContext& ctx) { + auto id = ctx.dst.id; + + if (id.type == DxsoRegisterType::Sampler) { + this->emitDclSampler( + ctx.dst.id.num, + ctx.dcl.textureType); + } + else if (id.type == DxsoRegisterType::Input + || id.type == DxsoRegisterType::Texture + || id.type == DxsoRegisterType::Output) { + DxsoSemantic semantic = ctx.dcl.semantic; + + uint32_t vIndex = id.num; + + if (m_programInfo.type() == DxsoProgramTypes::PixelShader) { + // Semantic in PS < 3 is based upon id. + if (m_programInfo.majorVersion() < 3) { + // Account for the two color registers. + if (id.type == DxsoRegisterType::Texture) + vIndex += 2; + + semantic = DxsoSemantic{ + id.type == DxsoRegisterType::Texture ? DxsoUsage::Texcoord : DxsoUsage::Color, + id.num }; + } + } + + this->emitDclInterface( + id.type != DxsoRegisterType::Output, + vIndex, + semantic, + ctx.dst.mask, + ctx.dst.centroid); + } + else { + //Logger::warn(str::format("DxsoCompiler::emitDcl: unhandled register type ", id.type)); + } + } + + void DxsoCompiler::emitDef(const DxsoInstructionContext& ctx) { + switch (ctx.instruction.opcode) { + case DxsoOpcode::Def: emitDefF(ctx); break; + case DxsoOpcode::DefI: emitDefI(ctx); break; + case DxsoOpcode::DefB: emitDefB(ctx); break; + default: + throw DxvkError("DxsoCompiler::emitDef: Invalid definition opcode"); + break; + } + } + + void DxsoCompiler::emitDefF(const DxsoInstructionContext& ctx) { + const float* data = ctx.def.float32; + + uint32_t constId = m_module.constvec4f32(data[0], data[1], data[2], data[3]); + m_cFloat.at(ctx.dst.id.num) = constId; + + std::string name = str::format("cF", ctx.dst.id.num, "_def"); + m_module.setDebugName(constId, name.c_str()); + + DxsoDefinedConstant constant; + constant.uboIdx = ctx.dst.id.num; + for (uint32_t i = 0; i < 4; i++) + constant.float32[i] = data[i]; + m_constants.push_back(constant); + m_maxDefinedConstant = std::max(constant.uboIdx, m_maxDefinedConstant); + } + + void DxsoCompiler::emitDefI(const DxsoInstructionContext& ctx) { + const int32_t* data = ctx.def.int32; + + uint32_t constId = m_module.constvec4i32(data[0], data[1], data[2], data[3]); + m_cInt.at(ctx.dst.id.num) = constId; + + std::string name = str::format("cI", ctx.dst.id.num, "_def"); + m_module.setDebugName(constId, name.c_str()); + } + + void DxsoCompiler::emitDefB(const DxsoInstructionContext& ctx) { + const int32_t* data = ctx.def.int32; + + uint32_t constId = m_module.constBool(data[0] != 0); + m_cBool.at(ctx.dst.id.num) = constId; + + std::string name = str::format("cB", ctx.dst.id.num, "_def"); + m_module.setDebugName(constId, name.c_str()); + } + + + bool DxsoCompiler::isScalarRegister(DxsoRegisterId id) { + return id == DxsoRegisterId{DxsoRegisterType::DepthOut, 0} + || id == DxsoRegisterId{DxsoRegisterType::RasterizerOut, RasterOutPointSize} + || id == DxsoRegisterId{DxsoRegisterType::RasterizerOut, RasterOutFog}; + } + + + void DxsoCompiler::emitMov(const DxsoInstructionContext& ctx) { + DxsoRegisterPointer dst = emitGetOperandPtr(ctx.dst); + + DxsoRegMask mask = ctx.dst.mask; + + if (isScalarRegister(ctx.dst.id)) + mask = DxsoRegMask(true, false, false, false); + + DxsoRegisterValue src0 = emitRegisterLoad(ctx.src[0], mask); + + DxsoRegisterValue result; + result.type.ctype = dst.type.ctype; + result.type.ccount = mask.popCount(); + + const uint32_t typeId = getVectorTypeId(result.type); + + if (dst.type.ctype != src0.type.ctype) { + // We have Mova for this... but it turns out Mov has the same behaviour in d3d9! + + // Convert float -> int32_t + // and vice versa + if (dst.type.ctype == DxsoScalarType::Sint32) { + // We need to floor for VS 1.1 and below, the documentation is a dirty stinking liar. + if (m_programInfo.majorVersion() < 2 && m_programInfo.minorVersion() < 2) + result.id = m_module.opFloor(getVectorTypeId(src0.type), src0.id); + else + result.id = m_module.opRound(getVectorTypeId(src0.type), src0.id); + + result.id = m_module.opConvertFtoS(typeId, result.id); + } + else // Float32 + result.id = m_module.opConvertStoF(typeId, src0.id); + } + else // No special stuff needed! + result.id = src0.id; + + this->emitDstStore(dst, result, mask, ctx.dst.saturate, emitPredicateLoad(ctx), ctx.dst.shift, ctx.dst.id); + } + + + void DxsoCompiler::emitVectorAlu(const DxsoInstructionContext& ctx) { + const auto& src = ctx.src; + + DxsoRegMask mask = ctx.dst.mask; + + DxsoRegisterPointer dst = emitGetOperandPtr(ctx.dst); + + if (isScalarRegister(ctx.dst.id)) + mask = DxsoRegMask(true, false, false, false); + + DxsoRegisterValue result; + result.type.ctype = dst.type.ctype; + result.type.ccount = mask.popCount(); + + DxsoVectorType scalarType = result.type; + scalarType.ccount = 1; + + const uint32_t typeId = getVectorTypeId(result.type); + const uint32_t scalarTypeId = getVectorTypeId(scalarType); + + const DxsoOpcode opcode = ctx.instruction.opcode; + switch (opcode) { + case DxsoOpcode::Add: + result.id = m_module.opFAdd(typeId, + emitRegisterLoad(src[0], mask).id, + emitRegisterLoad(src[1], mask).id); + break; + case DxsoOpcode::Sub: + result.id = m_module.opFSub(typeId, + emitRegisterLoad(src[0], mask).id, + emitRegisterLoad(src[1], mask).id); + break; + case DxsoOpcode::Mad: + if (!m_moduleInfo.options.longMad) { + result.id = emitFma( + emitRegisterLoad(src[0], mask), + emitRegisterLoad(src[1], mask), + emitRegisterLoad(src[2], mask)).id; + } + else { + result.id = emitMul( + emitRegisterLoad(src[0], mask), + emitRegisterLoad(src[1], mask)).id; + + result.id = m_module.opFAdd(typeId, + result.id, + emitRegisterLoad(src[2], mask).id); + } + break; + case DxsoOpcode::Mul: + result.id = emitMul( + emitRegisterLoad(src[0], mask), + emitRegisterLoad(src[1], mask)).id; + break; + case DxsoOpcode::Rcp: + result.id = m_module.opFDiv(typeId, + m_module.constfReplicant(1.0f, result.type.ccount), + emitRegisterLoad(src[0], mask).id); + + if (m_moduleInfo.options.d3d9FloatEmulation == D3D9FloatEmulation::Enabled) { + result.id = m_module.opNMin(typeId, result.id, + m_module.constfReplicant(FLT_MAX, result.type.ccount)); + } + break; + case DxsoOpcode::Rsq: + result.id = m_module.opFAbs(typeId, + emitRegisterLoad(src[0], mask).id); + + result.id = m_module.opInverseSqrt(typeId, + result.id); + + if (m_moduleInfo.options.d3d9FloatEmulation == D3D9FloatEmulation::Enabled) { + result.id = m_module.opNMin(typeId, result.id, + m_module.constfReplicant(FLT_MAX, result.type.ccount)); + } + break; + case DxsoOpcode::Dp3: { + DxsoRegMask srcMask(true, true, true, false); + result = emitDot( + emitRegisterLoad(src[0], srcMask), + emitRegisterLoad(src[1], srcMask)); + break; + } + case DxsoOpcode::Dp4: + result = emitDot( + emitRegisterLoad(src[0], IdentityWriteMask), + emitRegisterLoad(src[1], IdentityWriteMask)); + break; + case DxsoOpcode::Slt: + case DxsoOpcode::Sge: { + const uint32_t boolTypeId = + getVectorTypeId({ DxsoScalarType::Bool, result.type.ccount }); + + uint32_t cmpResult = opcode == DxsoOpcode::Slt + ? m_module.opFOrdLessThan (boolTypeId, emitRegisterLoad(src[0], mask).id, emitRegisterLoad(src[1], mask).id) + : m_module.opFOrdGreaterThanEqual(boolTypeId, emitRegisterLoad(src[0], mask).id, emitRegisterLoad(src[1], mask).id); + + result.id = m_module.opSelect(typeId, cmpResult, + m_module.constfReplicant(1.0f, result.type.ccount), + m_module.constfReplicant(0.0f, result.type.ccount)); + break; + } + case DxsoOpcode::Min: + result.id = m_module.opFMin(typeId, + emitRegisterLoad(src[0], mask).id, + emitRegisterLoad(src[1], mask).id); + break; + case DxsoOpcode::Max: + result.id = m_module.opFMax(typeId, + emitRegisterLoad(src[0], mask).id, + emitRegisterLoad(src[1], mask).id); + break; + case DxsoOpcode::ExpP: + if (m_programInfo.majorVersion() < 2) { + DxsoRegMask srcMask(true, false, false, false); + uint32_t src0 = emitRegisterLoad(src[0], srcMask).id; + + uint32_t index = 0; + + std::array resultIndices; + + if (mask[0]) resultIndices[index++] = m_module.opExp2(scalarTypeId, m_module.opFloor(scalarTypeId, src0)); + if (mask[1]) resultIndices[index++] = m_module.opFSub(scalarTypeId, src0, m_module.opFloor(scalarTypeId, src0)); + if (mask[2]) resultIndices[index++] = m_module.opExp2(scalarTypeId, src0); + if (mask[3]) resultIndices[index++] = m_module.constf32(1.0f); + + if (result.type.ccount == 1) + result.id = resultIndices[0]; + else + result.id = m_module.opCompositeConstruct(typeId, result.type.ccount, resultIndices.data()); + break; + } + [[fallthrough]]; + case DxsoOpcode::Exp: + result.id = m_module.opExp2(typeId, + emitRegisterLoad(src[0], mask).id); + break; + case DxsoOpcode::Pow: { + uint32_t base = emitRegisterLoad(src[0], mask).id; + base = m_module.opFAbs(typeId, base); + + uint32_t exponent = emitRegisterLoad(src[1], mask).id; + + result.id = m_module.opPow(typeId, base, exponent); + + if (m_moduleInfo.options.strictPow && m_moduleInfo.options.d3d9FloatEmulation != D3D9FloatEmulation::Disabled) { + DxsoRegisterValue cmp; + cmp.type = { DxsoScalarType::Bool, result.type.ccount }; + cmp.id = m_module.opFOrdEqual(getVectorTypeId(cmp.type), + exponent, m_module.constfReplicant(0.0f, cmp.type.ccount)); + + result.id = m_module.opSelect(typeId, cmp.id, + m_module.constfReplicant(1.0f, cmp.type.ccount), result.id); + } + break; + } + case DxsoOpcode::Crs: { + DxsoRegMask vec3Mask(true, true, true, false); + + DxsoRegisterValue crossValue = emitCross( + emitRegisterLoad(src[0], vec3Mask), + emitRegisterLoad(src[1], vec3Mask)); + + std::array indices = { 0, 0, 0 }; + + uint32_t index = 0; + for (uint32_t i = 0; i < indices.size(); i++) { + if (mask[i]) + indices[index++] = m_module.opCompositeExtract(m_module.defFloatType(32), crossValue.id, 1, &i); + } + + result.id = m_module.opCompositeConstruct(getVectorTypeId(result.type), result.type.ccount, indices.data()); + + break; + } + case DxsoOpcode::Abs: + result.id = m_module.opFAbs(typeId, + emitRegisterLoad(src[0], mask).id); + break; + case DxsoOpcode::Sgn: + result.id = m_module.opFSign(typeId, + emitRegisterLoad(src[0], mask).id); + break; + case DxsoOpcode::Nrm: { + // Nrm is 3D... + DxsoRegMask srcMask(true, true, true, false); + auto vec3 = emitRegisterLoad(src[0], srcMask); + + DxsoRegisterValue dot = emitDot(vec3, vec3); + dot.id = m_module.opInverseSqrt (scalarTypeId, dot.id); + if (m_moduleInfo.options.d3d9FloatEmulation == D3D9FloatEmulation::Enabled) { + dot.id = m_module.opNMin (scalarTypeId, dot.id, + m_module.constf32(FLT_MAX)); + } + + // r * rsq(r . r); + result.id = m_module.opVectorTimesScalar( + typeId, + emitRegisterLoad(src[0], mask).id, + dot.id); + break; + } + case DxsoOpcode::SinCos: { + DxsoRegMask srcMask(true, false, false, false); + uint32_t src0 = emitRegisterLoad(src[0], srcMask).id; + + std::array sincosVectorIndices = { 0, 0, 0, 0 }; + + uint32_t index = 0; + if (mask[0]) + sincosVectorIndices[index++] = m_module.opCos(scalarTypeId, src0); + + if (mask[1]) + sincosVectorIndices[index++] = m_module.opSin(scalarTypeId, src0); + + for (; index < result.type.ccount; index++) { + if (sincosVectorIndices[index] == 0) + sincosVectorIndices[index] = m_module.constf32(0.0f); + } + + if (result.type.ccount == 1) + result.id = sincosVectorIndices[0]; + else + result.id = m_module.opCompositeConstruct(typeId, result.type.ccount, sincosVectorIndices.data()); + + break; + } + case DxsoOpcode::Lit: { + DxsoRegMask srcMask(true, true, true, true); + uint32_t srcOp = emitRegisterLoad(src[0], srcMask).id; + + const uint32_t x = 0; + const uint32_t y = 1; + const uint32_t w = 3; + + uint32_t srcX = m_module.opCompositeExtract(scalarTypeId, srcOp, 1, &x); + uint32_t srcY = m_module.opCompositeExtract(scalarTypeId, srcOp, 1, &y); + uint32_t srcW = m_module.opCompositeExtract(scalarTypeId, srcOp, 1, &w); + + uint32_t power = m_module.opFClamp( + scalarTypeId, srcW, + m_module.constf32(-127.9961f), m_module.constf32(127.9961f)); + + std::array resultIndices; + + uint32_t index = 0; + + if (mask[0]) resultIndices[index++] = m_module.constf32(1.0f); + if (mask[1]) resultIndices[index++] = m_module.opFMax(scalarTypeId, srcX, m_module.constf32(0)); + if (mask[2]) resultIndices[index++] = m_module.opPow (scalarTypeId, m_module.opFMax(scalarTypeId, srcY, m_module.constf32(0)), power); + if (mask[3]) resultIndices[index++] = m_module.constf32(1.0f); + + const uint32_t boolType = m_module.defBoolType(); + uint32_t zTestX = m_module.opFOrdGreaterThanEqual(boolType, srcX, m_module.constf32(0)); + uint32_t zTestY = m_module.opFOrdGreaterThanEqual(boolType, srcY, m_module.constf32(0)); + uint32_t zTest = m_module.opLogicalAnd(boolType, zTestX, zTestY); + + if (result.type.ccount > 2) + resultIndices[2] = m_module.opSelect( + scalarTypeId, + zTest, + resultIndices[2], + m_module.constf32(0.0f)); + + if (result.type.ccount == 1) + result.id = resultIndices[0]; + else + result.id = m_module.opCompositeConstruct(typeId, result.type.ccount, resultIndices.data()); + break; + } + case DxsoOpcode::Dst: { + //dest.x = 1; + //dest.y = src0.y * src1.y; + //dest.z = src0.z; + //dest.w = src1.w; + + DxsoRegMask srcMask(true, true, true, true); + + uint32_t src0 = emitRegisterLoad(src[0], srcMask).id; + uint32_t src1 = emitRegisterLoad(src[1], srcMask).id; + + const uint32_t y = 1; + const uint32_t z = 2; + const uint32_t w = 3; + + DxsoRegisterValue src0Y = { scalarType, m_module.opCompositeExtract(scalarTypeId, src0, 1, &y) }; + DxsoRegisterValue src1Y = { scalarType, m_module.opCompositeExtract(scalarTypeId, src1, 1, &y) }; + + uint32_t src0Z = m_module.opCompositeExtract(scalarTypeId, src0, 1, &z); + uint32_t src1W = m_module.opCompositeExtract(scalarTypeId, src1, 1, &w); + + std::array resultIndices; + resultIndices[0] = m_module.constf32(1.0f); + resultIndices[1] = emitMul(src0Y, src1Y).id; + resultIndices[2] = src0Z; + resultIndices[3] = src1W; + + if (result.type.ccount == 1) + result.id = resultIndices[0]; + else + result.id = m_module.opCompositeConstruct(typeId, result.type.ccount, resultIndices.data()); + break; + } + case DxsoOpcode::LogP: + case DxsoOpcode::Log: + result.id = m_module.opFAbs(typeId, emitRegisterLoad(src[0], mask).id); + result.id = m_module.opLog2(typeId, result.id); + if (m_moduleInfo.options.d3d9FloatEmulation == D3D9FloatEmulation::Enabled) { + result.id = m_module.opNMax(typeId, result.id, + m_module.constfReplicant(-FLT_MAX, result.type.ccount)); + } + break; + case DxsoOpcode::Lrp: + result.id = emitMix( + emitRegisterLoad(src[2], mask), + emitRegisterLoad(src[1], mask), + emitRegisterLoad(src[0], mask)).id; + break; + case DxsoOpcode::Frc: + result.id = m_module.opFract(typeId, + emitRegisterLoad(src[0], mask).id); + break; + case DxsoOpcode::Cmp: { + const uint32_t boolTypeId = + getVectorTypeId({ DxsoScalarType::Bool, result.type.ccount }); + + uint32_t cmp = m_module.opFOrdGreaterThanEqual( + boolTypeId, + emitRegisterLoad(src[0], mask).id, + m_module.constfReplicant(0.0f, result.type.ccount)); + + result.id = m_module.opSelect( + typeId, cmp, + emitRegisterLoad(src[1], mask).id, + emitRegisterLoad(src[2], mask).id); + break; + } + case DxsoOpcode::Cnd: { + const uint32_t boolTypeId = + getVectorTypeId({ DxsoScalarType::Bool, result.type.ccount }); + + uint32_t cmp = m_module.opFOrdGreaterThan( + boolTypeId, + emitRegisterLoad(src[0], mask).id, + m_module.constfReplicant(0.5f, result.type.ccount)); + + result.id = m_module.opSelect( + typeId, cmp, + emitRegisterLoad(src[1], mask).id, + emitRegisterLoad(src[2], mask).id); + break; + } + case DxsoOpcode::Dp2Add: { + DxsoRegMask dotSrcMask(true, true, false, false); + DxsoRegMask addSrcMask(true, false, false, false); + + DxsoRegisterValue dot = emitDot( + emitRegisterLoad(src[0], dotSrcMask), + emitRegisterLoad(src[1], dotSrcMask)); + + dot.id = m_module.opFAdd(scalarTypeId, + dot.id, emitRegisterLoad(src[2], addSrcMask).id); + + result.id = dot.id; + result.type = scalarType; + break; + } + case DxsoOpcode::DsX: + result.id = m_module.opDpdx( + typeId, emitRegisterLoad(src[0], mask).id); + break; + case DxsoOpcode::DsY: + result.id = m_module.opDpdy( + typeId, emitRegisterLoad(src[0], mask).id); + break; + default: + Logger::warn(str::format("DxsoCompiler::emitVectorAlu: unimplemented op ", opcode)); + return; + } + + this->emitDstStore(dst, result, mask, ctx.dst.saturate, emitPredicateLoad(ctx), ctx.dst.shift, ctx.dst.id); + } + + + void DxsoCompiler::emitPredicateOp(const DxsoInstructionContext& ctx) { + const auto& src = ctx.src; + + DxsoRegMask mask = ctx.dst.mask; + + DxsoRegisterPointer dst = emitGetOperandPtr(ctx.dst); + + DxsoRegisterValue result; + result.type.ctype = dst.type.ctype; + result.type.ccount = mask.popCount(); + + result.id = emitBoolComparison( + result.type, ctx.instruction.specificData.comparison, + emitRegisterLoad(src[0], mask).id, emitRegisterLoad(src[1], mask).id); + + this->emitValueStore(dst, result, mask, emitPredicateLoad(ctx)); + } + + + void DxsoCompiler::emitMatrixAlu(const DxsoInstructionContext& ctx) { + const DxsoOpcode opcode = ctx.instruction.opcode; + + uint32_t dotCount; + uint32_t componentCount; + + switch (opcode) { + case DxsoOpcode::M3x2: + dotCount = 3; + componentCount = 2; + break; + case DxsoOpcode::M3x3: + dotCount = 3; + componentCount = 3; + break; + case DxsoOpcode::M3x4: + dotCount = 3; + componentCount = 4; + break; + case DxsoOpcode::M4x3: + dotCount = 4; + componentCount = 3; + break; + case DxsoOpcode::M4x4: + dotCount = 4; + componentCount = 4; + break; + default: + Logger::warn(str::format("DxsoCompiler::emitMatrixAlu: unimplemented op ", opcode)); + return; + } + + DxsoRegisterPointer dst = emitGetOperandPtr(ctx.dst); + + // Fix the dst mask if componentCount != maskCount + // ie. M4x3 on .xyzw. + uint32_t maskCnt = 0; + uint8_t mask = 0; + for (uint32_t i = 0; i < 4 && maskCnt < componentCount; i++) { + if (ctx.dst.mask[i]) { + mask |= 1 << i; + maskCnt++; + } + } + DxsoRegMask dstMask = DxsoRegMask(mask); + + DxsoRegisterValue result; + result.type.ctype = dst.type.ctype; + result.type.ccount = componentCount; + + const uint32_t typeId = getVectorTypeId(result.type); + + DxsoRegMask srcMask(true, true, true, dotCount == 4); + std::array indices; + + DxsoRegister src0 = ctx.src[0]; + DxsoRegister src1 = ctx.src[1]; + + for (uint32_t i = 0; i < componentCount; i++) { + indices[i] = emitDot( + emitRegisterLoad(src0, srcMask), + emitRegisterLoad(src1, srcMask)).id; + + src1.id.num++; + } + + result.id = m_module.opCompositeConstruct( + typeId, componentCount, indices.data()); + + this->emitDstStore(dst, result, dstMask, ctx.dst.saturate, emitPredicateLoad(ctx), ctx.dst.shift, ctx.dst.id); + } + + +void DxsoCompiler::emitControlFlowGenericLoop( + bool count, + uint32_t initialVar, + uint32_t strideVar, + uint32_t iterationCountVar) { + const uint32_t itType = m_module.defIntType(32, 1); + + DxsoCfgBlock block; + block.type = DxsoCfgBlockType::Loop; + block.b_loop.labelHeader = m_module.allocateId(); + block.b_loop.labelBegin = m_module.allocateId(); + block.b_loop.labelContinue = m_module.allocateId(); + block.b_loop.labelBreak = m_module.allocateId(); + block.b_loop.iteratorPtr = m_module.newVar( + m_module.defPointerType(itType, spv::StorageClassPrivate), spv::StorageClassPrivate); + block.b_loop.strideVar = strideVar; + block.b_loop.countBackup = 0; + + if (count) { + DxsoBaseRegister loop; + loop.id = { DxsoRegisterType::Loop, 0 }; + + DxsoRegisterPointer loopPtr = emitGetOperandPtr(loop, nullptr); + uint32_t loopVal = m_module.opLoad( + getVectorTypeId(loopPtr.type), loopPtr.id); + + block.b_loop.countBackup = loopVal; + + m_module.opStore(loopPtr.id, initialVar); + } + + m_module.setDebugName(block.b_loop.iteratorPtr, "iter"); + + m_module.opStore(block.b_loop.iteratorPtr, iterationCountVar); + + m_module.opBranch(block.b_loop.labelHeader); + m_module.opLabel (block.b_loop.labelHeader); + + m_module.opLoopMerge( + block.b_loop.labelBreak, + block.b_loop.labelContinue, + spv::LoopControlMaskNone); + + m_module.opBranch(block.b_loop.labelBegin); + m_module.opLabel (block.b_loop.labelBegin); + + uint32_t iterator = m_module.opLoad(itType, block.b_loop.iteratorPtr); + uint32_t complete = m_module.opIEqual(m_module.defBoolType(), iterator, m_module.consti32(0)); + + const uint32_t breakBlock = m_module.allocateId(); + const uint32_t mergeBlock = m_module.allocateId(); + + m_module.opSelectionMerge(mergeBlock, + spv::SelectionControlMaskNone); + + m_module.opBranchConditional( + complete, breakBlock, mergeBlock); + + m_module.opLabel(breakBlock); + + m_module.opBranch(block.b_loop.labelBreak); + + m_module.opLabel(mergeBlock); + + iterator = m_module.opISub(itType, iterator, m_module.consti32(1)); + m_module.opStore(block.b_loop.iteratorPtr, iterator); + + m_controlFlowBlocks.push_back(block); + } + + void DxsoCompiler::emitControlFlowGenericLoopEnd() { + if (m_controlFlowBlocks.size() == 0 + || m_controlFlowBlocks.back().type != DxsoCfgBlockType::Loop) + throw DxvkError("DxsoCompiler: 'EndRep' without 'Rep' or 'Loop' found"); + + // Remove the block from the stack, it's closed + const DxsoCfgBlock block = m_controlFlowBlocks.back(); + m_controlFlowBlocks.pop_back(); + + if (block.b_loop.strideVar) { + DxsoBaseRegister loop; + loop.id = { DxsoRegisterType::Loop, 0 }; + + DxsoRegisterPointer loopPtr = emitGetOperandPtr(loop, nullptr); + uint32_t val = m_module.opLoad( + getVectorTypeId(loopPtr.type), loopPtr.id); + + val = m_module.opIAdd( + getVectorTypeId(loopPtr.type), + val, block.b_loop.strideVar); + + m_module.opStore(loopPtr.id, val); + } + + // Declare the continue block + m_module.opBranch(block.b_loop.labelContinue); + m_module.opLabel(block.b_loop.labelContinue); + + // Declare the merge block + m_module.opBranch(block.b_loop.labelHeader); + m_module.opLabel(block.b_loop.labelBreak); + + if (block.b_loop.countBackup) { + DxsoBaseRegister loop; + loop.id = { DxsoRegisterType::Loop, 0 }; + + DxsoRegisterPointer loopPtr = emitGetOperandPtr(loop, nullptr); + + m_module.opStore(loopPtr.id, block.b_loop.countBackup); + } + } + + void DxsoCompiler::emitControlFlowRep(const DxsoInstructionContext& ctx) { + DxsoRegMask srcMask(true, false, false, false); + this->emitControlFlowGenericLoop( + false, 0, 0, + emitRegisterLoad(ctx.src[0], srcMask).id); + } + + void DxsoCompiler::emitControlFlowEndRep(const DxsoInstructionContext& ctx) { + emitControlFlowGenericLoopEnd(); + } + + void DxsoCompiler::emitControlFlowLoop(const DxsoInstructionContext& ctx) { + const uint32_t itType = m_module.defIntType(32, 1); + + DxsoRegMask srcMask(true, true, true, false); + uint32_t integerRegister = emitRegisterLoad(ctx.src[1], srcMask).id; + uint32_t x = 0; + uint32_t y = 1; + uint32_t z = 2; + + uint32_t iterCount = m_module.opCompositeExtract(itType, integerRegister, 1, &x); + uint32_t initialValue = m_module.opCompositeExtract(itType, integerRegister, 1, &y); + uint32_t strideSize = m_module.opCompositeExtract(itType, integerRegister, 1, &z); + + this->emitControlFlowGenericLoop( + true, + initialValue, + strideSize, + iterCount); + } + + void DxsoCompiler::emitControlFlowEndLoop(const DxsoInstructionContext& ctx) { + this->emitControlFlowGenericLoopEnd(); + } + + void DxsoCompiler::emitControlFlowBreak(const DxsoInstructionContext& ctx) { + DxsoCfgBlock* cfgBlock = + cfgFindBlock({ DxsoCfgBlockType::Loop }); + + if (cfgBlock == nullptr) + throw DxvkError("DxbcCompiler: 'Break' outside 'Rep' or 'Loop' found"); + + m_module.opBranch(cfgBlock->b_loop.labelBreak); + + // Subsequent instructions assume that there is an open block + const uint32_t labelId = m_module.allocateId(); + m_module.opLabel(labelId); + } + + void DxsoCompiler::emitControlFlowBreakC(const DxsoInstructionContext& ctx) { + DxsoCfgBlock* cfgBlock = + cfgFindBlock({ DxsoCfgBlockType::Loop }); + + if (cfgBlock == nullptr) + throw DxvkError("DxbcCompiler: 'BreakC' outside 'Rep' or 'Loop' found"); + + DxsoRegMask srcMask(true, false, false, false); + auto a = emitRegisterLoad(ctx.src[0], srcMask); + auto b = emitRegisterLoad(ctx.src[1], srcMask); + + uint32_t result = this->emitBoolComparison( + { DxsoScalarType::Bool, a.type.ccount }, + ctx.instruction.specificData.comparison, + a.id, b.id); + + // We basically have to wrap this into an 'if' block + const uint32_t breakBlock = m_module.allocateId(); + const uint32_t mergeBlock = m_module.allocateId(); + + m_module.opSelectionMerge(mergeBlock, + spv::SelectionControlMaskNone); + + m_module.opBranchConditional( + result, breakBlock, mergeBlock); + + m_module.opLabel(breakBlock); + + m_module.opBranch(cfgBlock->b_loop.labelBreak); + + m_module.opLabel(mergeBlock); + } + + void DxsoCompiler::emitControlFlowIf(const DxsoInstructionContext& ctx) { + const auto opcode = ctx.instruction.opcode; + + uint32_t result; + + DxsoRegMask srcMask(true, false, false, false); + if (opcode == DxsoOpcode::Ifc) { + auto a = emitRegisterLoad(ctx.src[0], srcMask); + auto b = emitRegisterLoad(ctx.src[1], srcMask); + + result = this->emitBoolComparison( + { DxsoScalarType::Bool, a.type.ccount }, + ctx.instruction.specificData.comparison, + a.id, b.id); + } else + result = emitRegisterLoad(ctx.src[0], srcMask).id; + + // Declare the 'if' block. We do not know if there + // will be an 'else' block or not, so we'll assume + // that there is one and leave it empty otherwise. + DxsoCfgBlock block; + block.type = DxsoCfgBlockType::If; + block.b_if.ztestId = result; + block.b_if.labelIf = m_module.allocateId(); + block.b_if.labelElse = 0; + block.b_if.labelEnd = m_module.allocateId(); + block.b_if.headerPtr = m_module.getInsertionPtr(); + m_controlFlowBlocks.push_back(block); + + // We'll insert the branch instruction when closing + // the block, since we don't know whether or not an + // else block is needed right now. + m_module.opLabel(block.b_if.labelIf); + } + + void DxsoCompiler::emitControlFlowElse(const DxsoInstructionContext& ctx) { + if (m_controlFlowBlocks.size() == 0 + || m_controlFlowBlocks.back().type != DxsoCfgBlockType::If + || m_controlFlowBlocks.back().b_if.labelElse != 0) + throw DxvkError("DxsoCompiler: 'Else' without 'If' found"); + + // Set the 'Else' flag so that we do + // not insert a dummy block on 'EndIf' + DxsoCfgBlock& block = m_controlFlowBlocks.back(); + block.b_if.labelElse = m_module.allocateId(); + + // Close the 'If' block by branching to + // the merge block we declared earlier + m_module.opBranch(block.b_if.labelEnd); + m_module.opLabel (block.b_if.labelElse); + } + + void DxsoCompiler::emitControlFlowEndIf(const DxsoInstructionContext& ctx) { + if (m_controlFlowBlocks.size() == 0 + || m_controlFlowBlocks.back().type != DxsoCfgBlockType::If) + throw DxvkError("DxsoCompiler: 'EndIf' without 'If' found"); + + // Remove the block from the stack, it's closed + DxsoCfgBlock block = m_controlFlowBlocks.back(); + m_controlFlowBlocks.pop_back(); + + // Write out the 'if' header + m_module.beginInsertion(block.b_if.headerPtr); + + m_module.opSelectionMerge( + block.b_if.labelEnd, + spv::SelectionControlMaskNone); + + m_module.opBranchConditional( + block.b_if.ztestId, + block.b_if.labelIf, + block.b_if.labelElse != 0 + ? block.b_if.labelElse + : block.b_if.labelEnd); + + m_module.endInsertion(); + + // End the active 'if' or 'else' block + m_module.opBranch(block.b_if.labelEnd); + m_module.opLabel (block.b_if.labelEnd); + } + + + void DxsoCompiler::emitTexCoord(const DxsoInstructionContext& ctx) { + DxsoRegisterValue result; + + if (m_programInfo.majorVersion() == 1 && m_programInfo.minorVersion() == 4) { + // TexCrd Op (PS 1.4) + result = emitRegisterLoad(ctx.src[0], ctx.dst.mask); + } else { + // TexCoord Op (PS 1.0 - PS 1.3) + DxsoRegister texcoord; + texcoord.id.type = DxsoRegisterType::PixelTexcoord; + texcoord.id.num = ctx.dst.id.num; + + result = emitRegisterLoadRaw(texcoord, nullptr); + // Saturate + result = emitSaturate(result); + // w = 1.0f + uint32_t wIndex = 3; + result.id = m_module.opCompositeInsert(getVectorTypeId(result.type), + m_module.constf32(1.0f), + result.id, + 1, &wIndex); + } + + DxsoRegisterPointer dst = emitGetOperandPtr(ctx.dst); + + this->emitDstStore(dst, result, ctx.dst.mask, ctx.dst.saturate, emitPredicateLoad(ctx), ctx.dst.shift, ctx.dst.id); + } + + void DxsoCompiler::emitTextureSample(const DxsoInstructionContext& ctx) { + DxsoRegisterPointer dst = emitGetOperandPtr(ctx.dst); + + const DxsoOpcode opcode = ctx.instruction.opcode; + + DxsoRegisterValue texcoordVar; + uint32_t samplerIdx; + + DxsoRegMask vec3Mask(true, true, true, false); + DxsoRegMask srcMask (true, true, true, true); + + auto GetProjectionValue = [&]() { + uint32_t w = 3; + return m_module.opCompositeExtract( + m_module.defFloatType(32), texcoordVar.id, 1, &w); + }; + + if (opcode == DxsoOpcode::TexM3x2Tex || opcode == DxsoOpcode::TexM3x3Tex || opcode == DxsoOpcode::TexM3x3Spec || opcode == DxsoOpcode::TexM3x3VSpec) { + const uint32_t count = opcode == DxsoOpcode::TexM3x2Tex ? 2 : 3; + + auto n = emitRegisterLoad(ctx.src[0], vec3Mask); + + std::array indices = { 0, 0, m_module.constf32(0.0f), m_module.constf32(0.0f) }; + for (uint32_t i = 0; i < count; i++) { + auto reg = ctx.dst; + reg.id.num -= (count - 1) - i; + auto m = emitRegisterLoadTexcoord(reg, vec3Mask); + + indices[i] = emitDot(m, n).id; + } + + if (opcode == DxsoOpcode::TexM3x3Spec || opcode == DxsoOpcode::TexM3x3VSpec) { + uint32_t vec3Type = getVectorTypeId({ DxsoScalarType::Float32, 3 }); + uint32_t normal = m_module.opCompositeConstruct(vec3Type, 3, indices.data()); + + uint32_t eyeRay; + // VSpec -> Create eye ray from .w of last 3 tex coords (m, m-1, m-2) + // Spec -> Get eye ray from src[1] + if (opcode == DxsoOpcode::TexM3x3VSpec) { + DxsoRegMask wMask(false, false, false, true); + + std::array eyeRayIndices; + for (uint32_t i = 0; i < 3; i++) { + auto reg = ctx.dst; + reg.id.num -= (count - 1) - i; + eyeRayIndices[i] = emitRegisterLoadTexcoord(reg, wMask).id; + } + + eyeRay = m_module.opCompositeConstruct(vec3Type, eyeRayIndices.size(), eyeRayIndices.data()); + } + else + eyeRay = emitRegisterLoad(ctx.src[1], vec3Mask).id; + + eyeRay = m_module.opNormalize(vec3Type, eyeRay); + normal = m_module.opNormalize(vec3Type, normal); + uint32_t reflection = m_module.opReflect(vec3Type, eyeRay, normal); + reflection = m_module.opFNegate(vec3Type, reflection); + + for (uint32_t i = 0; i < 3; i++) + indices[i] = m_module.opCompositeExtract(m_module.defFloatType(32), reflection, 1, &i); + } + + texcoordVar.type = { DxsoScalarType::Float32, 4 }; + texcoordVar.id = m_module.opCompositeConstruct(getVectorTypeId(texcoordVar.type), indices.size(), indices.data()); + + samplerIdx = ctx.dst.id.num; + } + else if (opcode == DxsoOpcode::TexBem || opcode == DxsoOpcode::TexBemL) { + auto m = emitRegisterLoadTexcoord(ctx.dst, srcMask); + auto n = emitRegisterLoad(ctx.src[0], srcMask); + + texcoordVar = m; + samplerIdx = ctx.dst.id.num; + + uint32_t texcoord_t = getVectorTypeId(texcoordVar.type); + + // The projection (/.w) happens before this... + // Of course it does... + uint32_t bool_t = m_module.defBoolType(); + + uint32_t shouldProj = m_module.opBitFieldUExtract( + m_module.defIntType(32, 0), m_ps.projectionSpec, + m_module.consti32(samplerIdx), m_module.consti32(1)); + + shouldProj = m_module.opIEqual(bool_t, shouldProj, m_module.constu32(1)); + + uint32_t bvec4_t = m_module.defVectorType(bool_t, 4); + std::array indices = { shouldProj, shouldProj, shouldProj, shouldProj }; + shouldProj = m_module.opCompositeConstruct(bvec4_t, indices.size(), indices.data()); + + uint32_t projScalar = m_module.opFDiv(m_module.defFloatType(32), m_module.constf32(1.0), GetProjectionValue()); + uint32_t projResult = m_module.opVectorTimesScalar(texcoord_t, texcoordVar.id, projScalar); + + texcoordVar.id = m_module.opSelect(texcoord_t, shouldProj, projResult, texcoordVar.id); + + // u' = tc(m).x + [bm00(m) * t(n).x + bm10(m) * t(n).y] + // v' = tc(m).y + [bm01(m) * t(n).x + bm11(m) * t(n).y] + + // But we flipped the bm indices so we can use dot here... + + // u' = tc(m).x + dot(bm0, tn) + // v' = tc(m).y + dot(bm1, tn) + + for (uint32_t i = 0; i < 2; i++) { + uint32_t fl_t = getScalarTypeId(DxsoScalarType::Float32); + uint32_t vec2_t = getVectorTypeId({ DxsoScalarType::Float32, 2 }); + std::array indices = { 0, 1, 2, 3 }; + + uint32_t tc_m_n = m_module.opCompositeExtract(fl_t, texcoordVar.id, 1, &i); + + uint32_t offset = m_module.constu32(D3D9SharedPSStages_Count * ctx.dst.id.num + D3D9SharedPSStages_BumpEnvMat0 + i); + uint32_t bm = m_module.opAccessChain(m_module.defPointerType(vec2_t, spv::StorageClassUniform), + m_ps.sharedState, 1, &offset); + bm = m_module.opLoad(vec2_t, bm); + + uint32_t t = m_module.opVectorShuffle(vec2_t, n.id, n.id, 2, indices.data()); + + uint32_t dot = m_module.opDot(fl_t, bm, t); + + uint32_t result = m_module.opFAdd(fl_t, tc_m_n, dot); + texcoordVar.id = m_module.opCompositeInsert(getVectorTypeId(texcoordVar.type), result, texcoordVar.id, 1, &i); + } + } + else if (opcode == DxsoOpcode::TexReg2Ar) { + texcoordVar = emitRegisterLoad(ctx.src[0], srcMask); + texcoordVar = emitRegisterSwizzle(texcoordVar, DxsoRegSwizzle(3, 0, 0, 0), srcMask); + + samplerIdx = ctx.dst.id.num; + } + else if (opcode == DxsoOpcode::TexReg2Gb) { + texcoordVar = emitRegisterLoad(ctx.src[0], srcMask); + texcoordVar = emitRegisterSwizzle(texcoordVar, DxsoRegSwizzle(1, 2, 2, 2), srcMask); + + samplerIdx = ctx.dst.id.num; + } + else if (opcode == DxsoOpcode::TexReg2Rgb) { + texcoordVar = emitRegisterLoad(ctx.src[0], srcMask); + texcoordVar = emitRegisterSwizzle(texcoordVar, DxsoRegSwizzle(0, 1, 2, 2), srcMask); + + samplerIdx = ctx.dst.id.num; + } + else if (opcode == DxsoOpcode::TexDp3Tex) { + auto m = emitRegisterLoadTexcoord(ctx.dst, vec3Mask); + auto n = emitRegisterLoad(ctx.src[0], vec3Mask); + + auto dot = emitDot(m, n); + + std::array indices = { dot.id, m_module.constf32(0.0f), m_module.constf32(0.0f), m_module.constf32(0.0f) }; + + texcoordVar.type = { DxsoScalarType::Float32, 4 }; + texcoordVar.id = m_module.opCompositeConstruct(getVectorTypeId(texcoordVar.type), + indices.size(), indices.data()); + + samplerIdx = ctx.dst.id.num; + } + else { + if (m_programInfo.majorVersion() >= 2) { // SM 2.0+ + texcoordVar = emitRegisterLoad(ctx.src[0], srcMask); + samplerIdx = ctx.src[1].id.num; + } else if ( + m_programInfo.majorVersion() == 1 + && m_programInfo.minorVersion() == 4) { // SM 1.4 + texcoordVar = emitRegisterLoad(ctx.src[0], srcMask); + samplerIdx = ctx.dst.id.num; + } + else { // SM 1.0-1.3 + texcoordVar = emitRegisterLoadTexcoord(ctx.dst, srcMask); + samplerIdx = ctx.dst.id.num; + } + } + + // SM < 1.x does not have dcl sampler type. + if (m_programInfo.majorVersion() < 2 && m_samplers[samplerIdx].color[SamplerTypeTexture2D].varId == 0) + emitDclSampler(samplerIdx, DxsoTextureType::Texture2D); + + DxsoSampler sampler = m_samplers.at(samplerIdx); + + auto SampleImage = [this, opcode, dst, ctx, samplerIdx, GetProjectionValue](DxsoRegisterValue texcoordVar, DxsoSamplerInfo& sampler, bool depth, DxsoSamplerType samplerType, uint32_t specConst) { + DxsoRegisterValue result; + result.type.ctype = dst.type.ctype; + result.type.ccount = depth ? 1 : 4; + + const uint32_t typeId = getVectorTypeId(result.type); + + SpirvImageOperands imageOperands; + if (m_programInfo.type() == DxsoProgramTypes::VertexShader) { + imageOperands.sLod = m_module.constf32(0.0f); + imageOperands.flags |= spv::ImageOperandsLodMask; + } + + if (opcode == DxsoOpcode::TexLdl) { + uint32_t w = 3; + imageOperands.sLod = m_module.opCompositeExtract( + m_module.defFloatType(32), texcoordVar.id, 1, &w); + imageOperands.flags |= spv::ImageOperandsLodMask; + } + + if (opcode == DxsoOpcode::TexLdd) { + DxsoRegMask gradMask(true, true, sampler.dimensions == 3, false); + imageOperands.flags |= spv::ImageOperandsGradMask; + imageOperands.sGradX = emitRegisterLoad(ctx.src[2], gradMask).id; + imageOperands.sGradY = emitRegisterLoad(ctx.src[3], gradMask).id; + } + + uint32_t projDivider = 0; + + if (opcode == DxsoOpcode::Tex + && m_programInfo.majorVersion() >= 2) { + if (ctx.instruction.specificData.texld == DxsoTexLdMode::Project) { + projDivider = GetProjectionValue(); + } + else if (ctx.instruction.specificData.texld == DxsoTexLdMode::Bias) { + uint32_t w = 3; + imageOperands.sLodBias = m_module.opCompositeExtract( + m_module.defFloatType(32), texcoordVar.id, 1, &w); + imageOperands.flags |= spv::ImageOperandsBiasMask; + } + } + + bool switchProjResult = m_programInfo.majorVersion() < 2 && samplerType != SamplerTypeTextureCube; + + if (switchProjResult) + projDivider = GetProjectionValue(); + + // We already handled this... + if (opcode == DxsoOpcode::TexBem) { + switchProjResult = false; + projDivider = 0; + } + + uint32_t reference = 0; + + if (depth) { + uint32_t component = sampler.dimensions; + reference = m_module.opCompositeExtract( + m_module.defFloatType(32), texcoordVar.id, 1, &component); + } + + if (projDivider != 0) { + for (uint32_t i = sampler.dimensions; i < 4; i++) { + texcoordVar.id = m_module.opCompositeInsert(getVectorTypeId(texcoordVar.type), + projDivider, texcoordVar.id, 1, &i); + } + } + + uint32_t fetch4 = 0; + if (m_programInfo.type() == DxsoProgramType::PixelShader && samplerType != SamplerTypeTexture3D) { + fetch4 = m_module.opBitFieldUExtract( + m_module.defIntType(32, 0), m_ps.fetch4Spec, + m_module.consti32(samplerIdx), m_module.consti32(1)); + + uint32_t bool_t = m_module.defBoolType(); + fetch4 = m_module.opIEqual(bool_t, fetch4, m_module.constu32(1)); + + uint32_t bvec4_t = m_module.defVectorType(bool_t, 4); + std::array indices = { fetch4, fetch4, fetch4, fetch4 }; + fetch4 = m_module.opCompositeConstruct(bvec4_t, indices.size(), indices.data()); + } + + result.id = this->emitSample( + projDivider != 0, + typeId, + sampler, + texcoordVar, + reference, + fetch4, + imageOperands); + + if (switchProjResult) { + uint32_t bool_t = m_module.defBoolType(); + + uint32_t nonProjResult = this->emitSample( + 0, + typeId, + sampler, + texcoordVar, + reference, + fetch4, + imageOperands); + + uint32_t shouldProj = m_module.opBitFieldUExtract( + m_module.defIntType(32, 0), m_ps.projectionSpec, + m_module.consti32(samplerIdx), m_module.consti32(1)); + + shouldProj = m_module.opIEqual(m_module.defBoolType(), shouldProj, m_module.constu32(1)); + + // Depth -> .x + // Colour -> .xyzw + // Need to replicate the bool for the opSelect. + if (!depth) { + uint32_t bvec4_t = m_module.defVectorType(bool_t, 4); + std::array indices = { shouldProj, shouldProj, shouldProj, shouldProj }; + shouldProj = m_module.opCompositeConstruct(bvec4_t, indices.size(), indices.data()); + } + + result.id = m_module.opSelect(typeId, shouldProj, result.id, nonProjResult); + } + + // If we are sampling depth we've already specc'ed this! + // This path is always size 4 because it only hits on color. + if (specConst != 0) { + uint32_t bool_t = m_module.defBoolType(); + uint32_t bvec4_t = m_module.defVectorType(bool_t, 4); + std::array indices = { specConst, specConst, specConst, specConst }; + specConst = m_module.opCompositeConstruct(bvec4_t, indices.size(), indices.data()); + result.id = m_module.opSelect(typeId, specConst, result.id, m_module.constvec4f32(0.0f, 0.0f, 0.0f, 1.0f)); + } + + // Apply operand swizzle to the operand value + if (m_programInfo.majorVersion() >= 2) // SM 2.0+ + result = emitRegisterSwizzle(result, ctx.src[1].swizzle, ctx.dst.mask); + else + result = emitRegisterSwizzle(result, IdentitySwizzle, ctx.dst.mask); + + if (opcode == DxsoOpcode::TexBemL) { + uint32_t float_t = m_module.defFloatType(32); + + uint32_t index = m_module.constu32(D3D9SharedPSStages_Count * ctx.dst.id.num + D3D9SharedPSStages_BumpEnvLScale); + uint32_t lScale = m_module.opAccessChain(m_module.defPointerType(float_t, spv::StorageClassUniform), + m_ps.sharedState, 1, &index); + lScale = m_module.opLoad(float_t, lScale); + + index = m_module.constu32(D3D9SharedPSStages_Count * ctx.dst.id.num + D3D9SharedPSStages_BumpEnvLOffset); + uint32_t lOffset = m_module.opAccessChain(m_module.defPointerType(float_t, spv::StorageClassUniform), + m_ps.sharedState, 1, &index); + lOffset = m_module.opLoad(float_t, lOffset); + + uint32_t zIndex = 2; + uint32_t scale = m_module.opCompositeExtract(float_t, result.id, 1, &zIndex); + scale = m_module.opFMul(float_t, scale, lScale); + scale = m_module.opFAdd(float_t, scale, lOffset); + scale = m_module.opFClamp(float_t, scale, m_module.constf32(0.0f), m_module.constf32(1.0)); + + result.id = m_module.opVectorTimesScalar(getVectorTypeId(result.type), result.id, scale); + } + + this->emitDstStore(dst, result, ctx.dst.mask, ctx.dst.saturate, emitPredicateLoad(ctx), ctx.dst.shift, ctx.dst.id); + }; + + auto SampleType = [&](DxsoSamplerType samplerType) { + // Only do the check for depth comp. samplers + // if we aren't a 3D texture + if (samplerType != SamplerTypeTexture3D) { + uint32_t colorLabel = m_module.allocateId(); + uint32_t depthLabel = m_module.allocateId(); + uint32_t endLabel = m_module.allocateId(); + + uint32_t typeId = m_module.defIntType(32, 0); + uint32_t offset = m_module.consti32(m_programInfo.type() == DxsoProgramTypes::VertexShader ? samplerIdx + 17 : samplerIdx); + uint32_t bitCnt = m_module.consti32(1); + uint32_t isDepth = m_module.opBitFieldUExtract(typeId, m_depthSpecConstant, offset, bitCnt); + isDepth = m_module.opIEqual(m_module.defBoolType(), isDepth, m_module.constu32(1)); + + m_module.opSelectionMerge(endLabel, spv::SelectionControlMaskNone); + m_module.opBranchConditional(isDepth, depthLabel, colorLabel); + + m_module.opLabel(colorLabel); + SampleImage(texcoordVar, sampler.color[samplerType], false, samplerType, sampler.boundConst); + m_module.opBranch(endLabel); + + m_module.opLabel(depthLabel); + // No spec constant as if we are unbound we always fall down the color path. + SampleImage(texcoordVar, sampler.depth[samplerType], true, samplerType, 0); + m_module.opBranch(endLabel); + + m_module.opLabel(endLabel); + } + else + SampleImage(texcoordVar, sampler.color[samplerType], false, samplerType, sampler.boundConst); + }; + + if (m_programInfo.majorVersion() >= 2 && !m_moduleInfo.options.forceSamplerTypeSpecConstants) { + DxsoSamplerType samplerType = + SamplerTypeFromTextureType(sampler.type); + + SampleType(samplerType); + } + else { + std::array typeCaseLabels = {{ + { uint32_t(SamplerTypeTexture2D), m_module.allocateId() }, + { uint32_t(SamplerTypeTexture3D), m_module.allocateId() }, + { uint32_t(SamplerTypeTextureCube), m_module.allocateId() }, + }}; + + uint32_t switchEndLabel = m_module.allocateId(); + + uint32_t typeId = m_module.defIntType(32, 0); + + uint32_t offset = m_module.consti32(samplerIdx * 2); + uint32_t bitCnt = m_module.consti32(2); + uint32_t type = m_module.opBitFieldUExtract(typeId, m_ps.samplerTypeSpec, offset, bitCnt); + + m_module.opSelectionMerge(switchEndLabel, spv::SelectionControlMaskNone); + m_module.opSwitch(type, + typeCaseLabels[uint32_t(SamplerTypeTexture2D)].labelId, + typeCaseLabels.size(), + typeCaseLabels.data()); + + for (const auto& label : typeCaseLabels) { + m_module.opLabel(label.labelId); + + SampleType(DxsoSamplerType(label.literal)); + + m_module.opBranch(switchEndLabel); + } + + m_module.opLabel(switchEndLabel); + } + } + + void DxsoCompiler::emitTextureKill(const DxsoInstructionContext& ctx) { + DxsoRegisterValue texReg; + + if (m_programInfo.majorVersion() >= 2 || + (m_programInfo.majorVersion() == 1 + && m_programInfo.minorVersion() == 4)) // SM 2.0+ or 1.4 + texReg = emitRegisterLoadRaw(ctx.dst, ctx.dst.hasRelative ? &ctx.dst.relative : nullptr); + else { // SM 1.0-1.3 + DxsoRegister texcoord; + texcoord.id = { DxsoRegisterType::PixelTexcoord, ctx.dst.id.num }; + + texReg = emitRegisterLoadRaw(texcoord, nullptr); + } + + std::array indices = { 0, 1, 2, 3 }; + + // On SM1 it only works on the first + if (m_programInfo.majorVersion() < 2) { + texReg.type.ccount = 3; + + texReg.id = m_module.opVectorShuffle( + getVectorTypeId(texReg.type), + texReg.id, texReg.id, + texReg.type.ccount, indices.data()); + } + else { + // The writemask actually applies and works here... + // (FXC doesn't generate this but it fixes broken ENB shaders) + texReg = emitRegisterSwizzle(texReg, IdentitySwizzle, ctx.dst.mask); + } + + const uint32_t boolVecTypeId = + getVectorTypeId({ DxsoScalarType::Bool, texReg.type.ccount }); + + uint32_t result = m_module.opFOrdLessThan( + boolVecTypeId, texReg.id, + m_module.constfReplicant(0.0f, texReg.type.ccount)); + + if (texReg.type.ccount != 1) + result = m_module.opAny(m_module.defBoolType(), result); + + if (m_ps.killState == 0) { + uint32_t labelIf = m_module.allocateId(); + uint32_t labelEnd = m_module.allocateId(); + + m_module.opSelectionMerge(labelEnd, spv::SelectionControlMaskNone); + m_module.opBranchConditional(result, labelIf, labelEnd); + + m_module.opLabel(labelIf); + + if (m_moduleInfo.options.useDemoteToHelperInvocation) { + m_module.opDemoteToHelperInvocation(); + m_module.opBranch(labelEnd); + } else { + // OpKill terminates the block + m_module.opKill(); + } + + m_module.opLabel(labelEnd); + } + else { + uint32_t typeId = m_module.defBoolType(); + + uint32_t killState = m_module.opLoad (typeId, m_ps.killState); + killState = m_module.opLogicalOr(typeId, killState, result); + m_module.opStore(m_ps.killState, killState); + + if (m_moduleInfo.options.useSubgroupOpsForEarlyDiscard) { + uint32_t ballot = m_module.opGroupNonUniformBallot( + getVectorTypeId({ DxsoScalarType::Uint32, 4 }), + m_module.constu32(spv::ScopeSubgroup), + killState); + + uint32_t laneId = m_module.opLoad( + getScalarTypeId(DxsoScalarType::Uint32), + m_ps.builtinLaneId); + + uint32_t laneIdPart = m_module.opShiftRightLogical( + getScalarTypeId(DxsoScalarType::Uint32), + laneId, m_module.constu32(5)); + + uint32_t laneMask = m_module.opVectorExtractDynamic( + getScalarTypeId(DxsoScalarType::Uint32), + ballot, laneIdPart); + + uint32_t laneIdQuad = m_module.opBitwiseAnd( + getScalarTypeId(DxsoScalarType::Uint32), + laneId, m_module.constu32(0x1c)); + + laneMask = m_module.opShiftRightLogical( + getScalarTypeId(DxsoScalarType::Uint32), + laneMask, laneIdQuad); + + laneMask = m_module.opBitwiseAnd( + getScalarTypeId(DxsoScalarType::Uint32), + laneMask, m_module.constu32(0xf)); + + uint32_t killSubgroup = m_module.opIEqual( + m_module.defBoolType(), + laneMask, m_module.constu32(0xf)); + + uint32_t labelIf = m_module.allocateId(); + uint32_t labelEnd = m_module.allocateId(); + + m_module.opSelectionMerge(labelEnd, spv::SelectionControlMaskNone); + m_module.opBranchConditional(killSubgroup, labelIf, labelEnd); + + // OpKill terminates the block + m_module.opLabel(labelIf); + m_module.opKill(); + + m_module.opLabel(labelEnd); + } + } + } + + void DxsoCompiler::emitTextureDepth(const DxsoInstructionContext& ctx) { + const uint32_t fType = m_module.defFloatType(32); + + DxsoRegMask srcMask(true, true, false, false); + uint32_t r5 = emitRegisterLoad(ctx.src[0], srcMask).id; + uint32_t x = 0; + uint32_t y = 1; + + uint32_t xValue = m_module.opCompositeExtract(fType, r5, 1, &x); + uint32_t yValue = m_module.opCompositeExtract(fType, r5, 1, &y); + + // The docs say if yValue is 0 the result is 1.0 but native drivers return + // 0 for xValue <= 0. So we don't have to do anything special since -INF and + // NAN get clamped to 0 at the end of the shader. + uint32_t result = m_module.opFDiv(fType, xValue, yValue); + + DxsoBaseRegister depth; + depth.id = { DxsoRegisterType::DepthOut, 0 }; + + DxsoRegisterPointer depthPtr = emitGetOperandPtr(depth, nullptr); + + m_module.opStore(depthPtr.id, result); + } + + + uint32_t DxsoCompiler::emitSample( + bool projected, + uint32_t resultType, + DxsoSamplerInfo& samplerInfo, + DxsoRegisterValue coordinates, + uint32_t reference, + uint32_t fetch4, + const SpirvImageOperands& operands) { + const bool depthCompare = reference != 0; + const bool explicitLod = + (operands.flags & spv::ImageOperandsLodMask) + || (operands.flags & spv::ImageOperandsGradMask); + + const uint32_t sampledImage = m_module.opLoad(samplerInfo.typeId, samplerInfo.varId); + + uint32_t val; + + // No Fetch 4 + if (projected) { + if (depthCompare) { + if (explicitLod) + val = m_module.opImageSampleProjDrefExplicitLod(resultType, sampledImage, coordinates.id, reference, operands); + else + val = m_module.opImageSampleProjDrefImplicitLod(resultType, sampledImage, coordinates.id, reference, operands); + } + else { + if (explicitLod) + val = m_module.opImageSampleProjExplicitLod(resultType, sampledImage, coordinates.id, operands); + else + val = m_module.opImageSampleProjImplicitLod(resultType, sampledImage, coordinates.id, operands); + } + } + else { + if (depthCompare) { + if (explicitLod) + val = m_module.opImageSampleDrefExplicitLod(resultType, sampledImage, coordinates.id, reference, operands); + else + val = m_module.opImageSampleDrefImplicitLod(resultType, sampledImage, coordinates.id, reference, operands); + } + else { + if (explicitLod) + val = m_module.opImageSampleExplicitLod(resultType, sampledImage, coordinates.id, operands); + else + val = m_module.opImageSampleImplicitLod(resultType, sampledImage, coordinates.id, operands); + } + } + + + if (fetch4 && !depthCompare) { + SpirvImageOperands fetch4Operands = operands; + fetch4Operands.flags &= ~spv::ImageOperandsLodMask; + fetch4Operands.flags &= ~spv::ImageOperandsGradMask; + fetch4Operands.flags &= ~spv::ImageOperandsBiasMask; + + // Doesn't really work for cubes... + // D3D9 does support gather on 3D but we cannot :< + // Nothing probably relies on that though. + // If we come back to this ever, make sure to handle cube/3d differences. + if (samplerInfo.dimensions == 2) { + uint32_t image = m_module.opImage(samplerInfo.imageTypeId, sampledImage); + + // Account for half texel offset... + // textureSize = 1.0f / float(2 * textureSize(sampler, 0)) + DxsoRegisterValue textureSize; + textureSize.type = { DxsoScalarType::Sint32, samplerInfo.dimensions }; + textureSize.id = m_module.opImageQuerySizeLod(getVectorTypeId(textureSize.type), image, m_module.consti32(0)); + textureSize.id = m_module.opIMul(getVectorTypeId(textureSize.type), textureSize.id, m_module.constiReplicant(2, samplerInfo.dimensions)); + + textureSize.type = { DxsoScalarType::Float32, samplerInfo.dimensions }; + textureSize.id = m_module.opConvertStoF(getVectorTypeId(textureSize.type), textureSize.id); + // HACK: Bias fetch4 half-texel offset to avoid a "grid" effect. + // Technically we should only do that for non-powers of two + // as only then does the imprecision need to be biased + // towards infinity -- but that's not really worth doing... + float numerator = 1.0f - 1.0f / 256.0f; + textureSize.id = m_module.opFDiv(getVectorTypeId(textureSize.type), m_module.constfReplicant(numerator, samplerInfo.dimensions), textureSize.id); + + // coord => same dimensions as texture size (no cube here !) + const std::array naturalIndices = { 0, 1, 2, 3 }; + coordinates.type.ccount = samplerInfo.dimensions; + coordinates.id = m_module.opVectorShuffle(getVectorTypeId(coordinates.type), coordinates.id, coordinates.id, coordinates.type.ccount, naturalIndices.data()); + // coord += textureSize; + coordinates.id = m_module.opFAdd(getVectorTypeId(coordinates.type), coordinates.id, textureSize.id); + } + + uint32_t fetch4Val = m_module.opImageGather(resultType, sampledImage, coordinates.id, m_module.consti32(0), fetch4Operands); + // B R G A swizzle... Funny D3D9 order. + const std::array indices = { 2, 0, 1, 3 }; + fetch4Val = m_module.opVectorShuffle(resultType, fetch4Val, fetch4Val, indices.size(), indices.data()); + + val = m_module.opSelect(resultType, fetch4, fetch4Val, val); + } + + return val; + } + + + void DxsoCompiler::emitInputSetup() { + uint32_t pointCoord = 0; + D3D9PointSizeInfoPS pointInfo; + + if (m_programInfo.type() == DxsoProgramType::PixelShader) { + pointCoord = GetPointCoord(m_module, m_entryPointInterfaces); + pointInfo = GetPointSizeInfoPS(m_module, m_rsBlock); + } + + for (uint32_t i = 0; i < m_isgn.elemCount; i++) { + const auto& elem = m_isgn.elems[i]; + const uint32_t slot = elem.slot; + + DxsoRegisterInfo info; + info.type.ctype = DxsoScalarType::Float32; + info.type.ccount = 4; + info.type.alength = 1; + info.sclass = spv::StorageClassInput; + + DxsoRegisterPointer inputPtr; + inputPtr.id = emitNewVariable(info); + inputPtr.type.ctype = DxsoScalarType::Float32; + inputPtr.type.ccount = info.type.ccount; + + m_module.decorateLocation(inputPtr.id, slot); + + std::string name = + str::format("in_", elem.semantic.usage, elem.semantic.usageIndex); + m_module.setDebugName(inputPtr.id, name.c_str()); + + if (elem.centroid) + m_module.decorate(inputPtr.id, spv::DecorationCentroid); + + m_entryPointInterfaces.push_back(inputPtr.id); + + uint32_t typeId = this->getVectorTypeId({ DxsoScalarType::Float32, 4 }); + uint32_t ptrTypeId = m_module.defPointerType(typeId, spv::StorageClassPrivate); + + uint32_t regNumVar = m_module.constu32(elem.regNumber); + + DxsoRegisterPointer indexPtr; + indexPtr.id = m_module.opAccessChain(ptrTypeId, m_vArray, 1, ®NumVar); + indexPtr.type = inputPtr.type; + indexPtr.type.ccount = 4; + + DxsoRegisterValue indexVal = this->emitValueLoad(inputPtr); + + DxsoRegisterValue workingReg; + workingReg.type = indexVal.type; + + workingReg.id = m_module.constvec4f32(0.0f, 0.0f, 0.0f, 0.0f); + + DxsoRegMask mask = elem.mask; + if (mask.popCount() == 0) + mask = DxsoRegMask(true, true, true, true); + + std::array indices = { 0, 1, 2, 3 }; + uint32_t count = 0; + for (uint32_t i = 0; i < 4; i++) { + if (mask[i]) { + indices[i] = i + 4; + count++; + } + } + + workingReg.id = m_module.opVectorShuffle(getVectorTypeId(workingReg.type), + workingReg.id, indexVal.id, 4, indices.data()); + + // We need to replace TEXCOORD inputs with gl_PointCoord + // if D3DRS_POINTSPRITEENABLE is set. + if (m_programInfo.type() == DxsoProgramType::PixelShader && elem.semantic.usage == DxsoUsage::Texcoord) + workingReg.id = m_module.opSelect(getVectorTypeId(workingReg.type), pointInfo.isSprite, pointCoord, workingReg.id); + + if (m_programInfo.type() == DxsoProgramType::PixelShader && elem.semantic.usage == DxsoUsage::Color) { + if (elem.semantic.usageIndex == 0) + m_ps.diffuseColorIn = inputPtr.id; + else if (elem.semantic.usageIndex == 1) + m_ps.specularColorIn = inputPtr.id; + } + + m_module.opStore(indexPtr.id, workingReg.id); + } + } + + + void DxsoCompiler::emitLinkerOutputSetup() { + bool outputtedColor0 = false; + bool outputtedColor1 = false; + + for (uint32_t i = 0; i < m_osgn.elemCount; i++) { + const auto& elem = m_osgn.elems[i]; + const uint32_t slot = elem.slot; + + if (elem.semantic.usage == DxsoUsage::Color) { + if (elem.semantic.usageIndex == 0) + outputtedColor0 = true; + else + outputtedColor1 = true; + } + + DxsoRegisterInfo info; + info.type.ctype = DxsoScalarType::Float32; + info.type.ccount = 4; + info.type.alength = 1; + info.sclass = spv::StorageClassOutput; + + spv::BuiltIn builtIn = + semanticToBuiltIn(false, elem.semantic); + + DxsoRegisterPointer outputPtr; + outputPtr.type.ctype = DxsoScalarType::Float32; + outputPtr.type.ccount = 4; + + DxsoRegMask mask = elem.mask; + + bool scalar = false; + + if (builtIn == spv::BuiltInMax) { + outputPtr.id = emitNewVariableDefault(info, + m_module.constvec4f32(0.0f, 0.0f, 0.0f, 0.0f)); + m_module.decorateLocation(outputPtr.id, slot); + + std::string name = + str::format("out_", elem.semantic.usage, elem.semantic.usageIndex); + m_module.setDebugName(outputPtr.id, name.c_str()); + } + else { + const char* name = "unknown_builtin"; + if (builtIn == spv::BuiltInPosition) + name = "oPos"; + else if (builtIn == spv::BuiltInPointSize) { + outputPtr.type.ccount = 1; + info.type.ccount = 1; + name = "oPSize"; + bool maskValues[4]; + for (uint32_t i = 0; i < 4; i++) + maskValues[i] = i == elem.mask.firstSet(); + mask = DxsoRegMask(maskValues[0], maskValues[1], maskValues[2], maskValues[3]); + } + + outputPtr.id = emitNewVariableDefault(info, + m_module.constfReplicant(0.0f, info.type.ccount)); + + m_module.setDebugName(outputPtr.id, name); + m_module.decorateBuiltIn(outputPtr.id, builtIn); + + if (builtIn == spv::BuiltInPosition) + m_vs.oPos = outputPtr; + else if (builtIn == spv::BuiltInPointSize) { + scalar = true; + m_vs.oPSize = outputPtr; + } + } + + m_entryPointInterfaces.push_back(outputPtr.id); + + uint32_t typeId = this->getVectorTypeId({ DxsoScalarType::Float32, 4 }); + uint32_t ptrTypeId = m_module.defPointerType(typeId, spv::StorageClassPrivate); + + uint32_t regNumVar = m_module.constu32(elem.regNumber); + + DxsoRegisterPointer indexPtr; + indexPtr.id = m_module.opAccessChain(ptrTypeId, m_oArray, 1, ®NumVar); + indexPtr.type = outputPtr.type; + indexPtr.type.ccount = 4; + + DxsoRegisterValue indexVal = this->emitValueLoad(indexPtr); + + DxsoRegisterValue workingReg; + workingReg.type.ctype = indexVal.type.ctype; + workingReg.type.ccount = scalar ? 1 : 4; + + workingReg.id = scalar + ? m_module.constf32(0.0f) + : m_module.constvec4f32(0.0f, 0.0f, 0.0f, 0.0f); + + std::array indices = { 0, 1, 2, 3 }; + + if (scalar) { + workingReg.id = m_module.opCompositeExtract(getVectorTypeId(workingReg.type), + indexVal.id, 1, indices.data()); + } else { + if (mask.popCount() == 0) + mask = DxsoRegMask(true, true, true, true); + + uint32_t count = 0; + for (uint32_t i = 0; i < 4; i++) { + if (mask[i]) + indices[count++] = i + 4; + } + + + workingReg.id = m_module.opVectorShuffle(getVectorTypeId(workingReg.type), + workingReg.id, indexVal.id, 4, indices.data()); + } + + // Ie. 0 or 1 for diffuse and specular color + // and for Shader Model 1 or 2 + // (because those have dedicated color registers + // where this rule applies) + if (elem.semantic.usage == DxsoUsage::Color && + elem.semantic.usageIndex < 2 && + m_programInfo.majorVersion() < 3) + workingReg = emitSaturate(workingReg); + + m_module.opStore(outputPtr.id, workingReg.id); + } + + auto OutputDefault = [&](DxsoSemantic semantic) { + DxsoRegisterInfo info; + info.type.ctype = DxsoScalarType::Float32; + info.type.ccount = 4; + info.type.alength = 1; + info.sclass = spv::StorageClassOutput; + + uint32_t slot = RegisterLinkerSlot(semantic); + + uint32_t value = semantic == DxsoSemantic{ DxsoUsage::Color, 0 } + ? m_module.constvec4f32(1.0f, 1.0f, 1.0f, 1.0f) + : m_module.constvec4f32(0.0f, 0.0f, 0.0f, 0.0f); + + + uint32_t outputPtr = emitNewVariableDefault(info, value); + + m_module.decorateLocation(outputPtr, slot); + + std::string name = + str::format("out_", semantic.usage, semantic.usageIndex, "_default"); + + m_module.setDebugName(outputPtr, name.c_str()); + + m_outputMask |= 1u << slot; + m_entryPointInterfaces.push_back(outputPtr); + }; + + if (!outputtedColor0) + OutputDefault(DxsoSemantic{ DxsoUsage::Color, 0 }); + + if (!outputtedColor1) + OutputDefault(DxsoSemantic{ DxsoUsage::Color, 1 }); + + auto pointInfo = GetPointSizeInfoVS(m_module, m_vs.oPos.id, 0, 0, m_rsBlock, false); + + if (m_vs.oPSize.id == 0) { + m_vs.oPSize = this->emitRegisterPtr( + "oPSize", DxsoScalarType::Float32, 1, 0, + spv::StorageClassOutput, spv::BuiltInPointSize); + + uint32_t pointSize = m_module.opFClamp(m_module.defFloatType(32), pointInfo.defaultValue, pointInfo.min, pointInfo.max); + + m_module.opStore(m_vs.oPSize.id, pointSize); + } + else { + uint32_t float_t = m_module.defFloatType(32); + uint32_t pointSize = m_module.opFClamp(m_module.defFloatType(32), m_module.opLoad(float_t, m_vs.oPSize.id), pointInfo.min, pointInfo.max); + m_module.opStore(m_vs.oPSize.id, pointSize); + } + } + + + void DxsoCompiler::emitVsClipping() { + uint32_t clipPlaneCountId = m_module.constu32(caps::MaxClipPlanes); + + uint32_t floatType = m_module.defFloatType(32); + uint32_t vec4Type = m_module.defVectorType(floatType, 4); + + // Declare uniform buffer containing clip planes + uint32_t clipPlaneArray = m_module.defArrayTypeUnique(vec4Type, clipPlaneCountId); + uint32_t clipPlaneStruct = m_module.defStructTypeUnique(1, &clipPlaneArray); + uint32_t clipPlaneBlock = m_module.newVar( + m_module.defPointerType(clipPlaneStruct, spv::StorageClassUniform), + spv::StorageClassUniform); + + m_module.decorateArrayStride (clipPlaneArray, 16); + + m_module.setDebugName (clipPlaneStruct, "clip_info_t"); + m_module.setDebugMemberName (clipPlaneStruct, 0, "clip_planes"); + m_module.decorate (clipPlaneStruct, spv::DecorationBlock); + m_module.memberDecorateOffset (clipPlaneStruct, 0, 0); + + uint32_t bindingId = computeResourceSlotId( + m_programInfo.type(), DxsoBindingType::ConstantBuffer, + DxsoConstantBuffers::VSClipPlanes); + + m_module.setDebugName (clipPlaneBlock, "clip_info"); + m_module.decorateDescriptorSet(clipPlaneBlock, 0); + m_module.decorateBinding (clipPlaneBlock, bindingId); + + DxvkResourceSlot resource; + resource.slot = bindingId; + resource.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + resource.view = VK_IMAGE_VIEW_TYPE_MAX_ENUM; + resource.access = VK_ACCESS_UNIFORM_READ_BIT; + m_resourceSlots.push_back(resource); + + // Declare output array for clip distances + uint32_t clipDistArray = m_module.newVar( + m_module.defPointerType( + m_module.defArrayType(floatType, clipPlaneCountId), + spv::StorageClassOutput), + spv::StorageClassOutput); + + m_module.decorateBuiltIn(clipDistArray, spv::BuiltInClipDistance); + m_entryPointInterfaces.push_back(clipDistArray); + + if (m_moduleInfo.options.invariantPosition) + m_module.decorate(m_vs.oPos.id, spv::DecorationInvariant); + + const uint32_t positionPtr = m_vs.oPos.id; + + // We generated a bad shader, let's not make it even worse. + if (positionPtr == 0) { + Logger::warn("Shader without Position output. Something is likely wrong here."); + return; + } + + // Compute clip distances + DxsoRegisterValue position; + position.type = { DxsoScalarType::Float32, 4 }; + position.id = m_module.opLoad(vec4Type, positionPtr); + + for (uint32_t i = 0; i < caps::MaxClipPlanes; i++) { + std::array blockMembers = {{ + m_module.constu32(0), + m_module.constu32(i), + }}; + + DxsoRegisterValue plane; + plane.type = { DxsoScalarType::Float32, 4 }; + plane.id = m_module.opLoad(vec4Type, m_module.opAccessChain( + m_module.defPointerType(vec4Type, spv::StorageClassUniform), + clipPlaneBlock, blockMembers.size(), blockMembers.data())); + + DxsoRegisterValue dist = emitDot(position, plane); + + m_module.opStore(m_module.opAccessChain( + m_module.defPointerType(floatType, spv::StorageClassOutput), + clipDistArray, 1, &blockMembers[1]), dist.id); + } + } + + + void DxsoCompiler::setupRenderStateInfo() { + uint32_t count; + + // Only need alpha ref for PS 3. + // No FF fog component. + if (m_programInfo.type() == DxsoProgramType::PixelShader) { + if (m_programInfo.majorVersion() == 3) { + m_pushConstOffset = offsetof(D3D9RenderStateInfo, alphaRef); + m_pushConstSize = sizeof(float); + } + else { + m_pushConstOffset = 0; + m_pushConstSize = offsetof(D3D9RenderStateInfo, pointSize); + } + + count = 5; + } + else { + m_pushConstOffset = offsetof(D3D9RenderStateInfo, pointSize); + // Point scale never triggers on programmable + m_pushConstSize = sizeof(float) * 3; + count = 8; + } + + m_rsBlock = SetupRenderStateBlock(m_module, count); + } + + + void DxsoCompiler::emitFog() { + DxsoRegister color0; + color0.id = DxsoRegisterId{ DxsoRegisterType::ColorOut, 0 }; + auto oColor0Ptr = this->emitGetOperandPtr(color0); + + DxsoRegister vFog; + vFog.id = DxsoRegisterId{ DxsoRegisterType::RasterizerOut, RasterOutFog }; + auto vFogPtr = this->emitGetOperandPtr(vFog); + + DxsoRegister vPos; + vPos.id = DxsoRegisterId{ DxsoRegisterType::MiscType, DxsoMiscTypeIndices::MiscTypePosition }; + auto vPosPtr = this->emitGetOperandPtr(vPos); + + D3D9FogContext fogCtx; + fogCtx.IsPixel = true; + fogCtx.RangeFog = false; + fogCtx.RenderState = m_rsBlock; + fogCtx.vPos = m_module.opLoad(getVectorTypeId(vPosPtr.type), vPosPtr.id); + fogCtx.vFog = m_module.opLoad(getVectorTypeId(vFogPtr.type), vFogPtr.id); + fogCtx.oColor = m_module.opLoad(getVectorTypeId(oColor0Ptr.type), oColor0Ptr.id); + fogCtx.IsFixedFunction = false; + fogCtx.IsPositionT = false; + fogCtx.HasSpecular = false; + fogCtx.Specular = 0; + + m_module.opStore(oColor0Ptr.id, DoFixedFunctionFog(m_module, fogCtx)); + } + + + void DxsoCompiler::emitPsProcessing() { + uint32_t boolType = m_module.defBoolType(); + uint32_t floatType = m_module.defFloatType(32); + uint32_t floatPtr = m_module.defPointerType(floatType, spv::StorageClassPushConstant); + + uint32_t alphaFuncId = m_module.specConst32(m_module.defIntType(32, 0), 0); + m_module.setDebugName (alphaFuncId, "alpha_func"); + m_module.decorateSpecId (alphaFuncId, getSpecId(D3D9SpecConstantId::AlphaCompareOp)); + + // Implement alpha test and fog + DxsoRegister color0; + color0.id = DxsoRegisterId{ DxsoRegisterType::ColorOut, 0 }; + auto oC0 = this->emitGetOperandPtr(color0); + + if (oC0.id) { + if (m_programInfo.majorVersion() < 3) + emitFog(); + + // Labels for the alpha test + std::array atestCaseLabels = {{ + { uint32_t(VK_COMPARE_OP_NEVER), m_module.allocateId() }, + { uint32_t(VK_COMPARE_OP_LESS), m_module.allocateId() }, + { uint32_t(VK_COMPARE_OP_EQUAL), m_module.allocateId() }, + { uint32_t(VK_COMPARE_OP_LESS_OR_EQUAL), m_module.allocateId() }, + { uint32_t(VK_COMPARE_OP_GREATER), m_module.allocateId() }, + { uint32_t(VK_COMPARE_OP_NOT_EQUAL), m_module.allocateId() }, + { uint32_t(VK_COMPARE_OP_GREATER_OR_EQUAL), m_module.allocateId() }, + { uint32_t(VK_COMPARE_OP_ALWAYS), m_module.allocateId() }, + }}; + + uint32_t atestBeginLabel = m_module.allocateId(); + uint32_t atestTestLabel = m_module.allocateId(); + uint32_t atestDiscardLabel = m_module.allocateId(); + uint32_t atestKeepLabel = m_module.allocateId(); + uint32_t atestSkipLabel = m_module.allocateId(); + + // if (alpha_func != ALWAYS) { ... } + uint32_t isNotAlways = m_module.opINotEqual(boolType, alphaFuncId, m_module.constu32(VK_COMPARE_OP_ALWAYS)); + m_module.opSelectionMerge(atestSkipLabel, spv::SelectionControlMaskNone); + m_module.opBranchConditional(isNotAlways, atestBeginLabel, atestSkipLabel); + m_module.opLabel(atestBeginLabel); + + // Load alpha component + uint32_t alphaComponentId = 3; + uint32_t alphaId = m_module.opCompositeExtract(floatType, + m_module.opLoad(m_module.defVectorType(floatType, 4), oC0.id), + 1, &alphaComponentId); + + if (m_moduleInfo.options.alphaTestWiggleRoom) { + // NV has wonky interpolation of all 1's in a VS -> PS going to 0.999999... + // This causes garbage-looking graphics on people's clothing in EverQuest 2 as it does alpha == 1.0. + + // My testing shows the alpha test has a precision of 1/256 for all A8 and below formats, + // and around 1 / 2048 for A32F formats and 1 / 4096 for A16F formats (It makes no sense to me too) + // so anyway, we're just going to round this to a precision of 1 / 4096 and hopefully this should make things happy + // everywhere. + const uint32_t alphaSizeId = m_module.constf32(4096.0f); + + alphaId = m_module.opFMul(floatType, alphaId, alphaSizeId); + alphaId = m_module.opRound(floatType, alphaId); + alphaId = m_module.opFDiv(floatType, alphaId, alphaSizeId); + } + + // Load alpha reference + uint32_t alphaRefMember = m_module.constu32(uint32_t(D3D9RenderStateItem::AlphaRef)); + uint32_t alphaRefId = m_module.opLoad(floatType, + m_module.opAccessChain(floatPtr, m_rsBlock, 1, &alphaRefMember)); + + // switch (alpha_func) { ... } + m_module.opSelectionMerge(atestTestLabel, spv::SelectionControlMaskNone); + m_module.opSwitch(alphaFuncId, + atestCaseLabels[uint32_t(VK_COMPARE_OP_ALWAYS)].labelId, + atestCaseLabels.size(), + atestCaseLabels.data()); + + std::array atestVariables; + + for (uint32_t i = 0; i < atestCaseLabels.size(); i++) { + m_module.opLabel(atestCaseLabels[i].labelId); + + atestVariables[i].labelId = atestCaseLabels[i].labelId; + atestVariables[i].varId = [&] { + switch (VkCompareOp(atestCaseLabels[i].literal)) { + case VK_COMPARE_OP_NEVER: return m_module.constBool(false); + case VK_COMPARE_OP_LESS: return m_module.opFOrdLessThan (boolType, alphaId, alphaRefId); + case VK_COMPARE_OP_EQUAL: return m_module.opFOrdEqual (boolType, alphaId, alphaRefId); + case VK_COMPARE_OP_LESS_OR_EQUAL: return m_module.opFOrdLessThanEqual (boolType, alphaId, alphaRefId); + case VK_COMPARE_OP_GREATER: return m_module.opFOrdGreaterThan (boolType, alphaId, alphaRefId); + case VK_COMPARE_OP_NOT_EQUAL: return m_module.opFOrdNotEqual (boolType, alphaId, alphaRefId); + case VK_COMPARE_OP_GREATER_OR_EQUAL: return m_module.opFOrdGreaterThanEqual(boolType, alphaId, alphaRefId); + default: + case VK_COMPARE_OP_ALWAYS: return m_module.constBool(true); + } + }(); + + m_module.opBranch(atestTestLabel); + } + + // end switch + m_module.opLabel(atestTestLabel); + + uint32_t atestResult = m_module.opPhi(boolType, + atestVariables.size(), + atestVariables.data()); + uint32_t atestDiscard = m_module.opLogicalNot(boolType, atestResult); + + // if (do_discard) { ... } + m_module.opSelectionMerge(atestKeepLabel, spv::SelectionControlMaskNone); + m_module.opBranchConditional(atestDiscard, atestDiscardLabel, atestKeepLabel); + + m_module.opLabel(atestDiscardLabel); + m_module.opKill(); + + // end if (do_discard) + m_module.opLabel(atestKeepLabel); + m_module.opBranch(atestSkipLabel); + + // end if (alpha_test) + m_module.opLabel(atestSkipLabel); + } + } + + void DxsoCompiler::emitOutputDepthClamp() { + // HACK: Some drivers do not clamp FragDepth to [minDepth..maxDepth] + // before writing to the depth attachment, but we do not have acccess + // to those. Clamp to [0..1] instead. + + if (m_ps.oDepth.id != 0) { + auto result = emitValueLoad(m_ps.oDepth); + + result = emitSaturate(result); + + m_module.opStore( + m_ps.oDepth.id, + result.id); + } +} + + + void DxsoCompiler::emitVsFinalize() { + this->emitMainFunctionBegin(); + + this->emitInputSetup(); + m_module.opFunctionCall( + m_module.defVoidType(), + m_vs.functionId, 0, nullptr); + this->emitLinkerOutputSetup(); + + this->emitVsClipping(); + + this->emitFunctionEnd(); + } + + void DxsoCompiler::emitPsFinalize() { + this->emitMainFunctionBegin(); + + this->emitInputSetup(); + + bool canUsePixelFog = m_programInfo.majorVersion() < 3; + + if (canUsePixelFog) { + // Look up vPos so it gets initted. + DxsoRegister vPos; + vPos.id = DxsoRegisterId{ DxsoRegisterType::MiscType, DxsoMiscTypeIndices::MiscTypePosition }; + this->emitGetOperandPtr(vPos); + } + + if (m_ps.vPos.id != 0) { + DxsoRegisterPointer fragCoord = this->emitRegisterPtr( + "ps_frag_coord", DxsoScalarType::Float32, 4, 0, + spv::StorageClassInput, spv::BuiltInFragCoord); + + DxsoRegisterValue val = this->emitValueLoad(fragCoord); + val.id = m_module.opFSub( + getVectorTypeId(val.type), val.id, + m_module.constvec4f32(0.5f, 0.5f, 0.0f, 0.0f)); + + m_module.opStore(m_ps.vPos.id, val.id); + } + + if (m_ps.vFace.id != 0) { + DxsoRegisterPointer faceBool = this->emitRegisterPtr( + "ps_is_front_face", DxsoScalarType::Bool, 1, 0, + spv::StorageClassInput, spv::BuiltInFrontFacing); + + DxsoRegisterValue frontFace = emitValueLoad(faceBool); + DxsoRegisterValue selectOp = emitRegisterExtend(frontFace, 4); + + m_module.opStore( + m_ps.vFace.id, + m_module.opSelect(getVectorTypeId(m_ps.vFace.type), selectOp.id, + m_module.constvec4f32( 1.0f, 1.0f, 1.0f, 1.0f), + m_module.constvec4f32(-1.0f, -1.0f, -1.0f, -1.0f))); + } + + m_module.opFunctionCall( + m_module.defVoidType(), + m_ps.functionId, 0, nullptr); + + if (m_ps.killState != 0) { + uint32_t labelIf = m_module.allocateId(); + uint32_t labelEnd = m_module.allocateId(); + + uint32_t killTest = m_module.opLoad(m_module.defBoolType(), m_ps.killState); + + m_module.opSelectionMerge(labelEnd, spv::SelectionControlMaskNone); + m_module.opBranchConditional(killTest, labelIf, labelEnd); + + m_module.opLabel(labelIf); + m_module.opKill(); + + m_module.opLabel(labelEnd); + } + + // r0 in PS1 is the colour output register. Move r0 -> cO0 here. + if (m_programInfo.majorVersion() == 1 + && m_programInfo.type() == DxsoProgramTypes::PixelShader) { + DxsoRegister r0; + r0.id = { DxsoRegisterType::Temp, 0 }; + + DxsoRegister c0; + c0.id = { DxsoRegisterType::ColorOut, 0 }; + + DxsoRegisterValue val = emitRegisterLoadRaw(r0, nullptr); + DxsoRegisterPointer out = emitGetOperandPtr(c0); + m_module.opStore(out.id, val.id); + } + + // No need to setup output here as it's non-indexable + // everything has already gone to the right place! + + this->emitPsProcessing(); + this->emitOutputDepthClamp(); + this->emitFunctionEnd(); + } + + + + uint32_t DxsoCompiler::getScalarTypeId(DxsoScalarType type) { + switch (type) { + case DxsoScalarType::Uint32: return m_module.defIntType(32, 0); + case DxsoScalarType::Sint32: return m_module.defIntType(32, 1); + case DxsoScalarType::Float32: return m_module.defFloatType(32); + case DxsoScalarType::Bool: return m_module.defBoolType(); + } + + throw DxvkError("DxsoCompiler: Invalid scalar type"); + } + + + uint32_t DxsoCompiler::getVectorTypeId(const DxsoVectorType& type) { + uint32_t typeId = this->getScalarTypeId(type.ctype); + + if (type.ccount > 1) + typeId = m_module.defVectorType(typeId, type.ccount); + + return typeId; + } + + + uint32_t DxsoCompiler::getArrayTypeId(const DxsoArrayType& type) { + DxsoVectorType vtype; + vtype.ctype = type.ctype; + vtype.ccount = type.ccount; + + uint32_t typeId = this->getVectorTypeId(vtype); + + if (type.alength > 1) { + typeId = m_module.defArrayType(typeId, + m_module.constu32(type.alength)); + } + + return typeId; + } + + + uint32_t DxsoCompiler::getPointerTypeId(const DxsoRegisterInfo& type) { + return m_module.defPointerType( + this->getArrayTypeId(type.type), + type.sclass); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxso/dxso_compiler.h b/utils/dxvk-1.10.3/src/dxso/dxso_compiler.h new file mode 100644 index 00000000000..f26732f4531 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxso/dxso_compiler.h @@ -0,0 +1,722 @@ +#pragma once + +#include "dxso_decoder.h" +#include "dxso_header.h" +#include "dxso_modinfo.h" +#include "dxso_isgn.h" +#include "dxso_util.h" + +#include "../d3d9/d3d9_constant_layout.h" +#include "../d3d9/d3d9_shader_permutations.h" +#include "../spirv/spirv_module.h" + +namespace dxvk { + + /** + * \brief Scalar value type + * + * Enumerates possible register component + * types. Scalar types are represented as + * a one-component vector type. + */ + enum class DxsoScalarType : uint32_t { + Uint32 = 0, + Sint32 = 1, + Float32 = 2, + Bool = 3, + }; + + /** + * \brief Vector type + * + * Convenience struct that stores a scalar + * type and a component count. The compiler + * can use this to generate SPIR-V types. + */ + struct DxsoVectorType { + DxsoScalarType ctype; + uint32_t ccount; + }; + + + /** + * \brief Array type + * + * Convenience struct that stores a scalar type, a + * component count and an array size. An array of + * length 0 will be evaluated to a vector type. The + * compiler can use this to generate SPIR-V types. + */ + struct DxsoArrayType { + DxsoScalarType ctype; + uint32_t ccount; + uint32_t alength; + }; + + + /** + * \brief Register info + * + * Stores the array type of a register and + * its storage class. The compiler can use + * this to generate SPIR-V pointer types. + */ + struct DxsoRegisterInfo { + DxsoArrayType type; + spv::StorageClass sclass; + }; + + + /** + * \brief Register value + * + * Stores a vector type and a SPIR-V ID that + * represents an intermediate value. This is + * used to track the type of such values. + */ + struct DxsoRegisterValue { + DxsoVectorType type; + uint32_t id; + }; + + + /** + * \brief Register pointer + * + * Stores a vector type and a SPIR-V ID that + * represents a pointer to such a vector. This + * can be used to load registers conveniently. + */ + struct DxsoRegisterPointer { + DxsoVectorType type; + uint32_t id = 0; + }; + + /** + * \brief Sampler info + * + * Stores a vector type and a SPIR-V ID that + * represents a pointer to such a vector. This + * can be used to load registers conveniently. + */ + struct DxsoSamplerInfo { + uint32_t dimensions = 0; + + uint32_t varId = 0; + uint32_t typeId = 0; + + uint32_t imageTypeId = 0; + }; + + enum DxsoSamplerType : uint32_t { + SamplerTypeTexture2D = 0, + SamplerTypeTexture3D = 1, + SamplerTypeTextureCube, + + SamplerTypeCount + }; + + inline auto SamplerTypeFromTextureType(DxsoTextureType type) { + switch (type) { + default: + case DxsoTextureType::Texture2D: return SamplerTypeTexture2D; break; + case DxsoTextureType::Texture3D: return SamplerTypeTexture3D; break; + case DxsoTextureType::TextureCube: return SamplerTypeTextureCube; break; + } + } + + struct DxsoSampler { + DxsoSamplerInfo color[SamplerTypeCount]; + DxsoSamplerInfo depth[SamplerTypeCount]; + + uint32_t boundConst; + + DxsoTextureType type; + }; + + struct DxsoAnalysisInfo; + + /** + * \brief Vertex shader-specific structure + */ + struct DxsoCompilerVsPart { + uint32_t functionId = 0; + + //////////////////// + // Address register + DxsoRegisterPointer addr; + + ////////////////////////////// + // Rasterizer output registers + DxsoRegisterPointer oPos; + DxsoRegisterPointer oPSize; + }; + + /** + * \brief Pixel shader-specific structure + */ + struct DxsoCompilerPsPart { + uint32_t functionId = 0; + uint32_t samplerTypeSpec = 0; + uint32_t projectionSpec = 0; + uint32_t fetch4Spec = 0; + + ////////////// + // Misc Types + DxsoRegisterPointer vPos; + DxsoRegisterPointer vFace; + + /////////////////// + // Colour Outputs + std::array oColor; + + //////////////// + // Depth output + DxsoRegisterPointer oDepth; + + //////////////// + // Shared State + uint32_t sharedState = 0; + + uint32_t killState = 0; + uint32_t builtinLaneId = 0; + + uint32_t diffuseColorIn = 0; + uint32_t specularColorIn = 0; + }; + + struct DxsoCfgBlockIf { + uint32_t ztestId; + uint32_t labelIf; + uint32_t labelElse; + uint32_t labelEnd; + size_t headerPtr; + }; + + struct DxsoCfgBlockLoop { + uint32_t labelHeader; + uint32_t labelBegin; + uint32_t labelContinue; + uint32_t labelBreak; + uint32_t iteratorPtr; + + uint32_t strideVar; + uint32_t countBackup; + }; + + enum class DxsoCfgBlockType : uint32_t { + If, Loop + }; + + struct DxsoCfgBlock { + DxsoCfgBlockType type; + + union { + DxsoCfgBlockIf b_if; + DxsoCfgBlockLoop b_loop; + }; + }; + + using DxsoSrcArray = std::array; + + class DxsoCompiler { + + public: + + DxsoCompiler( + const std::string& fileName, + const DxsoModuleInfo& moduleInfo, + const DxsoProgramInfo& programInfo, + const DxsoAnalysisInfo& analysis, + const D3D9ConstantLayout& layout); + + /** + * \brief Processes a single instruction + * \param [in] ins The instruction + */ + void processInstruction( + const DxsoInstructionContext& ctx, + uint32_t currentCoissueIdx = 0); + + /** + * \brief Finalizes the shader + */ + void finalize(); + + /** + * \brief Compiles the shader + * \returns The final shader objects + */ + DxsoPermutations compile(); + + const DxsoIsgn& isgn() { return m_isgn; } + const DxsoIsgn& osgn() { return m_osgn; } + + const DxsoShaderMetaInfo& meta() { return m_meta; } + const DxsoDefinedConstants& constants() { return m_constants; } + uint32_t usedSamplers() const { return m_usedSamplers; } + uint32_t usedRTs() const { return m_usedRTs; } + uint32_t maxDefinedConstant() const { return m_maxDefinedConstant; } + + private: + + DxsoModuleInfo m_moduleInfo; + DxsoProgramInfo m_programInfo; + const DxsoAnalysisInfo* m_analysis; + const D3D9ConstantLayout* m_layout; + + DxsoShaderMetaInfo m_meta; + DxsoDefinedConstants m_constants; + uint32_t m_maxDefinedConstant; + + SpirvModule m_module; + + uint32_t m_boolSpecConstant; + uint32_t m_depthSpecConstant; + + /////////////////////////////////////////////////////// + // Resource slot description for the shader. This will + // be used to map D3D9 bindings to DXVK bindings. + std::vector m_resourceSlots; + + //////////////////////////////////////////////// + // Temporary r# vector registers with immediate + // indexing, and x# vector array registers. + std::array< + DxsoRegisterPointer, + DxsoMaxTempRegs> m_rRegs; + + //////////////////////////////////////////////// + // Predicate registers + std::array< + DxsoRegisterPointer, + 1> m_pRegs; + + ////////////////////////////////////////////////////////////////// + // Array of input values. Since v# and o# registers are indexable + // in DXSO, we need to copy them into an array first. + uint32_t m_vArray = 0; + uint32_t m_oArray = 0; + + //////////////////////////////// + // Input and output signatures + DxsoIsgn m_isgn; + DxsoIsgn m_osgn; + + //////////////////////////////////// + // Ptr to the constant buffer array + uint32_t m_cBuffer = 0; + uint32_t m_cFloatBuffer = 0; + uint32_t m_cIntBuffer = 0; + uint32_t m_cBoolBuffer = 0; + + //////////////////////////////////////// + // Constant buffer deffed mappings + std::array m_cFloat; + std::array m_cInt; + std::array m_cBool; + + ////////////////////// + // Loop counter + DxsoRegisterPointer m_loopCounter; + + /////////////////////////////////// + // Working tex/coord registers (PS) + std::array< + DxsoRegisterPointer, + DxsoMaxTextureRegs> m_tRegs; + + /////////////////////////////////////////////// + // Control flow information. Stores labels for + // currently active if-else blocks and loops. + std::vector m_controlFlowBlocks; + + ////////////////////////////////////////////// + // Function state tracking. Required in order + // to properly end functions in some cases. + bool m_insideFunction = false; + + //////////// + // Samplers + std::array m_samplers; + + //////////////////////////////////////////// + // What io regswe need to + // NOT generate semantics for + uint16_t m_explicitInputs = 0; + uint16_t m_explicitOutputs = 0; + + /////////////////////////////////////////////////// + // Entry point description - we'll need to declare + // the function ID and all input/output variables. + std::vector m_entryPointInterfaces; + uint32_t m_entryPointId = 0; + + //////////////////////////////////////////// + // Inter-stage shader interface slots. Also + // covers vertex input and fragment output. + uint32_t m_inputMask = 0u; + uint32_t m_outputMask = 0u; + uint32_t m_pushConstOffset = 0u; + uint32_t m_pushConstSize = 0u; + + /////////////////////////////////// + // Shader-specific data structures + DxsoCompilerVsPart m_vs; + DxsoCompilerPsPart m_ps; + + DxsoRegisterPointer m_fog; + + ////////////////////////////////////////// + // Bit masks containing used samplers + // and render targets for hazard tracking + uint32_t m_usedSamplers; + uint32_t m_usedRTs; + + uint32_t m_rsBlock = 0; + uint32_t m_mainFuncLabel = 0; + + ////////////////////////////////////// + // Common function definition methods + void emitInit(); + + ////////////////////// + // Common shader dcls + template + int emitDclSwvpConstantBuffer(); + + void emitDclConstantBuffer(); + + void emitDclInputArray(); + void emitDclOutputArray(); + + ///////////////////////////////// + // Shader initialization methods + void emitVsInit(); + + void emitPsSharedConstants(); + void emitPsInit(); + + void emitFunctionBegin( + uint32_t entryPoint, + uint32_t returnType, + uint32_t funcType); + + void emitFunctionEnd(); + + uint32_t emitFunctionLabel(); + + void emitMainFunctionBegin(); + + /////////////////////////////// + // Variable definition methods + uint32_t emitNewVariable( + const DxsoRegisterInfo& info); + + uint32_t emitNewVariableDefault( + const DxsoRegisterInfo& info, + uint32_t value); + + uint32_t emitNewBuiltinVariable( + const DxsoRegisterInfo& info, + spv::BuiltIn builtIn, + const char* name, + uint32_t value); + + DxsoCfgBlock* cfgFindBlock( + const std::initializer_list& types); + + void emitDclInterface( + bool input, + uint32_t regNumber, + DxsoSemantic semantic, + DxsoRegMask mask, + bool centroid); + + void emitDclSampler( + uint32_t idx, + DxsoTextureType type); + + bool defineInput(uint32_t idx) { + bool alreadyDefined = m_inputMask & 1u << idx; + m_inputMask |= 1u << idx; + return alreadyDefined; + } + + bool defineOutput(uint32_t idx) { + bool alreadyDefined = m_outputMask & 1u << idx; + m_outputMask |= 1u << idx; + return alreadyDefined; + } + + uint32_t emitArrayIndex( + uint32_t idx, + const DxsoBaseRegister* relative); + + DxsoRegisterPointer emitInputPtr( + bool texture, + const DxsoBaseRegister& reg, + const DxsoBaseRegister* relative); + + DxsoRegisterPointer emitRegisterPtr( + const char* name, + DxsoScalarType ctype, + uint32_t ccount, + uint32_t defaultVal, + spv::StorageClass storageClass = spv::StorageClassPrivate, + spv::BuiltIn builtIn = spv::BuiltInMax); + + DxsoRegisterValue emitLoadConstant( + const DxsoBaseRegister& reg, + const DxsoBaseRegister* relative); + + DxsoRegisterPointer emitOutputPtr( + bool texcrdOut, + const DxsoBaseRegister& reg, + const DxsoBaseRegister* relative); + + DxsoRegisterPointer emitGetOperandPtr( + const DxsoBaseRegister& reg, + const DxsoBaseRegister* relative); + + DxsoRegisterPointer emitGetOperandPtr( + const DxsoRegister& reg) { + return this->emitGetOperandPtr( + reg, + reg.hasRelative ? ®.relative : nullptr); + } + + uint32_t emitBoolComparison(DxsoVectorType type, DxsoComparison cmp, uint32_t a, uint32_t b); + + DxsoRegisterValue emitValueLoad( + DxsoRegisterPointer ptr); + + void emitDstStore( + DxsoRegisterPointer ptr, + DxsoRegisterValue value, + DxsoRegMask writeMask, + bool saturate, + DxsoRegisterValue predicate, + int8_t shift, + DxsoRegisterId regId) { + if (regId.type == DxsoRegisterType::RasterizerOut && regId.num == RasterOutFog) + saturate = true; + + if (value.type.ctype == DxsoScalarType::Float32) { + const uint32_t typeId = getVectorTypeId(value.type); + + // There doesn't seem to be a nice float bitshift method for float vectors + // in Spirv that I can see... Resorting to multiplication. + if (shift != 0) { + float shiftAmount = shift < 0 + ? 1.0f / (1 << -shift) + : float(1 << shift); + + uint32_t shiftConst = m_module.constf32(shiftAmount); + + if (value.type.ccount == 1) + value.id = m_module.opFMul(typeId, value.id, shiftConst); + else + value.id = m_module.opVectorTimesScalar(typeId, value.id, shiftConst); + } + + // Saturating only makes sense on floats + if (saturate) { + value.id = m_module.opNClamp( + typeId, value.id, + m_module.constfReplicant(0.0f, value.type.ccount), + m_module.constfReplicant(1.0f, value.type.ccount)); + } + } + + this->emitValueStore(ptr, value, writeMask, predicate); + } + + DxsoRegisterValue applyPredicate(DxsoRegisterValue pred, DxsoRegisterValue dst, DxsoRegisterValue src); + + void emitValueStore( + DxsoRegisterPointer ptr, + DxsoRegisterValue value, + DxsoRegMask writeMask, + DxsoRegisterValue predicate); + + DxsoRegisterValue emitClampBoundReplicant( + DxsoRegisterValue srcValue, + float lb, + float ub); + + DxsoRegisterValue emitSaturate( + DxsoRegisterValue srcValue); + + DxsoRegisterValue emitMulOperand( + DxsoRegisterValue operand, + DxsoRegisterValue other); + + DxsoRegisterValue emitMul( + DxsoRegisterValue a, + DxsoRegisterValue b); + + DxsoRegisterValue emitFma( + DxsoRegisterValue a, + DxsoRegisterValue b, + DxsoRegisterValue c); + + DxsoRegisterValue emitDot( + DxsoRegisterValue a, + DxsoRegisterValue b); + + DxsoRegisterValue emitMix( + DxsoRegisterValue x, + DxsoRegisterValue y, + DxsoRegisterValue a); + + DxsoRegisterValue emitCross( + DxsoRegisterValue a, + DxsoRegisterValue b); + + DxsoRegisterValue emitRegisterInsert( + DxsoRegisterValue dstValue, + DxsoRegisterValue srcValue, + DxsoRegMask srcMask); + + DxsoRegisterValue emitRegisterLoadRaw( + const DxsoBaseRegister& reg, + const DxsoBaseRegister* relative); + + DxsoRegisterValue emitRegisterExtend( + DxsoRegisterValue value, + uint32_t size); + + DxsoRegisterValue emitSrcOperandPreSwizzleModifiers( + DxsoRegisterValue value, + DxsoRegModifier modifier); + + DxsoRegisterValue emitSrcOperandPostSwizzleModifiers( + DxsoRegisterValue value, + DxsoRegModifier modifier); + + DxsoRegisterValue emitRegisterSwizzle( + DxsoRegisterValue value, + DxsoRegSwizzle swizzle, + DxsoRegMask writeMask); + + DxsoRegisterValue emitRegisterLoad( + const DxsoBaseRegister& reg, + DxsoRegMask writeMask, + const DxsoBaseRegister* relative); + + DxsoRegisterValue emitRegisterLoad( + const DxsoRegister& reg, + DxsoRegMask writeMask) { + return this->emitRegisterLoad( + reg, writeMask, + reg.hasRelative ? ®.relative : nullptr); + } + + DxsoRegisterValue emitPredicateLoad(const DxsoInstructionContext& ctx) { + if (!ctx.instruction.predicated) + return DxsoRegisterValue(); + + return emitRegisterLoad(ctx.pred, IdentityWriteMask); + } + + DxsoRegisterValue emitRegisterLoadTexcoord( + const DxsoRegister& reg, + DxsoRegMask writeMask) { + DxsoRegister lookup = reg; + if (reg.id.type == DxsoRegisterType::Texture) + lookup.id.type = DxsoRegisterType::PixelTexcoord; + + return this->emitRegisterLoad(lookup, writeMask); + } + + Rc compileShader(); + + /////////////////////////////// + // Handle shader ops + void emitDcl(const DxsoInstructionContext& ctx); + + void emitDef(const DxsoInstructionContext& ctx); + void emitDefF(const DxsoInstructionContext& ctx); + void emitDefI(const DxsoInstructionContext& ctx); + void emitDefB(const DxsoInstructionContext& ctx); + + bool isScalarRegister(DxsoRegisterId id); + + void emitMov(const DxsoInstructionContext& ctx); + void emitPredicateOp(const DxsoInstructionContext& ctx); + void emitVectorAlu(const DxsoInstructionContext& ctx); + void emitMatrixAlu(const DxsoInstructionContext& ctx); + + void emitControlFlowGenericLoop( + bool count, + uint32_t initialVar, + uint32_t strideVar, + uint32_t iterationCountVar); + + void emitControlFlowGenericLoopEnd(); + + void emitControlFlowRep(const DxsoInstructionContext& ctx); + void emitControlFlowEndRep(const DxsoInstructionContext& ctx); + + void emitControlFlowLoop(const DxsoInstructionContext& ctx); + void emitControlFlowEndLoop(const DxsoInstructionContext& ctx); + + void emitControlFlowBreak(const DxsoInstructionContext& ctx); + void emitControlFlowBreakC(const DxsoInstructionContext& ctx); + + void emitControlFlowIf(const DxsoInstructionContext& ctx); + void emitControlFlowElse(const DxsoInstructionContext& ctx); + void emitControlFlowEndIf(const DxsoInstructionContext& ctx); + + void emitTexCoord(const DxsoInstructionContext& ctx); + void emitTextureSample(const DxsoInstructionContext& ctx); + void emitTextureKill(const DxsoInstructionContext& ctx); + void emitTextureDepth(const DxsoInstructionContext& ctx); + + uint32_t emitSample( + bool projected, + uint32_t resultType, + DxsoSamplerInfo& samplerInfo, + DxsoRegisterValue coordinates, + uint32_t reference, + uint32_t fetch4, + const SpirvImageOperands& operands); + + /////////////////////////////// + // Shader finalization methods + void emitInputSetup(); + + void emitVsClipping(); + void setupRenderStateInfo(); + void emitFog(); + void emitPsProcessing(); + void emitOutputDepthClamp(); + + void emitLinkerOutputSetup(); + + void emitVsFinalize(); + void emitPsFinalize(); + + /////////////////////////// + // Type definition methods + uint32_t getScalarTypeId( + DxsoScalarType type); + + uint32_t getVectorTypeId( + const DxsoVectorType& type); + + uint32_t getArrayTypeId( + const DxsoArrayType& type); + + uint32_t getPointerTypeId( + const DxsoRegisterInfo& type); + + + bool isSwvp() { + return m_layout->bitmaskCount != 1; + } + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxso/dxso_ctab.cpp b/utils/dxvk-1.10.3/src/dxso/dxso_ctab.cpp new file mode 100644 index 00000000000..880c7ead474 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxso/dxso_ctab.cpp @@ -0,0 +1,19 @@ +#include "dxso_ctab.h" + +namespace dxvk { + + DxsoCtab::DxsoCtab(DxsoReader& reader, uint32_t commentTokenCount) { + m_size = reader.readu32(); + + if (m_size != sizeof(DxsoCtab)) + throw DxvkError("DxsoCtab: ctab size invalid"); + + m_creator = reader.readu32(); + m_version = reader.readu32(); + m_constants = reader.readu32(); + m_constantInfo = reader.readu32(); + m_flags = reader.readu32(); + m_target = reader.readu32(); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxso/dxso_ctab.h b/utils/dxvk-1.10.3/src/dxso/dxso_ctab.h new file mode 100644 index 00000000000..56f4f9451bd --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxso/dxso_ctab.h @@ -0,0 +1,32 @@ +#pragma once + +#include "dxso_common.h" + +#include "dxso_reader.h" + +namespace dxvk { + + /** + * \brief DXSO CTAB + * + * Stores meta information about the shader + */ + class DxsoCtab : public RcObject { + + public: + + DxsoCtab(DxsoReader& reader, uint32_t commentTokenCount); + + private: + + uint32_t m_size; + uint32_t m_creator; + uint32_t m_version; + uint32_t m_constants; + uint32_t m_constantInfo; + uint32_t m_flags; + uint32_t m_target; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxso/dxso_decoder.cpp b/utils/dxvk-1.10.3/src/dxso/dxso_decoder.cpp new file mode 100644 index 00000000000..42d8d64b76e --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxso/dxso_decoder.cpp @@ -0,0 +1,280 @@ +#include "dxso_decoder.h" + +#include "dxso_tables.h" + +namespace dxvk { + + bool DxsoSemantic::operator== (const DxsoSemantic& b) const { + return usage == b.usage && usageIndex == b.usageIndex; + } + + bool DxsoSemantic::operator!= (const DxsoSemantic& b) const { + return usage != b.usage || usageIndex != b.usageIndex; + } + + uint32_t DxsoDecodeContext::decodeInstructionLength(uint32_t token) { + auto opcode = m_ctx.instruction.opcode; + + uint32_t length = 0; + const auto& info = this->getProgramInfo(); + + // Comment ops have their own system for getting length. + if (opcode == DxsoOpcode::Comment) + return (token & 0x7fff0000) >> 16; + + if (opcode == DxsoOpcode::End) + return 0; + + // SM2.0 and above has the length of the op in instruction count baked into it. + // SM1.4 and below have fixed lengths and run off expectation. + // Phase does not respect the following rules. :shrug: + if (opcode != DxsoOpcode::Phase) { + if (info.majorVersion() >= 2) + length = (token & 0x0f000000) >> 24; + else + length = DxsoGetDefaultOpcodeLength(opcode); + } + + // We've already logged this... + if (length == InvalidOpcodeLength) + return 0; + + // SM 1.4 has an extra param on Tex and TexCoord + // As stated before, it also doesn't have the length of the op baked into the opcode + if (info.majorVersion() == 1 + && info.minorVersion() == 4) { + switch (opcode) { + case DxsoOpcode::TexCoord: + case DxsoOpcode::Tex: length += 1; + default: break; + } + } + + return length; + } + + bool DxsoDecodeContext::relativeAddressingUsesToken( + DxsoInstructionArgumentType type) { + auto& info = this->getProgramInfo(); + + return (info.majorVersion() >= 2 && type == DxsoInstructionArgumentType::Source) + || (info.majorVersion() >= 3 && type == DxsoInstructionArgumentType::Destination); + } + + void DxsoDecodeContext::decodeDeclaration(DxsoCodeIter& iter) { + uint32_t dclToken = iter.read(); + + m_ctx.dcl.textureType = static_cast((dclToken & 0x78000000) >> 27); + m_ctx.dcl.semantic.usage = static_cast(dclToken & 0x0000000f); + m_ctx.dcl.semantic.usageIndex = (dclToken & 0x000f0000) >> 16; + } + + void DxsoDecodeContext::decodeDefinition(DxsoOpcode opcode, DxsoCodeIter& iter) { + const uint32_t instructionLength = std::min(m_ctx.instruction.tokenLength - 1, 4u); + + for (uint32_t i = 0; i < instructionLength; i++) + m_ctx.def.uint32[i] = iter.read(); + } + + void DxsoDecodeContext::decodeBaseRegister( + DxsoBaseRegister& reg, + uint32_t token) { + reg.id.type = static_cast( + ((token & 0x00001800) >> 8) + | ((token & 0x70000000) >> 28)); + + reg.id.num = token & 0x000007ff; + } + + void DxsoDecodeContext::decodeGenericRegister( + DxsoRegister& reg, + uint32_t token) { + this->decodeBaseRegister(reg, token); + + reg.hasRelative = (token & (1 << 13)) == 8192; + reg.relative.id = DxsoRegisterId { + DxsoRegisterType::Addr, 0 }; + reg.relative.swizzle = IdentitySwizzle; + + reg.centroid = token & (4 << 20); + reg.partialPrecision = token & (2 << 20); + } + + void DxsoDecodeContext::decodeRelativeRegister( + DxsoBaseRegister& reg, + uint32_t token) { + this->decodeBaseRegister(reg, token); + + reg.swizzle = DxsoRegSwizzle( + uint8_t((token & 0x00ff0000) >> 16)); + } + + bool DxsoDecodeContext::decodeDestinationRegister(DxsoCodeIter& iter) { + uint32_t token = iter.read(); + + this->decodeGenericRegister(m_ctx.dst, token); + + m_ctx.dst.mask = DxsoRegMask( + uint8_t((token & 0x000f0000) >> 16)); + + m_ctx.dst.saturate = (token & (1 << 20)) != 0; + + m_ctx.dst.shift = (token & 0x0f000000) >> 24; + m_ctx.dst.shift = (m_ctx.dst.shift & 0x7) - (m_ctx.dst.shift & 0x8); + + const bool extraToken = + relativeAddressingUsesToken(DxsoInstructionArgumentType::Destination); + + if (m_ctx.dst.hasRelative && extraToken) { + this->decodeRelativeRegister(m_ctx.dst.relative, iter.read()); + return true; + } + + return false; + } + + bool DxsoDecodeContext::decodeSourceRegister(uint32_t i, DxsoCodeIter& iter) { + if (i >= m_ctx.src.size()) + throw DxvkError("DxsoDecodeContext::decodeSourceRegister: source register out of range."); + + uint32_t token = iter.read(); + + this->decodeGenericRegister(m_ctx.src[i], token); + + m_ctx.src[i].swizzle = DxsoRegSwizzle( + uint8_t((token & 0x00ff0000) >> 16)); + + m_ctx.src[i].modifier = static_cast( + (token & 0x0f000000) >> 24); + + const bool extraToken = + relativeAddressingUsesToken(DxsoInstructionArgumentType::Source); + + if (m_ctx.src[i].hasRelative && extraToken) { + this->decodeRelativeRegister(m_ctx.src[i].relative, iter.read()); + return true; + } + + return false; + } + + + void DxsoDecodeContext::decodePredicateRegister(DxsoCodeIter& iter) { + uint32_t token = iter.read(); + + this->decodeGenericRegister(m_ctx.pred, token); + + m_ctx.pred.swizzle = DxsoRegSwizzle( + uint8_t((token & 0x00ff0000) >> 16)); + + m_ctx.pred.modifier = static_cast( + (token & 0x0f000000) >> 24); + } + + + bool DxsoDecodeContext::decodeInstruction(DxsoCodeIter& iter) { + uint32_t token = iter.read(); + + m_ctx.instructionIdx++; + + m_ctx.instruction.opcode = static_cast( + token & 0x0000ffff); + + m_ctx.instruction.predicated = token & (1 << 28); + + m_ctx.instruction.coissue = token & 0x40000000; + + m_ctx.instruction.specificData.uint32 = + (token & 0x00ff0000) >> 16; + + m_ctx.instruction.tokenLength = + this->decodeInstructionLength(token); + + uint32_t tokenLength = + m_ctx.instruction.tokenLength; + + switch (m_ctx.instruction.opcode) { + case DxsoOpcode::If: + case DxsoOpcode::Ifc: + case DxsoOpcode::Rep: + case DxsoOpcode::Loop: + case DxsoOpcode::BreakC: + case DxsoOpcode::BreakP: { + uint32_t sourceIdx = 0; + for (uint32_t i = 0; i < tokenLength; i++) { + if (this->decodeSourceRegister(sourceIdx, iter)) + i++; + + sourceIdx++; + } + return true; + } + + case DxsoOpcode::Dcl: + this->decodeDeclaration(iter); + this->decodeDestinationRegister(iter); + return true; + + case DxsoOpcode::Def: + case DxsoOpcode::DefI: + case DxsoOpcode::DefB: + this->decodeDestinationRegister(iter); + this->decodeDefinition( + m_ctx.instruction.opcode, iter); + return true; + + case DxsoOpcode::Comment: + iter = iter.skip(tokenLength); + return true; + + default: { + uint32_t sourceIdx = 0; + for (uint32_t i = 0; i < tokenLength; i++) { + if (i == 0) { + if (this->decodeDestinationRegister(iter)) + i++; + } + else if (i == 1 && m_ctx.instruction.predicated) { + // Relative addressing makes no sense + // for predicate registers. + this->decodePredicateRegister(iter); + } + else { + if (this->decodeSourceRegister(sourceIdx, iter)) + i++; + + sourceIdx++; + } + } + return true; + } + + case DxsoOpcode::End: + return false; + } + } + + std::ostream& operator << (std::ostream& os, DxsoUsage usage) { + switch (usage) { + case DxsoUsage::Position: os << "Position"; break; + case DxsoUsage::BlendWeight: os << "BlendWeight"; break; + case DxsoUsage::BlendIndices: os << "BlendIndices"; break; + case DxsoUsage::Normal: os << "Normal"; break; + case DxsoUsage::PointSize: os << "PointSize"; break; + case DxsoUsage::Texcoord: os << "Texcoord"; break; + case DxsoUsage::Tangent: os << "Tangent"; break; + case DxsoUsage::Binormal: os << "Binormal"; break; + case DxsoUsage::TessFactor: os << "TessFactor"; break; + case DxsoUsage::PositionT: os << "PositionT"; break; + case DxsoUsage::Color: os << "Color"; break; + case DxsoUsage::Fog: os << "Fog"; break; + case DxsoUsage::Depth: os << "Depth"; break; + case DxsoUsage::Sample: os << "Sample"; break; + default: + os << "Invalid Format (" << static_cast(usage) << ")"; break; + } + + return os; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxso/dxso_decoder.h b/utils/dxvk-1.10.3/src/dxso/dxso_decoder.h new file mode 100644 index 00000000000..178f80754b6 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxso/dxso_decoder.h @@ -0,0 +1,276 @@ +#pragma once + +#include "dxso_common.h" +#include "dxso_enums.h" +#include "dxso_code.h" + +namespace dxvk { + + constexpr size_t DxsoMaxTempRegs = 32; + constexpr size_t DxsoMaxTextureRegs = 10; + constexpr size_t DxsoMaxInterfaceRegs = 16; + constexpr size_t DxsoMaxOperandCount = 8; + + constexpr uint32_t DxsoRegModifierShift = 24; + + class DxsoDecodeContext; + + /** + * \brief Source operand modifiers + * + * These are applied after loading + * an operand register. + */ + enum class DxsoRegModifier : uint32_t { + None = 0, // r + Neg = 1, // -r + Bias = 2, // r - 0.5 + BiasNeg = 3, // -(r - 0.5) + Sign = 4, // fma(r, 2.0f, -1.0f) + SignNeg = 5, // -fma(r, 2.0f, -1.0f) + Comp = 6, // 1 - r + X2 = 7, // r * 2 + X2Neg = 8, // -r * 2 + Dz = 9, // r / r.z + Dw = 10, // r / r.w + Abs = 11, // abs(r) + AbsNeg = 12, // -abs(r) + Not = 13, // !r + }; + + enum class DxsoInstructionArgumentType : uint16_t { + Source, + Destination + }; + + enum class DxsoComparison : uint32_t { + // < = > + Never = 0, // 0 0 0 + GreaterThan = 1, // 0 0 1 + Equal = 2, // 0 1 0 + GreaterEqual = 3, // 0 1 1 + LessThan = 4, // 1 0 0 + NotEqual = 5, // 1 0 1 + LessEqual = 6, // 1 1 0 + Always = 7 // 1 1 1 + }; + + enum class DxsoTexLdMode : uint32_t { + Regular = 0, + Project = 1, + Bias = 2 + }; + + union DxsoOpcodeSpecificData { + DxsoComparison comparison; + DxsoTexLdMode texld; + + uint32_t uint32; + }; + + struct DxsoShaderInstruction { + DxsoOpcode opcode; + bool predicated; + bool coissue; + DxsoOpcodeSpecificData specificData; + + uint32_t tokenLength; + }; + + struct DxsoRegisterId { + DxsoRegisterType type; + uint32_t num; + + bool operator == (const DxsoRegisterId& other) const { return type == other.type && num == other.num; } + bool operator != (const DxsoRegisterId& other) const { return type != other.type || num != other.num; } + }; + + class DxsoRegMask { + + public: + + DxsoRegMask(uint8_t mask) + : m_mask(mask) { } + + DxsoRegMask(bool x, bool y, bool z, bool w) + : m_mask((x ? 0x1 : 0) | (y ? 0x2 : 0) + | (z ? 0x4 : 0) | (w ? 0x8 : 0)) { } + + bool operator [] (uint32_t id) const { + return ((m_mask & (1u << id)) != 0); + } + + uint32_t popCount() const { + const uint8_t n[16] = { 0, 1, 1, 2, 1, 2, 2, 3, + 1, 2, 2, 3, 2, 3, 3, 4 }; + return n[m_mask & 0xF]; + } + + uint32_t firstSet() const { + const uint8_t n[16] = { 4, 0, 1, 0, 2, 0, 1, 0, + 3, 0, 1, 0, 2, 0, 1, 0 }; + return n[m_mask & 0xF]; + } + + uint32_t minComponents() const { + const uint8_t n[16] = { 0, 1, 2, 2, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4 }; + return n[m_mask & 0xF]; + } + + bool operator == (const DxsoRegMask& other) const { return m_mask == other.m_mask; } + bool operator != (const DxsoRegMask& other) const { return m_mask != other.m_mask; } + + private: + + uint8_t m_mask; + + }; + + const DxsoRegMask IdentityWriteMask = DxsoRegMask(true, true, true, true); + + class DxsoRegSwizzle { + + public: + + DxsoRegSwizzle(uint8_t mask) + : m_mask(mask) { } + + DxsoRegSwizzle(uint32_t x, uint32_t y, uint32_t z, uint32_t w) + : m_mask((x << 0) | (y << 2) | (z << 4) | (w << 6)) {} + + uint32_t operator [] (uint32_t id) const { + return (m_mask >> (id + id)) & 0x3; + } + + bool operator == (const DxsoRegSwizzle& other) const { return m_mask == other.m_mask; } + bool operator != (const DxsoRegSwizzle& other) const { return m_mask != other.m_mask; } + + private: + + uint8_t m_mask; + + }; + + const DxsoRegSwizzle IdentitySwizzle{ 0, 1, 2, 3 }; + + struct DxsoBaseRegister { + DxsoRegisterId id = { DxsoRegisterType::Temp, 0 }; + bool centroid = false; + bool partialPrecision = false; + bool saturate = false; + DxsoRegModifier modifier = DxsoRegModifier::None; + DxsoRegMask mask = IdentityWriteMask; + DxsoRegSwizzle swizzle = IdentitySwizzle; + int8_t shift = 0; + }; + + struct DxsoRegister : public DxsoBaseRegister { + bool hasRelative = false; + DxsoBaseRegister relative; + }; + + struct DxsoSemantic { + DxsoUsage usage; + uint32_t usageIndex; + + bool operator== (const DxsoSemantic& b) const; + bool operator!= (const DxsoSemantic& b) const; + }; + + struct DxsoDeclaration { + DxsoSemantic semantic; + + DxsoTextureType textureType; + }; + + union DxsoDefinition { + float float32[4]; + int32_t int32[4]; + + // Not a type we actually use in compiler, but used for decoding. + uint32_t uint32[4]; + }; + + struct DxsoInstructionContext { + uint32_t instructionIdx; + + DxsoShaderInstruction instruction; + + DxsoRegister pred; + + DxsoRegister dst; + std::array< + DxsoRegister, + DxsoMaxOperandCount> src; + + DxsoDefinition def; + + DxsoDeclaration dcl; + }; + + class DxsoDecodeContext { + + public: + + DxsoDecodeContext(const DxsoProgramInfo& programInfo) + : m_programInfo( programInfo ) { + m_ctx.instructionIdx = 0; + } + + /** + * \brief Retrieves current instruction context + * + * This is only valid after a call to \ref decode. + * \returns Reference to last decoded instruction & its context + */ + const DxsoInstructionContext& getInstructionContext() const { + return m_ctx; + } + + const DxsoProgramInfo& getProgramInfo() const { + return m_programInfo; + } + + /** + * \brief Decodes an instruction + * + * This also advances the given code slice by the + * number of dwords consumed by the instruction. + * \param [in] code Code slice + */ + bool decodeInstruction(DxsoCodeIter& iter); + + private: + + uint32_t decodeInstructionLength(uint32_t token); + + void decodeBaseRegister( + DxsoBaseRegister& reg, + uint32_t token); + void decodeGenericRegister( + DxsoRegister& reg, + uint32_t token); + void decodeRelativeRegister( + DxsoBaseRegister& reg, + uint32_t token); + + // Returns whether an extra token was read. + bool decodeDestinationRegister(DxsoCodeIter& iter); + bool decodeSourceRegister(uint32_t i, DxsoCodeIter& iter); + void decodePredicateRegister(DxsoCodeIter& iter); + + void decodeDeclaration(DxsoCodeIter& iter); + void decodeDefinition(DxsoOpcode opcode, DxsoCodeIter& iter); + + bool relativeAddressingUsesToken(DxsoInstructionArgumentType type); + + const DxsoProgramInfo& m_programInfo; + + DxsoInstructionContext m_ctx; + + }; + + std::ostream& operator << (std::ostream& os, DxsoUsage usage); + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxso/dxso_enums.cpp b/utils/dxvk-1.10.3/src/dxso/dxso_enums.cpp new file mode 100644 index 00000000000..fc966c299a1 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxso/dxso_enums.cpp @@ -0,0 +1,101 @@ +#include "dxso_enums.h" + +namespace dxvk { + + std::ostream& operator << (std::ostream& os, DxsoOpcode opcode) { + switch (opcode) { + case DxsoOpcode::Nop: os << "Nop"; break; + case DxsoOpcode::Mov: os << "Mov"; break; + case DxsoOpcode::Add: os << "Add"; break; + case DxsoOpcode::Sub: os << "Sub"; break; + case DxsoOpcode::Mad: os << "Mad"; break; + case DxsoOpcode::Mul: os << "Mul"; break; + case DxsoOpcode::Rcp: os << "Rcp"; break; + case DxsoOpcode::Rsq: os << "Rsq"; break; + case DxsoOpcode::Dp3: os << "Dp3"; break; + case DxsoOpcode::Dp4: os << "Dp4"; break; + case DxsoOpcode::Min: os << "Min"; break; + case DxsoOpcode::Max: os << "Max"; break; + case DxsoOpcode::Slt: os << "Slt"; break; + case DxsoOpcode::Sge: os << "Sge"; break; + case DxsoOpcode::Exp: os << "Exp"; break; + case DxsoOpcode::Log: os << "Log"; break; + case DxsoOpcode::Lit: os << "Lit"; break; + case DxsoOpcode::Dst: os << "Dst"; break; + case DxsoOpcode::Lrp: os << "Lrp"; break; + case DxsoOpcode::Frc: os << "Frc"; break; + case DxsoOpcode::M4x4: os << "M4x4"; break; + case DxsoOpcode::M4x3: os << "M4x3"; break; + case DxsoOpcode::M3x4: os << "M3x4"; break; + case DxsoOpcode::M3x3: os << "M3x3"; break; + case DxsoOpcode::M3x2: os << "M3x2"; break; + case DxsoOpcode::Call: os << "Call"; break; + case DxsoOpcode::CallNz: os << "CallNz"; break; + case DxsoOpcode::Loop: os << "Loop"; break; + case DxsoOpcode::Ret: os << "Ret"; break; + case DxsoOpcode::EndLoop: os << "EndLoop"; break; + case DxsoOpcode::Label: os << "Label"; break; + case DxsoOpcode::Dcl: os << "Dcl"; break; + case DxsoOpcode::Pow: os << "Pow"; break; + case DxsoOpcode::Crs: os << "Crs"; break; + case DxsoOpcode::Sgn: os << "Sgn"; break; + case DxsoOpcode::Abs: os << "Abs"; break; + case DxsoOpcode::Nrm: os << "Nrm"; break; + case DxsoOpcode::SinCos: os << "SinCos"; break; + case DxsoOpcode::Rep: os << "Rep"; break; + case DxsoOpcode::EndRep: os << "EndRep"; break; + case DxsoOpcode::If: os << "If"; break; + case DxsoOpcode::Ifc: os << "Ifc"; break; + case DxsoOpcode::Else: os << "Else"; break; + case DxsoOpcode::EndIf: os << "EndIf"; break; + case DxsoOpcode::Break: os << "Break"; break; + case DxsoOpcode::BreakC: os << "BreakC"; break; + case DxsoOpcode::Mova: os << "Mova"; break; + case DxsoOpcode::DefB: os << "DefB"; break; + case DxsoOpcode::DefI: os << "DefI"; break; + + case DxsoOpcode::TexCoord: os << "TexCoord"; break; + case DxsoOpcode::TexKill: os << "TexKill"; break; + case DxsoOpcode::Tex: os << "Tex"; break; + case DxsoOpcode::TexBem: os << "TexBem"; break; + case DxsoOpcode::TexBemL: os << "TexBemL"; break; + case DxsoOpcode::TexReg2Ar: os << "TexReg2Ar"; break; + case DxsoOpcode::TexReg2Gb: os << "TexReg2Gb"; break; + case DxsoOpcode::TexM3x2Pad: os << "TexM3x2Pad"; break; + case DxsoOpcode::TexM3x2Tex: os << "TexM3x2Tex"; break; + case DxsoOpcode::TexM3x3Pad: os << "TexM3x3Pad"; break; + case DxsoOpcode::TexM3x3Tex: os << "TexM3x3Tex"; break; + case DxsoOpcode::Reserved0: os << "Reserved0"; break; + case DxsoOpcode::TexM3x3Spec: os << "TexM3x3Spec"; break; + case DxsoOpcode::TexM3x3VSpec: os << "TexM3x3VSpec"; break; + case DxsoOpcode::ExpP: os << "ExpP"; break; + case DxsoOpcode::LogP: os << "LogP"; break; + case DxsoOpcode::Cnd: os << "Cnd"; break; + case DxsoOpcode::Def: os << "Def"; break; + case DxsoOpcode::TexReg2Rgb: os << "TexReg2Rgb"; break; + case DxsoOpcode::TexDp3Tex: os << "TexDp3Tex"; break; + case DxsoOpcode::TexM3x2Depth: os << "TexM3x2Depth"; break; + case DxsoOpcode::TexDp3: os << "TexDp3"; break; + case DxsoOpcode::TexM3x3: os << "TexM3x3"; break; + case DxsoOpcode::TexDepth: os << "TexDepth"; break; + case DxsoOpcode::Cmp: os << "Cmp"; break; + case DxsoOpcode::Bem: os << "Bem"; break; + case DxsoOpcode::Dp2Add: os << "Dp2Add"; break; + case DxsoOpcode::DsX: os << "DsX"; break; + case DxsoOpcode::DsY: os << "DsY"; break; + case DxsoOpcode::TexLdd: os << "TexLdd"; break; + case DxsoOpcode::SetP: os << "SetP"; break; + case DxsoOpcode::TexLdl: os << "TexLdl"; break; + case DxsoOpcode::BreakP: os << "BreakP"; break; + + case DxsoOpcode::Phase: os << "Phase"; break; + case DxsoOpcode::Comment: os << "Comment"; break; + case DxsoOpcode::End: os << "End"; break; + default: + os << "Invalid Opcode (" << static_cast(opcode) << ")"; break; + } + + return os; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxso/dxso_enums.h b/utils/dxvk-1.10.3/src/dxso/dxso_enums.h new file mode 100644 index 00000000000..84f2e5b73f8 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxso/dxso_enums.h @@ -0,0 +1,164 @@ +#pragma once + +#include "dxso_include.h" + +#include + +namespace dxvk { + + /** + * \brief Instruction code listing + */ + enum class DxsoOpcode : uint32_t { + Nop = 0, + Mov , + Add , + Sub , + Mad , + Mul , + Rcp , + Rsq , + Dp3 , + Dp4 , + Min , + Max , + Slt , + Sge , + Exp , + Log , + Lit , + Dst , + Lrp , + Frc , + M4x4 , + M4x3 , + M3x4 , + M3x3 , + M3x2 , + Call , + CallNz , + Loop , + Ret , + EndLoop , + Label , + Dcl , + Pow , + Crs , + Sgn , + Abs , + Nrm , + SinCos , + Rep , + EndRep , + If , + Ifc , + Else , + EndIf , + Break , + BreakC , + Mova , + DefB , + DefI , + + TexCoord = 64, + TexKill , + Tex , + TexBem , + TexBemL , + TexReg2Ar , + TexReg2Gb , + TexM3x2Pad , + TexM3x2Tex , + TexM3x3Pad , + TexM3x3Tex , + Reserved0 , + TexM3x3Spec , + TexM3x3VSpec , + ExpP , + LogP , + Cnd , + Def , + TexReg2Rgb , + TexDp3Tex , + TexM3x2Depth , + TexDp3 , + TexM3x3 , + TexDepth , + Cmp , + Bem , + Dp2Add , + DsX , + DsY , + TexLdd , + SetP , + TexLdl , + BreakP , + + Phase = 0xfffd, + Comment = 0xfffe, + End = 0xffff + }; + + std::ostream& operator << (std::ostream& os, DxsoOpcode opcode); + + enum class DxsoRegisterType : uint32_t { + Temp = 0, // Temporary Register File + Input = 1, // Input Register File + Const = 2, // Constant Register File + Addr = 3, // Address Register (VS) + Texture = 3, // Texture Register File (PS) + RasterizerOut = 4, // Rasterizer Register File + AttributeOut = 5, // Attribute Output Register File + TexcoordOut = 6, // Texture Coordinate Output Register File + Output = 6, // Output register file for VS3.0+ + ConstInt = 7, // Constant Integer Vector Register File + ColorOut = 8, // Color Output Register File + DepthOut = 9, // Depth Output Register File + Sampler = 10, // Sampler State Register File + Const2 = 11, // Constant Register File 2048 - 4095 + Const3 = 12, // Constant Register File 4096 - 6143 + Const4 = 13, // Constant Register File 6144 - 8191 + ConstBool = 14, // Constant Boolean register file + Loop = 15, // Loop counter register file + TempFloat16 = 16, // 16-bit float temp register file + MiscType = 17, // Miscellaneous (single) registers. + Label = 18, // Label + Predicate = 19, // Predicate register + PixelTexcoord = 20 + }; + + enum class DxsoUsage : 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 + }; + + enum class DxsoTextureType : uint32_t { + Texture2D = 2, + TextureCube = 3, + Texture3D = 4 + }; + + enum DxsoReasterizerOutIndices : uint32_t { + RasterOutPosition = 0, + RasterOutFog = 1, + RasterOutPointSize = 2 + }; + + enum DxsoMiscTypeIndices : uint32_t { + MiscTypePosition, + MiscTypeFace, + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxso/dxso_header.cpp b/utils/dxvk-1.10.3/src/dxso/dxso_header.cpp new file mode 100644 index 00000000000..81077c95e3a --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxso/dxso_header.cpp @@ -0,0 +1,24 @@ +#include "dxso_header.h" + +namespace dxvk { + + DxsoHeader::DxsoHeader(DxsoReader& reader) { + uint32_t headerToken = reader.readu32(); + + uint32_t headerTypeMask = headerToken & 0xffff0000; + + DxsoProgramType programType; + if (headerTypeMask == 0xffff0000) + programType = DxsoProgramTypes::PixelShader; + else if (headerTypeMask == 0xfffe0000) + programType = DxsoProgramTypes::VertexShader; + else + throw DxvkError("DxsoHeader: invalid header - invalid version"); + + const uint32_t majorVersion = (headerToken >> 8) & 0xff; + const uint32_t minorVersion = headerToken & 0xff; + + m_info = DxsoProgramInfo{ programType, minorVersion, majorVersion }; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxso/dxso_header.h b/utils/dxvk-1.10.3/src/dxso/dxso_header.h new file mode 100644 index 00000000000..3a7f4bd3c9d --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxso/dxso_header.h @@ -0,0 +1,31 @@ +#pragma once + +#include "dxso_common.h" + +#include "dxso_reader.h" + +namespace dxvk { + +/** + * \brief DXSO header + * + * Stores meta information about the shader such + * as the version and the type. + */ + class DxsoHeader { + + public: + + DxsoHeader(DxsoReader& reader); + + const DxsoProgramInfo& info() const { + return m_info; + } + + private: + + DxsoProgramInfo m_info; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxso/dxso_include.h b/utils/dxvk-1.10.3/src/dxso/dxso_include.h new file mode 100644 index 00000000000..2f41e784ac0 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxso/dxso_include.h @@ -0,0 +1,18 @@ +#pragma once + +#include "../dxvk/dxvk_shader.h" + +#include "../util/com/com_guid.h" +#include "../util/com/com_object.h" +#include "../util/com/com_pointer.h" + +#include "../util/log/log.h" +#include "../util/log/log_debug.h" + +#include "../util/rc/util_rc.h" +#include "../util/rc/util_rc_ptr.h" + +#include "../util/util_bit.h" +#include "../util/util_enum.h" +#include "../util/util_error.h" +#include "../util/util_string.h" \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxso/dxso_isgn.h b/utils/dxvk-1.10.3/src/dxso/dxso_isgn.h new file mode 100644 index 00000000000..2faa04ef9e5 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxso/dxso_isgn.h @@ -0,0 +1,41 @@ +#pragma once + +#include "dxso_decoder.h" + +namespace dxvk { + + struct DxsoIsgnEntry { + uint32_t regNumber = 0; + uint32_t slot = 0; + DxsoSemantic semantic = DxsoSemantic{ DxsoUsage::Position, 0 }; + DxsoRegMask mask = IdentityWriteMask; + bool centroid = false; + }; + + struct DxsoIsgn { + std::array< + DxsoIsgnEntry, + 2 * DxsoMaxInterfaceRegs> elems; + uint32_t elemCount = 0; + }; + + struct DxsoDefinedConstant { + uint32_t uboIdx; + + // Only float constants may be indexed. + // So that's the only ones we care about putting in the UBO. + float float32[4]; + }; + + using DxsoDefinedConstants = std::vector; + + struct DxsoShaderMetaInfo { + bool needsConstantCopies = false; + uint32_t maxConstIndexF = 0; + uint32_t maxConstIndexI = 0; + uint32_t maxConstIndexB = 0; + + uint32_t boolConstantMask = 0; + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxso/dxso_modinfo.h b/utils/dxvk-1.10.3/src/dxso/dxso_modinfo.h new file mode 100644 index 00000000000..410c90f3872 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxso/dxso_modinfo.h @@ -0,0 +1,17 @@ +#pragma once + +#include "dxso_options.h" + +namespace dxvk { + + /** + * \brief Shader module info + * + * Stores information which may affect shader compilation. + * This data can be supplied by the client API implementation. + */ + struct DxsoModuleInfo { + DxsoOptions options; + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxso/dxso_module.cpp b/utils/dxvk-1.10.3/src/dxso/dxso_module.cpp new file mode 100644 index 00000000000..cf32cdaa203 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxso/dxso_module.cpp @@ -0,0 +1,87 @@ +#include "dxso_module.h" + +#include "dxso_code.h" +#include "dxso_compiler.h" + +#include + +namespace dxvk { + + DxsoModule::DxsoModule(DxsoReader& reader) + : m_header( reader ) + , m_code ( reader ) { } + + DxsoAnalysisInfo DxsoModule::analyze() { + DxsoAnalysisInfo info; + + DxsoAnalyzer analyzer(info); + + this->runAnalyzer(analyzer, m_code.iter()); + + return info; + } + + DxsoPermutations DxsoModule::compile( + const DxsoModuleInfo& moduleInfo, + const std::string& fileName, + const DxsoAnalysisInfo& analysis, + const D3D9ConstantLayout& layout) { + auto compiler = std::make_unique( + fileName, moduleInfo, + m_header.info(), analysis, + layout); + + this->runCompiler(*compiler, m_code.iter()); + m_isgn = compiler->isgn(); + + m_meta = compiler->meta(); + m_constants = compiler->constants(); + m_maxDefinedConst = compiler->maxDefinedConstant(); + m_usedSamplers = compiler->usedSamplers(); + m_usedRTs = compiler->usedRTs(); + + compiler->finalize(); + + return compiler->compile(); + } + + void DxsoModule::runAnalyzer( + DxsoAnalyzer& analyzer, + DxsoCodeIter iter) const { + DxsoCodeIter start = iter; + + DxsoDecodeContext decoder(m_header.info()); + + while (decoder.decodeInstruction(iter)) + analyzer.processInstruction( + decoder.getInstructionContext()); + + size_t tokenCount = size_t(iter.ptrAt(0) - start.ptrAt(0)); + + // We need to account for the header token in the bytecode size... + + // At this point, start is offset by the header due to us this being + // a *code* iterator, and not the general reader class. + // [start token] ^(start caret)^ [frog rendering code] [end token] ^(end caret)^ + // where the tokenCount above is inbetween the start and end carets. + + // We need to account for this otherwise it will show up as us not + // accounting for the *end* token in GetFunction due to the total size being + // offset by -1. + // [start token] [frog rendering code] (end of tokenCount) [end token] + tokenCount += 1; + + analyzer.finalize(tokenCount); + } + + void DxsoModule::runCompiler( + DxsoCompiler& compiler, + DxsoCodeIter iter) const { + DxsoDecodeContext decoder(m_header.info()); + + while (decoder.decodeInstruction(iter)) + compiler.processInstruction( + decoder.getInstructionContext()); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxso/dxso_module.h b/utils/dxvk-1.10.3/src/dxso/dxso_module.h new file mode 100644 index 00000000000..4b8238df3df --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxso/dxso_module.h @@ -0,0 +1,88 @@ +#pragma once + +#include "dxso_reader.h" +#include "dxso_code.h" +#include "dxso_header.h" +#include "dxso_ctab.h" + +#include "dxso_isgn.h" +#include "dxso_analysis.h" + +#include "../d3d9/d3d9_constant_layout.h" +#include "../d3d9/d3d9_shader_permutations.h" + +#include + +namespace dxvk { + + class DxsoCompiler; + class DxsoCode; + struct DxsoModuleInfo; + + /** + * \brief DXSO shader module, a d3d9 shader object. + */ + class DxsoModule { + + public: + + DxsoModule(DxsoReader& reader); + + const DxsoProgramInfo& info() { + return m_header.info(); + } + + DxsoAnalysisInfo analyze(); + + /** + * \brief Compiles DXSO shader to SPIR-V module + * + * \param [in] moduleInfo DXSO module info + * \param [in] fileName File name, will be added to + * the compiled SPIR-V for debugging purposes. + * \returns The compiled shader object + */ + DxsoPermutations compile( + const DxsoModuleInfo& moduleInfo, + const std::string& fileName, + const DxsoAnalysisInfo& analysis, + const D3D9ConstantLayout& layout); + + const DxsoIsgn& isgn() { + return m_isgn; + } + + const DxsoShaderMetaInfo& meta() { return m_meta; } + + const DxsoDefinedConstants& constants() { return m_constants; } + + uint32_t usedSamplers() { return m_usedSamplers; } + + uint32_t usedRTs() { return m_usedRTs; } + + uint32_t maxDefinedConstant() { return m_maxDefinedConst; } + + private: + + void runCompiler( + DxsoCompiler& compiler, + DxsoCodeIter iter) const; + + void runAnalyzer( + DxsoAnalyzer& analyzer, + DxsoCodeIter iter) const; + + DxsoHeader m_header; + DxsoCode m_code; + + DxsoIsgn m_isgn; + uint32_t m_usedSamplers; + uint32_t m_usedRTs; + + DxsoShaderMetaInfo m_meta; + uint32_t m_maxDefinedConst; + DxsoDefinedConstants m_constants; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxso/dxso_options.cpp b/utils/dxvk-1.10.3/src/dxso/dxso_options.cpp new file mode 100644 index 00000000000..5e05ee6504a --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxso/dxso_options.cpp @@ -0,0 +1,50 @@ +#include "dxso_options.h" + +#include "../d3d9/d3d9_device.h" + +namespace dxvk { + + DxsoOptions::DxsoOptions() {} + + DxsoOptions::DxsoOptions(D3D9DeviceEx* pDevice, const D3D9Options& options) { + const Rc device = pDevice->GetDXVKDevice(); + + const Rc adapter = device->adapter(); + + const DxvkDeviceFeatures& devFeatures = device->features(); + const DxvkDeviceInfo& devInfo = adapter->devicePropertiesExt(); + + useDemoteToHelperInvocation + = (devFeatures.extShaderDemoteToHelperInvocation.shaderDemoteToHelperInvocation); + + useSubgroupOpsForEarlyDiscard + = (devInfo.coreSubgroup.subgroupSize >= 4) + && (devInfo.coreSubgroup.supportedStages & VK_SHADER_STAGE_FRAGMENT_BIT) + && (devInfo.coreSubgroup.supportedOperations & VK_SUBGROUP_FEATURE_BALLOT_BIT); + + // Disable early discard on Nvidia because it may hurt performance + if (adapter->matchesDriver(DxvkGpuVendor::Nvidia, VK_DRIVER_ID_NVIDIA_PROPRIETARY_KHR, 0, 0)) + useSubgroupOpsForEarlyDiscard = false; + + // Apply shader-related options + strictConstantCopies = options.strictConstantCopies; + + strictPow = options.strictPow; + d3d9FloatEmulation = options.d3d9FloatEmulation; + + shaderModel = options.shaderModel; + + invariantPosition = options.invariantPosition; + + forceSamplerTypeSpecConstants = options.forceSamplerTypeSpecConstants; + + vertexFloatConstantBufferAsSSBO = pDevice->GetVertexConstantLayout().floatSize() > devInfo.core.properties.limits.maxUniformBufferRange; + + longMad = options.longMad; + + alphaTestWiggleRoom = options.alphaTestWiggleRoom; + + robustness2Supported = devFeatures.extRobustness2.robustBufferAccess2; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxso/dxso_options.h b/utils/dxvk-1.10.3/src/dxso/dxso_options.h new file mode 100644 index 00000000000..c977ce8a31f --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxso/dxso_options.h @@ -0,0 +1,62 @@ +#pragma once + +#include "../dxvk/dxvk_device.h" +#include "../d3d9/d3d9_options.h" + +namespace dxvk { + + class D3D9DeviceEx; + struct D3D9Options; + + struct DxsoOptions { + DxsoOptions(); + DxsoOptions(D3D9DeviceEx* pDevice, const D3D9Options& options); + + /// Use a SPIR-V extension to implement D3D-style discards + bool useDemoteToHelperInvocation = false; + + /// Use subgroup operations to discard fragment + /// shader invocations if derivatives remain valid. + bool useSubgroupOpsForEarlyDiscard = false; + + /// True: Copy our constant set into UBO if we are relative indexing ever. + /// False: Copy our constant set into UBO if we are relative indexing at the start of a defined constant + /// Why?: In theory, FXC should never generate code where this would be an issue. + bool strictConstantCopies; + + /// Whether to emulate d3d9 float behaviour using clampps + /// True: Perform emulation to emulate behaviour (ie. anything * 0 = 0) + /// False: Don't do anything. + D3D9FloatEmulation d3d9FloatEmulation; + + /// Whether or not we should care about pow(0, 0) = 1 + bool strictPow; + + /// Max version of shader to support + uint32_t shaderModel; + + /// Work around a NV driver quirk + /// Fixes flickering/z-fighting in some games. + bool invariantPosition; + + /// Always use a spec constant to determine sampler type (instead of just in PS 1.x) + /// Works around a game bug in Halo CE where it gives cube textures to 2d/volume samplers + bool forceSamplerTypeSpecConstants; + + /// Should the SWVP float constant buffer be a SSBO (because of the size on NV) + bool vertexFloatConstantBufferAsSSBO; + + /// Should we make our Mads a FFma or do it the long way with an FMul and an FAdd? + /// This solves some rendering bugs in games that have z-pass shaders which + /// don't match entirely to the regular vertex shader in this way. + bool longMad; + + /// Workaround for games using alpha test == 1.0, etc due to wonky interpolation or + /// misc. imprecision on some vendors + bool alphaTestWiggleRoom; + + /// Whether or not we can rely on robustness2 to handle oob constant access + bool robustness2Supported; + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxso/dxso_reader.cpp b/utils/dxvk-1.10.3/src/dxso/dxso_reader.cpp new file mode 100644 index 00000000000..ab47f2833ad --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxso/dxso_reader.cpp @@ -0,0 +1,26 @@ +#include "dxso_reader.h" + +#include + +namespace dxvk { + + DxbcTag DxsoReader::readTag() { + DxbcTag tag; + this->read(&tag, 4); + return tag; + } + + void DxsoReader::read(void* dst, size_t n) { + std::memcpy(dst, m_data + m_pos, n); + m_pos += n; + } + + void DxsoReader::skip(size_t n) { + m_pos += n; + } + + void DxsoReader::store(std::ostream && stream, size_t size) const { + stream.write(m_data, size); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxso/dxso_reader.h b/utils/dxvk-1.10.3/src/dxso/dxso_reader.h new file mode 100644 index 00000000000..fa650bb894e --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxso/dxso_reader.h @@ -0,0 +1,60 @@ +#pragma once + +#include "dxso_include.h" + +#include "../dxbc/dxbc_tag.h" + +#include + +namespace dxvk { + + /** + * \brief DXSO (d3d9) bytecode reader + * + * Holds references to the shader byte code and + * provides methods to read + */ + class DxsoReader { + + public: + + DxsoReader(const char* data) + : DxsoReader(data, 0) { } + + size_t pos() { + return m_pos; + } + + auto readu32() { return this->readNum (); } + auto readf32() { return this->readNum (); } + + DxbcTag readTag(); + + void read(void* dst, size_t n); + + void skip(size_t n); + + void store(std::ostream&& stream, size_t size) const; + + const char* currentPtr() { + return m_data + m_pos; + } + + private: + + DxsoReader(const char* data, size_t pos) + : m_data(data), m_pos(pos) { } + + const char* m_data = nullptr; + size_t m_pos = 0; + + template + T readNum() { + T result; + this->read(&result, sizeof(result)); + return result; + } + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxso/dxso_tables.cpp b/utils/dxvk-1.10.3/src/dxso/dxso_tables.cpp new file mode 100644 index 00000000000..5b8ab91f087 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxso/dxso_tables.cpp @@ -0,0 +1,93 @@ +#include "dxso_tables.h" + +namespace dxvk { + + uint32_t DxsoGetDefaultOpcodeLength(DxsoOpcode opcode) { + + switch (opcode) { + case DxsoOpcode::Nop: return 0; + case DxsoOpcode::Mov: return 2; + case DxsoOpcode::Add: return 3; + case DxsoOpcode::Sub: return 3; + case DxsoOpcode::Mad: return 4; + case DxsoOpcode::Mul: return 3; + case DxsoOpcode::Rcp: return 2; + case DxsoOpcode::Rsq: return 2; + case DxsoOpcode::Dp3: return 3; + case DxsoOpcode::Dp4: return 3; + case DxsoOpcode::Min: return 3; + case DxsoOpcode::Max: return 3; + case DxsoOpcode::Slt: return 3; + case DxsoOpcode::Sge: return 3; + case DxsoOpcode::Exp: return 2; + case DxsoOpcode::Log: return 2; + case DxsoOpcode::Lit: return 2; + case DxsoOpcode::Dst: return 3; + case DxsoOpcode::Lrp: return 4; + case DxsoOpcode::Frc: return 2; + case DxsoOpcode::M4x4: return 3; + case DxsoOpcode::M4x3: return 3; + case DxsoOpcode::M3x4: return 3; + case DxsoOpcode::M3x3: return 3; + case DxsoOpcode::M3x2: return 3; + case DxsoOpcode::Call: return 1; + case DxsoOpcode::CallNz: return 2; + case DxsoOpcode::Loop: return 2; + case DxsoOpcode::Ret: return 0; + case DxsoOpcode::EndLoop: return 0; + case DxsoOpcode::Label: return 1; + case DxsoOpcode::Dcl: return 2; + case DxsoOpcode::Pow: return 3; + case DxsoOpcode::Crs: return 3; + case DxsoOpcode::Sgn: return 4; + case DxsoOpcode::Abs: return 2; + case DxsoOpcode::Nrm: return 2; + case DxsoOpcode::SinCos: return 4; + case DxsoOpcode::Rep: return 1; + case DxsoOpcode::EndRep: return 0; + case DxsoOpcode::If: return 1; + case DxsoOpcode::Ifc: return 2; + case DxsoOpcode::Else: return 0; + case DxsoOpcode::EndIf: return 0; + case DxsoOpcode::Break: return 0; + case DxsoOpcode::BreakC: return 2; + case DxsoOpcode::Mova: return 2; + case DxsoOpcode::DefB: return 2; + case DxsoOpcode::DefI: return 5; + case DxsoOpcode::TexCoord: return 1; + case DxsoOpcode::TexKill: return 1; + case DxsoOpcode::Tex: return 1; + case DxsoOpcode::TexBem: return 2; + case DxsoOpcode::TexBemL: return 2; + case DxsoOpcode::TexReg2Ar: return 2; + case DxsoOpcode::TexReg2Gb: return 2; + case DxsoOpcode::TexM3x2Pad: return 2; + case DxsoOpcode::TexM3x2Tex: return 2; + case DxsoOpcode::TexM3x3Pad: return 2; + case DxsoOpcode::TexM3x3Tex: return 2; + case DxsoOpcode::TexM3x3Spec: return 3; + case DxsoOpcode::TexM3x3VSpec: return 2; + case DxsoOpcode::ExpP: return 2; + case DxsoOpcode::LogP: return 2; + case DxsoOpcode::Cnd: return 4; + case DxsoOpcode::Def: return 5; + case DxsoOpcode::TexReg2Rgb: return 2; + case DxsoOpcode::TexDp3Tex: return 2; + case DxsoOpcode::TexM3x2Depth: return 2; + case DxsoOpcode::TexDp3: return 2; + case DxsoOpcode::TexM3x3: return 2; + case DxsoOpcode::TexDepth: return 1; + case DxsoOpcode::Cmp: return 4; + case DxsoOpcode::Bem: return 3; + case DxsoOpcode::Dp2Add: return 4; + case DxsoOpcode::DsX: return 2; + case DxsoOpcode::DsY: return 2; + case DxsoOpcode::TexLdd: return 5; + case DxsoOpcode::SetP: return 3; + case DxsoOpcode::TexLdl: return 3; + case DxsoOpcode::BreakP: return 2; + default: Logger::warn("DxsoGetDefaultOpcodeLength: unknown opcode to get default length for."); return UINT32_MAX; + } + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxso/dxso_tables.h b/utils/dxvk-1.10.3/src/dxso/dxso_tables.h new file mode 100644 index 00000000000..73e3801d3bd --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxso/dxso_tables.h @@ -0,0 +1,11 @@ +#pragma once + +#include "dxso_enums.h" + +namespace dxvk { + + constexpr uint32_t InvalidOpcodeLength = UINT32_MAX; + + uint32_t DxsoGetDefaultOpcodeLength(DxsoOpcode opcode); + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxso/dxso_util.cpp b/utils/dxvk-1.10.3/src/dxso/dxso_util.cpp new file mode 100644 index 00000000000..16a75082642 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxso/dxso_util.cpp @@ -0,0 +1,34 @@ +#include "dxso_util.h" + +#include "dxso_include.h" + +namespace dxvk { + + dxvk::mutex g_linkerSlotMutex; + uint32_t g_linkerSlotCount = 0; + std::array g_linkerSlots; + + uint32_t RegisterLinkerSlot(DxsoSemantic semantic) { + // Lock, because games could be trying + // to make multiple shaders at a time. + std::lock_guard lock(g_linkerSlotMutex); + + // Need to chose a slot that maps nicely and similarly + // between vertex and pixel shaders + + // Find or map a slot. + uint32_t slot = g_linkerSlotCount; + for (uint32_t j = 0; j < g_linkerSlotCount; j++) { + if (g_linkerSlots[j] == semantic) { + slot = j; + break; + } + } + + if (slot == g_linkerSlotCount) + g_linkerSlots[g_linkerSlotCount++] = semantic; + + return slot; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxso/dxso_util.h b/utils/dxvk-1.10.3/src/dxso/dxso_util.h new file mode 100644 index 00000000000..3a94acfb1a0 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxso/dxso_util.h @@ -0,0 +1,58 @@ +#pragma once + +#include + +#include "dxso_common.h" +#include "dxso_decoder.h" + +#include "../d3d9/d3d9_caps.h" + +namespace dxvk { + + enum class DxsoBindingType : uint32_t { + ConstantBuffer, + Image, + }; + + enum class DxsoConstantBufferType : uint32_t { + Float, + Int, + Bool + }; + + enum DxsoConstantBuffers : uint32_t { + VSConstantBuffer = 0, + VSFloatConstantBuffer = 0, + VSIntConstantBuffer = 1, + VSBoolConstantBuffer = 2, + VSClipPlanes = 3, + VSFixedFunction = 4, + VSVertexBlendData = 5, + VSCount, + + PSConstantBuffer = 0, + PSFixedFunction = 1, + PSShared = 2, + PSCount + }; + + constexpr uint32_t computeResourceSlotId( + DxsoProgramType shaderStage, + DxsoBindingType bindingType, + uint32_t bindingIndex) { + const uint32_t stageOffset = (DxsoConstantBuffers::VSCount + caps::MaxTexturesVS) * uint32_t(shaderStage); + + if (bindingType == DxsoBindingType::ConstantBuffer) + return bindingIndex + stageOffset; + else // if (bindingType == DxsoBindingType::Image) + return bindingIndex + stageOffset + (shaderStage == DxsoProgramType::PixelShader ? DxsoConstantBuffers::PSCount : DxsoConstantBuffers::VSCount); + } + + // TODO: Intergrate into compute resource slot ID/refactor all of this? + constexpr uint32_t getSWVPBufferSlot() { + return DxsoConstantBuffers::VSCount + caps::MaxTexturesVS + DxsoConstantBuffers::PSCount + caps::MaxTexturesPS + 1; // From last pixel shader slot, above. + } + + uint32_t RegisterLinkerSlot(DxsoSemantic semantic); + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxso/meson.build b/utils/dxvk-1.10.3/src/dxso/meson.build new file mode 100644 index 00000000000..f8d28fc67cf --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxso/meson.build @@ -0,0 +1,24 @@ +dxso_src = files([ + 'dxso_common.cpp', + 'dxso_options.cpp', + 'dxso_module.cpp', + 'dxso_reader.cpp', + 'dxso_header.cpp', + 'dxso_ctab.cpp', + 'dxso_util.cpp', + 'dxso_code.cpp', + 'dxso_tables.cpp', + 'dxso_decoder.cpp', + 'dxso_analysis.cpp', + 'dxso_compiler.cpp', + 'dxso_enums.cpp' +]) + +dxso_lib = static_library('dxso', dxso_src, + include_directories : [ dxvk_include_path ], +) + +dxso_dep = declare_dependency( + link_with : [ dxso_lib ], + include_directories : [ dxvk_include_path ], +) diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_adapter.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_adapter.cpp new file mode 100644 index 00000000000..24c7cea720f --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_adapter.cpp @@ -0,0 +1,849 @@ +#include +#include + +#include "dxvk_adapter.h" +#include "dxvk_device.h" +#include "dxvk_instance.h" + +namespace dxvk { + + DxvkAdapter::DxvkAdapter( + const Rc& vki, + VkPhysicalDevice handle) + : m_vki (vki), + m_handle (handle) { + this->initHeapAllocInfo(); + this->queryExtensions(); + this->queryDeviceInfo(); + this->queryDeviceFeatures(); + this->queryDeviceQueues(); + + m_hasMemoryBudget = m_deviceExtensions.supports(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME); + } + + + DxvkAdapter::~DxvkAdapter() { + + } + + + DxvkAdapterMemoryInfo DxvkAdapter::getMemoryHeapInfo() const { + VkPhysicalDeviceMemoryBudgetPropertiesEXT memBudget = { }; + memBudget.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT; + memBudget.pNext = nullptr; + + VkPhysicalDeviceMemoryProperties2 memProps = { }; + memProps.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2; + memProps.pNext = m_hasMemoryBudget ? &memBudget : nullptr; + + m_vki->vkGetPhysicalDeviceMemoryProperties2(m_handle, &memProps); + + DxvkAdapterMemoryInfo info = { }; + info.heapCount = memProps.memoryProperties.memoryHeapCount; + + for (uint32_t i = 0; i < info.heapCount; i++) { + info.heaps[i].heapFlags = memProps.memoryProperties.memoryHeaps[i].flags; + + if (m_hasMemoryBudget) { + info.heaps[i].memoryBudget = memBudget.heapBudget[i]; + info.heaps[i].memoryAllocated = memBudget.heapUsage[i]; + } else { + info.heaps[i].memoryBudget = memProps.memoryProperties.memoryHeaps[i].size; + info.heaps[i].memoryAllocated = m_heapAlloc[i].load(); + } + } + + return info; + } + + + VkPhysicalDeviceMemoryProperties DxvkAdapter::memoryProperties() const { + VkPhysicalDeviceMemoryProperties memoryProperties; + m_vki->vkGetPhysicalDeviceMemoryProperties(m_handle, &memoryProperties); + return memoryProperties; + } + + + VkFormatProperties DxvkAdapter::formatProperties(VkFormat format) const { + VkFormatProperties formatProperties; + m_vki->vkGetPhysicalDeviceFormatProperties(m_handle, format, &formatProperties); + return formatProperties; + } + + + VkResult DxvkAdapter::imageFormatProperties( + VkFormat format, + VkImageType type, + VkImageTiling tiling, + VkImageUsageFlags usage, + VkImageCreateFlags flags, + VkImageFormatProperties& properties) const { + return m_vki->vkGetPhysicalDeviceImageFormatProperties( + m_handle, format, type, tiling, usage, flags, &properties); + } + + + DxvkAdapterQueueIndices DxvkAdapter::findQueueFamilies() const { + uint32_t graphicsQueue = findQueueFamily( + VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, + VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT); + + uint32_t computeQueue = findQueueFamily( + VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, + VK_QUEUE_COMPUTE_BIT); + + if (computeQueue == VK_QUEUE_FAMILY_IGNORED) + computeQueue = graphicsQueue; + + uint32_t transferQueue = findQueueFamily( + VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT, + VK_QUEUE_TRANSFER_BIT); + + if (transferQueue == VK_QUEUE_FAMILY_IGNORED) + transferQueue = computeQueue; + + DxvkAdapterQueueIndices queues; + queues.graphics = graphicsQueue; + queues.transfer = transferQueue; + return queues; + } + + + bool DxvkAdapter::checkFeatureSupport(const DxvkDeviceFeatures& required) const { + return (m_deviceFeatures.core.features.robustBufferAccess + || !required.core.features.robustBufferAccess) + && (m_deviceFeatures.core.features.fullDrawIndexUint32 + || !required.core.features.fullDrawIndexUint32) + && (m_deviceFeatures.core.features.imageCubeArray + || !required.core.features.imageCubeArray) + && (m_deviceFeatures.core.features.independentBlend + || !required.core.features.independentBlend) + && (m_deviceFeatures.core.features.geometryShader + || !required.core.features.geometryShader) + && (m_deviceFeatures.core.features.tessellationShader + || !required.core.features.tessellationShader) + && (m_deviceFeatures.core.features.sampleRateShading + || !required.core.features.sampleRateShading) + && (m_deviceFeatures.core.features.dualSrcBlend + || !required.core.features.dualSrcBlend) + && (m_deviceFeatures.core.features.logicOp + || !required.core.features.logicOp) + && (m_deviceFeatures.core.features.multiDrawIndirect + || !required.core.features.multiDrawIndirect) + && (m_deviceFeatures.core.features.drawIndirectFirstInstance + || !required.core.features.drawIndirectFirstInstance) + && (m_deviceFeatures.core.features.depthClamp + || !required.core.features.depthClamp) + && (m_deviceFeatures.core.features.depthBiasClamp + || !required.core.features.depthBiasClamp) + && (m_deviceFeatures.core.features.fillModeNonSolid + || !required.core.features.fillModeNonSolid) + && (m_deviceFeatures.core.features.depthBounds + || !required.core.features.depthBounds) + && (m_deviceFeatures.core.features.wideLines + || !required.core.features.wideLines) + && (m_deviceFeatures.core.features.largePoints + || !required.core.features.largePoints) + && (m_deviceFeatures.core.features.alphaToOne + || !required.core.features.alphaToOne) + && (m_deviceFeatures.core.features.multiViewport + || !required.core.features.multiViewport) + && (m_deviceFeatures.core.features.samplerAnisotropy + || !required.core.features.samplerAnisotropy) + && (m_deviceFeatures.core.features.textureCompressionETC2 + || !required.core.features.textureCompressionETC2) + && (m_deviceFeatures.core.features.textureCompressionASTC_LDR + || !required.core.features.textureCompressionASTC_LDR) + && (m_deviceFeatures.core.features.textureCompressionBC + || !required.core.features.textureCompressionBC) + && (m_deviceFeatures.core.features.occlusionQueryPrecise + || !required.core.features.occlusionQueryPrecise) + && (m_deviceFeatures.core.features.pipelineStatisticsQuery + || !required.core.features.pipelineStatisticsQuery) + && (m_deviceFeatures.core.features.vertexPipelineStoresAndAtomics + || !required.core.features.vertexPipelineStoresAndAtomics) + && (m_deviceFeatures.core.features.fragmentStoresAndAtomics + || !required.core.features.fragmentStoresAndAtomics) + && (m_deviceFeatures.core.features.shaderTessellationAndGeometryPointSize + || !required.core.features.shaderTessellationAndGeometryPointSize) + && (m_deviceFeatures.core.features.shaderImageGatherExtended + || !required.core.features.shaderImageGatherExtended) + && (m_deviceFeatures.core.features.shaderStorageImageExtendedFormats + || !required.core.features.shaderStorageImageExtendedFormats) + && (m_deviceFeatures.core.features.shaderStorageImageMultisample + || !required.core.features.shaderStorageImageMultisample) + && (m_deviceFeatures.core.features.shaderStorageImageReadWithoutFormat + || !required.core.features.shaderStorageImageReadWithoutFormat) + && (m_deviceFeatures.core.features.shaderStorageImageWriteWithoutFormat + || !required.core.features.shaderStorageImageWriteWithoutFormat) + && (m_deviceFeatures.core.features.shaderUniformBufferArrayDynamicIndexing + || !required.core.features.shaderUniformBufferArrayDynamicIndexing) + && (m_deviceFeatures.core.features.shaderSampledImageArrayDynamicIndexing + || !required.core.features.shaderSampledImageArrayDynamicIndexing) + && (m_deviceFeatures.core.features.shaderStorageBufferArrayDynamicIndexing + || !required.core.features.shaderStorageBufferArrayDynamicIndexing) + && (m_deviceFeatures.core.features.shaderStorageImageArrayDynamicIndexing + || !required.core.features.shaderStorageImageArrayDynamicIndexing) + && (m_deviceFeatures.core.features.shaderClipDistance + || !required.core.features.shaderClipDistance) + && (m_deviceFeatures.core.features.shaderCullDistance + || !required.core.features.shaderCullDistance) + && (m_deviceFeatures.core.features.shaderFloat64 + || !required.core.features.shaderFloat64) + && (m_deviceFeatures.core.features.shaderInt64 + || !required.core.features.shaderInt64) + && (m_deviceFeatures.core.features.shaderInt16 + || !required.core.features.shaderInt16) + && (m_deviceFeatures.core.features.shaderResourceResidency + || !required.core.features.shaderResourceResidency) + && (m_deviceFeatures.core.features.shaderResourceMinLod + || !required.core.features.shaderResourceMinLod) + && (m_deviceFeatures.core.features.sparseBinding + || !required.core.features.sparseBinding) + && (m_deviceFeatures.core.features.sparseResidencyBuffer + || !required.core.features.sparseResidencyBuffer) + && (m_deviceFeatures.core.features.sparseResidencyImage2D + || !required.core.features.sparseResidencyImage2D) + && (m_deviceFeatures.core.features.sparseResidencyImage3D + || !required.core.features.sparseResidencyImage3D) + && (m_deviceFeatures.core.features.sparseResidency2Samples + || !required.core.features.sparseResidency2Samples) + && (m_deviceFeatures.core.features.sparseResidency4Samples + || !required.core.features.sparseResidency4Samples) + && (m_deviceFeatures.core.features.sparseResidency8Samples + || !required.core.features.sparseResidency8Samples) + && (m_deviceFeatures.core.features.sparseResidency16Samples + || !required.core.features.sparseResidency16Samples) + && (m_deviceFeatures.core.features.sparseResidencyAliased + || !required.core.features.sparseResidencyAliased) + && (m_deviceFeatures.core.features.variableMultisampleRate + || !required.core.features.variableMultisampleRate) + && (m_deviceFeatures.core.features.inheritedQueries + || !required.core.features.inheritedQueries) + && (m_deviceFeatures.shaderDrawParameters.shaderDrawParameters + || !required.shaderDrawParameters.shaderDrawParameters) + && (m_deviceFeatures.ext4444Formats.formatA4R4G4B4 + || !required.ext4444Formats.formatA4R4G4B4) + && (m_deviceFeatures.ext4444Formats.formatA4B4G4R4 + || !required.ext4444Formats.formatA4B4G4R4) + && (m_deviceFeatures.extCustomBorderColor.customBorderColors + || !required.extCustomBorderColor.customBorderColors) + && (m_deviceFeatures.extCustomBorderColor.customBorderColorWithoutFormat + || !required.extCustomBorderColor.customBorderColorWithoutFormat) + && (m_deviceFeatures.extDepthClipEnable.depthClipEnable + || !required.extDepthClipEnable.depthClipEnable) + && (m_deviceFeatures.extExtendedDynamicState.extendedDynamicState + || !required.extExtendedDynamicState.extendedDynamicState) + && (m_deviceFeatures.extHostQueryReset.hostQueryReset + || !required.extHostQueryReset.hostQueryReset) + && (m_deviceFeatures.extMemoryPriority.memoryPriority + || !required.extMemoryPriority.memoryPriority) + && (m_deviceFeatures.extNonSeamlessCubeMap.nonSeamlessCubeMap + || !required.extNonSeamlessCubeMap.nonSeamlessCubeMap) + && (m_deviceFeatures.extRobustness2.robustBufferAccess2 + || !required.extRobustness2.robustBufferAccess2) + && (m_deviceFeatures.extRobustness2.robustImageAccess2 + || !required.extRobustness2.robustImageAccess2) + && (m_deviceFeatures.extRobustness2.nullDescriptor + || !required.extRobustness2.nullDescriptor) + && (m_deviceFeatures.extTransformFeedback.transformFeedback + || !required.extTransformFeedback.transformFeedback) + && (m_deviceFeatures.extVertexAttributeDivisor.vertexAttributeInstanceRateDivisor + || !required.extVertexAttributeDivisor.vertexAttributeInstanceRateDivisor) + && (m_deviceFeatures.extVertexAttributeDivisor.vertexAttributeInstanceRateZeroDivisor + || !required.extVertexAttributeDivisor.vertexAttributeInstanceRateZeroDivisor) + && (m_deviceFeatures.khrTimelineSemaphore.timelineSemaphore + || !required.khrTimelineSemaphore.timelineSemaphore); + } + + + void DxvkAdapter::enableExtensions(const DxvkNameSet& extensions) { + m_extraExtensions.merge(extensions); + } + + + Rc DxvkAdapter::createDevice( + const Rc& instance, + DxvkDeviceFeatures enabledFeatures) { + DxvkDeviceExtensions devExtensions; + + std::array devExtensionList = {{ + &devExtensions.amdMemoryOverallocationBehaviour, + &devExtensions.amdShaderFragmentMask, + &devExtensions.ext4444Formats, + &devExtensions.extConservativeRasterization, + &devExtensions.extCustomBorderColor, + &devExtensions.extDepthClipEnable, + &devExtensions.extExtendedDynamicState, + &devExtensions.extFullScreenExclusive, + &devExtensions.extHostQueryReset, + &devExtensions.extMemoryBudget, + &devExtensions.extMemoryPriority, + &devExtensions.extNonSeamlessCubeMap, + &devExtensions.extRobustness2, + &devExtensions.extShaderDemoteToHelperInvocation, + &devExtensions.extShaderStencilExport, + &devExtensions.extShaderViewportIndexLayer, + &devExtensions.extTransformFeedback, + &devExtensions.extVertexAttributeDivisor, + &devExtensions.khrBufferDeviceAddress, + &devExtensions.khrCreateRenderPass2, + &devExtensions.khrDepthStencilResolve, + &devExtensions.khrDrawIndirectCount, + &devExtensions.khrDriverProperties, + &devExtensions.khrExternalMemoryWin32, + &devExtensions.khrExternalSemaphoreWin32, + &devExtensions.khrImageFormatList, + &devExtensions.khrSamplerMirrorClampToEdge, + &devExtensions.khrShaderFloatControls, + &devExtensions.khrSwapchain, + &devExtensions.khrTimelineSemaphore, + &devExtensions.nvxBinaryImport, + &devExtensions.nvxImageViewHandle, + }}; + + // Only enable Cuda interop extensions in 64-bit builds in + // order to avoid potential driver or address space issues. + // VK_KHR_buffer_device_address is expensive on some drivers. + bool enableCudaInterop = !env::is32BitHostPlatform() && + m_deviceExtensions.supports(devExtensions.nvxBinaryImport.name()) && + m_deviceExtensions.supports(devExtensions.nvxImageViewHandle.name()) && + m_deviceFeatures.khrBufferDeviceAddress.bufferDeviceAddress; + + if (enableCudaInterop) { + devExtensions.nvxBinaryImport.setMode(DxvkExtMode::Optional); + devExtensions.nvxImageViewHandle.setMode(DxvkExtMode::Optional); + devExtensions.khrBufferDeviceAddress.setMode(DxvkExtMode::Optional); + + enabledFeatures.khrBufferDeviceAddress.bufferDeviceAddress = VK_TRUE; + } + + DxvkNameSet extensionsEnabled; + + if (!m_deviceExtensions.enableExtensions( + devExtensionList.size(), + devExtensionList.data(), + extensionsEnabled)) + throw DxvkError("DxvkAdapter: Failed to create device"); + + // Enable additional extensions if necessary + extensionsEnabled.merge(m_extraExtensions); + DxvkNameList extensionNameList = extensionsEnabled.toNameList(); + + // Enable additional device features if supported + enabledFeatures.extExtendedDynamicState.extendedDynamicState = m_deviceFeatures.extExtendedDynamicState.extendedDynamicState; + + enabledFeatures.ext4444Formats.formatA4B4G4R4 = m_deviceFeatures.ext4444Formats.formatA4B4G4R4; + enabledFeatures.ext4444Formats.formatA4R4G4B4 = m_deviceFeatures.ext4444Formats.formatA4R4G4B4; + + Logger::info(str::format("Device properties:" + "\n Device name: : ", m_deviceInfo.core.properties.deviceName, + "\n Driver version : ", + VK_VERSION_MAJOR(m_deviceInfo.core.properties.driverVersion), ".", + VK_VERSION_MINOR(m_deviceInfo.core.properties.driverVersion), ".", + VK_VERSION_PATCH(m_deviceInfo.core.properties.driverVersion))); + + Logger::info("Enabled device extensions:"); + this->logNameList(extensionNameList); + this->logFeatures(enabledFeatures); + + // Create pNext chain for additional device features + enabledFeatures.core.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR; + enabledFeatures.core.pNext = nullptr; + + enabledFeatures.shaderDrawParameters.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES; + enabledFeatures.shaderDrawParameters.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.shaderDrawParameters); + + if (devExtensions.ext4444Formats) { + enabledFeatures.ext4444Formats.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT; + enabledFeatures.ext4444Formats.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.ext4444Formats); + } + + if (devExtensions.extCustomBorderColor) { + enabledFeatures.extCustomBorderColor.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT; + enabledFeatures.extCustomBorderColor.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.extCustomBorderColor); + } + + if (devExtensions.extDepthClipEnable) { + enabledFeatures.extDepthClipEnable.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT; + enabledFeatures.extDepthClipEnable.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.extDepthClipEnable); + } + + if (devExtensions.extExtendedDynamicState) { + enabledFeatures.extExtendedDynamicState.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT; + enabledFeatures.extExtendedDynamicState.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.extExtendedDynamicState); + } + + if (devExtensions.extHostQueryReset) { + enabledFeatures.extHostQueryReset.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT; + enabledFeatures.extHostQueryReset.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.extHostQueryReset); + } + + if (devExtensions.extMemoryPriority) { + enabledFeatures.extMemoryPriority.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PRIORITY_FEATURES_EXT; + enabledFeatures.extMemoryPriority.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.extMemoryPriority); + } + + if (devExtensions.extNonSeamlessCubeMap) { + enabledFeatures.extNonSeamlessCubeMap.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NON_SEAMLESS_CUBE_MAP_FEATURES_EXT; + enabledFeatures.extNonSeamlessCubeMap.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.extNonSeamlessCubeMap); + } + + if (devExtensions.extShaderDemoteToHelperInvocation) { + enabledFeatures.extShaderDemoteToHelperInvocation.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT; + enabledFeatures.extShaderDemoteToHelperInvocation.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.extShaderDemoteToHelperInvocation); + } + + if (devExtensions.extRobustness2) { + enabledFeatures.extRobustness2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT; + enabledFeatures.extRobustness2.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.extRobustness2); + } + + if (devExtensions.extTransformFeedback) { + enabledFeatures.extTransformFeedback.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT; + enabledFeatures.extTransformFeedback.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.extTransformFeedback); + } + + if (devExtensions.extVertexAttributeDivisor.revision() >= 3) { + enabledFeatures.extVertexAttributeDivisor.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT; + enabledFeatures.extVertexAttributeDivisor.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.extVertexAttributeDivisor); + } + + if (devExtensions.khrBufferDeviceAddress) { + enabledFeatures.khrBufferDeviceAddress.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR; + enabledFeatures.khrBufferDeviceAddress.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.khrBufferDeviceAddress); + } + + if (devExtensions.khrTimelineSemaphore) { + enabledFeatures.khrTimelineSemaphore.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES_KHR; + enabledFeatures.khrTimelineSemaphore.pNext = std::exchange(enabledFeatures.core.pNext, &enabledFeatures.khrTimelineSemaphore); + } + + // Report the desired overallocation behaviour to the driver + VkDeviceMemoryOverallocationCreateInfoAMD overallocInfo; + overallocInfo.sType = VK_STRUCTURE_TYPE_DEVICE_MEMORY_OVERALLOCATION_CREATE_INFO_AMD; + overallocInfo.pNext = nullptr; + overallocInfo.overallocationBehavior = VK_MEMORY_OVERALLOCATION_BEHAVIOR_ALLOWED_AMD; + + // Create the requested queues + float queuePriority = 1.0f; + std::vector queueInfos; + + std::unordered_set queueFamiliySet; + + DxvkAdapterQueueIndices queueFamilies = findQueueFamilies(); + queueFamiliySet.insert(queueFamilies.graphics); + queueFamiliySet.insert(queueFamilies.transfer); + this->logQueueFamilies(queueFamilies); + + for (uint32_t family : queueFamiliySet) { + VkDeviceQueueCreateInfo graphicsQueue; + graphicsQueue.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + graphicsQueue.pNext = nullptr; + graphicsQueue.flags = 0; + graphicsQueue.queueFamilyIndex = family; + graphicsQueue.queueCount = 1; + graphicsQueue.pQueuePriorities = &queuePriority; + queueInfos.push_back(graphicsQueue); + } + + VkDeviceCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + info.pNext = enabledFeatures.core.pNext; + info.flags = 0; + info.queueCreateInfoCount = queueInfos.size(); + info.pQueueCreateInfos = queueInfos.data(); + info.enabledLayerCount = 0; + info.ppEnabledLayerNames = nullptr; + info.enabledExtensionCount = extensionNameList.count(); + info.ppEnabledExtensionNames = extensionNameList.names(); + info.pEnabledFeatures = &enabledFeatures.core.features; + + if (devExtensions.amdMemoryOverallocationBehaviour) + overallocInfo.pNext = std::exchange(info.pNext, &overallocInfo); + + VkDevice device = VK_NULL_HANDLE; + VkResult vr = m_vki->vkCreateDevice(m_handle, &info, nullptr, &device); + + if (vr != VK_SUCCESS && enableCudaInterop) { + // Enabling certain Vulkan extensions can cause device creation to fail on + // Nvidia drivers if a certain kernel module isn't loaded, but we cannot know + // that in advance since the extensions are reported as supported anyway. + Logger::err("DxvkAdapter: Failed to create device, retrying without CUDA interop extensions"); + + extensionsEnabled.disableExtension(devExtensions.khrBufferDeviceAddress); + extensionsEnabled.disableExtension(devExtensions.nvxBinaryImport); + extensionsEnabled.disableExtension(devExtensions.nvxImageViewHandle); + + enabledFeatures.khrBufferDeviceAddress.bufferDeviceAddress = VK_FALSE; + + vk::removeStructFromPNextChain(&enabledFeatures.core.pNext, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR); + + extensionNameList = extensionsEnabled.toNameList(); + info.enabledExtensionCount = extensionNameList.count(); + info.ppEnabledExtensionNames = extensionNameList.names(); + + vr = m_vki->vkCreateDevice(m_handle, &info, nullptr, &device); + } + + if (vr != VK_SUCCESS) + throw DxvkError("DxvkAdapter: Failed to create device"); + + Rc result = new DxvkDevice(instance, this, + new vk::DeviceFn(true, m_vki->instance(), device), + devExtensions, enabledFeatures); + result->initResources(); + return result; + } + + + void DxvkAdapter::notifyHeapMemoryAlloc( + uint32_t heap, + VkDeviceSize bytes) { + if (!m_hasMemoryBudget) + m_heapAlloc[heap] += bytes; + } + + + void DxvkAdapter::notifyHeapMemoryFree( + uint32_t heap, + VkDeviceSize bytes) { + if (!m_hasMemoryBudget) + m_heapAlloc[heap] -= bytes; + } + + + bool DxvkAdapter::matchesDriver( + DxvkGpuVendor vendor, + VkDriverIdKHR driver, + uint32_t minVer, + uint32_t maxVer) const { + bool driverMatches = m_deviceInfo.khrDeviceDriverProperties.driverID + ? driver == m_deviceInfo.khrDeviceDriverProperties.driverID + : vendor == DxvkGpuVendor(m_deviceInfo.core.properties.vendorID); + + if (minVer) driverMatches &= m_deviceInfo.core.properties.driverVersion >= minVer; + if (maxVer) driverMatches &= m_deviceInfo.core.properties.driverVersion < maxVer; + + return driverMatches; + } + + + void DxvkAdapter::logAdapterInfo() const { + VkPhysicalDeviceProperties deviceInfo = this->deviceProperties(); + VkPhysicalDeviceMemoryProperties memoryInfo = this->memoryProperties(); + + Logger::info(str::format(deviceInfo.deviceName, ":")); + Logger::info(str::format(" Driver: ", + VK_VERSION_MAJOR(deviceInfo.driverVersion), ".", + VK_VERSION_MINOR(deviceInfo.driverVersion), ".", + VK_VERSION_PATCH(deviceInfo.driverVersion))); + Logger::info(str::format(" Vulkan: ", + VK_VERSION_MAJOR(deviceInfo.apiVersion), ".", + VK_VERSION_MINOR(deviceInfo.apiVersion), ".", + VK_VERSION_PATCH(deviceInfo.apiVersion))); + + for (uint32_t i = 0; i < memoryInfo.memoryHeapCount; i++) { + constexpr VkDeviceSize mib = 1024 * 1024; + + Logger::info(str::format(" Memory Heap[", i, "]: ")); + Logger::info(str::format(" Size: ", memoryInfo.memoryHeaps[i].size / mib, " MiB")); + Logger::info(str::format(" Flags: ", "0x", std::hex, memoryInfo.memoryHeaps[i].flags)); + + for (uint32_t j = 0; j < memoryInfo.memoryTypeCount; j++) { + if (memoryInfo.memoryTypes[j].heapIndex == i) { + Logger::info(str::format( + " Memory Type[", j, "]: ", + "Property Flags = ", "0x", std::hex, memoryInfo.memoryTypes[j].propertyFlags)); + } + } + } + } + + + bool DxvkAdapter::isUnifiedMemoryArchitecture() const { + auto memory = this->memoryProperties(); + bool result = true; + + for (uint32_t i = 0; i < memory.memoryHeapCount; i++) + result &= memory.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT; + + return result; + } + + + void DxvkAdapter::initHeapAllocInfo() { + for (uint32_t i = 0; i < m_heapAlloc.size(); i++) + m_heapAlloc[i] = 0; + } + + + void DxvkAdapter::queryExtensions() { + m_deviceExtensions = DxvkNameSet::enumDeviceExtensions(m_vki, m_handle); + } + + + void DxvkAdapter::queryDeviceInfo() { + m_deviceInfo = DxvkDeviceInfo(); + m_deviceInfo.core.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; + m_deviceInfo.core.pNext = nullptr; + + // Query info now so that we have basic device properties available + m_vki->vkGetPhysicalDeviceProperties2(m_handle, &m_deviceInfo.core); + + m_deviceInfo.coreDeviceId.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES; + m_deviceInfo.coreDeviceId.pNext = std::exchange(m_deviceInfo.core.pNext, &m_deviceInfo.coreDeviceId); + + m_deviceInfo.coreSubgroup.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES; + m_deviceInfo.coreSubgroup.pNext = std::exchange(m_deviceInfo.core.pNext, &m_deviceInfo.coreSubgroup); + + if (m_deviceExtensions.supports(VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME)) { + m_deviceInfo.extConservativeRasterization.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONSERVATIVE_RASTERIZATION_PROPERTIES_EXT; + m_deviceInfo.extConservativeRasterization.pNext = std::exchange(m_deviceInfo.core.pNext, &m_deviceInfo.extConservativeRasterization); + } + + if (m_deviceExtensions.supports(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME)) { + m_deviceInfo.extCustomBorderColor.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_PROPERTIES_EXT; + m_deviceInfo.extCustomBorderColor.pNext = std::exchange(m_deviceInfo.core.pNext, &m_deviceInfo.extCustomBorderColor); + } + + if (m_deviceExtensions.supports(VK_EXT_ROBUSTNESS_2_EXTENSION_NAME)) { + m_deviceInfo.extRobustness2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_EXT; + m_deviceInfo.extRobustness2.pNext = std::exchange(m_deviceInfo.core.pNext, &m_deviceInfo.extRobustness2); + } + + if (m_deviceExtensions.supports(VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME)) { + m_deviceInfo.extTransformFeedback.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT; + m_deviceInfo.extTransformFeedback.pNext = std::exchange(m_deviceInfo.core.pNext, &m_deviceInfo.extTransformFeedback); + } + + if (m_deviceExtensions.supports(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME)) { + m_deviceInfo.extVertexAttributeDivisor.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT; + m_deviceInfo.extVertexAttributeDivisor.pNext = std::exchange(m_deviceInfo.core.pNext, &m_deviceInfo.extVertexAttributeDivisor); + } + + if (m_deviceExtensions.supports(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME)) { + m_deviceInfo.khrDepthStencilResolve.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES_KHR; + m_deviceInfo.khrDepthStencilResolve.pNext = std::exchange(m_deviceInfo.core.pNext, &m_deviceInfo.khrDepthStencilResolve); + } + + if (m_deviceExtensions.supports(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME)) { + m_deviceInfo.khrDeviceDriverProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR; + m_deviceInfo.khrDeviceDriverProperties.pNext = std::exchange(m_deviceInfo.core.pNext, &m_deviceInfo.khrDeviceDriverProperties); + } + + if (m_deviceExtensions.supports(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME)) { + m_deviceInfo.khrShaderFloatControls.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES_KHR; + m_deviceInfo.khrShaderFloatControls.pNext = std::exchange(m_deviceInfo.core.pNext, &m_deviceInfo.khrShaderFloatControls); + } + + if (m_deviceExtensions.supports(VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME)) { + m_deviceInfo.khrTimelineSemaphore.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES_KHR; + m_deviceInfo.khrTimelineSemaphore.pNext = std::exchange(m_deviceInfo.core.pNext, &m_deviceInfo.khrTimelineSemaphore); + } + + // Query full device properties for all enabled extensions + m_vki->vkGetPhysicalDeviceProperties2(m_handle, &m_deviceInfo.core); + + // Some drivers reports the driver version in a slightly different format + switch (m_deviceInfo.khrDeviceDriverProperties.driverID) { + case VK_DRIVER_ID_NVIDIA_PROPRIETARY: + m_deviceInfo.core.properties.driverVersion = VK_MAKE_VERSION( + (m_deviceInfo.core.properties.driverVersion >> 22) & 0x3ff, + (m_deviceInfo.core.properties.driverVersion >> 14) & 0x0ff, + (m_deviceInfo.core.properties.driverVersion >> 6) & 0x0ff); + break; + + case VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS: + m_deviceInfo.core.properties.driverVersion = VK_MAKE_VERSION( + m_deviceInfo.core.properties.driverVersion >> 14, + m_deviceInfo.core.properties.driverVersion & 0x3fff, 0); + break; + + default:; + } + } + + + void DxvkAdapter::queryDeviceFeatures() { + m_deviceFeatures = DxvkDeviceFeatures(); + m_deviceFeatures.core.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; + m_deviceFeatures.core.pNext = nullptr; + + m_deviceFeatures.shaderDrawParameters.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES; + m_deviceFeatures.shaderDrawParameters.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.shaderDrawParameters); + + if (m_deviceExtensions.supports(VK_EXT_4444_FORMATS_EXTENSION_NAME)) { + m_deviceFeatures.ext4444Formats.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT; + m_deviceFeatures.ext4444Formats.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.ext4444Formats); + } + + if (m_deviceExtensions.supports(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME)) { + m_deviceFeatures.extCustomBorderColor.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT; + m_deviceFeatures.extCustomBorderColor.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.extCustomBorderColor); + } + + if (m_deviceExtensions.supports(VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME)) { + m_deviceFeatures.extDepthClipEnable.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT; + m_deviceFeatures.extDepthClipEnable.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.extDepthClipEnable); + } + + if (m_deviceExtensions.supports(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME)) { + m_deviceFeatures.extExtendedDynamicState.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT; + m_deviceFeatures.extExtendedDynamicState.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.extExtendedDynamicState); + } + + if (m_deviceExtensions.supports(VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME)) { + m_deviceFeatures.extHostQueryReset.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT; + m_deviceFeatures.extHostQueryReset.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.extHostQueryReset); + } + + if (m_deviceExtensions.supports(VK_EXT_MEMORY_PRIORITY_EXTENSION_NAME)) { + m_deviceFeatures.extMemoryPriority.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PRIORITY_FEATURES_EXT; + m_deviceFeatures.extMemoryPriority.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.extMemoryPriority); + } + + if (m_deviceExtensions.supports(VK_EXT_NON_SEAMLESS_CUBE_MAP_EXTENSION_NAME)) { + m_deviceFeatures.extNonSeamlessCubeMap.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NON_SEAMLESS_CUBE_MAP_FEATURES_EXT; + m_deviceFeatures.extNonSeamlessCubeMap.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.extNonSeamlessCubeMap); + } + + if (m_deviceExtensions.supports(VK_EXT_ROBUSTNESS_2_EXTENSION_NAME)) { + m_deviceFeatures.extRobustness2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT; + m_deviceFeatures.extRobustness2.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.extRobustness2); + } + + if (m_deviceExtensions.supports(VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME)) { + m_deviceFeatures.extShaderDemoteToHelperInvocation.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT; + m_deviceFeatures.extShaderDemoteToHelperInvocation.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.extShaderDemoteToHelperInvocation); + } + + if (m_deviceExtensions.supports(VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME)) { + m_deviceFeatures.extTransformFeedback.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT; + m_deviceFeatures.extTransformFeedback.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.extTransformFeedback); + } + + if (m_deviceExtensions.supports(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME) >= 3) { + m_deviceFeatures.extVertexAttributeDivisor.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT; + m_deviceFeatures.extVertexAttributeDivisor.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.extVertexAttributeDivisor); + } + + if (m_deviceExtensions.supports(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME)) { + m_deviceFeatures.khrBufferDeviceAddress.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR; + m_deviceFeatures.khrBufferDeviceAddress.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.khrBufferDeviceAddress); + } + + if (m_deviceExtensions.supports(VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME)) { + m_deviceFeatures.khrTimelineSemaphore.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES_KHR; + m_deviceFeatures.khrTimelineSemaphore.pNext = std::exchange(m_deviceFeatures.core.pNext, &m_deviceFeatures.khrTimelineSemaphore); + } + + m_vki->vkGetPhysicalDeviceFeatures2(m_handle, &m_deviceFeatures.core); + } + + + void DxvkAdapter::queryDeviceQueues() { + uint32_t numQueueFamilies = 0; + m_vki->vkGetPhysicalDeviceQueueFamilyProperties( + m_handle, &numQueueFamilies, nullptr); + + m_queueFamilies.resize(numQueueFamilies); + m_vki->vkGetPhysicalDeviceQueueFamilyProperties( + m_handle, &numQueueFamilies, m_queueFamilies.data()); + } + + + uint32_t DxvkAdapter::findQueueFamily( + VkQueueFlags mask, + VkQueueFlags flags) const { + for (uint32_t i = 0; i < m_queueFamilies.size(); i++) { + if ((m_queueFamilies[i].queueFlags & mask) == flags) + return i; + } + + return VK_QUEUE_FAMILY_IGNORED; + } + + + void DxvkAdapter::logNameList(const DxvkNameList& names) { + for (uint32_t i = 0; i < names.count(); i++) + Logger::info(str::format(" ", names.name(i))); + } + + + void DxvkAdapter::logFeatures(const DxvkDeviceFeatures& features) { + Logger::info(str::format("Device features:", + "\n robustBufferAccess : ", features.core.features.robustBufferAccess ? "1" : "0", + "\n fullDrawIndexUint32 : ", features.core.features.fullDrawIndexUint32 ? "1" : "0", + "\n imageCubeArray : ", features.core.features.imageCubeArray ? "1" : "0", + "\n independentBlend : ", features.core.features.independentBlend ? "1" : "0", + "\n geometryShader : ", features.core.features.geometryShader ? "1" : "0", + "\n tessellationShader : ", features.core.features.tessellationShader ? "1" : "0", + "\n sampleRateShading : ", features.core.features.sampleRateShading ? "1" : "0", + "\n dualSrcBlend : ", features.core.features.dualSrcBlend ? "1" : "0", + "\n logicOp : ", features.core.features.logicOp ? "1" : "0", + "\n multiDrawIndirect : ", features.core.features.multiDrawIndirect ? "1" : "0", + "\n drawIndirectFirstInstance : ", features.core.features.drawIndirectFirstInstance ? "1" : "0", + "\n depthClamp : ", features.core.features.depthClamp ? "1" : "0", + "\n depthBiasClamp : ", features.core.features.depthBiasClamp ? "1" : "0", + "\n fillModeNonSolid : ", features.core.features.fillModeNonSolid ? "1" : "0", + "\n depthBounds : ", features.core.features.depthBounds ? "1" : "0", + "\n multiViewport : ", features.core.features.multiViewport ? "1" : "0", + "\n samplerAnisotropy : ", features.core.features.samplerAnisotropy ? "1" : "0", + "\n textureCompressionBC : ", features.core.features.textureCompressionBC ? "1" : "0", + "\n occlusionQueryPrecise : ", features.core.features.occlusionQueryPrecise ? "1" : "0", + "\n pipelineStatisticsQuery : ", features.core.features.pipelineStatisticsQuery ? "1" : "0", + "\n vertexPipelineStoresAndAtomics : ", features.core.features.vertexPipelineStoresAndAtomics ? "1" : "0", + "\n fragmentStoresAndAtomics : ", features.core.features.fragmentStoresAndAtomics ? "1" : "0", + "\n shaderImageGatherExtended : ", features.core.features.shaderImageGatherExtended ? "1" : "0", + "\n shaderStorageImageExtendedFormats : ", features.core.features.shaderStorageImageExtendedFormats ? "1" : "0", + "\n shaderStorageImageReadWithoutFormat : ", features.core.features.shaderStorageImageReadWithoutFormat ? "1" : "0", + "\n shaderStorageImageWriteWithoutFormat : ", features.core.features.shaderStorageImageWriteWithoutFormat ? "1" : "0", + "\n shaderClipDistance : ", features.core.features.shaderClipDistance ? "1" : "0", + "\n shaderCullDistance : ", features.core.features.shaderCullDistance ? "1" : "0", + "\n shaderFloat64 : ", features.core.features.shaderFloat64 ? "1" : "0", + "\n shaderInt64 : ", features.core.features.shaderInt64 ? "1" : "0", + "\n variableMultisampleRate : ", features.core.features.variableMultisampleRate ? "1" : "0", + "\n", VK_EXT_4444_FORMATS_EXTENSION_NAME, + "\n formatA4R4G4B4 : ", features.ext4444Formats.formatA4R4G4B4 ? "1" : "0", + "\n formatA4B4G4R4 : ", features.ext4444Formats.formatA4B4G4R4 ? "1" : "0", + "\n", VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME, + "\n customBorderColors : ", features.extCustomBorderColor.customBorderColors ? "1" : "0", + "\n customBorderColorWithoutFormat : ", features.extCustomBorderColor.customBorderColorWithoutFormat ? "1" : "0", + "\n", VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME, + "\n depthClipEnable : ", features.extDepthClipEnable.depthClipEnable ? "1" : "0", + "\n", VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME, + "\n extendedDynamicState : ", features.extExtendedDynamicState.extendedDynamicState ? "1" : "0", + "\n", VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME, + "\n hostQueryReset : ", features.extHostQueryReset.hostQueryReset ? "1" : "0", + "\n", VK_EXT_MEMORY_PRIORITY_EXTENSION_NAME, + "\n memoryPriority : ", features.extMemoryPriority.memoryPriority ? "1" : "0", + "\n", VK_EXT_NON_SEAMLESS_CUBE_MAP_EXTENSION_NAME, + "\n nonSeamlessCubeMap : ", features.extNonSeamlessCubeMap.nonSeamlessCubeMap ? "1" : "0", + "\n", VK_EXT_ROBUSTNESS_2_EXTENSION_NAME, + "\n robustBufferAccess2 : ", features.extRobustness2.robustBufferAccess2 ? "1" : "0", + "\n robustImageAccess2 : ", features.extRobustness2.robustImageAccess2 ? "1" : "0", + "\n nullDescriptor : ", features.extRobustness2.nullDescriptor ? "1" : "0", + "\n", VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME, + "\n shaderDemoteToHelperInvocation : ", features.extShaderDemoteToHelperInvocation.shaderDemoteToHelperInvocation ? "1" : "0", + "\n", VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME, + "\n transformFeedback : ", features.extTransformFeedback.transformFeedback ? "1" : "0", + "\n geometryStreams : ", features.extTransformFeedback.geometryStreams ? "1" : "0", + "\n", VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME, + "\n vertexAttributeInstanceRateDivisor : ", features.extVertexAttributeDivisor.vertexAttributeInstanceRateDivisor ? "1" : "0", + "\n vertexAttributeInstanceRateZeroDivisor : ", features.extVertexAttributeDivisor.vertexAttributeInstanceRateZeroDivisor ? "1" : "0", + "\n", VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME, + "\n bufferDeviceAddress : ", features.khrBufferDeviceAddress.bufferDeviceAddress, + "\n", VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME, + "\n timelineSemaphore : ", features.khrTimelineSemaphore.timelineSemaphore)); + } + + + void DxvkAdapter::logQueueFamilies(const DxvkAdapterQueueIndices& queues) { + Logger::info(str::format("Queue families:", + "\n Graphics : ", queues.graphics, + "\n Transfer : ", queues.transfer)); + } + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_adapter.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_adapter.h new file mode 100644 index 00000000000..f2fb1f0af75 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_adapter.h @@ -0,0 +1,291 @@ +#pragma once + +#include "dxvk_device_info.h" +#include "dxvk_extensions.h" +#include "dxvk_include.h" + +namespace dxvk { + + class DxvkDevice; + class DxvkInstance; + + /** + * \brief GPU vendors + * Based on PCIe IDs. + */ + enum class DxvkGpuVendor : uint16_t { + Amd = 0x1002, + Nvidia = 0x10de, + Intel = 0x8086, + }; + + /** + * \brief Adapter memory heap info + * + * Stores info about a heap, and the amount + * of memory allocated from it by the app. + */ + struct DxvkAdapterMemoryHeapInfo { + VkMemoryHeapFlags heapFlags; + VkDeviceSize memoryBudget; + VkDeviceSize memoryAllocated; + }; + + /** + * \brief Adapter memory info + * + * Stores properties and allocation + * info of each available heap. + */ + struct DxvkAdapterMemoryInfo { + uint32_t heapCount; + DxvkAdapterMemoryHeapInfo heaps[VK_MAX_MEMORY_HEAPS]; + }; + + /** + * \brief Retrieves queue indices + */ + struct DxvkAdapterQueueIndices { + uint32_t graphics; + uint32_t transfer; + }; + + /** + * \brief DXVK adapter + * + * Corresponds to a physical device in Vulkan. Provides + * all kinds of information about the device itself and + * the supported feature set. + */ + class DxvkAdapter : public RcObject { + + public: + + DxvkAdapter( + const Rc& vki, + VkPhysicalDevice handle); + ~DxvkAdapter(); + + /** + * \brief Vulkan instance functions + * \returns Vulkan instance functions + */ + Rc vki() const { + return m_vki; + } + + /** + * \brief Physical device handle + * \returns The adapter handle + */ + VkPhysicalDevice handle() const { + return m_handle; + } + + /** + * \brief Physical device properties + * + * Returns a read-only reference to the core + * properties of the Vulkan physical device. + * \returns Physical device core properties + */ + const VkPhysicalDeviceProperties& deviceProperties() const { + return m_deviceInfo.core.properties; + } + + /** + * \brief Device info + * + * Returns a read-only reference to the full + * device info structure, including extended + * properties. + * \returns Device info struct + */ + const DxvkDeviceInfo& devicePropertiesExt() const { + return m_deviceInfo; + } + + /** + * \brief Supportred device features + * + * Queries the supported device features. + * \returns Device features + */ + const DxvkDeviceFeatures& features() const { + return m_deviceFeatures; + } + + /** + * \brief Retrieves memory heap info + * + * Returns properties of all available memory heaps, + * both device-local and non-local heaps, and the + * amount of memory allocated from those heaps by + * logical devices. + * \returns Memory heap info + */ + DxvkAdapterMemoryInfo getMemoryHeapInfo() const; + + /** + * \brief Memory properties + * + * Queries the memory types and memory heaps of + * the device. This is useful for memory allocators. + * \returns Device memory properties + */ + VkPhysicalDeviceMemoryProperties memoryProperties() const; + + /** + * \brief Queries format support + * + * \param [in] format The format to query + * \returns Format support info + */ + VkFormatProperties formatProperties( + VkFormat format) const; + + /** + * \brief Queries image format support + * + * \param [in] format Format to query + * \param [in] type Image type + * \param [in] tiling Image tiling + * \param [in] usage Image usage flags + * \param [in] flags Image create flags + * \param [out] properties Format properties + * \returns \c VK_SUCCESS or \c VK_ERROR_FORMAT_NOT_SUPPORTED + */ + VkResult imageFormatProperties( + VkFormat format, + VkImageType type, + VkImageTiling tiling, + VkImageUsageFlags usage, + VkImageCreateFlags flags, + VkImageFormatProperties& properties) const; + + /** + * \brief Retrieves queue family indices + * \returns Indices for all queue families + */ + DxvkAdapterQueueIndices findQueueFamilies() const; + + /** + * \brief Tests whether all required features are supported + * + * \param [in] features Required device features + * \returns \c true if all features are supported + */ + bool checkFeatureSupport( + const DxvkDeviceFeatures& required) const; + + /** + * \brief Enables extensions for this adapter + * + * When creating a device, all extensions that + * are added using this method will be enabled + * in addition to the ones required by DXVK. + * This is used for OpenVR support. + */ + void enableExtensions( + const DxvkNameSet& extensions); + + /** + * \brief Creates a DXVK device + * + * Creates a logical device for this adapter. + * \param [in] instance Parent instance + * \param [in] enabledFeatures Device features + * \returns Device handle + */ + Rc createDevice( + const Rc& instance, + DxvkDeviceFeatures enabledFeatures); + + /** + * \brief Registers memory allocation + * + * Updates memory alloc info accordingly. + * \param [in] heap Memory heap index + * \param [in] bytes Allocation size + */ + void notifyHeapMemoryAlloc( + uint32_t heap, + VkDeviceSize bytes); + + /** + * \brief Registers memory deallocation + * + * Updates memory alloc info accordingly. + * \param [in] heap Memory heap index + * \param [in] bytes Allocation size + */ + void notifyHeapMemoryFree( + uint32_t heap, + VkDeviceSize bytes); + + /** + * \brief Tests if the driver matches certain criteria + * + * \param [in] vendor GPU vendor + * \param [in] driver Driver. Ignored when the + * driver properties extension is not supported. + * \param [in] minVer Match versions starting with this one + * \param [in] maxVer Match versions lower than this one + * \returns \c True if the driver matches these criteria + */ + bool matchesDriver( + DxvkGpuVendor vendor, + VkDriverIdKHR driver, + uint32_t minVer, + uint32_t maxVer) const; + + /** + * \brief Logs DXVK adapter info + * + * May be useful for bug reports + * and general troubleshooting. + */ + void logAdapterInfo() const; + + /** + * \brief Checks whether this is a UMA system + * + * Basically tests whether all heaps are device-local. + * Can be used for various optimizations in client APIs. + * \returns \c true if the system has unified memory. + */ + bool isUnifiedMemoryArchitecture() const; + + private: + + Rc m_vki; + VkPhysicalDevice m_handle; + + DxvkNameSet m_extraExtensions; + DxvkNameSet m_deviceExtensions; + DxvkDeviceInfo m_deviceInfo; + DxvkDeviceFeatures m_deviceFeatures; + + bool m_hasMemoryBudget; + + std::vector m_queueFamilies; + + std::array, VK_MAX_MEMORY_HEAPS> m_heapAlloc; + + void initHeapAllocInfo(); + void queryExtensions(); + void queryDeviceInfo(); + void queryDeviceFeatures(); + void queryDeviceQueues(); + + uint32_t findQueueFamily( + VkQueueFlags mask, + VkQueueFlags flags) const; + + static void logNameList(const DxvkNameList& names); + static void logFeatures(const DxvkDeviceFeatures& features); + static void logQueueFamilies(const DxvkAdapterQueueIndices& queues); + + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_annotation.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_annotation.h new file mode 100644 index 00000000000..e5d1cbc7252 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_annotation.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include + +MIDL_INTERFACE("7f2c2f72-1cc8-4979-8d9c-7e3faeddecde") +IDXVKUserDefinedAnnotation : public ID3DUserDefinedAnnotation { + +public: + + INT STDMETHODCALLTYPE BeginEvent( + LPCWSTR Name) final { + return this->BeginEvent(0, Name); + } + + void STDMETHODCALLTYPE SetMarker( + LPCWSTR Name) final { + this->SetMarker(0, Name); + } + + virtual INT STDMETHODCALLTYPE BeginEvent( + D3DCOLOR Color, + LPCWSTR Name) = 0; + + virtual void STDMETHODCALLTYPE SetMarker( + D3DCOLOR Color, + LPCWSTR Name) = 0; + +}; + +#ifdef _MSC_VER +struct __declspec(uuid("7f2c2f72-1cc8-4979-8d9c-7e3faeddecde")) IDXVKUserDefinedAnnotation; +#else +__CRT_UUID_DECL(IDXVKUserDefinedAnnotation, 0x7f2c2f72,0x1cc8,0x4979,0x8d,0x9c,0x7e,0x3f,0xae,0xdd,0xec,0xde); +#endif diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_barrier.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_barrier.cpp new file mode 100644 index 00000000000..65acedc98c9 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_barrier.cpp @@ -0,0 +1,298 @@ +#include "dxvk_barrier.h" + +namespace dxvk { + + constexpr static VkAccessFlags AccessReadMask + = VK_ACCESS_INDIRECT_COMMAND_READ_BIT + | VK_ACCESS_INDEX_READ_BIT + | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT + | VK_ACCESS_UNIFORM_READ_BIT + | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT + | VK_ACCESS_SHADER_READ_BIT + | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT + | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT + | VK_ACCESS_TRANSFER_READ_BIT + | VK_ACCESS_HOST_READ_BIT + | VK_ACCESS_MEMORY_READ_BIT + | VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT; + + constexpr static VkAccessFlags AccessWriteMask + = VK_ACCESS_SHADER_WRITE_BIT + | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT + | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT + | VK_ACCESS_TRANSFER_WRITE_BIT + | VK_ACCESS_HOST_WRITE_BIT + | VK_ACCESS_MEMORY_WRITE_BIT + | VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT + | VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT; + + DxvkBarrierSet:: DxvkBarrierSet(DxvkCmdBuffer cmdBuffer) + : m_cmdBuffer(cmdBuffer) { + + } + + + DxvkBarrierSet::~DxvkBarrierSet() { + + } + + + void DxvkBarrierSet::accessMemory( + VkPipelineStageFlags srcStages, + VkAccessFlags srcAccess, + VkPipelineStageFlags dstStages, + VkAccessFlags dstAccess) { + DxvkAccessFlags access = this->getAccessTypes(srcAccess); + + m_srcStages |= srcStages; + m_dstStages |= dstStages; + + m_srcAccess |= srcAccess & AccessWriteMask; + + if (access.test(DxvkAccess::Write)) + m_dstAccess |= dstAccess; + } + + + void DxvkBarrierSet::accessBuffer( + const DxvkBufferSliceHandle& bufSlice, + VkPipelineStageFlags srcStages, + VkAccessFlags srcAccess, + VkPipelineStageFlags dstStages, + VkAccessFlags dstAccess) { + DxvkAccessFlags access = this->getAccessTypes(srcAccess); + + if (srcStages == VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT + || dstStages == VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT) + access.set(DxvkAccess::Write); + + m_srcStages |= srcStages; + m_dstStages |= dstStages; + + m_srcAccess |= srcAccess & AccessWriteMask; + + if (access.test(DxvkAccess::Write)) + m_dstAccess |= dstAccess; + + m_bufSlices.insert(bufSlice.handle, + DxvkBarrierBufferSlice(bufSlice.offset, bufSlice.length, access)); + } + + + void DxvkBarrierSet::accessImage( + const Rc& image, + const VkImageSubresourceRange& subresources, + VkImageLayout srcLayout, + VkPipelineStageFlags srcStages, + VkAccessFlags srcAccess, + VkImageLayout dstLayout, + VkPipelineStageFlags dstStages, + VkAccessFlags dstAccess) { + DxvkAccessFlags access = this->getAccessTypes(srcAccess); + + if (srcStages == VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT + || dstStages == VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT + || srcLayout != dstLayout) + access.set(DxvkAccess::Write); + + m_srcStages |= srcStages; + m_dstStages |= dstStages; + + if (srcLayout == dstLayout) { + m_srcAccess |= srcAccess & AccessWriteMask; + + if (access.test(DxvkAccess::Write)) + m_dstAccess |= dstAccess; + } else { + VkImageMemoryBarrier barrier; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.pNext = nullptr; + barrier.srcAccessMask = srcAccess & AccessWriteMask; + barrier.dstAccessMask = dstAccess; + barrier.oldLayout = srcLayout; + barrier.newLayout = dstLayout; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.image = image->handle(); + barrier.subresourceRange = subresources; + barrier.subresourceRange.aspectMask = image->formatInfo()->aspectMask; + m_imgBarriers.push_back(barrier); + } + + m_imgSlices.insert(image->handle(), + DxvkBarrierImageSlice(subresources, access)); + } + + + void DxvkBarrierSet::releaseBuffer( + DxvkBarrierSet& acquire, + const DxvkBufferSliceHandle& bufSlice, + uint32_t srcQueue, + VkPipelineStageFlags srcStages, + VkAccessFlags srcAccess, + uint32_t dstQueue, + VkPipelineStageFlags dstStages, + VkAccessFlags dstAccess) { + auto& release = *this; + + release.m_srcStages |= srcStages; + acquire.m_dstStages |= dstStages; + + VkBufferMemoryBarrier barrier; + barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; + barrier.pNext = nullptr; + barrier.srcAccessMask = srcAccess & AccessWriteMask; + barrier.dstAccessMask = 0; + barrier.srcQueueFamilyIndex = srcQueue; + barrier.dstQueueFamilyIndex = dstQueue; + barrier.buffer = bufSlice.handle; + barrier.offset = bufSlice.offset; + barrier.size = bufSlice.length; + release.m_bufBarriers.push_back(barrier); + + barrier.srcAccessMask = 0; + barrier.dstAccessMask = dstAccess; + acquire.m_bufBarriers.push_back(barrier); + + DxvkAccessFlags access(DxvkAccess::Read, DxvkAccess::Write); + release.m_bufSlices.insert(bufSlice.handle, + DxvkBarrierBufferSlice(bufSlice.offset, bufSlice.length, access)); + acquire.m_bufSlices.insert(bufSlice.handle, + DxvkBarrierBufferSlice(bufSlice.offset, bufSlice.length, access)); + } + + + void DxvkBarrierSet::releaseImage( + DxvkBarrierSet& acquire, + const Rc& image, + const VkImageSubresourceRange& subresources, + uint32_t srcQueue, + VkImageLayout srcLayout, + VkPipelineStageFlags srcStages, + VkAccessFlags srcAccess, + uint32_t dstQueue, + VkImageLayout dstLayout, + VkPipelineStageFlags dstStages, + VkAccessFlags dstAccess) { + auto& release = *this; + + release.m_srcStages |= srcStages; + acquire.m_dstStages |= dstStages; + + VkImageMemoryBarrier barrier; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.pNext = nullptr; + barrier.srcAccessMask = srcAccess & AccessWriteMask; + barrier.dstAccessMask = 0; + barrier.oldLayout = srcLayout; + barrier.newLayout = dstLayout; + barrier.srcQueueFamilyIndex = srcQueue; + barrier.dstQueueFamilyIndex = dstQueue; + barrier.image = image->handle(); + barrier.subresourceRange = subresources; + barrier.subresourceRange.aspectMask = image->formatInfo()->aspectMask; + release.m_imgBarriers.push_back(barrier); + + if (srcQueue == dstQueue) + barrier.oldLayout = dstLayout; + + barrier.srcAccessMask = 0; + barrier.dstAccessMask = dstAccess; + acquire.m_imgBarriers.push_back(barrier); + + DxvkAccessFlags access(DxvkAccess::Read, DxvkAccess::Write); + release.m_imgSlices.insert(image->handle(), + DxvkBarrierImageSlice(subresources, access)); + acquire.m_imgSlices.insert(image->handle(), + DxvkBarrierImageSlice(subresources, access)); + } + + + bool DxvkBarrierSet::isBufferDirty( + const DxvkBufferSliceHandle& bufSlice, + DxvkAccessFlags bufAccess) { + return m_bufSlices.isDirty(bufSlice.handle, + DxvkBarrierBufferSlice(bufSlice.offset, bufSlice.length, bufAccess)); + } + + + bool DxvkBarrierSet::isImageDirty( + const Rc& image, + const VkImageSubresourceRange& imgSubres, + DxvkAccessFlags imgAccess) { + return m_imgSlices.isDirty(image->handle(), + DxvkBarrierImageSlice(imgSubres, imgAccess)); + } + + + DxvkAccessFlags DxvkBarrierSet::getBufferAccess( + const DxvkBufferSliceHandle& bufSlice) { + return m_bufSlices.getAccess(bufSlice.handle, + DxvkBarrierBufferSlice(bufSlice.offset, bufSlice.length, 0)); + } + + + DxvkAccessFlags DxvkBarrierSet::getImageAccess( + const Rc& image, + const VkImageSubresourceRange& imgSubres) { + return m_imgSlices.getAccess(image->handle(), + DxvkBarrierImageSlice(imgSubres, 0)); + } + + + void DxvkBarrierSet::recordCommands(const Rc& commandList) { + if (m_srcStages | m_dstStages) { + VkPipelineStageFlags srcFlags = m_srcStages; + VkPipelineStageFlags dstFlags = m_dstStages; + + if (!srcFlags) srcFlags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + if (!dstFlags) dstFlags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + + VkMemoryBarrier memBarrier; + memBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; + memBarrier.pNext = nullptr; + memBarrier.srcAccessMask = m_srcAccess; + memBarrier.dstAccessMask = m_dstAccess; + + VkMemoryBarrier* pMemBarrier = nullptr; + if (m_srcAccess | m_dstAccess) + pMemBarrier = &memBarrier; + + commandList->cmdPipelineBarrier( + m_cmdBuffer, srcFlags, dstFlags, 0, + pMemBarrier ? 1 : 0, pMemBarrier, + m_bufBarriers.size(), + m_bufBarriers.data(), + m_imgBarriers.size(), + m_imgBarriers.data()); + + commandList->addStatCtr(DxvkStatCounter::CmdBarrierCount, 1); + + this->reset(); + } + } + + + void DxvkBarrierSet::reset() { + m_srcStages = 0; + m_dstStages = 0; + + m_srcAccess = 0; + m_dstAccess = 0; + + m_bufBarriers.resize(0); + m_imgBarriers.resize(0); + + m_bufSlices.clear(); + m_imgSlices.clear(); + } + + + DxvkAccessFlags DxvkBarrierSet::getAccessTypes(VkAccessFlags flags) { + DxvkAccessFlags result; + if (flags & AccessReadMask) result.set(DxvkAccess::Read); + if (flags & AccessWriteMask) result.set(DxvkAccess::Write); + return result; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_barrier.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_barrier.h new file mode 100644 index 00000000000..f7a7713d956 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_barrier.h @@ -0,0 +1,572 @@ +#pragma once + +#include +#include + +#include "dxvk_buffer.h" +#include "dxvk_cmdlist.h" +#include "dxvk_image.h" + +namespace dxvk { + + /** + * \brief Buffer slice for barrier tracking + * + * Stores the offset and length of a buffer slice, + * as well as access flags for the given range. + */ + class DxvkBarrierBufferSlice { + + public: + + DxvkBarrierBufferSlice() + : m_offset(0), m_length(0), m_access(0) { } + + DxvkBarrierBufferSlice(VkDeviceSize offset, VkDeviceSize length, DxvkAccessFlags access) + : m_offset(offset), m_length(length), m_access(access) { } + + /** + * \brief Checks whether two slices overlap + * + * \param [in] slice The other buffer slice to check + * \returns \c true if the two slices overlap + */ + bool overlaps(const DxvkBarrierBufferSlice& slice) const { + return m_offset + m_length > slice.m_offset + && m_offset < slice.m_offset + slice.m_length; + } + + /** + * \brief Checks whether a given slice is dirty + * + * \param [in] slice The buffer slice to check + * \returns \c true if the two slices overlap, and if + * at least one of the two slices have write access. + */ + bool isDirty(const DxvkBarrierBufferSlice& slice) const { + return (slice.m_access | m_access).test(DxvkAccess::Write) && overlaps(slice); + } + + /** + * \brief Checks whether two slices can be merged + * + * Two buffer slices can be merged if they overlap or are adjacent + * and if the access flags are the same, or alternatively, if the + * offset and size are the same and only the access flags differ. + * \param [in] slice The other buffer slice to check + * \returns \c true if the slices can be merged. + */ + bool canMerge(const DxvkBarrierBufferSlice& slice) const { + if (m_access == slice.m_access) { + return m_offset + m_length >= slice.m_offset + && m_offset <= slice.m_offset + slice.m_length; + } else { + return m_offset == slice.m_offset + && m_length == slice.m_length; + } + } + + /** + * \brief Merges two buffer slices + * + * The resulting slice is guaranteed to fully contain both slices, + * including their access flags. If called when \c canMerge would + * return \c false, this will be a strict superset of both slices. + * \param [in] slice The slice to merge + */ + void merge(const DxvkBarrierBufferSlice& slice) { + VkDeviceSize end = std::max(m_offset + m_length, slice.m_offset + slice.m_length); + + m_offset = std::min(m_offset, slice.m_offset); + m_length = end - m_offset; + m_access.set(slice.m_access); + } + + /** + * \brief Queries access flags + * \returns Access flags + */ + DxvkAccessFlags getAccess() const { + return m_access; + } + + private: + + VkDeviceSize m_offset; + VkDeviceSize m_length; + DxvkAccessFlags m_access; + + }; + + + /** + * \brief Image slice for barrier tracking + * + * Stores an image subresource range, as well as + * access flags for the given image subresources. + */ + class DxvkBarrierImageSlice { + + public: + + DxvkBarrierImageSlice() + : m_range(VkImageSubresourceRange()), m_access(0) { } + + DxvkBarrierImageSlice(VkImageSubresourceRange range, DxvkAccessFlags access) + : m_range(range), m_access(access) { } + + /** + * \brief Checks whether two slices overlap + * + * \param [in] slice The other image slice to check + * \returns \c true if the two slices overlap + */ + bool overlaps(const DxvkBarrierImageSlice& slice) const { + return (m_range.aspectMask & slice.m_range.aspectMask) + && (m_range.baseArrayLayer < slice.m_range.baseArrayLayer + slice.m_range.layerCount) + && (m_range.baseArrayLayer + m_range.layerCount > slice.m_range.baseArrayLayer) + && (m_range.baseMipLevel < slice.m_range.baseMipLevel + slice.m_range.levelCount) + && (m_range.baseMipLevel + m_range.levelCount > slice.m_range.baseMipLevel); + } + + /** + * \brief Checks whether a given slice is dirty + * + * \param [in] slice The image slice to check + * \returns \c true if the two slices overlap, and if + * at least one of the two slices have write access. + */ + bool isDirty(const DxvkBarrierImageSlice& slice) const { + return (slice.m_access | m_access).test(DxvkAccess::Write) && overlaps(slice); + } + + /** + * \brief Checks whether two slices can be merged + * + * This is a simplified implementation that does not check for + * adjacent or overlapping layers or levels, and instead only + * returns \c true if both slices contain the same mip levels + * and array layers. Access flags and image aspects may differ. + * \param [in] slice The other image slice to check + * \returns \c true if the slices can be merged. + */ + bool canMerge(const DxvkBarrierImageSlice& slice) const { + return m_range.baseMipLevel == slice.m_range.baseMipLevel + && m_range.levelCount == slice.m_range.levelCount + && m_range.baseArrayLayer == slice.m_range.baseArrayLayer + && m_range.layerCount == slice.m_range.layerCount; + } + + /** + * \brief Merges two image slices + * + * The resulting slice is guaranteed to fully contain both slices, + * including their access flags. If called when \c canMerge would + * return \c false, this will be a strict superset of both slices. + * \param [in] slice The slice to merge + */ + void merge(const DxvkBarrierImageSlice& slice) { + uint32_t maxMipLevel = std::max(m_range.baseMipLevel + m_range.levelCount, + slice.m_range.baseMipLevel + slice.m_range.levelCount); + uint32_t maxArrayLayer = std::max(m_range.baseArrayLayer + m_range.layerCount, + slice.m_range.baseArrayLayer + slice.m_range.layerCount); + m_range.aspectMask |= slice.m_range.aspectMask; + m_range.baseMipLevel = std::min(m_range.baseMipLevel, slice.m_range.baseMipLevel); + m_range.levelCount = maxMipLevel - m_range.baseMipLevel; + m_range.baseArrayLayer = std::min(m_range.baseMipLevel, slice.m_range.baseArrayLayer); + m_range.layerCount = maxArrayLayer - m_range.baseArrayLayer; + m_access.set(slice.m_access); + } + + /** + * \brief Queries access flags + * \returns Access flags + */ + DxvkAccessFlags getAccess() const { + return m_access; + } + + private: + + VkImageSubresourceRange m_range; + DxvkAccessFlags m_access; + + }; + + + /** + * \brief Resource slice set for barrier tracking + * + * Implements a versioned hash table for fast resource + * lookup, with a single-linked list accurately storing + * each accessed slice if necessary. + * \tparam K Resource handle type + * \tparam T Resource slice type + */ + template + class DxvkBarrierSubresourceSet { + constexpr static uint32_t NoEntry = ~0u; + public: + + /** + * \brief Queries access flags of a given resource slice + * + * \param [in] resource Resource handle + * \param [in] slice Resource slice + * \returns Or'd access flags of all known slices + * that overlap with the given slice. + */ + DxvkAccessFlags getAccess(K resource, const T& slice) { + HashEntry* entry = findHashEntry(resource); + + if (!entry) + return DxvkAccessFlags(); + + // Exit early if we know that there are no overlapping + // slices, or if there is only one slice to check anyway. + if (!entry->data.overlaps(slice)) + return DxvkAccessFlags(); + + ListEntry* list = getListEntry(entry->next); + + if (!list) + return entry->data.getAccess(); + + // The early out condition just checks whether there are + // any access flags left that may potentially get added + DxvkAccessFlags access; + + while (list && access != entry->data.getAccess()) { + if (list->data.overlaps(slice)) + access.set(list->data.getAccess()); + + list = getListEntry(list->next); + } + + return access; + } + + /** + * \brief Checks whether a given resource slice is dirty + * + * \param [in] resource Resourece handle + * \param [in] slice Resource slice + * \returns \c true if there is at least one slice that + * overlaps with the given slice, and either slice has + * the \c DxvkAccess::Write flag set. + */ + bool isDirty(K resource, const T& slice) { + HashEntry* entry = findHashEntry(resource); + + if (!entry) + return false; + + // Exit early if there are no overlapping slices, or + // if none of the slices have the write flag set. + if (!entry->data.isDirty(slice)) + return false; + + // We know that some subresources are dirty, so if + // there is no list, the given slice must be dirty. + ListEntry* list = getListEntry(entry->next); + + if (!list) + return true; + + // Exit earlier if we find one dirty slice + bool dirty = false; + + while (list && !dirty) { + dirty = list->data.isDirty(slice); + list = getListEntry(list->next); + } + + return dirty; + } + + /** + * \brief Inserts a given resource slice + * + * This will attempt to deduplicate and merge entries if + * possible, so that lookup and further insertions remain + * reasonably fast. + * \param [in] resource Resource handle + * \param [in] slice Resource slice + */ + void insert(K resource, const T& slice) { + HashEntry* hashEntry = insertHashEntry(resource, slice); + + if (hashEntry) { + ListEntry* listEntry = getListEntry(hashEntry->next); + + // Only create the linear list if absolutely necessary + if (!listEntry && !hashEntry->data.canMerge(slice)) + listEntry = insertListEntry(hashEntry->data, hashEntry); + + if (listEntry) { + while (listEntry) { + // Avoid adding new list entries if possible + if (listEntry->data.canMerge(slice)) { + listEntry->data.merge(slice); + break; + } + + listEntry = getListEntry(listEntry->next); + } + + if (!listEntry) + insertListEntry(slice, hashEntry); + } + + // Merge hash entry data so that it stores + // a superset of all slices in the list. + hashEntry->data.merge(slice); + } + } + + /** + * \brief Removes all resources from the set + */ + void clear() { + m_used = 0; + m_version += 1; + m_list.clear(); + } + + private: + + struct ListEntry { + T data; + uint32_t next; + }; + + struct HashEntry { + uint64_t version; + K key; + T data; + uint32_t next; + }; + + uint64_t m_version = 1ull; + uint64_t m_used = 0ull; + + std::vector m_list; + std::vector m_hashMap; + + static size_t computeHash(K key) { + return size_t(uint64_t(key)); + } + + size_t computeIndex(K key) const { + return computeHash(key) % m_hashMap.size(); + } + + size_t advanceIndex(size_t index) const { + size_t size = m_hashMap.size(); + size_t next = index + 1; + return next < size ? next : 0; + } + + HashEntry* findHashEntry(K key) { + if (!m_used) + return nullptr; + + size_t index = computeIndex(key); + + while (m_hashMap[index].version == m_version) { + if (m_hashMap[index].key == key) + return &m_hashMap[index]; + + index = advanceIndex(index); + } + + return nullptr; + } + + HashEntry* insertHashEntry(K key, const T& data) { + growHashMapBeforeInsert(); + + // If we already have an entry for the given key, return + // the old one and let the caller deal with it + size_t index = computeIndex(key); + + while (m_hashMap[index].version == m_version) { + if (m_hashMap[index].key == key) + return &m_hashMap[index]; + + index = advanceIndex(index); + } + + HashEntry* entry = &m_hashMap[index]; + entry->version = m_version; + entry->key = key; + entry->data = data; + entry->next = NoEntry; + + m_used += 1; + return nullptr; + } + + void growHashMap(size_t newSize) { + size_t oldSize = m_hashMap.size(); + m_hashMap.resize(newSize); + + // Relocate hash entries in place + for (size_t i = 0; i < oldSize; i++) { + HashEntry entry = m_hashMap[i]; + m_hashMap[i].version = 0; + + while (entry.version == m_version) { + size_t index = computeIndex(entry.key); + entry.version = m_version + 1; + + while (m_hashMap[index].version > m_version) + index = advanceIndex(index); + + std::swap(entry, m_hashMap[index]); + } + } + + m_version += 1; + } + + void growHashMapBeforeInsert() { + // Allow a load factor of 0.7 for performance reasons + size_t oldSize = m_hashMap.size(); + + if (10 * m_used >= 7 * oldSize) { + size_t newSize = oldSize ? (oldSize * 2 + 5) : 37; + growHashMap(newSize); + } + } + + ListEntry* getListEntry(uint32_t index) { + return index < NoEntry ? &m_list[index] : nullptr; + } + + ListEntry* insertListEntry(const T& subresource, HashEntry* head) { + uint32_t newIndex = uint32_t(m_list.size()); + m_list.push_back({ subresource, head->next }); + head->next = newIndex; + return &m_list[newIndex]; + } + + }; + + /** + * \brief Barrier set + * + * Accumulates memory barriers and provides a + * method to record all those barriers into a + * command buffer at once. + */ + class DxvkBarrierSet { + + public: + + DxvkBarrierSet(DxvkCmdBuffer cmdBuffer); + ~DxvkBarrierSet(); + + void accessMemory( + VkPipelineStageFlags srcStages, + VkAccessFlags srcAccess, + VkPipelineStageFlags dstStages, + VkAccessFlags dstAccess); + + void accessBuffer( + const DxvkBufferSliceHandle& bufSlice, + VkPipelineStageFlags srcStages, + VkAccessFlags srcAccess, + VkPipelineStageFlags dstStages, + VkAccessFlags dstAccess); + + void accessImage( + const Rc& image, + const VkImageSubresourceRange& subresources, + VkImageLayout srcLayout, + VkPipelineStageFlags srcStages, + VkAccessFlags srcAccess, + VkImageLayout dstLayout, + VkPipelineStageFlags dstStages, + VkAccessFlags dstAccess); + + void releaseBuffer( + DxvkBarrierSet& acquire, + const DxvkBufferSliceHandle& bufSlice, + uint32_t srcQueue, + VkPipelineStageFlags srcStages, + VkAccessFlags srcAccess, + uint32_t dstQueue, + VkPipelineStageFlags dstStages, + VkAccessFlags dstAccess); + + void releaseImage( + DxvkBarrierSet& acquire, + const Rc& image, + const VkImageSubresourceRange& subresources, + uint32_t srcQueue, + VkImageLayout srcLayout, + VkPipelineStageFlags srcStages, + VkAccessFlags srcAccess, + uint32_t dstQueue, + VkImageLayout dstLayout, + VkPipelineStageFlags dstStages, + VkAccessFlags dstAccess); + + bool isBufferDirty( + const DxvkBufferSliceHandle& bufSlice, + DxvkAccessFlags bufAccess); + + bool isImageDirty( + const Rc& image, + const VkImageSubresourceRange& imgSubres, + DxvkAccessFlags imgAccess); + + DxvkAccessFlags getBufferAccess( + const DxvkBufferSliceHandle& bufSlice); + + DxvkAccessFlags getImageAccess( + const Rc& image, + const VkImageSubresourceRange& imgSubres); + + VkPipelineStageFlags getSrcStages() { + return m_srcStages; + } + + void recordCommands( + const Rc& commandList); + + void reset(); + + static DxvkAccessFlags getAccessTypes(VkAccessFlags flags); + + private: + + struct BufSlice { + DxvkBufferSliceHandle slice; + DxvkAccessFlags access; + }; + + struct ImgSlice { + VkImage image; + VkImageSubresourceRange subres; + DxvkAccessFlags access; + }; + + DxvkCmdBuffer m_cmdBuffer; + + VkPipelineStageFlags m_srcStages = 0; + VkPipelineStageFlags m_dstStages = 0; + + VkAccessFlags m_srcAccess = 0; + VkAccessFlags m_dstAccess = 0; + + std::vector m_bufBarriers; + std::vector m_imgBarriers; + + DxvkBarrierSubresourceSet m_bufSlices; + DxvkBarrierSubresourceSet m_imgSlices; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_bind_mask.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_bind_mask.h new file mode 100644 index 00000000000..b45b9b66af1 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_bind_mask.h @@ -0,0 +1,158 @@ +#pragma once + +#include "dxvk_buffer.h" +#include "dxvk_descriptor.h" +#include "dxvk_image.h" +#include "dxvk_limits.h" +#include "dxvk_sampler.h" + +namespace dxvk { + + /** + * \brief Binding mask + * + * Used to track which resource slots have a compatible + * binding and which ones don't. This is used to set up + * binding-related specialization constants in shaders. + * \tparam N Number of binding slots + */ + template + class DxvkBindingSet { + constexpr static uint32_t BitCount = 32; + constexpr static uint32_t IntCount = (BindingCount + BitCount - 1) / BitCount; + public: + + /** + * \brief Tests whether a binding is active + * + * \param [in] slot The binding ID + * \returns \c true if the binding is active + */ + bool test(uint32_t slot) const { + const uint32_t intId = slot / BitCount; + const uint32_t bitId = slot % BitCount; + const uint32_t bitMask = 1u << bitId; + return (m_slots[intId] & bitMask) != 0; + } + + /** + * \brief Changes a single binding + * + * \param [in] slot The binding ID + * \param [in] value New binding state + * \returns \c true if the state has changed + */ + bool set(uint32_t slot, bool value) { + const uint32_t intId = slot / BitCount; + const uint32_t bitId = slot % BitCount; + const uint32_t bitMask = 1u << bitId; + + const uint32_t prev = m_slots[intId]; + const uint32_t next = value + ? prev | bitMask + : prev & ~bitMask; + m_slots[intId] = next; + return prev != next; + } + + /** + * \brief Marks a binding as active + * + * \param [in] slot The binding ID + * \returns \c true if the state has changed + */ + bool set(uint32_t slot) { + return set(slot, true); + } + + /** + * \brief Marks a binding as inactive + * + * \param [in] slot The binding ID + * \returns \c true if the state has changed + */ + bool clr(uint32_t slot) { + return set(slot, false); + } + + /** + * \brief Clears binding state + * + * Useful to zero out any bindings + * that are not used by a pipeline. + */ + void clear() { + for (uint32_t i = 0; i < IntCount; i++) + m_slots[i] = 0; + } + + /** + * \brief Enables multiple bindings + * \param [in] n Number of bindings + */ + void setFirst(uint32_t n) { + for (uint32_t i = 0; i < IntCount; i++) { + m_slots[i] = n >= BitCount ? ~0u : ~(~0u << n); + n = n >= BitCount ? n - BitCount : 0; + } + } + + /** + * \brief Finds next set binding + * + * \param [in] first Fist bit to consider + * \returns Binding ID, or -1 if none was found + */ + int32_t findNext(uint32_t first) const { + if (unlikely(first >= BindingCount)) + return -1; + + uint32_t intId = first / BitCount; + uint32_t bitId = first % BitCount; + + auto mask = m_slots[intId] & ~((1 << bitId) - 1); + + while (!mask && ++intId < IntCount) + mask = m_slots[intId]; + + if (!mask) + return -1; + + return BitCount * intId + bit::tzcnt(mask); + } + + bool operator == (const DxvkBindingSet& other) const { + bool eq = true; + for (uint32_t i = 0; i < IntCount; i++) + eq &= m_slots[i] == other.m_slots[i]; + return eq; + } + + bool operator != (const DxvkBindingSet& other) const { + return !this->operator == (other); + } + + private: + + uint32_t m_slots[IntCount]; + + }; + + using DxvkBindingMask = DxvkBindingSet; + + + /** + * \brief Bound shader resources + * + * Stores the resources bound to a binding + * slot in DXVK. These are used to create + * descriptor sets. + */ + struct DxvkShaderResourceSlot { + Rc sampler; + Rc imageView; + Rc bufferView; + DxvkBufferSlice bufferSlice; + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_buffer.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_buffer.cpp new file mode 100644 index 00000000000..931a6269dd4 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_buffer.cpp @@ -0,0 +1,254 @@ +#include "dxvk_barrier.h" +#include "dxvk_buffer.h" +#include "dxvk_device.h" + +#include + +namespace dxvk { + + DxvkBuffer::DxvkBuffer( + DxvkDevice* device, + const DxvkBufferCreateInfo& createInfo, + DxvkMemoryAllocator& memAlloc, + VkMemoryPropertyFlags memFlags) + : m_device (device), + m_info (createInfo), + m_memAlloc (&memAlloc), + m_memFlags (memFlags) { + // Align slices so that we don't violate any alignment + // requirements imposed by the Vulkan device/driver + VkDeviceSize sliceAlignment = computeSliceAlignment(); + m_physSliceLength = createInfo.size; + m_physSliceStride = align(createInfo.size, sliceAlignment); + m_physSliceCount = std::max(1, 256 / m_physSliceStride); + + // Limit size of multi-slice buffers to reduce fragmentation + constexpr VkDeviceSize MaxBufferSize = 256 << 10; + + m_physSliceMaxCount = MaxBufferSize >= m_physSliceStride + ? MaxBufferSize / m_physSliceStride + : 1; + + // Allocate the initial set of buffer slices. Only clear + // buffer memory if there is more than one slice, since + // we expect the client api to initialize the first slice. + m_buffer = allocBuffer(m_physSliceCount, m_physSliceCount > 1); + + DxvkBufferSliceHandle slice; + slice.handle = m_buffer.buffer; + slice.offset = 0; + slice.length = m_physSliceLength; + slice.mapPtr = m_buffer.memory.mapPtr(0); + + m_physSlice = slice; + m_lazyAlloc = m_physSliceCount > 1; + } + + + DxvkBuffer::~DxvkBuffer() { + auto vkd = m_device->vkd(); + + for (const auto& buffer : m_buffers) + vkd->vkDestroyBuffer(vkd->device(), buffer.buffer, nullptr); + vkd->vkDestroyBuffer(vkd->device(), m_buffer.buffer, nullptr); + } + + + DxvkBufferHandle DxvkBuffer::allocBuffer(VkDeviceSize sliceCount, bool clear) const { + auto vkd = m_device->vkd(); + + VkBufferCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.size = m_physSliceStride * sliceCount; + info.usage = m_info.usage; + info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + info.queueFamilyIndexCount = 0; + info.pQueueFamilyIndices = nullptr; + + DxvkBufferHandle handle; + + if (vkd->vkCreateBuffer(vkd->device(), + &info, nullptr, &handle.buffer) != VK_SUCCESS) { + throw DxvkError(str::format( + "DxvkBuffer: Failed to create buffer:" + "\n size: ", info.size, + "\n usage: ", info.usage)); + } + + VkMemoryDedicatedRequirements dedicatedRequirements; + dedicatedRequirements.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS; + dedicatedRequirements.pNext = VK_NULL_HANDLE; + dedicatedRequirements.prefersDedicatedAllocation = VK_FALSE; + dedicatedRequirements.requiresDedicatedAllocation = VK_FALSE; + + VkMemoryRequirements2 memReq; + memReq.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2; + memReq.pNext = &dedicatedRequirements; + + VkBufferMemoryRequirementsInfo2 memReqInfo; + memReqInfo.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2; + memReqInfo.buffer = handle.buffer; + memReqInfo.pNext = VK_NULL_HANDLE; + + VkMemoryDedicatedAllocateInfo dedMemoryAllocInfo; + dedMemoryAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO; + dedMemoryAllocInfo.pNext = VK_NULL_HANDLE; + dedMemoryAllocInfo.buffer = handle.buffer; + dedMemoryAllocInfo.image = VK_NULL_HANDLE; + + vkd->vkGetBufferMemoryRequirements2( + vkd->device(), &memReqInfo, &memReq); + + // Use high memory priority for GPU-writable resources + bool isGpuWritable = (m_info.access & ( + VK_ACCESS_SHADER_WRITE_BIT | + VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT)) != 0; + + DxvkMemoryFlags hints(DxvkMemoryFlag::GpuReadable); + + if (isGpuWritable) + hints.set(DxvkMemoryFlag::GpuWritable); + + // Staging buffers that can't even be used as a transfer destinations + // are likely short-lived, so we should put them on a separate memory + // pool in order to avoid fragmentation + if ((DxvkBarrierSet::getAccessTypes(m_info.access) == DxvkAccess::Read) + && (m_info.usage & VK_BUFFER_USAGE_TRANSFER_SRC_BIT)) + hints.set(DxvkMemoryFlag::Transient); + + // Ask driver whether we should be using a dedicated allocation + handle.memory = m_memAlloc->alloc(&memReq.memoryRequirements, + dedicatedRequirements, dedMemoryAllocInfo, m_memFlags, hints); + + if (vkd->vkBindBufferMemory(vkd->device(), handle.buffer, + handle.memory.memory(), handle.memory.offset()) != VK_SUCCESS) + throw DxvkError("DxvkBuffer: Failed to bind device memory"); + + if (clear && (m_memFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) + std::memset(handle.memory.mapPtr(0), 0, info.size); + + return handle; + } + + + VkDeviceSize DxvkBuffer::computeSliceAlignment() const { + const auto& devInfo = m_device->properties().core.properties; + + VkDeviceSize result = sizeof(uint32_t); + + if (m_info.usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) + result = std::max(result, devInfo.limits.minUniformBufferOffsetAlignment); + + if (m_info.usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) + result = std::max(result, devInfo.limits.minStorageBufferOffsetAlignment); + + if (m_info.usage & (VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT)) { + result = std::max(result, devInfo.limits.minTexelBufferOffsetAlignment); + result = std::max(result, VkDeviceSize(16)); + } + + if (m_info.usage & (VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT) + && m_info.size > (devInfo.limits.optimalBufferCopyOffsetAlignment / 2)) + result = std::max(result, devInfo.limits.optimalBufferCopyOffsetAlignment); + + // For some reason, Warhammer Chaosbane breaks otherwise + if (m_info.usage & (VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT)) + result = std::max(result, VkDeviceSize(256)); + + if (m_memFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) { + result = std::max(result, devInfo.limits.nonCoherentAtomSize); + result = std::max(result, VkDeviceSize(64)); + } + + return result; + } + + + + + DxvkBufferView::DxvkBufferView( + const Rc& vkd, + const Rc& buffer, + const DxvkBufferViewCreateInfo& info) + : m_vkd(vkd), m_info(info), m_buffer(buffer), + m_bufferSlice (getSliceHandle()), + m_bufferView (createBufferView(m_bufferSlice)) { + + } + + + DxvkBufferView::~DxvkBufferView() { + if (m_views.empty()) { + m_vkd->vkDestroyBufferView( + m_vkd->device(), m_bufferView, nullptr); + } else { + for (const auto& pair : m_views) { + m_vkd->vkDestroyBufferView( + m_vkd->device(), pair.second, nullptr); + } + } + } + + + VkBufferView DxvkBufferView::createBufferView( + const DxvkBufferSliceHandle& slice) { + VkBufferViewCreateInfo viewInfo; + viewInfo.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO; + viewInfo.pNext = nullptr; + viewInfo.flags = 0; + viewInfo.buffer = slice.handle; + viewInfo.format = m_info.format; + viewInfo.offset = slice.offset; + viewInfo.range = slice.length; + + VkBufferView result = VK_NULL_HANDLE; + + if (m_vkd->vkCreateBufferView(m_vkd->device(), + &viewInfo, nullptr, &result) != VK_SUCCESS) { + throw DxvkError(str::format( + "DxvkBufferView: Failed to create buffer view:", + "\n Offset: ", viewInfo.offset, + "\n Range: ", viewInfo.range, + "\n Format: ", viewInfo.format)); + } + + return result; + } + + + void DxvkBufferView::updateBufferView( + const DxvkBufferSliceHandle& slice) { + if (m_views.empty()) + m_views.insert({ m_bufferSlice, m_bufferView }); + + m_bufferSlice = slice; + + auto entry = m_views.find(slice); + if (entry != m_views.end()) { + m_bufferView = entry->second; + } else { + m_bufferView = createBufferView(m_bufferSlice); + m_views.insert({ m_bufferSlice, m_bufferView }); + } + } + + + DxvkBufferTracker:: DxvkBufferTracker() { } + DxvkBufferTracker::~DxvkBufferTracker() { } + + + void DxvkBufferTracker::reset() { + std::sort(m_entries.begin(), m_entries.end(), + [] (const Entry& a, const Entry& b) { + return a.slice.handle < b.slice.handle; + }); + + for (const auto& e : m_entries) + e.buffer->freeSlice(e.slice); + + m_entries.clear(); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_buffer.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_buffer.h new file mode 100644 index 00000000000..4d94cec7301 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_buffer.h @@ -0,0 +1,691 @@ +#pragma once + +#include +#include + +#include "dxvk_descriptor.h" +#include "dxvk_format.h" +#include "dxvk_hash.h" +#include "dxvk_memory.h" +#include "dxvk_resource.h" + +namespace dxvk { + + /** + * \brief Buffer create info + * + * The properties of a buffer that are + * passed to \ref DxvkDevice::createBuffer + */ + struct DxvkBufferCreateInfo { + /// Size of the buffer, in bytes + VkDeviceSize size; + + /// Buffer usage flags + VkBufferUsageFlags usage; + + /// Pipeline stages that can access + /// the contents of the buffer. + VkPipelineStageFlags stages; + + /// Allowed access patterns + VkAccessFlags access; + }; + + + /** + * \brief Buffer view create info + * + * The properties of a buffer view that + * are to \ref DxvkDevice::createBufferView + */ + struct DxvkBufferViewCreateInfo { + /// Buffer data format, like image data + VkFormat format; + + /// Offset of the buffer region to include in the view + VkDeviceSize rangeOffset; + + /// Size of the buffer region to include in the view + VkDeviceSize rangeLength; + }; + + + /** + * \brief Buffer info + * + * Stores a Vulkan buffer handle and the + * memory object that is bound to the buffer. + */ + struct DxvkBufferHandle { + VkBuffer buffer = VK_NULL_HANDLE; + DxvkMemory memory; + }; + + + /** + * \brief Buffer slice info + * + * Stores the Vulkan buffer handle, offset + * and length of the slice, and a pointer + * to the mapped region.. + */ + struct DxvkBufferSliceHandle { + VkBuffer handle; + VkDeviceSize offset; + VkDeviceSize length; + void* mapPtr; + + bool eq(const DxvkBufferSliceHandle& other) const { + return handle == other.handle + && offset == other.offset + && length == other.length; + } + + size_t hash() const { + DxvkHashState result; + result.add(std::hash()(handle)); + result.add(std::hash()(offset)); + result.add(std::hash()(length)); + return result; + } + }; + + + /** + * \brief Virtual buffer resource + * + * A simple buffer resource that stores linear, + * unformatted data. Can be accessed by the host + * if allocated on an appropriate memory type. + */ + class DxvkBuffer : public DxvkResource { + friend class DxvkBufferView; + public: + + DxvkBuffer( + DxvkDevice* device, + const DxvkBufferCreateInfo& createInfo, + DxvkMemoryAllocator& memAlloc, + VkMemoryPropertyFlags memFlags); + + ~DxvkBuffer(); + + /** + * \brief Buffer properties + * \returns Buffer properties + */ + const DxvkBufferCreateInfo& info() const { + return m_info; + } + + /** + * \brief Memory type flags + * + * Use this to determine whether a + * buffer is mapped to host memory. + * \returns Vulkan memory flags + */ + VkMemoryPropertyFlags memFlags() const { + return m_memFlags; + } + + /** + * \brief Map pointer + * + * If the buffer has been created on a host-visible + * memory type, the buffer memory is mapped and can + * be accessed by the host. + * \param [in] offset Byte offset into mapped region + * \returns Pointer to mapped memory region + */ + void* mapPtr(VkDeviceSize offset) const { + return reinterpret_cast(m_physSlice.mapPtr) + offset; + } + + /** + * \brief Retrieves slice handle + * \returns Buffer slice handle + */ + DxvkBufferSliceHandle getSliceHandle() const { + return m_physSlice; + } + + /** + * \brief Retrieves sub slice handle + * + * \param [in] offset Offset into buffer + * \param [in] length Sub slice length + * \returns Buffer slice handle + */ + DxvkBufferSliceHandle getSliceHandle(VkDeviceSize offset, VkDeviceSize length) const { + DxvkBufferSliceHandle result; + result.handle = m_physSlice.handle; + result.offset = m_physSlice.offset + offset; + result.length = length; + result.mapPtr = mapPtr(offset); + return result; + } + + /** + * \brief Retrieves descriptor info + * + * \param [in] offset Buffer slice offset + * \param [in] length Buffer slice length + * \returns Buffer slice descriptor + */ + DxvkDescriptorInfo getDescriptor(VkDeviceSize offset, VkDeviceSize length) const { + DxvkDescriptorInfo result; + result.buffer.buffer = m_physSlice.handle; + result.buffer.offset = m_physSlice.offset + offset; + result.buffer.range = length; + return result; + } + + /** + * \brief Retrieves dynamic offset + * + * \param [in] offset Offset into the buffer + * \returns Offset for dynamic descriptors + */ + VkDeviceSize getDynamicOffset(VkDeviceSize offset) const { + return m_physSlice.offset + offset; + } + + /** + * \brief Replaces backing resource + * + * Replaces the underlying buffer and implicitly marks + * any buffer views using this resource as dirty. Do + * not call this directly as this is called implicitly + * by the context's \c invalidateBuffer method. + * \param [in] slice The new backing resource + * \returns Previous buffer slice + */ + DxvkBufferSliceHandle rename(const DxvkBufferSliceHandle& slice) { + return std::exchange(m_physSlice, slice); + } + + /** + * \brief Transform feedback vertex stride + * + * Used when drawing after transform feedback, + * \returns The current xfb vertex stride + */ + uint32_t getXfbVertexStride() const { + return m_vertexStride; + } + + /** + * \brief Set transform feedback vertex stride + * + * When the buffer is used as a transform feedback + * buffer, this will be set to the vertex stride + * defined by the geometry shader. + * \param [in] stride Vertex stride + */ + void setXfbVertexStride(uint32_t stride) { + m_vertexStride = stride; + } + + /** + * \brief Allocates new buffer slice + * \returns The new buffer slice + */ + DxvkBufferSliceHandle allocSlice() { + std::unique_lock freeLock(m_freeMutex); + + // If no slices are available, swap the two free lists. + if (unlikely(m_freeSlices.empty())) { + std::unique_lock swapLock(m_swapMutex); + std::swap(m_freeSlices, m_nextSlices); + } + + // If there are still no slices available, create a new + // backing buffer and add all slices to the free list. + if (unlikely(m_freeSlices.empty())) { + if (likely(!m_lazyAlloc)) { + DxvkBufferHandle handle = allocBuffer(m_physSliceCount, true); + + for (uint32_t i = 0; i < m_physSliceCount; i++) + pushSlice(handle, i); + + m_buffers.push_back(std::move(handle)); + m_physSliceCount = std::min(m_physSliceCount * 2, m_physSliceMaxCount); + } else { + for (uint32_t i = 1; i < m_physSliceCount; i++) + pushSlice(m_buffer, i); + + m_lazyAlloc = false; + } + } + + // Take the first slice from the queue + DxvkBufferSliceHandle result = m_freeSlices.back(); + m_freeSlices.pop_back(); + return result; + } + + /** + * \brief Frees a buffer slice + * + * Marks the slice as free so that it can be used for + * subsequent allocations. Called automatically when + * the slice is no longer needed by the GPU. + * \param [in] slice The buffer slice to free + */ + void freeSlice(const DxvkBufferSliceHandle& slice) { + // Add slice to a separate free list to reduce lock contention. + std::unique_lock swapLock(m_swapMutex); + m_nextSlices.push_back(slice); + } + + private: + + DxvkDevice* m_device; + DxvkBufferCreateInfo m_info; + DxvkMemoryAllocator* m_memAlloc; + VkMemoryPropertyFlags m_memFlags; + + DxvkBufferHandle m_buffer; + DxvkBufferSliceHandle m_physSlice; + uint32_t m_vertexStride = 0; + + alignas(CACHE_LINE_SIZE) + sync::Spinlock m_freeMutex; + + uint32_t m_lazyAlloc = false; + VkDeviceSize m_physSliceLength = 0; + VkDeviceSize m_physSliceStride = 0; + VkDeviceSize m_physSliceCount = 1; + VkDeviceSize m_physSliceMaxCount = 1; + + std::vector m_buffers; + std::vector m_freeSlices; + + alignas(CACHE_LINE_SIZE) + sync::Spinlock m_swapMutex; + std::vector m_nextSlices; + + void pushSlice(const DxvkBufferHandle& handle, uint32_t index) { + DxvkBufferSliceHandle slice; + slice.handle = handle.buffer; + slice.length = m_physSliceLength; + slice.offset = m_physSliceStride * index; + slice.mapPtr = handle.memory.mapPtr(slice.offset); + m_freeSlices.push_back(slice); + } + + DxvkBufferHandle allocBuffer( + VkDeviceSize sliceCount, + bool clear) const; + + VkDeviceSize computeSliceAlignment() const; + + }; + + + /** + * \brief Buffer slice + * + * Stores the buffer and a sub-range of the buffer. + * Slices are considered equal if the buffer and + * the buffer range are the same. + */ + class DxvkBufferSlice { + + public: + + DxvkBufferSlice() { } + + DxvkBufferSlice( + const Rc& buffer, + VkDeviceSize rangeOffset, + VkDeviceSize rangeLength) + : m_buffer(buffer), + m_offset(rangeOffset), + m_length(rangeLength) { } + + explicit DxvkBufferSlice(const Rc& buffer) + : DxvkBufferSlice(buffer, 0, buffer->info().size) { } + + DxvkBufferSlice(const DxvkBufferSlice& ) = default; + DxvkBufferSlice( DxvkBufferSlice&&) = default; + + DxvkBufferSlice& operator = (const DxvkBufferSlice& other) { + if (m_buffer != other.m_buffer) + m_buffer = other.m_buffer; + m_offset = other.m_offset; + m_length = other.m_length; + return *this; + } + + DxvkBufferSlice& operator = (DxvkBufferSlice&&) = default; + + /** + * \brief Buffer slice offset and length + * \returns Buffer slice offset and length + */ + size_t offset() const { return m_offset; } + size_t length() const { return m_length; } + + /** + * \brief Underlying buffer + * \returns The virtual buffer + */ + const Rc& buffer() const { + return m_buffer; + } + + /** + * \brief Buffer info + * + * Retrieves the properties of the underlying + * virtual buffer. Should not be used directly + * by client APIs. + * \returns Buffer properties + */ + const DxvkBufferCreateInfo& bufferInfo() const { + return m_buffer->info(); + } + + /** + * \brief Buffer sub slice + * + * Takes a sub slice from this slice. + * \param [in] offset Sub slice offset + * \param [in] length Sub slice length + * \returns The sub slice object + */ + DxvkBufferSlice subSlice(VkDeviceSize offset, VkDeviceSize length) const { + return DxvkBufferSlice(m_buffer, m_offset + offset, length); + } + + /** + * \brief Checks whether the slice is valid + * + * A buffer slice that does not point to any virtual + * buffer object is considered undefined and cannot + * be used for any operations. + * \returns \c true if the slice is defined + */ + bool defined() const { + return m_buffer != nullptr; + } + + /** + * \brief Retrieves buffer slice handle + * + * Returns the buffer handle and offset + * \returns Buffer slice handle + */ + DxvkBufferSliceHandle getSliceHandle() const { + return m_buffer != nullptr + ? m_buffer->getSliceHandle(m_offset, m_length) + : DxvkBufferSliceHandle(); + } + + /** + * \brief Retrieves sub slice handle + * + * \param [in] offset Offset into buffer + * \param [in] length Sub slice length + * \returns Buffer slice handle + */ + DxvkBufferSliceHandle getSliceHandle(VkDeviceSize offset, VkDeviceSize length) const { + return m_buffer != nullptr + ? m_buffer->getSliceHandle(m_offset + offset, length) + : DxvkBufferSliceHandle(); + } + + /** + * \brief Retrieves descriptor info + * \returns Buffer slice descriptor + */ + DxvkDescriptorInfo getDescriptor() const { + return m_buffer->getDescriptor(m_offset, m_length); + } + + /** + * \brief Retrieves dynamic offset + * + * Used for descriptor set binding. + * \returns Buffer slice offset + */ + VkDeviceSize getDynamicOffset() const { + return m_buffer->getDynamicOffset(m_offset); + } + + /** + * \brief Pointer to mapped memory region + * + * \param [in] offset Offset into the slice + * \returns Pointer into mapped buffer memory + */ + void* mapPtr(VkDeviceSize offset) const { + return m_buffer != nullptr + ? m_buffer->mapPtr(m_offset + offset) + : nullptr; + } + + /** + * \brief Checks whether two slices are equal + * + * Two slices are considered equal if they point to + * the same memory region within the same buffer. + * \param [in] other The slice to compare to + * \returns \c true if the two slices are the same + */ + bool matches(const DxvkBufferSlice& other) const { + return this->m_buffer == other.m_buffer + && this->m_offset == other.m_offset + && this->m_length == other.m_length; + } + + /** + * \brief Checks whether two slices are from the same buffer + * + * This returns \c true if the two slices are taken + * from the same buffer, but may have different ranges. + * \param [in] other The slice to compare to + * \returns \c true if the buffer objects are the same + */ + bool matchesBuffer(const DxvkBufferSlice& other) const { + return this->m_buffer == other.m_buffer; + } + + /** + * \brief Checks whether two slices have the same range + * + * This returns \c true if the two slices have the same + * offset and size, even if the buffers are different. + * May be useful if the buffers are know to be the same. + * \param [in] other The slice to compare to + * \returns \c true if the buffer objects are the same + */ + bool matchesRange(const DxvkBufferSlice& other) const { + return this->m_offset == other.m_offset + && this->m_length == other.m_length; + } + + private: + + Rc m_buffer = nullptr; + VkDeviceSize m_offset = 0; + VkDeviceSize m_length = 0; + + }; + + + /** + * \brief Buffer view + * + * Allows the application to interpret buffer + * contents like formatted pixel data. These + * buffer views are used as texel buffers. + */ + class DxvkBufferView : public DxvkResource { + + public: + + DxvkBufferView( + const Rc& vkd, + const Rc& buffer, + const DxvkBufferViewCreateInfo& info); + + ~DxvkBufferView(); + + /** + * \brief Buffer view handle + * \returns Buffer view handle + */ + VkBufferView handle() const { + return m_bufferView; + } + + /** + * \brief Element cound + * + * Number of typed elements contained + * in the buffer view. Depends on the + * buffer view format. + * \returns Element count + */ + VkDeviceSize elementCount() const { + auto format = imageFormatInfo(m_info.format); + return m_info.rangeLength / format->elementSize; + } + + /** + * \brief Buffer view properties + * \returns Buffer view properties + */ + const DxvkBufferViewCreateInfo& info() const { + return m_info; + } + + /** + * \brief Underlying buffer object + * \returns Underlying buffer object + */ + const Rc& buffer() const { + return m_buffer; + } + + /** + * \brief Underlying buffer info + * \returns Underlying buffer info + */ + const DxvkBufferCreateInfo& bufferInfo() const { + return m_buffer->info(); + } + + /** + * \brief View format info + * \returns View format info + */ + const DxvkFormatInfo* formatInfo() const { + return imageFormatInfo(m_info.format); + } + + /** + * \brief Retrieves buffer slice handle + * \returns Buffer slice handle + */ + DxvkBufferSliceHandle getSliceHandle() const { + return m_buffer->getSliceHandle( + m_info.rangeOffset, + m_info.rangeLength); + } + + /** + * \brief Underlying buffer slice + * \returns Slice backing the view + */ + DxvkBufferSlice slice() const { + return DxvkBufferSlice(m_buffer, + m_info.rangeOffset, + m_info.rangeLength); + } + + /** + * \brief Updates the buffer view + * + * If the buffer has been invalidated ever since + * the view was created, the view is invalid as + * well and needs to be re-created. Call this + * prior to using the buffer view handle. + */ + void updateView() { + DxvkBufferSliceHandle slice = getSliceHandle(); + + if (!m_bufferSlice.eq(slice)) + this->updateBufferView(slice); + } + + private: + + Rc m_vkd; + DxvkBufferViewCreateInfo m_info; + Rc m_buffer; + + DxvkBufferSliceHandle m_bufferSlice; + VkBufferView m_bufferView; + + std::unordered_map< + DxvkBufferSliceHandle, + VkBufferView, + DxvkHash, DxvkEq> m_views; + + VkBufferView createBufferView( + const DxvkBufferSliceHandle& slice); + + void updateBufferView( + const DxvkBufferSliceHandle& slice); + + }; + + + /** + * \brief Buffer slice tracker + * + * Stores a list of buffer slices that can be + * freed. Useful when buffers have been renamed + * and the original slice is no longer needed. + */ + class DxvkBufferTracker { + + public: + + DxvkBufferTracker(); + ~DxvkBufferTracker(); + + /** + * \brief Add buffer slice for tracking + * + * The slice will be returned to the + * buffer on the next call to \c reset. + * \param [in] buffer The parent buffer + * \param [in] slice The buffer slice + */ + void freeBufferSlice(const Rc& buffer, const DxvkBufferSliceHandle& slice) { + m_entries.push_back({ buffer, slice }); + } + + /** + * \brief Returns tracked buffer slices + */ + void reset(); + + private: + + struct Entry { + Rc buffer; + DxvkBufferSliceHandle slice; + }; + + std::vector m_entries; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_cmdlist.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_cmdlist.cpp new file mode 100644 index 00000000000..565b9a75d1a --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_cmdlist.cpp @@ -0,0 +1,234 @@ +#include "dxvk_cmdlist.h" +#include "dxvk_device.h" + +namespace dxvk { + + DxvkCommandList::DxvkCommandList(DxvkDevice* device) + : m_device (device), + m_vkd (device->vkd()), + m_vki (device->instance()->vki()), + m_cmdBuffersUsed(0), + m_descriptorPoolTracker(device) { + const auto& graphicsQueue = m_device->queues().graphics; + const auto& transferQueue = m_device->queues().transfer; + + VkFenceCreateInfo fenceInfo; + fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + fenceInfo.pNext = nullptr; + fenceInfo.flags = 0; + + if (m_vkd->vkCreateFence(m_vkd->device(), &fenceInfo, nullptr, &m_fence) != VK_SUCCESS) + throw DxvkError("DxvkCommandList: Failed to create fence"); + + VkCommandPoolCreateInfo poolInfo; + poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + poolInfo.pNext = nullptr; + poolInfo.flags = 0; + poolInfo.queueFamilyIndex = graphicsQueue.queueFamily; + + if (m_vkd->vkCreateCommandPool(m_vkd->device(), &poolInfo, nullptr, &m_graphicsPool) != VK_SUCCESS) + throw DxvkError("DxvkCommandList: Failed to create graphics command pool"); + + if (m_device->hasDedicatedTransferQueue()) { + poolInfo.queueFamilyIndex = transferQueue.queueFamily; + + if (m_vkd->vkCreateCommandPool(m_vkd->device(), &poolInfo, nullptr, &m_transferPool) != VK_SUCCESS) + throw DxvkError("DxvkCommandList: Failed to create transfer command pool"); + } + + VkCommandBufferAllocateInfo cmdInfoGfx; + cmdInfoGfx.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + cmdInfoGfx.pNext = nullptr; + cmdInfoGfx.commandPool = m_graphicsPool; + cmdInfoGfx.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + cmdInfoGfx.commandBufferCount = 1; + + VkCommandBufferAllocateInfo cmdInfoDma; + cmdInfoDma.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + cmdInfoDma.pNext = nullptr; + cmdInfoDma.commandPool = m_transferPool ? m_transferPool : m_graphicsPool; + cmdInfoDma.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + cmdInfoDma.commandBufferCount = 1; + + if (m_vkd->vkAllocateCommandBuffers(m_vkd->device(), &cmdInfoGfx, &m_execBuffer) != VK_SUCCESS + || m_vkd->vkAllocateCommandBuffers(m_vkd->device(), &cmdInfoGfx, &m_initBuffer) != VK_SUCCESS + || m_vkd->vkAllocateCommandBuffers(m_vkd->device(), &cmdInfoDma, &m_sdmaBuffer) != VK_SUCCESS) + throw DxvkError("DxvkCommandList: Failed to allocate command buffer"); + + if (m_device->hasDedicatedTransferQueue()) { + VkSemaphoreCreateInfo semInfo; + semInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + semInfo.pNext = nullptr; + semInfo.flags = 0; + + if (m_vkd->vkCreateSemaphore(m_vkd->device(), &semInfo, nullptr, &m_sdmaSemaphore) != VK_SUCCESS) + throw DxvkError("DxvkCommandList: Failed to create semaphore"); + } + } + + + DxvkCommandList::~DxvkCommandList() { + this->reset(); + + m_vkd->vkDestroySemaphore(m_vkd->device(), m_sdmaSemaphore, nullptr); + + m_vkd->vkDestroyCommandPool(m_vkd->device(), m_graphicsPool, nullptr); + m_vkd->vkDestroyCommandPool(m_vkd->device(), m_transferPool, nullptr); + + m_vkd->vkDestroyFence(m_vkd->device(), m_fence, nullptr); + } + + + VkResult DxvkCommandList::submit( + VkSemaphore waitSemaphore, + VkSemaphore wakeSemaphore) { + const auto& graphics = m_device->queues().graphics; + const auto& transfer = m_device->queues().transfer; + + m_submission.reset(); + + if (m_cmdBuffersUsed.test(DxvkCmdBuffer::SdmaBuffer)) { + m_submission.cmdBuffers.push_back(m_sdmaBuffer); + + if (m_device->hasDedicatedTransferQueue()) { + m_submission.addWakeSemaphore(m_sdmaSemaphore, 0); + VkResult status = submitToQueue(transfer.queueHandle, VK_NULL_HANDLE, m_submission); + + if (status != VK_SUCCESS) + return status; + + m_submission.reset(); + m_submission.addWaitSemaphore(m_sdmaSemaphore, 0, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); + } + } + + if (m_cmdBuffersUsed.test(DxvkCmdBuffer::InitBuffer)) + m_submission.cmdBuffers.push_back(m_initBuffer); + if (m_cmdBuffersUsed.test(DxvkCmdBuffer::ExecBuffer)) + m_submission.cmdBuffers.push_back(m_execBuffer); + + if (waitSemaphore) + m_submission.addWaitSemaphore(waitSemaphore, 0, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); + + if (wakeSemaphore) + m_submission.addWakeSemaphore(wakeSemaphore, 0); + + for (const auto& entry : m_waitSemaphores) { + m_submission.addWaitSemaphore(entry.fence->handle(), entry.value, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); + } + + for (const auto& entry : m_signalSemaphores) { + m_submission.addWakeSemaphore(entry.fence->handle(), entry.value); + } + + return submitToQueue(graphics.queueHandle, m_fence, m_submission); + } + + + VkResult DxvkCommandList::synchronize() { + VkResult status = VK_TIMEOUT; + + while (status == VK_TIMEOUT) { + status = m_vkd->vkWaitForFences( + m_vkd->device(), 1, &m_fence, VK_FALSE, + 1'000'000'000ull); + } + + return status; + } + + + void DxvkCommandList::beginRecording() { + VkCommandBufferBeginInfo info; + info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + info.pNext = nullptr; + info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + info.pInheritanceInfo = nullptr; + + if ((m_graphicsPool && m_vkd->vkResetCommandPool(m_vkd->device(), m_graphicsPool, 0) != VK_SUCCESS) + || (m_transferPool && m_vkd->vkResetCommandPool(m_vkd->device(), m_transferPool, 0) != VK_SUCCESS)) + Logger::err("DxvkCommandList: Failed to reset command buffer"); + + if (m_vkd->vkBeginCommandBuffer(m_execBuffer, &info) != VK_SUCCESS + || m_vkd->vkBeginCommandBuffer(m_initBuffer, &info) != VK_SUCCESS + || m_vkd->vkBeginCommandBuffer(m_sdmaBuffer, &info) != VK_SUCCESS) + Logger::err("DxvkCommandList: Failed to begin command buffer"); + + if (m_vkd->vkResetFences(m_vkd->device(), 1, &m_fence) != VK_SUCCESS) + Logger::err("DxvkCommandList: Failed to reset fence"); + + // Unconditionally mark the exec buffer as used. There + // is virtually no use case where this isn't correct. + m_cmdBuffersUsed = DxvkCmdBuffer::ExecBuffer; + } + + + void DxvkCommandList::endRecording() { + if (m_vkd->vkEndCommandBuffer(m_execBuffer) != VK_SUCCESS + || m_vkd->vkEndCommandBuffer(m_initBuffer) != VK_SUCCESS + || m_vkd->vkEndCommandBuffer(m_sdmaBuffer) != VK_SUCCESS) + Logger::err("DxvkCommandList::endRecording: Failed to record command buffer"); + } + + + void DxvkCommandList::reset() { + // Free resources and other objects + // that are no longer in use + m_resources.reset(); + + // Recycle heavy Vulkan objects + m_descriptorPoolTracker.reset(); + + // Return buffer memory slices + m_bufferTracker.reset(); + + // Return query and event handles + m_gpuQueryTracker.reset(); + m_gpuEventTracker.reset(); + + // Less important stuff + m_signalTracker.reset(); + m_statCounters.reset(); + + m_waitSemaphores.clear(); + m_signalSemaphores.clear(); + } + + + VkResult DxvkCommandList::submitToQueue( + VkQueue queue, + VkFence fence, + const DxvkQueueSubmission& info) { + VkTimelineSemaphoreSubmitInfoKHR timelineInfo = { VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO_KHR }; + timelineInfo.waitSemaphoreValueCount = info.waitValues.size(); + timelineInfo.pWaitSemaphoreValues = info.waitValues.data(); + timelineInfo.signalSemaphoreValueCount = info.wakeValues.size(); + timelineInfo.pSignalSemaphoreValues = info.wakeValues.data(); + + VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO }; + submitInfo.waitSemaphoreCount = info.waitSync.size(); + submitInfo.pWaitSemaphores = info.waitSync.data(); + submitInfo.pWaitDstStageMask = info.waitMask.data(); + submitInfo.commandBufferCount = info.cmdBuffers.size(); + submitInfo.pCommandBuffers = info.cmdBuffers.data(); + submitInfo.signalSemaphoreCount = info.wakeSync.size(); + submitInfo.pSignalSemaphores = info.wakeSync.data(); + + if (m_device->features().khrTimelineSemaphore.timelineSemaphore) + submitInfo.pNext = &timelineInfo; + + return m_vkd->vkQueueSubmit(queue, 1, &submitInfo, fence); + } + + void DxvkCommandList::cmdBeginDebugUtilsLabel(VkDebugUtilsLabelEXT *pLabelInfo) { + m_vki->vkCmdBeginDebugUtilsLabelEXT(m_execBuffer, pLabelInfo); + } + + void DxvkCommandList::cmdEndDebugUtilsLabel() { + m_vki->vkCmdEndDebugUtilsLabelEXT(m_execBuffer); + } + + void DxvkCommandList::cmdInsertDebugUtilsLabel(VkDebugUtilsLabelEXT *pLabelInfo) { + m_vki->vkCmdInsertDebugUtilsLabelEXT(m_execBuffer, pLabelInfo); + } +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_cmdlist.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_cmdlist.h new file mode 100644 index 00000000000..02549df4876 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_cmdlist.h @@ -0,0 +1,836 @@ +#pragma once + +#include + +#include "dxvk_bind_mask.h" +#include "dxvk_buffer.h" +#include "dxvk_descriptor.h" +#include "dxvk_fence.h" +#include "dxvk_gpu_event.h" +#include "dxvk_gpu_query.h" +#include "dxvk_lifetime.h" +#include "dxvk_limits.h" +#include "dxvk_pipelayout.h" +#include "dxvk_signal.h" +#include "dxvk_staging.h" +#include "dxvk_stats.h" + +namespace dxvk { + + /** + * \brief Command buffer flags + * + * A set of flags used to specify which of + * the command buffers need to be submitted. + */ + enum class DxvkCmdBuffer : uint32_t { + InitBuffer = 0, + ExecBuffer = 1, + SdmaBuffer = 2, + }; + + using DxvkCmdBufferFlags = Flags; + + /** + * \brief Queue submission info + * + * Convenience struct that holds data for + * actual command submissions. Internal use + * only, array sizes are based on need. + */ + struct DxvkQueueSubmission { + std::vector waitSync; + std::vector waitMask; + std::vector waitValues; + std::vector wakeSync; + std::vector wakeValues; + std::vector cmdBuffers; + + void addWaitSemaphore(VkSemaphore semaphore, uint64_t value, VkPipelineStageFlags stageMask) { + waitSync.push_back(semaphore); + waitMask.push_back(stageMask); + waitValues.push_back(value); + } + + void addWakeSemaphore(VkSemaphore semaphore, uint64_t value) { + wakeSync.push_back(semaphore); + wakeValues.push_back(value); + } + + void reset() { + waitSync.clear(); + waitMask.clear(); + waitValues.clear(); + wakeSync.clear(); + wakeValues.clear(); + cmdBuffers.clear(); + } + }; + + /** + * \brief DXVK command list + * + * Stores a command buffer that a context can use to record Vulkan + * commands. The command list shall also reference the resources + * used by the recorded commands for automatic lifetime tracking. + * When the command list has completed execution, resources that + * are no longer used may get destroyed. + */ + class DxvkCommandList : public RcObject { + + public: + + DxvkCommandList(DxvkDevice* device); + ~DxvkCommandList(); + + /** + * \brief Submits command list + * + * \param [in] queue Device queue + * \param [in] waitSemaphore Semaphore to wait on + * \param [in] wakeSemaphore Semaphore to signal + * \returns Submission status + */ + VkResult submit( + VkSemaphore waitSemaphore, + VkSemaphore wakeSemaphore); + + /** + * \brief Synchronizes command buffer execution + * + * Waits for the fence associated with + * this command buffer to get signaled. + * \returns Synchronization status + */ + VkResult synchronize(); + + /** + * \brief Stat counters + * + * Retrieves some info about per-command list + * statistics, such as the number of draw calls + * or the number of pipelines compiled. + * \returns Reference to stat counters + */ + DxvkStatCounters& statCounters() { + return m_statCounters; + } + + /** + * \brief Increments a stat counter value + * + * \param [in] ctr The counter to increment + * \param [in] val The value to add + */ + void addStatCtr(DxvkStatCounter ctr, uint64_t val) { + m_statCounters.addCtr(ctr, val); + } + + /** + * \brief Begins recording + * + * Resets the command buffer and + * begins command buffer recording. + */ + void beginRecording(); + + /** + * \brief Ends recording + * + * Ends command buffer recording, making + * the command list ready for submission. + * \param [in] stats Stat counters + */ + void endRecording(); + + /** + * \brief Frees buffer slice + * + * After the command buffer execution has finished, + * the given buffer slice will be released to the + * virtual buffer object so that it can be reused. + * \param [in] buffer The virtual buffer object + * \param [in] slice The buffer slice handle + */ + void freeBufferSlice( + const Rc& buffer, + const DxvkBufferSliceHandle& slice) { + m_bufferTracker.freeBufferSlice(buffer, slice); + } + + /** + * \brief Adds a resource to track + * + * Adds a resource to the internal resource tracker. + * Resources will be kept alive and "in use" until + * the device can guarantee that the submission has + * completed. + */ + template + void trackResource(Rc rc) { + m_resources.trackResource(std::move(rc)); + } + + /** + * \brief Tracks a descriptor pool + * \param [in] pool The descriptor pool + */ + void trackDescriptorPool(Rc pool) { + m_descriptorPoolTracker.trackDescriptorPool(pool); + } + + /** + * \brief Tracks a GPU event + * + * The event will be returned to its event pool + * after the command buffer has finished executing. + * \param [in] handle Event handle + */ + void trackGpuEvent(DxvkGpuEventHandle handle) { + m_gpuEventTracker.trackEvent(handle); + } + + /** + * \brief Tracks a GPU query + * + * The query handle will be returned to its allocator + * after the command buffer has finished executing. + * \param [in] handle Event handle + */ + void trackGpuQuery(DxvkGpuQueryHandle handle) { + m_gpuQueryTracker.trackQuery(handle); + } + + /** + * \brief Queues signal + * + * The signal will be notified once the command + * buffer has finished executing on the GPU. + * \param [in] signal The signal + * \param [in] value Signal value + */ + void queueSignal(const Rc& signal, uint64_t value) { + m_signalTracker.add(signal, value); + } + + /** + * \brief Notifies resources and signals + */ + void notifyObjects() { + m_resources.notify(); + m_signalTracker.notify(); + } + + /** + * \brief Waits for fence + * + * \param [in] fence Fence to wait on + * \param [in] value Value to wait for + */ + void waitFence(Rc fence, uint64_t value) { + m_waitSemaphores.emplace_back(std::move(fence), value); + } + + /** + * \brief Signals fence + * + * \param [in] fence Fence to signal + * \param [in] value Value to signal to + */ + void signalFence(Rc fence, uint64_t value) { + m_signalSemaphores.emplace_back(std::move(fence), value); + } + + /** + * \brief Resets the command list + * + * Resets the internal command buffer of the command list and + * marks all tracked resources as unused. When submitting the + * command list to the device, this method will be called once + * the command list completes execution. + */ + void reset(); + + void updateDescriptorSets( + uint32_t descriptorWriteCount, + const VkWriteDescriptorSet* pDescriptorWrites) { + m_vkd->vkUpdateDescriptorSets(m_vkd->device(), + descriptorWriteCount, pDescriptorWrites, + 0, nullptr); + } + + + void updateDescriptorSetWithTemplate( + VkDescriptorSet descriptorSet, + VkDescriptorUpdateTemplate descriptorTemplate, + const void* data) { + m_vkd->vkUpdateDescriptorSetWithTemplate(m_vkd->device(), + descriptorSet, descriptorTemplate, data); + } + + + void cmdBeginConditionalRendering( + const VkConditionalRenderingBeginInfoEXT* pConditionalRenderingBegin) { + m_vkd->vkCmdBeginConditionalRenderingEXT( + m_execBuffer, pConditionalRenderingBegin); + } + + + void cmdEndConditionalRendering() { + m_vkd->vkCmdEndConditionalRenderingEXT(m_execBuffer); + } + + + + void cmdBeginQuery( + VkQueryPool queryPool, + uint32_t query, + VkQueryControlFlags flags) { + m_vkd->vkCmdBeginQuery(m_execBuffer, + queryPool, query, flags); + } + + + void cmdBeginQueryIndexed( + VkQueryPool queryPool, + uint32_t query, + VkQueryControlFlags flags, + uint32_t index) { + m_vkd->vkCmdBeginQueryIndexedEXT( + m_execBuffer, queryPool, query, flags, index); + } + + + void cmdBeginRenderPass( + const VkRenderPassBeginInfo* pRenderPassBegin, + VkSubpassContents contents) { + m_vkd->vkCmdBeginRenderPass(m_execBuffer, + pRenderPassBegin, contents); + } + + + void cmdBeginTransformFeedback( + uint32_t firstBuffer, + uint32_t bufferCount, + const VkBuffer* counterBuffers, + const VkDeviceSize* counterOffsets) { + m_vkd->vkCmdBeginTransformFeedbackEXT(m_execBuffer, + firstBuffer, bufferCount, counterBuffers, counterOffsets); + } + + + void cmdBindDescriptorSet( + VkPipelineBindPoint pipeline, + VkPipelineLayout pipelineLayout, + VkDescriptorSet descriptorSet, + uint32_t dynamicOffsetCount, + const uint32_t* pDynamicOffsets) { + m_vkd->vkCmdBindDescriptorSets(m_execBuffer, + pipeline, pipelineLayout, 0, 1, + &descriptorSet, dynamicOffsetCount, pDynamicOffsets); + } + + + void cmdBindIndexBuffer( + VkBuffer buffer, + VkDeviceSize offset, + VkIndexType indexType) { + m_vkd->vkCmdBindIndexBuffer(m_execBuffer, + buffer, offset, indexType); + } + + + void cmdBindPipeline( + VkPipelineBindPoint pipelineBindPoint, + VkPipeline pipeline) { + m_vkd->vkCmdBindPipeline(m_execBuffer, + pipelineBindPoint, pipeline); + } + + + void cmdBindTransformFeedbackBuffers( + uint32_t firstBinding, + uint32_t bindingCount, + const VkBuffer* pBuffers, + const VkDeviceSize* pOffsets, + const VkDeviceSize* pSizes) { + m_vkd->vkCmdBindTransformFeedbackBuffersEXT(m_execBuffer, + firstBinding, bindingCount, pBuffers, pOffsets, pSizes); + } + + + void cmdBindVertexBuffers( + uint32_t firstBinding, + uint32_t bindingCount, + const VkBuffer* pBuffers, + const VkDeviceSize* pOffsets) { + m_vkd->vkCmdBindVertexBuffers(m_execBuffer, + firstBinding, bindingCount, pBuffers, pOffsets); + } + + + void cmdBindVertexBuffers2( + uint32_t firstBinding, + uint32_t bindingCount, + const VkBuffer* pBuffers, + const VkDeviceSize* pOffsets, + const VkDeviceSize* pSizes, + const VkDeviceSize* pStrides) { + m_vkd->vkCmdBindVertexBuffers2EXT(m_execBuffer, + firstBinding, bindingCount, pBuffers, pOffsets, + pSizes, pStrides); + } + + void cmdLaunchCuKernel(VkCuLaunchInfoNVX launchInfo) { + m_vkd->vkCmdCuLaunchKernelNVX(m_execBuffer, &launchInfo); + } + + void cmdBlitImage( + VkImage srcImage, + VkImageLayout srcImageLayout, + VkImage dstImage, + VkImageLayout dstImageLayout, + uint32_t regionCount, + const VkImageBlit* pRegions, + VkFilter filter) { + m_vkd->vkCmdBlitImage(m_execBuffer, + srcImage, srcImageLayout, + dstImage, dstImageLayout, + regionCount, pRegions, filter); + } + + + void cmdClearAttachments( + uint32_t attachmentCount, + const VkClearAttachment* pAttachments, + uint32_t rectCount, + const VkClearRect* pRects) { + m_vkd->vkCmdClearAttachments(m_execBuffer, + attachmentCount, pAttachments, + rectCount, pRects); + } + + + void cmdClearColorImage( + VkImage image, + VkImageLayout imageLayout, + const VkClearColorValue* pColor, + uint32_t rangeCount, + const VkImageSubresourceRange* pRanges) { + m_vkd->vkCmdClearColorImage(m_execBuffer, + image, imageLayout, pColor, + rangeCount, pRanges); + } + + + void cmdClearDepthStencilImage( + VkImage image, + VkImageLayout imageLayout, + const VkClearDepthStencilValue* pDepthStencil, + uint32_t rangeCount, + const VkImageSubresourceRange* pRanges) { + m_vkd->vkCmdClearDepthStencilImage(m_execBuffer, + image, imageLayout, pDepthStencil, + rangeCount, pRanges); + } + + + void cmdCopyBuffer( + DxvkCmdBuffer cmdBuffer, + VkBuffer srcBuffer, + VkBuffer dstBuffer, + uint32_t regionCount, + const VkBufferCopy* pRegions) { + m_cmdBuffersUsed.set(cmdBuffer); + + m_vkd->vkCmdCopyBuffer(getCmdBuffer(cmdBuffer), + srcBuffer, dstBuffer, + regionCount, pRegions); + } + + + void cmdCopyBufferToImage( + DxvkCmdBuffer cmdBuffer, + VkBuffer srcBuffer, + VkImage dstImage, + VkImageLayout dstImageLayout, + uint32_t regionCount, + const VkBufferImageCopy* pRegions) { + m_cmdBuffersUsed.set(cmdBuffer); + + m_vkd->vkCmdCopyBufferToImage(getCmdBuffer(cmdBuffer), + srcBuffer, dstImage, dstImageLayout, + regionCount, pRegions); + } + + + void cmdCopyImage( + DxvkCmdBuffer cmdBuffer, + VkImage srcImage, + VkImageLayout srcImageLayout, + VkImage dstImage, + VkImageLayout dstImageLayout, + uint32_t regionCount, + const VkImageCopy* pRegions) { + m_cmdBuffersUsed.set(cmdBuffer); + + m_vkd->vkCmdCopyImage(getCmdBuffer(cmdBuffer), + srcImage, srcImageLayout, + dstImage, dstImageLayout, + regionCount, pRegions); + } + + + void cmdCopyImageToBuffer( + DxvkCmdBuffer cmdBuffer, + VkImage srcImage, + VkImageLayout srcImageLayout, + VkBuffer dstBuffer, + uint32_t regionCount, + const VkBufferImageCopy* pRegions) { + m_cmdBuffersUsed.set(cmdBuffer); + + m_vkd->vkCmdCopyImageToBuffer(getCmdBuffer(cmdBuffer), + srcImage, srcImageLayout, dstBuffer, + regionCount, pRegions); + } + + + void cmdCopyQueryPoolResults( + VkQueryPool queryPool, + uint32_t firstQuery, + uint32_t queryCount, + VkBuffer dstBuffer, + VkDeviceSize dstOffset, + VkDeviceSize stride, + VkQueryResultFlags flags) { + m_vkd->vkCmdCopyQueryPoolResults(m_execBuffer, + queryPool, firstQuery, queryCount, + dstBuffer, dstOffset, stride, flags); + } + + + void cmdDispatch( + uint32_t x, + uint32_t y, + uint32_t z) { + m_vkd->vkCmdDispatch(m_execBuffer, x, y, z); + } + + + void cmdDispatchIndirect( + VkBuffer buffer, + VkDeviceSize offset) { + m_vkd->vkCmdDispatchIndirect( + m_execBuffer, buffer, offset); + } + + + void cmdDraw( + uint32_t vertexCount, + uint32_t instanceCount, + uint32_t firstVertex, + uint32_t firstInstance) { + m_vkd->vkCmdDraw(m_execBuffer, + vertexCount, instanceCount, + firstVertex, firstInstance); + } + + + void cmdDrawIndirect( + VkBuffer buffer, + VkDeviceSize offset, + uint32_t drawCount, + uint32_t stride) { + m_vkd->vkCmdDrawIndirect(m_execBuffer, + buffer, offset, drawCount, stride); + } + + + void cmdDrawIndirectCount( + VkBuffer buffer, + VkDeviceSize offset, + VkBuffer countBuffer, + VkDeviceSize countOffset, + uint32_t maxDrawCount, + uint32_t stride) { + m_vkd->vkCmdDrawIndirectCountKHR(m_execBuffer, + buffer, offset, countBuffer, countOffset, maxDrawCount, stride); + } + + + void cmdDrawIndexed( + uint32_t indexCount, + uint32_t instanceCount, + uint32_t firstIndex, + uint32_t vertexOffset, + uint32_t firstInstance) { + m_vkd->vkCmdDrawIndexed(m_execBuffer, + indexCount, instanceCount, + firstIndex, vertexOffset, + firstInstance); + } + + + void cmdDrawIndexedIndirect( + VkBuffer buffer, + VkDeviceSize offset, + uint32_t drawCount, + uint32_t stride) { + m_vkd->vkCmdDrawIndexedIndirect(m_execBuffer, + buffer, offset, drawCount, stride); + } + + + void cmdDrawIndexedIndirectCount( + VkBuffer buffer, + VkDeviceSize offset, + VkBuffer countBuffer, + VkDeviceSize countOffset, + uint32_t maxDrawCount, + uint32_t stride) { + m_vkd->vkCmdDrawIndexedIndirectCountKHR(m_execBuffer, + buffer, offset, countBuffer, countOffset, maxDrawCount, stride); + } + + + void cmdDrawIndirectVertexCount( + uint32_t instanceCount, + uint32_t firstInstance, + VkBuffer counterBuffer, + VkDeviceSize counterBufferOffset, + uint32_t counterOffset, + uint32_t vertexStride) { + m_vkd->vkCmdDrawIndirectByteCountEXT(m_execBuffer, + instanceCount, firstInstance, counterBuffer, + counterBufferOffset, counterOffset, vertexStride); + } + + + void cmdEndQuery( + VkQueryPool queryPool, + uint32_t query) { + m_vkd->vkCmdEndQuery(m_execBuffer, queryPool, query); + } + + + void cmdEndQueryIndexed( + VkQueryPool queryPool, + uint32_t query, + uint32_t index) { + m_vkd->vkCmdEndQueryIndexedEXT( + m_execBuffer, queryPool, query, index); + } + + + void cmdEndRenderPass() { + m_vkd->vkCmdEndRenderPass(m_execBuffer); + } + + + void cmdEndTransformFeedback( + uint32_t firstBuffer, + uint32_t bufferCount, + const VkBuffer* counterBuffers, + const VkDeviceSize* counterOffsets) { + m_vkd->vkCmdEndTransformFeedbackEXT(m_execBuffer, + firstBuffer, bufferCount, counterBuffers, counterOffsets); + } + + + void cmdFillBuffer( + DxvkCmdBuffer cmdBuffer, + VkBuffer dstBuffer, + VkDeviceSize dstOffset, + VkDeviceSize size, + uint32_t data) { + m_cmdBuffersUsed.set(cmdBuffer); + + m_vkd->vkCmdFillBuffer(getCmdBuffer(cmdBuffer), + dstBuffer, dstOffset, size, data); + } + + + void cmdPipelineBarrier( + DxvkCmdBuffer cmdBuffer, + VkPipelineStageFlags srcStageMask, + VkPipelineStageFlags dstStageMask, + VkDependencyFlags dependencyFlags, + uint32_t memoryBarrierCount, + const VkMemoryBarrier* pMemoryBarriers, + uint32_t bufferMemoryBarrierCount, + const VkBufferMemoryBarrier* pBufferMemoryBarriers, + uint32_t imageMemoryBarrierCount, + const VkImageMemoryBarrier* pImageMemoryBarriers) { + m_cmdBuffersUsed.set(cmdBuffer); + + m_vkd->vkCmdPipelineBarrier(getCmdBuffer(cmdBuffer), + srcStageMask, dstStageMask, dependencyFlags, + memoryBarrierCount, pMemoryBarriers, + bufferMemoryBarrierCount, pBufferMemoryBarriers, + imageMemoryBarrierCount, pImageMemoryBarriers); + } + + + void cmdPushConstants( + VkPipelineLayout layout, + VkShaderStageFlags stageFlags, + uint32_t offset, + uint32_t size, + const void* pValues) { + m_vkd->vkCmdPushConstants(m_execBuffer, + layout, stageFlags, offset, size, pValues); + } + + + void cmdResolveImage( + VkImage srcImage, + VkImageLayout srcImageLayout, + VkImage dstImage, + VkImageLayout dstImageLayout, + uint32_t regionCount, + const VkImageResolve* pRegions) { + m_vkd->vkCmdResolveImage(m_execBuffer, + srcImage, srcImageLayout, + dstImage, dstImageLayout, + regionCount, pRegions); + } + + + void cmdUpdateBuffer( + DxvkCmdBuffer cmdBuffer, + VkBuffer dstBuffer, + VkDeviceSize dstOffset, + VkDeviceSize dataSize, + const void* pData) { + m_cmdBuffersUsed.set(cmdBuffer); + + m_vkd->vkCmdUpdateBuffer(getCmdBuffer(cmdBuffer), + dstBuffer, dstOffset, dataSize, pData); + } + + + void cmdSetBlendConstants(const float blendConstants[4]) { + m_vkd->vkCmdSetBlendConstants(m_execBuffer, blendConstants); + } + + + void cmdSetDepthBias( + float depthBiasConstantFactor, + float depthBiasClamp, + float depthBiasSlopeFactor) { + m_vkd->vkCmdSetDepthBias(m_execBuffer, + depthBiasConstantFactor, + depthBiasClamp, + depthBiasSlopeFactor); + } + + + void cmdSetDepthBounds( + float minDepthBounds, + float maxDepthBounds) { + m_vkd->vkCmdSetDepthBounds(m_execBuffer, + minDepthBounds, + maxDepthBounds); + } + + + void cmdSetEvent( + VkEvent event, + VkPipelineStageFlags stages) { + m_vkd->vkCmdSetEvent(m_execBuffer, event, stages); + } + + + void cmdSetScissor( + uint32_t firstScissor, + uint32_t scissorCount, + const VkRect2D* scissors) { + m_vkd->vkCmdSetScissor(m_execBuffer, + firstScissor, scissorCount, scissors); + } + + + void cmdSetStencilReference( + VkStencilFaceFlags faceMask, + uint32_t reference) { + m_vkd->vkCmdSetStencilReference(m_execBuffer, + faceMask, reference); + } + + + void cmdSetViewport( + uint32_t firstViewport, + uint32_t viewportCount, + const VkViewport* viewports) { + m_vkd->vkCmdSetViewport(m_execBuffer, + firstViewport, viewportCount, viewports); + } + + + void cmdWriteTimestamp( + VkPipelineStageFlagBits pipelineStage, + VkQueryPool queryPool, + uint32_t query) { + m_vkd->vkCmdWriteTimestamp(m_execBuffer, + pipelineStage, queryPool, query); + } + + void cmdBeginDebugUtilsLabel(VkDebugUtilsLabelEXT *pLabelInfo); + + void cmdEndDebugUtilsLabel(); + + void cmdInsertDebugUtilsLabel(VkDebugUtilsLabelEXT *pLabelInfo); + + void resetQuery( + VkQueryPool queryPool, + uint32_t queryId) { + m_vkd->vkResetQueryPoolEXT( + m_vkd->device(), queryPool, queryId, 1); + } + + private: + + DxvkDevice* m_device; + Rc m_vkd; + Rc m_vki; + + VkFence m_fence; + + VkCommandPool m_graphicsPool = VK_NULL_HANDLE; + VkCommandPool m_transferPool = VK_NULL_HANDLE; + + VkCommandBuffer m_execBuffer = VK_NULL_HANDLE; + VkCommandBuffer m_initBuffer = VK_NULL_HANDLE; + VkCommandBuffer m_sdmaBuffer = VK_NULL_HANDLE; + + VkSemaphore m_sdmaSemaphore = VK_NULL_HANDLE; + + DxvkCmdBufferFlags m_cmdBuffersUsed; + DxvkLifetimeTracker m_resources; + DxvkDescriptorPoolTracker m_descriptorPoolTracker; + DxvkSignalTracker m_signalTracker; + DxvkGpuEventTracker m_gpuEventTracker; + DxvkGpuQueryTracker m_gpuQueryTracker; + DxvkBufferTracker m_bufferTracker; + DxvkStatCounters m_statCounters; + DxvkQueueSubmission m_submission; + + std::vector m_waitSemaphores; + std::vector m_signalSemaphores; + + VkCommandBuffer getCmdBuffer(DxvkCmdBuffer cmdBuffer) const { + if (cmdBuffer == DxvkCmdBuffer::ExecBuffer) return m_execBuffer; + if (cmdBuffer == DxvkCmdBuffer::InitBuffer) return m_initBuffer; + if (cmdBuffer == DxvkCmdBuffer::SdmaBuffer) return m_sdmaBuffer; + return VK_NULL_HANDLE; + } + + VkResult submitToQueue( + VkQueue queue, + VkFence fence, + const DxvkQueueSubmission& info); + + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_compute.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_compute.cpp new file mode 100644 index 00000000000..4e0609081fb --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_compute.cpp @@ -0,0 +1,156 @@ +#include + +#include "../util/util_time.h" + +#include "dxvk_compute.h" +#include "dxvk_device.h" +#include "dxvk_pipemanager.h" +#include "dxvk_spec_const.h" +#include "dxvk_state_cache.h" + +namespace dxvk { + + DxvkComputePipeline::DxvkComputePipeline( + DxvkPipelineManager* pipeMgr, + DxvkComputePipelineShaders shaders) + : m_vkd(pipeMgr->m_device->vkd()), m_pipeMgr(pipeMgr), + m_shaders(std::move(shaders)) { + m_shaders.cs->defineResourceSlots(m_slotMapping); + + m_slotMapping.makeDescriptorsDynamic( + m_pipeMgr->m_device->options().maxNumDynamicUniformBuffers, + m_pipeMgr->m_device->options().maxNumDynamicStorageBuffers); + + m_layout = new DxvkPipelineLayout(m_vkd, + m_slotMapping, VK_PIPELINE_BIND_POINT_COMPUTE); + } + + + DxvkComputePipeline::~DxvkComputePipeline() { + for (const auto& instance : m_pipelines) + this->destroyPipeline(instance.pipeline()); + } + + + VkPipeline DxvkComputePipeline::getPipelineHandle( + const DxvkComputePipelineStateInfo& state) { + DxvkComputePipelineInstance* instance = this->findInstance(state); + + if (unlikely(!instance)) { + std::lock_guard lock(m_mutex); + instance = this->findInstance(state); + + if (!instance) { + instance = this->createInstance(state); + this->writePipelineStateToCache(state); + } + } + + return instance->pipeline(); + } + + + void DxvkComputePipeline::compilePipeline( + const DxvkComputePipelineStateInfo& state) { + std::lock_guard lock(m_mutex); + + if (!this->findInstance(state)) + this->createInstance(state); + } + + + DxvkComputePipelineInstance* DxvkComputePipeline::createInstance( + const DxvkComputePipelineStateInfo& state) { + VkPipeline newPipelineHandle = this->createPipeline(state); + + m_pipeMgr->m_numComputePipelines += 1; + return &(*m_pipelines.emplace(state, newPipelineHandle)); + } + + + DxvkComputePipelineInstance* DxvkComputePipeline::findInstance( + const DxvkComputePipelineStateInfo& state) { + for (auto& instance : m_pipelines) { + if (instance.isCompatible(state)) + return &instance; + } + + return nullptr; + } + + + VkPipeline DxvkComputePipeline::createPipeline( + const DxvkComputePipelineStateInfo& state) const { + std::vector bindings; + + if (Logger::logLevel() <= LogLevel::Debug) { + Logger::debug("Compiling compute pipeline..."); + Logger::debug(str::format(" cs : ", m_shaders.cs->debugName())); + } + + DxvkSpecConstants specData; + for (uint32_t i = 0; i < m_layout->bindingCount(); i++) + specData.set(i, state.bsBindingMask.test(i), true); + + for (uint32_t i = 0; i < MaxNumSpecConstants; i++) + specData.set(getSpecId(i), state.sc.specConstants[i], 0u); + + VkSpecializationInfo specInfo = specData.getSpecInfo(); + + DxvkShaderModuleCreateInfo moduleInfo; + moduleInfo.fsDualSrcBlend = false; + + auto csm = m_shaders.cs->createShaderModule(m_vkd, m_slotMapping, moduleInfo); + + VkComputePipelineCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.stage = csm.stageInfo(&specInfo); + info.layout = m_layout->pipelineLayout(); + info.basePipelineHandle = VK_NULL_HANDLE; + info.basePipelineIndex = -1; + + // Time pipeline compilation for debugging purposes + dxvk::high_resolution_clock::time_point t0, t1; + + if (Logger::logLevel() <= LogLevel::Debug) + t0 = dxvk::high_resolution_clock::now(); + + VkPipeline pipeline = VK_NULL_HANDLE; + if (m_vkd->vkCreateComputePipelines(m_vkd->device(), + m_pipeMgr->m_cache->handle(), 1, &info, nullptr, &pipeline) != VK_SUCCESS) { + Logger::err("DxvkComputePipeline: Failed to compile pipeline"); + Logger::err(str::format(" cs : ", m_shaders.cs->debugName())); + return VK_NULL_HANDLE; + } + + if (Logger::logLevel() <= LogLevel::Debug) { + t1 = dxvk::high_resolution_clock::now(); + auto td = std::chrono::duration_cast(t1 - t0); + Logger::debug(str::format("DxvkComputePipeline: Finished in ", td.count(), " ms")); + } + + return pipeline; + } + + + void DxvkComputePipeline::destroyPipeline(VkPipeline pipeline) { + m_vkd->vkDestroyPipeline(m_vkd->device(), pipeline, nullptr); + } + + + void DxvkComputePipeline::writePipelineStateToCache( + const DxvkComputePipelineStateInfo& state) const { + if (m_pipeMgr->m_stateCache == nullptr) + return; + + DxvkStateCacheKey key; + + if (m_shaders.cs != nullptr) + key.cs = m_shaders.cs->getShaderKey(); + + m_pipeMgr->m_stateCache->addComputePipeline(key, state); + } + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_compute.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_compute.h new file mode 100644 index 00000000000..186d17ef193 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_compute.h @@ -0,0 +1,168 @@ +#pragma once + +#include + +#include "../util/sync/sync_list.h" + +#include "dxvk_bind_mask.h" +#include "dxvk_graphics_state.h" +#include "dxvk_pipecache.h" +#include "dxvk_pipelayout.h" +#include "dxvk_resource.h" +#include "dxvk_shader.h" +#include "dxvk_stats.h" + +namespace dxvk { + + class DxvkDevice; + class DxvkPipelineManager; + + /** + * \brief Shaders used in compute pipelines + */ + struct DxvkComputePipelineShaders { + Rc cs; + + bool eq(const DxvkComputePipelineShaders& other) const { + return cs == other.cs; + } + + size_t hash() const { + return DxvkShader::getHash(cs); + } + }; + + + /** + * \brief Compute pipeline instance + */ + class DxvkComputePipelineInstance { + + public: + + DxvkComputePipelineInstance() + : m_stateVector (), + m_pipeline (VK_NULL_HANDLE) { } + + DxvkComputePipelineInstance( + const DxvkComputePipelineStateInfo& state, + VkPipeline pipe) + : m_stateVector (state), + m_pipeline (pipe) { } + + /** + * \brief Checks for matching pipeline state + * + * \param [in] stateVector Graphics pipeline state + * \param [in] renderPass Render pass handle + * \returns \c true if the specialization is compatible + */ + bool isCompatible(const DxvkComputePipelineStateInfo& state) const { + return m_stateVector == state; + } + + /** + * \brief Retrieves pipeline + * \returns The pipeline handle + */ + VkPipeline pipeline() const { + return m_pipeline; + } + + private: + + DxvkComputePipelineStateInfo m_stateVector; + VkPipeline m_pipeline; + + }; + + + /** + * \brief Compute pipeline + * + * Stores a compute pipeline object and the corresponding + * pipeline layout. Unlike graphics pipelines, compute + * pipelines do not need to be recompiled against any sort + * of pipeline state. + */ + class DxvkComputePipeline { + + public: + + DxvkComputePipeline( + DxvkPipelineManager* pipeMgr, + DxvkComputePipelineShaders shaders); + + ~DxvkComputePipeline(); + + /** + * \brief Shaders used by the pipeline + * \returns Shaders used by the pipeline + */ + const DxvkComputePipelineShaders& shaders() const { + return m_shaders; + } + + /** + * \brief Pipeline layout + * + * Stores the pipeline layout and the descriptor set + * layout, as well as information on the resource + * slots used by the pipeline. + * \returns Pipeline layout + */ + DxvkPipelineLayout* layout() const { + return m_layout.ptr(); + } + + /** + * \brief Retrieves pipeline handle + * + * \param [in] state Pipeline state + * \returns Pipeline handle + */ + VkPipeline getPipelineHandle( + const DxvkComputePipelineStateInfo& state); + + /** + * \brief Compiles a pipeline + * + * Asynchronously compiles the given pipeline + * and stores the result for future use. + * \param [in] state Pipeline state + */ + void compilePipeline( + const DxvkComputePipelineStateInfo& state); + + private: + + Rc m_vkd; + DxvkPipelineManager* m_pipeMgr; + + DxvkComputePipelineShaders m_shaders; + DxvkDescriptorSlotMapping m_slotMapping; + + Rc m_layout; + + alignas(CACHE_LINE_SIZE) + dxvk::mutex m_mutex; + sync::List m_pipelines; + + DxvkComputePipelineInstance* createInstance( + const DxvkComputePipelineStateInfo& state); + + DxvkComputePipelineInstance* findInstance( + const DxvkComputePipelineStateInfo& state); + + VkPipeline createPipeline( + const DxvkComputePipelineStateInfo& state) const; + + void destroyPipeline( + VkPipeline pipeline); + + void writePipelineStateToCache( + const DxvkComputePipelineStateInfo& state) const; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_constant_state.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_constant_state.h new file mode 100644 index 00000000000..b17dd9b52a8 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_constant_state.h @@ -0,0 +1,208 @@ +#pragma once + +#include "dxvk_buffer.h" +#include "dxvk_framebuffer.h" +#include "dxvk_limits.h" +#include "dxvk_resource.h" +#include "dxvk_shader.h" + +namespace dxvk { + + /** + * \brief Blend constants + * + * Stores a blend factor + * as an RGBA color value. + */ + struct DxvkBlendConstants { + float r, g, b, a; + + bool operator == (const DxvkBlendConstants& other) const { + return this->r == other.r && this->g == other.g + && this->b == other.b && this->a == other.a; + } + + bool operator != (const DxvkBlendConstants& other) const { + return this->r != other.r || this->g != other.g + || this->b != other.b || this->a != other.a; + } + }; + + + /** + * \brief Depth bias + * + * Stores depth bias values. + */ + struct DxvkDepthBias { + float depthBiasConstant; + float depthBiasSlope; + float depthBiasClamp; + + bool operator == (const DxvkDepthBias& other) const { + return depthBiasConstant == other.depthBiasConstant + && depthBiasSlope == other.depthBiasSlope + && depthBiasClamp == other.depthBiasClamp; + } + + bool operator != (const DxvkDepthBias& other) const { + return depthBiasConstant != other.depthBiasConstant + || depthBiasSlope != other.depthBiasSlope + || depthBiasClamp != other.depthBiasClamp; + } + }; + + + /** + * \brief Depth bounds + * + * Stores depth bounds values. + */ + struct DxvkDepthBounds { + VkBool32 enableDepthBounds; + float minDepthBounds; + float maxDepthBounds; + + bool operator == (const DxvkDepthBounds& other) const { + return enableDepthBounds == other.enableDepthBounds + && minDepthBounds == other.minDepthBounds + && maxDepthBounds == other.maxDepthBounds; + } + + bool operator != (const DxvkDepthBounds& other) const { + return enableDepthBounds != other.enableDepthBounds + || minDepthBounds != other.minDepthBounds + || maxDepthBounds != other.maxDepthBounds; + } + }; + + + /** + * \brief Input assembly state + * + * Stores the primitive topology and + * whether or not primitive restart + * is enabled. + */ + struct DxvkInputAssemblyState { + VkPrimitiveTopology primitiveTopology; + VkBool32 primitiveRestart; + uint32_t patchVertexCount; + }; + + + /** + * \brief Rasterizer state + * + * Stores the operating mode of the + * rasterizer, including the depth bias. + */ + struct DxvkRasterizerState { + VkPolygonMode polygonMode; + VkCullModeFlags cullMode; + VkFrontFace frontFace; + VkBool32 depthClipEnable; + VkBool32 depthBiasEnable; + VkConservativeRasterizationModeEXT conservativeMode; + VkSampleCountFlags sampleCount; + }; + + + /** + * \brief Multisample state + * + * Defines how to handle certain + * aspects of multisampling. + */ + struct DxvkMultisampleState { + uint32_t sampleMask; + VkBool32 enableAlphaToCoverage; + }; + + + /** + * \brief Depth-stencil state + * + * Defines the depth test and stencil + * operations for the graphics pipeline. + */ + struct DxvkDepthStencilState { + VkBool32 enableDepthTest; + VkBool32 enableDepthWrite; + VkBool32 enableStencilTest; + VkCompareOp depthCompareOp; + VkStencilOpState stencilOpFront; + VkStencilOpState stencilOpBack; + }; + + + /** + * \brief Logic op state + * Defines a logic op. + */ + struct DxvkLogicOpState { + VkBool32 enableLogicOp; + VkLogicOp logicOp; + }; + + + /** + * \brief Blend mode for a single attachment + * + * Stores the blend state for a single color attachment. + * Blend modes can be set separately for each attachment. + */ + struct DxvkBlendMode { + VkBool32 enableBlending; + VkBlendFactor colorSrcFactor; + VkBlendFactor colorDstFactor; + VkBlendOp colorBlendOp; + VkBlendFactor alphaSrcFactor; + VkBlendFactor alphaDstFactor; + VkBlendOp alphaBlendOp; + VkColorComponentFlags writeMask; + }; + + + /** + * \brief Vertex attribute description + * + * Stores information about a + * single vertex attribute. + */ + struct DxvkVertexAttribute { + uint32_t location; + uint32_t binding; + VkFormat format; + uint32_t offset; + }; + + + /** + * \brief Vertex binding description + * + * Stores information about a + * single vertex binding slot. + */ + struct DxvkVertexBinding { + uint32_t binding; + uint32_t fetchRate; + VkVertexInputRate inputRate; + }; + + + /** + * \brief Input layout + * + * Stores the description of all active + * vertex attributes and vertex bindings. + */ + struct DxvkInputLayout { + uint32_t numAttributes; + uint32_t numBindings; + + std::array attributes; + std::array bindings; + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_context.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_context.cpp new file mode 100644 index 00000000000..6d300887f8d --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_context.cpp @@ -0,0 +1,5286 @@ +#include +#include +#include + +#include "dxvk_device.h" +#include "dxvk_context.h" + +namespace dxvk { + + DxvkContext::DxvkContext(const Rc& device) + : m_device (device), + m_common (&device->m_objects), + m_sdmaAcquires(DxvkCmdBuffer::SdmaBuffer), + m_sdmaBarriers(DxvkCmdBuffer::SdmaBuffer), + m_initBarriers(DxvkCmdBuffer::InitBuffer), + m_execAcquires(DxvkCmdBuffer::ExecBuffer), + m_execBarriers(DxvkCmdBuffer::ExecBuffer), + m_gfxBarriers (DxvkCmdBuffer::ExecBuffer), + m_queryManager(m_common->queryPool()), + m_staging (device, StagingBufferSize) { + if (m_device->features().extRobustness2.nullDescriptor) + m_features.set(DxvkContextFeature::NullDescriptors); + if (m_device->features().extExtendedDynamicState.extendedDynamicState) + m_features.set(DxvkContextFeature::ExtendedDynamicState); + + // Init framebuffer info with default render pass in case + // the app does not explicitly bind any render targets + m_state.om.framebufferInfo = makeFramebufferInfo(m_state.om.renderTargets); + } + + + DxvkContext::~DxvkContext() { + + } + + + void DxvkContext::beginRecording(const Rc& cmdList) { + m_cmd = cmdList; + m_cmd->beginRecording(); + + // Mark all resources as untracked + m_vbTracked.clear(); + m_rcTracked.clear(); + + // The current state of the internal command buffer is + // undefined, so we have to bind and set up everything + // before any draw or dispatch command is recorded. + m_flags.clr( + DxvkContextFlag::GpRenderPassBound, + DxvkContextFlag::GpXfbActive); + + m_flags.set( + DxvkContextFlag::GpDirtyFramebuffer, + DxvkContextFlag::GpDirtyPipeline, + DxvkContextFlag::GpDirtyPipelineState, + DxvkContextFlag::GpDirtyResources, + DxvkContextFlag::GpDirtyVertexBuffers, + DxvkContextFlag::GpDirtyIndexBuffer, + DxvkContextFlag::GpDirtyXfbBuffers, + DxvkContextFlag::GpDirtyBlendConstants, + DxvkContextFlag::GpDirtyStencilRef, + DxvkContextFlag::GpDirtyViewport, + DxvkContextFlag::GpDirtyDepthBias, + DxvkContextFlag::GpDirtyDepthBounds, + DxvkContextFlag::CpDirtyPipeline, + DxvkContextFlag::CpDirtyPipelineState, + DxvkContextFlag::CpDirtyResources, + DxvkContextFlag::DirtyDrawBuffer); + } + + + Rc DxvkContext::endRecording() { + this->spillRenderPass(true); + this->flushSharedImages(); + + m_sdmaBarriers.recordCommands(m_cmd); + m_initBarriers.recordCommands(m_cmd); + m_execBarriers.recordCommands(m_cmd); + + m_cmd->endRecording(); + return std::exchange(m_cmd, nullptr); + } + + + void DxvkContext::flushCommandList() { + m_device->submitCommandList( + this->endRecording(), + VK_NULL_HANDLE, + VK_NULL_HANDLE); + + this->beginRecording( + m_device->createCommandList()); + } + + + void DxvkContext::beginQuery(const Rc& query) { + m_queryManager.enableQuery(m_cmd, query); + } + + + void DxvkContext::endQuery(const Rc& query) { + m_queryManager.disableQuery(m_cmd, query); + } + + + void DxvkContext::bindRenderTargets( + const DxvkRenderTargets& targets) { + // Set up default render pass ops + m_state.om.renderTargets = targets; + + this->resetRenderPassOps( + m_state.om.renderTargets, + m_state.om.renderPassOps); + + if (!m_state.om.framebufferInfo.hasTargets(targets)) { + // Create a new framebuffer object next + // time we start rendering something + m_flags.set(DxvkContextFlag::GpDirtyFramebuffer); + } else { + // Don't redundantly spill the render pass if + // the same render targets are bound again + m_flags.clr(DxvkContextFlag::GpDirtyFramebuffer); + } + } + + + void DxvkContext::bindDrawBuffers( + const DxvkBufferSlice& argBuffer, + const DxvkBufferSlice& cntBuffer) { + m_state.id.argBuffer = argBuffer; + m_state.id.cntBuffer = cntBuffer; + + m_flags.set(DxvkContextFlag::DirtyDrawBuffer); + } + + + void DxvkContext::bindIndexBuffer( + const DxvkBufferSlice& buffer, + VkIndexType indexType) { + if (!m_state.vi.indexBuffer.matchesBuffer(buffer)) + m_vbTracked.clr(MaxNumVertexBindings); + + m_state.vi.indexBuffer = buffer; + m_state.vi.indexType = indexType; + + m_flags.set(DxvkContextFlag::GpDirtyIndexBuffer); + } + + + void DxvkContext::bindResourceBuffer( + uint32_t slot, + const DxvkBufferSlice& buffer) { + bool needsUpdate = !m_rc[slot].bufferSlice.matchesBuffer(buffer); + + if (likely(needsUpdate)) + m_rcTracked.clr(slot); + else + needsUpdate = m_rc[slot].bufferSlice.length() != buffer.length(); + + if (likely(needsUpdate)) { + m_flags.set( + DxvkContextFlag::CpDirtyResources, + DxvkContextFlag::GpDirtyResources); + } else { + m_flags.set( + DxvkContextFlag::CpDirtyDescriptorBinding, + DxvkContextFlag::GpDirtyDescriptorBinding); + } + + m_rc[slot].bufferSlice = buffer; + } + + + void DxvkContext::bindResourceView( + uint32_t slot, + const Rc& imageView, + const Rc& bufferView) { + m_rc[slot].imageView = imageView; + m_rc[slot].bufferView = bufferView; + m_rc[slot].bufferSlice = bufferView != nullptr + ? bufferView->slice() + : DxvkBufferSlice(); + m_rcTracked.clr(slot); + + m_flags.set( + DxvkContextFlag::CpDirtyResources, + DxvkContextFlag::GpDirtyResources); + } + + + void DxvkContext::bindResourceSampler( + uint32_t slot, + const Rc& sampler) { + m_rc[slot].sampler = sampler; + m_rcTracked.clr(slot); + + m_flags.set( + DxvkContextFlag::CpDirtyResources, + DxvkContextFlag::GpDirtyResources); + } + + + void DxvkContext::bindShader( + VkShaderStageFlagBits stage, + const Rc& shader) { + Rc* shaderStage; + + switch (stage) { + case VK_SHADER_STAGE_VERTEX_BIT: shaderStage = &m_state.gp.shaders.vs; break; + case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: shaderStage = &m_state.gp.shaders.tcs; break; + case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: shaderStage = &m_state.gp.shaders.tes; break; + case VK_SHADER_STAGE_GEOMETRY_BIT: shaderStage = &m_state.gp.shaders.gs; break; + case VK_SHADER_STAGE_FRAGMENT_BIT: shaderStage = &m_state.gp.shaders.fs; break; + case VK_SHADER_STAGE_COMPUTE_BIT: shaderStage = &m_state.cp.shaders.cs; break; + default: return; + } + + *shaderStage = shader; + + if (stage == VK_SHADER_STAGE_COMPUTE_BIT) { + m_flags.set( + DxvkContextFlag::CpDirtyPipeline, + DxvkContextFlag::CpDirtyPipelineState, + DxvkContextFlag::CpDirtyResources); + } else { + m_flags.set( + DxvkContextFlag::GpDirtyPipeline, + DxvkContextFlag::GpDirtyPipelineState, + DxvkContextFlag::GpDirtyResources); + } + } + + + void DxvkContext::bindVertexBuffer( + uint32_t binding, + const DxvkBufferSlice& buffer, + uint32_t stride) { + if (!m_state.vi.vertexBuffers[binding].matchesBuffer(buffer)) + m_vbTracked.clr(binding); + + m_state.vi.vertexBuffers[binding] = buffer; + m_flags.set(DxvkContextFlag::GpDirtyVertexBuffers); + + if (unlikely(m_state.vi.vertexStrides[binding] != stride)) { + m_state.vi.vertexStrides[binding] = stride; + m_flags.set(DxvkContextFlag::GpDirtyPipelineState); + } + } + + + void DxvkContext::bindXfbBuffer( + uint32_t binding, + const DxvkBufferSlice& buffer, + const DxvkBufferSlice& counter) { + if (!m_state.xfb.buffers [binding].matches(buffer) + || !m_state.xfb.counters[binding].matches(counter)) { + m_state.xfb.buffers [binding] = buffer; + m_state.xfb.counters[binding] = counter; + + m_flags.set(DxvkContextFlag::GpDirtyXfbBuffers); + } + } + + + void DxvkContext::blitImage( + const Rc& dstImage, + const VkComponentMapping& dstMapping, + const Rc& srcImage, + const VkComponentMapping& srcMapping, + const VkImageBlit& region, + VkFilter filter) { + this->spillRenderPass(true); + this->prepareImage(m_execBarriers, dstImage, vk::makeSubresourceRange(region.dstSubresource)); + this->prepareImage(m_execBarriers, srcImage, vk::makeSubresourceRange(region.srcSubresource)); + + auto mapping = util::resolveSrcComponentMapping(dstMapping, srcMapping); + + bool canUseFb = (srcImage->info().usage & VK_IMAGE_USAGE_SAMPLED_BIT) + && (dstImage->info().usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) + && ((dstImage->info().flags & VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT) + || (dstImage->info().type != VK_IMAGE_TYPE_3D)); + + bool useFb = dstImage->info().sampleCount != VK_SAMPLE_COUNT_1_BIT + || !util::isIdentityMapping(mapping); + + if (!useFb) { + this->blitImageHw( + dstImage, srcImage, + region, filter); + } else if (canUseFb) { + this->blitImageFb( + dstImage, srcImage, + region, mapping, filter); + } else { + Logger::err("DxvkContext: Unsupported blit operation"); + } + } + + + void DxvkContext::changeImageLayout( + const Rc& image, + VkImageLayout layout) { + if (image->info().layout != layout) { + this->spillRenderPass(true); + + VkImageSubresourceRange subresources = image->getAvailableSubresources(); + + this->prepareImage(m_execBarriers, image, subresources); + + if (m_execBarriers.isImageDirty(image, subresources, DxvkAccess::Write)) + m_execBarriers.recordCommands(m_cmd); + + m_execBarriers.accessImage(image, subresources, + image->info().layout, + image->info().stages, 0, + layout, + image->info().stages, + image->info().access); + + image->setLayout(layout); + + m_cmd->trackResource(image); + } + } + + + void DxvkContext::clearBuffer( + const Rc& buffer, + VkDeviceSize offset, + VkDeviceSize length, + uint32_t value) { + bool replaceBuffer = this->tryInvalidateDeviceLocalBuffer(buffer, length); + auto bufferSlice = buffer->getSliceHandle(offset, align(length, sizeof(uint32_t))); + + if (!replaceBuffer) { + this->spillRenderPass(true); + + if (m_execBarriers.isBufferDirty(bufferSlice, DxvkAccess::Write)) + m_execBarriers.recordCommands(m_cmd); + } + + DxvkCmdBuffer cmdBuffer = replaceBuffer + ? DxvkCmdBuffer::InitBuffer + : DxvkCmdBuffer::ExecBuffer; + + if (length > sizeof(value)) { + m_cmd->cmdFillBuffer(cmdBuffer, + bufferSlice.handle, + bufferSlice.offset, + bufferSlice.length, + value); + } else { + m_cmd->cmdUpdateBuffer(cmdBuffer, + bufferSlice.handle, + bufferSlice.offset, + bufferSlice.length, + &value); + } + + auto& barriers = replaceBuffer + ? m_initBarriers + : m_execBarriers; + + barriers.accessBuffer(bufferSlice, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT, + buffer->info().stages, + buffer->info().access); + + m_cmd->trackResource(buffer); + } + + + void DxvkContext::clearBufferView( + const Rc& bufferView, + VkDeviceSize offset, + VkDeviceSize length, + VkClearColorValue value) { + this->spillRenderPass(true); + this->unbindComputePipeline(); + + // The view range might have been invalidated, so + // we need to make sure the handle is up to date + bufferView->updateView(); + + auto bufferSlice = bufferView->getSliceHandle(); + + if (m_execBarriers.isBufferDirty(bufferSlice, DxvkAccess::Write)) + m_execBarriers.recordCommands(m_cmd); + + // Query pipeline objects to use for this clear operation + DxvkMetaClearPipeline pipeInfo = m_common->metaClear().getClearBufferPipeline( + imageFormatInfo(bufferView->info().format)->flags); + + // Create a descriptor set pointing to the view + VkBufferView viewObject = bufferView->handle(); + + VkDescriptorSet descriptorSet = allocateDescriptorSet(pipeInfo.dsetLayout); + + VkWriteDescriptorSet descriptorWrite; + descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrite.pNext = nullptr; + descriptorWrite.dstSet = descriptorSet; + descriptorWrite.dstBinding = 0; + descriptorWrite.dstArrayElement = 0; + descriptorWrite.descriptorCount = 1; + descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; + descriptorWrite.pImageInfo = nullptr; + descriptorWrite.pBufferInfo = nullptr; + descriptorWrite.pTexelBufferView = &viewObject; + m_cmd->updateDescriptorSets(1, &descriptorWrite); + + // Prepare shader arguments + DxvkMetaClearArgs pushArgs = { }; + pushArgs.clearValue = value; + pushArgs.offset = VkOffset3D { int32_t(offset), 0, 0 }; + pushArgs.extent = VkExtent3D { uint32_t(length), 1, 1 }; + + VkExtent3D workgroups = util::computeBlockCount( + pushArgs.extent, pipeInfo.workgroupSize); + + m_cmd->cmdBindPipeline( + VK_PIPELINE_BIND_POINT_COMPUTE, + pipeInfo.pipeline); + m_cmd->cmdBindDescriptorSet( + VK_PIPELINE_BIND_POINT_COMPUTE, + pipeInfo.pipeLayout, descriptorSet, + 0, nullptr); + m_cmd->cmdPushConstants( + pipeInfo.pipeLayout, + VK_SHADER_STAGE_COMPUTE_BIT, + 0, sizeof(pushArgs), &pushArgs); + m_cmd->cmdDispatch( + workgroups.width, + workgroups.height, + workgroups.depth); + + m_execBarriers.accessBuffer(bufferSlice, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_ACCESS_SHADER_WRITE_BIT, + bufferView->bufferInfo().stages, + bufferView->bufferInfo().access); + + m_cmd->trackResource(bufferView); + m_cmd->trackResource(bufferView->buffer()); + } + + + void DxvkContext::clearRenderTarget( + const Rc& imageView, + VkImageAspectFlags clearAspects, + VkClearValue clearValue) { + // Make sure the color components are ordered correctly + if (clearAspects & VK_IMAGE_ASPECT_COLOR_BIT) { + clearValue.color = util::swizzleClearColor(clearValue.color, + util::invertComponentMapping(imageView->info().swizzle)); + } + + // Check whether the render target view is an attachment + // of the current framebuffer and is included entirely. + // If not, we need to create a temporary framebuffer. + int32_t attachmentIndex = -1; + + if (m_state.om.framebufferInfo.isFullSize(imageView)) + attachmentIndex = m_state.om.framebufferInfo.findAttachment(imageView); + + if (attachmentIndex < 0) { + // Suspend works here because we'll end up with one of these scenarios: + // 1) The render pass gets ended for good, in which case we emit barriers + // 2) The clear gets folded into render pass ops, so the layout is correct + // 3) The clear gets executed separately, in which case updateFramebuffer + // will indirectly emit barriers for the given render target. + // If there is overlap, we need to explicitly transition affected attachments. + this->spillRenderPass(true); + this->prepareImage(m_execBarriers, imageView->image(), imageView->subresources(), false); + } else if (!m_state.om.framebufferInfo.isWritable(attachmentIndex, clearAspects)) { + // We cannot inline clears if the clear aspects are not writable + this->spillRenderPass(true); + } + + if (m_flags.test(DxvkContextFlag::GpRenderPassBound)) { + uint32_t colorIndex = std::max(0, m_state.om.framebufferInfo.getColorAttachmentIndex(attachmentIndex)); + + VkClearAttachment clearInfo; + clearInfo.aspectMask = clearAspects; + clearInfo.colorAttachment = colorIndex; + clearInfo.clearValue = clearValue; + + VkClearRect clearRect; + clearRect.rect.offset.x = 0; + clearRect.rect.offset.y = 0; + clearRect.rect.extent.width = imageView->mipLevelExtent(0).width; + clearRect.rect.extent.height = imageView->mipLevelExtent(0).height; + clearRect.baseArrayLayer = 0; + clearRect.layerCount = imageView->info().numLayers; + + m_cmd->cmdClearAttachments(1, &clearInfo, 1, &clearRect); + } else + this->deferClear(imageView, clearAspects, clearValue); + } + + + void DxvkContext::clearImageView( + const Rc& imageView, + VkOffset3D offset, + VkExtent3D extent, + VkImageAspectFlags aspect, + VkClearValue value) { + const VkImageUsageFlags viewUsage = imageView->info().usage; + + if (aspect & VK_IMAGE_ASPECT_COLOR_BIT) { + value.color = util::swizzleClearColor(value.color, + util::invertComponentMapping(imageView->info().swizzle)); + } + + if (viewUsage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) + this->clearImageViewFb(imageView, offset, extent, aspect, value); + else if (viewUsage & VK_IMAGE_USAGE_STORAGE_BIT) + this->clearImageViewCs(imageView, offset, extent, value); + } + + + void DxvkContext::copyBuffer( + const Rc& dstBuffer, + VkDeviceSize dstOffset, + const Rc& srcBuffer, + VkDeviceSize srcOffset, + VkDeviceSize numBytes) { + // When overwriting small buffers, we can allocate a new slice in order to + // avoid suspending the current render pass or inserting barriers. The source + // buffer must be read-only since otherwise we cannot schedule the copy early. + bool srcIsReadOnly = DxvkBarrierSet::getAccessTypes(srcBuffer->info().access) == DxvkAccess::Read; + bool replaceBuffer = srcIsReadOnly && this->tryInvalidateDeviceLocalBuffer(dstBuffer, numBytes); + + auto srcSlice = srcBuffer->getSliceHandle(srcOffset, numBytes); + auto dstSlice = dstBuffer->getSliceHandle(dstOffset, numBytes); + + if (!replaceBuffer) { + this->spillRenderPass(true); + + if (m_execBarriers.isBufferDirty(srcSlice, DxvkAccess::Read) + || m_execBarriers.isBufferDirty(dstSlice, DxvkAccess::Write)) + m_execBarriers.recordCommands(m_cmd); + } + + DxvkCmdBuffer cmdBuffer = replaceBuffer + ? DxvkCmdBuffer::InitBuffer + : DxvkCmdBuffer::ExecBuffer; + + VkBufferCopy bufferRegion; + bufferRegion.srcOffset = srcSlice.offset; + bufferRegion.dstOffset = dstSlice.offset; + bufferRegion.size = dstSlice.length; + + m_cmd->cmdCopyBuffer(cmdBuffer, + srcSlice.handle, dstSlice.handle, 1, &bufferRegion); + + auto& barriers = replaceBuffer + ? m_initBarriers + : m_execBarriers; + + barriers.accessBuffer(srcSlice, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_READ_BIT, + srcBuffer->info().stages, + srcBuffer->info().access); + + barriers.accessBuffer(dstSlice, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT, + dstBuffer->info().stages, + dstBuffer->info().access); + + m_cmd->trackResource(dstBuffer); + m_cmd->trackResource(srcBuffer); + } + + + void DxvkContext::copyBufferRegion( + const Rc& dstBuffer, + VkDeviceSize dstOffset, + VkDeviceSize srcOffset, + VkDeviceSize numBytes) { + VkDeviceSize loOvl = std::max(dstOffset, srcOffset); + VkDeviceSize hiOvl = std::min(dstOffset, srcOffset) + numBytes; + + if (hiOvl > loOvl) { + DxvkBufferCreateInfo bufInfo; + bufInfo.size = numBytes; + bufInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + bufInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT; + bufInfo.access = VK_ACCESS_TRANSFER_WRITE_BIT + | VK_ACCESS_TRANSFER_READ_BIT; + + auto tmpBuffer = m_device->createBuffer( + bufInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + + VkDeviceSize tmpOffset = 0; + + this->copyBuffer(tmpBuffer, tmpOffset, dstBuffer, srcOffset, numBytes); + this->copyBuffer(dstBuffer, dstOffset, tmpBuffer, tmpOffset, numBytes); + } else { + this->copyBuffer(dstBuffer, dstOffset, dstBuffer, srcOffset, numBytes); + } + } + + + void DxvkContext::copyBufferToImage( + const Rc& dstImage, + VkImageSubresourceLayers dstSubresource, + VkOffset3D dstOffset, + VkExtent3D dstExtent, + const Rc& srcBuffer, + VkDeviceSize srcOffset, + VkDeviceSize rowAlignment, + VkDeviceSize sliceAlignment) { + this->spillRenderPass(true); + this->prepareImage(m_execBarriers, dstImage, vk::makeSubresourceRange(dstSubresource)); + + auto srcSlice = srcBuffer->getSliceHandle(srcOffset, 0); + + // We may copy to only one aspect at a time, but pipeline + // barriers need to have all available aspect bits set + auto dstFormatInfo = dstImage->formatInfo(); + + auto dstSubresourceRange = vk::makeSubresourceRange(dstSubresource); + dstSubresourceRange.aspectMask = dstFormatInfo->aspectMask; + + if (m_execBarriers.isImageDirty(dstImage, dstSubresourceRange, DxvkAccess::Write) + || m_execBarriers.isBufferDirty(srcSlice, DxvkAccess::Read)) + m_execBarriers.recordCommands(m_cmd); + + // Initialize the image if the entire subresource is covered + VkImageLayout dstImageLayoutInitial = dstImage->info().layout; + VkImageLayout dstImageLayoutTransfer = dstImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + + if (dstImage->isFullSubresource(dstSubresource, dstExtent)) + dstImageLayoutInitial = VK_IMAGE_LAYOUT_UNDEFINED; + + if (dstImageLayoutTransfer != dstImageLayoutInitial) { + m_execAcquires.accessImage( + dstImage, dstSubresourceRange, + dstImageLayoutInitial, + VK_PIPELINE_STAGE_TRANSFER_BIT, 0, + dstImageLayoutTransfer, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT); + } + + m_execAcquires.recordCommands(m_cmd); + + this->copyImageBufferData(DxvkCmdBuffer::ExecBuffer, dstImage, dstSubresource, + dstOffset, dstExtent, dstImageLayoutTransfer, srcSlice, rowAlignment, sliceAlignment); + + m_execBarriers.accessImage( + dstImage, dstSubresourceRange, + dstImageLayoutTransfer, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT, + dstImage->info().layout, + dstImage->info().stages, + dstImage->info().access); + + m_execBarriers.accessBuffer(srcSlice, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_READ_BIT, + srcBuffer->info().stages, + srcBuffer->info().access); + + m_cmd->trackResource(dstImage); + m_cmd->trackResource(srcBuffer); + } + + + void DxvkContext::copyImage( + const Rc& dstImage, + VkImageSubresourceLayers dstSubresource, + VkOffset3D dstOffset, + const Rc& srcImage, + VkImageSubresourceLayers srcSubresource, + VkOffset3D srcOffset, + VkExtent3D extent) { + this->spillRenderPass(true); + + if (this->copyImageClear(dstImage, dstSubresource, dstOffset, extent, srcImage, srcSubresource)) + return; + + this->prepareImage(m_execBarriers, dstImage, vk::makeSubresourceRange(dstSubresource)); + this->prepareImage(m_execBarriers, srcImage, vk::makeSubresourceRange(srcSubresource)); + + bool useFb = dstSubresource.aspectMask != srcSubresource.aspectMask; + + if (m_device->perfHints().preferFbDepthStencilCopy) { + useFb |= (dstSubresource.aspectMask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) + && (dstImage->info().usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) + && (srcImage->info().usage & VK_IMAGE_USAGE_SAMPLED_BIT); + } + + if (!useFb) { + this->copyImageHw( + dstImage, dstSubresource, dstOffset, + srcImage, srcSubresource, srcOffset, + extent); + } else { + this->copyImageFb( + dstImage, dstSubresource, dstOffset, + srcImage, srcSubresource, srcOffset, + extent); + } + } + + + void DxvkContext::copyImageRegion( + const Rc& dstImage, + VkImageSubresourceLayers dstSubresource, + VkOffset3D dstOffset, + VkOffset3D srcOffset, + VkExtent3D extent) { + VkOffset3D loOvl = { + std::max(dstOffset.x, srcOffset.x), + std::max(dstOffset.y, srcOffset.y), + std::max(dstOffset.z, srcOffset.z) }; + + VkOffset3D hiOvl = { + std::min(dstOffset.x, srcOffset.x) + int32_t(extent.width), + std::min(dstOffset.y, srcOffset.y) + int32_t(extent.height), + std::min(dstOffset.z, srcOffset.z) + int32_t(extent.depth) }; + + bool overlap = hiOvl.x > loOvl.x + && hiOvl.y > loOvl.y + && hiOvl.z > loOvl.z; + + if (overlap) { + DxvkImageCreateInfo imgInfo; + imgInfo.type = dstImage->info().type; + imgInfo.format = dstImage->info().format; + imgInfo.flags = 0; + imgInfo.sampleCount = dstImage->info().sampleCount; + imgInfo.extent = extent; + imgInfo.numLayers = dstSubresource.layerCount; + imgInfo.mipLevels = 1; + imgInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; + imgInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT; + imgInfo.access = VK_ACCESS_TRANSFER_WRITE_BIT + | VK_ACCESS_TRANSFER_READ_BIT; + imgInfo.tiling = dstImage->info().tiling; + imgInfo.layout = VK_IMAGE_LAYOUT_GENERAL; + + auto tmpImage = m_device->createImage( + imgInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + + VkImageSubresourceLayers tmpSubresource; + tmpSubresource.aspectMask = dstSubresource.aspectMask; + tmpSubresource.mipLevel = 0; + tmpSubresource.baseArrayLayer = 0; + tmpSubresource.layerCount = dstSubresource.layerCount; + + VkOffset3D tmpOffset = { 0, 0, 0 }; + + this->copyImage( + tmpImage, tmpSubresource, tmpOffset, + dstImage, dstSubresource, srcOffset, + extent); + + this->copyImage( + dstImage, dstSubresource, dstOffset, + tmpImage, tmpSubresource, tmpOffset, + extent); + } else { + this->copyImage( + dstImage, dstSubresource, dstOffset, + dstImage, dstSubresource, srcOffset, + extent); + } + } + + + void DxvkContext::copyImageToBuffer( + const Rc& dstBuffer, + VkDeviceSize dstOffset, + VkDeviceSize rowAlignment, + VkDeviceSize sliceAlignment, + const Rc& srcImage, + VkImageSubresourceLayers srcSubresource, + VkOffset3D srcOffset, + VkExtent3D srcExtent) { + this->spillRenderPass(true); + this->prepareImage(m_execBarriers, srcImage, vk::makeSubresourceRange(srcSubresource)); + + auto dstSlice = dstBuffer->getSliceHandle(dstOffset, 0); + + // We may copy to only one aspect of a depth-stencil image, + // but pipeline barriers need to have all aspect bits set + auto srcFormatInfo = srcImage->formatInfo(); + + auto srcSubresourceRange = vk::makeSubresourceRange(srcSubresource); + srcSubresourceRange.aspectMask = srcFormatInfo->aspectMask; + + if (m_execBarriers.isImageDirty(srcImage, srcSubresourceRange, DxvkAccess::Write) + || m_execBarriers.isBufferDirty(dstSlice, DxvkAccess::Write)) + m_execBarriers.recordCommands(m_cmd); + + // Select a suitable image layout for the transfer op + VkImageLayout srcImageLayoutTransfer = srcImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + + m_execAcquires.accessImage( + srcImage, srcSubresourceRange, + srcImage->info().layout, + VK_PIPELINE_STAGE_TRANSFER_BIT, 0, + srcImageLayoutTransfer, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_READ_BIT); + + m_execAcquires.recordCommands(m_cmd); + + this->copyImageBufferData(DxvkCmdBuffer::ExecBuffer, srcImage, srcSubresource, + srcOffset, srcExtent, srcImageLayoutTransfer, dstSlice, rowAlignment, sliceAlignment); + + m_execBarriers.accessImage( + srcImage, srcSubresourceRange, + srcImageLayoutTransfer, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_READ_BIT, + srcImage->info().layout, + srcImage->info().stages, + srcImage->info().access); + + m_execBarriers.accessBuffer(dstSlice, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT, + dstBuffer->info().stages, + dstBuffer->info().access); + + m_cmd->trackResource(dstBuffer); + m_cmd->trackResource(srcImage); + } + + + void DxvkContext::copyDepthStencilImageToPackedBuffer( + const Rc& dstBuffer, + VkDeviceSize dstBufferOffset, + VkOffset2D dstOffset, + VkExtent2D dstExtent, + const Rc& srcImage, + VkImageSubresourceLayers srcSubresource, + VkOffset2D srcOffset, + VkExtent2D srcExtent, + VkFormat format) { + this->spillRenderPass(true); + this->prepareImage(m_execBarriers, srcImage, vk::makeSubresourceRange(srcSubresource)); + + this->unbindComputePipeline(); + + // Retrieve compute pipeline for the given format + auto pipeInfo = m_common->metaPack().getPackPipeline(format); + + if (!pipeInfo.pipeHandle) + return; + + // Create one depth view and one stencil view + DxvkImageViewCreateInfo dViewInfo; + dViewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; + dViewInfo.format = srcImage->info().format; + dViewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT; + dViewInfo.aspect = VK_IMAGE_ASPECT_DEPTH_BIT; + dViewInfo.minLevel = srcSubresource.mipLevel; + dViewInfo.numLevels = 1; + dViewInfo.minLayer = srcSubresource.baseArrayLayer; + dViewInfo.numLayers = srcSubresource.layerCount; + + DxvkImageViewCreateInfo sViewInfo = dViewInfo; + sViewInfo.aspect = VK_IMAGE_ASPECT_STENCIL_BIT; + + Rc dView = m_device->createImageView(srcImage, dViewInfo); + Rc sView = m_device->createImageView(srcImage, sViewInfo); + + // Create a descriptor set for the pack operation + VkImageLayout layout = srcImage->pickLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL); + + DxvkMetaPackDescriptors descriptors; + descriptors.dstBuffer = dstBuffer->getDescriptor(dstBufferOffset, VK_WHOLE_SIZE).buffer; + descriptors.srcDepth = dView->getDescriptor(VK_IMAGE_VIEW_TYPE_2D_ARRAY, layout).image; + descriptors.srcStencil = sView->getDescriptor(VK_IMAGE_VIEW_TYPE_2D_ARRAY, layout).image; + + VkDescriptorSet dset = allocateDescriptorSet(pipeInfo.dsetLayout); + m_cmd->updateDescriptorSetWithTemplate(dset, pipeInfo.dsetTemplate, &descriptors); + + // Since this is a meta operation, the image may be + // in a different layout and we have to transition it + auto subresourceRange = vk::makeSubresourceRange(srcSubresource); + + if (m_execBarriers.isImageDirty(srcImage, subresourceRange, DxvkAccess::Write)) + m_execBarriers.recordCommands(m_cmd); + + if (srcImage->info().layout != layout) { + m_execAcquires.accessImage( + srcImage, subresourceRange, + srcImage->info().layout, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, + layout, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_ACCESS_SHADER_READ_BIT); + + m_execAcquires.recordCommands(m_cmd); + } + + // Execute the actual pack operation + DxvkMetaPackArgs args; + args.srcOffset = srcOffset; + args.srcExtent = srcExtent; + args.dstOffset = dstOffset; + args.dstExtent = dstExtent; + + m_cmd->cmdBindPipeline( + VK_PIPELINE_BIND_POINT_COMPUTE, + pipeInfo.pipeHandle); + + m_cmd->cmdBindDescriptorSet( + VK_PIPELINE_BIND_POINT_COMPUTE, + pipeInfo.pipeLayout, dset, + 0, nullptr); + + m_cmd->cmdPushConstants( + pipeInfo.pipeLayout, + VK_SHADER_STAGE_COMPUTE_BIT, + 0, sizeof(args), &args); + + m_cmd->cmdDispatch( + (srcExtent.width + 7) / 8, + (srcExtent.height + 7) / 8, + srcSubresource.layerCount); + + m_execBarriers.accessImage( + srcImage, subresourceRange, layout, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_ACCESS_SHADER_READ_BIT, + srcImage->info().layout, + srcImage->info().stages, + srcImage->info().access); + + m_execBarriers.accessBuffer( + dstBuffer->getSliceHandle(), + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_ACCESS_SHADER_WRITE_BIT, + dstBuffer->info().stages, + dstBuffer->info().access); + + m_cmd->trackResource(dView); + m_cmd->trackResource(sView); + + m_cmd->trackResource(dstBuffer); + m_cmd->trackResource(srcImage); + } + + + void DxvkContext::copyPackedBufferImage( + const Rc& dstBuffer, + VkDeviceSize dstBufferOffset, + VkOffset3D dstOffset, + VkExtent3D dstSize, + const Rc& srcBuffer, + VkDeviceSize srcBufferOffset, + VkOffset3D srcOffset, + VkExtent3D srcSize, + VkExtent3D extent, + VkDeviceSize elementSize) { + this->spillRenderPass(true); + this->unbindComputePipeline(); + + auto dstBufferSlice = dstBuffer->getSliceHandle(dstBufferOffset, elementSize * util::flattenImageExtent(dstSize)); + auto srcBufferSlice = srcBuffer->getSliceHandle(srcBufferOffset, elementSize * util::flattenImageExtent(srcSize)); + + if (m_execBarriers.isBufferDirty(dstBufferSlice, DxvkAccess::Write) + || m_execBarriers.isBufferDirty(srcBufferSlice, DxvkAccess::Read)) + m_execBarriers.recordCommands(m_cmd); + + // We'll use texel buffer views with an appropriately + // sized integer format to perform the copy + VkFormat format = VK_FORMAT_UNDEFINED; + + switch (elementSize) { + case 1: format = VK_FORMAT_R8_UINT; break; + case 2: format = VK_FORMAT_R16_UINT; break; + case 4: format = VK_FORMAT_R32_UINT; break; + case 8: format = VK_FORMAT_R32G32_UINT; break; + case 12: format = VK_FORMAT_R32G32B32_UINT; break; + case 16: format = VK_FORMAT_R32G32B32A32_UINT; break; + } + + if (!format) { + Logger::err(str::format("DxvkContext: copyPackedBufferImage: Unsupported element size ", elementSize)); + return; + } + + DxvkBufferViewCreateInfo viewInfo; + viewInfo.format = format; + viewInfo.rangeOffset = dstBufferOffset; + viewInfo.rangeLength = dstBufferSlice.length; + Rc dstView = m_device->createBufferView(dstBuffer, viewInfo); + + viewInfo.rangeOffset = srcBufferOffset; + viewInfo.rangeLength = srcBufferSlice.length; + Rc srcView; + + if (srcBuffer == dstBuffer + && srcBufferSlice.offset < dstBufferSlice.offset + dstBufferSlice.length + && srcBufferSlice.offset + srcBufferSlice.length > dstBufferSlice.offset) { + // Create temporary copy in case of overlapping regions + DxvkBufferCreateInfo bufferInfo; + bufferInfo.size = srcBufferSlice.length; + bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT; + bufferInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT + | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; + bufferInfo.access = VK_ACCESS_TRANSFER_WRITE_BIT + | VK_ACCESS_SHADER_READ_BIT; + Rc tmpBuffer = m_device->createBuffer(bufferInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + + auto tmpBufferSlice = tmpBuffer->getSliceHandle(); + + VkBufferCopy copyRegion; + copyRegion.srcOffset = srcBufferSlice.offset; + copyRegion.dstOffset = tmpBufferSlice.offset; + copyRegion.size = tmpBufferSlice.length; + + m_cmd->cmdCopyBuffer(DxvkCmdBuffer::ExecBuffer, + srcBufferSlice.handle, tmpBufferSlice.handle, + 1, ©Region); + + emitMemoryBarrier(0, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_ACCESS_SHADER_READ_BIT); + + viewInfo.rangeOffset = 0; + srcView = m_device->createBufferView(tmpBuffer, viewInfo); + + m_cmd->trackResource(tmpBuffer); + } else { + srcView = m_device->createBufferView(srcBuffer, viewInfo); + } + + auto pipeInfo = m_common->metaCopy().getCopyBufferImagePipeline(); + VkDescriptorSet descriptorSet = allocateDescriptorSet(pipeInfo.dsetLayout); + + std::array descriptorWrites; + + std::array, 2> descriptorInfos = {{ + { VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, dstView->handle() }, + { VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, srcView->handle() }, + }}; + + for (uint32_t i = 0; i < descriptorWrites.size(); i++) { + auto write = &descriptorWrites[i]; + auto info = &descriptorInfos[i]; + + write->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write->pNext = nullptr; + write->dstSet = descriptorSet; + write->dstBinding = i; + write->dstArrayElement = 0; + write->descriptorCount = 1; + write->descriptorType = info->first; + write->pImageInfo = nullptr; + write->pBufferInfo = nullptr; + write->pTexelBufferView = &info->second; + } + + m_cmd->updateDescriptorSets(descriptorWrites.size(), descriptorWrites.data()); + + DxvkCopyBufferImageArgs args = { }; + args.dstOffset = dstOffset; + args.srcOffset = srcOffset; + args.extent = extent; + args.dstSize = { dstSize.width, dstSize.height }; + args.srcSize = { srcSize.width, srcSize.height }; + + m_cmd->cmdBindPipeline( + VK_PIPELINE_BIND_POINT_COMPUTE, + pipeInfo.pipeHandle); + + m_cmd->cmdBindDescriptorSet( + VK_PIPELINE_BIND_POINT_COMPUTE, + pipeInfo.pipeLayout, descriptorSet, + 0, nullptr); + + m_cmd->cmdPushConstants( + pipeInfo.pipeLayout, + VK_SHADER_STAGE_COMPUTE_BIT, + 0, sizeof(args), &args); + + m_cmd->cmdDispatch( + (extent.width + 7) / 8, + (extent.height + 7) / 8, + extent.depth); + + m_execBarriers.accessBuffer( + dstView->getSliceHandle(), + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_ACCESS_SHADER_WRITE_BIT, + dstBuffer->info().stages, + dstBuffer->info().access); + + m_execBarriers.accessBuffer( + srcView->getSliceHandle(), + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_ACCESS_SHADER_READ_BIT, + srcBuffer->info().stages, + srcBuffer->info().access); + + // Track all involved resources + m_cmd->trackResource(dstBuffer); + m_cmd->trackResource(srcBuffer); + + m_cmd->trackResource(dstView); + m_cmd->trackResource(srcView); + } + + + void DxvkContext::copyPackedBufferToDepthStencilImage( + const Rc& dstImage, + VkImageSubresourceLayers dstSubresource, + VkOffset2D dstOffset, + VkExtent2D dstExtent, + const Rc& srcBuffer, + VkDeviceSize srcBufferOffset, + VkOffset2D srcOffset, + VkExtent2D srcExtent, + VkFormat format) { + this->spillRenderPass(true); + this->prepareImage(m_execBarriers, dstImage, vk::makeSubresourceRange(dstSubresource)); + + this->unbindComputePipeline(); + + if (m_execBarriers.isBufferDirty(srcBuffer->getSliceHandle(), DxvkAccess::Read) + || m_execBarriers.isImageDirty(dstImage, vk::makeSubresourceRange(dstSubresource), DxvkAccess::Write)) + m_execBarriers.recordCommands(m_cmd); + + // Retrieve compute pipeline for the given format + auto pipeInfo = m_common->metaPack().getUnpackPipeline(dstImage->info().format, format); + + if (!pipeInfo.pipeHandle) { + Logger::err(str::format( + "DxvkContext: copyPackedBufferToDepthStencilImage: Unhandled formats" + "\n dstFormat = ", dstImage->info().format, + "\n srcFormat = ", format)); + return; + } + + // Pick depth and stencil data formats + VkFormat dataFormatD = VK_FORMAT_UNDEFINED; + VkFormat dataFormatS = VK_FORMAT_UNDEFINED; + + const std::array, 2> formats = {{ + { VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_R32_UINT, VK_FORMAT_R8_UINT }, + { VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_R32_SFLOAT, VK_FORMAT_R8_UINT }, + }}; + + for (const auto& e : formats) { + if (std::get<0>(e) == dstImage->info().format) { + dataFormatD = std::get<1>(e); + dataFormatS = std::get<2>(e); + } + } + + // Create temporary buffer for depth/stencil data + VkDeviceSize pixelCount = dstExtent.width * dstExtent.height * dstSubresource.layerCount; + VkDeviceSize dataSizeD = align(pixelCount * imageFormatInfo(dataFormatD)->elementSize, 256); + VkDeviceSize dataSizeS = align(pixelCount * imageFormatInfo(dataFormatS)->elementSize, 256); + + DxvkBufferCreateInfo tmpBufferInfo; + tmpBufferInfo.size = dataSizeD + dataSizeS; + tmpBufferInfo.usage = VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT + | VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + tmpBufferInfo.stages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT + | VK_PIPELINE_STAGE_TRANSFER_BIT; + tmpBufferInfo.access = VK_ACCESS_SHADER_WRITE_BIT + | VK_ACCESS_TRANSFER_READ_BIT; + + auto tmpBuffer = m_device->createBuffer(tmpBufferInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + + // Create formatted buffer views + DxvkBufferViewCreateInfo tmpViewInfoD; + tmpViewInfoD.format = dataFormatD; + tmpViewInfoD.rangeOffset = 0; + tmpViewInfoD.rangeLength = dataSizeD; + + DxvkBufferViewCreateInfo tmpViewInfoS; + tmpViewInfoS.format = dataFormatS; + tmpViewInfoS.rangeOffset = dataSizeD; + tmpViewInfoS.rangeLength = dataSizeS; + + auto tmpBufferViewD = m_device->createBufferView(tmpBuffer, tmpViewInfoD); + auto tmpBufferViewS = m_device->createBufferView(tmpBuffer, tmpViewInfoS); + + // Create descriptor set for the unpack operation + DxvkMetaUnpackDescriptors descriptors; + descriptors.dstDepth = tmpBufferViewD->handle(); + descriptors.dstStencil = tmpBufferViewS->handle(); + descriptors.srcBuffer = srcBuffer->getDescriptor(srcBufferOffset, VK_WHOLE_SIZE).buffer; + + VkDescriptorSet dset = allocateDescriptorSet(pipeInfo.dsetLayout); + m_cmd->updateDescriptorSetWithTemplate(dset, pipeInfo.dsetTemplate, &descriptors); + + // Unpack the source buffer to temporary buffers + DxvkMetaPackArgs args; + args.srcOffset = srcOffset; + args.srcExtent = srcExtent; + args.dstOffset = VkOffset2D { 0, 0 }; + args.dstExtent = dstExtent; + + m_cmd->cmdBindPipeline( + VK_PIPELINE_BIND_POINT_COMPUTE, + pipeInfo.pipeHandle); + + m_cmd->cmdBindDescriptorSet( + VK_PIPELINE_BIND_POINT_COMPUTE, + pipeInfo.pipeLayout, dset, + 0, nullptr); + + m_cmd->cmdPushConstants( + pipeInfo.pipeLayout, + VK_SHADER_STAGE_COMPUTE_BIT, + 0, sizeof(args), &args); + + m_cmd->cmdDispatch( + (dstExtent.width + 63) / 64, + dstExtent.height, + dstSubresource.layerCount); + + m_execBarriers.accessBuffer( + tmpBuffer->getSliceHandle(), + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_ACCESS_SHADER_WRITE_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_READ_BIT); + + m_execBarriers.accessBuffer( + srcBuffer->getSliceHandle(), + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_ACCESS_SHADER_READ_BIT, + srcBuffer->info().stages, + srcBuffer->info().access); + + // Prepare image for the data transfer operation + VkOffset3D dstOffset3D = { dstOffset.x, dstOffset.y, 0 }; + VkExtent3D dstExtent3D = { dstExtent.width, dstExtent.height, 1 }; + + VkImageLayout initialImageLayout = dstImage->info().layout; + + if (dstImage->isFullSubresource(dstSubresource, dstExtent3D)) + initialImageLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + m_execBarriers.accessImage( + dstImage, vk::makeSubresourceRange(dstSubresource), + initialImageLayout, + dstImage->info().stages, + dstImage->info().access, + dstImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL), + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT); + + m_execBarriers.recordCommands(m_cmd); + + // Copy temporary buffer data to depth-stencil image + VkImageSubresourceLayers dstSubresourceD = dstSubresource; + dstSubresourceD.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + + VkImageSubresourceLayers dstSubresourceS = dstSubresource; + dstSubresourceS.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; + + std::array copyRegions = {{ + { tmpBufferViewD->info().rangeOffset, 0, 0, dstSubresourceD, dstOffset3D, dstExtent3D }, + { tmpBufferViewS->info().rangeOffset, 0, 0, dstSubresourceS, dstOffset3D, dstExtent3D }, + }}; + + m_cmd->cmdCopyBufferToImage(DxvkCmdBuffer::ExecBuffer, + tmpBuffer->getSliceHandle().handle, + dstImage->handle(), + dstImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL), + copyRegions.size(), + copyRegions.data()); + + m_execBarriers.accessImage( + dstImage, vk::makeSubresourceRange(dstSubresource), + dstImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL), + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT, + dstImage->info().layout, + dstImage->info().stages, + dstImage->info().access); + + // Track all involved resources + m_cmd->trackResource(dstImage); + m_cmd->trackResource(srcBuffer); + + m_cmd->trackResource(tmpBufferViewD); + m_cmd->trackResource(tmpBufferViewS); + } + + + void DxvkContext::discardBuffer( + const Rc& buffer) { + if (buffer->memFlags() & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) + return; + + if (m_execBarriers.isBufferDirty(buffer->getSliceHandle(), DxvkAccess::Write)) + this->invalidateBuffer(buffer, buffer->allocSlice()); + } + + + void DxvkContext::discardImageView( + const Rc& imageView, + VkImageAspectFlags discardAspects) { + VkImageUsageFlags viewUsage = imageView->info().usage; + + // Ignore non-render target views since there's likely no good use case for + // discarding those. Also, force reinitialization even if the image is bound + // as a render target, which may have niche use cases for depth buffers. + if (viewUsage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) { + this->spillRenderPass(true); + this->deferDiscard(imageView, discardAspects); + } + } + + + void DxvkContext::dispatch( + uint32_t x, + uint32_t y, + uint32_t z) { + if (this->commitComputeState()) { + this->commitComputeInitBarriers(); + + m_queryManager.beginQueries(m_cmd, + VK_QUERY_TYPE_PIPELINE_STATISTICS); + + m_cmd->cmdDispatch(x, y, z); + + m_queryManager.endQueries(m_cmd, + VK_QUERY_TYPE_PIPELINE_STATISTICS); + + this->commitComputePostBarriers(); + } + + m_cmd->addStatCtr(DxvkStatCounter::CmdDispatchCalls, 1); + } + + + void DxvkContext::dispatchIndirect( + VkDeviceSize offset) { + auto bufferSlice = m_state.id.argBuffer.getSliceHandle( + offset, sizeof(VkDispatchIndirectCommand)); + + if (m_execBarriers.isBufferDirty(bufferSlice, DxvkAccess::Read)) + m_execBarriers.recordCommands(m_cmd); + + if (this->commitComputeState()) { + this->commitComputeInitBarriers(); + + m_queryManager.beginQueries(m_cmd, + VK_QUERY_TYPE_PIPELINE_STATISTICS); + + m_cmd->cmdDispatchIndirect( + bufferSlice.handle, + bufferSlice.offset); + + m_queryManager.endQueries(m_cmd, + VK_QUERY_TYPE_PIPELINE_STATISTICS); + + this->commitComputePostBarriers(); + + m_execBarriers.accessBuffer(bufferSlice, + VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, + VK_ACCESS_INDIRECT_COMMAND_READ_BIT, + m_state.id.argBuffer.bufferInfo().stages, + m_state.id.argBuffer.bufferInfo().access); + + this->trackDrawBuffer(); + } + + m_cmd->addStatCtr(DxvkStatCounter::CmdDispatchCalls, 1); + } + + + void DxvkContext::draw( + uint32_t vertexCount, + uint32_t instanceCount, + uint32_t firstVertex, + uint32_t firstInstance) { + if (this->commitGraphicsState()) { + m_cmd->cmdDraw( + vertexCount, instanceCount, + firstVertex, firstInstance); + } + + m_cmd->addStatCtr(DxvkStatCounter::CmdDrawCalls, 1); + } + + + void DxvkContext::drawIndirect( + VkDeviceSize offset, + uint32_t count, + uint32_t stride) { + if (this->commitGraphicsState()) { + auto descriptor = m_state.id.argBuffer.getDescriptor(); + + m_cmd->cmdDrawIndirect( + descriptor.buffer.buffer, + descriptor.buffer.offset + offset, + count, stride); + } + + m_cmd->addStatCtr(DxvkStatCounter::CmdDrawCalls, 1); + } + + + void DxvkContext::drawIndirectCount( + VkDeviceSize offset, + VkDeviceSize countOffset, + uint32_t maxCount, + uint32_t stride) { + if (this->commitGraphicsState()) { + auto argDescriptor = m_state.id.argBuffer.getDescriptor(); + auto cntDescriptor = m_state.id.cntBuffer.getDescriptor(); + + m_cmd->cmdDrawIndirectCount( + argDescriptor.buffer.buffer, + argDescriptor.buffer.offset + offset, + cntDescriptor.buffer.buffer, + cntDescriptor.buffer.offset + countOffset, + maxCount, stride); + } + + m_cmd->addStatCtr(DxvkStatCounter::CmdDrawCalls, 1); + } + + + void DxvkContext::drawIndexed( + uint32_t indexCount, + uint32_t instanceCount, + uint32_t firstIndex, + uint32_t vertexOffset, + uint32_t firstInstance) { + if (this->commitGraphicsState()) { + m_cmd->cmdDrawIndexed( + indexCount, instanceCount, + firstIndex, vertexOffset, + firstInstance); + } + + m_cmd->addStatCtr(DxvkStatCounter::CmdDrawCalls, 1); + } + + + void DxvkContext::drawIndexedIndirect( + VkDeviceSize offset, + uint32_t count, + uint32_t stride) { + if (this->commitGraphicsState()) { + auto descriptor = m_state.id.argBuffer.getDescriptor(); + + m_cmd->cmdDrawIndexedIndirect( + descriptor.buffer.buffer, + descriptor.buffer.offset + offset, + count, stride); + } + + m_cmd->addStatCtr(DxvkStatCounter::CmdDrawCalls, 1); + } + + + void DxvkContext::drawIndexedIndirectCount( + VkDeviceSize offset, + VkDeviceSize countOffset, + uint32_t maxCount, + uint32_t stride) { + if (this->commitGraphicsState()) { + auto argDescriptor = m_state.id.argBuffer.getDescriptor(); + auto cntDescriptor = m_state.id.cntBuffer.getDescriptor(); + + m_cmd->cmdDrawIndexedIndirectCount( + argDescriptor.buffer.buffer, + argDescriptor.buffer.offset + offset, + cntDescriptor.buffer.buffer, + cntDescriptor.buffer.offset + countOffset, + maxCount, stride); + } + + m_cmd->addStatCtr(DxvkStatCounter::CmdDrawCalls, 1); + } + + + void DxvkContext::drawIndirectXfb( + const DxvkBufferSlice& counterBuffer, + uint32_t counterDivisor, + uint32_t counterBias) { + if (this->commitGraphicsState()) { + auto physSlice = counterBuffer.getSliceHandle(); + + m_cmd->cmdDrawIndirectVertexCount(1, 0, + physSlice.handle, + physSlice.offset, + counterBias, + counterDivisor); + } + + m_cmd->addStatCtr(DxvkStatCounter::CmdDrawCalls, 1); + } + + + void DxvkContext::emitRenderTargetReadbackBarrier() { + if (m_flags.test(DxvkContextFlag::GpRenderPassBound)) { + emitMemoryBarrier(VK_DEPENDENCY_BY_REGION_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_ACCESS_SHADER_READ_BIT); + } + } + + + void DxvkContext::initBuffer( + const Rc& buffer) { + auto slice = buffer->getSliceHandle(); + + m_cmd->cmdFillBuffer(DxvkCmdBuffer::InitBuffer, + slice.handle, slice.offset, + dxvk::align(slice.length, 4), 0); + + m_initBarriers.accessBuffer(slice, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT, + buffer->info().stages, + buffer->info().access); + + m_cmd->trackResource(buffer); + } + + + void DxvkContext::initImage( + const Rc& image, + const VkImageSubresourceRange& subresources, + VkImageLayout initialLayout) { + if (initialLayout == VK_IMAGE_LAYOUT_PREINITIALIZED) { + m_initBarriers.accessImage(image, subresources, + initialLayout, 0, 0, + image->info().layout, + image->info().stages, + image->info().access); + + m_cmd->trackResource(image); + } else { + VkImageLayout clearLayout = image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + + m_execAcquires.accessImage(image, subresources, + initialLayout, 0, 0, clearLayout, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT); + m_execAcquires.recordCommands(m_cmd); + + auto formatInfo = image->formatInfo(); + + if (formatInfo->flags.any(DxvkFormatFlag::BlockCompressed, DxvkFormatFlag::MultiPlane)) { + for (auto aspects = formatInfo->aspectMask; aspects; ) { + auto aspect = vk::getNextAspect(aspects); + auto extent = image->mipLevelExtent(subresources.baseMipLevel); + auto elementSize = formatInfo->elementSize; + + if (formatInfo->flags.test(DxvkFormatFlag::MultiPlane)) { + auto plane = &formatInfo->planes[vk::getPlaneIndex(aspect)]; + extent.width /= plane->blockSize.width; + extent.height /= plane->blockSize.height; + elementSize = plane->elementSize; + } + + // Allocate enough staging buffer memory to fit one + // single subresource, then dispatch multiple copies + VkExtent3D blockCount = util::computeBlockCount(extent, formatInfo->blockSize); + VkDeviceSize dataSize = util::flattenImageExtent(blockCount) * elementSize; + + auto zeroBuffer = createZeroBuffer(dataSize); + auto zeroHandle = zeroBuffer->getSliceHandle(); + + for (uint32_t level = 0; level < subresources.levelCount; level++) { + VkOffset3D offset = VkOffset3D { 0, 0, 0 }; + VkExtent3D extent = image->mipLevelExtent(subresources.baseMipLevel + level); + + if (formatInfo->flags.test(DxvkFormatFlag::MultiPlane)) { + auto plane = &formatInfo->planes[vk::getPlaneIndex(aspect)]; + extent.width /= plane->blockSize.width; + extent.height /= plane->blockSize.height; + } + + for (uint32_t layer = 0; layer < subresources.layerCount; layer++) { + VkBufferImageCopy region; + region.bufferOffset = zeroHandle.offset; + region.bufferRowLength = 0; + region.bufferImageHeight = 0; + region.imageSubresource = vk::makeSubresourceLayers( + vk::pickSubresource(subresources, level, layer)); + region.imageSubresource.aspectMask = aspect; + region.imageOffset = offset; + region.imageExtent = extent; + + m_cmd->cmdCopyBufferToImage(DxvkCmdBuffer::ExecBuffer, + zeroHandle.handle, image->handle(), clearLayout, 1, ®ion); + } + } + + m_cmd->trackResource(zeroBuffer); + } + } else { + if (subresources.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { + VkClearDepthStencilValue value = { }; + + m_cmd->cmdClearDepthStencilImage(image->handle(), + clearLayout, &value, 1, &subresources); + } else { + VkClearColorValue value = { }; + + m_cmd->cmdClearColorImage(image->handle(), + clearLayout, &value, 1, &subresources); + } + } + + m_execBarriers.accessImage(image, subresources, + clearLayout, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT, + image->info().layout, + image->info().stages, + image->info().access); + + m_cmd->trackResource(image); + } + } + + + void DxvkContext::generateMipmaps( + const Rc& imageView, + VkFilter filter) { + if (imageView->info().numLevels <= 1) + return; + + this->spillRenderPass(false); + + m_execBarriers.recordCommands(m_cmd); + + // Create the a set of framebuffers and image views + const Rc mipGenerator + = new DxvkMetaMipGenRenderPass(m_device->vkd(), imageView); + + // Common descriptor set properties that we use to + // bind the source image view to the fragment shader + VkDescriptorImageInfo descriptorImage; + descriptorImage.sampler = m_common->metaBlit().getSampler(filter); + descriptorImage.imageView = VK_NULL_HANDLE; + descriptorImage.imageLayout = imageView->imageInfo().layout; + + VkWriteDescriptorSet descriptorWrite; + descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrite.pNext = nullptr; + descriptorWrite.dstSet = VK_NULL_HANDLE; + descriptorWrite.dstBinding = 0; + descriptorWrite.dstArrayElement = 0; + descriptorWrite.descriptorCount = 1; + descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + descriptorWrite.pImageInfo = &descriptorImage; + descriptorWrite.pBufferInfo = nullptr; + descriptorWrite.pTexelBufferView = nullptr; + + // Common render pass info + VkRenderPassBeginInfo passInfo; + passInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + passInfo.pNext = nullptr; + passInfo.renderPass = mipGenerator->renderPass(); + passInfo.framebuffer = VK_NULL_HANDLE; + passInfo.renderArea = VkRect2D { }; + passInfo.clearValueCount = 0; + passInfo.pClearValues = nullptr; + + // Retrieve a compatible pipeline to use for rendering + DxvkMetaBlitPipeline pipeInfo = m_common->metaBlit().getPipeline( + mipGenerator->viewType(), imageView->info().format, VK_SAMPLE_COUNT_1_BIT); + + for (uint32_t i = 0; i < mipGenerator->passCount(); i++) { + DxvkMetaBlitPass pass = mipGenerator->pass(i); + + // Width, height and layer count for the current pass + VkExtent3D passExtent = mipGenerator->passExtent(i); + + // Create descriptor set with the current source view + descriptorImage.imageView = pass.srcView; + descriptorWrite.dstSet = allocateDescriptorSet(pipeInfo.dsetLayout); + m_cmd->updateDescriptorSets(1, &descriptorWrite); + + // Set up viewport and scissor rect + VkViewport viewport; + viewport.x = 0.0f; + viewport.y = 0.0f; + viewport.width = float(passExtent.width); + viewport.height = float(passExtent.height); + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + VkRect2D scissor; + scissor.offset = { 0, 0 }; + scissor.extent = { passExtent.width, passExtent.height }; + + // Set up render pass info + passInfo.framebuffer = pass.framebuffer; + passInfo.renderArea = scissor; + + // Set up push constants + DxvkMetaBlitPushConstants pushConstants = { }; + pushConstants.srcCoord0 = { 0.0f, 0.0f, 0.0f }; + pushConstants.srcCoord1 = { 1.0f, 1.0f, 1.0f }; + pushConstants.layerCount = passExtent.depth; + + m_cmd->cmdBeginRenderPass(&passInfo, VK_SUBPASS_CONTENTS_INLINE); + m_cmd->cmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeInfo.pipeHandle); + m_cmd->cmdBindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, + pipeInfo.pipeLayout, descriptorWrite.dstSet, 0, nullptr); + + m_cmd->cmdSetViewport(0, 1, &viewport); + m_cmd->cmdSetScissor (0, 1, &scissor); + + m_cmd->cmdPushConstants( + pipeInfo.pipeLayout, + VK_SHADER_STAGE_FRAGMENT_BIT, + 0, sizeof(pushConstants), + &pushConstants); + + m_cmd->cmdDraw(3, passExtent.depth, 0, 0); + m_cmd->cmdEndRenderPass(); + } + + m_cmd->trackResource(mipGenerator); + m_cmd->trackResource(imageView->image()); + } + + + void DxvkContext::invalidateBuffer( + const Rc& buffer, + const DxvkBufferSliceHandle& slice) { + // Allocate new backing resource + DxvkBufferSliceHandle prevSlice = buffer->rename(slice); + m_cmd->freeBufferSlice(buffer, prevSlice); + + // We also need to update all bindings that the buffer + // may be bound to either directly or through views. + VkBufferUsageFlags usage = buffer->info().usage & + ~(VK_BUFFER_USAGE_TRANSFER_DST_BIT | + VK_BUFFER_USAGE_TRANSFER_SRC_BIT); + + if (usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) { + m_flags.set(prevSlice.handle == slice.handle + ? DxvkContextFlags(DxvkContextFlag::GpDirtyDescriptorBinding, + DxvkContextFlag::CpDirtyDescriptorBinding) + : DxvkContextFlags(DxvkContextFlag::GpDirtyResources, + DxvkContextFlag::CpDirtyResources)); + } + + // Fast early-out for uniform buffers, very common + if (likely(usage == VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)) + return; + + if (usage & (VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT + | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT + | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)) { + m_flags.set(DxvkContextFlag::GpDirtyResources, + DxvkContextFlag::CpDirtyResources); + } + + if (usage & VK_BUFFER_USAGE_INDEX_BUFFER_BIT) + m_flags.set(DxvkContextFlag::GpDirtyIndexBuffer); + + if (usage & VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) + m_flags.set(DxvkContextFlag::GpDirtyVertexBuffers); + + if (usage & VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT) + m_flags.set(DxvkContextFlag::DirtyDrawBuffer); + + if (usage & VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT) + m_flags.set(DxvkContextFlag::GpDirtyXfbBuffers); + } + + + void DxvkContext::pushConstants( + uint32_t offset, + uint32_t size, + const void* data) { + std::memcpy(&m_state.pc.data[offset], data, size); + + m_flags.set(DxvkContextFlag::DirtyPushConstants); + } + + + void DxvkContext::resolveImage( + const Rc& dstImage, + const Rc& srcImage, + const VkImageResolve& region, + VkFormat format) { + this->spillRenderPass(true); + this->prepareImage(m_execBarriers, dstImage, vk::makeSubresourceRange(region.dstSubresource)); + this->prepareImage(m_execBarriers, srcImage, vk::makeSubresourceRange(region.srcSubresource)); + + if (format == VK_FORMAT_UNDEFINED) + format = srcImage->info().format; + + bool useFb = srcImage->info().format != format + || dstImage->info().format != format; + + if (m_device->perfHints().preferFbResolve) { + useFb |= (dstImage->info().usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) + && (srcImage->info().usage & VK_IMAGE_USAGE_SAMPLED_BIT); + } + + if (!useFb) { + this->resolveImageHw( + dstImage, srcImage, region); + } else { + this->resolveImageFb( + dstImage, srcImage, region, format, + VK_RESOLVE_MODE_NONE_KHR, + VK_RESOLVE_MODE_NONE_KHR); + } + } + + + void DxvkContext::resolveDepthStencilImage( + const Rc& dstImage, + const Rc& srcImage, + const VkImageResolve& region, + VkResolveModeFlagBitsKHR depthMode, + VkResolveModeFlagBitsKHR stencilMode) { + this->spillRenderPass(true); + this->prepareImage(m_execBarriers, dstImage, vk::makeSubresourceRange(region.dstSubresource)); + this->prepareImage(m_execBarriers, srcImage, vk::makeSubresourceRange(region.srcSubresource)); + + // Technically legal, but no-op + if (!depthMode && !stencilMode) + return; + + // Subsequent functions expect stencil mode to be None + // if either of the images have no stencil aspect + if (!(region.dstSubresource.aspectMask + & region.srcSubresource.aspectMask + & VK_IMAGE_ASPECT_STENCIL_BIT)) + stencilMode = VK_RESOLVE_MODE_NONE_KHR; + + // We can only use the depth-stencil resolve path if the + // extension is supported, if we are resolving a full + // subresource, and both images have the same format. + bool useFb = !m_device->extensions().khrDepthStencilResolve + || !dstImage->isFullSubresource(region.dstSubresource, region.extent) + || !srcImage->isFullSubresource(region.srcSubresource, region.extent) + || dstImage->info().format != srcImage->info().format; + + if (!useFb) { + // Additionally, the given mode combination must be supported. + const auto& properties = m_device->properties().khrDepthStencilResolve; + + useFb |= (properties.supportedDepthResolveModes & depthMode) != depthMode + || (properties.supportedStencilResolveModes & stencilMode) != stencilMode; + + if (depthMode != stencilMode) { + useFb |= (!depthMode || !stencilMode) + ? !properties.independentResolveNone + : !properties.independentResolve; + } + } + + if (useFb) { + this->resolveImageFb( + dstImage, srcImage, region, VK_FORMAT_UNDEFINED, + depthMode, stencilMode); + } else { + this->resolveImageDs( + dstImage, srcImage, region, + depthMode, stencilMode); + } + } + + + void DxvkContext::transformImage( + const Rc& dstImage, + const VkImageSubresourceRange& dstSubresources, + VkImageLayout srcLayout, + VkImageLayout dstLayout) { + this->spillRenderPass(false); + + if (srcLayout != dstLayout) { + m_execBarriers.recordCommands(m_cmd); + + m_execBarriers.accessImage( + dstImage, dstSubresources, + srcLayout, + dstImage->info().stages, + dstImage->info().access, + dstLayout, + dstImage->info().stages, + dstImage->info().access); + + m_cmd->trackResource(dstImage); + } + } + + + void DxvkContext::performClear( + const Rc& imageView, + int32_t attachmentIndex, + VkImageAspectFlags discardAspects, + VkImageAspectFlags clearAspects, + VkClearValue clearValue) { + DxvkColorAttachmentOps colorOp; + colorOp.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + colorOp.loadLayout = imageView->imageInfo().layout; + colorOp.storeLayout = imageView->imageInfo().layout; + + DxvkDepthAttachmentOps depthOp; + depthOp.loadOpD = VK_ATTACHMENT_LOAD_OP_LOAD; + depthOp.loadOpS = VK_ATTACHMENT_LOAD_OP_LOAD; + depthOp.loadLayout = imageView->imageInfo().layout; + depthOp.storeLayout = imageView->imageInfo().layout; + + if (clearAspects & VK_IMAGE_ASPECT_COLOR_BIT) + colorOp.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + else if (discardAspects & VK_IMAGE_ASPECT_COLOR_BIT) + colorOp.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + + if (clearAspects & VK_IMAGE_ASPECT_DEPTH_BIT) + depthOp.loadOpD = VK_ATTACHMENT_LOAD_OP_CLEAR; + else if (discardAspects & VK_IMAGE_ASPECT_DEPTH_BIT) + depthOp.loadOpD = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + + if (clearAspects & VK_IMAGE_ASPECT_STENCIL_BIT) + depthOp.loadOpS = VK_ATTACHMENT_LOAD_OP_CLEAR; + else if (discardAspects & VK_IMAGE_ASPECT_DEPTH_BIT) + depthOp.loadOpS = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + + if (attachmentIndex >= 0 && !m_state.om.framebufferInfo.isWritable(attachmentIndex, clearAspects | discardAspects)) { + // Do not fold the clear/discard into the render pass if any of the affected aspects + // isn't writable. We can only hit this particular path when starting a render pass, + // so we can safely manipulate load layouts here. + int32_t colorIndex = m_state.om.framebufferInfo.getColorAttachmentIndex(attachmentIndex); + VkImageLayout renderLayout = m_state.om.framebufferInfo.getAttachment(attachmentIndex).layout; + + if (colorIndex < 0) { + depthOp.loadLayout = m_state.om.renderPassOps.depthOps.loadLayout; + depthOp.storeLayout = renderLayout; + m_state.om.renderPassOps.depthOps.loadLayout = renderLayout; + } else { + colorOp.loadLayout = m_state.om.renderPassOps.colorOps[colorIndex].loadLayout; + colorOp.storeLayout = renderLayout; + m_state.om.renderPassOps.colorOps[colorIndex].loadLayout = renderLayout; + } + + attachmentIndex = -1; + } + + bool is3D = imageView->imageInfo().type == VK_IMAGE_TYPE_3D; + + if ((clearAspects | discardAspects) == imageView->info().aspect && !is3D) { + colorOp.loadLayout = VK_IMAGE_LAYOUT_UNDEFINED; + depthOp.loadLayout = VK_IMAGE_LAYOUT_UNDEFINED; + } + + if (attachmentIndex < 0) { + if (m_execBarriers.isImageDirty( + imageView->image(), + imageView->imageSubresources(), + DxvkAccess::Write)) + m_execBarriers.recordCommands(m_cmd); + + // Set up and bind a temporary framebuffer + DxvkRenderTargets attachments; + DxvkRenderPassOps ops; + + VkPipelineStageFlags clearStages = 0; + VkAccessFlags clearAccess = 0; + + if ((clearAspects | discardAspects) & VK_IMAGE_ASPECT_COLOR_BIT) { + clearStages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + clearAccess |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + + attachments.color[0].view = imageView; + attachments.color[0].layout = imageView->pickLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + + ops.colorOps[0] = colorOp; + } else { + clearStages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT + | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + clearAccess |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + + attachments.depth.view = imageView; + attachments.depth.layout = imageView->pickLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + + ops.depthOps = depthOp; + } + + ops.barrier.srcStages = clearStages; + ops.barrier.srcAccess = clearAccess; + ops.barrier.dstStages = imageView->imageInfo().stages; + ops.barrier.dstAccess = imageView->imageInfo().access; + + this->renderPassBindFramebuffer(makeFramebufferInfo(attachments), ops, 1, &clearValue); + this->renderPassUnbindFramebuffer(); + } else { + // Perform the operation when starting the next render pass + if ((clearAspects | discardAspects) & VK_IMAGE_ASPECT_COLOR_BIT) { + uint32_t colorIndex = m_state.om.framebufferInfo.getColorAttachmentIndex(attachmentIndex); + + m_state.om.renderPassOps.colorOps[colorIndex].loadOp = colorOp.loadOp; + if (m_state.om.renderPassOps.colorOps[colorIndex].loadOp != VK_ATTACHMENT_LOAD_OP_LOAD && !is3D) + m_state.om.renderPassOps.colorOps[colorIndex].loadLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + m_state.om.clearValues[attachmentIndex].color = clearValue.color; + } + + if ((clearAspects | discardAspects) & VK_IMAGE_ASPECT_DEPTH_BIT) { + m_state.om.renderPassOps.depthOps.loadOpD = depthOp.loadOpD; + m_state.om.clearValues[attachmentIndex].depthStencil.depth = clearValue.depthStencil.depth; + } + + if ((clearAspects | discardAspects) & VK_IMAGE_ASPECT_STENCIL_BIT) { + m_state.om.renderPassOps.depthOps.loadOpS = depthOp.loadOpS; + m_state.om.clearValues[attachmentIndex].depthStencil.stencil = clearValue.depthStencil.stencil; + } + + if ((clearAspects | discardAspects) & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { + if (m_state.om.renderPassOps.depthOps.loadOpD != VK_ATTACHMENT_LOAD_OP_LOAD + && m_state.om.renderPassOps.depthOps.loadOpS != VK_ATTACHMENT_LOAD_OP_LOAD) + m_state.om.renderPassOps.depthOps.loadLayout = VK_IMAGE_LAYOUT_UNDEFINED; + } + } + } + + + void DxvkContext::deferClear( + const Rc& imageView, + VkImageAspectFlags clearAspects, + VkClearValue clearValue) { + for (auto& entry : m_deferredClears) { + if (entry.imageView->matchesView(imageView)) { + entry.imageView = imageView; + entry.discardAspects &= ~clearAspects; + entry.clearAspects |= clearAspects; + + if (clearAspects & VK_IMAGE_ASPECT_COLOR_BIT) + entry.clearValue.color = clearValue.color; + if (clearAspects & VK_IMAGE_ASPECT_DEPTH_BIT) + entry.clearValue.depthStencil.depth = clearValue.depthStencil.depth; + if (clearAspects & VK_IMAGE_ASPECT_STENCIL_BIT) + entry.clearValue.depthStencil.stencil = clearValue.depthStencil.stencil; + + return; + } else if (entry.imageView->checkSubresourceOverlap(imageView)) { + this->spillRenderPass(false); + break; + } + } + + m_deferredClears.push_back({ imageView, 0, clearAspects, clearValue }); + } + + + void DxvkContext::deferDiscard( + const Rc& imageView, + VkImageAspectFlags discardAspects) { + for (auto& entry : m_deferredClears) { + if (entry.imageView->matchesView(imageView)) { + entry.imageView = imageView; + entry.discardAspects |= discardAspects; + entry.clearAspects &= ~discardAspects; + return; + } else if (entry.imageView->checkSubresourceOverlap(imageView)) { + this->spillRenderPass(false); + break; + } + } + + m_deferredClears.push_back({ imageView, discardAspects }); + } + + + void DxvkContext::flushClears( + bool useRenderPass) { + for (const auto& clear : m_deferredClears) { + int32_t attachmentIndex = -1; + + if (useRenderPass && m_state.om.framebufferInfo.isFullSize(clear.imageView)) + attachmentIndex = m_state.om.framebufferInfo.findAttachment(clear.imageView); + + this->performClear(clear.imageView, attachmentIndex, + clear.discardAspects, clear.clearAspects, clear.clearValue); + } + + m_deferredClears.clear(); + } + + + void DxvkContext::flushSharedImages() { + for (auto i = m_deferredClears.begin(); i != m_deferredClears.end(); ) { + if (i->imageView->imageInfo().shared) { + this->performClear(i->imageView, -1, i->discardAspects, i->clearAspects, i->clearValue); + i = m_deferredClears.erase(i); + } else { + i++; + } + } + + this->transitionRenderTargetLayouts(m_execBarriers, true); + } + + + void DxvkContext::updateBuffer( + const Rc& buffer, + VkDeviceSize offset, + VkDeviceSize size, + const void* data) { + bool replaceBuffer = this->tryInvalidateDeviceLocalBuffer(buffer, size); + auto bufferSlice = buffer->getSliceHandle(offset, size); + + if (!replaceBuffer) { + this->spillRenderPass(true); + + if (m_execBarriers.isBufferDirty(bufferSlice, DxvkAccess::Write)) + m_execBarriers.recordCommands(m_cmd); + } + + DxvkCmdBuffer cmdBuffer = replaceBuffer + ? DxvkCmdBuffer::InitBuffer + : DxvkCmdBuffer::ExecBuffer; + + m_cmd->cmdUpdateBuffer(cmdBuffer, + bufferSlice.handle, + bufferSlice.offset, + bufferSlice.length, + data); + + auto& barriers = replaceBuffer + ? m_initBarriers + : m_execBarriers; + + barriers.accessBuffer(bufferSlice, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT, + buffer->info().stages, + buffer->info().access); + + m_cmd->trackResource(buffer); + } + + + void DxvkContext::updateDepthStencilImage( + const Rc& image, + const VkImageSubresourceLayers& subresources, + VkOffset2D imageOffset, + VkExtent2D imageExtent, + const void* data, + VkDeviceSize pitchPerRow, + VkDeviceSize pitchPerLayer, + VkFormat format) { + auto formatInfo = imageFormatInfo(format); + + VkExtent3D extent3D; + extent3D.width = imageExtent.width; + extent3D.height = imageExtent.height; + extent3D.depth = subresources.layerCount; + + VkDeviceSize pixelCount = extent3D.width * extent3D.height * extent3D.depth; + + DxvkBufferCreateInfo tmpBufferInfo; + tmpBufferInfo.size = pixelCount * formatInfo->elementSize; + tmpBufferInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + tmpBufferInfo.stages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; + tmpBufferInfo.access = VK_ACCESS_SHADER_READ_BIT; + + auto tmpBuffer = m_device->createBuffer(tmpBufferInfo, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | + VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + + util::packImageData(tmpBuffer->mapPtr(0), data, + extent3D, formatInfo->elementSize, + pitchPerRow, pitchPerLayer); + + copyPackedBufferToDepthStencilImage( + image, subresources, imageOffset, imageExtent, + tmpBuffer, 0, VkOffset2D { 0, 0 }, imageExtent, + format); + } + + + void DxvkContext::uploadBuffer( + const Rc& buffer, + const void* data) { + auto bufferSlice = buffer->getSliceHandle(); + + auto stagingSlice = m_staging.alloc(CACHE_LINE_SIZE, bufferSlice.length); + auto stagingHandle = stagingSlice.getSliceHandle(); + std::memcpy(stagingHandle.mapPtr, data, bufferSlice.length); + + VkBufferCopy region; + region.srcOffset = stagingHandle.offset; + region.dstOffset = bufferSlice.offset; + region.size = bufferSlice.length; + + m_cmd->cmdCopyBuffer(DxvkCmdBuffer::SdmaBuffer, + stagingHandle.handle, bufferSlice.handle, 1, ®ion); + + m_sdmaBarriers.releaseBuffer( + m_initBarriers, bufferSlice, + m_device->queues().transfer.queueFamily, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT, + m_device->queues().graphics.queueFamily, + buffer->info().stages, + buffer->info().access); + + m_cmd->trackResource(stagingSlice.buffer()); + m_cmd->trackResource(buffer); + } + + + void DxvkContext::uploadImage( + const Rc& image, + const VkImageSubresourceLayers& subresources, + const void* data, + VkDeviceSize pitchPerRow, + VkDeviceSize pitchPerLayer) { + VkOffset3D imageOffset = { 0, 0, 0 }; + VkExtent3D imageExtent = image->mipLevelExtent(subresources.mipLevel); + + DxvkCmdBuffer cmdBuffer = DxvkCmdBuffer::SdmaBuffer; + DxvkBarrierSet* barriers = &m_sdmaAcquires; + + if (subresources.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { + cmdBuffer = DxvkCmdBuffer::InitBuffer; + barriers = &m_initBarriers; + } + + // Discard previous subresource contents + barriers->accessImage(image, + vk::makeSubresourceRange(subresources), + VK_IMAGE_LAYOUT_UNDEFINED, 0, 0, + image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL), + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT); + + barriers->recordCommands(m_cmd); + + this->copyImageHostData(cmdBuffer, + image, subresources, imageOffset, imageExtent, + data, pitchPerRow, pitchPerLayer); + + // Transfer ownership to graphics queue + if (cmdBuffer == DxvkCmdBuffer::SdmaBuffer) { + m_sdmaBarriers.releaseImage(m_initBarriers, + image, vk::makeSubresourceRange(subresources), + m_device->queues().transfer.queueFamily, + image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL), + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT, + m_device->queues().graphics.queueFamily, + image->info().layout, + image->info().stages, + image->info().access); + } else { + barriers->accessImage(image, + vk::makeSubresourceRange(subresources), + image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL), + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT, + image->info().layout, + image->info().stages, + image->info().access); + } + + m_cmd->trackResource(image); + } + + + void DxvkContext::setViewports( + uint32_t viewportCount, + const VkViewport* viewports, + const VkRect2D* scissorRects) { + if (m_state.gp.state.rs.viewportCount() != viewportCount) { + m_state.gp.state.rs.setViewportCount(viewportCount); + m_flags.set(DxvkContextFlag::GpDirtyPipelineState); + } + + for (uint32_t i = 0; i < viewportCount; i++) { + m_state.vp.viewports[i] = viewports[i]; + m_state.vp.scissorRects[i] = scissorRects[i]; + + // Vulkan viewports are not allowed to have a width or + // height of zero, so we fall back to a dummy viewport + // and instead set an empty scissor rect, which is legal. + if (viewports[i].width == 0.0f || viewports[i].height == 0.0f) { + m_state.vp.viewports[i] = VkViewport { + 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f }; + m_state.vp.scissorRects[i] = VkRect2D { + VkOffset2D { 0, 0 }, + VkExtent2D { 0, 0 } }; + } + } + + m_flags.set(DxvkContextFlag::GpDirtyViewport); + } + + + void DxvkContext::setBlendConstants( + DxvkBlendConstants blendConstants) { + if (m_state.dyn.blendConstants != blendConstants) { + m_state.dyn.blendConstants = blendConstants; + m_flags.set(DxvkContextFlag::GpDirtyBlendConstants); + } + } + + + void DxvkContext::setDepthBias( + DxvkDepthBias depthBias) { + if (m_state.dyn.depthBias != depthBias) { + m_state.dyn.depthBias = depthBias; + m_flags.set(DxvkContextFlag::GpDirtyDepthBias); + } + } + + + void DxvkContext::setDepthBounds( + DxvkDepthBounds depthBounds) { + if (m_state.dyn.depthBounds != depthBounds) { + m_state.dyn.depthBounds = depthBounds; + m_flags.set(DxvkContextFlag::GpDirtyDepthBounds); + } + + if (m_state.gp.state.ds.enableDepthBoundsTest() != depthBounds.enableDepthBounds) { + m_state.gp.state.ds.setEnableDepthBoundsTest(depthBounds.enableDepthBounds); + m_flags.set(DxvkContextFlag::GpDirtyPipelineState); + } + } + + + void DxvkContext::setStencilReference( + uint32_t reference) { + if (m_state.dyn.stencilReference != reference) { + m_state.dyn.stencilReference = reference; + m_flags.set(DxvkContextFlag::GpDirtyStencilRef); + } + } + + + void DxvkContext::setInputAssemblyState(const DxvkInputAssemblyState& ia) { + m_state.gp.state.ia = DxvkIaInfo( + ia.primitiveTopology, + ia.primitiveRestart, + ia.patchVertexCount); + + m_flags.set(DxvkContextFlag::GpDirtyPipelineState); + } + + + void DxvkContext::setInputLayout( + uint32_t attributeCount, + const DxvkVertexAttribute* attributes, + uint32_t bindingCount, + const DxvkVertexBinding* bindings) { + m_flags.set( + DxvkContextFlag::GpDirtyPipelineState, + DxvkContextFlag::GpDirtyVertexBuffers); + + for (uint32_t i = 0; i < attributeCount; i++) { + m_state.gp.state.ilAttributes[i] = DxvkIlAttribute( + attributes[i].location, attributes[i].binding, + attributes[i].format, attributes[i].offset); + } + + for (uint32_t i = attributeCount; i < m_state.gp.state.il.attributeCount(); i++) + m_state.gp.state.ilAttributes[i] = DxvkIlAttribute(); + + for (uint32_t i = 0; i < bindingCount; i++) { + m_state.gp.state.ilBindings[i] = DxvkIlBinding( + bindings[i].binding, 0, bindings[i].inputRate, + bindings[i].fetchRate); + } + + for (uint32_t i = bindingCount; i < m_state.gp.state.il.bindingCount(); i++) + m_state.gp.state.ilBindings[i] = DxvkIlBinding(); + + m_state.gp.state.il = DxvkIlInfo(attributeCount, bindingCount); + } + + + void DxvkContext::setRasterizerState(const DxvkRasterizerState& rs) { + m_state.gp.state.rs = DxvkRsInfo( + rs.depthClipEnable, + rs.depthBiasEnable, + rs.polygonMode, + rs.cullMode, + rs.frontFace, + m_state.gp.state.rs.viewportCount(), + rs.sampleCount, + rs.conservativeMode); + + m_flags.set(DxvkContextFlag::GpDirtyPipelineState); + } + + + void DxvkContext::setMultisampleState(const DxvkMultisampleState& ms) { + m_state.gp.state.ms = DxvkMsInfo( + m_state.gp.state.ms.sampleCount(), + ms.sampleMask, + ms.enableAlphaToCoverage); + + m_flags.set(DxvkContextFlag::GpDirtyPipelineState); + } + + + void DxvkContext::setDepthStencilState(const DxvkDepthStencilState& ds) { + m_state.gp.state.ds = DxvkDsInfo( + ds.enableDepthTest, + ds.enableDepthWrite, + m_state.gp.state.ds.enableDepthBoundsTest(), + ds.enableStencilTest, + ds.depthCompareOp); + + m_state.gp.state.dsFront = DxvkDsStencilOp(ds.stencilOpFront); + m_state.gp.state.dsBack = DxvkDsStencilOp(ds.stencilOpBack); + + m_flags.set(DxvkContextFlag::GpDirtyPipelineState); + } + + + void DxvkContext::setLogicOpState(const DxvkLogicOpState& lo) { + m_state.gp.state.om = DxvkOmInfo( + lo.enableLogicOp, + lo.logicOp); + + m_flags.set(DxvkContextFlag::GpDirtyPipelineState); + } + + + void DxvkContext::setBlendMode( + uint32_t attachment, + const DxvkBlendMode& blendMode) { + m_state.gp.state.omBlend[attachment] = DxvkOmAttachmentBlend( + blendMode.enableBlending, + blendMode.colorSrcFactor, + blendMode.colorDstFactor, + blendMode.colorBlendOp, + blendMode.alphaSrcFactor, + blendMode.alphaDstFactor, + blendMode.alphaBlendOp, + blendMode.writeMask); + + m_flags.set(DxvkContextFlag::GpDirtyPipelineState); + } + + + void DxvkContext::setSpecConstant( + VkPipelineBindPoint pipeline, + uint32_t index, + uint32_t value) { + auto& specConst = pipeline == VK_PIPELINE_BIND_POINT_GRAPHICS + ? m_state.gp.state.sc.specConstants[index] + : m_state.cp.state.sc.specConstants[index]; + + if (specConst != value) { + specConst = value; + + m_flags.set(pipeline == VK_PIPELINE_BIND_POINT_GRAPHICS + ? DxvkContextFlag::GpDirtyPipelineState + : DxvkContextFlag::CpDirtyPipelineState); + } + } + + + void DxvkContext::setBarrierControl(DxvkBarrierControlFlags control) { + m_barrierControl = control; + } + + + void DxvkContext::signalGpuEvent(const Rc& event) { + this->spillRenderPass(true); + + DxvkGpuEventHandle handle = m_common->eventPool().allocEvent(); + + m_cmd->cmdSetEvent(handle.event, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT); + + m_cmd->trackGpuEvent(event->reset(handle)); + m_cmd->trackResource(event); + } + + + void DxvkContext::launchCuKernelNVX( + const VkCuLaunchInfoNVX& nvxLaunchInfo, + const std::vector, DxvkAccessFlags>>& buffers, + const std::vector, DxvkAccessFlags>>& images) { + // The resources in the std::vectors above are called-out + // explicitly in the API for barrier and tracking purposes + // since they're being used bindlessly. + this->spillRenderPass(true); + + VkPipelineStageFlags srcStages = 0; + VkAccessFlags srcAccess = 0; + + for (auto& r : buffers) { + srcStages |= r.first->info().stages; + srcAccess |= r.first->info().access; + } + + for (auto& r : images) { + srcStages |= r.first->info().stages; + srcAccess |= r.first->info().access; + + this->prepareImage(m_execBarriers, r.first, r.first->getAvailableSubresources()); + } + + m_execBarriers.accessMemory(srcStages, srcAccess, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT); + m_execBarriers.recordCommands(m_cmd); + + m_cmd->cmdLaunchCuKernel(nvxLaunchInfo); + + for (auto& r : buffers) { + VkAccessFlags accessFlags = (r.second.test(DxvkAccess::Read) * VK_ACCESS_SHADER_READ_BIT) + | (r.second.test(DxvkAccess::Write) * VK_ACCESS_SHADER_WRITE_BIT); + DxvkBufferSliceHandle bufferSlice = r.first->getSliceHandle(); + m_execBarriers.accessBuffer(bufferSlice, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + accessFlags, + r.first->info().stages, + r.first->info().access); + } + + for (auto& r : images) { + VkAccessFlags accessFlags = (r.second.test(DxvkAccess::Read) * VK_ACCESS_SHADER_READ_BIT) + | (r.second.test(DxvkAccess::Write) * VK_ACCESS_SHADER_WRITE_BIT); + m_execBarriers.accessImage(r.first, + r.first->getAvailableSubresources(), + r.first->info().layout, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + accessFlags, + r.first->info().layout, + r.first->info().stages, + r.first->info().access); + } + + for (auto& r : images) { + if (r.second.test(DxvkAccess::Read)) m_cmd->trackResource(r.first); + if (r.second.test(DxvkAccess::Write)) m_cmd->trackResource(r.first); + } + + for (auto& r : buffers) { + if (r.second.test(DxvkAccess::Read)) m_cmd->trackResource(r.first); + if (r.second.test(DxvkAccess::Write)) m_cmd->trackResource(r.first); + } + } + + + void DxvkContext::writeTimestamp(const Rc& query) { + m_queryManager.writeTimestamp(m_cmd, query); + } + + + void DxvkContext::signal(const Rc& signal, uint64_t value) { + m_cmd->queueSignal(signal, value); + } + + + void DxvkContext::waitFence(const Rc& fence, uint64_t value) { + m_cmd->waitFence(fence, value); + } + + + void DxvkContext::signalFence(const Rc& fence, uint64_t value) { + m_cmd->signalFence(fence, value); + } + + + void DxvkContext::beginDebugLabel(VkDebugUtilsLabelEXT *label) { + if (!m_device->instance()->extensions().extDebugUtils) + return; + + m_cmd->cmdBeginDebugUtilsLabel(label); + } + + void DxvkContext::endDebugLabel() { + if (!m_device->instance()->extensions().extDebugUtils) + return; + + m_cmd->cmdEndDebugUtilsLabel(); + } + + void DxvkContext::insertDebugLabel(VkDebugUtilsLabelEXT *label) { + if (!m_device->instance()->extensions().extDebugUtils) + return; + + m_cmd->cmdInsertDebugUtilsLabel(label); + } + + + void DxvkContext::blitImageFb( + const Rc& dstImage, + const Rc& srcImage, + const VkImageBlit& region, + const VkComponentMapping& mapping, + VkFilter filter) { + auto dstSubresourceRange = vk::makeSubresourceRange(region.dstSubresource); + auto srcSubresourceRange = vk::makeSubresourceRange(region.srcSubresource); + + if (m_execBarriers.isImageDirty(dstImage, dstSubresourceRange, DxvkAccess::Write) + || m_execBarriers.isImageDirty(srcImage, srcSubresourceRange, DxvkAccess::Write)) + m_execBarriers.recordCommands(m_cmd); + + bool isDepthStencil = region.srcSubresource.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); + + VkImageLayout srcLayout = srcImage->pickLayout(isDepthStencil + ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL + : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + + if (srcImage->info().layout != srcLayout) { + m_execAcquires.accessImage( + srcImage, srcSubresourceRange, + srcImage->info().layout, + srcImage->info().stages, 0, + srcLayout, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_ACCESS_SHADER_READ_BIT); + + m_execAcquires.recordCommands(m_cmd); + } + + // Sort out image offsets so that dstOffset[0] points + // to the top-left corner of the target area + VkOffset3D srcOffsets[2] = { region.srcOffsets[0], region.srcOffsets[1] }; + VkOffset3D dstOffsets[2] = { region.dstOffsets[0], region.dstOffsets[1] }; + + if (dstOffsets[0].x > dstOffsets[1].x) { + std::swap(dstOffsets[0].x, dstOffsets[1].x); + std::swap(srcOffsets[0].x, srcOffsets[1].x); + } + + if (dstOffsets[0].y > dstOffsets[1].y) { + std::swap(dstOffsets[0].y, dstOffsets[1].y); + std::swap(srcOffsets[0].y, srcOffsets[1].y); + } + + if (dstOffsets[0].z > dstOffsets[1].z) { + std::swap(dstOffsets[0].z, dstOffsets[1].z); + std::swap(srcOffsets[0].z, srcOffsets[1].z); + } + + VkExtent3D dstExtent = { + uint32_t(dstOffsets[1].x - dstOffsets[0].x), + uint32_t(dstOffsets[1].y - dstOffsets[0].y), + uint32_t(dstOffsets[1].z - dstOffsets[0].z) }; + + // Begin render pass + Rc pass = new DxvkMetaBlitRenderPass( + m_device, dstImage, srcImage, region, mapping); + DxvkMetaBlitPass passObjects = pass->pass(); + + VkExtent3D imageExtent = dstImage->mipLevelExtent(region.dstSubresource.mipLevel); + + VkRect2D renderArea; + renderArea.offset = VkOffset2D { 0, 0 }; + renderArea.extent = VkExtent2D { imageExtent.width, imageExtent.height }; + + VkRenderPassBeginInfo passInfo; + passInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + passInfo.pNext = nullptr; + passInfo.renderPass = passObjects.renderPass; + passInfo.framebuffer = passObjects.framebuffer; + passInfo.renderArea = renderArea; + passInfo.clearValueCount = 0; + passInfo.pClearValues = nullptr; + + m_cmd->cmdBeginRenderPass(&passInfo, VK_SUBPASS_CONTENTS_INLINE); + + // Bind pipeline + DxvkMetaBlitPipeline pipeInfo = m_common->metaBlit().getPipeline( + pass->viewType(), dstImage->info().format, dstImage->info().sampleCount); + + m_cmd->cmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeInfo.pipeHandle); + + // Set up viewport + VkViewport viewport; + viewport.x = float(dstOffsets[0].x); + viewport.y = float(dstOffsets[0].y); + viewport.width = float(dstExtent.width); + viewport.height = float(dstExtent.height); + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + VkRect2D scissor; + scissor.offset = { dstOffsets[0].x, dstOffsets[0].y }; + scissor.extent = { dstExtent.width, dstExtent.height }; + + m_cmd->cmdSetViewport(0, 1, &viewport); + m_cmd->cmdSetScissor (0, 1, &scissor); + + // Bind source image view + VkDescriptorImageInfo descriptorImage; + descriptorImage.sampler = m_common->metaBlit().getSampler(filter); + descriptorImage.imageView = passObjects.srcView; + descriptorImage.imageLayout = srcLayout; + + VkWriteDescriptorSet descriptorWrite; + descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrite.pNext = nullptr; + descriptorWrite.dstSet = allocateDescriptorSet(pipeInfo.dsetLayout); + descriptorWrite.dstBinding = 0; + descriptorWrite.dstArrayElement = 0; + descriptorWrite.descriptorCount = 1; + descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + descriptorWrite.pImageInfo = &descriptorImage; + descriptorWrite.pBufferInfo = nullptr; + descriptorWrite.pTexelBufferView = nullptr; + + m_cmd->updateDescriptorSets(1, &descriptorWrite); + m_cmd->cmdBindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, + pipeInfo.pipeLayout, descriptorWrite.dstSet, 0, nullptr); + + // Compute shader parameters for the operation + VkExtent3D srcExtent = srcImage->mipLevelExtent(region.srcSubresource.mipLevel); + + DxvkMetaBlitPushConstants pushConstants = { }; + pushConstants.srcCoord0 = { + float(srcOffsets[0].x) / float(srcExtent.width), + float(srcOffsets[0].y) / float(srcExtent.height), + float(srcOffsets[0].z) / float(srcExtent.depth) }; + pushConstants.srcCoord1 = { + float(srcOffsets[1].x) / float(srcExtent.width), + float(srcOffsets[1].y) / float(srcExtent.height), + float(srcOffsets[1].z) / float(srcExtent.depth) }; + pushConstants.layerCount = pass->framebufferLayerCount(); + + m_cmd->cmdPushConstants( + pipeInfo.pipeLayout, + VK_SHADER_STAGE_FRAGMENT_BIT, + 0, sizeof(pushConstants), + &pushConstants); + + m_cmd->cmdDraw(3, pushConstants.layerCount, 0, 0); + m_cmd->cmdEndRenderPass(); + + // Add barriers and track image objects + m_execBarriers.accessImage(dstImage, + vk::makeSubresourceRange(region.dstSubresource), + dstImage->info().layout, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + dstImage->info().layout, + dstImage->info().stages, + dstImage->info().access); + + m_execBarriers.accessImage(srcImage, + vk::makeSubresourceRange(region.srcSubresource), + srcLayout, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_ACCESS_SHADER_READ_BIT, + srcImage->info().layout, + srcImage->info().stages, + srcImage->info().access); + + m_cmd->trackResource(dstImage); + m_cmd->trackResource(srcImage); + m_cmd->trackResource(pass); + } + + + void DxvkContext::blitImageHw( + const Rc& dstImage, + const Rc& srcImage, + const VkImageBlit& region, + VkFilter filter) { + auto dstSubresourceRange = vk::makeSubresourceRange(region.dstSubresource); + auto srcSubresourceRange = vk::makeSubresourceRange(region.srcSubresource); + + if (m_execBarriers.isImageDirty(dstImage, dstSubresourceRange, DxvkAccess::Write) + || m_execBarriers.isImageDirty(srcImage, srcSubresourceRange, DxvkAccess::Write)) + m_execBarriers.recordCommands(m_cmd); + + // Prepare the two images for transfer ops if necessary + auto dstLayout = dstImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + auto srcLayout = srcImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + + if (dstImage->info().layout != dstLayout) { + m_execAcquires.accessImage( + dstImage, dstSubresourceRange, + dstImage->info().layout, + VK_PIPELINE_STAGE_TRANSFER_BIT, 0, + dstLayout, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT); + } + + if (srcImage->info().layout != srcLayout) { + m_execAcquires.accessImage( + srcImage, srcSubresourceRange, + srcImage->info().layout, + VK_PIPELINE_STAGE_TRANSFER_BIT, 0, + srcLayout, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_READ_BIT); + } + + m_execAcquires.recordCommands(m_cmd); + + // Perform the blit operation + m_cmd->cmdBlitImage( + srcImage->handle(), srcLayout, + dstImage->handle(), dstLayout, + 1, ®ion, filter); + + m_execBarriers.accessImage( + dstImage, dstSubresourceRange, dstLayout, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT, + dstImage->info().layout, + dstImage->info().stages, + dstImage->info().access); + + m_execBarriers.accessImage( + srcImage, srcSubresourceRange, srcLayout, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_READ_BIT, + srcImage->info().layout, + srcImage->info().stages, + srcImage->info().access); + + m_cmd->trackResource(dstImage); + m_cmd->trackResource(srcImage); + } + + + template + void DxvkContext::copyImageBufferData( + DxvkCmdBuffer cmd, + const Rc& image, + const VkImageSubresourceLayers& imageSubresource, + VkOffset3D imageOffset, + VkExtent3D imageExtent, + VkImageLayout imageLayout, + const DxvkBufferSliceHandle& bufferSlice, + VkDeviceSize bufferRowAlignment, + VkDeviceSize bufferSliceAlignment) { + auto formatInfo = image->formatInfo(); + auto layers = imageSubresource.layerCount; + + VkDeviceSize bufferOffset = bufferSlice.offset; + + // Do one copy region per layer in case the buffer memory layout is weird + if (bufferSliceAlignment || formatInfo->flags.test(DxvkFormatFlag::MultiPlane)) + layers = 1; + + for (uint32_t i = 0; i < imageSubresource.layerCount; i += layers) { + auto aspectOffset = bufferOffset; + + for (auto aspects = imageSubresource.aspectMask; aspects; ) { + auto aspect = vk::getNextAspect(aspects); + auto elementSize = formatInfo->elementSize; + + VkBufferImageCopy copyRegion = { }; + copyRegion.imageSubresource.aspectMask = aspect; + copyRegion.imageSubresource.baseArrayLayer = imageSubresource.baseArrayLayer + i; + copyRegion.imageSubresource.layerCount = layers; + copyRegion.imageSubresource.mipLevel = imageSubresource.mipLevel; + copyRegion.imageOffset = imageOffset; + copyRegion.imageExtent = imageExtent; + + if (formatInfo->flags.test(DxvkFormatFlag::MultiPlane)) { + auto plane = &formatInfo->planes[vk::getPlaneIndex(aspect)]; + copyRegion.imageOffset.x /= plane->blockSize.width; + copyRegion.imageOffset.y /= plane->blockSize.height; + copyRegion.imageExtent.width /= plane->blockSize.width; + copyRegion.imageExtent.height /= plane->blockSize.height; + elementSize = plane->elementSize; + } + + // Vulkan can't really express row pitch in the same way that client APIs + // may expect, so we'll need to do some heroics here and hope that it works + VkExtent3D blockCount = util::computeBlockCount(copyRegion.imageExtent, formatInfo->blockSize); + VkDeviceSize rowPitch = blockCount.width * elementSize; + + if (bufferRowAlignment > elementSize) + rowPitch = bufferRowAlignment >= rowPitch ? bufferRowAlignment : align(rowPitch, bufferRowAlignment); + + VkDeviceSize slicePitch = blockCount.height * rowPitch; + + if (image->info().type == VK_IMAGE_TYPE_3D && bufferSliceAlignment > elementSize) + slicePitch = bufferSliceAlignment >= slicePitch ? bufferSliceAlignment : align(slicePitch, bufferSliceAlignment); + + copyRegion.bufferOffset = aspectOffset; + copyRegion.bufferRowLength = formatInfo->blockSize.width * rowPitch / elementSize; + copyRegion.bufferImageHeight = formatInfo->blockSize.height * slicePitch / rowPitch; + + // Perform the actual copy + if constexpr (ToImage) { + m_cmd->cmdCopyBufferToImage(cmd, bufferSlice.handle, + image->handle(), imageLayout, 1, ©Region); + } else { + m_cmd->cmdCopyImageToBuffer(cmd, image->handle(), imageLayout, + bufferSlice.handle, 1, ©Region); + } + + aspectOffset += blockCount.depth * slicePitch; + } + + // Advance to next layer. This is non-trivial for multi-plane formats + // since plane data for each layer is expected to be packed. + VkDeviceSize layerPitch = aspectOffset - bufferOffset; + + if (bufferSliceAlignment) + layerPitch = bufferSliceAlignment >= layerPitch ? bufferSliceAlignment : align(layerPitch, bufferSliceAlignment); + + bufferOffset += layerPitch; + } + } + + + void DxvkContext::copyImageHostData( + DxvkCmdBuffer cmd, + const Rc& image, + const VkImageSubresourceLayers& imageSubresource, + VkOffset3D imageOffset, + VkExtent3D imageExtent, + const void* hostData, + VkDeviceSize rowPitch, + VkDeviceSize slicePitch) { + auto formatInfo = image->formatInfo(); + auto srcData = reinterpret_cast(hostData); + + for (uint32_t i = 0; i < imageSubresource.layerCount; i++) { + auto layerData = srcData + i * slicePitch; + + for (auto aspects = imageSubresource.aspectMask; aspects; ) { + auto aspect = vk::getNextAspect(aspects); + auto extent = imageExtent; + + VkDeviceSize elementSize = formatInfo->elementSize; + + if (formatInfo->flags.test(DxvkFormatFlag::MultiPlane)) { + auto plane = &formatInfo->planes[vk::getPlaneIndex(aspect)]; + extent.width /= plane->blockSize.width; + extent.height /= plane->blockSize.height; + elementSize = plane->elementSize; + } + + auto blockCount = util::computeBlockCount(extent, formatInfo->blockSize); + auto stagingSlice = m_staging.alloc(CACHE_LINE_SIZE, elementSize * util::flattenImageExtent(blockCount)); + auto stagingHandle = stagingSlice.getSliceHandle(); + + util::packImageData(stagingHandle.mapPtr, layerData, + blockCount, elementSize, rowPitch, slicePitch); + + auto subresource = imageSubresource; + subresource.aspectMask = aspect; + + this->copyImageBufferData(cmd, + image, subresource, imageOffset, imageExtent, + image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL), + stagingHandle, 0, 0); + + layerData += blockCount.height * rowPitch; + + m_cmd->trackResource(stagingSlice.buffer()); + } + } + } + + + void DxvkContext::clearImageViewFb( + const Rc& imageView, + VkOffset3D offset, + VkExtent3D extent, + VkImageAspectFlags aspect, + VkClearValue value) { + this->updateFramebuffer(); + + // Find out if the render target view is currently bound, + // so that we can avoid spilling the render pass if it is. + int32_t attachmentIndex = -1; + + if (m_state.om.framebufferInfo.isFullSize(imageView)) + attachmentIndex = m_state.om.framebufferInfo.findAttachment(imageView); + + if (attachmentIndex >= 0 && !m_state.om.framebufferInfo.isWritable(attachmentIndex, aspect)) + attachmentIndex = -1; + + if (attachmentIndex < 0) { + this->spillRenderPass(false); + + if (m_execBarriers.isImageDirty( + imageView->image(), + imageView->imageSubresources(), + DxvkAccess::Write)) + m_execBarriers.recordCommands(m_cmd); + + // Set up a temporary framebuffer + DxvkRenderTargets attachments; + DxvkRenderPassOps ops; + + VkPipelineStageFlags clearStages = 0; + VkAccessFlags clearAccess = 0; + + if (imageView->info().aspect & VK_IMAGE_ASPECT_COLOR_BIT) { + clearStages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + clearAccess |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT + | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; + + attachments.color[0].view = imageView; + attachments.color[0].layout = imageView->pickLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + + ops.colorOps[0].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + ops.colorOps[0].loadLayout = imageView->imageInfo().layout; + ops.colorOps[0].storeLayout = imageView->imageInfo().layout; + } else { + clearStages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT + | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + clearAccess |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT + | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; + + attachments.depth.view = imageView; + attachments.depth.layout = imageView->pickLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + + ops.depthOps.loadOpD = VK_ATTACHMENT_LOAD_OP_LOAD; + ops.depthOps.loadOpS = VK_ATTACHMENT_LOAD_OP_LOAD; + ops.depthOps.loadLayout = imageView->imageInfo().layout; + ops.depthOps.storeLayout = imageView->imageInfo().layout; + } + + ops.barrier.srcStages = clearStages; + ops.barrier.srcAccess = clearAccess; + ops.barrier.dstStages = imageView->imageInfo().stages; + ops.barrier.dstAccess = imageView->imageInfo().access; + + // We cannot leverage render pass clears + // because we clear only part of the view + this->renderPassBindFramebuffer(makeFramebufferInfo(attachments), ops, 0, nullptr); + } else { + // Make sure the render pass is active so + // that we can actually perform the clear + this->startRenderPass(); + } + + // Perform the actual clear operation + VkClearAttachment clearInfo; + clearInfo.aspectMask = aspect; + clearInfo.colorAttachment = 0; + clearInfo.clearValue = value; + + if ((aspect & VK_IMAGE_ASPECT_COLOR_BIT) && (attachmentIndex >= 0)) + clearInfo.colorAttachment = m_state.om.framebufferInfo.getColorAttachmentIndex(attachmentIndex); + + VkClearRect clearRect; + clearRect.rect.offset.x = offset.x; + clearRect.rect.offset.y = offset.y; + clearRect.rect.extent.width = extent.width; + clearRect.rect.extent.height = extent.height; + clearRect.baseArrayLayer = 0; + clearRect.layerCount = imageView->info().numLayers; + + m_cmd->cmdClearAttachments(1, &clearInfo, 1, &clearRect); + + // Unbind temporary framebuffer + if (attachmentIndex < 0) + this->renderPassUnbindFramebuffer(); + } + + + void DxvkContext::clearImageViewCs( + const Rc& imageView, + VkOffset3D offset, + VkExtent3D extent, + VkClearValue value) { + this->spillRenderPass(false); + this->unbindComputePipeline(); + + if (m_execBarriers.isImageDirty( + imageView->image(), + imageView->imageSubresources(), + DxvkAccess::Write)) + m_execBarriers.recordCommands(m_cmd); + + // Query pipeline objects to use for this clear operation + DxvkMetaClearPipeline pipeInfo = m_common->metaClear().getClearImagePipeline( + imageView->type(), imageFormatInfo(imageView->info().format)->flags); + + // Create a descriptor set pointing to the view + VkDescriptorSet descriptorSet = allocateDescriptorSet(pipeInfo.dsetLayout); + + VkDescriptorImageInfo viewInfo; + viewInfo.sampler = VK_NULL_HANDLE; + viewInfo.imageView = imageView->handle(); + viewInfo.imageLayout = imageView->imageInfo().layout; + + VkWriteDescriptorSet descriptorWrite; + descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrite.pNext = nullptr; + descriptorWrite.dstSet = descriptorSet; + descriptorWrite.dstBinding = 0; + descriptorWrite.dstArrayElement = 0; + descriptorWrite.descriptorCount = 1; + descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + descriptorWrite.pImageInfo = &viewInfo; + descriptorWrite.pBufferInfo = nullptr; + descriptorWrite.pTexelBufferView = nullptr; + m_cmd->updateDescriptorSets(1, &descriptorWrite); + + // Prepare shader arguments + DxvkMetaClearArgs pushArgs = { }; + pushArgs.clearValue = value.color; + pushArgs.offset = offset; + pushArgs.extent = extent; + + VkExtent3D workgroups = util::computeBlockCount( + pushArgs.extent, pipeInfo.workgroupSize); + + if (imageView->type() == VK_IMAGE_VIEW_TYPE_1D_ARRAY) + workgroups.height = imageView->subresources().layerCount; + else if (imageView->type() == VK_IMAGE_VIEW_TYPE_2D_ARRAY) + workgroups.depth = imageView->subresources().layerCount; + + m_cmd->cmdBindPipeline( + VK_PIPELINE_BIND_POINT_COMPUTE, + pipeInfo.pipeline); + m_cmd->cmdBindDescriptorSet( + VK_PIPELINE_BIND_POINT_COMPUTE, + pipeInfo.pipeLayout, descriptorSet, + 0, nullptr); + m_cmd->cmdPushConstants( + pipeInfo.pipeLayout, + VK_SHADER_STAGE_COMPUTE_BIT, + 0, sizeof(pushArgs), &pushArgs); + m_cmd->cmdDispatch( + workgroups.width, + workgroups.height, + workgroups.depth); + + m_execBarriers.accessImage( + imageView->image(), + imageView->imageSubresources(), + imageView->imageInfo().layout, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_ACCESS_SHADER_WRITE_BIT, + imageView->imageInfo().layout, + imageView->imageInfo().stages, + imageView->imageInfo().access); + + m_cmd->trackResource(imageView); + m_cmd->trackResource(imageView->image()); + } + + + void DxvkContext::copyImageHw( + const Rc& dstImage, + VkImageSubresourceLayers dstSubresource, + VkOffset3D dstOffset, + const Rc& srcImage, + VkImageSubresourceLayers srcSubresource, + VkOffset3D srcOffset, + VkExtent3D extent) { + auto dstSubresourceRange = vk::makeSubresourceRange(dstSubresource); + auto srcSubresourceRange = vk::makeSubresourceRange(srcSubresource); + + auto dstFormatInfo = dstImage->formatInfo(); + + if (m_execBarriers.isImageDirty(dstImage, dstSubresourceRange, DxvkAccess::Write) + || m_execBarriers.isImageDirty(srcImage, srcSubresourceRange, DxvkAccess::Write)) + m_execBarriers.recordCommands(m_cmd); + + VkImageLayout dstImageLayout = dstImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + VkImageLayout srcImageLayout = srcImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + + VkImageLayout dstInitImageLayout = dstImage->info().layout; + + if (dstImage->isFullSubresource(dstSubresource, extent)) + dstInitImageLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + if (dstImageLayout != dstInitImageLayout) { + m_execAcquires.accessImage( + dstImage, dstSubresourceRange, + dstInitImageLayout, + VK_PIPELINE_STAGE_TRANSFER_BIT, 0, + dstImageLayout, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT); + } + + if (srcImageLayout != srcImage->info().layout) { + m_execAcquires.accessImage( + srcImage, srcSubresourceRange, + srcImage->info().layout, + VK_PIPELINE_STAGE_TRANSFER_BIT, 0, + srcImageLayout, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_READ_BIT); + } + + m_execAcquires.recordCommands(m_cmd); + + for (auto aspects = dstSubresource.aspectMask; aspects; ) { + auto aspect = vk::getNextAspect(aspects); + + VkImageCopy imageRegion; + imageRegion.srcSubresource = srcSubresource; + imageRegion.srcSubresource.aspectMask = aspect; + imageRegion.srcOffset = srcOffset; + imageRegion.dstSubresource = dstSubresource; + imageRegion.dstSubresource.aspectMask = aspect; + imageRegion.dstOffset = dstOffset; + imageRegion.extent = extent; + + if (dstFormatInfo->flags.test(DxvkFormatFlag::MultiPlane)) { + auto plane = &dstFormatInfo->planes[vk::getPlaneIndex(aspect)]; + imageRegion.srcOffset.x /= plane->blockSize.width; + imageRegion.srcOffset.y /= plane->blockSize.height; + imageRegion.dstOffset.x /= plane->blockSize.width; + imageRegion.dstOffset.y /= plane->blockSize.height; + imageRegion.extent.width /= plane->blockSize.width; + imageRegion.extent.height /= plane->blockSize.height; + } + + m_cmd->cmdCopyImage(DxvkCmdBuffer::ExecBuffer, + srcImage->handle(), srcImageLayout, + dstImage->handle(), dstImageLayout, + 1, &imageRegion); + } + + m_execBarriers.accessImage( + dstImage, dstSubresourceRange, + dstImageLayout, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT, + dstImage->info().layout, + dstImage->info().stages, + dstImage->info().access); + + m_execBarriers.accessImage( + srcImage, srcSubresourceRange, + srcImageLayout, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_READ_BIT, + srcImage->info().layout, + srcImage->info().stages, + srcImage->info().access); + + m_cmd->trackResource(dstImage); + m_cmd->trackResource(srcImage); + } + + + void DxvkContext::copyImageFb( + const Rc& dstImage, + VkImageSubresourceLayers dstSubresource, + VkOffset3D dstOffset, + const Rc& srcImage, + VkImageSubresourceLayers srcSubresource, + VkOffset3D srcOffset, + VkExtent3D extent) { + auto dstSubresourceRange = vk::makeSubresourceRange(dstSubresource); + auto srcSubresourceRange = vk::makeSubresourceRange(srcSubresource); + + if (m_execBarriers.isImageDirty(dstImage, dstSubresourceRange, DxvkAccess::Write) + || m_execBarriers.isImageDirty(srcImage, srcSubresourceRange, DxvkAccess::Write)) + m_execBarriers.recordCommands(m_cmd); + + // Source image needs to be readable + if (!(srcImage->info().usage & VK_IMAGE_USAGE_SAMPLED_BIT)) { + Logger::err("DxvkContext: copyImageFb: Source image not readable"); + return; + } + + // Render target format to use for this copy + VkFormat viewFormat = m_common->metaCopy().getCopyDestinationFormat( + dstSubresource.aspectMask, + srcSubresource.aspectMask, + srcImage->info().format); + + if (viewFormat == VK_FORMAT_UNDEFINED) { + Logger::err("DxvkContext: copyImageFb: Unsupported format"); + return; + } + + // We might have to transition the source image layout + VkImageLayout srcLayout = (srcSubresource.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) + ? srcImage->pickLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) + : srcImage->pickLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL); + + if (srcImage->info().layout != srcLayout) { + m_execAcquires.accessImage( + srcImage, srcSubresourceRange, + srcImage->info().layout, + srcImage->info().stages, 0, + srcLayout, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_ACCESS_SHADER_READ_BIT); + + m_execAcquires.recordCommands(m_cmd); + } + + // In some cases, we may be able to render to the destination + // image directly, which is faster than using a temporary image + VkImageUsageFlagBits tgtUsage = (dstSubresource.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) + ? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT + : VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + + bool useDirectRender = (dstImage->isViewCompatible(viewFormat)) + && (dstImage->info().usage & tgtUsage); + + // If needed, create a temporary render target for the copy + Rc tgtImage; + VkImageSubresourceLayers tgtSubresource = dstSubresource; + VkOffset3D tgtOffset = dstOffset; + + if (!useDirectRender) { + DxvkImageCreateInfo info; + info.type = dstImage->info().type; + info.format = viewFormat; + info.flags = 0; + info.sampleCount = dstImage->info().sampleCount; + info.extent = extent; + info.numLayers = dstSubresource.layerCount; + info.mipLevels = 1; + info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | tgtUsage; + info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT; + info.access = VK_ACCESS_TRANSFER_READ_BIT; + info.tiling = VK_IMAGE_TILING_OPTIMAL; + info.layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + + tgtImage = m_device->createImage(info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + + tgtSubresource.mipLevel = 0; + tgtSubresource.baseArrayLayer = 0; + + tgtOffset = { 0, 0, 0 }; + } else { + tgtImage = dstImage; + } + + // Create source and destination image views + VkImageViewType viewType = dstImage->info().type == VK_IMAGE_TYPE_1D + ? VK_IMAGE_VIEW_TYPE_1D_ARRAY + : VK_IMAGE_VIEW_TYPE_2D_ARRAY; + + DxvkImageViewCreateInfo tgtViewInfo; + tgtViewInfo.type = viewType; + tgtViewInfo.format = viewFormat; + tgtViewInfo.usage = tgtUsage; + tgtViewInfo.aspect = tgtSubresource.aspectMask; + tgtViewInfo.minLevel = tgtSubresource.mipLevel; + tgtViewInfo.numLevels = 1; + tgtViewInfo.minLayer = tgtSubresource.baseArrayLayer; + tgtViewInfo.numLayers = tgtSubresource.layerCount; + + DxvkImageViewCreateInfo srcViewInfo; + srcViewInfo.type = viewType; + srcViewInfo.format = srcImage->info().format; + srcViewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT; + srcViewInfo.aspect = srcSubresource.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_COLOR_BIT); + srcViewInfo.minLevel = srcSubresource.mipLevel; + srcViewInfo.numLevels = 1; + srcViewInfo.minLayer = srcSubresource.baseArrayLayer; + srcViewInfo.numLayers = srcSubresource.layerCount; + + Rc tgtImageView = m_device->createImageView(tgtImage, tgtViewInfo); + Rc srcImageView = m_device->createImageView(srcImage, srcViewInfo); + Rc srcStencilView; + + if (srcSubresource.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) { + srcViewInfo.aspect = VK_IMAGE_ASPECT_STENCIL_BIT; + srcStencilView = m_device->createImageView(srcImage, srcViewInfo); + } + + // Create framebuffer and pipeline for the copy + Rc fb = new DxvkMetaCopyRenderPass( + m_device->vkd(), tgtImageView, srcImageView, srcStencilView, + tgtImage->isFullSubresource(tgtSubresource, extent)); + + auto pipeInfo = m_common->metaCopy().getPipeline( + viewType, viewFormat, tgtImage->info().sampleCount); + + VkDescriptorImageInfo descriptorImage; + descriptorImage.sampler = VK_NULL_HANDLE; + descriptorImage.imageView = srcImageView->handle(); + descriptorImage.imageLayout = srcLayout; + + VkWriteDescriptorSet descriptorWrite; + descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrite.pNext = nullptr; + descriptorWrite.dstBinding = 0; + descriptorWrite.dstArrayElement = 0; + descriptorWrite.descriptorCount = 1; + descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + descriptorWrite.pImageInfo = &descriptorImage; + descriptorWrite.pBufferInfo = nullptr; + descriptorWrite.pTexelBufferView = nullptr; + + descriptorWrite.dstSet = allocateDescriptorSet(pipeInfo.dsetLayout); + m_cmd->updateDescriptorSets(1, &descriptorWrite); + + if (srcSubresource.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) { + descriptorImage.imageView = srcStencilView->handle(); + descriptorWrite.dstBinding = 1; + m_cmd->updateDescriptorSets(1, &descriptorWrite); + } + + VkViewport viewport; + viewport.x = float(tgtOffset.x); + viewport.y = float(tgtOffset.y); + viewport.width = float(extent.width); + viewport.height = float(extent.height); + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + VkRect2D scissor; + scissor.offset = { tgtOffset.x, tgtOffset.y }; + scissor.extent = { extent.width, extent.height }; + + VkRenderPassBeginInfo info; + info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + info.pNext = nullptr; + info.renderPass = fb->renderPass(); + info.framebuffer = fb->framebuffer(); + info.renderArea.offset = { 0, 0 }; + info.renderArea.extent = { + tgtImage->mipLevelExtent(tgtSubresource.mipLevel).width, + tgtImage->mipLevelExtent(tgtSubresource.mipLevel).height }; + info.clearValueCount = 0; + info.pClearValues = nullptr; + + // Perform the actual copy operation + m_cmd->cmdBeginRenderPass(&info, VK_SUBPASS_CONTENTS_INLINE); + m_cmd->cmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeInfo.pipeHandle); + m_cmd->cmdBindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, + pipeInfo.pipeLayout, descriptorWrite.dstSet, 0, nullptr); + + m_cmd->cmdSetViewport(0, 1, &viewport); + m_cmd->cmdSetScissor (0, 1, &scissor); + + VkOffset2D srcCoordOffset = { + srcOffset.x - tgtOffset.x, + srcOffset.y - tgtOffset.y }; + + m_cmd->cmdPushConstants(pipeInfo.pipeLayout, + VK_SHADER_STAGE_FRAGMENT_BIT, + 0, sizeof(srcCoordOffset), + &srcCoordOffset); + + m_cmd->cmdDraw(3, tgtSubresource.layerCount, 0, 0); + m_cmd->cmdEndRenderPass(); + + if (srcLayout != srcImage->info().layout) { + m_execBarriers.accessImage( + srcImage, srcSubresourceRange, srcLayout, + srcImage->info().stages, + srcImage->info().access, + srcImage->info().layout, + srcImage->info().stages, + srcImage->info().access); + } + + m_cmd->trackResource(tgtImage); + m_cmd->trackResource(srcImage); + m_cmd->trackResource(fb); + + // If necessary, copy the temporary image + // to the original destination image + if (!useDirectRender) { + this->copyImageHw( + dstImage, dstSubresource, dstOffset, + tgtImage, tgtSubresource, tgtOffset, + extent); + } + } + + + bool DxvkContext::copyImageClear( + const Rc& dstImage, + VkImageSubresourceLayers dstSubresource, + VkOffset3D dstOffset, + VkExtent3D dstExtent, + const Rc& srcImage, + VkImageSubresourceLayers srcSubresource) { + // If the source image has a pending deferred clear, we can + // implement the copy by clearing the destination image to + // the same clear value. + const VkImageUsageFlags attachmentUsage + = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT + | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + + if (!(dstImage->info().usage & attachmentUsage) + || !(srcImage->info().usage & attachmentUsage)) + return false; + + // Ignore 3D images since those are complicated to handle + if (dstImage->info().type == VK_IMAGE_TYPE_3D + || srcImage->info().type == VK_IMAGE_TYPE_3D) + return false; + + // Find a pending clear that overlaps with the source image + const DxvkDeferredClear* clear = nullptr; + + for (const auto& entry : m_deferredClears) { + // Entries in the deferred clear array cannot overlap, so + // if we find an entry covering all source subresources, + // it's the only one in the list that does. + if ((entry.imageView->image() == srcImage) && ((srcSubresource.aspectMask & entry.clearAspects) == srcSubresource.aspectMask) + && (vk::checkSubresourceRangeSuperset(entry.imageView->subresources(), vk::makeSubresourceRange(srcSubresource)))) { + clear = &entry; + break; + } + } + + if (!clear) + return false; + + // Create a view for the destination image with the general + // properties ofthe source image view used for the clear + DxvkImageViewCreateInfo viewInfo = clear->imageView->info(); + viewInfo.type = dstImage->info().type == VK_IMAGE_TYPE_1D + ? VK_IMAGE_VIEW_TYPE_1D_ARRAY + : VK_IMAGE_VIEW_TYPE_2D_ARRAY; + viewInfo.minLevel = dstSubresource.mipLevel; + viewInfo.numLevels = 1; + viewInfo.minLayer = dstSubresource.baseArrayLayer; + viewInfo.numLayers = dstSubresource.layerCount; + + // That is, if the formats are actually compatible + // so that we can safely use the same clear value + if (!dstImage->isViewCompatible(viewInfo.format)) + return false; + + // Ignore mismatched size for now, needs more testing since we'd + // need to prepare the image first and then call clearImageViewFb + if (dstImage->mipLevelExtent(dstSubresource.mipLevel) != dstExtent) + return false; + + auto view = m_device->createImageView(dstImage, viewInfo); + this->deferClear(view, srcSubresource.aspectMask, clear->clearValue); + return true; + } + + + void DxvkContext::resolveImageHw( + const Rc& dstImage, + const Rc& srcImage, + const VkImageResolve& region) { + auto dstSubresourceRange = vk::makeSubresourceRange(region.dstSubresource); + auto srcSubresourceRange = vk::makeSubresourceRange(region.srcSubresource); + + if (m_execBarriers.isImageDirty(dstImage, dstSubresourceRange, DxvkAccess::Write) + || m_execBarriers.isImageDirty(srcImage, srcSubresourceRange, DxvkAccess::Write)) + m_execBarriers.recordCommands(m_cmd); + + // We only support resolving to the entire image + // area, so we might as well discard its contents + VkImageLayout dstLayout = dstImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + VkImageLayout srcLayout = srcImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + + VkImageLayout initialLayout = dstImage->info().layout; + + if (dstImage->isFullSubresource(region.dstSubresource, region.extent)) + initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + if (dstLayout != initialLayout) { + m_execAcquires.accessImage( + dstImage, dstSubresourceRange, initialLayout, + VK_PIPELINE_STAGE_TRANSFER_BIT, 0, + dstLayout, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT); + } + + if (srcLayout != srcImage->info().layout) { + m_execAcquires.accessImage( + srcImage, srcSubresourceRange, + srcImage->info().layout, + VK_PIPELINE_STAGE_TRANSFER_BIT, 0, + srcLayout, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_READ_BIT); + } + + m_execAcquires.recordCommands(m_cmd); + + m_cmd->cmdResolveImage( + srcImage->handle(), srcLayout, + dstImage->handle(), dstLayout, + 1, ®ion); + + m_execBarriers.accessImage( + dstImage, dstSubresourceRange, dstLayout, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT, + dstImage->info().layout, + dstImage->info().stages, + dstImage->info().access); + + m_execBarriers.accessImage( + srcImage, srcSubresourceRange, srcLayout, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_READ_BIT, + srcImage->info().layout, + srcImage->info().stages, + srcImage->info().access); + + m_cmd->trackResource(dstImage); + m_cmd->trackResource(srcImage); + } + + + void DxvkContext::resolveImageDs( + const Rc& dstImage, + const Rc& srcImage, + const VkImageResolve& region, + VkResolveModeFlagBitsKHR depthMode, + VkResolveModeFlagBitsKHR stencilMode) { + auto dstSubresourceRange = vk::makeSubresourceRange(region.dstSubresource); + auto srcSubresourceRange = vk::makeSubresourceRange(region.srcSubresource); + + if (m_execBarriers.isImageDirty(dstImage, dstSubresourceRange, DxvkAccess::Write) + || m_execBarriers.isImageDirty(srcImage, srcSubresourceRange, DxvkAccess::Write)) + m_execBarriers.recordCommands(m_cmd); + + // Create image views covering the requested subresourcs + DxvkImageViewCreateInfo dstViewInfo; + dstViewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; + dstViewInfo.format = dstImage->info().format; + dstViewInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + dstViewInfo.aspect = region.dstSubresource.aspectMask; + dstViewInfo.minLevel = region.dstSubresource.mipLevel; + dstViewInfo.numLevels = 1; + dstViewInfo.minLayer = region.dstSubresource.baseArrayLayer; + dstViewInfo.numLayers = region.dstSubresource.layerCount; + + DxvkImageViewCreateInfo srcViewInfo; + srcViewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; + srcViewInfo.format = srcImage->info().format; + srcViewInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + srcViewInfo.aspect = region.srcSubresource.aspectMask; + srcViewInfo.minLevel = region.srcSubresource.mipLevel; + srcViewInfo.numLevels = 1; + srcViewInfo.minLayer = region.srcSubresource.baseArrayLayer; + srcViewInfo.numLayers = region.srcSubresource.layerCount; + + Rc dstImageView = m_device->createImageView(dstImage, dstViewInfo); + Rc srcImageView = m_device->createImageView(srcImage, srcViewInfo); + + // Create a framebuffer for the resolve op + VkExtent3D passExtent = dstImageView->mipLevelExtent(0); + + Rc fb = new DxvkMetaResolveRenderPass( + m_device->vkd(), dstImageView, srcImageView, depthMode, stencilMode); + + VkRenderPassBeginInfo info; + info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + info.pNext = nullptr; + info.renderPass = fb->renderPass(); + info.framebuffer = fb->framebuffer(); + info.renderArea.offset = { 0, 0 }; + info.renderArea.extent = { passExtent.width, passExtent.height }; + info.clearValueCount = 0; + info.pClearValues = nullptr; + + m_cmd->cmdBeginRenderPass(&info, VK_SUBPASS_CONTENTS_INLINE); + m_cmd->cmdEndRenderPass(); + + m_cmd->trackResource(dstImage); + m_cmd->trackResource(srcImage); + m_cmd->trackResource(fb); + } + + + void DxvkContext::resolveImageFb( + const Rc& dstImage, + const Rc& srcImage, + const VkImageResolve& region, + VkFormat format, + VkResolveModeFlagBitsKHR depthMode, + VkResolveModeFlagBitsKHR stencilMode) { + auto dstSubresourceRange = vk::makeSubresourceRange(region.dstSubresource); + auto srcSubresourceRange = vk::makeSubresourceRange(region.srcSubresource); + + if (m_execBarriers.isImageDirty(dstImage, dstSubresourceRange, DxvkAccess::Write) + || m_execBarriers.isImageDirty(srcImage, srcSubresourceRange, DxvkAccess::Write)) + m_execBarriers.recordCommands(m_cmd); + + // We might have to transition the source image layout + VkImageLayout srcLayout = srcImage->pickLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + + if (srcImage->info().layout != srcLayout) { + m_execAcquires.accessImage( + srcImage, srcSubresourceRange, + srcImage->info().layout, + srcImage->info().stages, 0, + srcLayout, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_ACCESS_SHADER_READ_BIT); + + m_execAcquires.recordCommands(m_cmd); + } + + // Create image views covering the requested subresourcs + DxvkImageViewCreateInfo dstViewInfo; + dstViewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; + dstViewInfo.format = format ? format : dstImage->info().format; + dstViewInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + dstViewInfo.aspect = region.dstSubresource.aspectMask; + dstViewInfo.minLevel = region.dstSubresource.mipLevel; + dstViewInfo.numLevels = 1; + dstViewInfo.minLayer = region.dstSubresource.baseArrayLayer; + dstViewInfo.numLayers = region.dstSubresource.layerCount; + + if (region.dstSubresource.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) + dstViewInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + + DxvkImageViewCreateInfo srcViewInfo; + srcViewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; + srcViewInfo.format = format ? format : srcImage->info().format; + srcViewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT; + srcViewInfo.aspect = region.srcSubresource.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_COLOR_BIT); + srcViewInfo.minLevel = region.srcSubresource.mipLevel; + srcViewInfo.numLevels = 1; + srcViewInfo.minLayer = region.srcSubresource.baseArrayLayer; + srcViewInfo.numLayers = region.srcSubresource.layerCount; + + Rc dstImageView = m_device->createImageView(dstImage, dstViewInfo); + Rc srcImageView = m_device->createImageView(srcImage, srcViewInfo); + Rc srcStencilView = nullptr; + + if ((region.dstSubresource.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) && stencilMode != VK_RESOLVE_MODE_NONE_KHR) { + srcViewInfo.aspect = VK_IMAGE_ASPECT_STENCIL_BIT; + srcStencilView = m_device->createImageView(srcImage, srcViewInfo); + } + + // Create a framebuffer and pipeline for the resolve op + VkExtent3D passExtent = dstImageView->mipLevelExtent(0); + + Rc fb = new DxvkMetaResolveRenderPass( + m_device->vkd(), dstImageView, srcImageView, srcStencilView, + dstImage->isFullSubresource(region.dstSubresource, region.extent)); + + auto pipeInfo = m_common->metaResolve().getPipeline( + dstViewInfo.format, srcImage->info().sampleCount, depthMode, stencilMode); + + VkDescriptorImageInfo descriptorImage; + descriptorImage.sampler = VK_NULL_HANDLE; + descriptorImage.imageView = srcImageView->handle(); + descriptorImage.imageLayout = srcLayout; + + VkWriteDescriptorSet descriptorWrite; + descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrite.pNext = nullptr; + descriptorWrite.dstBinding = 0; + descriptorWrite.dstArrayElement = 0; + descriptorWrite.descriptorCount = 1; + descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + descriptorWrite.pImageInfo = &descriptorImage; + descriptorWrite.pBufferInfo = nullptr; + descriptorWrite.pTexelBufferView = nullptr; + + descriptorWrite.dstSet = allocateDescriptorSet(pipeInfo.dsetLayout); + m_cmd->updateDescriptorSets(1, &descriptorWrite); + + if (srcStencilView != nullptr) { + descriptorWrite.dstBinding = 1; + descriptorImage.imageView = srcStencilView->handle(); + m_cmd->updateDescriptorSets(1, &descriptorWrite); + } + + VkViewport viewport; + viewport.x = float(region.dstOffset.x); + viewport.y = float(region.dstOffset.y); + viewport.width = float(region.extent.width); + viewport.height = float(region.extent.height); + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + VkRect2D scissor; + scissor.offset = { region.dstOffset.x, region.dstOffset.y }; + scissor.extent = { region.extent.width, region.extent.height }; + + VkRenderPassBeginInfo info; + info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + info.pNext = nullptr; + info.renderPass = fb->renderPass(); + info.framebuffer = fb->framebuffer(); + info.renderArea.offset = { 0, 0 }; + info.renderArea.extent = { passExtent.width, passExtent.height }; + info.clearValueCount = 0; + info.pClearValues = nullptr; + + // Perform the actual resolve operation + VkOffset2D srcOffset = { + region.srcOffset.x - region.dstOffset.x, + region.srcOffset.y - region.dstOffset.y }; + + m_cmd->cmdBeginRenderPass(&info, VK_SUBPASS_CONTENTS_INLINE); + m_cmd->cmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeInfo.pipeHandle); + m_cmd->cmdBindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, + pipeInfo.pipeLayout, descriptorWrite.dstSet, 0, nullptr); + m_cmd->cmdSetViewport(0, 1, &viewport); + m_cmd->cmdSetScissor (0, 1, &scissor); + m_cmd->cmdPushConstants(pipeInfo.pipeLayout, + VK_SHADER_STAGE_FRAGMENT_BIT, + 0, sizeof(srcOffset), &srcOffset); + m_cmd->cmdDraw(3, region.dstSubresource.layerCount, 0, 0); + m_cmd->cmdEndRenderPass(); + + if (srcImage->info().layout != srcLayout) { + m_execBarriers.accessImage( + srcImage, srcSubresourceRange, srcLayout, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, + srcImage->info().layout, + srcImage->info().stages, + srcImage->info().access); + } + + m_cmd->trackResource(dstImage); + m_cmd->trackResource(srcImage); + m_cmd->trackResource(fb); + } + + + void DxvkContext::startRenderPass() { + if (!m_flags.test(DxvkContextFlag::GpRenderPassBound)) { + this->applyRenderTargetLoadLayouts(); + this->flushClears(true); + + m_flags.set(DxvkContextFlag::GpRenderPassBound); + m_flags.clr(DxvkContextFlag::GpRenderPassSuspended); + + m_execBarriers.recordCommands(m_cmd); + + this->renderPassBindFramebuffer( + m_state.om.framebufferInfo, + m_state.om.renderPassOps, + m_state.om.framebufferInfo.numAttachments(), + m_state.om.clearValues.data()); + + // Track the final layout of each render target + this->applyRenderTargetStoreLayouts(); + + // Don't discard image contents if we have + // to spill the current render pass + this->resetRenderPassOps( + m_state.om.renderTargets, + m_state.om.renderPassOps); + + // Begin occlusion queries + m_queryManager.beginQueries(m_cmd, VK_QUERY_TYPE_OCCLUSION); + m_queryManager.beginQueries(m_cmd, VK_QUERY_TYPE_PIPELINE_STATISTICS); + } + } + + + void DxvkContext::spillRenderPass(bool suspend) { + if (m_flags.test(DxvkContextFlag::GpRenderPassBound)) { + m_flags.clr(DxvkContextFlag::GpRenderPassBound); + + this->pauseTransformFeedback(); + + m_queryManager.endQueries(m_cmd, VK_QUERY_TYPE_OCCLUSION); + m_queryManager.endQueries(m_cmd, VK_QUERY_TYPE_PIPELINE_STATISTICS); + + this->renderPassUnbindFramebuffer(); + + if (suspend) + m_flags.set(DxvkContextFlag::GpRenderPassSuspended); + else + this->transitionRenderTargetLayouts(m_gfxBarriers, false); + + m_gfxBarriers.recordCommands(m_cmd); + + this->unbindGraphicsPipeline(); + } else if (!suspend) { + // We may end a previously suspended render pass + if (m_flags.test(DxvkContextFlag::GpRenderPassSuspended)) { + m_flags.clr(DxvkContextFlag::GpRenderPassSuspended); + this->transitionRenderTargetLayouts(m_gfxBarriers, false); + m_gfxBarriers.recordCommands(m_cmd); + } + + // Execute deferred clears if necessary + this->flushClears(false); + } + } + + + void DxvkContext::renderPassBindFramebuffer( + const DxvkFramebufferInfo& framebufferInfo, + const DxvkRenderPassOps& ops, + uint32_t clearValueCount, + const VkClearValue* clearValues) { + const DxvkFramebufferSize fbSize = framebufferInfo.size(); + + Rc framebuffer = this->lookupFramebuffer(framebufferInfo); + + VkRect2D renderArea; + renderArea.offset = VkOffset2D { 0, 0 }; + renderArea.extent = VkExtent2D { fbSize.width, fbSize.height }; + + VkRenderPassBeginInfo info; + info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + info.pNext = nullptr; + info.renderPass = framebufferInfo.renderPass()->getHandle(ops); + info.framebuffer = framebuffer->handle(); + info.renderArea = renderArea; + info.clearValueCount = clearValueCount; + info.pClearValues = clearValues; + + m_cmd->cmdBeginRenderPass(&info, + VK_SUBPASS_CONTENTS_INLINE); + + m_cmd->trackResource(framebuffer); + + for (uint32_t i = 0; i < framebufferInfo.numAttachments(); i++) { + m_cmd->trackResource (framebufferInfo.getAttachment(i).view); + m_cmd->trackResource(framebufferInfo.getAttachment(i).view->image()); + } + + m_cmd->addStatCtr(DxvkStatCounter::CmdRenderPassCount, 1); + } + + + void DxvkContext::renderPassUnbindFramebuffer() { + m_cmd->cmdEndRenderPass(); + } + + + void DxvkContext::resetRenderPassOps( + const DxvkRenderTargets& renderTargets, + DxvkRenderPassOps& renderPassOps) { + VkAccessFlags access = 0; + + if (renderTargets.depth.view != nullptr) { + renderPassOps.depthOps = DxvkDepthAttachmentOps { + VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_LOAD_OP_LOAD, + renderTargets.depth.layout, renderTargets.depth.layout }; + + access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; + + if (renderTargets.depth.layout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL) + access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + } else { + renderPassOps.depthOps = DxvkDepthAttachmentOps { }; + } + + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { + if (renderTargets.color[i].view != nullptr) { + renderPassOps.colorOps[i] = DxvkColorAttachmentOps { + VK_ATTACHMENT_LOAD_OP_LOAD, + renderTargets.color[i].layout, + renderTargets.color[i].layout }; + + access |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT + | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + } else { + renderPassOps.colorOps[i] = DxvkColorAttachmentOps { }; + } + } + + renderPassOps.barrier.srcStages = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT; + renderPassOps.barrier.srcAccess = access; + renderPassOps.barrier.dstStages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; + renderPassOps.barrier.dstAccess = access; + } + + + void DxvkContext::startTransformFeedback() { + if (!m_flags.test(DxvkContextFlag::GpXfbActive)) { + m_flags.set(DxvkContextFlag::GpXfbActive); + + VkBuffer ctrBuffers[MaxNumXfbBuffers]; + VkDeviceSize ctrOffsets[MaxNumXfbBuffers]; + + for (uint32_t i = 0; i < MaxNumXfbBuffers; i++) { + auto physSlice = m_state.xfb.counters[i].getSliceHandle(); + + ctrBuffers[i] = physSlice.handle; + ctrOffsets[i] = physSlice.offset; + + if (physSlice.handle != VK_NULL_HANDLE) + m_cmd->trackResource(m_state.xfb.counters[i].buffer()); + } + + m_cmd->cmdBeginTransformFeedback( + 0, MaxNumXfbBuffers, ctrBuffers, ctrOffsets); + + m_queryManager.beginQueries(m_cmd, + VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT); + } + } + + + void DxvkContext::pauseTransformFeedback() { + if (m_flags.test(DxvkContextFlag::GpXfbActive)) { + m_flags.clr(DxvkContextFlag::GpXfbActive); + + VkBuffer ctrBuffers[MaxNumXfbBuffers]; + VkDeviceSize ctrOffsets[MaxNumXfbBuffers]; + + for (uint32_t i = 0; i < MaxNumXfbBuffers; i++) { + auto physSlice = m_state.xfb.counters[i].getSliceHandle(); + + ctrBuffers[i] = physSlice.handle; + ctrOffsets[i] = physSlice.offset; + + if (physSlice.handle != VK_NULL_HANDLE) + m_cmd->trackResource(m_state.xfb.counters[i].buffer()); + } + + m_queryManager.endQueries(m_cmd, + VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT); + + m_cmd->cmdEndTransformFeedback( + 0, MaxNumXfbBuffers, ctrBuffers, ctrOffsets); + } + } + + + void DxvkContext::unbindComputePipeline() { + m_flags.set( + DxvkContextFlag::CpDirtyPipeline, + DxvkContextFlag::CpDirtyPipelineState, + DxvkContextFlag::CpDirtyResources); + + m_cpActivePipeline = VK_NULL_HANDLE; + } + + + bool DxvkContext::updateComputePipeline() { + m_state.cp.pipeline = lookupComputePipeline(m_state.cp.shaders); + + if (unlikely(m_state.cp.pipeline == nullptr)) + return false; + + if (m_state.cp.pipeline->layout()->pushConstRange().size) + m_flags.set(DxvkContextFlag::DirtyPushConstants); + + m_flags.clr(DxvkContextFlag::CpDirtyPipeline); + return true; + } + + + bool DxvkContext::updateComputePipelineState() { + m_cpActivePipeline = m_state.cp.pipeline->getPipelineHandle(m_state.cp.state); + + if (unlikely(!m_cpActivePipeline)) + return false; + + m_cmd->cmdBindPipeline( + VK_PIPELINE_BIND_POINT_COMPUTE, + m_cpActivePipeline); + + m_flags.clr(DxvkContextFlag::CpDirtyPipelineState); + return true; + } + + + void DxvkContext::unbindGraphicsPipeline() { + m_flags.set( + DxvkContextFlag::GpDirtyPipeline, + DxvkContextFlag::GpDirtyPipelineState, + DxvkContextFlag::GpDirtyResources, + DxvkContextFlag::GpDirtyVertexBuffers, + DxvkContextFlag::GpDirtyIndexBuffer, + DxvkContextFlag::GpDirtyXfbBuffers, + DxvkContextFlag::GpDirtyBlendConstants, + DxvkContextFlag::GpDirtyStencilRef, + DxvkContextFlag::GpDirtyViewport, + DxvkContextFlag::GpDirtyDepthBias, + DxvkContextFlag::GpDirtyDepthBounds); + + m_gpActivePipeline = VK_NULL_HANDLE; + } + + + bool DxvkContext::updateGraphicsPipeline() { + m_state.gp.pipeline = lookupGraphicsPipeline(m_state.gp.shaders); + + if (unlikely(m_state.gp.pipeline == nullptr)) { + m_state.gp.flags = DxvkGraphicsPipelineFlags(); + return false; + } + + if (m_state.gp.flags != m_state.gp.pipeline->flags()) { + m_state.gp.flags = m_state.gp.pipeline->flags(); + + // Force-update vertex/index buffers for hazard checks + m_flags.set(DxvkContextFlag::GpDirtyIndexBuffer, + DxvkContextFlag::GpDirtyVertexBuffers, + DxvkContextFlag::GpDirtyXfbBuffers, + DxvkContextFlag::DirtyDrawBuffer); + + // This is necessary because we'll only do hazard + // tracking if the active pipeline has side effects + if (!m_barrierControl.test(DxvkBarrierControl::IgnoreGraphicsBarriers)) + this->spillRenderPass(true); + } + + if (m_state.gp.pipeline->layout()->pushConstRange().size) + m_flags.set(DxvkContextFlag::DirtyPushConstants); + + m_flags.clr(DxvkContextFlag::GpDirtyPipeline); + return true; + } + + + bool DxvkContext::updateGraphicsPipelineState() { + // Set up vertex buffer strides for active bindings + for (uint32_t i = 0; i < m_state.gp.state.il.bindingCount(); i++) { + const uint32_t binding = m_state.gp.state.ilBindings[i].binding(); + m_state.gp.state.ilBindings[i].setStride(m_state.vi.vertexStrides[binding]); + } + + // Check which dynamic states need to be active. States that + // are not dynamic will be invalidated in the command buffer. + m_flags.clr(DxvkContextFlag::GpDynamicBlendConstants, + DxvkContextFlag::GpDynamicDepthBias, + DxvkContextFlag::GpDynamicDepthBounds, + DxvkContextFlag::GpDynamicStencilRef); + + m_flags.set(m_state.gp.state.useDynamicBlendConstants() + ? DxvkContextFlag::GpDynamicBlendConstants + : DxvkContextFlag::GpDirtyBlendConstants); + + m_flags.set(m_state.gp.state.useDynamicDepthBias() + ? DxvkContextFlag::GpDynamicDepthBias + : DxvkContextFlag::GpDirtyDepthBias); + + m_flags.set(m_state.gp.state.useDynamicDepthBounds() + ? DxvkContextFlag::GpDynamicDepthBounds + : DxvkContextFlag::GpDirtyDepthBounds); + + m_flags.set(m_state.gp.state.useDynamicStencilRef() + ? DxvkContextFlag::GpDynamicStencilRef + : DxvkContextFlag::GpDirtyStencilRef); + + // Retrieve and bind actual Vulkan pipeline handle + m_gpActivePipeline = m_state.gp.pipeline->getPipelineHandle( + m_state.gp.state, m_state.om.framebufferInfo.renderPass()); + + if (unlikely(!m_gpActivePipeline)) + return false; + + m_cmd->cmdBindPipeline( + VK_PIPELINE_BIND_POINT_GRAPHICS, + m_gpActivePipeline); + + m_flags.clr(DxvkContextFlag::GpDirtyPipelineState); + return true; + } + + + void DxvkContext::updateComputeShaderResources() { + if ((m_flags.test(DxvkContextFlag::CpDirtyResources)) + || (m_state.cp.pipeline->layout()->hasStaticBufferBindings())) + this->updateShaderResources(m_state.cp.pipeline->layout()); + + this->updateShaderDescriptorSetBinding( + m_cpSet, m_state.cp.pipeline->layout()); + + m_flags.clr(DxvkContextFlag::CpDirtyResources, + DxvkContextFlag::CpDirtyDescriptorBinding); + } + + + void DxvkContext::updateGraphicsShaderResources() { + if ((m_flags.test(DxvkContextFlag::GpDirtyResources)) + || (m_state.gp.pipeline->layout()->hasStaticBufferBindings())) + this->updateShaderResources(m_state.gp.pipeline->layout()); + + this->updateShaderDescriptorSetBinding( + m_gpSet, m_state.gp.pipeline->layout()); + + m_flags.clr(DxvkContextFlag::GpDirtyResources, + DxvkContextFlag::GpDirtyDescriptorBinding); + } + + + template + void DxvkContext::updateShaderResources(const DxvkPipelineLayout* layout) { + std::array descriptors; + + // Assume that all bindings are active as a fast path + DxvkBindingMask bindMask; + bindMask.setFirst(layout->bindingCount()); + + for (uint32_t i = 0; i < layout->bindingCount(); i++) { + const auto& binding = layout->binding(i); + const auto& res = m_rc[binding.slot]; + + switch (binding.type) { + case VK_DESCRIPTOR_TYPE_SAMPLER: + if (res.sampler != nullptr) { + descriptors[i].image.sampler = res.sampler->handle(); + descriptors[i].image.imageView = VK_NULL_HANDLE; + descriptors[i].image.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + if (m_rcTracked.set(binding.slot)) + m_cmd->trackResource(res.sampler); + } else { + descriptors[i].image = m_common->dummyResources().samplerDescriptor(); + } break; + + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + if (res.imageView != nullptr && res.imageView->handle(binding.view) != VK_NULL_HANDLE) { + descriptors[i].image.sampler = VK_NULL_HANDLE; + descriptors[i].image.imageView = res.imageView->handle(binding.view); + descriptors[i].image.imageLayout = res.imageView->imageInfo().layout; + + if (m_rcTracked.set(binding.slot)) { + m_cmd->trackResource(res.imageView); + m_cmd->trackResource(res.imageView->image()); + } + } else { + bindMask.clr(i); + descriptors[i].image = m_common->dummyResources().imageViewDescriptor(binding.view, true); + } break; + + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: + if (res.imageView != nullptr && res.imageView->handle(binding.view) != VK_NULL_HANDLE) { + descriptors[i].image.sampler = VK_NULL_HANDLE; + descriptors[i].image.imageView = res.imageView->handle(binding.view); + descriptors[i].image.imageLayout = res.imageView->imageInfo().layout; + + if (m_rcTracked.set(binding.slot)) { + m_cmd->trackResource(res.imageView); + m_cmd->trackResource(res.imageView->image()); + } + } else { + bindMask.clr(i); + descriptors[i].image = m_common->dummyResources().imageViewDescriptor(binding.view, false); + } break; + + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + if (res.sampler != nullptr && res.imageView != nullptr + && res.imageView->handle(binding.view) != VK_NULL_HANDLE) { + descriptors[i].image.sampler = res.sampler->handle(); + descriptors[i].image.imageView = res.imageView->handle(binding.view); + descriptors[i].image.imageLayout = res.imageView->imageInfo().layout; + + if (m_rcTracked.set(binding.slot)) { + m_cmd->trackResource(res.sampler); + m_cmd->trackResource(res.imageView); + m_cmd->trackResource(res.imageView->image()); + } + } else { + bindMask.clr(i); + descriptors[i].image = m_common->dummyResources().imageSamplerDescriptor(binding.view); + } break; + + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: + if (res.bufferView != nullptr) { + res.bufferView->updateView(); + descriptors[i].texelBuffer = res.bufferView->handle(); + + if (m_rcTracked.set(binding.slot)) { + m_cmd->trackResource(res.bufferView); + m_cmd->trackResource(res.bufferView->buffer()); + } + } else { + bindMask.clr(i); + descriptors[i].texelBuffer = m_common->dummyResources().bufferViewDescriptor(); + } break; + + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + if (res.bufferView != nullptr) { + res.bufferView->updateView(); + descriptors[i].texelBuffer = res.bufferView->handle(); + + if (m_rcTracked.set(binding.slot)) { + m_cmd->trackResource(res.bufferView); + m_cmd->trackResource(res.bufferView->buffer()); + } + } else { + bindMask.clr(i); + descriptors[i].texelBuffer = m_common->dummyResources().bufferViewDescriptor(); + } break; + + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: + if (res.bufferSlice.defined()) { + descriptors[i] = res.bufferSlice.getDescriptor(); + + if (m_rcTracked.set(binding.slot)) + m_cmd->trackResource(res.bufferSlice.buffer()); + } else { + bindMask.clr(i); + descriptors[i].buffer = m_common->dummyResources().bufferDescriptor(); + } break; + + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: + if (res.bufferSlice.defined()) { + descriptors[i] = res.bufferSlice.getDescriptor(); + + if (m_rcTracked.set(binding.slot)) + m_cmd->trackResource(res.bufferSlice.buffer()); + } else { + bindMask.clr(i); + descriptors[i].buffer = m_common->dummyResources().bufferDescriptor(); + } break; + + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: + if (res.bufferSlice.defined()) { + descriptors[i] = res.bufferSlice.getDescriptor(); + descriptors[i].buffer.offset = 0; + + if (m_rcTracked.set(binding.slot)) + m_cmd->trackResource(res.bufferSlice.buffer()); + } else { + bindMask.clr(i); + descriptors[i].buffer = m_common->dummyResources().bufferDescriptor(); + } break; + + default: + Logger::err(str::format("DxvkContext: Unhandled descriptor type: ", binding.type)); + } + } + + // Allocate and update descriptor set + auto& set = BindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS ? m_gpSet : m_cpSet; + + if (layout->bindingCount()) { + set = allocateDescriptorSet(layout->descriptorSetLayout()); + + m_cmd->updateDescriptorSetWithTemplate(set, + layout->descriptorTemplate(), descriptors.data()); + } else { + set = VK_NULL_HANDLE; + } + + // Select the active binding mask to update + auto& refMask = BindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS + ? m_state.gp.state.bsBindingMask + : m_state.cp.state.bsBindingMask; + + // If some resources are not bound, we may need to + // update spec constants and rebind the pipeline + if (refMask != bindMask) { + refMask = bindMask; + + m_flags.set(BindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS + ? DxvkContextFlag::GpDirtyPipelineState + : DxvkContextFlag::CpDirtyPipelineState); + } + } + + + template + void DxvkContext::updateShaderDescriptorSetBinding( + VkDescriptorSet set, + const DxvkPipelineLayout* layout) { + if (set) { + std::array offsets; + + for (uint32_t i = 0; i < layout->dynamicBindingCount(); i++) { + const auto& binding = layout->dynamicBinding(i); + const auto& res = m_rc[binding.slot]; + + offsets[i] = res.bufferSlice.defined() + ? res.bufferSlice.getDynamicOffset() + : 0; + } + + m_cmd->cmdBindDescriptorSet(BindPoint, + layout->pipelineLayout(), set, + layout->dynamicBindingCount(), + offsets.data()); + } + } + + + DxvkFramebufferInfo DxvkContext::makeFramebufferInfo( + const DxvkRenderTargets& renderTargets) { + auto renderPassFormat = DxvkFramebufferInfo::getRenderPassFormat(renderTargets); + auto renderPassObject = m_common->renderPassPool().getRenderPass(renderPassFormat); + + return DxvkFramebufferInfo(renderTargets, m_device->getDefaultFramebufferSize(), renderPassObject); + } + + + void DxvkContext::updateFramebuffer() { + if (m_flags.test(DxvkContextFlag::GpDirtyFramebuffer)) { + m_flags.clr(DxvkContextFlag::GpDirtyFramebuffer); + + this->spillRenderPass(true); + + DxvkFramebufferInfo fbInfo = makeFramebufferInfo(m_state.om.renderTargets); + this->updateRenderTargetLayouts(fbInfo, m_state.om.framebufferInfo); + + m_state.gp.state.ms.setSampleCount(fbInfo.getSampleCount()); + m_state.om.framebufferInfo = fbInfo; + + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { + const Rc& attachment = fbInfo.getColorTarget(i).view; + + VkComponentMapping mapping = attachment != nullptr + ? util::invertComponentMapping(attachment->info().swizzle) + : VkComponentMapping(); + + m_state.gp.state.omSwizzle[i] = DxvkOmAttachmentSwizzle(mapping); + } + + m_flags.set(DxvkContextFlag::GpDirtyPipelineState); + } + } + + + void DxvkContext::applyRenderTargetLoadLayouts() { + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) + m_state.om.renderPassOps.colorOps[i].loadLayout = m_rtLayouts.color[i]; + + m_state.om.renderPassOps.depthOps.loadLayout = m_rtLayouts.depth; + } + + + void DxvkContext::applyRenderTargetStoreLayouts() { + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) + m_rtLayouts.color[i] = m_state.om.renderPassOps.colorOps[i].storeLayout; + + m_rtLayouts.depth = m_state.om.renderPassOps.depthOps.storeLayout; + } + + + void DxvkContext::transitionRenderTargetLayouts( + DxvkBarrierSet& barriers, + bool sharedOnly) { + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { + const DxvkAttachment& color = m_state.om.framebufferInfo.getColorTarget(i); + + if (color.view != nullptr && (!sharedOnly || color.view->imageInfo().shared)) { + this->transitionColorAttachment(barriers, color, m_rtLayouts.color[i]); + m_rtLayouts.color[i] = color.view->imageInfo().layout; + } + } + + const DxvkAttachment& depth = m_state.om.framebufferInfo.getDepthTarget(); + + if (depth.view != nullptr && (!sharedOnly || depth.view->imageInfo().shared)) { + this->transitionDepthAttachment(barriers, depth, m_rtLayouts.depth); + m_rtLayouts.depth = depth.view->imageInfo().layout; + } + } + + + void DxvkContext::transitionColorAttachment( + DxvkBarrierSet& barriers, + const DxvkAttachment& attachment, + VkImageLayout oldLayout) { + if (oldLayout != attachment.view->imageInfo().layout) { + barriers.accessImage( + attachment.view->image(), + attachment.view->imageSubresources(), oldLayout, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + attachment.view->imageInfo().layout, + attachment.view->imageInfo().stages, + attachment.view->imageInfo().access); + + m_cmd->trackResource(attachment.view->image()); + } + } + + + void DxvkContext::transitionDepthAttachment( + DxvkBarrierSet& barriers, + const DxvkAttachment& attachment, + VkImageLayout oldLayout) { + if (oldLayout != attachment.view->imageInfo().layout) { + barriers.accessImage( + attachment.view->image(), + attachment.view->imageSubresources(), oldLayout, + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + oldLayout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL + ? VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT : 0, + attachment.view->imageInfo().layout, + attachment.view->imageInfo().stages, + attachment.view->imageInfo().access); + + m_cmd->trackResource(attachment.view->image()); + } + } + + + void DxvkContext::updateRenderTargetLayouts( + const DxvkFramebufferInfo& newFb, + const DxvkFramebufferInfo& oldFb) { + DxvkRenderTargetLayouts layouts = { }; + + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { + if (newFb.getColorTarget(i).view != nullptr) + layouts.color[i] = newFb.getColorTarget(i).view->imageInfo().layout; + } + + if (newFb.getDepthTarget().view != nullptr) + layouts.depth = newFb.getDepthTarget().view->imageInfo().layout; + + // Check whether any of the previous attachments have been moved + // around or been rebound with a different view. This may help + // reduce the number of image layout transitions between passes. + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { + const DxvkAttachment& oldAttachment = oldFb.getColorTarget(i); + + if (oldAttachment.view != nullptr) { + bool found = false; + + for (uint32_t j = 0; j < MaxNumRenderTargets && !found; j++) { + const DxvkAttachment& newAttachment = newFb.getColorTarget(j); + + found = newAttachment.view == oldAttachment.view || (newAttachment.view != nullptr + && newAttachment.view->image() == oldAttachment.view->image() + && newAttachment.view->subresources() == oldAttachment.view->subresources()); + + if (found) + layouts.color[j] = m_rtLayouts.color[i]; + } + + if (!found && m_flags.test(DxvkContextFlag::GpRenderPassSuspended)) + this->transitionColorAttachment(m_execBarriers, oldAttachment, m_rtLayouts.color[i]); + } + } + + const DxvkAttachment& oldAttachment = oldFb.getDepthTarget(); + + if (oldAttachment.view != nullptr) { + const DxvkAttachment& newAttachment = newFb.getDepthTarget(); + + bool found = newAttachment.view == oldAttachment.view || (newAttachment.view != nullptr + && newAttachment.view->image() == oldAttachment.view->image() + && newAttachment.view->subresources() == oldAttachment.view->subresources()); + + if (found) + layouts.depth = m_rtLayouts.depth; + else if (m_flags.test(DxvkContextFlag::GpRenderPassSuspended)) + this->transitionDepthAttachment(m_execBarriers, oldAttachment, m_rtLayouts.depth); + } + + m_rtLayouts = layouts; + } + + + void DxvkContext::prepareImage( + DxvkBarrierSet& barriers, + const Rc& image, + const VkImageSubresourceRange& subresources, + bool flushClears) { + // Images that can't be used as attachments are always in their + // default layout, so we don't have to do anything in this case + if (!(image->info().usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT))) + return; + + // Flush clears if there are any since they may affect the image + if (!m_deferredClears.empty() && flushClears) + this->spillRenderPass(false); + + // All images are in their default layout for suspended passes + if (!m_flags.test(DxvkContextFlag::GpRenderPassSuspended)) + return; + + // 3D images require special care because they only have one + // layer, but views may address individual 2D slices as layers + bool is3D = image->info().type == VK_IMAGE_TYPE_3D; + + // Transition any attachment with overlapping subresources + if (image->info().usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) { + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { + const DxvkAttachment& attachment = m_state.om.framebufferInfo.getColorTarget(i); + + if (attachment.view != nullptr && attachment.view->image() == image + && (is3D || vk::checkSubresourceRangeOverlap(attachment.view->subresources(), subresources))) { + this->transitionColorAttachment(barriers, attachment, m_rtLayouts.color[i]); + m_rtLayouts.color[i] = image->info().layout; + } + } + } else { + const DxvkAttachment& attachment = m_state.om.framebufferInfo.getDepthTarget(); + + if (attachment.view != nullptr && attachment.view->image() == image + && (is3D || vk::checkSubresourceRangeOverlap(attachment.view->subresources(), subresources))) { + this->transitionDepthAttachment(barriers, attachment, m_rtLayouts.depth); + m_rtLayouts.depth = image->info().layout; + } + } + } + + + bool DxvkContext::updateIndexBufferBinding() { + if (unlikely(!m_state.vi.indexBuffer.defined())) + return false; + + m_flags.clr(DxvkContextFlag::GpDirtyIndexBuffer); + auto bufferInfo = m_state.vi.indexBuffer.getDescriptor(); + + m_cmd->cmdBindIndexBuffer( + bufferInfo.buffer.buffer, + bufferInfo.buffer.offset, + m_state.vi.indexType); + + if (m_vbTracked.set(MaxNumVertexBindings)) + m_cmd->trackResource(m_state.vi.indexBuffer.buffer()); + + return true; + } + + + void DxvkContext::updateVertexBufferBindings() { + m_flags.clr(DxvkContextFlag::GpDirtyVertexBuffers); + + if (unlikely(!m_state.gp.state.il.bindingCount())) + return; + + std::array buffers; + std::array offsets; + std::array lengths; + + // Set buffer handles and offsets for active bindings + for (uint32_t i = 0; i < m_state.gp.state.il.bindingCount(); i++) { + uint32_t binding = m_state.gp.state.ilBindings[i].binding(); + + if (likely(m_state.vi.vertexBuffers[binding].defined())) { + auto vbo = m_state.vi.vertexBuffers[binding].getDescriptor(); + + buffers[i] = vbo.buffer.buffer; + offsets[i] = vbo.buffer.offset; + lengths[i] = vbo.buffer.range; + + if (m_vbTracked.set(binding)) + m_cmd->trackResource(m_state.vi.vertexBuffers[binding].buffer()); + } else if (m_features.test(DxvkContextFeature::NullDescriptors)) { + buffers[i] = VK_NULL_HANDLE; + offsets[i] = 0; + lengths[i] = 0; + } else { + buffers[i] = m_common->dummyResources().bufferHandle(); + offsets[i] = 0; + lengths[i] = 0; + } + } + + // Vertex bindigs get remapped when compiling the + // pipeline, so this actually does the right thing + if (m_features.test(DxvkContextFeature::ExtendedDynamicState)) { + m_cmd->cmdBindVertexBuffers2(0, m_state.gp.state.il.bindingCount(), + buffers.data(), offsets.data(), lengths.data(), nullptr); + } else { + m_cmd->cmdBindVertexBuffers(0, m_state.gp.state.il.bindingCount(), + buffers.data(), offsets.data()); + } + } + + + void DxvkContext::updateTransformFeedbackBuffers() { + const auto& gsInfo = m_state.gp.shaders.gs->info(); + + VkBuffer xfbBuffers[MaxNumXfbBuffers]; + VkDeviceSize xfbOffsets[MaxNumXfbBuffers]; + VkDeviceSize xfbLengths[MaxNumXfbBuffers]; + + for (size_t i = 0; i < MaxNumXfbBuffers; i++) { + auto physSlice = m_state.xfb.buffers[i].getSliceHandle(); + + xfbBuffers[i] = physSlice.handle; + xfbOffsets[i] = physSlice.offset; + xfbLengths[i] = physSlice.length; + + if (physSlice.handle == VK_NULL_HANDLE) + xfbBuffers[i] = m_common->dummyResources().bufferHandle(); + + if (physSlice.handle != VK_NULL_HANDLE) { + const Rc& buffer = m_state.xfb.buffers[i].buffer(); + buffer->setXfbVertexStride(gsInfo.xfbStrides[i]); + + m_cmd->trackResource(buffer); + } + } + + m_cmd->cmdBindTransformFeedbackBuffers( + 0, MaxNumXfbBuffers, + xfbBuffers, xfbOffsets, xfbLengths); + } + + + void DxvkContext::updateTransformFeedbackState() { + if (m_flags.test(DxvkContextFlag::GpDirtyXfbBuffers)) { + m_flags.clr(DxvkContextFlag::GpDirtyXfbBuffers); + + this->pauseTransformFeedback(); + this->updateTransformFeedbackBuffers(); + } + + this->startTransformFeedback(); + } + + + void DxvkContext::updateDynamicState() { + if (!m_gpActivePipeline) + return; + + if (m_flags.test(DxvkContextFlag::GpDirtyViewport)) { + m_flags.clr(DxvkContextFlag::GpDirtyViewport); + + uint32_t viewportCount = m_state.gp.state.rs.viewportCount(); + m_cmd->cmdSetViewport(0, viewportCount, m_state.vp.viewports.data()); + m_cmd->cmdSetScissor (0, viewportCount, m_state.vp.scissorRects.data()); + } + + if (m_flags.all(DxvkContextFlag::GpDirtyBlendConstants, + DxvkContextFlag::GpDynamicBlendConstants)) { + m_flags.clr(DxvkContextFlag::GpDirtyBlendConstants); + m_cmd->cmdSetBlendConstants(&m_state.dyn.blendConstants.r); + } + + if (m_flags.all(DxvkContextFlag::GpDirtyStencilRef, + DxvkContextFlag::GpDynamicStencilRef)) { + m_flags.clr(DxvkContextFlag::GpDirtyStencilRef); + + m_cmd->cmdSetStencilReference( + VK_STENCIL_FRONT_AND_BACK, + m_state.dyn.stencilReference); + } + + if (m_flags.all(DxvkContextFlag::GpDirtyDepthBias, + DxvkContextFlag::GpDynamicDepthBias)) { + m_flags.clr(DxvkContextFlag::GpDirtyDepthBias); + + m_cmd->cmdSetDepthBias( + m_state.dyn.depthBias.depthBiasConstant, + m_state.dyn.depthBias.depthBiasClamp, + m_state.dyn.depthBias.depthBiasSlope); + } + + if (m_flags.all(DxvkContextFlag::GpDirtyDepthBounds, + DxvkContextFlag::GpDynamicDepthBounds)) { + m_flags.clr(DxvkContextFlag::GpDirtyDepthBounds); + + m_cmd->cmdSetDepthBounds( + m_state.dyn.depthBounds.minDepthBounds, + m_state.dyn.depthBounds.maxDepthBounds); + } + } + + + template + void DxvkContext::updatePushConstants() { + m_flags.clr(DxvkContextFlag::DirtyPushConstants); + + auto layout = BindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS + ? m_state.gp.pipeline->layout() + : m_state.cp.pipeline->layout(); + + if (!layout) + return; + + VkPushConstantRange pushConstRange = layout->pushConstRange(); + if (!pushConstRange.size) + return; + + m_cmd->cmdPushConstants( + layout->pipelineLayout(), + pushConstRange.stageFlags, + pushConstRange.offset, + pushConstRange.size, + &m_state.pc.data[pushConstRange.offset]); + } + + + bool DxvkContext::commitComputeState() { + this->spillRenderPass(false); + + if (m_flags.test(DxvkContextFlag::CpDirtyPipeline)) { + if (unlikely(!this->updateComputePipeline())) + return false; + } + + if (m_flags.any( + DxvkContextFlag::CpDirtyResources, + DxvkContextFlag::CpDirtyDescriptorBinding)) + this->updateComputeShaderResources(); + + if (m_flags.test(DxvkContextFlag::CpDirtyPipelineState)) { + if (unlikely(!this->updateComputePipelineState())) + return false; + } + + if (m_flags.test(DxvkContextFlag::DirtyPushConstants)) + this->updatePushConstants(); + + return true; + } + + + template + bool DxvkContext::commitGraphicsState() { + if (m_flags.test(DxvkContextFlag::GpDirtyPipeline)) { + if (unlikely(!this->updateGraphicsPipeline())) + return false; + } + + if (m_state.gp.flags.any(DxvkGraphicsPipelineFlag::HasStorageDescriptors, + DxvkGraphicsPipelineFlag::HasTransformFeedback)) { + this->commitGraphicsBarriers(); + this->commitGraphicsBarriers(); + } + + if (m_flags.test(DxvkContextFlag::GpDirtyFramebuffer)) + this->updateFramebuffer(); + + if (!m_flags.test(DxvkContextFlag::GpRenderPassBound)) + this->startRenderPass(); + + if (m_flags.test(DxvkContextFlag::GpDirtyIndexBuffer) && Indexed) { + if (unlikely(!this->updateIndexBufferBinding())) + return false; + } + + if (m_flags.test(DxvkContextFlag::GpDirtyVertexBuffers)) + this->updateVertexBufferBindings(); + + if (m_flags.any( + DxvkContextFlag::GpDirtyResources, + DxvkContextFlag::GpDirtyDescriptorBinding)) + this->updateGraphicsShaderResources(); + + if (m_flags.test(DxvkContextFlag::GpDirtyPipelineState)) { + if (unlikely(!this->updateGraphicsPipelineState())) + return false; + } + + if (m_state.gp.flags.test(DxvkGraphicsPipelineFlag::HasTransformFeedback)) + this->updateTransformFeedbackState(); + + if (m_flags.any( + DxvkContextFlag::GpDirtyViewport, + DxvkContextFlag::GpDirtyBlendConstants, + DxvkContextFlag::GpDirtyStencilRef, + DxvkContextFlag::GpDirtyDepthBias, + DxvkContextFlag::GpDirtyDepthBounds)) + this->updateDynamicState(); + + if (m_flags.test(DxvkContextFlag::DirtyPushConstants)) + this->updatePushConstants(); + + if (m_flags.test(DxvkContextFlag::DirtyDrawBuffer) && Indirect) + this->trackDrawBuffer(); + + return true; + } + + + void DxvkContext::commitComputeInitBarriers() { + auto layout = m_state.cp.pipeline->layout(); + + bool requiresBarrier = false; + + for (uint32_t i = 0; i < layout->bindingCount() && !requiresBarrier; i++) { + if (m_state.cp.state.bsBindingMask.test(i)) { + const DxvkDescriptorSlot binding = layout->binding(i); + const DxvkShaderResourceSlot& slot = m_rc[binding.slot]; + + DxvkAccessFlags dstAccess = DxvkBarrierSet::getAccessTypes(binding.access); + DxvkAccessFlags srcAccess = 0; + + switch (binding.type) { + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: + srcAccess = m_execBarriers.getBufferAccess( + slot.bufferSlice.getSliceHandle()); + break; + + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: + srcAccess = m_execBarriers.getBufferAccess( + slot.bufferView->getSliceHandle()); + break; + + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + srcAccess = m_execBarriers.getImageAccess( + slot.imageView->image(), + slot.imageView->imageSubresources()); + break; + + default: + /* nothing to do */; + } + + if (srcAccess == 0) + continue; + + // Skip write-after-write barriers if explicitly requested + VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT + | VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT; + + if ((m_barrierControl.test(DxvkBarrierControl::IgnoreWriteAfterWrite)) + && (!(m_execBarriers.getSrcStages() & ~stageMask)) + && ((srcAccess | dstAccess) == DxvkAccess::Write)) + continue; + + requiresBarrier = (srcAccess | dstAccess).test(DxvkAccess::Write); + } + } + + if (requiresBarrier) + m_execBarriers.recordCommands(m_cmd); + } + + + void DxvkContext::commitComputePostBarriers() { + auto layout = m_state.cp.pipeline->layout(); + + for (uint32_t i = 0; i < layout->bindingCount(); i++) { + if (m_state.cp.state.bsBindingMask.test(i)) { + const DxvkDescriptorSlot binding = layout->binding(i); + const DxvkShaderResourceSlot& slot = m_rc[binding.slot]; + + VkPipelineStageFlags stages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; + VkAccessFlags access = binding.access; + + switch (binding.type) { + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: + m_execBarriers.accessBuffer( + slot.bufferSlice.getSliceHandle(), + stages, access, + slot.bufferSlice.bufferInfo().stages, + slot.bufferSlice.bufferInfo().access); + break; + + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: + m_execBarriers.accessBuffer( + slot.bufferView->getSliceHandle(), + stages, access, + slot.bufferView->bufferInfo().stages, + slot.bufferView->bufferInfo().access); + break; + + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + m_execBarriers.accessImage( + slot.imageView->image(), + slot.imageView->imageSubresources(), + slot.imageView->imageInfo().layout, + stages, access, + slot.imageView->imageInfo().layout, + slot.imageView->imageInfo().stages, + slot.imageView->imageInfo().access); + break; + + default: + /* nothing to do */; + } + } + } + } + + + template + void DxvkContext::commitGraphicsBarriers() { + if (m_barrierControl.test(DxvkBarrierControl::IgnoreGraphicsBarriers)) + return; + + auto layout = m_state.gp.pipeline->layout(); + + constexpr auto storageBufferAccess = VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT; + constexpr auto storageImageAccess = VK_ACCESS_SHADER_WRITE_BIT; + + bool requiresBarrier = false; + + // Check the draw buffer for indirect draw calls + if (m_flags.test(DxvkContextFlag::DirtyDrawBuffer) && Indirect) { + std::array slices = {{ + &m_state.id.argBuffer, + &m_state.id.cntBuffer, + }}; + + for (uint32_t i = 0; i < slices.size() && !requiresBarrier; i++) { + if ((slices[i]->defined()) + && (slices[i]->bufferInfo().access & storageBufferAccess)) { + requiresBarrier = this->checkGfxBufferBarrier(*slices[i], + VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, + VK_ACCESS_INDIRECT_COMMAND_READ_BIT).test(DxvkAccess::Write); + } + } + } + + // Read-only stage, so we only have to check this if + // the bindngs have actually changed between draws + if (m_flags.test(DxvkContextFlag::GpDirtyIndexBuffer) && !requiresBarrier && Indexed) { + const auto& indexBufferSlice = m_state.vi.indexBuffer; + + if ((indexBufferSlice.defined()) + && (indexBufferSlice.bufferInfo().access & storageBufferAccess)) { + requiresBarrier = this->checkGfxBufferBarrier(indexBufferSlice, + VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, + VK_ACCESS_INDEX_READ_BIT).test(DxvkAccess::Write); + } + } + + // Same here, also ignore unused vertex bindings + if (m_flags.test(DxvkContextFlag::GpDirtyVertexBuffers)) { + uint32_t bindingCount = m_state.gp.state.il.bindingCount(); + + for (uint32_t i = 0; i < bindingCount && !requiresBarrier; i++) { + uint32_t binding = m_state.gp.state.ilBindings[i].binding(); + const auto& vertexBufferSlice = m_state.vi.vertexBuffers[binding]; + + if ((vertexBufferSlice.defined()) + && (vertexBufferSlice.bufferInfo().access & storageBufferAccess)) { + requiresBarrier = this->checkGfxBufferBarrier(vertexBufferSlice, + VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, + VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT).test(DxvkAccess::Write); + } + } + } + + // Transform feedback buffer writes won't overlap, so we + // also only need to check those when they are rebound + if (m_flags.test(DxvkContextFlag::GpDirtyXfbBuffers) + && m_state.gp.flags.test(DxvkGraphicsPipelineFlag::HasTransformFeedback)) { + for (uint32_t i = 0; i < MaxNumXfbBuffers && !requiresBarrier; i++) { + const auto& xfbBufferSlice = m_state.xfb.buffers[i]; + const auto& xfbCounterSlice = m_state.xfb.counters[i]; + + if (xfbBufferSlice.defined()) { + requiresBarrier = this->checkGfxBufferBarrier(xfbBufferSlice, + VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, + VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT) != 0; + + if (xfbCounterSlice.defined()) { + requiresBarrier |= this->checkGfxBufferBarrier(xfbCounterSlice, + VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT | + VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, + VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT | + VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT) != 0; + } + } + } + } + + // Check shader resources on every draw to handle WAW hazards + for (uint32_t i = 0; i < layout->bindingCount() && !requiresBarrier; i++) { + const DxvkDescriptorSlot binding = layout->binding(i); + const DxvkShaderResourceSlot& slot = m_rc[binding.slot]; + + DxvkAccessFlags dstAccess = DxvkBarrierSet::getAccessTypes(binding.access); + DxvkAccessFlags srcAccess = 0; + + switch (binding.type) { + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: + if ((slot.bufferSlice.defined()) + && (slot.bufferSlice.bufferInfo().access & storageBufferAccess)) { + srcAccess = this->checkGfxBufferBarrier(slot.bufferSlice, + util::pipelineStages(binding.stages), binding.access); + } + break; + + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: + if ((slot.bufferView != nullptr) + && (slot.bufferView->bufferInfo().access & storageBufferAccess)) { + srcAccess = this->checkGfxBufferBarrier(slot.bufferView->slice(), + util::pipelineStages(binding.stages), binding.access); + } + break; + + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + if ((slot.imageView != nullptr) + && (slot.imageView->imageInfo().access & storageImageAccess)) { + srcAccess = this->checkGfxImageBarrier(slot.imageView, + util::pipelineStages(binding.stages), binding.access); + } + break; + + default: + /* nothing to do */; + } + + if (srcAccess == 0) + continue; + + // Skip write-after-write barriers if explicitly requested + if ((m_barrierControl.test(DxvkBarrierControl::IgnoreWriteAfterWrite)) + && ((srcAccess | dstAccess) == DxvkAccess::Write)) + continue; + + requiresBarrier = (srcAccess | dstAccess).test(DxvkAccess::Write); + } + + // External subpass dependencies serve as full memory + // and execution barriers, so we can use this to allow + // inter-stage synchronization. + if (requiresBarrier) + this->spillRenderPass(true); + } + + + template + DxvkAccessFlags DxvkContext::checkGfxBufferBarrier( + const DxvkBufferSlice& slice, + VkPipelineStageFlags stages, + VkAccessFlags access) { + if constexpr (DoEmit) { + m_gfxBarriers.accessBuffer( + slice.getSliceHandle(), + stages, access, + slice.bufferInfo().stages, + slice.bufferInfo().access); + return DxvkAccessFlags(); + } else { + return m_gfxBarriers.getBufferAccess(slice.getSliceHandle()); + } + } + + + template + DxvkAccessFlags DxvkContext::checkGfxImageBarrier( + const Rc& imageView, + VkPipelineStageFlags stages, + VkAccessFlags access) { + if constexpr (DoEmit) { + m_gfxBarriers.accessImage( + imageView->image(), + imageView->imageSubresources(), + imageView->imageInfo().layout, + stages, access, + imageView->imageInfo().layout, + imageView->imageInfo().stages, + imageView->imageInfo().access); + return DxvkAccessFlags(); + } else { + return m_gfxBarriers.getImageAccess( + imageView->image(), + imageView->imageSubresources()); + } + } + + + void DxvkContext::emitMemoryBarrier( + VkDependencyFlags flags, + VkPipelineStageFlags srcStages, + VkAccessFlags srcAccess, + VkPipelineStageFlags dstStages, + VkAccessFlags dstAccess) { + VkMemoryBarrier barrier; + barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; + barrier.pNext = nullptr; + barrier.srcAccessMask = srcAccess; + barrier.dstAccessMask = dstAccess; + + m_cmd->cmdPipelineBarrier( + DxvkCmdBuffer::ExecBuffer, srcStages, dstStages, + flags, 1, &barrier, 0, nullptr, 0, nullptr); + + m_cmd->addStatCtr(DxvkStatCounter::CmdBarrierCount, 1); + } + + + VkDescriptorSet DxvkContext::allocateDescriptorSet( + VkDescriptorSetLayout layout) { + if (m_descPool == nullptr) + m_descPool = m_device->createDescriptorPool(); + + VkDescriptorSet set = m_descPool->alloc(layout); + + if (set == VK_NULL_HANDLE) { + m_cmd->trackDescriptorPool(std::move(m_descPool)); + + m_descPool = m_device->createDescriptorPool(); + set = m_descPool->alloc(layout); + } + + return set; + } + + + void DxvkContext::trackDrawBuffer() { + if (m_flags.test(DxvkContextFlag::DirtyDrawBuffer)) { + m_flags.clr(DxvkContextFlag::DirtyDrawBuffer); + + if (m_state.id.argBuffer.defined()) + m_cmd->trackResource(m_state.id.argBuffer.buffer()); + + if (m_state.id.cntBuffer.defined()) + m_cmd->trackResource(m_state.id.cntBuffer.buffer()); + } + } + + + bool DxvkContext::tryInvalidateDeviceLocalBuffer( + const Rc& buffer, + VkDeviceSize copySize) { + // We can only discard if the full buffer gets written, and we will only discard + // small buffers in order to not waste significant amounts of memory. + if (copySize != buffer->info().size || copySize > 0x40000) + return false; + + // Don't discard host-visible buffers since that may interfere with the frontend + if (buffer->memFlags() & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) + return false; + + // Suspend the current render pass if transform feedback is active prior to + // invalidating the buffer, since otherwise we may invalidate a bound buffer. + if ((buffer->info().usage & VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT) + && (m_flags.test(DxvkContextFlag::GpXfbActive))) + this->spillRenderPass(true); + + this->invalidateBuffer(buffer, buffer->allocSlice()); + return true; + } + + + DxvkGraphicsPipeline* DxvkContext::lookupGraphicsPipeline( + const DxvkGraphicsPipelineShaders& shaders) { + auto idx = shaders.hash() % m_gpLookupCache.size(); + + if (unlikely(!m_gpLookupCache[idx] || !shaders.eq(m_gpLookupCache[idx]->shaders()))) + m_gpLookupCache[idx] = m_common->pipelineManager().createGraphicsPipeline(shaders); + + return m_gpLookupCache[idx]; + } + + + DxvkComputePipeline* DxvkContext::lookupComputePipeline( + const DxvkComputePipelineShaders& shaders) { + auto idx = shaders.hash() % m_cpLookupCache.size(); + + if (unlikely(!m_cpLookupCache[idx] || !shaders.eq(m_cpLookupCache[idx]->shaders()))) + m_cpLookupCache[idx] = m_common->pipelineManager().createComputePipeline(shaders); + + return m_cpLookupCache[idx]; + } + + + Rc DxvkContext::lookupFramebuffer( + const DxvkFramebufferInfo& framebufferInfo) { + DxvkFramebufferKey key = framebufferInfo.key(); + size_t idx = key.hash() % m_framebufferCache.size(); + + if (m_framebufferCache[idx] == nullptr || !m_framebufferCache[idx]->key().eq(key)) + m_framebufferCache[idx] = m_device->createFramebuffer(framebufferInfo); + + return m_framebufferCache[idx]; + } + + + Rc DxvkContext::createZeroBuffer( + VkDeviceSize size) { + if (m_zeroBuffer != nullptr && m_zeroBuffer->info().size >= size) + return m_zeroBuffer; + + DxvkBufferCreateInfo bufInfo; + bufInfo.size = align(size, 1 << 20); + bufInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + bufInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT; + bufInfo.access = VK_ACCESS_TRANSFER_WRITE_BIT + | VK_ACCESS_TRANSFER_READ_BIT; + + m_zeroBuffer = m_device->createBuffer(bufInfo, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + + this->initBuffer(m_zeroBuffer); + return m_zeroBuffer; + } + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_context.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_context.h new file mode 100644 index 00000000000..c5547c1d82d --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_context.h @@ -0,0 +1,1344 @@ +#pragma once + +#include "dxvk_barrier.h" +#include "dxvk_bind_mask.h" +#include "dxvk_cmdlist.h" +#include "dxvk_context_state.h" +#include "dxvk_data.h" +#include "dxvk_objects.h" +#include "dxvk_resource.h" +#include "dxvk_util.h" + +namespace dxvk { + + /** + * \brief DXVk context + * + * Tracks pipeline state and records command lists. + * This is where the actual rendering commands are + * recorded. + */ + class DxvkContext : public RcObject { + constexpr static VkDeviceSize StagingBufferSize = 4ull << 20; + public: + + DxvkContext(const Rc& device); + ~DxvkContext(); + + /** + * \brief Begins command buffer recording + * + * Begins recording a command list. This does + * not alter any context state other than the + * active command list. + * \param [in] cmdList Target command list + */ + void beginRecording( + const Rc& cmdList); + + /** + * \brief Ends command buffer recording + * + * Finishes recording the active command list. + * The command list can then be submitted to + * the device. + * + * This will not change any context state + * other than the active command list. + * \returns Active command list + */ + Rc endRecording(); + + /** + * \brief Flushes command buffer + * + * Transparently submits the current command + * buffer and allocates a new one. + */ + void flushCommandList(); + + /** + * \brief Begins generating query data + * \param [in] query The query to end + */ + void beginQuery( + const Rc& query); + + /** + * \brief Ends generating query data + * \param [in] query The query to end + */ + void endQuery( + const Rc& query); + + /** + * \brief Sets render targets + * + * Creates a framebuffer on the fly if necessary + * and binds it using \c bindFramebuffer. + * \param [in] targets Render targets to bind + */ + void bindRenderTargets( + const DxvkRenderTargets& targets); + + /** + * \brief Binds indirect argument buffer + * + * Sets the buffers that are going to be used + * for indirect draw and dispatch operations. + * \param [in] argBuffer New argument buffer + * \param [in] cntBuffer New count buffer + */ + void bindDrawBuffers( + const DxvkBufferSlice& argBuffer, + const DxvkBufferSlice& cntBuffer); + + /** + * \brief Binds index buffer + * + * The index buffer will be used when + * issuing \c drawIndexed commands. + * \param [in] buffer New index buffer + * \param [in] indexType Index type + */ + void bindIndexBuffer( + const DxvkBufferSlice& buffer, + VkIndexType indexType); + + /** + * \brief Binds buffer as a shader resource + * + * Can be used for uniform and storage buffers. + * \param [in] slot Resource binding slot + * \param [in] buffer Buffer to bind + */ + void bindResourceBuffer( + uint32_t slot, + const DxvkBufferSlice& buffer); + + /** + * \brief Binds image or buffer view + * + * Can be used for sampled images with a dedicated + * sampler and for storage images, as well as for + * uniform texel buffers and storage texel buffers. + * \param [in] slot Resource binding slot + * \param [in] imageView Image view to bind + * \param [in] bufferView Buffer view to bind + */ + void bindResourceView( + uint32_t slot, + const Rc& imageView, + const Rc& bufferView); + + /** + * \brief Binds image sampler + * + * Binds a sampler that can be used together with + * an image in order to read from a texture. + * \param [in] slot Resource binding slot + * \param [in] sampler Sampler view to bind + */ + void bindResourceSampler( + uint32_t slot, + const Rc& sampler); + + /** + * \brief Binds a shader to a given state + * + * \param [in] stage Target shader stage + * \param [in] shader The shader to bind + */ + void bindShader( + VkShaderStageFlagBits stage, + const Rc& shader); + + /** + * \brief Binds vertex buffer + * + * When binding a null buffer, stride must be 0. + * \param [in] binding Vertex buffer binding + * \param [in] buffer New vertex buffer + * \param [in] stride Stride between vertices + */ + void bindVertexBuffer( + uint32_t binding, + const DxvkBufferSlice& buffer, + uint32_t stride); + + /** + * \brief Binds transform feedback buffer + * + * \param [in] binding Xfb buffer binding + * \param [in] buffer The buffer to bind + * \param [in] counter Xfb counter buffer + */ + void bindXfbBuffer( + uint32_t binding, + const DxvkBufferSlice& buffer, + const DxvkBufferSlice& counter); + + /** + * \brief Blits an image + * + * \param [in] dstImage Destination image + * \param [in] dstMapping Destination swizzle + * \param [in] srcImage Source image + * \param [in] srcMapping Source swizzle + * \param [in] region Blit region + * \param [in] filter Texture filter + */ + void blitImage( + const Rc& dstImage, + const VkComponentMapping& dstMapping, + const Rc& srcImage, + const VkComponentMapping& srcMapping, + const VkImageBlit& region, + VkFilter filter); + + /** + * \brief Changes image layout + * + * Permanently changes the layout for a given + * image. Immediately performs the transition. + * \param [in] image The image to transition + * \param [in] layout New image layout + */ + void changeImageLayout( + const Rc& image, + VkImageLayout layout); + + /** + * \brief Clears a buffer with a fixed value + * + * Note that both \c offset and \c length must + * be multiples of four, and that \c value is + * consumed as a four-byte word. + * \param [in] buffer The buffer to clear + * \param [in] offset Offset of the range to clear + * \param [in] length Bumber of bytes to clear + * \param [in] value Clear value + */ + void clearBuffer( + const Rc& buffer, + VkDeviceSize offset, + VkDeviceSize length, + uint32_t value); + + /** + * \brief Clears a buffer view + * + * Unlike \c clearBuffer, this method can be used + * to clear a buffer view with format conversion. + * \param [in] bufferView The buffer view + * \param [in] offset Offset of the region to clear + * \param [in] length Extent of the region to clear + * \param [in] value The clear value + */ + void clearBufferView( + const Rc& bufferView, + VkDeviceSize offset, + VkDeviceSize length, + VkClearColorValue value); + + /** + * \brief Clears an active render target + * + * \param [in] imageView Render target view to clear + * \param [in] clearAspects Image aspects to clear + * \param [in] clearValue The clear value + */ + void clearRenderTarget( + const Rc& imageView, + VkImageAspectFlags clearAspects, + VkClearValue clearValue); + + /** + * \brief Clears an image view + * + * Can be used to clear sub-regions of storage images + * that are not going to be used as render targets. + * Implicit format conversion will be applied. + * \param [in] imageView The image view + * \param [in] offset Offset of the rect to clear + * \param [in] extent Extent of the rect to clear + * \param [in] aspect Aspect mask to clear + * \param [in] value The clear value + */ + void clearImageView( + const Rc& imageView, + VkOffset3D offset, + VkExtent3D extent, + VkImageAspectFlags aspect, + VkClearValue value); + + /** + * \brief Copies data from one buffer to another + * + * \param [in] dstBuffer Destination buffer + * \param [in] dstOffset Destination data offset + * \param [in] srcBuffer Source buffer + * \param [in] srcOffset Source data offset + * \param [in] numBytes Number of bytes to copy + */ + void copyBuffer( + const Rc& dstBuffer, + VkDeviceSize dstOffset, + const Rc& srcBuffer, + VkDeviceSize srcOffset, + VkDeviceSize numBytes); + + /** + * \brief Copies overlapping buffer region + * + * Can be used to copy potentially overlapping + * buffer regions within the same buffer. If + * the source and destination regions do not + * overlap, it will behave as \ref copyBuffer. + * \param [in] dstBuffer The buffer + * \param [in] dstOffset Offset of target region + * \param [in] srcOffset Offset of source region + * \param [in] numBytes Number of bytes to copy + */ + void copyBufferRegion( + const Rc& dstBuffer, + VkDeviceSize dstOffset, + VkDeviceSize srcOffset, + VkDeviceSize numBytes); + + /** + * \brief Copies data from a buffer to an image + * + * Source data must be packed, except for the row alignment. + * \param [in] dstImage Destination image + * \param [in] dstSubresource Destination subresource + * \param [in] dstOffset Destination area offset + * \param [in] dstExtent Destination area size + * \param [in] srcBuffer Source buffer + * \param [in] srcOffset Source offset, in bytes + * \param [in] rowAlignment Row alignment, in bytes + * \param [in] sliceAlignment Slice alignment, in bytes + */ + void copyBufferToImage( + const Rc& dstImage, + VkImageSubresourceLayers dstSubresource, + VkOffset3D dstOffset, + VkExtent3D dstExtent, + const Rc& srcBuffer, + VkDeviceSize srcOffset, + VkDeviceSize rowAlignment, + VkDeviceSize sliceAlignment); + + /** + * \brief Copies data from one image to another + * + * \param [in] dstImage Destination image + * \param [in] dstSubresource Destination subresource + * \param [in] dstOffset Destination area offset + * \param [in] srcImage Source image + * \param [in] srcSubresource Source subresource + * \param [in] srcOffset Source area offset + * \param [in] extent Size of the area to copy + */ + void copyImage( + const Rc& dstImage, + VkImageSubresourceLayers dstSubresource, + VkOffset3D dstOffset, + const Rc& srcImage, + VkImageSubresourceLayers srcSubresource, + VkOffset3D srcOffset, + VkExtent3D extent); + + /** + * \brief Copies overlapping image region + * + * \param [in] dstImage The image + * \param [in] dstSubresource The image subresource + * \param [in] dstOffset Destination region offset + * \param [in] srcOffset Source region offset + * \param [in] extent Size of the copy region + */ + void copyImageRegion( + const Rc& dstImage, + VkImageSubresourceLayers dstSubresource, + VkOffset3D dstOffset, + VkOffset3D srcOffset, + VkExtent3D extent); + + /** + * \brief Copies data from an image into a buffer + * + * \param [in] dstBuffer Destination buffer + * \param [in] dstOffset Destination offset, in bytes + * \param [in] dstExtent Destination data extent + * \param [in] rowAlignment Row alignment, in bytes + * \param [in] sliceAlignment Slice alignment, in bytes + * \param [in] srcImage Source image + * \param [in] srcSubresource Source subresource + * \param [in] srcOffset Source area offset + * \param [in] srcExtent Source area size + */ + void copyImageToBuffer( + const Rc& dstBuffer, + VkDeviceSize dstOffset, + VkDeviceSize rowAlignment, + VkDeviceSize sliceAlignment, + const Rc& srcImage, + VkImageSubresourceLayers srcSubresource, + VkOffset3D srcOffset, + VkExtent3D srcExtent); + + /** + * \brief Packs depth-stencil image data to a buffer + * + * Packs data from both the depth and stencil aspects + * of an image into a buffer. The supported formats are: + * - \c VK_FORMAT_D24_UNORM_S8_UINT: 0xssdddddd + * - \c VK_FORMAT_D32_SFLOAT_S8_UINT: 0xdddddddd 0x000000ss + * \param [in] dstBuffer Destination buffer + * \param [in] dstBufferOffset Destination offset, in bytes + * \param [in] dstOffset Destination image offset + * \param [in] dstSize Destination image size + * \param [in] srcImage Source image + * \param [in] srcSubresource Source subresource + * \param [in] srcOffset Source area offset + * \param [in] srcExtent Source area size + * \param [in] format Packed data format + */ + void copyDepthStencilImageToPackedBuffer( + const Rc& dstBuffer, + VkDeviceSize dstBufferOffset, + VkOffset2D dstOffset, + VkExtent2D dstExtent, + const Rc& srcImage, + VkImageSubresourceLayers srcSubresource, + VkOffset2D srcOffset, + VkExtent2D srcExtent, + VkFormat format); + + /** + * \brief Copies image data stored in a linear buffer to another + * + * The source and destination regions may overlap, in which case + * a temporary copy of the source buffer will be created. + * \param [in] dstBuffer Destination buffer + * \param [in] dstBufferOffset Destination subresource offset + * \param [in] dstOffset Destination image offset + * \param [in] dstSize Total size of the destination image + * \param [in] srcBuffer Source buffer + * \param [in] srcBufferOffset Source subresource offset + * \param [in] srcOffset Source image offset + * \param [in] srcSize Total size of the source image + * \param [in] extent Number of pixels to copy + * \param [in] elementSize Pixel size, in bytes + */ + void copyPackedBufferImage( + const Rc& dstBuffer, + VkDeviceSize dstBufferOffset, + VkOffset3D dstOffset, + VkExtent3D dstSize, + const Rc& srcBuffer, + VkDeviceSize srcBufferOffset, + VkOffset3D srcOffset, + VkExtent3D srcSize, + VkExtent3D extent, + VkDeviceSize elementSize); + + /** + * \brief Unpacks buffer data to a depth-stencil image + * + * Writes the packed depth-stencil data to an image. + * See \ref copyDepthStencilImageToPackedBuffer for + * which formats are supported and how they are packed. + * \param [in] dstImage Destination image + * \param [in] dstSubresource Destination subresource + * \param [in] dstOffset Image area offset + * \param [in] dstExtent Image area size + * \param [in] srcBuffer Packed data buffer + * \param [in] srcBufferOffset Buffer offset of source image + * \param [in] srcOffset Offset into the source image + * \param [in] srcExtent Total size of the source image + * \param [in] format Packed data format + */ + void copyPackedBufferToDepthStencilImage( + const Rc& dstImage, + VkImageSubresourceLayers dstSubresource, + VkOffset2D dstOffset, + VkExtent2D dstExtent, + const Rc& srcBuffer, + VkDeviceSize srcBufferOffset, + VkOffset2D srcOffset, + VkExtent2D srcExtent, + VkFormat format); + + /** + * \brief Discards a buffer + * + * Renames the buffer in case it is currently + * used by the GPU in order to avoid having to + * insert barriers before future commands using + * the buffer. + * \param [in] buffer The buffer to discard + */ + void discardBuffer( + const Rc& buffer); + + /** + * \brief Discards contents of an image view + * + * Discards the current contents of the image + * and performs a fast layout transition. This + * may improve performance in some cases. + * \param [in] imageView View to discard + * \param [in] discardAspects Image aspects to discard + */ + void discardImageView( + const Rc& imageView, + VkImageAspectFlags discardAspects); + + /** + * \brief Starts compute jobs + * + * \param [in] x Number of threads in X direction + * \param [in] y Number of threads in Y direction + * \param [in] z Number of threads in Z direction + */ + void dispatch( + uint32_t x, + uint32_t y, + uint32_t z); + + /** + * \brief Indirect dispatch call + * + * Takes arguments from a buffer. The buffer must contain + * a structure of the type \c VkDispatchIndirectCommand. + * \param [in] offset Draw buffer offset + */ + void dispatchIndirect( + VkDeviceSize offset); + + /** + * \brief Draws primitive without using an index buffer + * + * \param [in] vertexCount Number of vertices to draw + * \param [in] instanceCount Number of instances to render + * \param [in] firstVertex First vertex in vertex buffer + * \param [in] firstInstance First instance ID + */ + void draw( + uint32_t vertexCount, + uint32_t instanceCount, + uint32_t firstVertex, + uint32_t firstInstance); + + /** + * \brief Indirect draw call + * + * Takes arguments from a buffer. The structure stored + * in the buffer must be of type \c VkDrawIndirectCommand. + * \param [in] offset Draw buffer offset + * \param [in] count Number of draws + * \param [in] stride Stride between dispatch calls + */ + void drawIndirect( + VkDeviceSize offset, + uint32_t count, + uint32_t stride); + + /** + * \brief Indirect draw call + * + * Takes arguments from a buffer. The structure stored + * in the buffer must be of type \c VkDrawIndirectCommand. + * \param [in] offset Draw buffer offset + * \param [in] countOffset Draw count offset + * \param [in] maxCount Maximum number of draws + * \param [in] stride Stride between dispatch calls + */ + void drawIndirectCount( + VkDeviceSize offset, + VkDeviceSize countOffset, + uint32_t maxCount, + uint32_t stride); + + /** + * \brief Draws primitives using an index buffer + * + * \param [in] indexCount Number of indices to draw + * \param [in] instanceCount Number of instances to render + * \param [in] firstIndex First index within the index buffer + * \param [in] vertexOffset Vertex ID that corresponds to index 0 + * \param [in] firstInstance First instance ID + */ + void drawIndexed( + uint32_t indexCount, + uint32_t instanceCount, + uint32_t firstIndex, + uint32_t vertexOffset, + uint32_t firstInstance); + + /** + * \brief Indirect indexed draw call + * + * Takes arguments from a buffer. The structure type for + * the draw buffer is \c VkDrawIndexedIndirectCommand. + * \param [in] offset Draw buffer offset + * \param [in] count Number of draws + * \param [in] stride Stride between dispatch calls + */ + void drawIndexedIndirect( + VkDeviceSize offset, + uint32_t count, + uint32_t stride); + + /** + * \brief Indirect indexed draw call + * + * Takes arguments from a buffer. The structure type for + * the draw buffer is \c VkDrawIndexedIndirectCommand. + * \param [in] offset Draw buffer offset + * \param [in] countOffset Draw count offset + * \param [in] maxCount Maximum number of draws + * \param [in] stride Stride between dispatch calls + */ + void drawIndexedIndirectCount( + VkDeviceSize offset, + VkDeviceSize countOffset, + uint32_t maxCount, + uint32_t stride); + + /** + * \brief Transform feddback draw call + + * \param [in] counterBuffer Xfb counter buffer + * \param [in] counterDivisor Vertex stride + * \param [in] counterBias Counter bias + */ + void drawIndirectXfb( + const DxvkBufferSlice& counterBuffer, + uint32_t counterDivisor, + uint32_t counterBias); + + /** + * \brief Emits barrier for render target readback + * + * Use between draw calls if the fragment shader + * reads one of the currently bound render targets. + */ + void emitRenderTargetReadbackBarrier(); + + /** + * \brief Generates mip maps + * + * Uses blitting to generate lower mip levels from + * the top-most mip level passed to this method. + * \param [in] imageView The image to generate mips for + * \param [in] filter The filter to use for generation + */ + void generateMipmaps( + const Rc& imageView, + VkFilter filter); + + /** + * \brief Initializes a buffer + * + * Clears the given buffer to zero. Only safe to call + * if the buffer is not currently in use by the GPU. + * \param [in] buffer Buffer to clear + */ + void initBuffer( + const Rc& buffer); + + /** + * \brief Initializes an image + * + * Transitions the image into its default layout, and clears + * it to black unless the initial layout is preinitialized. + * Only safe to call if the image is not in use by the GPU. + * \param [in] image The image to initialize + * \param [in] subresources Image subresources + * \param [in] initialLayout Initial image layout + */ + void initImage( + const Rc& image, + const VkImageSubresourceRange& subresources, + VkImageLayout initialLayout); + + /** + * \brief Invalidates a buffer's contents + * + * Discards a buffer's contents by replacing the + * backing resource. This allows the host to access + * the buffer while the GPU is still accessing the + * original backing resource. + * + * \warning If the buffer is used by another context, + * invalidating it will result in undefined behaviour. + * \param [in] buffer The buffer to invalidate + * \param [in] slice New buffer slice handle + */ + void invalidateBuffer( + const Rc& buffer, + const DxvkBufferSliceHandle& slice); + + /** + * \brief Updates push constants + * + * Updates the given push constant range. + * \param [in] offset Byte offset of data to update + * \param [in] size Number of bytes to update + * \param [in] data Pointer to raw data + */ + void pushConstants( + uint32_t offset, + uint32_t size, + const void* data); + + /** + * \brief Resolves a multisampled image resource + * + * Resolves a multisampled image into a non-multisampled + * image. The subresources of both images must have the + * same size and compatible formats. + * A format can be specified for the resolve operation. + * If it is \c VK_FORMAT_UNDEFINED, the resolve operation + * will use the source image format. + * \param [in] dstImage Destination image + * \param [in] srcImage Source image + * \param [in] region Region to resolve + * \param [in] format Format for the resolve operation + */ + void resolveImage( + const Rc& dstImage, + const Rc& srcImage, + const VkImageResolve& region, + VkFormat format); + + /** + * \brief Resolves a multisampled depth-stencil resource + * + * \param [in] dstImage Destination image + * \param [in] srcImage Source image + * \param [in] region Region to resolve + * \param [in] depthMode Resolve mode for depth aspect + * \param [in] stencilMode Resolve mode for stencil aspect + */ + void resolveDepthStencilImage( + const Rc& dstImage, + const Rc& srcImage, + const VkImageResolve& region, + VkResolveModeFlagBitsKHR depthMode, + VkResolveModeFlagBitsKHR stencilMode); + + /** + * \brief Transforms image subresource layouts + * + * \param [in] dstImage Image to transform + * \param [in] dstSubresources Subresources + * \param [in] srcLayout Current layout + * \param [in] dstLayout Desired layout + */ + void transformImage( + const Rc& dstImage, + const VkImageSubresourceRange& dstSubresources, + VkImageLayout srcLayout, + VkImageLayout dstLayout); + + /** + * \brief Updates a buffer + * + * Copies data from the host into a buffer. + * \param [in] buffer Destination buffer + * \param [in] offset Offset of sub range to update + * \param [in] size Length of sub range to update + * \param [in] data Data to upload + */ + void updateBuffer( + const Rc& buffer, + VkDeviceSize offset, + VkDeviceSize size, + const void* data); + + /** + * \brief Updates an depth-stencil image + * + * \param [in] image Destination image + * \param [in] subsresources Image subresources to update + * \param [in] imageOffset Offset of the image area to update + * \param [in] imageExtent Size of the image area to update + * \param [in] data Source data + * \param [in] pitchPerRow Row pitch of the source data + * \param [in] pitchPerLayer Layer pitch of the source data + * \param [in] format Packed depth-stencil format + */ + void updateDepthStencilImage( + const Rc& image, + const VkImageSubresourceLayers& subresources, + VkOffset2D imageOffset, + VkExtent2D imageExtent, + const void* data, + VkDeviceSize pitchPerRow, + VkDeviceSize pitchPerLayer, + VkFormat format); + + /** + * \brief Uses transfer queue to initialize buffer + * + * Only safe to use if the buffer is not in use by the GPU. + * \param [in] buffer The buffer to initialize + * \param [in] data The data to copy to the buffer + */ + void uploadBuffer( + const Rc& buffer, + const void* data); + + /** + * \brief Uses transfer queue to initialize image + * + * Only safe to use if the image is not in use by the GPU. + * \param [in] image The image to initialize + * \param [in] subresources Subresources to initialize + * \param [in] data Source data + * \param [in] pitchPerRow Row pitch of the source data + * \param [in] pitchPerLayer Layer pitch of the source data + */ + void uploadImage( + const Rc& image, + const VkImageSubresourceLayers& subresources, + const void* data, + VkDeviceSize pitchPerRow, + VkDeviceSize pitchPerLayer); + + /** + * \brief Sets viewports + * + * \param [in] viewportCount Number of viewports + * \param [in] viewports The viewports + * \param [in] scissorRects Schissor rectangles + */ + void setViewports( + uint32_t viewportCount, + const VkViewport* viewports, + const VkRect2D* scissorRects); + + /** + * \brief Sets blend constants + * + * Blend constants are a set of four floating + * point numbers that may be used as an input + * for blending operations. + * \param [in] blendConstants Blend constants + */ + void setBlendConstants( + DxvkBlendConstants blendConstants); + + /** + * \brief Sets depth bias + * + * Depth bias has to be enabled explicitly in + * the rasterizer state to have any effect. + * \param [in] depthBias Depth bias values + */ + void setDepthBias( + DxvkDepthBias depthBias); + + /** + * \brief Sets depth bounds + * + * Enables or disables the depth bounds test, + * and updates the values if necessary. + * \param [in] depthBounds Depth bounds + */ + void setDepthBounds( + DxvkDepthBounds depthBounds); + + /** + * \brief Sets stencil reference + * + * Sets the reference value for stencil compare operations. + * \param [in] reference Reference value + */ + void setStencilReference( + uint32_t reference); + + /** + * \brief Sets input assembly state + * \param [in] ia New state object + */ + void setInputAssemblyState( + const DxvkInputAssemblyState& ia); + + /** + * \brief Sets input layout + * + * \param [in] attributeCount Number of vertex attributes + * \param [in] attributes The vertex attributes + * \param [in] bindingCount Number of buffer bindings + * \param [in] bindings Vertex buffer bindigs + */ + void setInputLayout( + uint32_t attributeCount, + const DxvkVertexAttribute* attributes, + uint32_t bindingCount, + const DxvkVertexBinding* bindings); + + /** + * \brief Sets rasterizer state + * \param [in] rs New state object + */ + void setRasterizerState( + const DxvkRasterizerState& rs); + + /** + * \brief Sets multisample state + * \param [in] ms New state object + */ + void setMultisampleState( + const DxvkMultisampleState& ms); + + /** + * \brief Sets depth stencil state + * \param [in] ds New state object + */ + void setDepthStencilState( + const DxvkDepthStencilState& ds); + + /** + * \brief Sets logic op state + * \param [in] lo New state object + */ + void setLogicOpState( + const DxvkLogicOpState& lo); + + /** + * \brief Sets blend mode for an attachment + * + * \param [in] attachment The attachment index + * \param [in] blendMode The blend mode + */ + void setBlendMode( + uint32_t attachment, + const DxvkBlendMode& blendMode); + + /** + * \brief Sets specialization constants + * + * Replaces current specialization constants with + * the given list of constant entries. The specId + * in the shader can be computed with \c getSpecId. + * \param [in] pipeline Graphics or Compute pipeline + * \param [in] index Constant index + * \param [in] value Constant value + */ + void setSpecConstant( + VkPipelineBindPoint pipeline, + uint32_t index, + uint32_t value); + + /** + * \brief Sets barrier control flags + * + * Barrier control flags can be used to control + * implicit synchronization of compute shaders. + * \param [in] control New barrier control flags + */ + void setBarrierControl( + DxvkBarrierControlFlags control); + + /** + * \brief Launches a Cuda kernel + * + * Since the kernel is launched with an opaque set of + * kernel-specific parameters which may reference + * resources bindlessly, such resources must be listed by + * the caller in the 'buffers' and 'images' parameters so + * that their access may be tracked appropriately. + * \param [in] nvxLaunchInfo Kernel launch parameter struct + * \param [in] buffers List of {buffer,read,write} used by kernel + * \param [in] images List of {image,read,write} used by kernel + */ + void launchCuKernelNVX( + const VkCuLaunchInfoNVX& nvxLaunchInfo, + const std::vector, DxvkAccessFlags>>& buffers, + const std::vector, DxvkAccessFlags>>& images); + + /** + * \brief Signals a GPU event + * \param [in] event The event + */ + void signalGpuEvent( + const Rc& event); + + /** + * \brief Writes to a timestamp query + * \param [in] query The timestamp query + */ + void writeTimestamp( + const Rc& query); + + /** + * \brief Queues a signal + * + * The signal will be notified after all + * previously submitted commands have + * finished execution on the GPU. + * \param [in] signal The signal + * \param [in] value Signal value + */ + void signal( + const Rc& signal, + uint64_t value); + + /** + * \brief Waits for fence + * + * Stalls current command list execution until + * the fence reaches the given value or higher. + * \param [in] fence Fence to wait on + * \param [in] value Value to wait on + */ + void waitFence(const Rc& fence, uint64_t value); + + /** + * \brief Signals fence + * + * Signals fence to the given value once the current + * command list execution completes on the GPU. + * \param [in] fence Fence to signal + * \param [in] value Value to signal + */ + void signalFence(const Rc& fence, uint64_t value); + + /** + * \brief Begins a debug label region + * \param [in] label The debug label + * + * Marks the start of a debug label region. Used by debugging/profiling + * tools to mark different workloads within a frame. + */ + void beginDebugLabel(VkDebugUtilsLabelEXT *label); + + /** + * \brief Ends a debug label region + * + * Marks the close of a debug label region. Used by debugging/profiling + * tools to mark different workloads within a frame. + */ + void endDebugLabel(); + + /** + * \brief Inserts a debug label + * \param [in] label The debug label + * + * Inserts an instantaneous debug label. Used by debugging/profiling + * tools to mark different workloads within a frame. + */ + void insertDebugLabel(VkDebugUtilsLabelEXT *label); + + /** + * \brief Increments a given stat counter + * + * The stat counters will be merged into the global + * stat counters upon execution of the command list. + * \param [in] counter Stat counter to increment + * \param [in] value Increment value + */ + void addStatCtr(DxvkStatCounter counter, uint64_t value) { + if (m_cmd != nullptr) + m_cmd->addStatCtr(counter, value); + } + + private: + + Rc m_device; + DxvkObjects* m_common; + + Rc m_cmd; + Rc m_descPool; + Rc m_zeroBuffer; + + DxvkContextFlags m_flags; + DxvkContextState m_state; + DxvkContextFeatures m_features; + + DxvkBarrierSet m_sdmaAcquires; + DxvkBarrierSet m_sdmaBarriers; + DxvkBarrierSet m_initBarriers; + DxvkBarrierSet m_execAcquires; + DxvkBarrierSet m_execBarriers; + DxvkBarrierSet m_gfxBarriers; + DxvkBarrierControlFlags m_barrierControl; + + DxvkGpuQueryManager m_queryManager; + DxvkStagingBuffer m_staging; + + DxvkRenderTargetLayouts m_rtLayouts = { }; + + VkPipeline m_gpActivePipeline = VK_NULL_HANDLE; + VkPipeline m_cpActivePipeline = VK_NULL_HANDLE; + + VkDescriptorSet m_gpSet = VK_NULL_HANDLE; + VkDescriptorSet m_cpSet = VK_NULL_HANDLE; + + DxvkBindingSet m_vbTracked; + DxvkBindingSet m_rcTracked; + + std::vector m_deferredClears; + + std::array m_rc; + std::array m_gpLookupCache = { }; + std::array m_cpLookupCache = { }; + std::array, 512> m_framebufferCache = { }; + + void blitImageFb( + const Rc& dstImage, + const Rc& srcImage, + const VkImageBlit& region, + const VkComponentMapping& mapping, + VkFilter filter); + + void blitImageHw( + const Rc& dstImage, + const Rc& srcImage, + const VkImageBlit& region, + VkFilter filter); + + template + void copyImageBufferData( + DxvkCmdBuffer cmd, + const Rc& image, + const VkImageSubresourceLayers& imageSubresource, + VkOffset3D imageOffset, + VkExtent3D imageExtent, + VkImageLayout imageLayout, + const DxvkBufferSliceHandle& bufferSlice, + VkDeviceSize bufferRowAlignment, + VkDeviceSize bufferSliceAlignment); + + void copyImageHostData( + DxvkCmdBuffer cmd, + const Rc& image, + const VkImageSubresourceLayers& imageSubresource, + VkOffset3D imageOffset, + VkExtent3D imageExtent, + const void* hostData, + VkDeviceSize rowPitch, + VkDeviceSize slicePitch); + + void clearImageViewFb( + const Rc& imageView, + VkOffset3D offset, + VkExtent3D extent, + VkImageAspectFlags aspect, + VkClearValue value); + + void clearImageViewCs( + const Rc& imageView, + VkOffset3D offset, + VkExtent3D extent, + VkClearValue value); + + void copyImageHw( + const Rc& dstImage, + VkImageSubresourceLayers dstSubresource, + VkOffset3D dstOffset, + const Rc& srcImage, + VkImageSubresourceLayers srcSubresource, + VkOffset3D srcOffset, + VkExtent3D extent); + + void copyImageFb( + const Rc& dstImage, + VkImageSubresourceLayers dstSubresource, + VkOffset3D dstOffset, + const Rc& srcImage, + VkImageSubresourceLayers srcSubresource, + VkOffset3D srcOffset, + VkExtent3D extent); + + bool copyImageClear( + const Rc& dstImage, + VkImageSubresourceLayers dstSubresource, + VkOffset3D dstOffset, + VkExtent3D dstExtent, + const Rc& srcImage, + VkImageSubresourceLayers srcSubresource); + + void resolveImageHw( + const Rc& dstImage, + const Rc& srcImage, + const VkImageResolve& region); + + void resolveImageDs( + const Rc& dstImage, + const Rc& srcImage, + const VkImageResolve& region, + VkResolveModeFlagBitsKHR depthMode, + VkResolveModeFlagBitsKHR stencilMode); + + void resolveImageFb( + const Rc& dstImage, + const Rc& srcImage, + const VkImageResolve& region, + VkFormat format, + VkResolveModeFlagBitsKHR depthMode, + VkResolveModeFlagBitsKHR stencilMode); + + void performClear( + const Rc& imageView, + int32_t attachmentIndex, + VkImageAspectFlags discardAspects, + VkImageAspectFlags clearAspects, + VkClearValue clearValue); + + void deferClear( + const Rc& imageView, + VkImageAspectFlags clearAspects, + VkClearValue clearValue); + + void deferDiscard( + const Rc& imageView, + VkImageAspectFlags discardAspects); + + void flushClears( + bool useRenderPass); + + void flushSharedImages(); + + void startRenderPass(); + void spillRenderPass(bool suspend); + + void renderPassBindFramebuffer( + const DxvkFramebufferInfo& framebufferInfo, + const DxvkRenderPassOps& ops, + uint32_t clearValueCount, + const VkClearValue* clearValues); + + void renderPassUnbindFramebuffer(); + + void resetRenderPassOps( + const DxvkRenderTargets& renderTargets, + DxvkRenderPassOps& renderPassOps); + + void startTransformFeedback(); + void pauseTransformFeedback(); + + void unbindComputePipeline(); + bool updateComputePipeline(); + bool updateComputePipelineState(); + + void unbindGraphicsPipeline(); + bool updateGraphicsPipeline(); + bool updateGraphicsPipelineState(); + + void updateComputeShaderResources(); + void updateGraphicsShaderResources(); + + template + void updateShaderResources( + const DxvkPipelineLayout* layout); + + template + void updateShaderDescriptorSetBinding( + VkDescriptorSet set, + const DxvkPipelineLayout* layout); + + DxvkFramebufferInfo makeFramebufferInfo( + const DxvkRenderTargets& renderTargets); + + void updateFramebuffer(); + + void applyRenderTargetLoadLayouts(); + + void applyRenderTargetStoreLayouts(); + + void transitionRenderTargetLayouts( + DxvkBarrierSet& barriers, + bool sharedOnly); + + void transitionColorAttachment( + DxvkBarrierSet& barriers, + const DxvkAttachment& attachment, + VkImageLayout oldLayout); + + void transitionDepthAttachment( + DxvkBarrierSet& barriers, + const DxvkAttachment& attachment, + VkImageLayout oldLayout); + + void updateRenderTargetLayouts( + const DxvkFramebufferInfo& newFb, + const DxvkFramebufferInfo& oldFb); + + void prepareImage( + DxvkBarrierSet& barriers, + const Rc& image, + const VkImageSubresourceRange& subresources, + bool flushClears = true); + + bool updateIndexBufferBinding(); + void updateVertexBufferBindings(); + + void updateTransformFeedbackBuffers(); + void updateTransformFeedbackState(); + + void updateDynamicState(); + + template + void updatePushConstants(); + + bool commitComputeState(); + + template + bool commitGraphicsState(); + + void commitComputeInitBarriers(); + void commitComputePostBarriers(); + + template + void commitGraphicsBarriers(); + + template + DxvkAccessFlags checkGfxBufferBarrier( + const DxvkBufferSlice& slice, + VkPipelineStageFlags stages, + VkAccessFlags access); + + template + DxvkAccessFlags checkGfxImageBarrier( + const Rc& imageView, + VkPipelineStageFlags stages, + VkAccessFlags access); + + void emitMemoryBarrier( + VkDependencyFlags flags, + VkPipelineStageFlags srcStages, + VkAccessFlags srcAccess, + VkPipelineStageFlags dstStages, + VkAccessFlags dstAccess); + + VkDescriptorSet allocateDescriptorSet( + VkDescriptorSetLayout layout); + + void trackDrawBuffer(); + + bool tryInvalidateDeviceLocalBuffer( + const Rc& buffer, + VkDeviceSize copySize); + + DxvkGraphicsPipeline* lookupGraphicsPipeline( + const DxvkGraphicsPipelineShaders& shaders); + + DxvkComputePipeline* lookupComputePipeline( + const DxvkComputePipelineShaders& shaders); + + Rc lookupFramebuffer( + const DxvkFramebufferInfo& framebufferInfo); + + Rc createZeroBuffer( + VkDeviceSize size); + + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_context_state.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_context_state.h new file mode 100644 index 00000000000..27a6de5876e --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_context_state.h @@ -0,0 +1,173 @@ +#pragma once + +#include "dxvk_buffer.h" +#include "dxvk_compute.h" +#include "dxvk_constant_state.h" +#include "dxvk_framebuffer.h" +#include "dxvk_graphics.h" +#include "dxvk_image.h" +#include "dxvk_limits.h" +#include "dxvk_pipelayout.h" +#include "dxvk_sampler.h" +#include "dxvk_shader.h" + +namespace dxvk { + + /** + * \brief Graphics pipeline state flags + * + * Stores some information on which state + * of the graphics and compute pipelines + * has changed and/or needs to be updated. + */ + enum class DxvkContextFlag : uint32_t { + GpRenderPassBound, ///< Render pass is currently bound + GpRenderPassSuspended, ///< Render pass is currently suspended + GpXfbActive, ///< Transform feedback is enabled + GpDirtyFramebuffer, ///< Framebuffer binding is out of date + GpDirtyPipeline, ///< Graphics pipeline binding is out of date + GpDirtyPipelineState, ///< Graphics pipeline needs to be recompiled + GpDirtyResources, ///< Graphics pipeline resource bindings are out of date + GpDirtyDescriptorBinding, ///< Graphics descriptor set needs to be rebound + GpDirtyVertexBuffers, ///< Vertex buffer bindings are out of date + GpDirtyIndexBuffer, ///< Index buffer binding are out of date + GpDirtyXfbBuffers, ///< Transform feedback buffer bindings are out of date + GpDirtyBlendConstants, ///< Blend constants have changed + GpDirtyDepthBias, ///< Depth bias has changed + GpDirtyDepthBounds, ///< Depth bounds have changed + GpDirtyStencilRef, ///< Stencil reference has changed + GpDirtyViewport, ///< Viewport state has changed + GpDynamicBlendConstants, ///< Blend constants are dynamic + GpDynamicDepthBias, ///< Depth bias is dynamic + GpDynamicDepthBounds, ///< Depth bounds are dynamic + GpDynamicStencilRef, ///< Stencil reference is dynamic + + CpDirtyPipeline, ///< Compute pipeline binding are out of date + CpDirtyPipelineState, ///< Compute pipeline needs to be recompiled + CpDirtyResources, ///< Compute pipeline resource bindings are out of date + CpDirtyDescriptorBinding, ///< Compute descriptor set needs to be rebound + + DirtyDrawBuffer, ///< Indirect argument buffer is dirty + DirtyPushConstants, ///< Push constant data has changed + }; + + using DxvkContextFlags = Flags; + + + /** + * \brief Context feature bits + */ + enum class DxvkContextFeature { + NullDescriptors, + ExtendedDynamicState, + }; + + using DxvkContextFeatures = Flags; + + + /** + * \brief Barrier control flags + * + * These flags specify what (not) to + * synchronize implicitly. + */ + enum class DxvkBarrierControl : uint32_t { + IgnoreWriteAfterWrite = 1, + IgnoreGraphicsBarriers = 2, + }; + + using DxvkBarrierControlFlags = Flags; + + + struct DxvkIndirectDrawState { + DxvkBufferSlice argBuffer; + DxvkBufferSlice cntBuffer; + }; + + + struct DxvkVertexInputState { + DxvkBufferSlice indexBuffer; + VkIndexType indexType = VK_INDEX_TYPE_UINT32; + + std::array vertexBuffers = { }; + std::array vertexStrides = { }; + }; + + + struct DxvkViewportState { + std::array viewports = { }; + std::array scissorRects = { }; + }; + + + struct DxvkOutputMergerState { + std::array clearValues = { }; + + DxvkRenderTargets renderTargets; + DxvkRenderPassOps renderPassOps; + DxvkFramebufferInfo framebufferInfo; + }; + + + struct DxvkPushConstantState { + char data[MaxPushConstantSize]; + }; + + + struct DxvkXfbState { + std::array buffers; + std::array counters; + }; + + + struct DxvkGraphicsPipelineState { + DxvkGraphicsPipelineShaders shaders; + DxvkGraphicsPipelineStateInfo state; + DxvkGraphicsPipelineFlags flags; + DxvkGraphicsPipeline* pipeline = nullptr; + }; + + + struct DxvkComputePipelineState { + DxvkComputePipelineShaders shaders; + DxvkComputePipelineStateInfo state; + DxvkComputePipeline* pipeline = nullptr; + }; + + + struct DxvkDynamicState { + DxvkBlendConstants blendConstants = { 0.0f, 0.0f, 0.0f, 0.0f }; + DxvkDepthBias depthBias = { 0.0f, 0.0f, 0.0f }; + DxvkDepthBounds depthBounds = { false, 0.0f, 1.0f }; + uint32_t stencilReference = 0; + }; + + + struct DxvkDeferredClear { + Rc imageView; + VkImageAspectFlags discardAspects; + VkImageAspectFlags clearAspects; + VkClearValue clearValue; + }; + + + /** + * \brief Pipeline state + * + * Stores all bound shaders, resources, + * and constant pipeline state objects. + */ + struct DxvkContextState { + DxvkIndirectDrawState id; + DxvkVertexInputState vi; + DxvkViewportState vp; + DxvkOutputMergerState om; + DxvkPushConstantState pc; + DxvkXfbState xfb; + DxvkDynamicState dyn; + + DxvkGraphicsPipelineState gp; + DxvkComputePipelineState cp; + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_cs.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_cs.cpp new file mode 100644 index 00000000000..7061f1a634a --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_cs.cpp @@ -0,0 +1,191 @@ +#include "dxvk_cs.h" + +namespace dxvk { + + DxvkCsChunk::DxvkCsChunk() { + + } + + + DxvkCsChunk::~DxvkCsChunk() { + this->reset(); + } + + + void DxvkCsChunk::init(DxvkCsChunkFlags flags) { + m_flags = flags; + } + + + void DxvkCsChunk::executeAll(DxvkContext* ctx) { + auto cmd = m_head; + + if (m_flags.test(DxvkCsChunkFlag::SingleUse)) { + m_commandOffset = 0; + + while (cmd != nullptr) { + auto next = cmd->next(); + cmd->exec(ctx); + cmd->~DxvkCsCmd(); + cmd = next; + } + + m_head = nullptr; + m_tail = nullptr; + } else { + while (cmd != nullptr) { + cmd->exec(ctx); + cmd = cmd->next(); + } + } + } + + + void DxvkCsChunk::reset() { + auto cmd = m_head; + + while (cmd != nullptr) { + auto next = cmd->next(); + cmd->~DxvkCsCmd(); + cmd = next; + } + + m_head = nullptr; + m_tail = nullptr; + + m_commandOffset = 0; + } + + + DxvkCsChunkPool::DxvkCsChunkPool() { + + } + + + DxvkCsChunkPool::~DxvkCsChunkPool() { + for (DxvkCsChunk* chunk : m_chunks) + delete chunk; + } + + + DxvkCsChunk* DxvkCsChunkPool::allocChunk(DxvkCsChunkFlags flags) { + DxvkCsChunk* chunk = nullptr; + + { std::lock_guard lock(m_mutex); + + if (m_chunks.size() != 0) { + chunk = m_chunks.back(); + m_chunks.pop_back(); + } + } + + if (!chunk) + chunk = new DxvkCsChunk(); + + chunk->init(flags); + return chunk; + } + + + void DxvkCsChunkPool::freeChunk(DxvkCsChunk* chunk) { + chunk->reset(); + + std::lock_guard lock(m_mutex); + m_chunks.push_back(chunk); + } + + + DxvkCsThread::DxvkCsThread( + const Rc& device, + const Rc& context) + : m_device(device), m_context(context), + m_thread([this] { threadFunc(); }) { + + } + + + DxvkCsThread::~DxvkCsThread() { + { std::unique_lock lock(m_mutex); + m_stopped.store(true); + } + + m_condOnAdd.notify_one(); + m_thread.join(); + } + + + uint64_t DxvkCsThread::dispatchChunk(DxvkCsChunkRef&& chunk) { + uint64_t seq; + + { std::unique_lock lock(m_mutex); + seq = ++m_chunksDispatched; + m_chunksQueued.push(std::move(chunk)); + } + + m_condOnAdd.notify_one(); + return seq; + } + + + void DxvkCsThread::synchronize(uint64_t seq) { + // Avoid locking if we know the sync is a no-op, may + // reduce overhead if this is being called frequently + if (seq > m_chunksExecuted.load(std::memory_order_acquire)) { + std::unique_lock lock(m_mutex); + + if (seq == SynchronizeAll) + seq = m_chunksDispatched.load(); + + auto t0 = dxvk::high_resolution_clock::now(); + m_condOnSync.wait(lock, [this, seq] { + return m_chunksExecuted.load() >= seq; + }); + auto t1 = dxvk::high_resolution_clock::now(); + auto ticks = std::chrono::duration_cast(t1 - t0); + + m_device->addStatCtr(DxvkStatCounter::CsSyncCount, 1); + m_device->addStatCtr(DxvkStatCounter::CsSyncTicks, ticks.count()); + } + } + + + void DxvkCsThread::threadFunc() { + env::setThreadName("dxvk-cs"); + + DxvkCsChunkRef chunk; + + try { + while (!m_stopped.load()) { + { std::unique_lock lock(m_mutex); + if (chunk) { + m_chunksExecuted++; + m_condOnSync.notify_one(); + + chunk = DxvkCsChunkRef(); + } + + if (m_chunksQueued.size() == 0) { + m_condOnAdd.wait(lock, [this] { + return (m_chunksQueued.size() != 0) + || (m_stopped.load()); + }); + } + + if (m_chunksQueued.size() != 0) { + chunk = std::move(m_chunksQueued.front()); + m_chunksQueued.pop(); + } + } + + if (chunk) { + m_context->addStatCtr(DxvkStatCounter::CsChunkCount, 1); + chunk->executeAll(m_context.ptr()); + } + } + } catch (const DxvkError& e) { + Logger::err("Exception on CS thread!"); + Logger::err(e.message()); + } + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_cs.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_cs.h new file mode 100644 index 00000000000..ab2733c14d4 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_cs.h @@ -0,0 +1,442 @@ +#pragma once + +#include +#include +#include +#include + +#include "../util/thread.h" + +#include "dxvk_device.h" +#include "dxvk_context.h" + +namespace dxvk { + + /** + * \brief Command stream operation + * + * An abstract representation of an operation + * that can be recorded into a command list. + */ + class DxvkCsCmd { + + public: + + virtual ~DxvkCsCmd() { } + + /** + * \brief Retrieves next command in a command chain + * + * This can be used to quickly iterate + * over commands within a chunk. + * \returns Pointer the next command + */ + DxvkCsCmd* next() const { + return m_next; + } + + /** + * \brief Sets next command in a command chain + * \param [in] next Next command + */ + void setNext(DxvkCsCmd* next) { + m_next = next; + } + + /** + * \brief Executes embedded commands + * \param [in] ctx The target context + */ + virtual void exec(DxvkContext* ctx) const = 0; + + private: + + DxvkCsCmd* m_next = nullptr; + + }; + + + /** + * \brief Typed command + * + * Stores a function object which is + * used to execute an embedded command. + */ + template + class alignas(16) DxvkCsTypedCmd : public DxvkCsCmd { + + public: + + DxvkCsTypedCmd(T&& cmd) + : m_command(std::move(cmd)) { } + + DxvkCsTypedCmd (DxvkCsTypedCmd&&) = delete; + DxvkCsTypedCmd& operator = (DxvkCsTypedCmd&&) = delete; + + void exec(DxvkContext* ctx) const { + m_command(ctx); + } + + private: + + T m_command; + + }; + + + /** + * \brief Typed command with metadata + * + * Stores a function object and an arbitrary + * data structure which can be modified after + * submitting the command to a cs chunk. + */ + template + class alignas(16) DxvkCsDataCmd : public DxvkCsCmd { + + public: + + template + DxvkCsDataCmd(T&& cmd, Args&&... args) + : m_command (std::move(cmd)), + m_data (std::forward(args)...) { } + + DxvkCsDataCmd (DxvkCsDataCmd&&) = delete; + DxvkCsDataCmd& operator = (DxvkCsDataCmd&&) = delete; + + void exec(DxvkContext* ctx) const { + m_command(ctx, &m_data); + } + + M* data() { + return &m_data; + } + + private: + + T m_command; + M m_data; + + }; + + + /** + * \brief Submission flags + */ + enum class DxvkCsChunkFlag : uint32_t { + /// Indicates that the submitted chunk will + /// no longer be needed after one submission. + SingleUse, + }; + + using DxvkCsChunkFlags = Flags; + + + /** + * \brief Command chunk + * + * Stores a list of commands. + */ + class DxvkCsChunk : public RcObject { + constexpr static size_t MaxBlockSize = 16384; + public: + + DxvkCsChunk(); + ~DxvkCsChunk(); + + /** + * \brief Checks whether the chunk is empty + * \returns \c true if the chunk is empty + */ + bool empty() const { + return m_commandOffset == 0; + } + + /** + * \brief Tries to add a command to the chunk + * + * If the given command can be added to the chunk, it + * will be consumed. Otherwise, a new chunk must be + * created which is large enough to hold the command. + * \param [in] command The command to add + * \returns \c true on success, \c false if + * a new chunk needs to be allocated + */ + template + bool push(T& command) { + using FuncType = DxvkCsTypedCmd; + + if (unlikely(m_commandOffset > MaxBlockSize - sizeof(FuncType))) + return false; + + DxvkCsCmd* tail = m_tail; + + m_tail = new (m_data + m_commandOffset) + FuncType(std::move(command)); + + if (likely(tail != nullptr)) + tail->setNext(m_tail); + else + m_head = m_tail; + + m_commandOffset += sizeof(FuncType); + return true; + } + + /** + * \brief Adds a command with data to the chunk + * + * \param [in] command The command to add + * \param [in] args Constructor args for the data object + * \returns Pointer to the data object, or \c nullptr + */ + template + M* pushCmd(T& command, Args&&... args) { + using FuncType = DxvkCsDataCmd; + + if (unlikely(m_commandOffset > MaxBlockSize - sizeof(FuncType))) + return nullptr; + + FuncType* func = new (m_data + m_commandOffset) + FuncType(std::move(command), std::forward(args)...); + + if (likely(m_tail != nullptr)) + m_tail->setNext(func); + else + m_head = func; + m_tail = func; + + m_commandOffset += sizeof(FuncType); + return func->data(); + } + + /** + * \brief Initializes chunk for recording + * \param [in] flags Chunk flags + */ + void init(DxvkCsChunkFlags flags); + + /** + * \brief Executes all commands + * + * This will also reset the chunk + * so that it can be reused. + * \param [in] ctx The context + */ + void executeAll(DxvkContext* ctx); + + /** + * \brief Resets chunk + * + * Destroys all recorded commands and + * marks the chunk itself as empty, so + * that it can be reused later. + */ + void reset(); + + private: + + size_t m_commandOffset = 0; + + DxvkCsCmd* m_head = nullptr; + DxvkCsCmd* m_tail = nullptr; + + DxvkCsChunkFlags m_flags; + + alignas(64) + char m_data[MaxBlockSize]; + + }; + + + /** + * \brief Chunk pool + * + * Implements a pool of CS chunks which can be + * recycled. The goal is to reduce the number + * of dynamic memory allocations. + */ + class DxvkCsChunkPool { + + public: + + DxvkCsChunkPool(); + ~DxvkCsChunkPool(); + + DxvkCsChunkPool (const DxvkCsChunkPool&) = delete; + DxvkCsChunkPool& operator = (const DxvkCsChunkPool&) = delete; + + /** + * \brief Allocates a chunk + * + * Takes an existing chunk from the pool, + * or creates a new one if necessary. + * \param [in] flags Chunk flags + * \returns Allocated chunk object + */ + DxvkCsChunk* allocChunk(DxvkCsChunkFlags flags); + + /** + * \brief Releases a chunk + * + * Resets the chunk and adds it to the pool. + * \param [in] chunk Chunk to release + */ + void freeChunk(DxvkCsChunk* chunk); + + private: + + dxvk::mutex m_mutex; + std::vector m_chunks; + + }; + + + /** + * \brief Chunk reference + * + * Implements basic reference counting for + * CS chunks and returns them to the pool + * as soon as they are no longer needed. + */ + class DxvkCsChunkRef { + + public: + + DxvkCsChunkRef() { } + DxvkCsChunkRef( + DxvkCsChunk* chunk, + DxvkCsChunkPool* pool) + : m_chunk (chunk), + m_pool (pool) { + this->incRef(); + } + + DxvkCsChunkRef(const DxvkCsChunkRef& other) + : m_chunk (other.m_chunk), + m_pool (other.m_pool) { + this->incRef(); + } + + DxvkCsChunkRef(DxvkCsChunkRef&& other) + : m_chunk (other.m_chunk), + m_pool (other.m_pool) { + other.m_chunk = nullptr; + other.m_pool = nullptr; + } + + DxvkCsChunkRef& operator = (const DxvkCsChunkRef& other) { + other.incRef(); + this->decRef(); + this->m_chunk = other.m_chunk; + this->m_pool = other.m_pool; + return *this; + } + + DxvkCsChunkRef& operator = (DxvkCsChunkRef&& other) { + this->decRef(); + this->m_chunk = other.m_chunk; + this->m_pool = other.m_pool; + other.m_chunk = nullptr; + other.m_pool = nullptr; + return *this; + } + + ~DxvkCsChunkRef() { + this->decRef(); + } + + DxvkCsChunk* operator -> () const { + return m_chunk; + } + + operator bool () const { + return m_chunk != nullptr; + } + + private: + + DxvkCsChunk* m_chunk = nullptr; + DxvkCsChunkPool* m_pool = nullptr; + + void incRef() const { + if (m_chunk != nullptr) + m_chunk->incRef(); + } + + void decRef() const { + if (m_chunk != nullptr && m_chunk->decRef() == 0) + m_pool->freeChunk(m_chunk); + } + + }; + + + /** + * \brief Command stream thread + * + * Spawns a thread that will execute + * commands on a DXVK context. + */ + class DxvkCsThread { + + public: + + constexpr static uint64_t SynchronizeAll = ~0ull; + + DxvkCsThread( + const Rc& device, + const Rc& context); + ~DxvkCsThread(); + + /** + * \brief Dispatches an entire chunk + * + * Can be used to efficiently play back large + * command lists recorded on another thread. + * \param [in] chunk The chunk to dispatch + * \returns Sequence number of the submission + */ + uint64_t dispatchChunk(DxvkCsChunkRef&& chunk); + + /** + * \brief Synchronizes with the thread + * + * This waits for all chunks in the dispatch queue to + * be processed by the thread, up to the given sequence + * number. If the sequence number is 0, this will wait + * for all pending chunks to complete execution. + * \param [in] seq Sequence number to wait for. + */ + void synchronize(uint64_t seq); + + /** + * \brief Retrieves last executed sequence number + * + * Can be used to avoid synchronization in some cases. + * \returns Sequence number of last executed chunk + */ + uint64_t lastSequenceNumber() const { + return m_chunksExecuted.load(); + } + + private: + + Rc m_device; + Rc m_context; + + std::atomic m_chunksDispatched = { 0ull }; + std::atomic m_chunksExecuted = { 0ull }; + + std::atomic m_stopped = { false }; + dxvk::mutex m_mutex; + dxvk::condition_variable m_condOnAdd; + dxvk::condition_variable m_condOnSync; + std::queue m_chunksQueued; + dxvk::thread m_thread; + + void threadFunc(); + + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_data.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_data.cpp new file mode 100644 index 00000000000..bece0efdc38 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_data.cpp @@ -0,0 +1,26 @@ +#include + +#include "dxvk_data.h" + +namespace dxvk { + + DxvkDataBuffer:: DxvkDataBuffer() { } + DxvkDataBuffer::DxvkDataBuffer(size_t size) + : m_data(new char[size]), m_size(size) { } + + + DxvkDataBuffer::~DxvkDataBuffer() { + delete[] m_data; + } + + + DxvkDataSlice DxvkDataBuffer::alloc(size_t n) { + const size_t offset = m_offset; + + if (offset + n <= m_size) { + m_offset += align(n, CACHE_LINE_SIZE); + return DxvkDataSlice(this, offset, n); + } return DxvkDataSlice(); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_data.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_data.h new file mode 100644 index 00000000000..2a5ee924194 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_data.h @@ -0,0 +1,82 @@ +#pragma once + +#include "dxvk_include.h" + +namespace dxvk { + + class DxvkDataSlice; + + /** + * \brief Data buffer + * + * Provides a fixed-size buffer with a linear memory + * allocator for arbitrary data. Can be used to copy + * data to or from resources. Note that allocations + * will be aligned to a cache line boundary. + */ + class DxvkDataBuffer : public RcObject { + friend class DxvkDataSlice; + public: + + DxvkDataBuffer(); + DxvkDataBuffer(size_t size); + ~DxvkDataBuffer(); + + /** + * \brief Allocates a slice + * + * If the desired slice length is larger than the + * number of bytes left in the buffer, this will + * fail and the returned slice points to \c nullptr. + * \param [in] n Number of bytes to allocate + * \returns The slice, or an empty slice on failure + */ + DxvkDataSlice alloc(size_t n); + + private: + + char* m_data = nullptr; + size_t m_size = 0; + size_t m_offset = 0; + + }; + + + /** + * \brief Data buffer slice + * + * A slice of a \ref DxvkDataBuffer which stores + * a strong reference to the backing buffer object. + */ + class DxvkDataSlice { + + public: + + DxvkDataSlice() { } + DxvkDataSlice( + const Rc& buffer, + size_t offset, + size_t length) + : m_buffer(buffer), + m_offset(offset), + m_length(length) { } + + void* ptr() const { + return m_buffer != nullptr + ? m_buffer->m_data + m_offset + : nullptr; + } + + size_t offset() const { return m_offset; } + size_t length() const { return m_length; } + + private: + + Rc m_buffer; + size_t m_offset = 0; + size_t m_length = 0; + + }; + + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_descriptor.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_descriptor.cpp new file mode 100644 index 00000000000..cdd2ae67bae --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_descriptor.cpp @@ -0,0 +1,88 @@ +#include "dxvk_descriptor.h" +#include "dxvk_device.h" + +namespace dxvk { + + DxvkDescriptorPool::DxvkDescriptorPool(const Rc& vkd) + : m_vkd(vkd) { + constexpr uint32_t MaxSets = 2048; + + std::array pools = {{ + { VK_DESCRIPTOR_TYPE_SAMPLER, MaxSets * 2 }, + { VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, MaxSets * 3 }, + { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, MaxSets / 8 }, + { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, MaxSets * 3 }, + { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, MaxSets / 8 }, + { VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, MaxSets * 3 }, + { VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, MaxSets / 8 }, + { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, MaxSets * 3 }, + { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, MaxSets * 2 } }}; + + VkDescriptorPoolCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.maxSets = MaxSets; + info.poolSizeCount = pools.size(); + info.pPoolSizes = pools.data(); + + if (m_vkd->vkCreateDescriptorPool(m_vkd->device(), &info, nullptr, &m_pool) != VK_SUCCESS) + throw DxvkError("DxvkDescriptorPool: Failed to create descriptor pool"); + } + + + DxvkDescriptorPool::~DxvkDescriptorPool() { + m_vkd->vkDestroyDescriptorPool( + m_vkd->device(), m_pool, nullptr); + } + + + VkDescriptorSet DxvkDescriptorPool::alloc(VkDescriptorSetLayout layout) { + VkDescriptorSetAllocateInfo info; + info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + info.pNext = nullptr; + info.descriptorPool = m_pool; + info.descriptorSetCount = 1; + info.pSetLayouts = &layout; + + VkDescriptorSet set = VK_NULL_HANDLE; + if (m_vkd->vkAllocateDescriptorSets(m_vkd->device(), &info, &set) != VK_SUCCESS) + return VK_NULL_HANDLE; + return set; + } + + + void DxvkDescriptorPool::reset() { + m_vkd->vkResetDescriptorPool( + m_vkd->device(), m_pool, 0); + } + + + + + DxvkDescriptorPoolTracker::DxvkDescriptorPoolTracker(DxvkDevice* device) + : m_device(device) { + + } + + + DxvkDescriptorPoolTracker::~DxvkDescriptorPoolTracker() { + + } + + + void DxvkDescriptorPoolTracker::trackDescriptorPool(Rc pool) { + m_pools.push_back(std::move(pool)); + } + + + void DxvkDescriptorPoolTracker::reset() { + for (const auto& pool : m_pools) { + pool->reset(); + m_device->recycleDescriptorPool(pool); + } + + m_pools.clear(); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_descriptor.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_descriptor.h new file mode 100644 index 00000000000..243e6b0a2d0 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_descriptor.h @@ -0,0 +1,100 @@ +#pragma once + +#include + +#include "dxvk_include.h" + +namespace dxvk { + + class DxvkDevice; + + /** + * \brief Descriptor info + * + * Stores information that is required to + * update a single resource descriptor. + */ + union DxvkDescriptorInfo { + VkDescriptorImageInfo image; + VkDescriptorBufferInfo buffer; + VkBufferView texelBuffer; + }; + + + /** + * \brief Descriptor pool + * + * Wrapper around a Vulkan descriptor pool that + * descriptor sets can be allocated from. + */ + class DxvkDescriptorPool : public RcObject { + + public: + + DxvkDescriptorPool( + const Rc& vkd); + ~DxvkDescriptorPool(); + + /** + * \brief Allocates a descriptor set + * + * \param [in] layout Descriptor set layout + * \returns The descriptor set + */ + VkDescriptorSet alloc( + VkDescriptorSetLayout layout); + + /** + * \brief Resets descriptor set allocator + * + * Destroys all descriptor sets and + * resets the Vulkan descriptor pools. + */ + void reset(); + + private: + + Rc m_vkd; + VkDescriptorPool m_pool; + + }; + + + /** + * \brief Descriptor pool tracker + * + * Tracks descriptor pools that are either full + * or no longer needed by the DXVK context. The + * command list will reset and recycle all pools + * once it has completed execution on the GPU. + */ + class DxvkDescriptorPoolTracker { + + public: + + DxvkDescriptorPoolTracker(DxvkDevice* device); + ~DxvkDescriptorPoolTracker(); + + /** + * \brief Adds a descriptor pool to track + * \param [in] pool The descriptor pool + */ + void trackDescriptorPool(Rc pool); + + /** + * \brief Resets event tracker + * + * Resets all tracked descriptor pools + * and returns them to the device. + */ + void reset(); + + private: + + DxvkDevice* m_device; + + std::vector> m_pools; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_device.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_device.cpp new file mode 100644 index 00000000000..dc12ab470a3 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_device.cpp @@ -0,0 +1,301 @@ +#include "dxvk_device.h" +#include "dxvk_instance.h" + +namespace dxvk { + + DxvkDevice::DxvkDevice( + const Rc& instance, + const Rc& adapter, + const Rc& vkd, + const DxvkDeviceExtensions& extensions, + const DxvkDeviceFeatures& features) + : m_options (instance->options()), + m_instance (instance), + m_adapter (adapter), + m_vkd (vkd), + m_extensions (extensions), + m_features (features), + m_properties (adapter->devicePropertiesExt()), + m_perfHints (getPerfHints()), + m_objects (this), + m_submissionQueue (this) { + auto queueFamilies = m_adapter->findQueueFamilies(); + m_queues.graphics = getQueue(queueFamilies.graphics, 0); + m_queues.transfer = getQueue(queueFamilies.transfer, 0); + } + + + DxvkDevice::~DxvkDevice() { + // Wait for all pending Vulkan commands to be + // executed before we destroy any resources. + this->waitForIdle(); + + // Stop workers explicitly in order to prevent + // access to structures that are being destroyed. + m_objects.pipelineManager().stopWorkerThreads(); + } + + + bool DxvkDevice::isUnifiedMemoryArchitecture() const { + return m_adapter->isUnifiedMemoryArchitecture(); + } + + + DxvkFramebufferSize DxvkDevice::getDefaultFramebufferSize() const { + return DxvkFramebufferSize { + m_properties.core.properties.limits.maxFramebufferWidth, + m_properties.core.properties.limits.maxFramebufferHeight, + m_properties.core.properties.limits.maxFramebufferLayers }; + } + + + VkPipelineStageFlags DxvkDevice::getShaderPipelineStages() const { + VkPipelineStageFlags result = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT + | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT + | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + + if (m_features.core.features.geometryShader) + result |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT; + + if (m_features.core.features.tessellationShader) { + result |= VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT + | VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT; + } + + return result; + } + + + DxvkDeviceOptions DxvkDevice::options() const { + DxvkDeviceOptions options; + options.maxNumDynamicUniformBuffers = m_properties.core.properties.limits.maxDescriptorSetUniformBuffersDynamic; + options.maxNumDynamicStorageBuffers = m_properties.core.properties.limits.maxDescriptorSetStorageBuffersDynamic; + return options; + } + + + Rc DxvkDevice::createCommandList() { + Rc cmdList = m_recycledCommandLists.retrieveObject(); + + if (cmdList == nullptr) + cmdList = new DxvkCommandList(this); + + return cmdList; + } + + + Rc DxvkDevice::createDescriptorPool() { + Rc pool = m_recycledDescriptorPools.retrieveObject(); + + if (pool == nullptr) + pool = new DxvkDescriptorPool(m_vkd); + + return pool; + } + + + Rc DxvkDevice::createContext() { + return new DxvkContext(this); + } + + + Rc DxvkDevice::createGpuEvent() { + return new DxvkGpuEvent(m_vkd); + } + + + Rc DxvkDevice::createGpuQuery( + VkQueryType type, + VkQueryControlFlags flags, + uint32_t index) { + return new DxvkGpuQuery(m_vkd, type, flags, index); + } + + + Rc DxvkDevice::createFence( + const DxvkFenceCreateInfo& fenceInfo) { + return new DxvkFence(this, fenceInfo); + } + + + Rc DxvkDevice::createFramebuffer( + const DxvkFramebufferInfo& info) { + return new DxvkFramebuffer(m_vkd, info); + } + + + Rc DxvkDevice::createBuffer( + const DxvkBufferCreateInfo& createInfo, + VkMemoryPropertyFlags memoryType) { + return new DxvkBuffer(this, createInfo, m_objects.memoryManager(), memoryType); + } + + + Rc DxvkDevice::createBufferView( + const Rc& buffer, + const DxvkBufferViewCreateInfo& createInfo) { + return new DxvkBufferView(m_vkd, buffer, createInfo); + } + + + Rc DxvkDevice::createImage( + const DxvkImageCreateInfo& createInfo, + VkMemoryPropertyFlags memoryType) { + return new DxvkImage(this, createInfo, m_objects.memoryManager(), memoryType); + } + + + Rc DxvkDevice::createImageFromVkImage( + const DxvkImageCreateInfo& createInfo, + VkImage image) { + return new DxvkImage(this, createInfo, image); + } + + Rc DxvkDevice::createImageView( + const Rc& image, + const DxvkImageViewCreateInfo& createInfo) { + return new DxvkImageView(m_vkd, image, createInfo); + } + + + Rc DxvkDevice::createSampler( + const DxvkSamplerCreateInfo& createInfo) { + return new DxvkSampler(this, createInfo); + } + + + DxvkStatCounters DxvkDevice::getStatCounters() { + DxvkPipelineCount pipe = m_objects.pipelineManager().getPipelineCount(); + + DxvkStatCounters result; + result.setCtr(DxvkStatCounter::PipeCountGraphics, pipe.numGraphicsPipelines); + result.setCtr(DxvkStatCounter::PipeCountCompute, pipe.numComputePipelines); + result.setCtr(DxvkStatCounter::PipeCompilerBusy, m_objects.pipelineManager().isCompilingShaders()); + result.setCtr(DxvkStatCounter::GpuIdleTicks, m_submissionQueue.gpuIdleTicks()); + + std::lock_guard lock(m_statLock); + result.merge(m_statCounters); + return result; + } + + + DxvkMemoryStats DxvkDevice::getMemoryStats(uint32_t heap) { + return m_objects.memoryManager().getMemoryStats(heap); + } + + + uint32_t DxvkDevice::getCurrentFrameId() const { + return m_statCounters.getCtr(DxvkStatCounter::QueuePresentCount); + } + + + void DxvkDevice::initResources() { + m_objects.dummyResources().clearResources(this); + } + + + void DxvkDevice::registerShader(const Rc& shader) { + m_objects.pipelineManager().registerShader(shader); + } + + + void DxvkDevice::presentImage( + const Rc& presenter, + DxvkSubmitStatus* status) { + status->result = VK_NOT_READY; + + DxvkPresentInfo presentInfo; + presentInfo.presenter = presenter; + m_submissionQueue.present(presentInfo, status); + + std::lock_guard statLock(m_statLock); + m_statCounters.addCtr(DxvkStatCounter::QueuePresentCount, 1); + } + + + void DxvkDevice::submitCommandList( + const Rc& commandList, + VkSemaphore waitSync, + VkSemaphore wakeSync) { + DxvkSubmitInfo submitInfo; + submitInfo.cmdList = commandList; + submitInfo.waitSync = waitSync; + submitInfo.wakeSync = wakeSync; + m_submissionQueue.submit(submitInfo); + + std::lock_guard statLock(m_statLock); + m_statCounters.merge(commandList->statCounters()); + m_statCounters.addCtr(DxvkStatCounter::QueueSubmitCount, 1); + } + + + VkResult DxvkDevice::waitForSubmission(DxvkSubmitStatus* status) { + VkResult result = status->result.load(); + + if (result == VK_NOT_READY) { + m_submissionQueue.synchronizeSubmission(status); + result = status->result.load(); + } + + return result; + } + + + void DxvkDevice::waitForResource(const Rc& resource, DxvkAccess access) { + if (resource->isInUse(access)) { + auto t0 = dxvk::high_resolution_clock::now(); + + m_submissionQueue.synchronizeUntil([resource, access] { + return !resource->isInUse(access); + }); + + auto t1 = dxvk::high_resolution_clock::now(); + auto us = std::chrono::duration_cast(t1 - t0); + + std::lock_guard lock(m_statLock); + m_statCounters.addCtr(DxvkStatCounter::GpuSyncCount, 1); + m_statCounters.addCtr(DxvkStatCounter::GpuSyncTicks, us.count()); + } + } + + + void DxvkDevice::waitForIdle() { + this->lockSubmission(); + if (m_vkd->vkDeviceWaitIdle(m_vkd->device()) != VK_SUCCESS) + Logger::err("DxvkDevice: waitForIdle: Operation failed"); + this->unlockSubmission(); + } + + + DxvkDevicePerfHints DxvkDevice::getPerfHints() { + DxvkDevicePerfHints hints; + hints.preferFbDepthStencilCopy = m_extensions.extShaderStencilExport + && (m_adapter->matchesDriver(DxvkGpuVendor::Amd, VK_DRIVER_ID_MESA_RADV_KHR, 0, 0) + || m_adapter->matchesDriver(DxvkGpuVendor::Amd, VK_DRIVER_ID_AMD_OPEN_SOURCE_KHR, 0, 0) + || m_adapter->matchesDriver(DxvkGpuVendor::Amd, VK_DRIVER_ID_AMD_PROPRIETARY_KHR, 0, 0)); + hints.preferFbResolve = m_extensions.amdShaderFragmentMask + && (m_adapter->matchesDriver(DxvkGpuVendor::Amd, VK_DRIVER_ID_AMD_OPEN_SOURCE_KHR, 0, 0) + || m_adapter->matchesDriver(DxvkGpuVendor::Amd, VK_DRIVER_ID_AMD_PROPRIETARY_KHR, 0, 0)); + return hints; + } + + + void DxvkDevice::recycleCommandList(const Rc& cmdList) { + m_recycledCommandLists.returnObject(cmdList); + } + + + void DxvkDevice::recycleDescriptorPool(const Rc& pool) { + m_recycledDescriptorPools.returnObject(pool); + } + + + DxvkDeviceQueue DxvkDevice::getQueue( + uint32_t family, + uint32_t index) const { + VkQueue queue = VK_NULL_HANDLE; + m_vkd->vkGetDeviceQueue(m_vkd->device(), family, index, &queue); + return DxvkDeviceQueue { queue, family, index }; + } + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_device.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_device.h new file mode 100644 index 00000000000..e23f2c6f048 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_device.h @@ -0,0 +1,528 @@ +#pragma once + +#include "dxvk_adapter.h" +#include "dxvk_buffer.h" +#include "dxvk_compute.h" +#include "dxvk_constant_state.h" +#include "dxvk_context.h" +#include "dxvk_extensions.h" +#include "dxvk_fence.h" +#include "dxvk_framebuffer.h" +#include "dxvk_image.h" +#include "dxvk_instance.h" +#include "dxvk_memory.h" +#include "dxvk_meta_clear.h" +#include "dxvk_objects.h" +#include "dxvk_options.h" +#include "dxvk_pipecache.h" +#include "dxvk_pipemanager.h" +#include "dxvk_queue.h" +#include "dxvk_recycler.h" +#include "dxvk_renderpass.h" +#include "dxvk_sampler.h" +#include "dxvk_shader.h" +#include "dxvk_stats.h" +#include "dxvk_unbound.h" + +#include "../vulkan/vulkan_presenter.h" + +namespace dxvk { + + class DxvkInstance; + + /** + * \brief Device options + */ + struct DxvkDeviceOptions { + uint32_t maxNumDynamicUniformBuffers = 0; + uint32_t maxNumDynamicStorageBuffers = 0; + }; + + /** + * \brief Device performance hints + */ + struct DxvkDevicePerfHints { + VkBool32 preferFbDepthStencilCopy : 1; + VkBool32 preferFbResolve : 1; + }; + + /** + * \brief Device queue + * + * Stores a Vulkan queue and the + * queue family that it belongs to. + */ + struct DxvkDeviceQueue { + VkQueue queueHandle = VK_NULL_HANDLE; + uint32_t queueFamily = 0; + uint32_t queueIndex = 0; + }; + + /** + * \brief Device queue infos + */ + struct DxvkDeviceQueueSet { + DxvkDeviceQueue graphics; + DxvkDeviceQueue transfer; + }; + + /** + * \brief DXVK device + * + * Device object. This is responsible for resource creation, + * memory allocation, command submission and state tracking. + * Rendering commands are recorded into command lists using + * contexts. Multiple contexts can be created for a device. + */ + class DxvkDevice : public RcObject { + friend class DxvkContext; + friend class DxvkSubmissionQueue; + friend class DxvkDescriptorPoolTracker; + public: + + DxvkDevice( + const Rc& instance, + const Rc& adapter, + const Rc& vkd, + const DxvkDeviceExtensions& extensions, + const DxvkDeviceFeatures& features); + + ~DxvkDevice(); + + /** + * \brief Vulkan device functions + * \returns Vulkan device functions + */ + Rc vkd() const { + return m_vkd; + } + + /** + * \brief Logical device handle + * \returns The device handle + */ + VkDevice handle() const { + return m_vkd->device(); + } + + /** + * \brief Device options + * \returns Device options + */ + const DxvkOptions& config() const { + return m_options; + } + + /** + * \brief Queue handles + * + * Handles and queue family indices + * of all known device queues. + * \returns Device queue infos + */ + const DxvkDeviceQueueSet& queues() const { + return m_queues; + } + + /** + * \brief Tests whether a dedicated transfer queue is available + * \returns \c true if an SDMA queue is supported by the device + */ + bool hasDedicatedTransferQueue() const { + return m_queues.transfer.queueHandle + != m_queues.graphics.queueHandle; + } + + /** + * \brief The instance + * + * The DXVK instance that created this device. + * \returns Instance + */ + Rc instance() const { + return m_instance; + } + + /** + * \brief The adapter + * + * The physical device that the + * device has been created for. + * \returns Adapter + */ + Rc adapter() const { + return m_adapter; + } + + /** + * \brief Enabled device extensions + * \returns Enabled device extensions + */ + const DxvkDeviceExtensions& extensions() const { + return m_extensions; + } + + /** + * \brief Enabled device features + * \returns Enabled features + */ + const DxvkDeviceFeatures& features() const { + return m_features; + } + + /** + * \brief Device properties + * \returns Device properties + */ + const DxvkDeviceInfo& properties() const { + return m_properties; + } + + /** + * \brief Get device status + * + * This may report device loss in + * case a submission failed. + * \returns Device status + */ + VkResult getDeviceStatus() const { + return m_submissionQueue.getLastError(); + } + + /** + * \brief Checks whether this is a UMA system + * + * Basically tests whether all heaps are device-local. + * Can be used for various optimizations in client APIs. + * \returns \c true if the system has unified memory. + */ + bool isUnifiedMemoryArchitecture() const; + + /** + * \brief Queries default framebuffer size + * \returns Default framebuffer size + */ + DxvkFramebufferSize getDefaultFramebufferSize() const; + + /** + * \brief Queries supported shader stages + * \returns Supported shader pipeline stages + */ + VkPipelineStageFlags getShaderPipelineStages() const; + + /** + * \brief Retrieves device options + * \returns Device options + */ + DxvkDeviceOptions options() const; + + /** + * \brief Retrieves performance hints + * \returns Device-specific perf hints + */ + DxvkDevicePerfHints perfHints() const { + return m_perfHints; + } + + /** + * \brief Creates a command list + * \returns The command list + */ + Rc createCommandList(); + + /** + * \brief Creates a descriptor pool + * + * Returns a previously recycled pool, or creates + * a new one if necessary. The context should take + * ownership of the returned pool. + * \returns Descriptor pool + */ + Rc createDescriptorPool(); + + /** + * \brief Creates a context + * + * Creates a context object that can + * be used to record command buffers. + * \returns The context object + */ + Rc createContext(); + + /** + * \brief Creates a GPU event + * \returns New GPU event + */ + Rc createGpuEvent(); + + /** + * \brief Creates a query + * + * \param [in] type Query type + * \param [in] flags Query flags + * \param [in] index Query index + * \returns New query + */ + Rc createGpuQuery( + VkQueryType type, + VkQueryControlFlags flags, + uint32_t index); + + /** + * \brief Creates new fence + * + * \param [in] info Fence create info + * \returns The fence + */ + Rc createFence( + const DxvkFenceCreateInfo& fenceInfo); + + /** + * \brief Creates framebuffer for a set of render targets + * + * \param [in] info Framebuffer info + * \returns The framebuffer object + */ + Rc createFramebuffer( + const DxvkFramebufferInfo& info); + + /** + * \brief Creates a buffer object + * + * \param [in] createInfo Buffer create info + * \param [in] memoryType Memory type flags + * \returns The buffer object + */ + Rc createBuffer( + const DxvkBufferCreateInfo& createInfo, + VkMemoryPropertyFlags memoryType); + + /** + * \brief Creates a buffer view + * + * \param [in] buffer The buffer to view + * \param [in] createInfo Buffer view properties + * \returns The buffer view object + */ + Rc createBufferView( + const Rc& buffer, + const DxvkBufferViewCreateInfo& createInfo); + + /** + * \brief Creates an image object + * + * \param [in] createInfo Image create info + * \param [in] memoryType Memory type flags + * \returns The image object + */ + Rc createImage( + const DxvkImageCreateInfo& createInfo, + VkMemoryPropertyFlags memoryType); + + /** + * \brief Creates an image object for an existing VkImage + * + * \param [in] createInfo Image create info + * \param [in] image Vulkan image to wrap + * \returns The image object + */ + Rc createImageFromVkImage( + const DxvkImageCreateInfo& createInfo, + VkImage image); + + /** + * \brief Creates an image view + * + * \param [in] image The image to create a view for + * \param [in] createInfo Image view create info + * \returns The image view + */ + Rc createImageView( + const Rc& image, + const DxvkImageViewCreateInfo& createInfo); + + /** + * \brief Creates a sampler object + * + * \param [in] createInfo Sampler parameters + * \returns Newly created sampler object + */ + Rc createSampler( + const DxvkSamplerCreateInfo& createInfo); + + /** + * \brief Retrieves stat counters + * + * Can be used by the HUD to display some + * internal information, such as memory + * usage, draw calls, etc. + */ + DxvkStatCounters getStatCounters(); + + /** + * \brief Retrieves memors statistics + * + * \param [in] heap Memory heap index + * \returns Memory stats for this heap + */ + DxvkMemoryStats getMemoryStats(uint32_t heap); + + /** + * \brief Retreves current frame ID + * \returns Current frame ID + */ + uint32_t getCurrentFrameId() const; + + /** + * \brief Initializes dummy resources + * + * Should be called after creating the device in + * case the device initialization was successful + * and the device is usable. + */ + void initResources(); + + /** + * \brief Registers a shader + * \param [in] shader Newly compiled shader + */ + void registerShader( + const Rc& shader); + + /** + * \brief Presents a swap chain image + * + * Invokes the presenter's \c presentImage method on + * the submission thread. The status of this operation + * can be retrieved with \ref waitForSubmission. + * \param [in] presenter The presenter + * \param [out] status Present status + */ + void presentImage( + const Rc& presenter, + DxvkSubmitStatus* status); + + /** + * \brief Submits a command list + * + * Submits the given command list to the device using + * the given set of optional synchronization primitives. + * \param [in] commandList The command list to submit + * \param [in] waitSync (Optional) Semaphore to wait on + * \param [in] wakeSync (Optional) Semaphore to notify + */ + void submitCommandList( + const Rc& commandList, + VkSemaphore waitSync, + VkSemaphore wakeSync); + + /** + * \brief Locks submission queue + * + * Since Vulkan queues are only meant to be accessed + * from one thread at a time, external libraries need + * to lock the queue before submitting command buffers. + */ + void lockSubmission() { + m_submissionQueue.synchronize(); + m_submissionQueue.lockDeviceQueue(); + } + + /** + * \brief Unlocks submission queue + * + * Releases the Vulkan queues again so that DXVK + * itself can use them for submissions again. + */ + void unlockSubmission() { + m_submissionQueue.unlockDeviceQueue(); + } + + /** + * \brief Number of pending submissions + * + * A return value of 0 indicates + * that the GPU is currently idle. + * \returns Pending submission count + */ + uint32_t pendingSubmissions() const { + return m_submissionQueue.pendingSubmissions(); + } + + /** + * \brief Increments a given stat counter + * + * \param [in] counter Stat counter to increment + * \param [in] value Increment value + */ + void addStatCtr(DxvkStatCounter counter, uint64_t value) { + std::lock_guard lock(m_statLock); + m_statCounters.addCtr(counter, value); + } + + /** + * \brief Waits for a given submission + * + * \param [in,out] status Submission status + * \returns Result of the submission + */ + VkResult waitForSubmission(DxvkSubmitStatus* status); + + /** + * \brief Waits for resource to become idle + * + * \param [in] resource Resource to wait for + * \param [in] access Access mode to check + */ + void waitForResource(const Rc& resource, DxvkAccess access); + + /** + * \brief Waits until the device becomes idle + * + * Waits for the GPU to complete the execution of all + * previously submitted command buffers. This may be + * used to ensure that resources that were previously + * used by the GPU can be safely destroyed. + */ + void waitForIdle(); + + private: + + DxvkOptions m_options; + + Rc m_instance; + Rc m_adapter; + Rc m_vkd; + DxvkDeviceExtensions m_extensions; + + DxvkDeviceFeatures m_features; + DxvkDeviceInfo m_properties; + + DxvkDevicePerfHints m_perfHints; + DxvkObjects m_objects; + + sync::Spinlock m_statLock; + DxvkStatCounters m_statCounters; + + DxvkDeviceQueueSet m_queues; + + DxvkRecycler m_recycledCommandLists; + DxvkRecycler m_recycledDescriptorPools; + + DxvkSubmissionQueue m_submissionQueue; + + DxvkDevicePerfHints getPerfHints(); + + void recycleCommandList( + const Rc& cmdList); + + void recycleDescriptorPool( + const Rc& pool); + + DxvkDeviceQueue getQueue( + uint32_t family, + uint32_t index) const; + + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_device_filter.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_device_filter.cpp new file mode 100644 index 00000000000..02d8329eed4 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_device_filter.cpp @@ -0,0 +1,40 @@ +#include "dxvk_device_filter.h" + +namespace dxvk { + + DxvkDeviceFilter::DxvkDeviceFilter(DxvkDeviceFilterFlags flags) + : m_flags(flags) { + m_matchDeviceName = env::getEnvVar("DXVK_FILTER_DEVICE_NAME"); + + if (m_matchDeviceName.size() != 0) + m_flags.set(DxvkDeviceFilterFlag::MatchDeviceName); + } + + + DxvkDeviceFilter::~DxvkDeviceFilter() { + + } + + + bool DxvkDeviceFilter::testAdapter(const VkPhysicalDeviceProperties& properties) const { + if (properties.apiVersion < VK_MAKE_VERSION(1, 1, 0)) { + Logger::warn(str::format("Skipping Vulkan 1.0 adapter: ", properties.deviceName)); + return false; + } + + if (m_flags.test(DxvkDeviceFilterFlag::MatchDeviceName)) { + if (std::string(properties.deviceName).find(m_matchDeviceName) == std::string::npos) + return false; + } + + if (m_flags.test(DxvkDeviceFilterFlag::SkipCpuDevices)) { + if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU) { + Logger::warn(str::format("Skipping CPU adapter: ", properties.deviceName)); + return false; + } + } + + return true; + } + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_device_filter.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_device_filter.h new file mode 100644 index 00000000000..7b411e6ad29 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_device_filter.h @@ -0,0 +1,54 @@ +#pragma once + +#include "dxvk_adapter.h" + +namespace dxvk { + + /** + * \brief Device filter flags + * + * The device filter flags specify which device + * properties are considered when testing adapters. + * If no flags are set, all devices pass the test. + */ + enum class DxvkDeviceFilterFlag { + MatchDeviceName = 0, + SkipCpuDevices = 1, + }; + + using DxvkDeviceFilterFlags = Flags; + + + /** + * \brief DXVK device filter + * + * Used to select specific Vulkan devices to use + * with DXVK. This may be useful for games which + * do not offer an option to select the correct + * device. + */ + class DxvkDeviceFilter { + + public: + + DxvkDeviceFilter(DxvkDeviceFilterFlags flags); + ~DxvkDeviceFilter(); + + /** + * \brief Tests an adapter + * + * \param [in] properties Adapter properties + * \returns \c true if the test passes + */ + bool testAdapter( + const VkPhysicalDeviceProperties& properties) const; + + private: + + DxvkDeviceFilterFlags m_flags; + + std::string m_matchDeviceName; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_device_info.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_device_info.h new file mode 100644 index 00000000000..5b740674c3d --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_device_info.h @@ -0,0 +1,56 @@ +#pragma once + +#include "dxvk_include.h" + +namespace dxvk { + + /** + * \brief Device info + * + * Stores core properties and a bunch of extension-specific + * properties, if the respective extensions are available. + * Structures for unsupported extensions will be undefined, + * so before using them, check whether they are supported. + */ + struct DxvkDeviceInfo { + VkPhysicalDeviceProperties2 core; + VkPhysicalDeviceIDProperties coreDeviceId; + VkPhysicalDeviceSubgroupProperties coreSubgroup; + VkPhysicalDeviceConservativeRasterizationPropertiesEXT extConservativeRasterization; + VkPhysicalDeviceCustomBorderColorPropertiesEXT extCustomBorderColor; + VkPhysicalDeviceRobustness2PropertiesEXT extRobustness2; + VkPhysicalDeviceTransformFeedbackPropertiesEXT extTransformFeedback; + VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT extVertexAttributeDivisor; + VkPhysicalDeviceDepthStencilResolvePropertiesKHR khrDepthStencilResolve; + VkPhysicalDeviceDriverPropertiesKHR khrDeviceDriverProperties; + VkPhysicalDeviceFloatControlsPropertiesKHR khrShaderFloatControls; + VkPhysicalDeviceTimelineSemaphorePropertiesKHR khrTimelineSemaphore; + }; + + + /** + * \brief Device features + * + * Stores core features and extension-specific features. + * If the respective extensions are not available, the + * extended features will be marked as unsupported. + */ + struct DxvkDeviceFeatures { + VkPhysicalDeviceFeatures2 core; + VkPhysicalDeviceShaderDrawParametersFeatures shaderDrawParameters; + VkPhysicalDevice4444FormatsFeaturesEXT ext4444Formats; + VkPhysicalDeviceCustomBorderColorFeaturesEXT extCustomBorderColor; + VkPhysicalDeviceDepthClipEnableFeaturesEXT extDepthClipEnable; + VkPhysicalDeviceExtendedDynamicStateFeaturesEXT extExtendedDynamicState; + VkPhysicalDeviceHostQueryResetFeaturesEXT extHostQueryReset; + VkPhysicalDeviceMemoryPriorityFeaturesEXT extMemoryPriority; + VkPhysicalDeviceNonSeamlessCubeMapFeaturesEXT extNonSeamlessCubeMap; + VkPhysicalDeviceRobustness2FeaturesEXT extRobustness2; + VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT extShaderDemoteToHelperInvocation; + VkPhysicalDeviceTransformFeedbackFeaturesEXT extTransformFeedback; + VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT extVertexAttributeDivisor; + VkPhysicalDeviceBufferDeviceAddressFeaturesKHR khrBufferDeviceAddress; + VkPhysicalDeviceTimelineSemaphoreFeaturesKHR khrTimelineSemaphore; + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_extension_provider.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_extension_provider.h new file mode 100644 index 00000000000..090d56d3f81 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_extension_provider.h @@ -0,0 +1,67 @@ +#pragma once + +#include "dxvk_include.h" +#include "dxvk_extensions.h" + +#include +#include + +namespace dxvk { + + class DxvkInstance; + class DxvkExtensionProvider; + + /** + * \brief Extension provider base + * + * Abstract interface for extension + * providers + */ + class DxvkExtensionProvider { + + public: + + /** + * \brief Extension provider name + * \returns The extension provider's name + */ + virtual std::string_view getName() = 0; + + /** + * \brief Query instance extensions + * \returns Instance extensions + */ + virtual DxvkNameSet getInstanceExtensions() = 0; + + /** + * \brief Query device extensions + * + * Retrieves the extensions required for a specific + * physical device. The adapter index should remain + * the same across multiple Vulkan instances. + * \param [in] adapterId Adapter index + */ + virtual DxvkNameSet getDeviceExtensions( + uint32_t adapterId) = 0; + + /** + * \brief Initializes instance extension set + * + * Should be called before creating + * the first Vulkan instance. + */ + virtual void initInstanceExtensions() = 0; + + /** + * \brief Initializes device extension sets + * + * Should be called after setting + * up the Vulkan physical devices. + * \param [in] instance DXVK instance + */ + virtual void initDeviceExtensions( + const DxvkInstance* instance) = 0; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_extensions.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_extensions.cpp new file mode 100644 index 00000000000..6cb4c325ceb --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_extensions.cpp @@ -0,0 +1,132 @@ +#include "dxvk_extensions.h" + +namespace dxvk { + + DxvkNameSet::DxvkNameSet() { } + DxvkNameSet::~DxvkNameSet() { } + + + void DxvkNameSet::add(const char* pName) { + m_names.insert({ pName, 1u }); + } + + + void DxvkNameSet::merge(const DxvkNameSet& names) { + for (const auto& pair : names.m_names) + m_names.insert(pair); + } + + + uint32_t DxvkNameSet::supports(const char* pName) const { + auto entry = m_names.find(pName); + + if (entry == m_names.end()) + return 0; + + return entry->second != 0 + ? entry->second + : 1; + } + + + bool DxvkNameSet::enableExtensions( + uint32_t numExtensions, + DxvkExt** ppExtensions, + DxvkNameSet& nameSet) const { + bool allRequiredEnabled = true; + + for (uint32_t i = 0; i < numExtensions; i++) { + DxvkExt* ext = ppExtensions[i]; + + if (ext->mode() == DxvkExtMode::Disabled) + continue; + + uint32_t revision = supports(ext->name()); + + if (revision) { + if (ext->mode() != DxvkExtMode::Passive) + nameSet.add(ext->name()); + + ext->enable(revision); + } else if (ext->mode() == DxvkExtMode::Required) { + Logger::info(str::format("Required Vulkan extension ", ext->name(), " not supported")); + allRequiredEnabled = false; + continue; + } + } + + return allRequiredEnabled; + } + + + void DxvkNameSet::disableExtension( + DxvkExt& ext) { + m_names.erase(ext.name()); + ext.disable(); + } + + + DxvkNameList DxvkNameSet::toNameList() const { + DxvkNameList nameList; + for (const auto& pair : m_names) + nameList.add(pair.first.c_str()); + return nameList; + } + + + DxvkNameSet DxvkNameSet::enumInstanceLayers(const Rc& vkl) { + uint32_t entryCount = 0; + if (vkl->vkEnumerateInstanceLayerProperties( + &entryCount, nullptr) != VK_SUCCESS) + return DxvkNameSet(); + + std::vector entries(entryCount); + if (vkl->vkEnumerateInstanceLayerProperties( + &entryCount, entries.data()) != VK_SUCCESS) + return DxvkNameSet(); + + DxvkNameSet set; + for (uint32_t i = 0; i < entryCount; i++) + set.m_names.insert({ entries[i].layerName, entries[i].specVersion }); + return set; + } + + + DxvkNameSet DxvkNameSet::enumInstanceExtensions(const Rc& vkl) { + uint32_t entryCount = 0; + if (vkl->vkEnumerateInstanceExtensionProperties( + nullptr, &entryCount, nullptr) != VK_SUCCESS) + return DxvkNameSet(); + + std::vector entries(entryCount); + if (vkl->vkEnumerateInstanceExtensionProperties( + nullptr, &entryCount, entries.data()) != VK_SUCCESS) + return DxvkNameSet(); + + DxvkNameSet set; + for (uint32_t i = 0; i < entryCount; i++) + set.m_names.insert({ entries[i].extensionName, entries[i].specVersion }); + return set; + } + + + DxvkNameSet DxvkNameSet::enumDeviceExtensions( + const Rc& vki, + VkPhysicalDevice device) { + uint32_t entryCount = 0; + if (vki->vkEnumerateDeviceExtensionProperties( + device, nullptr, &entryCount, nullptr) != VK_SUCCESS) + return DxvkNameSet(); + + std::vector entries(entryCount); + if (vki->vkEnumerateDeviceExtensionProperties( + device, nullptr, &entryCount, entries.data()) != VK_SUCCESS) + return DxvkNameSet(); + + DxvkNameSet set; + for (uint32_t i = 0; i < entryCount; i++) + set.m_names.insert({ entries[i].extensionName, entries[i].specVersion }); + return set; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_extensions.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_extensions.h new file mode 100644 index 00000000000..0e2808d12fc --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_extensions.h @@ -0,0 +1,325 @@ +#pragma once + +#include +#include +#include + +#include "dxvk_include.h" + +namespace dxvk { + + /** + * \brief Vulkan extension mode + * + * Defines whether an extension is + * optional, required, or disabled. + */ + enum class DxvkExtMode { + Disabled, + Optional, + Required, + Passive, + }; + + + /** + * \brief Vulkan extension info + * + * Stores information for a single extension. + * The renderer can use this information to + * find out which extensions are enabled. + */ + class DxvkExt { + + public: + + DxvkExt( + const char* pName, + DxvkExtMode mode) + : m_name(pName), m_mode(mode) { } + + /** + * \brief Extension name + * \returns Extension name + */ + const char* name() const { + return m_name; + } + + /** + * \brief Extension mode + * \returns Extension mode + */ + DxvkExtMode mode() const { + return m_mode; + } + + /** + * \brief Checks whether the extension is enabled + * + * If an extension is enabled, the features + * provided by the extension can be used. + * \returns \c true if the extension is enabled + */ + operator bool () const { + return m_revision != 0; + } + + /** + * \brief Supported revision + * \returns Supported revision + */ + uint32_t revision() const { + return m_revision; + } + + /** + * \brief Changes extension mode + * + * In some cases, it may be useful to change the + * default mode dynamically after initialization. + */ + void setMode(DxvkExtMode mode) { + m_mode = mode; + } + + /** + * \brief Enables the extension + */ + void enable(uint32_t revision) { + m_revision = revision; + } + + /** + * \brief Disables the extension + */ + void disable() { + m_revision = 0; + } + + private: + + const char* m_name = nullptr; + DxvkExtMode m_mode = DxvkExtMode::Disabled; + uint32_t m_revision = 0; + + }; + + + /** + * \brief Vulkan name list + * + * A simple \c vector wrapper that can + * be used to build a list of layer and + * extension names. + */ + class DxvkNameList { + + public: + + /** + * \brief Adds a name + * \param [in] pName The name + */ + void add(const char* pName) { + m_names.push_back(pName); + } + + /** + * \brief Number of names + * \returns Name count + */ + uint32_t count() const { + return m_names.size(); + } + + /** + * \brief Name list + * \returns Name list + */ + const char* const* names() const { + return m_names.data(); + } + + /** + * \brief Retrieves a single name + * + * \param [in] index Name index + * \returns The given name + */ + const char* name(uint32_t index) const { + return m_names.at(index); + } + + private: + + std::vector m_names; + + }; + + + /** + * \brief Vulkan extension set + * + * Stores a set of extensions or layers + * supported by the Vulkan implementation. + */ + class DxvkNameSet { + + public: + + DxvkNameSet(); + ~DxvkNameSet(); + + /** + * \brief Adds a name to the set + * \param [in] pName Extension name + */ + void add( + const char* pName); + + /** + * \brief Merges two name sets + * + * Adds all names from the given name set to + * this name set, avoiding duplicate entries. + * \param [in] names Name set to merge + */ + void merge( + const DxvkNameSet& names); + + /** + * \brief Checks whether an extension is supported + * + * \param [in] pName Extension name + * \returns Supported revision, or zero + */ + uint32_t supports( + const char* pName) const; + + /** + * \brief Enables requested extensions + * + * Walks over a set of extensions and enables all + * extensions that are supported and not disabled. + * This also checks whether all required extensions + * could be enabled, and returns \c false otherwise. + * \param [in] numExtensions Number of extensions + * \param [in] ppExtensions List of extensions + * \param [out] nameSet Extension name set + * \returns \c true on success + */ + bool enableExtensions( + uint32_t numExtensions, + DxvkExt** ppExtensions, + DxvkNameSet& nameSet) const; + + /** + * \brief Disables given extension + * + * Removes the given extension from the set + * and sets its revision to 0 (i.e. disabled). + * \param [in,out] ext Extension to disable + */ + void disableExtension( + DxvkExt& ext); + + /** + * \brief Creates name list from name set + * + * Adds all names contained in the name set + * to a name list, which can then be passed + * to Vulkan functions. + * \returns Name list + */ + DxvkNameList toNameList() const; + + /** + * \brief Enumerates instance layers + * + * \param [in] vkl Vulkan library functions + * \returns Set of available instance layers + */ + static DxvkNameSet enumInstanceLayers( + const Rc& vkl); + + /** + * \brief Enumerates instance extensions + * + * \param [in] vkl Vulkan library functions + * \returns Set of available instance extensions + */ + static DxvkNameSet enumInstanceExtensions( + const Rc& vkl); + + /** + * \brief Enumerates device extensions + * + * \param [in] vki Vulkan instance functions + * \param [in] device The device to query + * \returns Set of available device extensions + */ + static DxvkNameSet enumDeviceExtensions( + const Rc& vki, + VkPhysicalDevice device); + + private: + + std::map m_names; + + }; + + /** + * \brief Device extensions + * + * Lists all Vulkan extensions that are potentially + * used by DXVK if supported by the implementation. + */ + struct DxvkDeviceExtensions { + DxvkExt amdMemoryOverallocationBehaviour = { VK_AMD_MEMORY_OVERALLOCATION_BEHAVIOR_EXTENSION_NAME, DxvkExtMode::Optional }; + DxvkExt amdShaderFragmentMask = { VK_AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME, DxvkExtMode::Optional }; + DxvkExt ext4444Formats = { VK_EXT_4444_FORMATS_EXTENSION_NAME, DxvkExtMode::Optional }; + DxvkExt extConservativeRasterization = { VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME, DxvkExtMode::Optional }; + DxvkExt extCustomBorderColor = { VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME, DxvkExtMode::Optional }; + DxvkExt extDepthClipEnable = { VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME, DxvkExtMode::Optional }; + DxvkExt extExtendedDynamicState = { VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME, DxvkExtMode::Optional }; + DxvkExt extFullScreenExclusive = { VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME, DxvkExtMode::Optional }; + DxvkExt extHostQueryReset = { VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME, DxvkExtMode::Optional }; + DxvkExt extMemoryBudget = { VK_EXT_MEMORY_BUDGET_EXTENSION_NAME, DxvkExtMode::Passive }; + DxvkExt extMemoryPriority = { VK_EXT_MEMORY_PRIORITY_EXTENSION_NAME, DxvkExtMode::Optional }; + DxvkExt extNonSeamlessCubeMap = { VK_EXT_NON_SEAMLESS_CUBE_MAP_EXTENSION_NAME, DxvkExtMode::Optional }; + DxvkExt extRobustness2 = { VK_EXT_ROBUSTNESS_2_EXTENSION_NAME, DxvkExtMode::Optional }; + DxvkExt extShaderDemoteToHelperInvocation = { VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME, DxvkExtMode::Optional }; + DxvkExt extShaderStencilExport = { VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME, DxvkExtMode::Optional }; + DxvkExt extShaderViewportIndexLayer = { VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME, DxvkExtMode::Optional }; + DxvkExt extTransformFeedback = { VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME, DxvkExtMode::Optional }; + DxvkExt extVertexAttributeDivisor = { VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME, DxvkExtMode::Optional }; + DxvkExt khrBufferDeviceAddress = { VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME, DxvkExtMode::Disabled }; + DxvkExt khrCreateRenderPass2 = { VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME, DxvkExtMode::Optional }; + DxvkExt khrDepthStencilResolve = { VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME, DxvkExtMode::Optional }; + DxvkExt khrDrawIndirectCount = { VK_KHR_DRAW_INDIRECT_COUNT_EXTENSION_NAME, DxvkExtMode::Optional }; + DxvkExt khrDriverProperties = { VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME, DxvkExtMode::Optional }; + DxvkExt khrExternalMemoryWin32 = { VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME, DxvkExtMode::Optional }; + DxvkExt khrExternalSemaphoreWin32 = { VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME, DxvkExtMode::Optional }; + DxvkExt khrImageFormatList = { VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME, DxvkExtMode::Required }; + DxvkExt khrSamplerMirrorClampToEdge = { VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME, DxvkExtMode::Optional }; + DxvkExt khrShaderFloatControls = { VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME, DxvkExtMode::Optional }; + DxvkExt khrSwapchain = { VK_KHR_SWAPCHAIN_EXTENSION_NAME, DxvkExtMode::Required }; + DxvkExt khrTimelineSemaphore = { VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME, DxvkExtMode::Optional }; + DxvkExt nvxBinaryImport = { VK_NVX_BINARY_IMPORT_EXTENSION_NAME, DxvkExtMode::Disabled }; + DxvkExt nvxImageViewHandle = { VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME, DxvkExtMode::Disabled }; + }; + + /** + * \brief Instance extensions + * + * Lists all Vulkan extensions that are potentially + * used by DXVK if supported by the implementation. + */ + struct DxvkInstanceExtensions { + DxvkExt extDebugUtils = { VK_EXT_DEBUG_UTILS_EXTENSION_NAME, DxvkExtMode::Optional }; + DxvkExt khrGetSurfaceCapabilities2 = { VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME, DxvkExtMode::Optional }; + DxvkExt khrSurface = { VK_KHR_SURFACE_EXTENSION_NAME, DxvkExtMode::Required }; + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_fence.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_fence.cpp new file mode 100644 index 00000000000..fc79584933a --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_fence.cpp @@ -0,0 +1,152 @@ +#include "dxvk_device.h" +#include "dxvk_fence.h" + +namespace dxvk { + + DxvkFence::DxvkFence( + DxvkDevice* device, + const DxvkFenceCreateInfo& info) + : m_vkd(device->vkd()), m_info(info) { + if (!device->features().khrTimelineSemaphore.timelineSemaphore) + throw DxvkError("Timeline semaphores not supported"); + + VkSemaphoreTypeCreateInfoKHR typeInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO_KHR }; + typeInfo.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE_KHR; + typeInfo.initialValue = info.initialValue; + + VkExportSemaphoreCreateInfo exportInfo = { VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO }; + exportInfo.handleTypes = info.sharedType; + + VkExternalSemaphoreFeatureFlags externalFeatures = 0; + + if (info.sharedType != VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FLAG_BITS_MAX_ENUM) { + auto vki = device->adapter()->vki(); + + VkPhysicalDeviceExternalSemaphoreInfo externalInfo = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO, &typeInfo }; + externalInfo.handleType = info.sharedType; + + VkExternalSemaphoreProperties externalProperties = { }; + vki->vkGetPhysicalDeviceExternalSemaphoreProperties( + device->adapter()->handle(), &externalInfo, &externalProperties); + + externalFeatures = externalProperties.externalSemaphoreFeatures; + + if (externalFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT) + typeInfo.pNext = &exportInfo; + else + Logger::warn(str::format("Exporting semaphores of type ", info.sharedType, " not supported by device")); + } + + VkSemaphoreCreateInfo semaphoreInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, &typeInfo }; + + VkResult vr = m_vkd->vkCreateSemaphore(m_vkd->device(), + &semaphoreInfo, nullptr, &m_semaphore); + + if (vr != VK_SUCCESS) + throw DxvkError("Failed to create timeline semaphore"); + + if (info.sharedHandle != INVALID_HANDLE_VALUE) { + if (externalFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT) { + VkImportSemaphoreWin32HandleInfoKHR importInfo = { VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR }; + importInfo.semaphore = m_semaphore; + importInfo.handleType = info.sharedType; + importInfo.handle = info.sharedHandle; + + vr = m_vkd->vkImportSemaphoreWin32HandleKHR(m_vkd->device(), &importInfo); + if (vr != VK_SUCCESS) + throw DxvkError("Failed to import timeline semaphore"); + } else { + Logger::warn(str::format("Importing semaphores of type ", info.sharedType, " not supported by device")); + } + } + + m_thread = dxvk::thread([this] { run(); }); + } + + + DxvkFence::~DxvkFence() { + m_stop.store(true); + m_thread.join(); + + m_vkd->vkDestroySemaphore(m_vkd->device(), m_semaphore, nullptr); + } + + + void DxvkFence::enqueueWait(uint64_t value, DxvkFenceEvent&& event) { + std::unique_lock lock(m_mutex); + + if (value > m_lastValue.load()) + m_queue.emplace(value, std::move(event)); + else + event(); + } + + + void DxvkFence::run() { + uint64_t value = 0ull; + + VkSemaphoreWaitInfoKHR waitInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO_KHR }; + waitInfo.semaphoreCount = 1; + waitInfo.pSemaphores = &m_semaphore; + waitInfo.pValues = &value; + + while (!m_stop.load()) { + std::unique_lock lock(m_mutex); + + // Query actual semaphore value and start from there, so that + // we can skip over large increments in the semaphore value + VkResult vr = m_vkd->vkGetSemaphoreCounterValueKHR(m_vkd->device(), m_semaphore, &value); + + if (vr != VK_SUCCESS) { + Logger::err(str::format("Failed to query semaphore value: ", vr)); + return; + } + + m_lastValue.store(value); + + // Signal all enqueued events whose value is not greater than + // the current semaphore value + while (!m_queue.empty() && m_queue.top().value <= value) { + m_queue.top().event(); + m_queue.pop(); + } + + if (m_stop) + return; + + lock.unlock(); + + // Wait for the semaphore to be singaled again and update state. + // The timeout is unfortunate, but we can't always know when a + // signal operation has been recorded, and the alternative would + // be to create a teardown semaphore and use WAIT_ANY, which may + // be fall back to a busy-wait loop on some drivers. + value += 1; + + vr = m_vkd->vkWaitSemaphoresKHR( + m_vkd->device(), &waitInfo, 10'000'000ull); + + if (vr != VK_SUCCESS && vr != VK_TIMEOUT) { + Logger::err(str::format("Failed to wait for semaphore: ", vr)); + return; + } + } + } + + HANDLE DxvkFence::sharedHandle() const { + if (m_info.sharedType == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FLAG_BITS_MAX_ENUM) + return INVALID_HANDLE_VALUE; + + VkSemaphoreGetWin32HandleInfoKHR win32HandleInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR }; + win32HandleInfo.semaphore = m_semaphore; + win32HandleInfo.handleType = m_info.sharedType; + + HANDLE sharedHandle = INVALID_HANDLE_VALUE; + VkResult vr = m_vkd->vkGetSemaphoreWin32HandleKHR(m_vkd->device(), &win32HandleInfo, &sharedHandle); + + if (vr != VK_SUCCESS) + Logger::err(str::format("Failed to get semaphore handle: ", vr)); + + return sharedHandle; + } +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_fence.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_fence.h new file mode 100644 index 00000000000..7974528605d --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_fence.h @@ -0,0 +1,129 @@ +#pragma once + +#include +#include +#include +#include + +#include "dxvk_resource.h" + +#include "../util/thread.h" + +namespace dxvk { + + class DxvkDevice; + class DxvkFence; + + using DxvkFenceEvent = std::function; + + /** + * \brief Fence create info + */ + struct DxvkFenceCreateInfo { + uint64_t initialValue; + VkExternalSemaphoreHandleTypeFlagBits sharedType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FLAG_BITS_MAX_ENUM; + union { +#ifdef _WIN32 + HANDLE sharedHandle = INVALID_HANDLE_VALUE; +#else + // Placeholder for other handle types, such as FD + void *dummy; +#endif + }; + }; + + /** + * \brief Fence-value pair + */ + struct DxvkFenceValuePair { + DxvkFenceValuePair() { } + DxvkFenceValuePair(Rc&& fence_, uint64_t value_) + : fence(std::move(fence_)), value(value_) { } + DxvkFenceValuePair(const Rc& fence_, uint64_t value_) + : fence(fence_), value(value_) { } + + Rc fence; + uint64_t value; + }; + + /** + * \brief Fence + * + * Wrapper around Vulkan timeline semaphores that + * can signal an event when the value changes. + */ + class DxvkFence : public RcObject { + + public: + + DxvkFence( + DxvkDevice* device, + const DxvkFenceCreateInfo& info); + + ~DxvkFence(); + + /** + * \brief Semaphore handle + */ + VkSemaphore handle() const { + return m_semaphore; + } + + /** + * \brief Retrieves current semaphore value + * \returns Current semaphore value + */ + uint64_t getValue() { + return m_lastValue.load(); + } + + /** + * \brief Enqueues semaphore wait + * + * Signals the given event when the + * semaphore reaches the given value. + * \param [in] value Enqueue value + * \param [in] event Callback + */ + void enqueueWait(uint64_t value, DxvkFenceEvent&& event); + + /** + * \brief Create a new shared handle to timeline semaphore backing the fence + * \returns The shared handle with the type given by DxvkFenceCreateInfo::sharedType + */ + HANDLE sharedHandle() const; + + private: + + struct QueueItem { + QueueItem() { } + QueueItem(uint32_t v, DxvkFenceEvent&& e) + : value(v), event(std::move(e)) { } + + uint64_t value; + DxvkFenceEvent event; + + bool operator == (const QueueItem& item) const { return value == item.value; } + bool operator != (const QueueItem& item) const { return value != item.value; } + bool operator < (const QueueItem& item) const { return value < item.value; } + bool operator <= (const QueueItem& item) const { return value <= item.value; } + bool operator > (const QueueItem& item) const { return value > item.value; } + bool operator >= (const QueueItem& item) const { return value >= item.value; } + }; + + Rc m_vkd; + DxvkFenceCreateInfo m_info; + VkSemaphore m_semaphore; + + std::priority_queue m_queue; + std::atomic m_lastValue = { 0ull }; + std::atomic m_stop = { false }; + + dxvk::mutex m_mutex; + dxvk::thread m_thread; + + void run(); + + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_format.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_format.cpp new file mode 100644 index 00000000000..1b76510acc7 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_format.cpp @@ -0,0 +1,591 @@ +#include "dxvk_format.h" + +namespace dxvk { + + constexpr VkColorComponentFlags RGBA = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + constexpr VkColorComponentFlags RGB = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT; + constexpr VkColorComponentFlags RG = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT; + constexpr VkColorComponentFlags R = VK_COLOR_COMPONENT_R_BIT; + + const std::array g_formatInfos = {{ + // VK_FORMAT_UNDEFINED + { }, + + // VK_FORMAT_R4G4_UNORM_PACK8 + { 1, RG, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R4G4B4A4_UNORM_PACK16 + { 2, RGBA, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_B4G4R4A4_UNORM_PACK16 + { 2, RGBA, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R5G6B5_UNORM_PACK16 + { 2, RGB, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_B5G6R5_UNORM_PACK16 + { 2, RGB, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R5G5B5A1_UNORM_PACK16 + { 2, RGBA, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_B5G5R5A1_UNORM_PACK16 + { 2, RGBA, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_A1R5G5B5_UNORM_PACK16 + { 2, RGBA, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R8_UNORM + { 1, R, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R8_SNORM + { 1, R, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R8_USCALED + { 1, R, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R8_SSCALED + { 1, R, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R8_UINT + { 1, R, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledUInt }, + + // VK_FORMAT_R8_SINT + { 1, R, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledSInt }, + + // VK_FORMAT_R8_SRGB + { 1, R, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::ColorSpaceSrgb }, + + // VK_FORMAT_R8G8_UNORM + { 2, RG, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R8G8_SNORM + { 2, RG, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R8G8_USCALED + { 2, RG, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R8G8_SSCALED + { 2, RG, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R8G8_UINT + { 2, RG, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledUInt }, + + // VK_FORMAT_R8G8_SINT + { 2, RG, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledSInt }, + + // VK_FORMAT_R8G8_SRGB + { 2, RG, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::ColorSpaceSrgb }, + + // VK_FORMAT_R8G8B8_UNORM + { 3, RGB, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R8G8B8_SNORM + { 3, RGB, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R8G8B8_USCALED + { 3, RGB, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R8G8B8_SSCALED + { 3, RGB, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R8G8B8_UINT + { 3, RGB, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledUInt }, + + // VK_FORMAT_R8G8B8_SINT + { 3, RGB, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledSInt }, + + // VK_FORMAT_R8G8B8_SRGB + { 3, RGB, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::ColorSpaceSrgb }, + + // VK_FORMAT_B8G8R8_UNORM + { 3, RGB, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_B8G8R8_SNORM + { 3, RGB, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_B8G8R8_USCALED + { 3, RGB, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_B8G8R8_SSCALED + { 3, RGB, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_B8G8R8_UINT + { 3, RGB, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledUInt }, + + // VK_FORMAT_B8G8R8_SINT + { 3, RGB, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledSInt }, + + // VK_FORMAT_B8G8R8_SRGB + { 3, RGB, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::ColorSpaceSrgb }, + + // VK_FORMAT_R8G8B8A8_UNORM + { 4, RGBA, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R8G8B8A8_SNORM + { 4, RGBA, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R8G8B8A8_USCALED + { 4, RGBA, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R8G8B8A8_SSCALED + { 4, RGBA, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R8G8B8A8_UINT + { 4, RGBA, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledUInt }, + + // VK_FORMAT_R8G8B8A8_SINT + { 4, RGBA, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledSInt }, + + // VK_FORMAT_R8G8B8A8_SRGB + { 4, RGBA, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::ColorSpaceSrgb }, + + // VK_FORMAT_B8G8R8A8_UNORM + { 4, RGBA, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_B8G8R8A8_SNORM + { 4, RGBA, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_B8G8R8A8_USCALED + { 4, RGBA, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_B8G8R8A8_SSCALED + { 4, RGBA, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_B8G8R8A8_UINT + { 4, RGBA, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledUInt }, + + // VK_FORMAT_B8G8R8A8_SINT + { 4, RGBA, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledSInt }, + + // VK_FORMAT_B8G8R8A8_SRGB + { 4, RGBA, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::ColorSpaceSrgb }, + + // VK_FORMAT_A8B8G8R8_UNORM_PACK32 + { 4, RGBA, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_A8B8G8R8_SNORM_PACK32 + { 4, RGBA, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_A8B8G8R8_USCALED_PACK32 + { 4, RGBA, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_A8B8G8R8_SSCALED_PACK32 + { 4, RGBA, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_A8B8G8R8_UINT_PACK32 + { 4, RGBA, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledUInt }, + + // VK_FORMAT_A8B8G8R8_SINT_PACK32 + { 4, RGBA, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledSInt }, + + // VK_FORMAT_A8B8G8R8_SRGB_PACK32 + { 4, RGBA, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::ColorSpaceSrgb }, + + // VK_FORMAT_A2R10G10B10_UNORM_PACK32 + { 4, RGBA, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_A2R10G10B10_SNORM_PACK32 + { 4, RGBA, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_A2R10G10B10_USCALED_PACK32 + { 4, RGBA, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_A2R10G10B10_SSCALED_PACK32 + { 4, RGBA, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_A2R10G10B10_UINT_PACK32 + { 4, RGBA, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledUInt }, + + // VK_FORMAT_A2R10G10B10_SINT_PACK32 + { 4, RGBA, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledSInt }, + + // VK_FORMAT_A2B10G10R10_UNORM_PACK32 + { 4, RGBA, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_A2B10G10R10_SNORM_PACK32 + { 4, RGBA, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_A2B10G10R10_USCALED_PACK32 + { 4, RGBA, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_A2B10G10R10_SSCALED_PACK32 + { 4, RGBA, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_A2B10G10R10_UINT_PACK32 + { 4, RGBA, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledUInt }, + + // VK_FORMAT_A2B10G10R10_SINT_PACK32 + { 4, RGBA, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledSInt }, + + // VK_FORMAT_R16_UNORM + { 2, R, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R16_SNORM + { 2, R, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R16_USCALED + { 2, R, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R16_SSCALED + { 2, R, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R16_UINT + { 2, R, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledUInt }, + + // VK_FORMAT_R16_SINT + { 2, R, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledSInt }, + + // VK_FORMAT_R16_SFLOAT + { 2, R, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R16G16_UNORM + { 4, RG, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R16G16_SNORM + { 4, RG, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R16G16_USCALED + { 4, RG, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R16G16_SSCALED + { 4, RG, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R16G16_UINT + { 4, RG, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledUInt }, + + // VK_FORMAT_R16G16_SINT + { 4, RG, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledSInt }, + + // VK_FORMAT_R16G16_SFLOAT + { 4, RG, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R16G16B16_UNORM + { 6, RGB, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R16G16B16_SNORM + { 6, RGB, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R16G16B16_USCALED + { 6, RGB, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R16G16B16_SSCALED + { 6, RGB, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R16G16B16_UINT + { 6, RGB, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledUInt }, + + // VK_FORMAT_R16G16B16_SINT + { 6, RGB, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledSInt }, + + // VK_FORMAT_R16G16B16_SFLOAT + { 6, RGB, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R16G16B16A16_UNORM + { 8, RGBA, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R16G16B16A16_SNORM + { 8, RGBA, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R16G16B16A16_USCALED + { 8, RGBA, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R16G16B16A16_SSCALED + { 8, RGBA, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R16G16B16A16_UINT + { 8, RGBA, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledUInt }, + + // VK_FORMAT_R16G16B16A16_SINT + { 8, RGBA, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledSInt }, + + // VK_FORMAT_R16G16B16A16_SFLOAT + { 8, RGBA, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R32_UINT + { 4, R, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledUInt }, + + // VK_FORMAT_R32_SINT + { 4, R, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledSInt }, + + // VK_FORMAT_R32_SFLOAT + { 4, R, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R32G32_UINT + { 8, RG, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledUInt }, + + // VK_FORMAT_R32G32_SINT + { 8, RG, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledSInt }, + + // VK_FORMAT_R32G32_SFLOAT + { 8, RG, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R32G32B32_UINT + { 12, RGB, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledUInt }, + + // VK_FORMAT_R32G32B32_SINT + { 12, RGB, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledSInt }, + + // VK_FORMAT_R32G32B32_SFLOAT + { 12, RGB, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R32G32B32A32_UINT + { 16, RGBA, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledUInt }, + + // VK_FORMAT_R32G32B32A32_SINT + { 16, RGBA, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledSInt }, + + // VK_FORMAT_R32G32B32A32_SFLOAT + { 16, RGBA, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R64_UINT + { 8, R, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledUInt }, + + // VK_FORMAT_R64_SINT + { 8, R, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledSInt }, + + // VK_FORMAT_R64_SFLOAT + { 8, R, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R64G64_UINT + { 16, RG, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledUInt }, + + // VK_FORMAT_R64G64_SINT + { 16, RG, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledSInt }, + + // VK_FORMAT_R64G64_SFLOAT + { 16, RG, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R64G64B64_UINT + { 24, RGB, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledUInt }, + + // VK_FORMAT_R64G64B64_SINT + { 24, RGB, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledSInt }, + + // VK_FORMAT_R64G64B64_SFLOAT + { 24, RGB, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_R64G64B64A64_UINT + { 32, RGBA, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledUInt }, + + // VK_FORMAT_R64G64B64A64_SINT + { 32, RGBA, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::SampledSInt }, + + // VK_FORMAT_R64G64B64A64_SFLOAT + { 32, RGBA, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_B10G11R11_UFLOAT_PACK32 + { 4, RGB, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 + { 4, RGB, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_D16_UNORM + { 2, 0, VK_IMAGE_ASPECT_DEPTH_BIT }, + + // VK_FORMAT_X8_D24_UNORM_PACK32 + { 4, 0, VK_IMAGE_ASPECT_DEPTH_BIT }, + + // VK_FORMAT_D32_SFLOAT + { 4, 0, VK_IMAGE_ASPECT_DEPTH_BIT }, + + // VK_FORMAT_S8_UINT + { 1, 0, VK_IMAGE_ASPECT_STENCIL_BIT }, + + // VK_FORMAT_D16_UNORM_S8_UINT + { 4, 0, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT }, + + // VK_FORMAT_D24_UNORM_S8_UINT + { 4, 0, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT }, + + // VK_FORMAT_D32_SFLOAT_S8_UINT + { 8, 0, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT }, + + // VK_FORMAT_BC1_RGB_UNORM_BLOCK + { 8, RGB, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::BlockCompressed, + VkExtent3D { 4, 4, 1 } }, + + // VK_FORMAT_BC1_RGB_SRGB_BLOCK + { 8, RGB, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlags( + DxvkFormatFlag::BlockCompressed, + DxvkFormatFlag::ColorSpaceSrgb), + VkExtent3D { 4, 4, 1 } }, + + // VK_FORMAT_BC1_RGBA_UNORM_BLOCK + { 8, RGBA, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::BlockCompressed, + VkExtent3D { 4, 4, 1 } }, + + // VK_FORMAT_BC1_RGBA_SRGB_BLOCK + { 8, RGBA, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlags( + DxvkFormatFlag::BlockCompressed, + DxvkFormatFlag::ColorSpaceSrgb), + VkExtent3D { 4, 4, 1 } }, + + // VK_FORMAT_BC2_UNORM_BLOCK + { 16, RGBA, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::BlockCompressed, + VkExtent3D { 4, 4, 1 } }, + + // VK_FORMAT_BC2_SRGB_BLOCK + { 16, RGBA, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlags( + DxvkFormatFlag::BlockCompressed, + DxvkFormatFlag::ColorSpaceSrgb), + VkExtent3D { 4, 4, 1 } }, + + // VK_FORMAT_BC3_UNORM_BLOCK + { 16, RGBA, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::BlockCompressed, + VkExtent3D { 4, 4, 1 } }, + + // VK_FORMAT_BC3_SRGB_BLOCK + { 16, RGBA, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlags( + DxvkFormatFlag::BlockCompressed, + DxvkFormatFlag::ColorSpaceSrgb), + VkExtent3D { 4, 4, 1 } }, + + // VK_FORMAT_BC4_UNORM_BLOCK + { 8, R, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::BlockCompressed, + VkExtent3D { 4, 4, 1 } }, + + // VK_FORMAT_BC4_SNORM_BLOCK + { 8, R, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::BlockCompressed, + VkExtent3D { 4, 4, 1 } }, + + // VK_FORMAT_BC5_UNORM_BLOCK + { 16, RG, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::BlockCompressed, + VkExtent3D { 4, 4, 1 } }, + + // VK_FORMAT_BC5_SNORM_BLOCK + { 16, RG, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::BlockCompressed, + VkExtent3D { 4, 4, 1 } }, + + // VK_FORMAT_BC6H_UFLOAT_BLOCK + { 16, RGB, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::BlockCompressed, + VkExtent3D { 4, 4, 1 } }, + + // VK_FORMAT_BC6H_SFLOAT_BLOCK + { 16, RGB, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::BlockCompressed, + VkExtent3D { 4, 4, 1 } }, + + // VK_FORMAT_BC7_UNORM_BLOCK + { 16, RGBA, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::BlockCompressed, + VkExtent3D { 4, 4, 1 } }, + + // VK_FORMAT_BC7_SRGB_BLOCK + { 16, RGBA, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlags( + DxvkFormatFlag::BlockCompressed, + DxvkFormatFlag::ColorSpaceSrgb), + VkExtent3D { 4, 4, 1 } }, + + // VK_FORMAT_G8B8G8R8_422_UNORM_KHR + { 4, RGB, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::BlockCompressed, + VkExtent3D { 2, 1, 1 } }, + + // VK_FORMAT_B8G8R8G8_422_UNORM_KHR + { 4, RGB, VK_IMAGE_ASPECT_COLOR_BIT, + DxvkFormatFlag::BlockCompressed, + VkExtent3D { 2, 1, 1 } }, + + // VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT + { 2, RGBA, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT + { 2, RGBA, VK_IMAGE_ASPECT_COLOR_BIT }, + + // VK_FORMAT_G8_B8R8_2PLANE_420_UNORM + { 6, RGB, VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT, + DxvkFormatFlag::MultiPlane, VkExtent3D { 1, 1, 1 }, + { DxvkPlaneFormatInfo { 1, { 1, 1 } }, + DxvkPlaneFormatInfo { 2, { 2, 2 } } } }, + }}; + + + const std::array, 4> g_formatGroups = {{ + { VK_FORMAT_UNDEFINED, VK_FORMAT_BC7_SRGB_BLOCK }, + { VK_FORMAT_G8B8G8R8_422_UNORM_KHR, VK_FORMAT_B8G8R8G8_422_UNORM_KHR }, + { VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT, VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT }, + { VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, VK_FORMAT_G8_B8R8_2PLANE_420_UNORM }, + }}; + + + const DxvkFormatInfo* imageFormatInfo(VkFormat format) { + uint32_t indexOffset = 0; + + for (const auto& group : g_formatGroups) { + if (format >= group.first && format <= group.second) { + uint32_t index = uint32_t(format) - uint32_t(group.first); + return &g_formatInfos[indexOffset + index]; + } else { + indexOffset += uint32_t(group.second) + - uint32_t(group.first) + 1; + } + } + + return nullptr; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_format.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_format.h new file mode 100644 index 00000000000..8541508e80d --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_format.h @@ -0,0 +1,60 @@ +#pragma once + +#include "dxvk_include.h" + +namespace dxvk { + + enum class DxvkFormatFlag { + BlockCompressed = 0, ///< Image format is block compressed + SampledUInt = 1, ///< Sampled type is an unsigned integer type + SampledSInt = 2, ///< Sampled type is a signed integer type + ColorSpaceSrgb = 3, ///< Non-linear SRGB color format + MultiPlane = 4, ///< Multi-plane format + }; + + using DxvkFormatFlags = Flags; + + /** + * \brief Planar format info + */ + struct DxvkPlaneFormatInfo { + /// Byte size of a pixel in the current plane + VkDeviceSize elementSize = 0; + /// Number of image pixels covered by a + /// single pixel in the current plane + VkExtent2D blockSize = { 1, 1 }; + }; + + /** + * \brief Format info structure + * + * Provides some useful information + * about a Vulkan image format. + */ + struct DxvkFormatInfo { + /// Size of an element in this format. For compressed + /// formats, this is the size of a block, in bytes. + VkDeviceSize elementSize = 0; + + /// Available component mask + VkColorComponentFlags componentMask = 0; + + /// Available image aspect flags + VkImageAspectFlags aspectMask = 0; + + /// Some other format info flags + DxvkFormatFlags flags = 0; + + /// Size, in pixels, of a compressed block. For + /// non-block formats, all these values are 1. + VkExtent3D blockSize = { 1, 1, 1 }; + + /// Plane info for multi-planar formats + std::array planes; + }; + + + + const DxvkFormatInfo* imageFormatInfo(VkFormat format); + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_framebuffer.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_framebuffer.cpp new file mode 100644 index 00000000000..58d07e3b0ee --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_framebuffer.cpp @@ -0,0 +1,181 @@ +#include "dxvk_framebuffer.h" + +namespace dxvk { + + DxvkFramebufferInfo::DxvkFramebufferInfo() { + + } + + + DxvkFramebufferInfo::DxvkFramebufferInfo( + const DxvkRenderTargets& renderTargets, + const DxvkFramebufferSize& defaultSize, + DxvkRenderPass* renderPass) + : m_renderTargets (renderTargets), + m_renderSize (computeRenderSize(defaultSize)), + m_renderPass (renderPass) { + + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { + if (m_renderTargets.color[i].view != nullptr) { + m_attachments[m_attachmentCount++] = i; + m_sampleCount = m_renderTargets.color[i].view->imageInfo().sampleCount; + } + } + + if (m_renderTargets.depth.view != nullptr) { + m_attachments[m_attachmentCount++] = -1; + m_sampleCount = m_renderTargets.depth.view->imageInfo().sampleCount; + } + } + + + DxvkFramebufferInfo::~DxvkFramebufferInfo() { + + } + + + int32_t DxvkFramebufferInfo::findAttachment(const Rc& view) const { + for (uint32_t i = 0; i < m_attachmentCount; i++) { + if (getAttachment(i).view->matchesView(view)) + return int32_t(i); + } + + return -1; + } + + + bool DxvkFramebufferInfo::hasTargets(const DxvkRenderTargets& renderTargets) { + bool eq = m_renderTargets.depth.view == renderTargets.depth.view + && m_renderTargets.depth.layout == renderTargets.depth.layout; + + for (uint32_t i = 0; i < MaxNumRenderTargets && eq; i++) { + eq &= m_renderTargets.color[i].view == renderTargets.color[i].view + && m_renderTargets.color[i].layout == renderTargets.color[i].layout; + } + + return eq; + } + + + bool DxvkFramebufferInfo::isFullSize(const Rc& view) const { + return m_renderSize.width == view->mipLevelExtent(0).width + && m_renderSize.height == view->mipLevelExtent(0).height + && m_renderSize.layers == view->info().numLayers; + } + + + bool DxvkFramebufferInfo::isWritable(uint32_t attachmentIndex, VkImageAspectFlags aspects) const { + VkImageAspectFlags writableAspects = vk::getWritableAspectsForLayout(getAttachment(attachmentIndex).layout); + return (writableAspects & aspects) == aspects; + } + + + DxvkFramebufferKey DxvkFramebufferInfo::key() const { + DxvkFramebufferKey result = { }; + + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { + if (m_renderTargets.color[i].view != nullptr) + result.colorViews[i] = m_renderTargets.color[i].view->cookie(); + } + + if (m_renderTargets.depth.view != nullptr) + result.depthView = m_renderTargets.depth.view->cookie(); + + if (result.renderPass) + result.renderPass = m_renderPass->getDefaultHandle(); + + return result; + } + + + DxvkRenderPassFormat DxvkFramebufferInfo::getRenderPassFormat(const DxvkRenderTargets& renderTargets) { + DxvkRenderPassFormat format; + + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { + if (renderTargets.color[i].view != nullptr) { + format.sampleCount = renderTargets.color[i].view->imageInfo().sampleCount; + format.color[i].format = renderTargets.color[i].view->info().format; + format.color[i].layout = renderTargets.color[i].layout; + } + } + + if (renderTargets.depth.view != nullptr) { + format.sampleCount = renderTargets.depth.view->imageInfo().sampleCount; + format.depth.format = renderTargets.depth.view->info().format; + format.depth.layout = renderTargets.depth.layout; + } + + return format; + } + + + DxvkFramebufferSize DxvkFramebufferInfo::computeRenderSize( + const DxvkFramebufferSize& defaultSize) const { + // Some games bind render targets of a different size and + // expect it to work, so we'll compute the minimum size + DxvkFramebufferSize minSize = defaultSize; + + if (m_renderTargets.depth.view != nullptr) { + DxvkFramebufferSize depthSize = this->computeRenderTargetSize(m_renderTargets.depth.view); + minSize.width = std::min(minSize.width, depthSize.width); + minSize.height = std::min(minSize.height, depthSize.height); + minSize.layers = std::min(minSize.layers, depthSize.layers); + } + + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { + if (m_renderTargets.color[i].view != nullptr) { + DxvkFramebufferSize colorSize = this->computeRenderTargetSize(m_renderTargets.color[i].view); + minSize.width = std::min(minSize.width, colorSize.width); + minSize.height = std::min(minSize.height, colorSize.height); + minSize.layers = std::min(minSize.layers, colorSize.layers); + } + } + + return minSize; + } + + + DxvkFramebufferSize DxvkFramebufferInfo::computeRenderTargetSize( + const Rc& renderTarget) const { + auto extent = renderTarget->mipLevelExtent(0); + auto layers = renderTarget->info().numLayers; + return DxvkFramebufferSize { extent.width, extent.height, layers }; + } + + + DxvkFramebuffer::DxvkFramebuffer( + const Rc& vkd, + const DxvkFramebufferInfo& info) + : m_vkd(vkd), m_key(info.key()) { + std::array views; + uint32_t attachmentCount = 0; + + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { + if (info.getColorTarget(i).view != nullptr) + views[attachmentCount++] = info.getColorTarget(i).view->handle(); + } + + if (info.getDepthTarget().view != nullptr) + views[attachmentCount++] = info.getDepthTarget().view->handle(); + + VkFramebufferCreateInfo fbInfo; + fbInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + fbInfo.pNext = nullptr; + fbInfo.flags = 0; + fbInfo.renderPass = info.renderPass()->getDefaultHandle(); + fbInfo.attachmentCount = attachmentCount; + fbInfo.pAttachments = views.data(); + fbInfo.width = info.size().width; + fbInfo.height = info.size().height; + fbInfo.layers = info.size().layers; + + if (m_vkd->vkCreateFramebuffer(m_vkd->device(), &fbInfo, nullptr, &m_handle) != VK_SUCCESS) + Logger::err("DxvkFramebuffer: Failed to create framebuffer object"); + } + + + DxvkFramebuffer::~DxvkFramebuffer() { + m_vkd->vkDestroyFramebuffer(m_vkd->device(), m_handle, nullptr); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_framebuffer.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_framebuffer.h new file mode 100644 index 00000000000..b55e6e5fa88 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_framebuffer.h @@ -0,0 +1,299 @@ +#pragma once + +#include "dxvk_image.h" +#include "dxvk_renderpass.h" + +namespace dxvk { + + /** + * \brief Framebuffer size + * + * Stores the width, height and number of layers + * of a framebuffer. This can be used in case a + * framebuffer does not have any attachments. + */ + struct DxvkFramebufferSize { + uint32_t width; + uint32_t height; + uint32_t layers; + }; + + + /** + * \brief Framebuffer attachment + * + * Stores an attachment, as well as the image layout + * that will be used for rendering to the attachment. + */ + struct DxvkAttachment { + Rc view = nullptr; + VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED; + }; + + + /** + * \brief Render targets + * + * Stores all depth-stencil and color + * attachments attached to a framebuffer. + */ + struct DxvkRenderTargets { + DxvkAttachment depth; + DxvkAttachment color[MaxNumRenderTargets]; + }; + + + /** + * \brief Render target layouts + */ + struct DxvkRenderTargetLayouts { + VkImageLayout color[MaxNumRenderTargets]; + VkImageLayout depth; + }; + + + /** + * \brief Framebuffer key + */ + struct DxvkFramebufferKey { + uint64_t colorViews[MaxNumRenderTargets]; + uint64_t depthView; + VkRenderPass renderPass; + + size_t hash() const { + DxvkHashState state; + state.add(depthView); + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) + state.add(colorViews[i]); + state.add(uint64_t(renderPass)); + return state; + } + + bool eq(const DxvkFramebufferKey& other) const { + bool eq = depthView == other.depthView + && renderPass == other.renderPass; + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) + eq &= colorViews[i] == other.colorViews[i]; + return eq; + } + }; + + + /** + * \brief Framebuffer info + * + * Stores metadata about the current framebuffer, + * without actually creating a framebuffer object. + */ + class DxvkFramebufferInfo { + + public: + + DxvkFramebufferInfo(); + + DxvkFramebufferInfo( + const DxvkRenderTargets& renderTargets, + const DxvkFramebufferSize& defaultSize, + DxvkRenderPass* renderPass); + + ~DxvkFramebufferInfo(); + + /** + * \brief Retrieves all attachments + * \returns Render targets + */ + const DxvkRenderTargets& attachments() const { + return m_renderTargets; + } + + /** + * \brief Framebuffer size + * \returns Framebuffer size + */ + DxvkFramebufferSize size() const { + return m_renderSize; + } + + /** + * \brief Render pass + * \returns Render pass + */ + DxvkRenderPass* renderPass() const { + return m_renderPass; + } + + /** + * \brief Framebuffer sample count + * + * Returns the sample count of the color + * and depth-stencil attachments, or 0 if + * there are no attachments. + * \returns Sample count + */ + VkSampleCountFlags getSampleCount() const { + return m_sampleCount; + } + + /** + * \brief Depth-stencil target + * \returns Depth-stencil target + */ + const DxvkAttachment& getDepthTarget() const { + return m_renderTargets.depth; + } + + /** + * \brief Color target + * + * \param [in] id Target Index + * \returns The color target + */ + const DxvkAttachment& getColorTarget(uint32_t id) const { + return m_renderTargets.color[id]; + } + + /** + * \brief Number of framebuffer attachment + * \returns Total attachment count + */ + uint32_t numAttachments() const { + return m_attachmentCount; + } + + /** + * \brief Queries color attachment index of a given attachment + * \returns The index, or -1 if the given attachment is the depth attachment + */ + const int32_t getColorAttachmentIndex(uint32_t id) const { + return m_attachments[id]; + } + + /** + * \brief Retrieves attachment by index + * + * \param [in] id Framebuffer attachment ID + * \returns The framebuffer attachment + */ + const DxvkAttachment& getAttachment(uint32_t id) const { + int32_t idx = getColorAttachmentIndex(id); + return idx < 0 ? m_renderTargets.depth : m_renderTargets.color[idx]; + } + + /** + * \brief Finds attachment index by view + * + * Color attachments start at 0 + * \param [in] view Image view + * \returns Attachment index + */ + int32_t findAttachment(const Rc& view) const; + + /** + * \brief Checks whether the framebuffer's targets match + * + * \param [in] renderTargets Render targets to check + * \returns \c true if the render targets are the same + * as the ones used for this framebuffer object. + */ + bool hasTargets(const DxvkRenderTargets& renderTargets); + + /** + * \brief Checks whether view and framebuffer sizes match + * + * Tests whether the size of the framebuffer is the same + * as the size of one of its views. This may be \c false + * when mixing attachments with mismatched dimensions. + * \param [in] view Image view to test + * \returns \c true if \c view has the same size as + * the framebuffer. + */ + bool isFullSize(const Rc& view) const; + + /** + * \brief Checks whether an attachment is writable + * + * Needed for certain clear optimizations. + * \param [in] attachmentIndex Attachment to check + * \param [in] aspects Aspect mask to check + * \returns \c true if all aspects can be written for the given attachment + */ + bool isWritable(uint32_t attachmentIndex, VkImageAspectFlags aspects) const; + + /** + * \brief Generates framebuffer key + * \returns Framebuffer key + */ + DxvkFramebufferKey key() const; + + /** + * \brief Generatess render pass format + * + * This render pass format can be used to + * look up a compatible render pass. + * \param [in] renderTargets Render targets + * \returns The render pass format + */ + static DxvkRenderPassFormat getRenderPassFormat( + const DxvkRenderTargets& renderTargets); + + private: + + DxvkRenderTargets m_renderTargets; + DxvkFramebufferSize m_renderSize = { 0u, 0u, 0u }; + VkSampleCountFlags m_sampleCount = 0; + DxvkRenderPass* m_renderPass; + + uint32_t m_attachmentCount = 0; + std::array m_attachments; + + DxvkFramebufferSize computeRenderSize( + const DxvkFramebufferSize& defaultSize) const; + + DxvkFramebufferSize computeRenderTargetSize( + const Rc& renderTarget) const; + + }; + + + + /** + * \brief Framebuffer + * + * A framebuffer either stores a set of image views + * that will be used as render targets, or in case + * no render targets are attached, fixed dimensions. + */ + class DxvkFramebuffer : public DxvkResource { + + public: + + DxvkFramebuffer( + const Rc& vkd, + const DxvkFramebufferInfo& info); + + ~DxvkFramebuffer(); + + /** + * \brief Framebuffer handle + * \returns Framebuffer handle + */ + VkFramebuffer handle() const { + return m_handle; + } + + /** + * \brief Framebuffer key + */ + const DxvkFramebufferKey& key() const { + return m_key; + } + + private: + + Rc m_vkd; + VkFramebuffer m_handle; + DxvkFramebufferKey m_key; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_gpu_event.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_gpu_event.cpp new file mode 100644 index 00000000000..b54303f7dee --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_gpu_event.cpp @@ -0,0 +1,104 @@ +#include "dxvk_gpu_event.h" +#include "dxvk_device.h" + +namespace dxvk { + + DxvkGpuEvent::DxvkGpuEvent(const Rc& vkd) + : m_vkd(vkd) { } + + + DxvkGpuEvent::~DxvkGpuEvent() { + if (m_handle.pool && m_handle.event) + m_handle.pool->freeEvent(m_handle.event); + } + + + DxvkGpuEventStatus DxvkGpuEvent::test() const { + if (!m_handle.event) + return DxvkGpuEventStatus::Invalid; + + VkResult status = m_vkd->vkGetEventStatus( + m_vkd->device(), m_handle.event); + + switch (status) { + case VK_EVENT_SET: return DxvkGpuEventStatus::Signaled; + case VK_EVENT_RESET: return DxvkGpuEventStatus::Pending; + default: return DxvkGpuEventStatus::Invalid; + } + } + + + DxvkGpuEventHandle DxvkGpuEvent::reset(DxvkGpuEventHandle handle) { + m_vkd->vkResetEvent(m_vkd->device(), handle.event); + return std::exchange(m_handle, handle); + } + + + + + DxvkGpuEventPool::DxvkGpuEventPool(const DxvkDevice* device) + : m_vkd(device->vkd()) { } + + + DxvkGpuEventPool::~DxvkGpuEventPool() { + for (VkEvent ev : m_events) + m_vkd->vkDestroyEvent(m_vkd->device(), ev, nullptr); + } + + + DxvkGpuEventHandle DxvkGpuEventPool::allocEvent() { + VkEvent event = VK_NULL_HANDLE; + + { std::lock_guard lock(m_mutex); + + if (m_events.size() > 0) { + event = m_events.back(); + m_events.pop_back(); + } + } + + if (!event) { + VkEventCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + + VkResult status = m_vkd->vkCreateEvent( + m_vkd->device(), &info, nullptr, &event); + + if (status != VK_SUCCESS) { + Logger::err("DXVK: Failed to create GPU event"); + return DxvkGpuEventHandle(); + } + } + + return { this, event }; + } + + + void DxvkGpuEventPool::freeEvent(VkEvent event) { + std::lock_guard lock(m_mutex); + m_events.push_back(event); + } + + + + + DxvkGpuEventTracker::DxvkGpuEventTracker() { } + DxvkGpuEventTracker::~DxvkGpuEventTracker() { } + + + void DxvkGpuEventTracker::trackEvent(DxvkGpuEventHandle handle) { + if (handle.pool && handle.event) + m_handles.push_back(handle); + } + + + void DxvkGpuEventTracker::reset() { + for (const auto& h : m_handles) + h.pool->freeEvent(h.event); + + m_handles.clear(); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_gpu_event.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_gpu_event.h new file mode 100644 index 00000000000..d1f4d1b4c91 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_gpu_event.h @@ -0,0 +1,154 @@ +#pragma once + +#include + +#include "dxvk_resource.h" + +namespace dxvk { + + class DxvkDevice; + class DxvkGpuEventPool; + + /** + * \brief Event status + * + * Reports whether the event is in + * a signaled or unsignaled state. + */ + enum class DxvkGpuEventStatus : uint32_t { + Invalid = 0, + Pending = 1, + Signaled = 2, + }; + + + /** + * \brief Event handle + * + * Stores the event handle itself as well + * as a pointer to the pool that the event + * was allocated from. + */ + struct DxvkGpuEventHandle { + DxvkGpuEventPool* pool = nullptr; + VkEvent event = VK_NULL_HANDLE; + }; + + + /** + * \brief GPU event + * + * An event managed by the GPU which allows + * the application to check whether a specific + * command has completed execution. + */ + class DxvkGpuEvent : public DxvkResource { + + public: + + DxvkGpuEvent(const Rc& vkd); + ~DxvkGpuEvent(); + + /** + * \brief Retrieves event status + * + * Only valid after the event has been + * recorded intro a command buffer. + * \returns Event status + */ + DxvkGpuEventStatus test() const; + + /** + * \brief Resets event + * + * Assigns a new Vulkan event to this event + * object and replaces the old one. The old + * event should be freed as soon as the GPU + * stops using it. + * \param [in] handle New GPU event handle + * \returns Old GPU event handle + */ + DxvkGpuEventHandle reset(DxvkGpuEventHandle handle); + + private: + + Rc m_vkd; + DxvkGpuEventHandle m_handle; + + }; + + + /** + * \brief Event pool + * + * Thread-safe event allocator that provides + * a way to create and recycle Vulkan events. + */ + class DxvkGpuEventPool { + + public: + + DxvkGpuEventPool(const DxvkDevice* device); + ~DxvkGpuEventPool(); + + /** + * \brief Allocates an event + * + * Either returns a recycled event, or + * creates a new one if necessary. The + * state of the event is undefined. + * \returns An event handle + */ + DxvkGpuEventHandle allocEvent(); + + /** + * \brief Recycles an event + * + * \param [in] handle Event to free + */ + void freeEvent(VkEvent event); + + private: + + Rc m_vkd; + dxvk::mutex m_mutex; + std::vector m_events; + + }; + + + /** + * \brief GPU event tracker + * + * Stores events currently accessed by the + * GPU, and returns them to the event pool + * once they are no longer in use. + */ + class DxvkGpuEventTracker { + + public: + + DxvkGpuEventTracker(); + ~DxvkGpuEventTracker(); + + /** + * \brief Tracks an event + * \param [in] handle Event to track + */ + void trackEvent(DxvkGpuEventHandle handle); + + /** + * \brief Resets event tracker + * + * Releases all tracked events back + * to the respective event pool + */ + void reset(); + + private: + + std::vector m_handles; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_gpu_query.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_gpu_query.cpp new file mode 100644 index 00000000000..40d3a091022 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_gpu_query.cpp @@ -0,0 +1,422 @@ +#include + +#include "dxvk_cmdlist.h" +#include "dxvk_device.h" +#include "dxvk_gpu_query.h" + +namespace dxvk { + + DxvkGpuQuery::DxvkGpuQuery( + const Rc& vkd, + VkQueryType type, + VkQueryControlFlags flags, + uint32_t index) + : m_vkd(vkd), m_type(type), m_flags(flags), + m_index(index), m_ended(false) { + + } + + + DxvkGpuQuery::~DxvkGpuQuery() { + if (m_handle.queryPool) + m_handle.allocator->freeQuery(m_handle); + + for (DxvkGpuQueryHandle handle : m_handles) + handle.allocator->freeQuery(handle); + } + + + bool DxvkGpuQuery::isIndexed() const { + return m_type == VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT; + } + + + DxvkGpuQueryStatus DxvkGpuQuery::getData(DxvkQueryData& queryData) const { + queryData = DxvkQueryData(); + + if (!m_ended) + return DxvkGpuQueryStatus::Invalid; + + // Empty begin/end pair + if (!m_handle.queryPool) + return DxvkGpuQueryStatus::Available; + + // Get query data from all associated handles + DxvkGpuQueryStatus status = getDataForHandle(queryData, m_handle); + + for (size_t i = 0; i < m_handles.size() + && status == DxvkGpuQueryStatus::Available; i++) + status = getDataForHandle(queryData, m_handles[i]); + + // Treat non-precise occlusion queries as available + // if we already know the result will be non-zero + if ((status == DxvkGpuQueryStatus::Pending) + && (m_type == VK_QUERY_TYPE_OCCLUSION) + && !(m_flags & VK_QUERY_CONTROL_PRECISE_BIT) + && (queryData.occlusion.samplesPassed)) + status = DxvkGpuQueryStatus::Available; + + return status; + } + + + void DxvkGpuQuery::begin(const Rc& cmd) { + m_ended = false; + + cmd->trackGpuQuery(m_handle); + m_handle = DxvkGpuQueryHandle(); + + for (const auto& handle : m_handles) + cmd->trackGpuQuery(handle); + m_handles.clear(); + } + + + void DxvkGpuQuery::end() { + m_ended = true; + } + + + void DxvkGpuQuery::addQueryHandle(const DxvkGpuQueryHandle& handle) { + if (m_handle.queryPool) + m_handles.push_back(m_handle); + + m_handle = handle; + } + + + DxvkGpuQueryStatus DxvkGpuQuery::getDataForHandle( + DxvkQueryData& queryData, + const DxvkGpuQueryHandle& handle) const { + DxvkQueryData tmpData; + + // Try to copy query data to temporary structure + VkResult result = m_vkd->vkGetQueryPoolResults(m_vkd->device(), + handle.queryPool, handle.queryId, 1, + sizeof(DxvkQueryData), &tmpData, + sizeof(DxvkQueryData), VK_QUERY_RESULT_64_BIT); + + if (result == VK_NOT_READY) + return DxvkGpuQueryStatus::Pending; + else if (result != VK_SUCCESS) + return DxvkGpuQueryStatus::Failed; + + // Add numbers to the destination structure + switch (m_type) { + case VK_QUERY_TYPE_OCCLUSION: + queryData.occlusion.samplesPassed += tmpData.occlusion.samplesPassed; + break; + + case VK_QUERY_TYPE_TIMESTAMP: + queryData.timestamp.time = tmpData.timestamp.time; + break; + + case VK_QUERY_TYPE_PIPELINE_STATISTICS: + queryData.statistic.iaVertices += tmpData.statistic.iaVertices; + queryData.statistic.iaPrimitives += tmpData.statistic.iaPrimitives; + queryData.statistic.vsInvocations += tmpData.statistic.vsInvocations; + queryData.statistic.gsInvocations += tmpData.statistic.gsInvocations; + queryData.statistic.gsPrimitives += tmpData.statistic.gsPrimitives; + queryData.statistic.clipInvocations += tmpData.statistic.clipInvocations; + queryData.statistic.clipPrimitives += tmpData.statistic.clipPrimitives; + queryData.statistic.fsInvocations += tmpData.statistic.fsInvocations; + queryData.statistic.tcsPatches += tmpData.statistic.tcsPatches; + queryData.statistic.tesInvocations += tmpData.statistic.tesInvocations; + queryData.statistic.csInvocations += tmpData.statistic.csInvocations; + break; + + case VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT: + queryData.xfbStream.primitivesWritten += tmpData.xfbStream.primitivesWritten; + queryData.xfbStream.primitivesNeeded += tmpData.xfbStream.primitivesNeeded; + break; + + default: + Logger::err(str::format("DXVK: Unhandled query type: ", m_type)); + return DxvkGpuQueryStatus::Invalid; + } + + return DxvkGpuQueryStatus::Available; + } + + + + + DxvkGpuQueryAllocator::DxvkGpuQueryAllocator( + DxvkDevice* device, + VkQueryType queryType, + uint32_t queryPoolSize) + : m_device (device), + m_vkd (device->vkd()), + m_queryType (queryType), + m_queryPoolSize (queryPoolSize) { + + } + + + DxvkGpuQueryAllocator::~DxvkGpuQueryAllocator() { + for (VkQueryPool pool : m_pools) { + m_vkd->vkDestroyQueryPool( + m_vkd->device(), pool, nullptr); + } + } + + + DxvkGpuQueryHandle DxvkGpuQueryAllocator::allocQuery() { + std::lock_guard lock(m_mutex); + + if (m_handles.size() == 0) + this->createQueryPool(); + + if (m_handles.size() == 0) + return DxvkGpuQueryHandle(); + + DxvkGpuQueryHandle result = m_handles.back(); + m_handles.pop_back(); + return result; + } + + + void DxvkGpuQueryAllocator::freeQuery(DxvkGpuQueryHandle handle) { + std::lock_guard lock(m_mutex); + m_handles.push_back(handle); + } + + + void DxvkGpuQueryAllocator::createQueryPool() { + VkQueryPoolCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.queryType = m_queryType; + info.queryCount = m_queryPoolSize; + info.pipelineStatistics = 0; + + if (m_queryType == VK_QUERY_TYPE_PIPELINE_STATISTICS) { + info.pipelineStatistics + = VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT + | VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT + | VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT + | VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT + | VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT + | VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT + | VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT + | VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT + | VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT + | VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT + | VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT; + } + + VkQueryPool queryPool = VK_NULL_HANDLE; + + if (m_vkd->vkCreateQueryPool(m_vkd->device(), &info, nullptr, &queryPool)) { + Logger::err(str::format("DXVK: Failed to create query pool (", m_queryType, "; ", m_queryPoolSize, ")")); + return; + } + + m_pools.push_back(queryPool); + + for (uint32_t i = 0; i < m_queryPoolSize; i++) + m_handles.push_back({ this, queryPool, i }); + } + + + + + DxvkGpuQueryPool::DxvkGpuQueryPool(DxvkDevice* device) + : m_occlusion(device, VK_QUERY_TYPE_OCCLUSION, 16384), + m_statistic(device, VK_QUERY_TYPE_PIPELINE_STATISTICS, 1024), + m_timestamp(device, VK_QUERY_TYPE_TIMESTAMP, 1024), + m_xfbStream(device, VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT, 1024) { + + } + + + DxvkGpuQueryPool::~DxvkGpuQueryPool() { + + } + + + DxvkGpuQueryHandle DxvkGpuQueryPool::allocQuery(VkQueryType type) { + switch (type) { + case VK_QUERY_TYPE_OCCLUSION: + return m_occlusion.allocQuery(); + case VK_QUERY_TYPE_PIPELINE_STATISTICS: + return m_statistic.allocQuery(); + case VK_QUERY_TYPE_TIMESTAMP: + return m_timestamp.allocQuery(); + case VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT: + return m_xfbStream.allocQuery(); + default: + Logger::err(str::format("DXVK: Unhandled query type: ", type)); + return DxvkGpuQueryHandle(); + } + } + + + + + DxvkGpuQueryManager::DxvkGpuQueryManager(DxvkGpuQueryPool& pool) + : m_pool(&pool), m_activeTypes(0) { + + } + + + DxvkGpuQueryManager::~DxvkGpuQueryManager() { + + } + + + void DxvkGpuQueryManager::enableQuery( + const Rc& cmd, + const Rc& query) { + query->begin(cmd); + + m_activeQueries.push_back(query); + + if (m_activeTypes & getQueryTypeBit(query->type())) + beginSingleQuery(cmd, query); + } + + + void DxvkGpuQueryManager::disableQuery( + const Rc& cmd, + const Rc& query) { + auto iter = std::find( + m_activeQueries.begin(), + m_activeQueries.end(), + query); + + if (iter != m_activeQueries.end()) { + if (m_activeTypes & getQueryTypeBit((*iter)->type())) + endSingleQuery(cmd, query); + m_activeQueries.erase(iter); + + query->end(); + } + } + + + void DxvkGpuQueryManager::writeTimestamp( + const Rc& cmd, + const Rc& query) { + DxvkGpuQueryHandle handle = m_pool->allocQuery(query->type()); + + query->begin(cmd); + query->addQueryHandle(handle); + query->end(); + + cmd->resetQuery( + handle.queryPool, + handle.queryId); + + cmd->cmdWriteTimestamp( + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + handle.queryPool, + handle.queryId); + + cmd->trackResource(query); + } + + + void DxvkGpuQueryManager::beginQueries( + const Rc& cmd, + VkQueryType type) { + m_activeTypes |= getQueryTypeBit(type); + + for (size_t i = 0; i < m_activeQueries.size(); i++) { + if (m_activeQueries[i]->type() == type) + beginSingleQuery(cmd, m_activeQueries[i]); + } + } + + + void DxvkGpuQueryManager::endQueries( + const Rc& cmd, + VkQueryType type) { + m_activeTypes &= ~getQueryTypeBit(type); + + for (size_t i = 0; i < m_activeQueries.size(); i++) { + if (m_activeQueries[i]->type() == type) + endSingleQuery(cmd, m_activeQueries[i]); + } + } + + + void DxvkGpuQueryManager::beginSingleQuery( + const Rc& cmd, + const Rc& query) { + DxvkGpuQueryHandle handle = m_pool->allocQuery(query->type()); + + cmd->resetQuery( + handle.queryPool, + handle.queryId); + + if (query->isIndexed()) { + cmd->cmdBeginQueryIndexed( + handle.queryPool, + handle.queryId, + query->flags(), + query->index()); + } else { + cmd->cmdBeginQuery( + handle.queryPool, + handle.queryId, + query->flags()); + } + + query->addQueryHandle(handle); + } + + + void DxvkGpuQueryManager::endSingleQuery( + const Rc& cmd, + const Rc& query) { + DxvkGpuQueryHandle handle = query->handle(); + + if (query->isIndexed()) { + cmd->cmdEndQueryIndexed( + handle.queryPool, + handle.queryId, + query->index()); + } else { + cmd->cmdEndQuery( + handle.queryPool, + handle.queryId); + } + + cmd->trackResource(query); + } + + + uint32_t DxvkGpuQueryManager::getQueryTypeBit( + VkQueryType type) { + switch (type) { + case VK_QUERY_TYPE_OCCLUSION: return 0x01; + case VK_QUERY_TYPE_PIPELINE_STATISTICS: return 0x02; + case VK_QUERY_TYPE_TIMESTAMP: return 0x04; + case VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT: return 0x08; + default: return 0; + } + } + + + + + DxvkGpuQueryTracker::DxvkGpuQueryTracker() { } + DxvkGpuQueryTracker::~DxvkGpuQueryTracker() { } + + + void DxvkGpuQueryTracker::trackQuery(DxvkGpuQueryHandle handle) { + if (handle.queryPool) + m_handles.push_back(handle); + } + + + void DxvkGpuQueryTracker::reset() { + for (DxvkGpuQueryHandle handle : m_handles) + handle.allocator->freeQuery(handle); + + m_handles.clear(); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_gpu_query.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_gpu_query.h new file mode 100644 index 00000000000..0c45d120006 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_gpu_query.h @@ -0,0 +1,448 @@ +#pragma once + +#include +#include + +#include "dxvk_resource.h" + +namespace dxvk { + + class DxvkCommandList; + + class DxvkGpuQueryPool; + class DxvkGpuQueryAllocator; + + /** + * \brief Query status + * + * Reports whether a query is in + * signaled or unsignaled state. + */ + enum class DxvkGpuQueryStatus : uint32_t { + Invalid = 0, + Pending = 1, + Available = 2, + Failed = 3, + }; + + + /** + * \brief Occlusion query data + * + * Stores the number of samples + * that passes fragment tests. + */ + struct DxvkQueryOcclusionData { + uint64_t samplesPassed; + }; + + /** + * \brief Timestamp data + * + * Stores a GPU time stamp. + */ + struct DxvkQueryTimestampData { + uint64_t time; + }; + + /** + * \brief Pipeline statistics + * + * Stores the counters for + * pipeline statistics queries. + */ + struct DxvkQueryStatisticData { + uint64_t iaVertices; + uint64_t iaPrimitives; + uint64_t vsInvocations; + uint64_t gsInvocations; + uint64_t gsPrimitives; + uint64_t clipInvocations; + uint64_t clipPrimitives; + uint64_t fsInvocations; + uint64_t tcsPatches; + uint64_t tesInvocations; + uint64_t csInvocations; + }; + + /** + * \brief Transform feedback stream query + * + * Stores the number of primitives written to the + * buffer, as well as the number of primitives + * generated. The latter can be used to check for + * overflow. + */ + struct DxvkQueryXfbStreamData { + uint64_t primitivesWritten; + uint64_t primitivesNeeded; + }; + + /** + * \brief Query data + * + * A union that stores query data. Select an + * appropriate member based on the query type. + */ + union DxvkQueryData { + DxvkQueryOcclusionData occlusion; + DxvkQueryTimestampData timestamp; + DxvkQueryStatisticData statistic; + DxvkQueryXfbStreamData xfbStream; + }; + + + /** + * \brief Query handle + * + * Stores the query allocator, as well as + * the actual pool and query index. Since + * query pools have to be reset on the GPU, + * this also comes with a reset event. + */ + struct DxvkGpuQueryHandle { + DxvkGpuQueryAllocator* allocator = nullptr; + VkQueryPool queryPool = VK_NULL_HANDLE; + uint32_t queryId = 0; + }; + + + /** + * \brief Query object + * + * Manages Vulkan queries that are sub-allocated + * from larger query pools + */ + class DxvkGpuQuery : public DxvkResource { + + public: + + DxvkGpuQuery( + const Rc& vkd, + VkQueryType type, + VkQueryControlFlags flags, + uint32_t index); + + ~DxvkGpuQuery(); + + /** + * \brief Query type + * \returns Query type + */ + VkQueryType type() const { + return m_type; + } + + /** + * \brief Query control flags + * \returns Query control flags + */ + VkQueryControlFlags flags() const { + return m_flags; + } + + /** + * \brief Retrieves current handle + * + * Note that the query handle will change + * when calling \ref addQueryHandle. + * \returns Current query handle + */ + DxvkGpuQueryHandle handle() const { + return m_handle; + } + + /** + * \brief Query index + * + * Only valid for indexed query types. + * For non-zero values, indexed query + * functions must be used. + * \returns Query index + */ + uint32_t index() const { + return m_index; + } + + /** + * \brief Checks whether query is indexed + * \returns \c true for indexed query types + */ + bool isIndexed() const; + + /** + * \brief Retrieves query data + * + * If all query data is available, this will + * return \c DxvkGpuQueryStatus::Signaled, and + * the destination structure will be filled + * with the data retrieved from all associated + * query handles. + * \param [out] queryData Query data + * \returns Current query status + */ + DxvkGpuQueryStatus getData( + DxvkQueryData& queryData) const; + + /** + * \brief Begins query + * + * Moves all current query handles to the given + * command list and sets the query into active + * state. No data can be retrieved while the + * query is active. + * \param [in] cmd Command list + */ + void begin( + const Rc& cmd); + + /** + * \brief Ends query + * + * Sets query into pending state. Calling + * \c getData is legal after calling this. + */ + void end(); + + /** + * \brief Adds a query handle to the query + * + * The given query handle shall be used when + * retrieving query data. A query can have + * multiple handles attached. + * \param [in] handle The query handle + */ + void addQueryHandle( + const DxvkGpuQueryHandle& handle); + + private: + + Rc m_vkd; + + VkQueryType m_type; + VkQueryControlFlags m_flags; + uint32_t m_index; + bool m_ended; + + DxvkGpuQueryHandle m_handle; + + std::vector m_handles; + + DxvkGpuQueryStatus getDataForHandle( + DxvkQueryData& queryData, + const DxvkGpuQueryHandle& handle) const; + + }; + + + /** + * \brief Query allocator + * + * Creates query pools and allocates + * queries for a single query type. + */ + class DxvkGpuQueryAllocator { + + public: + + DxvkGpuQueryAllocator( + DxvkDevice* device, + VkQueryType queryType, + uint32_t queryPoolSize); + + ~DxvkGpuQueryAllocator(); + + /** + * \brief Allocates a query + * + * If possible, this returns a free query + * from an existing query pool. Otherwise, + * a new query pool will be created. + * \returns Query handle + */ + DxvkGpuQueryHandle allocQuery(); + + /** + * \brief Recycles a query + * + * Returns a query back to the allocator + * so that it can be reused. The query + * must not be in pending state. + * \param [in] handle Query to reset + */ + void freeQuery(DxvkGpuQueryHandle handle); + + private: + + DxvkDevice* m_device; + Rc m_vkd; + VkQueryType m_queryType; + uint32_t m_queryPoolSize; + + dxvk::mutex m_mutex; + std::vector m_handles; + std::vector m_pools; + + void createQueryPool(); + + }; + + + /** + * \brief Query pool + * + * Small wrapper class that manages query + * allocators for all supported query types, + */ + class DxvkGpuQueryPool { + + public: + + DxvkGpuQueryPool(DxvkDevice* device); + + ~DxvkGpuQueryPool(); + + /** + * \brief Allocates a single query + * + * \param [in] type Query type + * \returns Handle to the allocated query + */ + DxvkGpuQueryHandle allocQuery(VkQueryType type); + + private: + + DxvkGpuQueryAllocator m_occlusion; + DxvkGpuQueryAllocator m_statistic; + DxvkGpuQueryAllocator m_timestamp; + DxvkGpuQueryAllocator m_xfbStream; + + }; + + + /** + * \brief Query manager + * + * Keeps track of enabled and disabled queries + * and assigns Vulkan queries to them as needed. + */ + class DxvkGpuQueryManager { + + public: + + DxvkGpuQueryManager(DxvkGpuQueryPool& pool); + + ~DxvkGpuQueryManager(); + + /** + * \brief Enables a query + * + * This will also immediately begin the + * query in case the query type is active. + * \param [in] cmd Command list + * \param [in] query Query to allocate + */ + void enableQuery( + const Rc& cmd, + const Rc& query); + + /** + * \brief Disables a query + * + * This will also immediately end the + * query in case the query type is active. + * \param [in] cmd Command list + * \param [in] query Query to allocate + */ + void disableQuery( + const Rc& cmd, + const Rc& query); + + /** + * \brief Signals a time stamp query + * + * Timestamp queries are not scoped. + * \param [in] cmd Command list + * \param [in] query Query to allocate + */ + void writeTimestamp( + const Rc& cmd, + const Rc& query); + + /** + * \brief Begins queries of a given type + * + * Makes a query type \e active. Begins + * all enabled queries of this type. + * \param [in] cmd Command list + * \param [in] type Query type + */ + void beginQueries( + const Rc& cmd, + VkQueryType type); + + /** + * \brief Ends queries of a given type + * + * Makes a query type \e inactive. Ends + * all enabled queries of this type. + * \param [in] cmd Command list + * \param [in] type Query type + */ + void endQueries( + const Rc& cmd, + VkQueryType type); + + private: + + DxvkGpuQueryPool* m_pool; + uint32_t m_activeTypes; + std::vector> m_activeQueries; + + void beginSingleQuery( + const Rc& cmd, + const Rc& query); + + void endSingleQuery( + const Rc& cmd, + const Rc& query); + + static uint32_t getQueryTypeBit( + VkQueryType type); + + }; + + + /** + * \brief Query tracker + * + * Returns queries to their allocators after + * the command buffer has finished executing. + */ + class DxvkGpuQueryTracker { + + public: + + DxvkGpuQueryTracker(); + ~DxvkGpuQueryTracker(); + + /** + * \param Tracks a query + * \param [in] handle Query handle + */ + void trackQuery(DxvkGpuQueryHandle handle); + + /** + * \brief Recycles all tracked handles + * + * Releases all tracked query handles + * to their respective query allocator. + */ + void reset(); + + private: + + std::vector m_handles; + + }; +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_graphics.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_graphics.cpp new file mode 100644 index 00000000000..66c4131ece1 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_graphics.cpp @@ -0,0 +1,637 @@ +#include "../util/util_time.h" + +#include "dxvk_device.h" +#include "dxvk_graphics.h" +#include "dxvk_pipemanager.h" +#include "dxvk_spec_const.h" +#include "dxvk_state_cache.h" + +namespace dxvk { + + DxvkGraphicsPipeline::DxvkGraphicsPipeline( + DxvkPipelineManager* pipeMgr, + DxvkGraphicsPipelineShaders shaders) + : m_vkd(pipeMgr->m_device->vkd()), m_pipeMgr(pipeMgr), + m_shaders(std::move(shaders)) { + if (m_shaders.vs != nullptr) m_shaders.vs ->defineResourceSlots(m_slotMapping); + if (m_shaders.tcs != nullptr) m_shaders.tcs->defineResourceSlots(m_slotMapping); + if (m_shaders.tes != nullptr) m_shaders.tes->defineResourceSlots(m_slotMapping); + if (m_shaders.gs != nullptr) m_shaders.gs ->defineResourceSlots(m_slotMapping); + if (m_shaders.fs != nullptr) m_shaders.fs ->defineResourceSlots(m_slotMapping); + + m_slotMapping.makeDescriptorsDynamic( + pipeMgr->m_device->options().maxNumDynamicUniformBuffers, + pipeMgr->m_device->options().maxNumDynamicStorageBuffers); + + m_layout = new DxvkPipelineLayout(m_vkd, + m_slotMapping, VK_PIPELINE_BIND_POINT_GRAPHICS); + + m_vsIn = m_shaders.vs != nullptr ? m_shaders.vs->info().inputMask : 0; + m_fsOut = m_shaders.fs != nullptr ? m_shaders.fs->info().outputMask : 0; + + if (m_shaders.gs != nullptr && m_shaders.gs->flags().test(DxvkShaderFlag::HasTransformFeedback)) + m_flags.set(DxvkGraphicsPipelineFlag::HasTransformFeedback); + + if (m_layout->getStorageDescriptorStages()) + m_flags.set(DxvkGraphicsPipelineFlag::HasStorageDescriptors); + + m_common.msSampleShadingEnable = m_shaders.fs != nullptr && m_shaders.fs->flags().test(DxvkShaderFlag::HasSampleRateShading); + m_common.msSampleShadingFactor = 1.0f; + } + + + DxvkGraphicsPipeline::~DxvkGraphicsPipeline() { + for (const auto& instance : m_pipelines) + this->destroyPipeline(instance.pipeline()); + } + + + Rc DxvkGraphicsPipeline::getShader( + VkShaderStageFlagBits stage) const { + switch (stage) { + case VK_SHADER_STAGE_VERTEX_BIT: return m_shaders.vs; + case VK_SHADER_STAGE_GEOMETRY_BIT: return m_shaders.gs; + case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: return m_shaders.tcs; + case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: return m_shaders.tes; + case VK_SHADER_STAGE_FRAGMENT_BIT: return m_shaders.fs; + default: + return nullptr; + } + } + + + VkPipeline DxvkGraphicsPipeline::getPipelineHandle( + const DxvkGraphicsPipelineStateInfo& state, + const DxvkRenderPass* renderPass) { + DxvkGraphicsPipelineInstance* instance = this->findInstance(state, renderPass); + + if (unlikely(!instance)) { + // Exit early if the state vector is invalid + if (!this->validatePipelineState(state, true)) + return VK_NULL_HANDLE; + + // Prevent other threads from adding new instances and check again + std::lock_guard lock(m_mutex); + instance = this->findInstance(state, renderPass); + + if (!instance) { + // Keep pipeline object locked, at worst we're going to stall + // a state cache worker and the current thread needs priority. + instance = this->createInstance(state, renderPass); + this->writePipelineStateToCache(state, renderPass->format()); + } + } + + return instance->pipeline(); + } + + + void DxvkGraphicsPipeline::compilePipeline( + const DxvkGraphicsPipelineStateInfo& state, + const DxvkRenderPass* renderPass) { + // Exit early if the state vector is invalid + if (!this->validatePipelineState(state, false)) + return; + + // Keep the object locked while compiling a pipeline since compiling + // similar pipelines concurrently is fragile on some drivers + std::lock_guard lock(m_mutex); + + if (!this->findInstance(state, renderPass)) + this->createInstance(state, renderPass); + } + + + DxvkGraphicsPipelineInstance* DxvkGraphicsPipeline::createInstance( + const DxvkGraphicsPipelineStateInfo& state, + const DxvkRenderPass* renderPass) { + VkPipeline pipeline = this->createPipeline(state, renderPass); + + m_pipeMgr->m_numGraphicsPipelines += 1; + return &(*m_pipelines.emplace(state, renderPass, pipeline)); + } + + + DxvkGraphicsPipelineInstance* DxvkGraphicsPipeline::findInstance( + const DxvkGraphicsPipelineStateInfo& state, + const DxvkRenderPass* renderPass) { + for (auto& instance : m_pipelines) { + if (instance.isCompatible(state, renderPass)) + return &instance; + } + + return nullptr; + } + + + VkPipeline DxvkGraphicsPipeline::createPipeline( + const DxvkGraphicsPipelineStateInfo& state, + const DxvkRenderPass* renderPass) const { + if (Logger::logLevel() <= LogLevel::Debug) { + Logger::debug("Compiling graphics pipeline..."); + this->logPipelineState(LogLevel::Debug, state); + } + + // Render pass format and image layouts + DxvkRenderPassFormat passFormat = renderPass->format(); + + // Set up dynamic states as needed + std::array dynamicStates; + uint32_t dynamicStateCount = 0; + + dynamicStates[dynamicStateCount++] = VK_DYNAMIC_STATE_VIEWPORT; + dynamicStates[dynamicStateCount++] = VK_DYNAMIC_STATE_SCISSOR; + + if (state.useDynamicDepthBias()) + dynamicStates[dynamicStateCount++] = VK_DYNAMIC_STATE_DEPTH_BIAS; + + if (state.useDynamicDepthBounds()) + dynamicStates[dynamicStateCount++] = VK_DYNAMIC_STATE_DEPTH_BOUNDS; + + if (state.useDynamicBlendConstants()) + dynamicStates[dynamicStateCount++] = VK_DYNAMIC_STATE_BLEND_CONSTANTS; + + if (state.useDynamicStencilRef()) + dynamicStates[dynamicStateCount++] = VK_DYNAMIC_STATE_STENCIL_REFERENCE; + + // Figure out the actual sample count to use + VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT; + + if (state.ms.sampleCount()) + sampleCount = VkSampleCountFlagBits(state.ms.sampleCount()); + else if (state.rs.sampleCount()) + sampleCount = VkSampleCountFlagBits(state.rs.sampleCount()); + + // Set up some specialization constants + DxvkSpecConstants specData; + specData.set(uint32_t(DxvkSpecConstantId::RasterizerSampleCount), sampleCount, VK_SAMPLE_COUNT_1_BIT); + + for (uint32_t i = 0; i < m_layout->bindingCount(); i++) + specData.set(i, state.bsBindingMask.test(i), true); + + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { + if ((m_fsOut & (1 << i)) != 0) { + specData.set(uint32_t(DxvkSpecConstantId::ColorComponentMappings) + i, + state.omSwizzle[i].rIndex() << 0 | state.omSwizzle[i].gIndex() << 4 | + state.omSwizzle[i].bIndex() << 8 | state.omSwizzle[i].aIndex() << 12, 0x3210u); + } + } + + for (uint32_t i = 0; i < MaxNumSpecConstants; i++) + specData.set(getSpecId(i), state.sc.specConstants[i], 0u); + + VkSpecializationInfo specInfo = specData.getSpecInfo(); + + auto vsm = createShaderModule(m_shaders.vs, state); + auto tcsm = createShaderModule(m_shaders.tcs, state); + auto tesm = createShaderModule(m_shaders.tes, state); + auto gsm = createShaderModule(m_shaders.gs, state); + auto fsm = createShaderModule(m_shaders.fs, state); + + std::vector stages; + if (vsm) stages.push_back(vsm.stageInfo(&specInfo)); + if (tcsm) stages.push_back(tcsm.stageInfo(&specInfo)); + if (tesm) stages.push_back(tesm.stageInfo(&specInfo)); + if (gsm) stages.push_back(gsm.stageInfo(&specInfo)); + if (fsm) stages.push_back(fsm.stageInfo(&specInfo)); + + // Fix up color write masks using the component mappings + std::array omBlendAttachments; + + const VkColorComponentFlags fullMask + = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT + | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { + auto formatInfo = imageFormatInfo(passFormat.color[i].format); + omBlendAttachments[i] = state.omBlend[i].state(); + + if (!(m_fsOut & (1 << i)) || !formatInfo) { + omBlendAttachments[i].colorWriteMask = 0; + } else { + if (omBlendAttachments[i].colorWriteMask != fullMask) { + omBlendAttachments[i].colorWriteMask = util::remapComponentMask( + state.omBlend[i].colorWriteMask(), state.omSwizzle[i].mapping()); + } + + omBlendAttachments[i].colorWriteMask &= formatInfo->componentMask; + + if (omBlendAttachments[i].colorWriteMask == formatInfo->componentMask) { + omBlendAttachments[i].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT + | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + } + } + } + + // Generate per-instance attribute divisors + std::array viDivisorDesc; + uint32_t viDivisorCount = 0; + + for (uint32_t i = 0; i < state.il.bindingCount(); i++) { + if (state.ilBindings[i].inputRate() == VK_VERTEX_INPUT_RATE_INSTANCE + && state.ilBindings[i].divisor() != 1) { + const uint32_t id = viDivisorCount++; + + viDivisorDesc[id].binding = i; /* see below */ + viDivisorDesc[id].divisor = state.ilBindings[i].divisor(); + } + } + + int32_t rasterizedStream = m_shaders.gs != nullptr + ? m_shaders.gs->info().xfbRasterizedStream + : 0; + + // Compact vertex bindings so that we can more easily update vertex buffers + std::array viAttribs; + std::array viBindings; + std::array viBindingMap = { }; + + for (uint32_t i = 0; i < state.il.bindingCount(); i++) { + viBindings[i] = state.ilBindings[i].description(); + viBindings[i].binding = i; + viBindingMap[state.ilBindings[i].binding()] = i; + } + + for (uint32_t i = 0; i < state.il.attributeCount(); i++) { + viAttribs[i] = state.ilAttributes[i].description(); + viAttribs[i].binding = viBindingMap[state.ilAttributes[i].binding()]; + } + + VkPipelineVertexInputDivisorStateCreateInfoEXT viDivisorInfo; + viDivisorInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT; + viDivisorInfo.pNext = nullptr; + viDivisorInfo.vertexBindingDivisorCount = viDivisorCount; + viDivisorInfo.pVertexBindingDivisors = viDivisorDesc.data(); + + VkPipelineVertexInputStateCreateInfo viInfo; + viInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + viInfo.pNext = &viDivisorInfo; + viInfo.flags = 0; + viInfo.vertexBindingDescriptionCount = state.il.bindingCount(); + viInfo.pVertexBindingDescriptions = viBindings.data(); + viInfo.vertexAttributeDescriptionCount = state.il.attributeCount(); + viInfo.pVertexAttributeDescriptions = viAttribs.data(); + + if (viDivisorCount == 0) + viInfo.pNext = viDivisorInfo.pNext; + + // TODO remove this once the extension is widely supported + if (!m_pipeMgr->m_device->features().extVertexAttributeDivisor.vertexAttributeInstanceRateDivisor) + viInfo.pNext = viDivisorInfo.pNext; + + VkPipelineInputAssemblyStateCreateInfo iaInfo; + iaInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + iaInfo.pNext = nullptr; + iaInfo.flags = 0; + iaInfo.topology = state.ia.primitiveTopology(); + iaInfo.primitiveRestartEnable = state.ia.primitiveRestart(); + + VkPipelineTessellationStateCreateInfo tsInfo; + tsInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO; + tsInfo.pNext = nullptr; + tsInfo.flags = 0; + tsInfo.patchControlPoints = state.ia.patchVertexCount(); + + VkPipelineViewportStateCreateInfo vpInfo; + vpInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + vpInfo.pNext = nullptr; + vpInfo.flags = 0; + vpInfo.viewportCount = state.rs.viewportCount(); + vpInfo.pViewports = nullptr; + vpInfo.scissorCount = state.rs.viewportCount(); + vpInfo.pScissors = nullptr; + + VkPipelineRasterizationConservativeStateCreateInfoEXT conservativeInfo; + conservativeInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT; + conservativeInfo.pNext = nullptr; + conservativeInfo.flags = 0; + conservativeInfo.conservativeRasterizationMode = state.rs.conservativeMode(); + conservativeInfo.extraPrimitiveOverestimationSize = 0.0f; + + VkPipelineRasterizationStateStreamCreateInfoEXT xfbStreamInfo; + xfbStreamInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT; + xfbStreamInfo.pNext = nullptr; + xfbStreamInfo.flags = 0; + xfbStreamInfo.rasterizationStream = uint32_t(rasterizedStream); + + VkPipelineRasterizationDepthClipStateCreateInfoEXT rsDepthClipInfo; + rsDepthClipInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT; + rsDepthClipInfo.pNext = nullptr; + rsDepthClipInfo.flags = 0; + rsDepthClipInfo.depthClipEnable = state.rs.depthClipEnable(); + + VkPipelineRasterizationStateCreateInfo rsInfo; + rsInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + rsInfo.pNext = nullptr; + rsInfo.flags = 0; + rsInfo.depthClampEnable = VK_TRUE; + rsInfo.rasterizerDiscardEnable = rasterizedStream < 0; + rsInfo.polygonMode = state.rs.polygonMode(); + rsInfo.cullMode = state.rs.cullMode(); + rsInfo.frontFace = state.rs.frontFace(); + rsInfo.depthBiasEnable = state.rs.depthBiasEnable(); + rsInfo.depthBiasConstantFactor= 0.0f; + rsInfo.depthBiasClamp = 0.0f; + rsInfo.depthBiasSlopeFactor = 0.0f; + rsInfo.lineWidth = 1.0f; + + if (rasterizedStream > 0) + xfbStreamInfo.pNext = std::exchange(rsInfo.pNext, &xfbStreamInfo); + + if (conservativeInfo.conservativeRasterizationMode != VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT) + conservativeInfo.pNext = std::exchange(rsInfo.pNext, &conservativeInfo); + + if (m_pipeMgr->m_device->features().extDepthClipEnable.depthClipEnable) + rsDepthClipInfo.pNext = std::exchange(rsInfo.pNext, &rsDepthClipInfo); + else + rsInfo.depthClampEnable = !state.rs.depthClipEnable(); + + uint32_t sampleMask = state.ms.sampleMask(); + + VkPipelineMultisampleStateCreateInfo msInfo; + msInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + msInfo.pNext = nullptr; + msInfo.flags = 0; + msInfo.rasterizationSamples = sampleCount; + msInfo.sampleShadingEnable = m_common.msSampleShadingEnable; + msInfo.minSampleShading = m_common.msSampleShadingFactor; + msInfo.pSampleMask = &sampleMask; + msInfo.alphaToCoverageEnable = state.ms.enableAlphaToCoverage(); + msInfo.alphaToOneEnable = VK_FALSE; + + VkPipelineDepthStencilStateCreateInfo dsInfo; + dsInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + dsInfo.pNext = nullptr; + dsInfo.flags = 0; + dsInfo.depthTestEnable = state.ds.enableDepthTest(); + dsInfo.depthWriteEnable = state.ds.enableDepthWrite() && !util::isDepthReadOnlyLayout(passFormat.depth.layout); + dsInfo.depthCompareOp = state.ds.depthCompareOp(); + dsInfo.depthBoundsTestEnable = state.ds.enableDepthBoundsTest(); + dsInfo.stencilTestEnable = state.ds.enableStencilTest(); + dsInfo.front = state.dsFront.state(); + dsInfo.back = state.dsBack.state(); + dsInfo.minDepthBounds = 0.0f; + dsInfo.maxDepthBounds = 1.0f; + + VkPipelineColorBlendStateCreateInfo cbInfo; + cbInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + cbInfo.pNext = nullptr; + cbInfo.flags = 0; + cbInfo.logicOpEnable = state.om.enableLogicOp(); + cbInfo.logicOp = state.om.logicOp(); + cbInfo.attachmentCount = DxvkLimits::MaxNumRenderTargets; + cbInfo.pAttachments = omBlendAttachments.data(); + + for (uint32_t i = 0; i < 4; i++) + cbInfo.blendConstants[i] = 0.0f; + + VkPipelineDynamicStateCreateInfo dyInfo; + dyInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; + dyInfo.pNext = nullptr; + dyInfo.flags = 0; + dyInfo.dynamicStateCount = dynamicStateCount; + dyInfo.pDynamicStates = dynamicStates.data(); + + VkGraphicsPipelineCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.stageCount = stages.size(); + info.pStages = stages.data(); + info.pVertexInputState = &viInfo; + info.pInputAssemblyState = &iaInfo; + info.pTessellationState = &tsInfo; + info.pViewportState = &vpInfo; + info.pRasterizationState = &rsInfo; + info.pMultisampleState = &msInfo; + info.pDepthStencilState = &dsInfo; + info.pColorBlendState = &cbInfo; + info.pDynamicState = &dyInfo; + info.layout = m_layout->pipelineLayout(); + info.renderPass = renderPass->getDefaultHandle(); + info.subpass = 0; + info.basePipelineHandle = VK_NULL_HANDLE; + info.basePipelineIndex = -1; + + if (tsInfo.patchControlPoints == 0) + info.pTessellationState = nullptr; + + // Time pipeline compilation for debugging purposes + dxvk::high_resolution_clock::time_point t0, t1; + + if (Logger::logLevel() <= LogLevel::Debug) + t0 = dxvk::high_resolution_clock::now(); + + VkPipeline pipeline = VK_NULL_HANDLE; + if (m_vkd->vkCreateGraphicsPipelines(m_vkd->device(), + m_pipeMgr->m_cache->handle(), 1, &info, nullptr, &pipeline) != VK_SUCCESS) { + Logger::err("DxvkGraphicsPipeline: Failed to compile pipeline"); + this->logPipelineState(LogLevel::Error, state); + return VK_NULL_HANDLE; + } + + if (Logger::logLevel() <= LogLevel::Debug) { + t1 = dxvk::high_resolution_clock::now(); + auto td = std::chrono::duration_cast(t1 - t0); + Logger::debug(str::format("DxvkGraphicsPipeline: Finished in ", td.count(), " ms")); + } + + return pipeline; + } + + + void DxvkGraphicsPipeline::destroyPipeline(VkPipeline pipeline) const { + m_vkd->vkDestroyPipeline(m_vkd->device(), pipeline, nullptr); + } + + + DxvkShaderModule DxvkGraphicsPipeline::createShaderModule( + const Rc& shader, + const DxvkGraphicsPipelineStateInfo& state) const { + if (shader == nullptr) + return DxvkShaderModule(); + + const DxvkShaderCreateInfo& shaderInfo = shader->info(); + DxvkShaderModuleCreateInfo info; + + // Fix up fragment shader outputs for dual-source blending + if (shaderInfo.stage == VK_SHADER_STAGE_FRAGMENT_BIT) { + info.fsDualSrcBlend = state.omBlend[0].blendEnable() && ( + util::isDualSourceBlendFactor(state.omBlend[0].srcColorBlendFactor()) || + util::isDualSourceBlendFactor(state.omBlend[0].dstColorBlendFactor()) || + util::isDualSourceBlendFactor(state.omBlend[0].srcAlphaBlendFactor()) || + util::isDualSourceBlendFactor(state.omBlend[0].dstAlphaBlendFactor())); + } + + // Deal with undefined shader inputs + uint32_t consumedInputs = shaderInfo.inputMask; + uint32_t providedInputs = 0; + + if (shaderInfo.stage == VK_SHADER_STAGE_VERTEX_BIT) { + for (uint32_t i = 0; i < state.il.attributeCount(); i++) + providedInputs |= 1u << state.ilAttributes[i].location(); + } else if (shaderInfo.stage != VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) { + auto prevStage = getPrevStageShader(shaderInfo.stage); + providedInputs = prevStage->info().outputMask; + } else { + // Technically not correct, but this + // would need a lot of extra care + providedInputs = consumedInputs; + } + + info.undefinedInputs = (providedInputs & consumedInputs) ^ consumedInputs; + return shader->createShaderModule(m_vkd, m_slotMapping, info); + } + + + Rc DxvkGraphicsPipeline::getPrevStageShader(VkShaderStageFlagBits stage) const { + if (stage == VK_SHADER_STAGE_VERTEX_BIT) + return nullptr; + + if (stage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) + return m_shaders.tcs; + + Rc result = m_shaders.vs; + + if (stage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) + return result; + + if (m_shaders.tes != nullptr) + result = m_shaders.tes; + + if (stage == VK_SHADER_STAGE_GEOMETRY_BIT) + return result; + + if (m_shaders.gs != nullptr) + result = m_shaders.gs; + + return result; + } + + + bool DxvkGraphicsPipeline::validatePipelineState( + const DxvkGraphicsPipelineStateInfo& state, + bool trusted) const { + // Tessellation shaders and patches must be used together + bool hasPatches = state.ia.primitiveTopology() == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST; + + bool hasTcs = m_shaders.tcs != nullptr; + bool hasTes = m_shaders.tes != nullptr; + + if (hasPatches != hasTcs || hasPatches != hasTes) + return false; + + // Filter out undefined primitive topologies + if (state.ia.primitiveTopology() == VK_PRIMITIVE_TOPOLOGY_MAX_ENUM) + return false; + + // Prevent unintended out-of-bounds access to the IL arrays + if (state.il.attributeCount() > DxvkLimits::MaxNumVertexAttributes + || state.il.bindingCount() > DxvkLimits::MaxNumVertexBindings) + return false; + + // Exit here on the fast path, perform more thorough validation if + // the state vector comes from an untrusted source (i.e. the cache) + if (trusted) + return true; + + // Validate shaders + if (!m_shaders.validate()) { + Logger::err("Invalid pipeline: Shader types do not match stage"); + return false; + } + + // Validate vertex input layout + const DxvkDevice* device = m_pipeMgr->m_device; + uint32_t ilLocationMask = 0; + uint32_t ilBindingMask = 0; + + for (uint32_t i = 0; i < state.il.bindingCount(); i++) + ilBindingMask |= 1u << state.ilBindings[i].binding(); + + for (uint32_t i = 0; i < state.il.attributeCount(); i++) { + const DxvkIlAttribute& attribute = state.ilAttributes[i]; + + if (ilLocationMask & (1u << attribute.location())) { + Logger::err(str::format("Invalid pipeline: Vertex location ", attribute.location(), " defined twice")); + return false; + } + + if (!(ilBindingMask & (1u << attribute.binding()))) { + Logger::err(str::format("Invalid pipeline: Vertex binding ", attribute.binding(), " not defined")); + return false; + } + + VkFormatProperties formatInfo = device->adapter()->formatProperties(attribute.format()); + + if (!(formatInfo.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)) { + Logger::err(str::format("Invalid pipeline: Format ", attribute.format(), " not supported for vertex buffers")); + return false; + } + + ilLocationMask |= 1u << attribute.location(); + } + + // Validate rasterization state + if (state.rs.conservativeMode() != VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT) { + if (!device->extensions().extConservativeRasterization) { + Logger::err("Conservative rasterization not supported by device"); + return false; + } + + if (state.rs.conservativeMode() == VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT + && !device->properties().extConservativeRasterization.primitiveUnderestimation) { + Logger::err("Primitive underestimation not supported by device"); + return false; + } + } + + // Validate depth-stencil state + if (state.ds.enableDepthBoundsTest() && !device->features().core.features.depthBounds) { + Logger::err("Depth bounds not supported by device"); + return false; + } + + return true; + } + + + void DxvkGraphicsPipeline::writePipelineStateToCache( + const DxvkGraphicsPipelineStateInfo& state, + const DxvkRenderPassFormat& format) const { + if (m_pipeMgr->m_stateCache == nullptr) + return; + + DxvkStateCacheKey key; + if (m_shaders.vs != nullptr) key.vs = m_shaders.vs->getShaderKey(); + if (m_shaders.tcs != nullptr) key.tcs = m_shaders.tcs->getShaderKey(); + if (m_shaders.tes != nullptr) key.tes = m_shaders.tes->getShaderKey(); + if (m_shaders.gs != nullptr) key.gs = m_shaders.gs->getShaderKey(); + if (m_shaders.fs != nullptr) key.fs = m_shaders.fs->getShaderKey(); + + m_pipeMgr->m_stateCache->addGraphicsPipeline(key, state, format); + } + + + void DxvkGraphicsPipeline::logPipelineState( + LogLevel level, + const DxvkGraphicsPipelineStateInfo& state) const { + if (m_shaders.vs != nullptr) Logger::log(level, str::format(" vs : ", m_shaders.vs ->debugName())); + if (m_shaders.tcs != nullptr) Logger::log(level, str::format(" tcs : ", m_shaders.tcs->debugName())); + if (m_shaders.tes != nullptr) Logger::log(level, str::format(" tes : ", m_shaders.tes->debugName())); + if (m_shaders.gs != nullptr) Logger::log(level, str::format(" gs : ", m_shaders.gs ->debugName())); + if (m_shaders.fs != nullptr) Logger::log(level, str::format(" fs : ", m_shaders.fs ->debugName())); + + for (uint32_t i = 0; i < state.il.attributeCount(); i++) { + const auto& attr = state.ilAttributes[i]; + Logger::log(level, str::format(" attr ", i, " : location ", attr.location(), ", binding ", attr.binding(), ", format ", attr.format(), ", offset ", attr.offset())); + } + for (uint32_t i = 0; i < state.il.bindingCount(); i++) { + const auto& bind = state.ilBindings[i]; + Logger::log(level, str::format(" binding ", i, " : binding ", bind.binding(), ", stride ", bind.stride(), ", rate ", bind.inputRate(), ", divisor ", bind.divisor())); + } + + // TODO log more pipeline state + } + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_graphics.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_graphics.h new file mode 100644 index 00000000000..50d16b1ef4c --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_graphics.h @@ -0,0 +1,277 @@ +#pragma once + +#include + +#include "../util/sync/sync_list.h" + +#include "dxvk_bind_mask.h" +#include "dxvk_constant_state.h" +#include "dxvk_graphics_state.h" +#include "dxvk_pipecache.h" +#include "dxvk_pipelayout.h" +#include "dxvk_renderpass.h" +#include "dxvk_resource.h" +#include "dxvk_shader.h" +#include "dxvk_stats.h" + +namespace dxvk { + + class DxvkDevice; + class DxvkPipelineManager; + + /** + * \brief Flags that describe pipeline properties + */ + enum class DxvkGraphicsPipelineFlag { + HasTransformFeedback, + HasStorageDescriptors, + }; + + using DxvkGraphicsPipelineFlags = Flags; + + + /** + * \brief Shaders used in graphics pipelines + */ + struct DxvkGraphicsPipelineShaders { + Rc vs; + Rc tcs; + Rc tes; + Rc gs; + Rc fs; + + bool eq(const DxvkGraphicsPipelineShaders& other) const { + return vs == other.vs && tcs == other.tcs + && tes == other.tes && gs == other.gs + && fs == other.fs; + } + + size_t hash() const { + DxvkHashState state; + state.add(DxvkShader::getHash(vs)); + state.add(DxvkShader::getHash(tcs)); + state.add(DxvkShader::getHash(tes)); + state.add(DxvkShader::getHash(gs)); + state.add(DxvkShader::getHash(fs)); + return state; + } + + bool validate() const { + return validateShaderType(vs, VK_SHADER_STAGE_VERTEX_BIT) + && validateShaderType(tcs, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) + && validateShaderType(tes, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) + && validateShaderType(gs, VK_SHADER_STAGE_GEOMETRY_BIT) + && validateShaderType(fs, VK_SHADER_STAGE_FRAGMENT_BIT); + } + + static bool validateShaderType(const Rc& shader, VkShaderStageFlagBits stage) { + return shader == nullptr || shader->info().stage == stage; + } + }; + + + /** + * \brief Common graphics pipeline state + * + * Non-dynamic pipeline state that cannot + * be changed dynamically. + */ + struct DxvkGraphicsCommonPipelineStateInfo { + bool msSampleShadingEnable; + float msSampleShadingFactor; + }; + + + /** + * \brief Graphics pipeline instance + * + * Stores a state vector and the + * corresponding pipeline handle. + */ + class DxvkGraphicsPipelineInstance { + + public: + + DxvkGraphicsPipelineInstance() + : m_stateVector (), + m_renderPass (nullptr), + m_pipeline (VK_NULL_HANDLE) { } + + DxvkGraphicsPipelineInstance( + const DxvkGraphicsPipelineStateInfo& state, + const DxvkRenderPass* rp, + VkPipeline pipe) + : m_stateVector (state), + m_renderPass (rp), + m_pipeline (pipe) { } + + /** + * \brief Checks for matching pipeline state + * + * \param [in] stateVector Graphics pipeline state + * \param [in] renderPass Render pass handle + * \returns \c true if the specialization is compatible + */ + bool isCompatible( + const DxvkGraphicsPipelineStateInfo& state, + const DxvkRenderPass* rp) { + return m_renderPass == rp + && m_stateVector == state; + } + + /** + * \brief Retrieves pipeline + * \returns The pipeline handle + */ + VkPipeline pipeline() const { + return m_pipeline; + } + + private: + + DxvkGraphicsPipelineStateInfo m_stateVector; + const DxvkRenderPass* m_renderPass; + VkPipeline m_pipeline; + + }; + + + /** + * \brief Graphics pipeline + * + * Stores the pipeline layout as well as methods to + * recompile the graphics pipeline against a given + * pipeline state vector. + */ + class DxvkGraphicsPipeline { + + public: + + DxvkGraphicsPipeline( + DxvkPipelineManager* pipeMgr, + DxvkGraphicsPipelineShaders shaders); + + ~DxvkGraphicsPipeline(); + + /** + * \brief Shaders used by the pipeline + * \returns Shaders used by the pipeline + */ + const DxvkGraphicsPipelineShaders& shaders() const { + return m_shaders; + } + + /** + * \brief Returns graphics pipeline flags + * \returns Graphics pipeline property flags + */ + DxvkGraphicsPipelineFlags flags() const { + return m_flags; + } + + /** + * \brief Pipeline layout + * + * Stores the pipeline layout and the descriptor set + * layout, as well as information on the resource + * slots used by the pipeline. + * \returns Pipeline layout + */ + DxvkPipelineLayout* layout() const { + return m_layout.ptr(); + } + + /** + * \brief Queries shader for a given stage + * + * In case no shader is specified for the + * given stage, \c nullptr will be returned. + * \param [in] stage The shader stage + * \returns Shader of the given stage + */ + Rc getShader( + VkShaderStageFlagBits stage) const; + + /** + * \brief Pipeline handle + * + * Retrieves a pipeline handle for the given pipeline + * state. If necessary, a new pipeline will be created. + * \param [in] state Pipeline state vector + * \param [in] renderPass The render pass + * \returns Pipeline handle + */ + VkPipeline getPipelineHandle( + const DxvkGraphicsPipelineStateInfo& state, + const DxvkRenderPass* renderPass); + + /** + * \brief Compiles a pipeline + * + * Asynchronously compiles the given pipeline + * and stores the result for future use. + * \param [in] state Pipeline state vector + * \param [in] renderPass The render pass + */ + void compilePipeline( + const DxvkGraphicsPipelineStateInfo& state, + const DxvkRenderPass* renderPass); + + private: + + Rc m_vkd; + DxvkPipelineManager* m_pipeMgr; + + DxvkGraphicsPipelineShaders m_shaders; + DxvkDescriptorSlotMapping m_slotMapping; + + Rc m_layout; + + uint32_t m_vsIn = 0; + uint32_t m_fsOut = 0; + + DxvkGraphicsPipelineFlags m_flags; + DxvkGraphicsCommonPipelineStateInfo m_common; + + // List of pipeline instances, shared between threads + alignas(CACHE_LINE_SIZE) + dxvk::mutex m_mutex; + sync::List m_pipelines; + + DxvkGraphicsPipelineInstance* createInstance( + const DxvkGraphicsPipelineStateInfo& state, + const DxvkRenderPass* renderPass); + + DxvkGraphicsPipelineInstance* findInstance( + const DxvkGraphicsPipelineStateInfo& state, + const DxvkRenderPass* renderPass); + + VkPipeline createPipeline( + const DxvkGraphicsPipelineStateInfo& state, + const DxvkRenderPass* renderPass) const; + + void destroyPipeline( + VkPipeline pipeline) const; + + DxvkShaderModule createShaderModule( + const Rc& shader, + const DxvkGraphicsPipelineStateInfo& state) const; + + Rc getPrevStageShader( + VkShaderStageFlagBits stage) const; + + bool validatePipelineState( + const DxvkGraphicsPipelineStateInfo& state, + bool trusted) const; + + void writePipelineStateToCache( + const DxvkGraphicsPipelineStateInfo& state, + const DxvkRenderPassFormat& format) const; + + void logPipelineState( + LogLevel level, + const DxvkGraphicsPipelineStateInfo& state) const; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_graphics_state.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_graphics_state.h new file mode 100644 index 00000000000..b10f7835585 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_graphics_state.h @@ -0,0 +1,728 @@ +#pragma once + +#include "dxvk_limits.h" + +#include + +namespace dxvk { + + /** + * \brief Packed input assembly state + * + * Stores the primitive topology + * and primitive restart info. + */ + class DxvkIaInfo { + + public: + + DxvkIaInfo() = default; + + DxvkIaInfo( + VkPrimitiveTopology primitiveTopology, + VkBool32 primitiveRestart, + uint32_t patchVertexCount) + : m_primitiveTopology (uint16_t(primitiveTopology)), + m_primitiveRestart (uint16_t(primitiveRestart)), + m_patchVertexCount (uint16_t(patchVertexCount)), + m_reserved (0) { } + + VkPrimitiveTopology primitiveTopology() const { + return m_primitiveTopology <= VK_PRIMITIVE_TOPOLOGY_PATCH_LIST + ? VkPrimitiveTopology(m_primitiveTopology) + : VK_PRIMITIVE_TOPOLOGY_MAX_ENUM; + } + + VkBool32 primitiveRestart() const { + return VkBool32(m_primitiveRestart); + } + + uint32_t patchVertexCount() const { + return m_patchVertexCount; + } + + private: + + uint16_t m_primitiveTopology : 4; + uint16_t m_primitiveRestart : 1; + uint16_t m_patchVertexCount : 6; + uint16_t m_reserved : 5; + + }; + + + /** + * \brief Packed input layout metadata + * + * Stores the number of vertex attributes + * and bindings in one byte each. + */ + class DxvkIlInfo { + + public: + + DxvkIlInfo() = default; + + DxvkIlInfo( + uint32_t attributeCount, + uint32_t bindingCount) + : m_attributeCount(uint8_t(attributeCount)), + m_bindingCount (uint8_t(bindingCount)) { } + + uint32_t attributeCount() const { + return m_attributeCount; + } + + uint32_t bindingCount() const { + return m_bindingCount; + } + + private: + + uint8_t m_attributeCount; + uint8_t m_bindingCount; + + }; + + + /** + * \brief Packed vertex attribute + * + * Stores a vertex attribute description. Assumes + * that all vertex formats have numerical values + * of 127 or less (i.e. fit into 7 bits). + */ + class DxvkIlAttribute { + + public: + + DxvkIlAttribute() = default; + + DxvkIlAttribute( + uint32_t location, + uint32_t binding, + VkFormat format, + uint32_t offset) + : m_location(uint32_t(location)), + m_binding (uint32_t(binding)), + m_format (uint32_t(format)), + m_offset (uint32_t(offset)), + m_reserved(0) { } + + uint32_t location() const { + return m_location; + } + + uint32_t binding() const { + return m_binding; + } + + VkFormat format() const { + return VkFormat(m_format); + } + + uint32_t offset() const { + return m_offset; + } + + VkVertexInputAttributeDescription description() const { + VkVertexInputAttributeDescription result; + result.location = m_location; + result.binding = m_binding; + result.format = VkFormat(m_format); + result.offset = m_offset; + return result; + } + + private: + + uint32_t m_location : 5; + uint32_t m_binding : 5; + uint32_t m_format : 7; + uint32_t m_offset : 11; + uint32_t m_reserved : 4; + + }; + + + /** + * \brief Packed vertex binding + * + * Stores a vertex binding description, + * including the 32-bit divisor. + */ + class DxvkIlBinding { + + public: + + DxvkIlBinding() = default; + + DxvkIlBinding( + uint32_t binding, + uint32_t stride, + VkVertexInputRate inputRate, + uint32_t divisor) + : m_binding (uint32_t(binding)), + m_stride (uint32_t(stride)), + m_inputRate (uint32_t(inputRate)), + m_divisor (uint32_t(divisor < (1u << 14) ? divisor : 0u)) { } + + uint32_t binding() const { + return m_binding; + } + + uint32_t stride() const { + return m_stride; + } + + VkVertexInputRate inputRate() const { + return VkVertexInputRate(m_inputRate); + } + + uint32_t divisor() const { + return m_divisor; + } + + VkVertexInputBindingDescription description() const { + VkVertexInputBindingDescription result; + result.binding = m_binding; + result.stride = m_stride; + result.inputRate = VkVertexInputRate(m_inputRate); + return result; + } + + void setStride(uint32_t stride) { + m_stride = stride; + } + + private: + + uint32_t m_binding : 5; + uint32_t m_stride : 12; + uint32_t m_inputRate : 1; + uint32_t m_divisor : 14; + + }; + + + /** + * \brief Packed rasterizer state + * + * Stores a bunch of flags and parameters + * related to rasterization in four bytes. + */ + class DxvkRsInfo { + + public: + + DxvkRsInfo() = default; + + DxvkRsInfo( + VkBool32 depthClipEnable, + VkBool32 depthBiasEnable, + VkPolygonMode polygonMode, + VkCullModeFlags cullMode, + VkFrontFace frontFace, + uint32_t viewportCount, + VkSampleCountFlags sampleCount, + VkConservativeRasterizationModeEXT conservativeMode) + : m_depthClipEnable (uint32_t(depthClipEnable)), + m_depthBiasEnable (uint32_t(depthBiasEnable)), + m_polygonMode (uint32_t(polygonMode)), + m_cullMode (uint32_t(cullMode)), + m_frontFace (uint32_t(frontFace)), + m_viewportCount (uint32_t(viewportCount)), + m_sampleCount (uint32_t(sampleCount)), + m_conservativeMode(uint32_t(conservativeMode)), + m_reserved (0) { } + + VkBool32 depthClipEnable() const { + return VkBool32(m_depthClipEnable); + } + + VkBool32 depthBiasEnable() const { + return VkBool32(m_depthBiasEnable); + } + + VkPolygonMode polygonMode() const { + return VkPolygonMode(m_polygonMode); + } + + VkCullModeFlags cullMode() const { + return VkCullModeFlags(m_cullMode); + } + + VkFrontFace frontFace() const { + return VkFrontFace(m_frontFace); + } + + uint32_t viewportCount() const { + return m_viewportCount; + } + + VkSampleCountFlags sampleCount() const { + return VkSampleCountFlags(m_sampleCount); + } + + VkConservativeRasterizationModeEXT conservativeMode() const { + return VkConservativeRasterizationModeEXT(m_conservativeMode); + } + + void setViewportCount(uint32_t viewportCount) { + m_viewportCount = viewportCount; + } + + private: + + uint32_t m_depthClipEnable : 1; + uint32_t m_depthBiasEnable : 1; + uint32_t m_polygonMode : 2; + uint32_t m_cullMode : 2; + uint32_t m_frontFace : 1; + uint32_t m_viewportCount : 5; + uint32_t m_sampleCount : 5; + uint32_t m_conservativeMode : 2; + uint32_t m_reserved : 13; + + }; + + + /** + * \brief Packed multisample info + * + * Stores the sample mask, sample count override + * and alpha-to-coverage state in four bytes. + */ + class DxvkMsInfo { + + public: + + DxvkMsInfo() = default; + + DxvkMsInfo( + VkSampleCountFlags sampleCount, + uint32_t sampleMask, + VkBool32 enableAlphaToCoverage) + : m_sampleCount (uint16_t(sampleCount)), + m_enableAlphaToCoverage (uint16_t(enableAlphaToCoverage)), + m_reserved (0), + m_sampleMask (uint16_t(sampleMask)) { } + + VkSampleCountFlags sampleCount() const { + return VkSampleCountFlags(m_sampleCount); + } + + uint32_t sampleMask() const { + return m_sampleMask; + } + + VkBool32 enableAlphaToCoverage() const { + return VkBool32(m_enableAlphaToCoverage); + } + + void setSampleCount(VkSampleCountFlags sampleCount) { + m_sampleCount = uint16_t(sampleCount); + } + + private: + + uint16_t m_sampleCount : 5; + uint16_t m_enableAlphaToCoverage : 1; + uint16_t m_reserved : 10; + uint16_t m_sampleMask; + + }; + + + /** + * \brief Packed depth-stencil metadata + * + * Stores some flags and the depth-compare op in + * two bytes. Stencil ops are stored separately. + */ + class DxvkDsInfo { + + public: + + DxvkDsInfo() = default; + + DxvkDsInfo( + VkBool32 enableDepthTest, + VkBool32 enableDepthWrite, + VkBool32 enableDepthBoundsTest, + VkBool32 enableStencilTest, + VkCompareOp depthCompareOp) + : m_enableDepthTest (uint16_t(enableDepthTest)), + m_enableDepthWrite (uint16_t(enableDepthWrite)), + m_enableDepthBoundsTest (uint16_t(enableDepthBoundsTest)), + m_enableStencilTest (uint16_t(enableStencilTest)), + m_depthCompareOp (uint16_t(depthCompareOp)), + m_reserved (0) { } + + VkBool32 enableDepthTest() const { + return VkBool32(m_enableDepthTest); + } + + VkBool32 enableDepthWrite() const { + return VkBool32(m_enableDepthWrite); + } + + VkBool32 enableDepthBoundsTest() const { + return VkBool32(m_enableDepthBoundsTest); + } + + VkBool32 enableStencilTest() const { + return VkBool32(m_enableStencilTest); + } + + VkCompareOp depthCompareOp() const { + return VkCompareOp(m_depthCompareOp); + } + + void setEnableDepthBoundsTest(VkBool32 enableDepthBoundsTest) { + m_enableDepthBoundsTest = VkBool32(enableDepthBoundsTest); + } + + private: + + uint16_t m_enableDepthTest : 1; + uint16_t m_enableDepthWrite : 1; + uint16_t m_enableDepthBoundsTest : 1; + uint16_t m_enableStencilTest : 1; + uint16_t m_depthCompareOp : 3; + uint16_t m_reserved : 9; + + }; + + + /** + * \brief Packed stencil op + * + * Stores various stencil op parameters + * for one single face in four bytes. + */ + class DxvkDsStencilOp { + + public: + + DxvkDsStencilOp() = default; + + DxvkDsStencilOp(VkStencilOpState state) + : m_failOp (uint32_t(state.failOp)), + m_passOp (uint32_t(state.passOp)), + m_depthFailOp (uint32_t(state.depthFailOp)), + m_compareOp (uint32_t(state.compareOp)), + m_reserved (0), + m_compareMask (uint32_t(state.compareMask)), + m_writeMask (uint32_t(state.writeMask)) { } + + VkStencilOpState state() const { + VkStencilOpState result; + result.failOp = VkStencilOp(m_failOp); + result.passOp = VkStencilOp(m_passOp); + result.depthFailOp = VkStencilOp(m_depthFailOp); + result.compareOp = VkCompareOp(m_compareOp); + result.compareMask = m_compareMask; + result.writeMask = m_writeMask; + result.reference = 0; + return result; + } + + private: + + uint32_t m_failOp : 3; + uint32_t m_passOp : 3; + uint32_t m_depthFailOp : 3; + uint32_t m_compareOp : 3; + uint32_t m_reserved : 4; + uint32_t m_compareMask : 8; + uint32_t m_writeMask : 8; + + }; + + + /** + * \brief Packed output merger metadata + * + * Stores the logic op state in two bytes. + * Blend modes are stored separately. + */ + class DxvkOmInfo { + + public: + + DxvkOmInfo() = default; + + DxvkOmInfo( + VkBool32 enableLogicOp, + VkLogicOp logicOp) + : m_enableLogicOp (uint16_t(enableLogicOp)), + m_logicOp (uint16_t(logicOp)), + m_reserved (0) { } + + VkBool32 enableLogicOp() const { + return VkBool32(m_enableLogicOp); + } + + VkLogicOp logicOp() const { + return VkLogicOp(m_logicOp); + } + + private: + + uint16_t m_enableLogicOp : 1; + uint16_t m_logicOp : 4; + uint16_t m_reserved : 11; + + }; + + + /** + * \brief Packed attachment blend mode + * + * Stores blendig parameters for a single + * color attachment in four bytes. + */ + class DxvkOmAttachmentBlend { + + public: + + DxvkOmAttachmentBlend() = default; + + DxvkOmAttachmentBlend( + VkBool32 blendEnable, + VkBlendFactor srcColorBlendFactor, + VkBlendFactor dstColorBlendFactor, + VkBlendOp colorBlendOp, + VkBlendFactor srcAlphaBlendFactor, + VkBlendFactor dstAlphaBlendFactor, + VkBlendOp alphaBlendOp, + VkColorComponentFlags colorWriteMask) + : m_blendEnable (uint32_t(blendEnable)), + m_srcColorBlendFactor (uint32_t(srcColorBlendFactor)), + m_dstColorBlendFactor (uint32_t(dstColorBlendFactor)), + m_colorBlendOp (uint32_t(colorBlendOp)), + m_srcAlphaBlendFactor (uint32_t(srcAlphaBlendFactor)), + m_dstAlphaBlendFactor (uint32_t(dstAlphaBlendFactor)), + m_alphaBlendOp (uint32_t(alphaBlendOp)), + m_colorWriteMask (uint32_t(colorWriteMask)), + m_reserved (0) { } + + VkBool32 blendEnable() const { + return m_blendEnable; + } + + VkBlendFactor srcColorBlendFactor() const { + return VkBlendFactor(m_srcColorBlendFactor); + } + + VkBlendFactor dstColorBlendFactor() const { + return VkBlendFactor(m_dstColorBlendFactor); + } + + VkBlendOp colorBlendOp() const { + return VkBlendOp(m_colorBlendOp); + } + + VkBlendFactor srcAlphaBlendFactor() const { + return VkBlendFactor(m_srcAlphaBlendFactor); + } + + VkBlendFactor dstAlphaBlendFactor() const { + return VkBlendFactor(m_dstAlphaBlendFactor); + } + + VkBlendOp alphaBlendOp() const { + return VkBlendOp(m_alphaBlendOp); + } + + VkColorComponentFlags colorWriteMask() const { + return VkColorComponentFlags(m_colorWriteMask); + } + + VkPipelineColorBlendAttachmentState state() const { + VkPipelineColorBlendAttachmentState result; + result.blendEnable = VkBool32(m_blendEnable); + result.srcColorBlendFactor = VkBlendFactor(m_srcColorBlendFactor); + result.dstColorBlendFactor = VkBlendFactor(m_dstColorBlendFactor); + result.colorBlendOp = VkBlendOp(m_colorBlendOp); + result.srcAlphaBlendFactor = VkBlendFactor(m_srcAlphaBlendFactor); + result.dstAlphaBlendFactor = VkBlendFactor(m_dstAlphaBlendFactor); + result.alphaBlendOp = VkBlendOp(m_alphaBlendOp); + result.colorWriteMask = VkColorComponentFlags(m_colorWriteMask); + return result; + } + + private: + + uint32_t m_blendEnable : 1; + uint32_t m_srcColorBlendFactor : 5; + uint32_t m_dstColorBlendFactor : 5; + uint32_t m_colorBlendOp : 3; + uint32_t m_srcAlphaBlendFactor : 5; + uint32_t m_dstAlphaBlendFactor : 5; + uint32_t m_alphaBlendOp : 3; + uint32_t m_colorWriteMask : 4; + uint32_t m_reserved : 1; + + }; + + + /** + * \brief Packed attachment swizzle + * + * Stores the component mapping for one + * single color attachment in one byte. + */ + class DxvkOmAttachmentSwizzle { + + public: + + DxvkOmAttachmentSwizzle() = default; + + DxvkOmAttachmentSwizzle(VkComponentMapping mapping) + : m_r(util::getComponentIndex(mapping.r, 0)), + m_g(util::getComponentIndex(mapping.g, 1)), + m_b(util::getComponentIndex(mapping.b, 2)), + m_a(util::getComponentIndex(mapping.a, 3)) { } + + uint32_t rIndex() const { return m_r; } + uint32_t gIndex() const { return m_g; } + uint32_t bIndex() const { return m_b; } + uint32_t aIndex() const { return m_a; } + + VkComponentMapping mapping() const { + VkComponentMapping result; + result.r = decodeSwizzle(m_r); + result.g = decodeSwizzle(m_g); + result.b = decodeSwizzle(m_b); + result.a = decodeSwizzle(m_a); + return result; + } + + private: + + uint8_t m_r : 2; + uint8_t m_g : 2; + uint8_t m_b : 2; + uint8_t m_a : 2; + + static VkComponentSwizzle decodeSwizzle(uint8_t swizzle) { + return VkComponentSwizzle(uint32_t(swizzle) + uint32_t(VK_COMPONENT_SWIZZLE_R)); + } + + }; + + + /** + * \brief Specialization constant state + * + * Stores the raw 32-bit spec constant values. + */ + struct DxvkScInfo { + uint32_t specConstants[DxvkLimits::MaxNumSpecConstants]; + }; + + + /** + * \brief Packed graphics pipeline state + * + * Stores a compressed representation of the full + * graphics pipeline state which is optimized for + * lookup performance. + */ + struct alignas(32) DxvkGraphicsPipelineStateInfo { + DxvkGraphicsPipelineStateInfo() { + std::memset(this, 0, sizeof(*this)); + } + + DxvkGraphicsPipelineStateInfo(const DxvkGraphicsPipelineStateInfo& other) { + std::memcpy(this, &other, sizeof(*this)); + } + + DxvkGraphicsPipelineStateInfo& operator = (const DxvkGraphicsPipelineStateInfo& other) { + std::memcpy(this, &other, sizeof(*this)); + return *this; + } + + bool operator == (const DxvkGraphicsPipelineStateInfo& other) const { + return bit::bcmpeq(this, &other); + } + + bool operator != (const DxvkGraphicsPipelineStateInfo& other) const { + return !bit::bcmpeq(this, &other); + } + + bool useDynamicStencilRef() const { + return ds.enableStencilTest(); + } + + bool useDynamicDepthBias() const { + return rs.depthBiasEnable(); + } + + bool useDynamicDepthBounds() const { + return ds.enableDepthBoundsTest(); + } + + bool useDynamicBlendConstants() const { + bool result = false; + + for (uint32_t i = 0; i < MaxNumRenderTargets && !result; i++) { + result |= omBlend[i].blendEnable() + && (util::isBlendConstantBlendFactor(omBlend[i].srcColorBlendFactor()) + || util::isBlendConstantBlendFactor(omBlend[i].dstColorBlendFactor()) + || util::isBlendConstantBlendFactor(omBlend[i].srcAlphaBlendFactor()) + || util::isBlendConstantBlendFactor(omBlend[i].dstAlphaBlendFactor())); + } + + return result; + } + + DxvkBindingMask bsBindingMask; + DxvkIaInfo ia; + DxvkIlInfo il; + DxvkRsInfo rs; + DxvkMsInfo ms; + DxvkDsInfo ds; + DxvkOmInfo om; + DxvkScInfo sc; + DxvkDsStencilOp dsFront; + DxvkDsStencilOp dsBack; + DxvkOmAttachmentSwizzle omSwizzle [DxvkLimits::MaxNumRenderTargets]; + DxvkOmAttachmentBlend omBlend [DxvkLimits::MaxNumRenderTargets]; + DxvkIlAttribute ilAttributes [DxvkLimits::MaxNumVertexAttributes]; + DxvkIlBinding ilBindings [DxvkLimits::MaxNumVertexBindings]; + }; + + + /** + * \brief Compute pipeline state info + */ + struct alignas(32) DxvkComputePipelineStateInfo { + DxvkComputePipelineStateInfo() { + std::memset(this, 0, sizeof(*this)); + } + + DxvkComputePipelineStateInfo(const DxvkComputePipelineStateInfo& other) { + std::memcpy(this, &other, sizeof(*this)); + } + + DxvkComputePipelineStateInfo& operator = (const DxvkComputePipelineStateInfo& other) { + std::memcpy(this, &other, sizeof(*this)); + return *this; + } + + bool operator == (const DxvkComputePipelineStateInfo& other) const { + return bit::bcmpeq(this, &other); + } + + bool operator != (const DxvkComputePipelineStateInfo& other) const { + return !bit::bcmpeq(this, &other); + } + + DxvkBindingMask bsBindingMask; + DxvkScInfo sc; + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_hash.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_hash.h new file mode 100644 index 00000000000..a0fe561d74b --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_hash.h @@ -0,0 +1,41 @@ +#pragma once + +#include + +namespace dxvk { + + struct DxvkEq { + template + size_t operator () (const T& a, const T& b) const { + return a.eq(b); + } + }; + + struct DxvkHash { + template + size_t operator () (const T& object) const { + return object.hash(); + } + }; + + class DxvkHashState { + + public: + + void add(size_t hash) { + m_value ^= hash + 0x9e3779b9 + + (m_value << 6) + + (m_value >> 2); + } + + operator size_t () const { + return m_value; + } + + private: + + size_t m_value = 0; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_image.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_image.cpp new file mode 100644 index 00000000000..851bbc53a40 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_image.cpp @@ -0,0 +1,369 @@ +#include "dxvk_image.h" + +#include "dxvk_device.h" + +namespace dxvk { + + std::atomic DxvkImageView::s_cookie = { 0ull }; + + + DxvkImage::DxvkImage( + const DxvkDevice* device, + const DxvkImageCreateInfo& createInfo, + DxvkMemoryAllocator& memAlloc, + VkMemoryPropertyFlags memFlags) + : m_vkd(device->vkd()), m_device(device), m_info(createInfo), m_memFlags(memFlags) { + + // Copy the compatible view formats to a persistent array + m_viewFormats.resize(createInfo.viewFormatCount); + for (uint32_t i = 0; i < createInfo.viewFormatCount; i++) + m_viewFormats[i] = createInfo.viewFormats[i]; + m_info.viewFormats = m_viewFormats.data(); + + // If defined, we should provide a format list, which + // allows some drivers to enable image compression + VkImageFormatListCreateInfoKHR formatList; + formatList.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO_KHR; + formatList.pNext = nullptr; + formatList.viewFormatCount = createInfo.viewFormatCount; + formatList.pViewFormats = createInfo.viewFormats; + + VkImageCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + info.pNext = &formatList; + info.flags = createInfo.flags; + info.imageType = createInfo.type; + info.format = createInfo.format; + info.extent = createInfo.extent; + info.mipLevels = createInfo.mipLevels; + info.arrayLayers = createInfo.numLayers; + info.samples = createInfo.sampleCount; + info.tiling = createInfo.tiling; + info.usage = createInfo.usage; + info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + info.queueFamilyIndexCount = 0; + info.pQueueFamilyIndices = nullptr; + info.initialLayout = createInfo.initialLayout; + + m_shared = canShareImage(info, createInfo.sharing); + + VkExternalMemoryImageCreateInfo externalInfo; + if (m_shared) { + externalInfo.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO; + externalInfo.pNext = nullptr; + externalInfo.handleTypes = createInfo.sharing.type; + + formatList.pNext = &externalInfo; + } + + if (m_vkd->vkCreateImage(m_vkd->device(), + &info, nullptr, &m_image.image) != VK_SUCCESS) { + throw DxvkError(str::format( + "DxvkImage: Failed to create image:", + "\n Type: ", info.imageType, + "\n Format: ", info.format, + "\n Extent: ", "(", info.extent.width, + ",", info.extent.height, + ",", info.extent.depth, ")", + "\n Mip levels: ", info.mipLevels, + "\n Array layers: ", info.arrayLayers, + "\n Samples: ", info.samples, + "\n Usage: ", info.usage, + "\n Tiling: ", info.tiling)); + } + + // Get memory requirements for the image. We may enforce strict + // alignment on non-linear images in order not to violate the + // bufferImageGranularity limit, which may be greater than the + // required resource memory alignment on some GPUs. + VkMemoryDedicatedRequirements dedicatedRequirements; + dedicatedRequirements.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS; + dedicatedRequirements.pNext = VK_NULL_HANDLE; + dedicatedRequirements.prefersDedicatedAllocation = VK_FALSE; + dedicatedRequirements.requiresDedicatedAllocation = VK_FALSE; + + VkMemoryRequirements2 memReq; + memReq.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2; + memReq.pNext = &dedicatedRequirements; + + VkImageMemoryRequirementsInfo2 memReqInfo; + memReqInfo.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2; + memReqInfo.image = m_image.image; + memReqInfo.pNext = VK_NULL_HANDLE; + + VkMemoryDedicatedAllocateInfo dedMemoryAllocInfo; + dedMemoryAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO; + dedMemoryAllocInfo.pNext = VK_NULL_HANDLE; + dedMemoryAllocInfo.buffer = VK_NULL_HANDLE; + dedMemoryAllocInfo.image = m_image.image; + + VkExportMemoryAllocateInfo exportInfo; + if (m_shared && createInfo.sharing.mode == DxvkSharedHandleMode::Export) { + exportInfo.sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO; + exportInfo.pNext = nullptr; + exportInfo.handleTypes = createInfo.sharing.type; + + dedMemoryAllocInfo.pNext = &exportInfo; + } + +#ifdef _WIN32 + VkImportMemoryWin32HandleInfoKHR importInfo; + if (m_shared && createInfo.sharing.mode == DxvkSharedHandleMode::Import) { + importInfo.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR; + importInfo.pNext = nullptr; + importInfo.handleType = createInfo.sharing.type; + importInfo.handle = createInfo.sharing.handle; + importInfo.name = nullptr; + + dedMemoryAllocInfo.pNext = &importInfo; + } +#endif + + m_vkd->vkGetImageMemoryRequirements2( + m_vkd->device(), &memReqInfo, &memReq); + + if (info.tiling != VK_IMAGE_TILING_LINEAR && !dedicatedRequirements.prefersDedicatedAllocation) { + memReq.memoryRequirements.size = align(memReq.memoryRequirements.size, memAlloc.bufferImageGranularity()); + memReq.memoryRequirements.alignment = align(memReq.memoryRequirements.alignment , memAlloc.bufferImageGranularity()); + } + + // Use high memory priority for GPU-writable resources + bool isGpuWritable = (m_info.access & ( + VK_ACCESS_SHADER_WRITE_BIT | + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT)) != 0; + + DxvkMemoryFlags hints(DxvkMemoryFlag::GpuReadable); + + if (isGpuWritable) + hints.set(DxvkMemoryFlag::GpuWritable); + + if (m_shared) { + dedicatedRequirements.prefersDedicatedAllocation = VK_TRUE; + dedicatedRequirements.requiresDedicatedAllocation = VK_TRUE; + } + + // Ask driver whether we should be using a dedicated allocation + m_image.memory = memAlloc.alloc(&memReq.memoryRequirements, + dedicatedRequirements, dedMemoryAllocInfo, memFlags, hints); + + // Try to bind the allocated memory slice to the image + if (m_vkd->vkBindImageMemory(m_vkd->device(), m_image.image, + m_image.memory.memory(), m_image.memory.offset()) != VK_SUCCESS) + throw DxvkError("DxvkImage::DxvkImage: Failed to bind device memory"); + } + + + DxvkImage::DxvkImage( + const DxvkDevice* device, + const DxvkImageCreateInfo& info, + VkImage image) + : m_vkd(device->vkd()), m_device(device), m_info(info), m_image({ image }) { + + m_viewFormats.resize(info.viewFormatCount); + for (uint32_t i = 0; i < info.viewFormatCount; i++) + m_viewFormats[i] = info.viewFormats[i]; + m_info.viewFormats = m_viewFormats.data(); + } + + + DxvkImage::~DxvkImage() { + // This is a bit of a hack to determine whether + // the image is implementation-handled or not + if (m_image.memory.memory() != VK_NULL_HANDLE) + m_vkd->vkDestroyImage(m_vkd->device(), m_image.image, nullptr); + } + + + bool DxvkImage::canShareImage(const VkImageCreateInfo& createInfo, const DxvkSharedHandleInfo& sharingInfo) const { + if (sharingInfo.mode == DxvkSharedHandleMode::None) + return false; + + if (!m_device->extensions().khrExternalMemoryWin32) { + Logger::err("Failed to create shared resource: VK_KHR_EXTERNAL_MEMORY_WIN32 not supported"); + return false; + } + + VkPhysicalDeviceExternalImageFormatInfo externalImageFormatInfo; + externalImageFormatInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO; + externalImageFormatInfo.pNext = VK_NULL_HANDLE; + externalImageFormatInfo.handleType = sharingInfo.type; + + VkPhysicalDeviceImageFormatInfo2 imageFormatInfo; + imageFormatInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2; + imageFormatInfo.pNext = &externalImageFormatInfo; + imageFormatInfo.format = createInfo.format; + imageFormatInfo.type = createInfo.imageType; + imageFormatInfo.tiling = createInfo.tiling; + imageFormatInfo.usage = createInfo.usage; + imageFormatInfo.flags = createInfo.flags; + + VkExternalImageFormatProperties externalImageFormatProperties; + externalImageFormatProperties.sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES; + externalImageFormatProperties.pNext = nullptr; + externalImageFormatProperties.externalMemoryProperties = {}; + + VkImageFormatProperties2 imageFormatProperties; + imageFormatProperties.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2; + imageFormatProperties.pNext = &externalImageFormatProperties; + imageFormatProperties.imageFormatProperties = {}; + + VkResult vr = m_device->adapter()->vki()->vkGetPhysicalDeviceImageFormatProperties2( + m_device->adapter()->handle(), &imageFormatInfo, &imageFormatProperties); + + if (vr != VK_SUCCESS) { + Logger::err(str::format("Failed to create shared resource: getImageProperties failed:", vr)); + return false; + } + + if (sharingInfo.mode == DxvkSharedHandleMode::Export) { + bool ret = externalImageFormatProperties.externalMemoryProperties.externalMemoryFeatures & VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT; + if (!ret) + Logger::err("Failed to create shared resource: image cannot be exported"); + return ret; + } + + if (sharingInfo.mode == DxvkSharedHandleMode::Import) { + bool ret = externalImageFormatProperties.externalMemoryProperties.externalMemoryFeatures & VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT; + if (!ret) + Logger::err("Failed to create shared resource: image cannot be imported"); + return ret; + } + + return false; + } + + + HANDLE DxvkImage::sharedHandle() const { + HANDLE handle = INVALID_HANDLE_VALUE; + + if (!m_shared) + return INVALID_HANDLE_VALUE; + +#ifdef _WIN32 + VkMemoryGetWin32HandleInfoKHR handleInfo; + handleInfo.sType = VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR; + handleInfo.pNext = nullptr; + handleInfo.handleType = m_info.sharing.type; + handleInfo.memory = m_image.memory.memory(); + if (m_vkd->vkGetMemoryWin32HandleKHR(m_vkd->device(), &handleInfo, &handle) != VK_SUCCESS) + Logger::warn("DxvkImage::DxvkImage: Failed to get shared handle for image"); +#endif + + return handle; + } + + + DxvkImageView::DxvkImageView( + const Rc& vkd, + const Rc& image, + const DxvkImageViewCreateInfo& info) + : m_vkd(vkd), m_image(image), m_info(info), m_cookie(++s_cookie) { + for (uint32_t i = 0; i < ViewCount; i++) + m_views[i] = VK_NULL_HANDLE; + + switch (m_info.type) { + case VK_IMAGE_VIEW_TYPE_1D: + case VK_IMAGE_VIEW_TYPE_1D_ARRAY: { + this->createView(VK_IMAGE_VIEW_TYPE_1D, 1); + this->createView(VK_IMAGE_VIEW_TYPE_1D_ARRAY, m_info.numLayers); + } break; + + case VK_IMAGE_VIEW_TYPE_2D: + case VK_IMAGE_VIEW_TYPE_2D_ARRAY: + this->createView(VK_IMAGE_VIEW_TYPE_2D, 1); + [[fallthrough]]; + + case VK_IMAGE_VIEW_TYPE_CUBE: + case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: { + this->createView(VK_IMAGE_VIEW_TYPE_2D_ARRAY, m_info.numLayers); + + if (m_image->info().flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) { + uint32_t cubeCount = m_info.numLayers / 6; + + if (cubeCount > 0) { + this->createView(VK_IMAGE_VIEW_TYPE_CUBE, 6); + this->createView(VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, 6 * cubeCount); + } + } + } break; + + case VK_IMAGE_VIEW_TYPE_3D: { + this->createView(VK_IMAGE_VIEW_TYPE_3D, 1); + + if (m_image->info().flags & VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT && m_info.numLevels == 1) { + this->createView(VK_IMAGE_VIEW_TYPE_2D, 1); + this->createView(VK_IMAGE_VIEW_TYPE_2D_ARRAY, m_image->mipLevelExtent(m_info.minLevel).depth); + } + } break; + + default: + throw DxvkError(str::format("DxvkImageView: Invalid view type: ", m_info.type)); + } + } + + + DxvkImageView::~DxvkImageView() { + for (uint32_t i = 0; i < ViewCount; i++) + m_vkd->vkDestroyImageView(m_vkd->device(), m_views[i], nullptr); + } + + + void DxvkImageView::createView(VkImageViewType type, uint32_t numLayers) { + VkImageSubresourceRange subresourceRange; + subresourceRange.aspectMask = m_info.aspect; + subresourceRange.baseMipLevel = m_info.minLevel; + subresourceRange.levelCount = m_info.numLevels; + subresourceRange.baseArrayLayer = m_info.minLayer; + subresourceRange.layerCount = numLayers; + + VkImageViewUsageCreateInfo viewUsage; + viewUsage.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO; + viewUsage.pNext = nullptr; + viewUsage.usage = m_info.usage; + + VkImageViewCreateInfo viewInfo; + viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + viewInfo.pNext = &viewUsage; + viewInfo.flags = 0; + viewInfo.image = m_image->handle(); + viewInfo.viewType = type; + viewInfo.format = m_info.format; + viewInfo.components = m_info.swizzle; + viewInfo.subresourceRange = subresourceRange; + + if (m_info.usage == VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) { + viewInfo.components = { + VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, + VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY }; + } + + if (m_vkd->vkCreateImageView(m_vkd->device(), + &viewInfo, nullptr, &m_views[type]) != VK_SUCCESS) { + throw DxvkError(str::format( + "DxvkImageView: Failed to create image view:" + "\n View type: ", viewInfo.viewType, + "\n View format: ", viewInfo.format, + "\n Subresources: ", + "\n Aspect mask: ", std::hex, viewInfo.subresourceRange.aspectMask, + "\n Mip levels: ", viewInfo.subresourceRange.baseMipLevel, " - ", + viewInfo.subresourceRange.levelCount, + "\n Array layers: ", viewInfo.subresourceRange.baseArrayLayer, " - ", + viewInfo.subresourceRange.layerCount, + "\n Image properties:", + "\n Type: ", m_image->info().type, + "\n Format: ", m_image->info().format, + "\n Extent: ", "(", m_image->info().extent.width, + ",", m_image->info().extent.height, + ",", m_image->info().extent.depth, ")", + "\n Mip levels: ", m_image->info().mipLevels, + "\n Array layers: ", m_image->info().numLayers, + "\n Samples: ", m_image->info().sampleCount, + "\n Usage: ", std::hex, m_image->info().usage, + "\n Tiling: ", m_image->info().tiling)); + } + } + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_image.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_image.h new file mode 100644 index 00000000000..b3b8a58e777 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_image.h @@ -0,0 +1,571 @@ +#pragma once + +#include "dxvk_descriptor.h" +#include "dxvk_format.h" +#include "dxvk_memory.h" +#include "dxvk_resource.h" +#include "dxvk_util.h" + +namespace dxvk { + + class DxvkImageView; + + /** + * \brief Image create info + * + * The properties of an image that are + * passed to \ref DxvkDevice::createImage + */ + struct DxvkImageCreateInfo { + /// Image dimension + VkImageType type; + + /// Pixel format + VkFormat format; + + /// Flags + VkImageCreateFlags flags; + + /// Sample count for MSAA + VkSampleCountFlagBits sampleCount; + + /// Image size, in texels + VkExtent3D extent; + + /// Number of image array layers + uint32_t numLayers; + + /// Number of mip levels + uint32_t mipLevels; + + /// Image usage flags + VkImageUsageFlags usage; + + /// Pipeline stages that can access + /// the contents of the image + VkPipelineStageFlags stages; + + /// Allowed access pattern + VkAccessFlags access; + + /// Image tiling mode + VkImageTiling tiling; + + /// Common image layout + VkImageLayout layout; + + // Initial image layout + VkImageLayout initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + // Image is used by multiple contexts so it needs + // to be in its default layout after each submission + VkBool32 shared = VK_FALSE; + + // Image view formats that can + // be used with this image + uint32_t viewFormatCount = 0; + const VkFormat* viewFormats = nullptr; + + // Shared handle info + DxvkSharedHandleInfo sharing; + }; + + + /** + * \brief Image create info + * + * The properties of an image view that are + * passed to \ref DxvkDevice::createImageView + */ + struct DxvkImageViewCreateInfo { + /// Image view dimension + VkImageViewType type = VK_IMAGE_VIEW_TYPE_2D; + + /// Pixel format + VkFormat format = VK_FORMAT_UNDEFINED; + + /// Image view usage flags + VkImageUsageFlags usage = 0; + + /// Subresources to use in the view + VkImageAspectFlags aspect = 0; + + uint32_t minLevel = 0; + uint32_t numLevels = 0; + uint32_t minLayer = 0; + uint32_t numLayers = 0; + + /// Component mapping. Defaults to identity. + VkComponentMapping swizzle = { + VK_COMPONENT_SWIZZLE_IDENTITY, + VK_COMPONENT_SWIZZLE_IDENTITY, + VK_COMPONENT_SWIZZLE_IDENTITY, + VK_COMPONENT_SWIZZLE_IDENTITY, + }; + }; + + + /** + * \brief Stores an image and its memory slice. + */ + struct DxvkPhysicalImage { + VkImage image = VK_NULL_HANDLE; + DxvkMemory memory; + }; + + + /** + * \brief DXVK image + * + * An image resource consisting of various subresources. + * Can be accessed by the host if allocated on a suitable + * memory type and if created with the linear tiling option. + */ + class DxvkImage : public DxvkResource { + friend class DxvkContext; + friend class DxvkImageView; + public: + + DxvkImage( + const DxvkDevice* device, + const DxvkImageCreateInfo& createInfo, + DxvkMemoryAllocator& memAlloc, + VkMemoryPropertyFlags memFlags); + + /** + * \brief Creates image object from existing image + * + * This can be used to create an image object for + * an implementation-managed image. Make sure to + * provide the correct image properties, since + * otherwise some image operations may fail. + */ + DxvkImage( + const DxvkDevice* device, + const DxvkImageCreateInfo& info, + VkImage image); + + /** + * \brief Destroys image + * + * If this is an implementation-managed image, + * this will not destroy the Vulkan image. + */ + ~DxvkImage(); + + /** + * \brief Image handle + * + * Internal use only. + * \returns Image handle + */ + VkImage handle() const { + return m_image.image; + } + + /** + * \brief Image properties + * + * The image create info structure. + * \returns Image properties + */ + const DxvkImageCreateInfo& info() const { + return m_info; + } + + /** + * \brief Memory type flags + * + * Use this to determine whether a + * buffer is mapped to host memory. + * \returns Vulkan memory flags + */ + VkMemoryPropertyFlags memFlags() const { + return m_memFlags; + } + + /** + * \brief Map pointer + * + * If the image has been created on a host-visible + * memory type, its memory is mapped and can be + * accessed by the host. + * \param [in] offset Byte offset into mapped region + * \returns Pointer to mapped memory region + */ + void* mapPtr(VkDeviceSize offset) const { + return m_image.memory.mapPtr(offset); + } + + /** + * \brief Image format info + * \returns Image format info + */ + const DxvkFormatInfo* formatInfo() const { + return imageFormatInfo(m_info.format); + } + + /** + * \brief Size of a mipmap level + * + * \param [in] level Mip level + * \returns Size of that level + */ + VkExtent3D mipLevelExtent(uint32_t level) const { + return util::computeMipLevelExtent(m_info.extent, level); + } + + /** + * \brief Size of a mipmap level + * + * \param [in] level Mip level + * \returns Size of that level + */ + VkExtent3D mipLevelExtent(uint32_t level, VkImageAspectFlags aspect) const { + return util::computeMipLevelExtent(m_info.extent, level, m_info.format, aspect); + } + + /** + * \brief Queries memory layout of a subresource + * + * Can be used to retrieve the exact pointer to a + * subresource of a mapped image with linear tiling. + * \param [in] subresource The image subresource + * \returns Memory layout of that subresource + */ + VkSubresourceLayout querySubresourceLayout( + const VkImageSubresource& subresource) const { + VkSubresourceLayout result; + m_vkd->vkGetImageSubresourceLayout( + m_vkd->device(), m_image.image, + &subresource, &result); + return result; + } + + /** + * \brief Picks a compatible layout + * + * Under some circumstances, we have to return + * a different layout than the one requested. + * \param [in] layout The image layout + * \returns A compatible image layout + */ + VkImageLayout pickLayout(VkImageLayout layout) const { + return m_info.layout == VK_IMAGE_LAYOUT_GENERAL + ? VK_IMAGE_LAYOUT_GENERAL : layout; + } + + /** + * \brief Changes image layout + * \param [in] layout New layout + */ + void setLayout(VkImageLayout layout) { + m_info.layout = layout; + } + + /** + * \brief Checks whether a subresource is entirely covered + * + * This can be used to determine whether an image can or + * should be initialized with \c VK_IMAGE_LAYOUT_UNDEFINED. + * \param [in] subresource The image subresource + * \param [in] extent Image extent to check + */ + bool isFullSubresource( + const VkImageSubresourceLayers& subresource, + VkExtent3D extent) const { + return subresource.aspectMask == this->formatInfo()->aspectMask + && extent == this->mipLevelExtent(subresource.mipLevel); + } + + /** + * \brief Checks view format compatibility + * + * If this returns true, a view with the given + * format can be safely created for this image. + * \param [in] format The format to check + * \returns \c true if the format is vompatible + */ + bool isViewCompatible(VkFormat format) const { + bool result = m_info.format == format; + for (uint32_t i = 0; i < m_viewFormats.size() && !result; i++) + result |= m_viewFormats[i] == format; + return result; + } + + /** + * \brief Memory size + * + * \returns The memory size of the image + */ + VkDeviceSize memSize() const { + return m_image.memory.length(); + } + + /** + * \brief Get full subresource range of the image + * + * \returns Resource range of the whole image + */ + VkImageSubresourceRange getAvailableSubresources() const { + VkImageSubresourceRange result; + result.aspectMask = formatInfo()->aspectMask; + result.baseMipLevel = 0; + result.levelCount = info().mipLevels; + result.baseArrayLayer = 0; + result.layerCount = info().numLayers; + return result; + } + + /** + * \brief Create a new shared handle to dedicated memory backing the image + * \returns The shared handle with the type given by DxvkSharedHandleInfo::type + */ + HANDLE sharedHandle() const; + + private: + + Rc m_vkd; + const DxvkDevice* m_device; + DxvkImageCreateInfo m_info; + VkMemoryPropertyFlags m_memFlags; + DxvkPhysicalImage m_image; + bool m_shared = false; + + small_vector m_viewFormats; + + bool canShareImage(const VkImageCreateInfo& createInfo, const DxvkSharedHandleInfo& sharingInfo) const; + + }; + + + /** + * \brief DXVK image view + */ + class DxvkImageView : public DxvkResource { + friend class DxvkImage; + constexpr static uint32_t ViewCount = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY + 1; + public: + + DxvkImageView( + const Rc& vkd, + const Rc& image, + const DxvkImageViewCreateInfo& info); + + ~DxvkImageView(); + + /** + * \brief Image view handle for the default type + * + * The default view type is guaranteed to be + * supported by the image view, and should be + * preferred over picking a different type. + * \returns Image view handle + */ + VkImageView handle() const { + return handle(m_info.type); + } + + /** + * \brief Image view handle for a given view type + * + * If the view does not support the requested image + * view type, \c VK_NULL_HANDLE will be returned. + * \param [in] viewType The requested view type + * \returns The image view handle + */ + VkImageView handle(VkImageViewType viewType) const { + if (unlikely(viewType == VK_IMAGE_VIEW_TYPE_MAX_ENUM)) + viewType = m_info.type; + return m_views[viewType]; + } + + /** + * \brief Image view type + * + * Convenience method to query the view type + * in order to check for resource compatibility. + * \returns Image view type + */ + VkImageViewType type() const { + return m_info.type; + } + + /** + * \brief Image view properties + * \returns Image view properties + */ + const DxvkImageViewCreateInfo& info() const { + return m_info; + } + + /** + * \brief Image handle + * \returns Image handle + */ + VkImage imageHandle() const { + return m_image->handle(); + } + + /** + * \brief Image properties + * \returns Image properties + */ + const DxvkImageCreateInfo& imageInfo() const { + return m_image->info(); + } + + /** + * \brief Image object + * \returns Image object + */ + const Rc& image() const { + return m_image; + } + + /** + * \brief View format info + * \returns View format info + */ + const DxvkFormatInfo* formatInfo() const { + return imageFormatInfo(m_info.format); + } + + /** + * \brief Unique object identifier + * + * Can be used to identify an object even when + * the lifetime of the object is unknown, and + * without referencing the actual object. + * \returns Unique identifier + */ + uint64_t cookie() const { + return m_cookie; + } + + /** + * \brief Mip level size + * + * Computes the mip level size relative to + * the first mip level that the view includes. + * \param [in] level Mip level + * \returns Size of that level + */ + VkExtent3D mipLevelExtent(uint32_t level) const { + return m_image->mipLevelExtent(level + m_info.minLevel, m_info.aspect); + } + + /** + * \brief View subresource range + * + * Returns the subresource range from the image + * description. For 2D views of 3D images, this + * will return the viewed 3D slices. + * \returns View subresource range + */ + VkImageSubresourceRange subresources() const { + VkImageSubresourceRange result; + result.aspectMask = m_info.aspect; + result.baseMipLevel = m_info.minLevel; + result.levelCount = m_info.numLevels; + result.baseArrayLayer = m_info.minLayer; + result.layerCount = m_info.numLayers; + return result; + } + + /** + * \brief Actual image subresource range + * + * Handles 3D images correctly in that it only + * returns one single array layer. Use this for + * barriers. + * \returns Image subresource range + */ + VkImageSubresourceRange imageSubresources() const { + VkImageSubresourceRange result; + result.aspectMask = m_info.aspect; + result.baseMipLevel = m_info.minLevel; + result.levelCount = m_info.numLevels; + if (likely(m_image->info().type != VK_IMAGE_TYPE_3D)) { + result.baseArrayLayer = m_info.minLayer; + result.layerCount = m_info.numLayers; + } else { + result.baseArrayLayer = 0; + result.layerCount = 1; + } + return result; + } + + /** + * \brief Picks an image layout + * \see DxvkImage::pickLayout + */ + VkImageLayout pickLayout(VkImageLayout layout) const { + return m_image->pickLayout(layout); + } + + /** + * \brief Retrieves descriptor info + * + * \param [in] type Exact view type + * \param [in] layout Image layout + * \returns Image descriptor + */ + DxvkDescriptorInfo getDescriptor(VkImageViewType type, VkImageLayout layout) const { + DxvkDescriptorInfo result; + result.image.sampler = VK_NULL_HANDLE; + result.image.imageView = handle(type); + result.image.imageLayout = layout; + return result; + } + + /** + * \brief Checks whether this view matches another + * + * \param [in] view The other view to check + * \returns \c true if the two views have the same subresources + */ + bool matchesView(const Rc& view) const { + if (this == view.ptr()) + return true; + + return this->image() == view->image() + && this->subresources() == view->subresources() + && this->info().type == view->info().type + && this->info().format == view->info().format; + } + + /** + * \brief Checks whether this view overlaps with another one + * + * Two views overlap if they were created for the same + * image and have at least one subresource in common. + * \param [in] view The other view to check + * \returns \c true if the two views overlap + */ + bool checkSubresourceOverlap(const Rc& view) const { + if (likely(m_image != view->m_image)) + return false; + + return vk::checkSubresourceRangeOverlap( + this->imageSubresources(), + view->imageSubresources()); + } + + private: + + Rc m_vkd; + Rc m_image; + + DxvkImageViewCreateInfo m_info; + VkImageView m_views[ViewCount]; + + uint64_t m_cookie; + + static std::atomic s_cookie; + + void createView(VkImageViewType type, uint32_t numLayers); + + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_include.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_include.h new file mode 100644 index 00000000000..3803afb5800 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_include.h @@ -0,0 +1,25 @@ +#pragma once + +#include "../util/log/log.h" +#include "../util/log/log_debug.h" + +#include "../util/util_env.h" +#include "../util/util_error.h" +#include "../util/util_flags.h" +#include "../util/util_likely.h" +#include "../util/util_math.h" +#include "../util/util_small_vector.h" +#include "../util/util_string.h" + +#include "../util/rc/util_rc.h" +#include "../util/rc/util_rc_ptr.h" + +#include "../util/sha1/sha1_util.h" + +#include "../util/sync/sync_signal.h" +#include "../util/sync/sync_spinlock.h" +#include "../util/sync/sync_ticketlock.h" + +#include "../vulkan/vulkan_loader.h" +#include "../vulkan/vulkan_names.h" +#include "../vulkan/vulkan_util.h" diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_instance.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_instance.cpp new file mode 100644 index 00000000000..8318a95e9cc --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_instance.cpp @@ -0,0 +1,214 @@ +#include + +#include "dxvk_instance.h" +#include "dxvk_openvr.h" +#include "dxvk_openxr.h" +#include "dxvk_platform_exts.h" + +#include + +namespace dxvk { + + DxvkInstance::DxvkInstance() { + Logger::info(str::format("Game: ", env::getExeName())); + Logger::info(str::format("DXVK: ", DXVK_VERSION)); + + m_config = Config::getUserConfig(); + m_config.merge(Config::getAppConfig(env::getExePath())); + m_config.logOptions(); + + m_options = DxvkOptions(m_config); + + m_extProviders.push_back(&DxvkPlatformExts::s_instance); + m_extProviders.push_back(&VrInstance::s_instance); + m_extProviders.push_back(&DxvkXrProvider::s_instance); + + Logger::info("Built-in extension providers:"); + for (const auto& provider : m_extProviders) + Logger::info(str::format(" ", provider->getName())); + + for (const auto& provider : m_extProviders) + provider->initInstanceExtensions(); + + m_vkl = new vk::LibraryFn(); + m_vki = new vk::InstanceFn(true, this->createInstance()); + + m_adapters = this->queryAdapters(); + + for (const auto& provider : m_extProviders) + provider->initDeviceExtensions(this); + + for (uint32_t i = 0; i < m_adapters.size(); i++) { + for (const auto& provider : m_extProviders) { + m_adapters[i]->enableExtensions( + provider->getDeviceExtensions(i)); + } + } + } + + + DxvkInstance::~DxvkInstance() { + + } + + + Rc DxvkInstance::enumAdapters(uint32_t index) const { + return index < m_adapters.size() + ? m_adapters[index] + : nullptr; + } + + + Rc DxvkInstance::findAdapterByLuid(const void* luid) const { + for (const auto& adapter : m_adapters) { + const auto& props = adapter->devicePropertiesExt().coreDeviceId; + + if (props.deviceLUIDValid && !std::memcmp(luid, props.deviceLUID, VK_LUID_SIZE)) + return adapter; + } + + return nullptr; + } + + + Rc DxvkInstance::findAdapterByDeviceId(uint16_t vendorId, uint16_t deviceId) const { + for (const auto& adapter : m_adapters) { + const auto& props = adapter->deviceProperties(); + + if (props.vendorID == vendorId + && props.deviceID == deviceId) + return adapter; + } + + return nullptr; + } + + + VkInstance DxvkInstance::createInstance() { + DxvkInstanceExtensions insExtensions; + + std::vector insExtensionList = {{ + &insExtensions.khrGetSurfaceCapabilities2, + &insExtensions.khrSurface, + }}; + + // Hide VK_EXT_debug_utils behind an environment variable. This extension + // adds additional overhead to winevulkan + if ((env::getEnvVar("DXVK_PERF_EVENTS") == "1") || + (m_options.enableDebugUtils)) { + insExtensionList.push_back(&insExtensions.extDebugUtils); + Logger::warn("DXVK: Debug Utils are enabled, perf events are ON. May affect performance!"); + } + + DxvkNameSet extensionsEnabled; + DxvkNameSet extensionsAvailable = DxvkNameSet::enumInstanceExtensions(m_vkl); + + if (!extensionsAvailable.enableExtensions( + insExtensionList.size(), + insExtensionList.data(), + extensionsEnabled)) + throw DxvkError("DxvkInstance: Failed to create instance"); + + m_extensions = insExtensions; + + // Enable additional extensions if necessary + for (const auto& provider : m_extProviders) + extensionsEnabled.merge(provider->getInstanceExtensions()); + + DxvkNameList extensionNameList = extensionsEnabled.toNameList(); + + Logger::info("Enabled instance extensions:"); + this->logNameList(extensionNameList); + + std::string appName = env::getExeName(); + + VkApplicationInfo appInfo; + appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + appInfo.pNext = nullptr; + appInfo.pApplicationName = appName.c_str(); + appInfo.applicationVersion = 0; + appInfo.pEngineName = "DXVK"; + appInfo.engineVersion = VK_MAKE_VERSION(1, 10, 3); + appInfo.apiVersion = VK_MAKE_VERSION(1, 1, 0); + + VkInstanceCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.pApplicationInfo = &appInfo; + info.enabledLayerCount = 0; + info.ppEnabledLayerNames = nullptr; + info.enabledExtensionCount = extensionNameList.count(); + info.ppEnabledExtensionNames = extensionNameList.names(); + + VkInstance result = VK_NULL_HANDLE; + VkResult status = m_vkl->vkCreateInstance(&info, nullptr, &result); + + if (status != VK_SUCCESS) + throw DxvkError("DxvkInstance::createInstance: Failed to create Vulkan 1.1 instance"); + + return result; + } + + + std::vector> DxvkInstance::queryAdapters() { + uint32_t numAdapters = 0; + if (m_vki->vkEnumeratePhysicalDevices(m_vki->instance(), &numAdapters, nullptr) != VK_SUCCESS) + throw DxvkError("DxvkInstance::enumAdapters: Failed to enumerate adapters"); + + std::vector adapters(numAdapters); + if (m_vki->vkEnumeratePhysicalDevices(m_vki->instance(), &numAdapters, adapters.data()) != VK_SUCCESS) + throw DxvkError("DxvkInstance::enumAdapters: Failed to enumerate adapters"); + + std::vector deviceProperties(numAdapters); + DxvkDeviceFilterFlags filterFlags = 0; + + for (uint32_t i = 0; i < numAdapters; i++) { + m_vki->vkGetPhysicalDeviceProperties(adapters[i], &deviceProperties[i]); + + if (deviceProperties[i].deviceType != VK_PHYSICAL_DEVICE_TYPE_CPU) + filterFlags.set(DxvkDeviceFilterFlag::SkipCpuDevices); + } + + DxvkDeviceFilter filter(filterFlags); + std::vector> result; + + for (uint32_t i = 0; i < numAdapters; i++) { + if (filter.testAdapter(deviceProperties[i])) + result.push_back(new DxvkAdapter(m_vki, adapters[i])); + } + + std::stable_sort(result.begin(), result.end(), + [] (const Rc& a, const Rc& b) -> bool { + static const std::array deviceTypes = {{ + VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, + VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU, + VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU, + }}; + + uint32_t aRank = deviceTypes.size(); + uint32_t bRank = deviceTypes.size(); + + for (uint32_t i = 0; i < std::min(aRank, bRank); i++) { + if (a->deviceProperties().deviceType == deviceTypes[i]) aRank = i; + if (b->deviceProperties().deviceType == deviceTypes[i]) bRank = i; + } + + return aRank < bRank; + }); + + if (result.size() == 0) { + Logger::warn("DXVK: No adapters found. Please check your " + "device filter settings and Vulkan setup."); + } + + return result; + } + + + void DxvkInstance::logNameList(const DxvkNameList& names) { + for (uint32_t i = 0; i < names.count(); i++) + Logger::info(str::format(" ", names.name(i))); + } + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_instance.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_instance.h new file mode 100644 index 00000000000..f945ed6d2d1 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_instance.h @@ -0,0 +1,129 @@ +#pragma once + +#include "../util/config/config.h" + +#include "dxvk_adapter.h" +#include "dxvk_device_filter.h" +#include "dxvk_extension_provider.h" +#include "dxvk_options.h" + +namespace dxvk { + + /** + * \brief DXVK instance + * + * Manages a Vulkan instance and stores a list + * of adapters. This also provides methods for + * device creation. + */ + class DxvkInstance : public RcObject { + + public: + + DxvkInstance(); + ~DxvkInstance(); + + /** + * \brief Vulkan instance functions + * \returns Vulkan instance functions + */ + Rc vki() const { + return m_vki; + } + + /** + * \brief Vulkan instance handle + * \returns The instance handle + */ + VkInstance handle() { + return m_vki->instance(); + } + + /** + * \brief Number of adapters + * + * \returns The number of adapters + */ + size_t adapterCount() { + return m_adapters.size(); + } + + /** + * \brief Retrieves an adapter + * + * Note that the adapter does not hold + * a hard reference to the instance. + * \param [in] index Adapter index + * \returns The adapter, or \c nullptr. + */ + Rc enumAdapters( + uint32_t index) const; + + /** + * \brief Finds adapter by LUID + * + * \param [in] luid Pointer to LUID + * \returns Matching adapter, if any + */ + Rc findAdapterByLuid( + const void* luid) const; + + /** + * \brief Finds adapter by device IDs + * + * \param [in] vendorId Vendor ID + * \param [in] deviceId Device ID + * \returns Matching adapter, if any + */ + Rc findAdapterByDeviceId( + uint16_t vendorId, + uint16_t deviceId) const; + + /** + * \brief Retrieves configuration options + * + * The configuration set contains user-defined + * options as well as app-specific options. + * \returns Configuration options + */ + const Config& config() const { + return m_config; + } + + /** + * \brief DXVK options + * \returns DXVK options + */ + const DxvkOptions& options() const { + return m_options; + } + + /** + * \brief Enabled instance extensions + * \returns Enabled instance extensions + */ + const DxvkInstanceExtensions& extensions() const { + return m_extensions; + } + + private: + + Config m_config; + DxvkOptions m_options; + + Rc m_vkl; + Rc m_vki; + DxvkInstanceExtensions m_extensions; + + std::vector m_extProviders; + std::vector> m_adapters; + + VkInstance createInstance(); + + std::vector> queryAdapters(); + + static void logNameList(const DxvkNameList& names); + + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_lifetime.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_lifetime.cpp new file mode 100644 index 00000000000..e9439c55d5f --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_lifetime.cpp @@ -0,0 +1,26 @@ +#include "dxvk_lifetime.h" + +namespace dxvk { + + DxvkLifetimeTracker:: DxvkLifetimeTracker() { } + DxvkLifetimeTracker::~DxvkLifetimeTracker() { } + + + void DxvkLifetimeTracker::notify() { + for (const auto& resource : m_resources) + resource.first->release(resource.second); + + m_notified = true; + } + + + void DxvkLifetimeTracker::reset() { + // If this gets called without ever being submitted then + // we should at least report the resources as unused + if (!m_notified) + this->notify(); + + m_resources.clear(); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_lifetime.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_lifetime.h new file mode 100644 index 00000000000..fb80d05f657 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_lifetime.h @@ -0,0 +1,56 @@ +#pragma once + +#include + +#include "dxvk_resource.h" + +namespace dxvk { + + /** + * \brief DXVK lifetime tracker + * + * Maintains references to a set of resources. This is + * used to guarantee that resources are not destroyed + * or otherwise accessed in an unsafe manner until the + * device has finished using them. + */ + class DxvkLifetimeTracker { + + public: + + DxvkLifetimeTracker(); + ~DxvkLifetimeTracker(); + + /** + * \brief Adds a resource to track + * \param [in] rc The resource to track + */ + template + void trackResource(Rc&& rc) { + rc->acquire(Access); + m_resources.emplace_back(std::move(rc), Access); + } + + /** + * \brief Releases resources + * + * Marks all tracked resources as unused. + */ + void notify(); + + /** + * \brief Resets the command list + * + * Called automatically by the device when + * the command list has completed execution. + */ + void reset(); + + private: + + std::vector, DxvkAccess>> m_resources; + bool m_notified = false; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_limits.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_limits.h new file mode 100644 index 00000000000..eb2431e68ec --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_limits.h @@ -0,0 +1,24 @@ +#pragma once + +#include "dxvk_include.h" + +namespace dxvk { + + enum DxvkLimits : size_t { + MaxNumRenderTargets = 8, + MaxNumVertexAttributes = 32, + MaxNumVertexBindings = 32, + MaxNumXfbBuffers = 4, + MaxNumXfbStreams = 4, + MaxNumViewports = 16, + MaxNumResourceSlots = 1216, + MaxNumActiveBindings = 384, + MaxNumQueuedCommandBuffers = 18, + MaxNumQueryCountPerPool = 128, + MaxNumSpecConstants = 12, + MaxUniformBufferSize = 65536, + MaxVertexBindingStride = 2048, + MaxPushConstantSize = 128, + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_memory.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_memory.cpp new file mode 100644 index 00000000000..a33772c709a --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_memory.cpp @@ -0,0 +1,566 @@ +#include + +#include "dxvk_device.h" +#include "dxvk_memory.h" + +namespace dxvk { + + DxvkMemory::DxvkMemory() { } + DxvkMemory::DxvkMemory( + DxvkMemoryAllocator* alloc, + DxvkMemoryChunk* chunk, + DxvkMemoryType* type, + VkDeviceMemory memory, + VkDeviceSize offset, + VkDeviceSize length, + void* mapPtr) + : m_alloc (alloc), + m_chunk (chunk), + m_type (type), + m_memory (memory), + m_offset (offset), + m_length (length), + m_mapPtr (mapPtr) { } + + + DxvkMemory::DxvkMemory(DxvkMemory&& other) + : m_alloc (std::exchange(other.m_alloc, nullptr)), + m_chunk (std::exchange(other.m_chunk, nullptr)), + m_type (std::exchange(other.m_type, nullptr)), + m_memory (std::exchange(other.m_memory, VkDeviceMemory(VK_NULL_HANDLE))), + m_offset (std::exchange(other.m_offset, 0)), + m_length (std::exchange(other.m_length, 0)), + m_mapPtr (std::exchange(other.m_mapPtr, nullptr)) { } + + + DxvkMemory& DxvkMemory::operator = (DxvkMemory&& other) { + this->free(); + m_alloc = std::exchange(other.m_alloc, nullptr); + m_chunk = std::exchange(other.m_chunk, nullptr); + m_type = std::exchange(other.m_type, nullptr); + m_memory = std::exchange(other.m_memory, VkDeviceMemory(VK_NULL_HANDLE)); + m_offset = std::exchange(other.m_offset, 0); + m_length = std::exchange(other.m_length, 0); + m_mapPtr = std::exchange(other.m_mapPtr, nullptr); + return *this; + } + + + DxvkMemory::~DxvkMemory() { + this->free(); + } + + + void DxvkMemory::free() { + if (m_alloc != nullptr) + m_alloc->free(*this); + } + + + DxvkMemoryChunk::DxvkMemoryChunk( + DxvkMemoryAllocator* alloc, + DxvkMemoryType* type, + DxvkDeviceMemory memory, + DxvkMemoryFlags hints) + : m_alloc(alloc), m_type(type), m_memory(memory), m_hints(hints) { + // Mark the entire chunk as free + m_freeList.push_back(FreeSlice { 0, memory.memSize }); + } + + + DxvkMemoryChunk::~DxvkMemoryChunk() { + // This call is technically not thread-safe, but it + // doesn't need to be since we don't free chunks + m_alloc->freeDeviceMemory(m_type, m_memory); + } + + + DxvkMemory DxvkMemoryChunk::alloc( + VkMemoryPropertyFlags flags, + VkDeviceSize size, + VkDeviceSize align, + DxvkMemoryFlags hints) { + // Property flags must be compatible. This could + // be refined a bit in the future if necessary. + if (m_memory.memFlags != flags || !checkHints(hints)) + return DxvkMemory(); + + // If the chunk is full, return + if (m_freeList.size() == 0) + return DxvkMemory(); + + // Select the slice to allocate from in a worst-fit + // manner. This may help keep fragmentation low. + auto bestSlice = m_freeList.begin(); + + for (auto slice = m_freeList.begin(); slice != m_freeList.end(); slice++) { + if (slice->length == size) { + bestSlice = slice; + break; + } else if (slice->length > bestSlice->length) { + bestSlice = slice; + } + } + + // We need to align the allocation to the requested alignment + const VkDeviceSize sliceStart = bestSlice->offset; + const VkDeviceSize sliceEnd = bestSlice->offset + bestSlice->length; + + const VkDeviceSize allocStart = dxvk::align(sliceStart, align); + const VkDeviceSize allocEnd = dxvk::align(allocStart + size, align); + + if (allocEnd > sliceEnd) + return DxvkMemory(); + + // We can use this slice, but we'll have to add + // the unused parts of it back to the free list. + m_freeList.erase(bestSlice); + + if (allocStart != sliceStart) + m_freeList.push_back({ sliceStart, allocStart - sliceStart }); + + if (allocEnd != sliceEnd) + m_freeList.push_back({ allocEnd, sliceEnd - allocEnd }); + + // Create the memory object with the aligned slice + return DxvkMemory(m_alloc, this, m_type, + m_memory.memHandle, allocStart, allocEnd - allocStart, + reinterpret_cast(m_memory.memPointer) + allocStart); + } + + + void DxvkMemoryChunk::free( + VkDeviceSize offset, + VkDeviceSize length) { + // Remove adjacent entries from the free list and then add + // a new slice that covers all those entries. Without doing + // so, the slice could not be reused for larger allocations. + auto curr = m_freeList.begin(); + + while (curr != m_freeList.end()) { + if (curr->offset == offset + length) { + length += curr->length; + curr = m_freeList.erase(curr); + } else if (curr->offset + curr->length == offset) { + offset -= curr->length; + length += curr->length; + curr = m_freeList.erase(curr); + } else { + curr++; + } + } + + m_freeList.push_back({ offset, length }); + } + + + bool DxvkMemoryChunk::isEmpty() const { + return m_freeList.size() == 1 + && m_freeList[0].length == m_memory.memSize; + } + + + bool DxvkMemoryChunk::isCompatible(const Rc& other) const { + return other->m_memory.memFlags == m_memory.memFlags && other->m_hints == m_hints; + } + + + bool DxvkMemoryChunk::checkHints(DxvkMemoryFlags hints) const { + DxvkMemoryFlags mask( + DxvkMemoryFlag::Small, + DxvkMemoryFlag::GpuReadable, + DxvkMemoryFlag::GpuWritable, + DxvkMemoryFlag::Transient); + + if (hints.test(DxvkMemoryFlag::IgnoreConstraints)) + mask = DxvkMemoryFlags(); + + return (m_hints & mask) == (hints & mask); + } + + + DxvkMemoryAllocator::DxvkMemoryAllocator(const DxvkDevice* device) + : m_vkd (device->vkd()), + m_device (device), + m_devProps (device->adapter()->deviceProperties()), + m_memProps (device->adapter()->memoryProperties()) { + for (uint32_t i = 0; i < m_memProps.memoryHeapCount; i++) { + m_memHeaps[i].properties = m_memProps.memoryHeaps[i]; + m_memHeaps[i].stats = DxvkMemoryStats { 0, 0 }; + m_memHeaps[i].budget = 0; + + /* Target 80% of a heap on systems where we want + * to avoid oversubscribing memory heaps */ + if ((m_memProps.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) + && (m_device->isUnifiedMemoryArchitecture())) + m_memHeaps[i].budget = (8 * m_memProps.memoryHeaps[i].size) / 10; + } + + for (uint32_t i = 0; i < m_memProps.memoryTypeCount; i++) { + m_memTypes[i].heap = &m_memHeaps[m_memProps.memoryTypes[i].heapIndex]; + m_memTypes[i].heapId = m_memProps.memoryTypes[i].heapIndex; + m_memTypes[i].memType = m_memProps.memoryTypes[i]; + m_memTypes[i].memTypeId = i; + } + + /* Check what kind of heap the HVV memory type is on, if any. If the + * HVV memory type is on the largest device-local heap, we either have + * an UMA system or an RBAR-enabled system. Otherwise, there will likely + * be a separate, smaller heap for it. */ + VkDeviceSize largestDeviceLocalHeap = 0; + + for (uint32_t i = 0; i < m_memProps.memoryTypeCount; i++) { + if (m_memTypes[i].memType.propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) + largestDeviceLocalHeap = std::max(largestDeviceLocalHeap, m_memTypes[i].heap->properties.size); + } + + /* Work around an issue on Nvidia drivers where using the entire + * device_local | host_visible heap can cause crashes or slowdowns */ + if (m_device->properties().core.properties.vendorID == uint16_t(DxvkGpuVendor::Nvidia)) { + bool shrinkNvidiaHvvHeap = device->adapter()->matchesDriver(DxvkGpuVendor::Nvidia, + VK_DRIVER_ID_NVIDIA_PROPRIETARY_KHR, 0, VK_MAKE_VERSION(465, 0, 0)); + + applyTristate(shrinkNvidiaHvvHeap, device->config().shrinkNvidiaHvvHeap); + + if (shrinkNvidiaHvvHeap) { + for (uint32_t i = 0; i < m_memProps.memoryTypeCount; i++) { + VkMemoryPropertyFlags hvvFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; + + if ((m_memTypes[i].memType.propertyFlags & hvvFlags) == hvvFlags + && (m_memTypes[i].heap->properties.size < largestDeviceLocalHeap)) + m_memTypes[i].heap->budget = 32 << 20; + } + } + } + } + + + DxvkMemoryAllocator::~DxvkMemoryAllocator() { + + } + + + DxvkMemory DxvkMemoryAllocator::alloc( + const VkMemoryRequirements* req, + const VkMemoryDedicatedRequirements& dedAllocReq, + const VkMemoryDedicatedAllocateInfo& dedAllocInfo, + VkMemoryPropertyFlags flags, + DxvkMemoryFlags hints) { + std::lock_guard lock(m_mutex); + + // Keep small allocations together to avoid fragmenting + // chunks for larger resources with lots of small gaps, + // as well as resources with potentially weird lifetimes + if (req->size <= SmallAllocationThreshold) { + hints.set(DxvkMemoryFlag::Small); + hints.clr(DxvkMemoryFlag::GpuWritable, DxvkMemoryFlag::GpuReadable); + } + + // Ignore most hints for host-visible allocations since they + // usually don't make much sense for those resources + if (flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) + hints = hints & DxvkMemoryFlag::Transient; + + // Try to allocate from a memory type which supports the given flags exactly + auto dedAllocPtr = dedAllocReq.prefersDedicatedAllocation ? &dedAllocInfo : nullptr; + DxvkMemory result = this->tryAlloc(req, dedAllocPtr, flags, hints); + + // If the first attempt failed, try ignoring the dedicated allocation + if (!result && dedAllocPtr && !dedAllocReq.requiresDedicatedAllocation) { + result = this->tryAlloc(req, nullptr, flags, hints); + dedAllocPtr = nullptr; + } + + // Retry without the hint constraints + if (!result) { + hints.set(DxvkMemoryFlag::IgnoreConstraints); + result = this->tryAlloc(req, nullptr, flags, hints); + } + + // If that still didn't work, probe slower memory types as well + VkMemoryPropertyFlags optFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT + | VK_MEMORY_PROPERTY_HOST_CACHED_BIT; + VkMemoryPropertyFlags remFlags = 0; + + while (!result && (flags & optFlags)) { + remFlags |= optFlags & -optFlags; + optFlags &= ~remFlags; + + result = this->tryAlloc(req, dedAllocPtr, flags & ~remFlags, hints); + } + + if (!result) { + DxvkAdapterMemoryInfo memHeapInfo = m_device->adapter()->getMemoryHeapInfo(); + + Logger::err(str::format( + "DxvkMemoryAllocator: Memory allocation failed", + "\n Size: ", req->size, + "\n Alignment: ", req->alignment, + "\n Mem flags: ", "0x", std::hex, flags, + "\n Mem types: ", "0x", std::hex, req->memoryTypeBits)); + + for (uint32_t i = 0; i < m_memProps.memoryHeapCount; i++) { + Logger::err(str::format("Heap ", i, ": ", + (m_memHeaps[i].stats.memoryAllocated >> 20), " MB allocated, ", + (m_memHeaps[i].stats.memoryUsed >> 20), " MB used, ", + m_device->extensions().extMemoryBudget + ? str::format( + (memHeapInfo.heaps[i].memoryAllocated >> 20), " MB allocated (driver), ", + (memHeapInfo.heaps[i].memoryBudget >> 20), " MB budget (driver), ", + (m_memHeaps[i].properties.size >> 20), " MB total") + : str::format( + (m_memHeaps[i].properties.size >> 20), " MB total"))); + } + + throw DxvkError("DxvkMemoryAllocator: Memory allocation failed"); + } + + return result; + } + + + DxvkMemory DxvkMemoryAllocator::tryAlloc( + const VkMemoryRequirements* req, + const VkMemoryDedicatedAllocateInfo* dedAllocInfo, + VkMemoryPropertyFlags flags, + DxvkMemoryFlags hints) { + DxvkMemory result; + + for (uint32_t i = 0; i < m_memProps.memoryTypeCount && !result; i++) { + const bool supported = (req->memoryTypeBits & (1u << i)) != 0; + const bool adequate = (m_memTypes[i].memType.propertyFlags & flags) == flags; + + if (supported && adequate) { + result = this->tryAllocFromType(&m_memTypes[i], + flags, req->size, req->alignment, hints, dedAllocInfo); + } + } + + return result; + } + + + DxvkMemory DxvkMemoryAllocator::tryAllocFromType( + DxvkMemoryType* type, + VkMemoryPropertyFlags flags, + VkDeviceSize size, + VkDeviceSize align, + DxvkMemoryFlags hints, + const VkMemoryDedicatedAllocateInfo* dedAllocInfo) { + VkDeviceSize chunkSize = pickChunkSize(type->memTypeId, hints); + + DxvkMemory memory; + + if (size >= chunkSize || dedAllocInfo) { + if (this->shouldFreeEmptyChunks(type->heap, size)) + this->freeEmptyChunks(type->heap); + + DxvkDeviceMemory devMem = this->tryAllocDeviceMemory( + type, flags, size, hints, dedAllocInfo); + + if (devMem.memHandle != VK_NULL_HANDLE) + memory = DxvkMemory(this, nullptr, type, devMem.memHandle, 0, size, devMem.memPointer); + } else { + for (uint32_t i = 0; i < type->chunks.size() && !memory; i++) + memory = type->chunks[i]->alloc(flags, size, align, hints); + + if (!memory) { + DxvkDeviceMemory devMem; + + if (this->shouldFreeEmptyChunks(type->heap, chunkSize)) + this->freeEmptyChunks(type->heap); + + for (uint32_t i = 0; i < 6 && (chunkSize >> i) >= size && !devMem.memHandle; i++) + devMem = tryAllocDeviceMemory(type, flags, chunkSize >> i, hints, nullptr); + + if (devMem.memHandle) { + Rc chunk = new DxvkMemoryChunk(this, type, devMem, hints); + memory = chunk->alloc(flags, size, align, hints); + + type->chunks.push_back(std::move(chunk)); + } + } + } + + if (memory) + type->heap->stats.memoryUsed += memory.m_length; + + return memory; + } + + + DxvkDeviceMemory DxvkMemoryAllocator::tryAllocDeviceMemory( + DxvkMemoryType* type, + VkMemoryPropertyFlags flags, + VkDeviceSize size, + DxvkMemoryFlags hints, + const VkMemoryDedicatedAllocateInfo* dedAllocInfo) { + bool useMemoryPriority = (flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) + && (m_device->features().extMemoryPriority.memoryPriority); + + if (type->heap->budget && type->heap->stats.memoryAllocated + size > type->heap->budget) + return DxvkDeviceMemory(); + + float priority = 0.0f; + + if (hints.test(DxvkMemoryFlag::GpuReadable)) + priority = 0.5f; + if (hints.test(DxvkMemoryFlag::GpuWritable)) + priority = 1.0f; + + DxvkDeviceMemory result; + result.memSize = size; + result.memFlags = flags; + result.priority = priority; + + VkMemoryPriorityAllocateInfoEXT prio; + prio.sType = VK_STRUCTURE_TYPE_MEMORY_PRIORITY_ALLOCATE_INFO_EXT; + prio.pNext = dedAllocInfo; + prio.priority = priority; + + VkMemoryAllocateInfo info; + info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + info.pNext = useMemoryPriority ? &prio : prio.pNext; + info.allocationSize = size; + info.memoryTypeIndex = type->memTypeId; + + if (m_vkd->vkAllocateMemory(m_vkd->device(), &info, nullptr, &result.memHandle) != VK_SUCCESS) + return DxvkDeviceMemory(); + + if (flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) { + VkResult status = m_vkd->vkMapMemory(m_vkd->device(), result.memHandle, 0, VK_WHOLE_SIZE, 0, &result.memPointer); + + if (status != VK_SUCCESS) { + Logger::err(str::format("DxvkMemoryAllocator: Mapping memory failed with ", status)); + m_vkd->vkFreeMemory(m_vkd->device(), result.memHandle, nullptr); + return DxvkDeviceMemory(); + } + } + + type->heap->stats.memoryAllocated += size; + m_device->adapter()->notifyHeapMemoryAlloc(type->heapId, size); + return result; + } + + + void DxvkMemoryAllocator::free( + const DxvkMemory& memory) { + std::lock_guard lock(m_mutex); + memory.m_type->heap->stats.memoryUsed -= memory.m_length; + + if (memory.m_chunk != nullptr) { + this->freeChunkMemory( + memory.m_type, + memory.m_chunk, + memory.m_offset, + memory.m_length); + } else { + DxvkDeviceMemory devMem; + devMem.memHandle = memory.m_memory; + devMem.memPointer = nullptr; + devMem.memSize = memory.m_length; + this->freeDeviceMemory(memory.m_type, devMem); + } + } + + + void DxvkMemoryAllocator::freeChunkMemory( + DxvkMemoryType* type, + DxvkMemoryChunk* chunk, + VkDeviceSize offset, + VkDeviceSize length) { + chunk->free(offset, length); + + if (chunk->isEmpty()) { + Rc chunkRef = chunk; + + // Free the chunk if we have to, or at least put it at the end of + // the list so that chunks that are already in use and cannot be + // freed are prioritized for allocations to reduce memory pressure. + type->chunks.erase(std::remove(type->chunks.begin(), type->chunks.end(), chunkRef)); + + if (!this->shouldFreeChunk(type, chunkRef)) + type->chunks.push_back(std::move(chunkRef)); + } + } + + + void DxvkMemoryAllocator::freeDeviceMemory( + DxvkMemoryType* type, + DxvkDeviceMemory memory) { + m_vkd->vkFreeMemory(m_vkd->device(), memory.memHandle, nullptr); + type->heap->stats.memoryAllocated -= memory.memSize; + m_device->adapter()->notifyHeapMemoryFree(type->heapId, memory.memSize); + } + + + VkDeviceSize DxvkMemoryAllocator::pickChunkSize(uint32_t memTypeId, DxvkMemoryFlags hints) const { + VkMemoryType type = m_memProps.memoryTypes[memTypeId]; + VkMemoryHeap heap = m_memProps.memoryHeaps[type.heapIndex]; + + // Default to a chunk size of 128 MiB + VkDeviceSize chunkSize = 128 << 20; + + if (hints.test(DxvkMemoryFlag::Small)) + chunkSize = 16 << 20; + + // Try to waste a bit less system memory especially in + // 32-bit applications due to address space constraints + if (type.propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) + chunkSize = (env::is32BitHostPlatform() ? 16 : 64) << 20; + + // Reduce the chunk size on small heaps so + // we can at least fit in 15 allocations + while (chunkSize * 15 > heap.size) + chunkSize >>= 1; + + return chunkSize; + } + + + bool DxvkMemoryAllocator::shouldFreeChunk( + const DxvkMemoryType* type, + const Rc& chunk) const { + // Under memory pressure, we should start freeing everything. + if (this->shouldFreeEmptyChunks(type->heap, 0)) + return true; + + // Even if we have enough memory to spare, only keep + // one chunk of each type around to save memory. + for (const auto& c : type->chunks) { + if (c != chunk && c->isEmpty() && c->isCompatible(chunk)) + return true; + } + + return false; + } + + + bool DxvkMemoryAllocator::shouldFreeEmptyChunks( + const DxvkMemoryHeap* heap, + VkDeviceSize allocationSize) const { + VkDeviceSize budget = heap->budget; + + if (!budget) + budget = (heap->properties.size * 4) / 5; + + return heap->stats.memoryAllocated + allocationSize > budget; + } + + + void DxvkMemoryAllocator::freeEmptyChunks( + const DxvkMemoryHeap* heap) { + for (uint32_t i = 0; i < m_memProps.memoryTypeCount; i++) { + DxvkMemoryType* type = &m_memTypes[i]; + + if (type->heap != heap) + continue; + + type->chunks.erase( + std::remove_if(type->chunks.begin(), type->chunks.end(), + [] (const Rc& chunk) { return chunk->isEmpty(); }), + type->chunks.end()); + } + } + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_memory.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_memory.h new file mode 100644 index 00000000000..795dd74d62a --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_memory.h @@ -0,0 +1,398 @@ +#pragma once + +#include "dxvk_adapter.h" + +namespace dxvk { + + class DxvkMemoryAllocator; + class DxvkMemoryChunk; + + /** + * \brief Memory stats + * + * Reports the amount of device memory + * allocated and used by the application. + */ + struct DxvkMemoryStats { + VkDeviceSize memoryAllocated = 0; + VkDeviceSize memoryUsed = 0; + }; + + + enum class DxvkSharedHandleMode { + None, + Import, + Export, + }; + + /** + * \brief Shared handle info + * + * The shared resource information for a given resource. + */ + struct DxvkSharedHandleInfo { + DxvkSharedHandleMode mode = DxvkSharedHandleMode::None; + VkExternalMemoryHandleTypeFlagBits type = VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM; + union { +#ifdef _WIN32 + HANDLE handle = INVALID_HANDLE_VALUE; +#else + // Placeholder for other handle types, such as FD + void *dummy; +#endif + }; + }; + + + /** + * \brief Device memory object + * + * Stores a Vulkan memory object. If the object + * was allocated on host-visible memory, it will + * be persistently mapped. + */ + struct DxvkDeviceMemory { + VkDeviceMemory memHandle = VK_NULL_HANDLE; + void* memPointer = nullptr; + VkDeviceSize memSize = 0; + VkMemoryPropertyFlags memFlags = 0; + float priority = 0.0f; + }; + + + /** + * \brief Memory heap + * + * Corresponds to a Vulkan memory heap and stores + * its properties as well as allocation statistics. + */ + struct DxvkMemoryHeap { + VkMemoryHeap properties; + DxvkMemoryStats stats; + VkDeviceSize budget; + }; + + + /** + * \brief Memory type + * + * Corresponds to a Vulkan memory type and stores + * memory chunks used to sub-allocate memory on + * this memory type. + */ + struct DxvkMemoryType { + DxvkMemoryHeap* heap; + uint32_t heapId; + + VkMemoryType memType; + uint32_t memTypeId; + + std::vector> chunks; + }; + + + /** + * \brief Memory slice + * + * Represents a slice of memory that has + * been sub-allocated from a bigger chunk. + */ + class DxvkMemory { + friend class DxvkMemoryAllocator; + public: + + DxvkMemory(); + DxvkMemory( + DxvkMemoryAllocator* alloc, + DxvkMemoryChunk* chunk, + DxvkMemoryType* type, + VkDeviceMemory memory, + VkDeviceSize offset, + VkDeviceSize length, + void* mapPtr); + DxvkMemory (DxvkMemory&& other); + DxvkMemory& operator = (DxvkMemory&& other); + ~DxvkMemory(); + + /** + * \brief Memory object + * + * This information is required when + * binding memory to Vulkan objects. + * \returns Memory object + */ + VkDeviceMemory memory() const { + return m_memory; + } + + /** + * \brief Offset into device memory + * + * This information is required when + * binding memory to Vulkan objects. + * \returns Offset into device memory + */ + VkDeviceSize offset() const { + return m_offset; + } + + /** + * \brief Pointer to mapped data + * + * \param [in] offset Byte offset + * \returns Pointer to mapped data + */ + void* mapPtr(VkDeviceSize offset) const { + return reinterpret_cast(m_mapPtr) + offset; + } + + /** + * \brief Returns length of memory allocated + * + * \returns Memory size + */ + VkDeviceSize length() const { + return m_length; + } + + /** + * \brief Checks whether the memory slice is defined + * + * \returns \c true if this slice points to actual device + * memory, and \c false if it is undefined. + */ + operator bool () const { + return m_memory != VK_NULL_HANDLE; + } + + private: + + DxvkMemoryAllocator* m_alloc = nullptr; + DxvkMemoryChunk* m_chunk = nullptr; + DxvkMemoryType* m_type = nullptr; + VkDeviceMemory m_memory = VK_NULL_HANDLE; + VkDeviceSize m_offset = 0; + VkDeviceSize m_length = 0; + void* m_mapPtr = nullptr; + + void free(); + + }; + + + /** + * \brief Memory allocation flags + * + * Used to batch similar allocations into the same + * set of chunks, which may help with fragmentation. + */ + enum class DxvkMemoryFlag : uint32_t { + Small = 0, ///< Small allocation + GpuReadable = 1, ///< Medium-priority resource + GpuWritable = 2, ///< High-priority resource + Transient = 3, ///< Resource is short-lived + IgnoreConstraints = 4, ///< Ignore most allocation flags + }; + + using DxvkMemoryFlags = Flags; + + + /** + * \brief Memory chunk + * + * A single chunk of memory that provides a + * sub-allocator. This is not thread-safe. + */ + class DxvkMemoryChunk : public RcObject { + + public: + + DxvkMemoryChunk( + DxvkMemoryAllocator* alloc, + DxvkMemoryType* type, + DxvkDeviceMemory memory, + DxvkMemoryFlags m_hints); + + ~DxvkMemoryChunk(); + + /** + * \brief Allocates memory from the chunk + * + * On failure, this returns a slice with + * \c VK_NULL_HANDLE as the memory handle. + * \param [in] flags Requested memory type flags + * \param [in] size Number of bytes to allocate + * \param [in] align Required alignment + * \param [in] hints Memory category + * \returns The allocated memory slice + */ + DxvkMemory alloc( + VkMemoryPropertyFlags flags, + VkDeviceSize size, + VkDeviceSize align, + DxvkMemoryFlags hints); + + /** + * \brief Frees memory + * + * Returns a slice back to the chunk. + * Called automatically when a memory + * slice runs out of scope. + * \param [in] offset Slice offset + * \param [in] length Slice length + */ + void free( + VkDeviceSize offset, + VkDeviceSize length); + + /** + * \brief Checks whether the chunk is being used + * \returns \c true if there are no allocations left + */ + bool isEmpty() const; + + /** + * \brief Checks whether hints and flags of another chunk match + * \param [in] other The chunk to compare to + */ + bool isCompatible(const Rc& other) const; + + private: + + struct FreeSlice { + VkDeviceSize offset; + VkDeviceSize length; + }; + + DxvkMemoryAllocator* m_alloc; + DxvkMemoryType* m_type; + DxvkDeviceMemory m_memory; + DxvkMemoryFlags m_hints; + + std::vector m_freeList; + + bool checkHints(DxvkMemoryFlags hints) const; + + }; + + + /** + * \brief Memory allocator + * + * Allocates device memory for Vulkan resources. + * Memory objects will be destroyed automatically. + */ + class DxvkMemoryAllocator { + friend class DxvkMemory; + friend class DxvkMemoryChunk; + + constexpr static VkDeviceSize SmallAllocationThreshold = 256 << 10; + public: + + DxvkMemoryAllocator(const DxvkDevice* device); + ~DxvkMemoryAllocator(); + + /** + * \brief Buffer-image granularity + * + * The granularity between linear and non-linear + * resources in adjacent memory locations. See + * section 11.6 of the Vulkan spec for details. + * \returns Buffer-image granularity + */ + VkDeviceSize bufferImageGranularity() const { + return m_devProps.limits.bufferImageGranularity; + } + + /** + * \brief Allocates device memory + * + * \param [in] req Memory requirements + * \param [in] dedAllocReq Dedicated allocation requirements + * \param [in] dedAllocInfo Dedicated allocation info + * \param [in] flags Memory type flags + * \param [in] hints Memory hints + * \returns Allocated memory slice + */ + DxvkMemory alloc( + const VkMemoryRequirements* req, + const VkMemoryDedicatedRequirements& dedAllocReq, + const VkMemoryDedicatedAllocateInfo& dedAllocInfo, + VkMemoryPropertyFlags flags, + DxvkMemoryFlags hints); + + /** + * \brief Queries memory stats + * + * Returns the total amount of memory + * allocated and used for a given heap. + * \param [in] heap Heap index + * \returns Memory stats for this heap + */ + DxvkMemoryStats getMemoryStats(uint32_t heap) const { + return m_memHeaps[heap].stats; + } + + private: + + const Rc m_vkd; + const DxvkDevice* m_device; + const VkPhysicalDeviceProperties m_devProps; + const VkPhysicalDeviceMemoryProperties m_memProps; + + dxvk::mutex m_mutex; + std::array m_memHeaps; + std::array m_memTypes; + + DxvkMemory tryAlloc( + const VkMemoryRequirements* req, + const VkMemoryDedicatedAllocateInfo* dedAllocInfo, + VkMemoryPropertyFlags flags, + DxvkMemoryFlags hints); + + DxvkMemory tryAllocFromType( + DxvkMemoryType* type, + VkMemoryPropertyFlags flags, + VkDeviceSize size, + VkDeviceSize align, + DxvkMemoryFlags hints, + const VkMemoryDedicatedAllocateInfo* dedAllocInfo); + + DxvkDeviceMemory tryAllocDeviceMemory( + DxvkMemoryType* type, + VkMemoryPropertyFlags flags, + VkDeviceSize size, + DxvkMemoryFlags hints, + const VkMemoryDedicatedAllocateInfo* dedAllocInfo); + + void free( + const DxvkMemory& memory); + + void freeChunkMemory( + DxvkMemoryType* type, + DxvkMemoryChunk* chunk, + VkDeviceSize offset, + VkDeviceSize length); + + void freeDeviceMemory( + DxvkMemoryType* type, + DxvkDeviceMemory memory); + + VkDeviceSize pickChunkSize( + uint32_t memTypeId, + DxvkMemoryFlags hints) const; + + bool shouldFreeChunk( + const DxvkMemoryType* type, + const Rc& chunk) const; + + bool shouldFreeEmptyChunks( + const DxvkMemoryHeap* heap, + VkDeviceSize allocationSize) const; + + void freeEmptyChunks( + const DxvkMemoryHeap* heap); + + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_blit.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_blit.cpp new file mode 100644 index 00000000000..7956b2ed4fd --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_blit.cpp @@ -0,0 +1,599 @@ +#include "dxvk_device.h" +#include "dxvk_meta_blit.h" + +#include +#include +#include + +#include +#include +#include + +namespace dxvk { + + DxvkMetaBlitRenderPass::DxvkMetaBlitRenderPass( + const Rc& device, + const Rc& dstImage, + const Rc& srcImage, + const VkImageBlit& region, + const VkComponentMapping& mapping) + : m_vkd (device->vkd()), + m_dstImage (dstImage), + m_srcImage (srcImage), + m_region (region), + m_dstView (createDstView()), + m_srcView (createSrcView(mapping)), + m_renderPass (createRenderPass()), + m_framebuffer (createFramebuffer()) { + + } + + + DxvkMetaBlitRenderPass::~DxvkMetaBlitRenderPass() { + m_vkd->vkDestroyImageView(m_vkd->device(), m_dstView, nullptr); + m_vkd->vkDestroyImageView(m_vkd->device(), m_srcView, nullptr); + m_vkd->vkDestroyRenderPass(m_vkd->device(), m_renderPass, nullptr); + m_vkd->vkDestroyFramebuffer(m_vkd->device(), m_framebuffer, nullptr); + } + + + VkImageViewType DxvkMetaBlitRenderPass::viewType() const { + std::array viewTypes = {{ + VK_IMAGE_VIEW_TYPE_1D_ARRAY, + VK_IMAGE_VIEW_TYPE_2D_ARRAY, + VK_IMAGE_VIEW_TYPE_3D, + }}; + + return viewTypes.at(uint32_t(m_srcImage->info().type)); + } + + + uint32_t DxvkMetaBlitRenderPass::framebufferLayerIndex() const { + uint32_t result = m_region.dstSubresource.baseArrayLayer; + + if (m_dstImage->info().type == VK_IMAGE_TYPE_3D) + result = std::min(m_region.dstOffsets[0].z, m_region.dstOffsets[1].z); + + return result; + } + + + uint32_t DxvkMetaBlitRenderPass::framebufferLayerCount() const { + uint32_t result = m_region.dstSubresource.layerCount; + + if (m_dstImage->info().type == VK_IMAGE_TYPE_3D) { + uint32_t minZ = std::min(m_region.dstOffsets[0].z, m_region.dstOffsets[1].z); + uint32_t maxZ = std::max(m_region.dstOffsets[0].z, m_region.dstOffsets[1].z); + result = maxZ - minZ; + } + + return result; + } + + + DxvkMetaBlitPass DxvkMetaBlitRenderPass::pass() const { + DxvkMetaBlitPass result; + result.srcView = m_srcView; + result.dstView = m_dstView; + result.renderPass = m_renderPass; + result.framebuffer = m_framebuffer; + return result; + } + + + VkImageView DxvkMetaBlitRenderPass::createDstView() { + std::array viewTypes = {{ + VK_IMAGE_VIEW_TYPE_1D_ARRAY, + VK_IMAGE_VIEW_TYPE_2D_ARRAY, + VK_IMAGE_VIEW_TYPE_2D_ARRAY, + }}; + + VkImageViewUsageCreateInfo usageInfo; + usageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO; + usageInfo.pNext = nullptr; + usageInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + + VkImageViewCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + info.pNext = &usageInfo; + info.flags = 0; + info.image = m_dstImage->handle(); + info.viewType = viewTypes.at(uint32_t(m_dstImage->info().type)); + info.format = m_dstImage->info().format; + info.components = VkComponentMapping(); + info.subresourceRange = vk::makeSubresourceRange(m_region.dstSubresource); + + if (m_dstImage->info().type) { + info.subresourceRange.baseArrayLayer = framebufferLayerIndex(); + info.subresourceRange.layerCount = framebufferLayerCount(); + } + + VkImageView result; + if (m_vkd->vkCreateImageView(m_vkd->device(), &info, nullptr, &result) != VK_SUCCESS) + throw DxvkError("DxvkMetaBlitRenderPass: Failed to create image view"); + return result; + } + + + VkImageView DxvkMetaBlitRenderPass::createSrcView(const VkComponentMapping& mapping) { + VkImageViewUsageCreateInfo usageInfo; + usageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO; + usageInfo.pNext = nullptr; + usageInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT; + + VkImageViewCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + info.pNext = &usageInfo; + info.flags = 0; + info.image = m_srcImage->handle(); + info.viewType = this->viewType(); + info.format = m_srcImage->info().format; + info.components = mapping; + info.subresourceRange = vk::makeSubresourceRange(m_region.srcSubresource); + + VkImageView result; + if (m_vkd->vkCreateImageView(m_vkd->device(), &info, nullptr, &result) != VK_SUCCESS) + throw DxvkError("DxvkMetaBlitRenderPass: Failed to create image view"); + return result; + } + + + VkRenderPass DxvkMetaBlitRenderPass::createRenderPass() { + VkAttachmentDescription attachment; + attachment.flags = 0; + attachment.format = m_dstImage->info().format; + attachment.samples = m_dstImage->info().sampleCount; + attachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attachment.initialLayout = m_dstImage->info().layout; + attachment.finalLayout = m_dstImage->info().layout; + + VkAttachmentReference attachmentRef; + attachmentRef.attachment = 0; + attachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + VkSubpassDescription subpass; + subpass.flags = 0; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.inputAttachmentCount = 0; + subpass.pInputAttachments = nullptr; + subpass.colorAttachmentCount = 1; + subpass.pColorAttachments = &attachmentRef; + subpass.pResolveAttachments = nullptr; + subpass.pDepthStencilAttachment = nullptr; + subpass.preserveAttachmentCount = 0; + subpass.pPreserveAttachments = nullptr; + + VkRenderPassCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.attachmentCount = 1; + info.pAttachments = &attachment; + info.subpassCount = 1; + info.pSubpasses = &subpass; + info.dependencyCount = 0; + info.pDependencies = nullptr; + + VkRenderPass result = VK_NULL_HANDLE; + if (m_vkd->vkCreateRenderPass(m_vkd->device(), &info, nullptr, &result) != VK_SUCCESS) + throw DxvkError("DxvkMetaBlitRenderPass: Failed to create render pass"); + return result; + } + + + VkFramebuffer DxvkMetaBlitRenderPass::createFramebuffer() { + VkExtent3D extent = m_dstImage->mipLevelExtent(m_region.dstSubresource.mipLevel); + + VkFramebufferCreateInfo fboInfo; + fboInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + fboInfo.pNext = nullptr; + fboInfo.flags = 0; + fboInfo.renderPass = m_renderPass; + fboInfo.attachmentCount = 1; + fboInfo.pAttachments = &m_dstView; + fboInfo.width = extent.width; + fboInfo.height = extent.height; + fboInfo.layers = framebufferLayerCount(); + + VkFramebuffer result; + if (m_vkd->vkCreateFramebuffer(m_vkd->device(), &fboInfo, nullptr, &result) != VK_SUCCESS) + throw DxvkError("DxvkMetaBlitRenderPass: Failed to create target framebuffer"); + return result; + } + + + + + DxvkMetaBlitObjects::DxvkMetaBlitObjects(const DxvkDevice* device) + : m_vkd (device->vkd()), + m_samplerCopy (createSampler(VK_FILTER_NEAREST)), + m_samplerBlit (createSampler(VK_FILTER_LINEAR)), + m_shaderFrag1D(createShaderModule(dxvk_blit_frag_1d)), + m_shaderFrag2D(createShaderModule(dxvk_blit_frag_2d)), + m_shaderFrag3D(createShaderModule(dxvk_blit_frag_3d)) { + if (device->extensions().extShaderViewportIndexLayer) { + m_shaderVert = createShaderModule(dxvk_fullscreen_layer_vert); + } else { + m_shaderVert = createShaderModule(dxvk_fullscreen_vert); + m_shaderGeom = createShaderModule(dxvk_fullscreen_geom); + } + } + + + DxvkMetaBlitObjects::~DxvkMetaBlitObjects() { + for (const auto& pair : m_renderPasses) + m_vkd->vkDestroyRenderPass(m_vkd->device(), pair.second, nullptr); + + for (const auto& pair : m_pipelines) { + m_vkd->vkDestroyPipeline(m_vkd->device(), pair.second.pipeHandle, nullptr); + m_vkd->vkDestroyPipelineLayout(m_vkd->device(), pair.second.pipeLayout, nullptr); + m_vkd->vkDestroyDescriptorSetLayout (m_vkd->device(), pair.second.dsetLayout, nullptr); + } + + m_vkd->vkDestroyShaderModule(m_vkd->device(), m_shaderFrag3D, nullptr); + m_vkd->vkDestroyShaderModule(m_vkd->device(), m_shaderFrag2D, nullptr); + m_vkd->vkDestroyShaderModule(m_vkd->device(), m_shaderFrag1D, nullptr); + m_vkd->vkDestroyShaderModule(m_vkd->device(), m_shaderGeom, nullptr); + m_vkd->vkDestroyShaderModule(m_vkd->device(), m_shaderVert, nullptr); + + m_vkd->vkDestroySampler(m_vkd->device(), m_samplerBlit, nullptr); + m_vkd->vkDestroySampler(m_vkd->device(), m_samplerCopy, nullptr); + } + + + DxvkMetaBlitPipeline DxvkMetaBlitObjects::getPipeline( + VkImageViewType viewType, + VkFormat viewFormat, + VkSampleCountFlagBits samples) { + std::lock_guard lock(m_mutex); + + DxvkMetaBlitPipelineKey key; + key.viewType = viewType; + key.viewFormat = viewFormat; + key.samples = samples; + + auto entry = m_pipelines.find(key); + if (entry != m_pipelines.end()) + return entry->second; + + DxvkMetaBlitPipeline pipeline = this->createPipeline(key); + m_pipelines.insert({ key, pipeline }); + return pipeline; + } + + + VkSampler DxvkMetaBlitObjects::getSampler(VkFilter filter) { + return filter == VK_FILTER_NEAREST + ? m_samplerCopy + : m_samplerBlit; + } + + + VkRenderPass DxvkMetaBlitObjects::getRenderPass( + VkFormat viewFormat, + VkSampleCountFlagBits samples) { + DxvkMetaBlitRenderPassKey key; + key.viewFormat = viewFormat; + key.samples = samples; + + auto entry = m_renderPasses.find(key); + if (entry != m_renderPasses.end()) + return entry->second; + + VkRenderPass renderPass = this->createRenderPass(viewFormat, samples); + m_renderPasses.insert({ key, renderPass }); + return renderPass; + } + + + VkSampler DxvkMetaBlitObjects::createSampler(VkFilter filter) const { + VkSamplerCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.magFilter = filter; + info.minFilter = filter; + info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; + info.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + info.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + info.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + info.mipLodBias = 0.0f; + info.anisotropyEnable = VK_FALSE; + info.maxAnisotropy = 1.0f; + info.compareEnable = VK_FALSE; + info.compareOp = VK_COMPARE_OP_ALWAYS; + info.minLod = 0.0f; + info.maxLod = 0.0f; + info.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; + info.unnormalizedCoordinates = VK_FALSE; + + VkSampler result = VK_NULL_HANDLE; + if (m_vkd->vkCreateSampler(m_vkd->device(), &info, nullptr, &result) != VK_SUCCESS) + throw DxvkError("DxvkMetaBlitObjects: Failed to create sampler"); + return result; + } + + + VkShaderModule DxvkMetaBlitObjects::createShaderModule(const SpirvCodeBuffer& code) const { + VkShaderModuleCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.codeSize = code.size(); + info.pCode = code.data(); + + VkShaderModule result = VK_NULL_HANDLE; + if (m_vkd->vkCreateShaderModule(m_vkd->device(), &info, nullptr, &result) != VK_SUCCESS) + throw DxvkError("DxvkMetaBlitObjects: Failed to create shader module"); + return result; + } + + + DxvkMetaBlitPipeline DxvkMetaBlitObjects::createPipeline( + const DxvkMetaBlitPipelineKey& key) { + DxvkMetaBlitPipeline pipe; + pipe.dsetLayout = this->createDescriptorSetLayout(key.viewType); + pipe.pipeLayout = this->createPipelineLayout(pipe.dsetLayout); + pipe.pipeHandle = this->createPipeline(key.viewType, pipe.pipeLayout, + this->getRenderPass(key.viewFormat, key.samples), key.samples); + return pipe; + } + + + VkRenderPass DxvkMetaBlitObjects::createRenderPass( + VkFormat format, + VkSampleCountFlagBits samples) const { + VkAttachmentDescription attachment; + attachment.flags = 0; + attachment.format = format; + attachment.samples = samples; + attachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + attachment.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + + VkAttachmentReference attachmentRef; + attachmentRef.attachment = 0; + attachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + VkSubpassDescription subpass; + subpass.flags = 0; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.inputAttachmentCount = 0; + subpass.pInputAttachments = nullptr; + subpass.colorAttachmentCount = 1; + subpass.pColorAttachments = &attachmentRef; + subpass.pResolveAttachments = nullptr; + subpass.pDepthStencilAttachment = nullptr; + subpass.preserveAttachmentCount = 0; + subpass.pPreserveAttachments = nullptr; + + VkRenderPassCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.attachmentCount = 1; + info.pAttachments = &attachment; + info.subpassCount = 1; + info.pSubpasses = &subpass; + info.dependencyCount = 0; + info.pDependencies = nullptr; + + VkRenderPass result = VK_NULL_HANDLE; + if (m_vkd->vkCreateRenderPass(m_vkd->device(), &info, nullptr, &result) != VK_SUCCESS) + throw DxvkError("DxvkMetaBlitObjects: Failed to create render pass"); + return result; + } + + + VkDescriptorSetLayout DxvkMetaBlitObjects::createDescriptorSetLayout( + VkImageViewType viewType) const { + VkDescriptorSetLayoutBinding binding; + binding.binding = 0; + binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + binding.descriptorCount = 1; + binding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + binding.pImmutableSamplers = nullptr; + + VkDescriptorSetLayoutCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.bindingCount = 1; + info.pBindings = &binding; + + VkDescriptorSetLayout result = VK_NULL_HANDLE; + if (m_vkd->vkCreateDescriptorSetLayout(m_vkd->device(), &info, nullptr, &result) != VK_SUCCESS) + throw DxvkError("DxvkMetaBlitObjects: Failed to create descriptor set layout"); + return result; + } + + + VkPipelineLayout DxvkMetaBlitObjects::createPipelineLayout( + VkDescriptorSetLayout descriptorSetLayout) const { + VkPushConstantRange pushRange; + pushRange.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + pushRange.offset = 0; + pushRange.size = sizeof(DxvkMetaBlitPushConstants); + + VkPipelineLayoutCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.setLayoutCount = 1; + info.pSetLayouts = &descriptorSetLayout; + info.pushConstantRangeCount = 1; + info.pPushConstantRanges = &pushRange; + + VkPipelineLayout result = VK_NULL_HANDLE; + if (m_vkd->vkCreatePipelineLayout(m_vkd->device(), &info, nullptr, &result) != VK_SUCCESS) + throw DxvkError("DxvkMetaBlitObjects: Failed to create pipeline layout"); + return result; + } + + + VkPipeline DxvkMetaBlitObjects::createPipeline( + VkImageViewType imageViewType, + VkPipelineLayout pipelineLayout, + VkRenderPass renderPass, + VkSampleCountFlagBits samples) const { + std::array stages; + uint32_t stageCount = 0; + + VkPipelineShaderStageCreateInfo& vsStage = stages[stageCount++]; + vsStage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + vsStage.pNext = nullptr; + vsStage.flags = 0; + vsStage.stage = VK_SHADER_STAGE_VERTEX_BIT; + vsStage.module = m_shaderVert; + vsStage.pName = "main"; + vsStage.pSpecializationInfo = nullptr; + + if (m_shaderGeom) { + VkPipelineShaderStageCreateInfo& gsStage = stages[stageCount++]; + gsStage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + gsStage.pNext = nullptr; + gsStage.flags = 0; + gsStage.stage = VK_SHADER_STAGE_GEOMETRY_BIT; + gsStage.module = m_shaderGeom; + gsStage.pName = "main"; + gsStage.pSpecializationInfo = nullptr; + } + + VkPipelineShaderStageCreateInfo& psStage = stages[stageCount++]; + psStage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + psStage.pNext = nullptr; + psStage.flags = 0; + psStage.stage = VK_SHADER_STAGE_FRAGMENT_BIT; + psStage.module = VK_NULL_HANDLE; + psStage.pName = "main"; + psStage.pSpecializationInfo = nullptr; + + switch (imageViewType) { + case VK_IMAGE_VIEW_TYPE_1D_ARRAY: psStage.module = m_shaderFrag1D; break; + case VK_IMAGE_VIEW_TYPE_2D_ARRAY: psStage.module = m_shaderFrag2D; break; + case VK_IMAGE_VIEW_TYPE_3D: psStage.module = m_shaderFrag3D; break; + default: throw DxvkError("DxvkMetaBlitObjects: Invalid view type"); + } + + std::array dynStates = {{ + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR, + }}; + + VkPipelineDynamicStateCreateInfo dynState; + dynState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; + dynState.pNext = nullptr; + dynState.flags = 0; + dynState.dynamicStateCount = dynStates.size(); + dynState.pDynamicStates = dynStates.data(); + + VkPipelineVertexInputStateCreateInfo viState; + viState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + viState.pNext = nullptr; + viState.flags = 0; + viState.vertexBindingDescriptionCount = 0; + viState.pVertexBindingDescriptions = nullptr; + viState.vertexAttributeDescriptionCount = 0; + viState.pVertexAttributeDescriptions = nullptr; + + VkPipelineInputAssemblyStateCreateInfo iaState; + iaState.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + iaState.pNext = nullptr; + iaState.flags = 0; + iaState.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + iaState.primitiveRestartEnable = VK_FALSE; + + VkPipelineViewportStateCreateInfo vpState; + vpState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + vpState.pNext = nullptr; + vpState.flags = 0; + vpState.viewportCount = 1; + vpState.pViewports = nullptr; + vpState.scissorCount = 1; + vpState.pScissors = nullptr; + + VkPipelineRasterizationStateCreateInfo rsState; + rsState.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + rsState.pNext = nullptr; + rsState.flags = 0; + rsState.depthClampEnable = VK_TRUE; + rsState.rasterizerDiscardEnable = VK_FALSE; + rsState.polygonMode = VK_POLYGON_MODE_FILL; + rsState.cullMode = VK_CULL_MODE_NONE; + rsState.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; + rsState.depthBiasEnable = VK_FALSE; + rsState.depthBiasConstantFactor = 0.0f; + rsState.depthBiasClamp = 0.0f; + rsState.depthBiasSlopeFactor = 0.0f; + rsState.lineWidth = 1.0f; + + uint32_t msMask = 0xFFFFFFFF; + VkPipelineMultisampleStateCreateInfo msState; + msState.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + msState.pNext = nullptr; + msState.flags = 0; + msState.rasterizationSamples = samples; + msState.sampleShadingEnable = VK_FALSE; + msState.minSampleShading = 1.0f; + msState.pSampleMask = &msMask; + msState.alphaToCoverageEnable = VK_FALSE; + msState.alphaToOneEnable = VK_FALSE; + + VkPipelineColorBlendAttachmentState cbAttachment; + cbAttachment.blendEnable = VK_FALSE; + cbAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; + cbAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; + cbAttachment.colorBlendOp = VK_BLEND_OP_ADD; + cbAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; + cbAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; + cbAttachment.alphaBlendOp = VK_BLEND_OP_ADD; + cbAttachment.colorWriteMask = + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | + VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + + VkPipelineColorBlendStateCreateInfo cbState; + cbState.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + cbState.pNext = nullptr; + cbState.flags = 0; + cbState.logicOpEnable = VK_FALSE; + cbState.logicOp = VK_LOGIC_OP_NO_OP; + cbState.attachmentCount = 1; + cbState.pAttachments = &cbAttachment; + + for (uint32_t i = 0; i < 4; i++) + cbState.blendConstants[i] = 0.0f; + + VkGraphicsPipelineCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.stageCount = stageCount; + info.pStages = stages.data(); + info.pVertexInputState = &viState; + info.pInputAssemblyState = &iaState; + info.pTessellationState = nullptr; + info.pViewportState = &vpState; + info.pRasterizationState = &rsState; + info.pMultisampleState = &msState; + info.pColorBlendState = &cbState; + info.pDepthStencilState = nullptr; + info.pDynamicState = &dynState; + info.layout = pipelineLayout; + info.renderPass = renderPass; + info.subpass = 0; + info.basePipelineHandle = VK_NULL_HANDLE; + info.basePipelineIndex = -1; + + VkPipeline result = VK_NULL_HANDLE; + if (m_vkd->vkCreateGraphicsPipelines(m_vkd->device(), VK_NULL_HANDLE, 1, &info, nullptr, &result) != VK_SUCCESS) + throw DxvkError("DxvkMetaBlitObjects: Failed to create graphics pipeline"); + return result; + } + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_blit.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_blit.h new file mode 100644 index 00000000000..28f8616c530 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_blit.h @@ -0,0 +1,245 @@ +#pragma once + +#include +#include + +#include "../spirv/spirv_code_buffer.h" + +#include "dxvk_hash.h" +#include "dxvk_image.h" + +namespace dxvk { + + /** + * \brief Texture coordinates + */ + struct DxvkMetaBlitOffset { + float x, y, z; + }; + + /** + * \brief Push constant data + */ + struct DxvkMetaBlitPushConstants { + DxvkMetaBlitOffset srcCoord0; + uint32_t pad1; + DxvkMetaBlitOffset srcCoord1; + uint32_t layerCount; + }; + + /** + * \brief Blit pipeline key + * + * We have to create pipelines for each + * combination of source image view type + * and image format. + */ + struct DxvkMetaBlitPipelineKey { + VkImageViewType viewType; + VkFormat viewFormat; + VkSampleCountFlagBits samples; + + bool eq(const DxvkMetaBlitPipelineKey& other) const { + return this->viewType == other.viewType + && this->viewFormat == other.viewFormat + && this->samples == other.samples; + } + + size_t hash() const { + DxvkHashState result; + result.add(uint32_t(this->viewType)); + result.add(uint32_t(this->viewFormat)); + result.add(uint32_t(this->samples)); + return result; + } + }; + + /** + * \brief Blit render pass key + */ + struct DxvkMetaBlitRenderPassKey { + VkFormat viewFormat; + VkSampleCountFlagBits samples; + + bool eq(const DxvkMetaBlitRenderPassKey& other) const { + return this->viewFormat == other.viewFormat + && this->samples == other.samples; + } + + size_t hash() const { + DxvkHashState result; + result.add(uint32_t(this->viewFormat)); + result.add(uint32_t(this->samples)); + return result; + } + }; + + /** + * \brief Blit pipeline + * + * Stores the objects for a single pipeline + * that is used for blitting. + */ + struct DxvkMetaBlitPipeline { + VkDescriptorSetLayout dsetLayout; + VkPipelineLayout pipeLayout; + VkPipeline pipeHandle; + }; + + + /** + * \brief Blit framebuffer + * + * Stores the image views and framebuffer + * handle used to generate one mip level. + */ + struct DxvkMetaBlitPass { + VkImageView srcView; + VkImageView dstView; + VkRenderPass renderPass; + VkFramebuffer framebuffer; + }; + + + /** + * \brief Blit render pass + * + * Stores image view, render pass and framebuffer + * objects for a blit operation, as well as some + * metadata. + */ + class DxvkMetaBlitRenderPass : public DxvkResource { + + public: + + DxvkMetaBlitRenderPass( + const Rc& device, + const Rc& dstImage, + const Rc& srcImage, + const VkImageBlit& region, + const VkComponentMapping& mapping); + + ~DxvkMetaBlitRenderPass(); + + VkImageViewType viewType() const; + + uint32_t framebufferLayerIndex() const; + uint32_t framebufferLayerCount() const; + + DxvkMetaBlitPass pass() const; + + private: + + Rc m_vkd; + Rc m_dstImage; + Rc m_srcImage; + + VkImageBlit m_region; + VkImageView m_dstView; + VkImageView m_srcView; + VkRenderPass m_renderPass; + VkFramebuffer m_framebuffer; + + VkImageView createDstView(); + VkImageView createSrcView(const VkComponentMapping& mapping); + + VkRenderPass createRenderPass(); + VkFramebuffer createFramebuffer(); + + }; + + + /** + * \brief Blitter objects + * + * Stores render pass objects and pipelines used + * to generate mip maps. Due to Vulkan API design + * decisions, we have to create one render pass + * and pipeline object per image format used. + */ + class DxvkMetaBlitObjects { + + public: + + DxvkMetaBlitObjects(const DxvkDevice* device); + ~DxvkMetaBlitObjects(); + + /** + * \brief Creates a blit pipeline + * + * \param [in] viewType Source image view type + * \param [in] viewFormat Image view format + * \param [in] samples Target sample count + * \returns The blit pipeline + */ + DxvkMetaBlitPipeline getPipeline( + VkImageViewType viewType, + VkFormat viewFormat, + VkSampleCountFlagBits samples); + + /** + * \brief Retrieves sampler with a given filter + * + * \param [in] filter The desired filter + * \returns Sampler object with the given filter + */ + VkSampler getSampler( + VkFilter filter); + + private: + + Rc m_vkd; + + VkSampler m_samplerCopy; + VkSampler m_samplerBlit; + + VkShaderModule m_shaderVert = VK_NULL_HANDLE; + VkShaderModule m_shaderGeom = VK_NULL_HANDLE; + VkShaderModule m_shaderFrag1D = VK_NULL_HANDLE; + VkShaderModule m_shaderFrag2D = VK_NULL_HANDLE; + VkShaderModule m_shaderFrag3D = VK_NULL_HANDLE; + + dxvk::mutex m_mutex; + + std::unordered_map< + DxvkMetaBlitRenderPassKey, + VkRenderPass, + DxvkHash, DxvkEq> m_renderPasses; + + std::unordered_map< + DxvkMetaBlitPipelineKey, + DxvkMetaBlitPipeline, + DxvkHash, DxvkEq> m_pipelines; + + VkRenderPass getRenderPass( + VkFormat viewFormat, + VkSampleCountFlagBits samples); + + VkSampler createSampler( + VkFilter filter) const; + + VkShaderModule createShaderModule( + const SpirvCodeBuffer& code) const; + + DxvkMetaBlitPipeline createPipeline( + const DxvkMetaBlitPipelineKey& key); + + VkRenderPass createRenderPass( + VkFormat format, + VkSampleCountFlagBits samples) const; + + VkDescriptorSetLayout createDescriptorSetLayout( + VkImageViewType viewType) const; + + VkPipelineLayout createPipelineLayout( + VkDescriptorSetLayout descriptorSetLayout) const; + + VkPipeline createPipeline( + VkImageViewType imageViewType, + VkPipelineLayout pipelineLayout, + VkRenderPass renderPass, + VkSampleCountFlagBits samples) const; + + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_clear.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_clear.cpp new file mode 100644 index 00000000000..d5b3381d21f --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_clear.cpp @@ -0,0 +1,210 @@ +#include "dxvk_meta_clear.h" +#include "dxvk_device.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace dxvk { + + DxvkMetaClearObjects::DxvkMetaClearObjects(const DxvkDevice* device) + : m_vkd(device->vkd()) { + // Create descriptor set layouts + m_clearBufDsetLayout = createDescriptorSetLayout(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER); + m_clearImgDsetLayout = createDescriptorSetLayout(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE); + + // Create pipeline layouts using those descriptor set layouts + m_clearBufPipeLayout = createPipelineLayout(m_clearBufDsetLayout); + m_clearImgPipeLayout = createPipelineLayout(m_clearImgDsetLayout); + + // Create the actual compute pipelines + m_clearPipesF32.clearBuf = createPipeline(dxvk_clear_buffer_f, m_clearBufPipeLayout); + m_clearPipesU32.clearBuf = createPipeline(dxvk_clear_buffer_u, m_clearBufPipeLayout); + + m_clearPipesF32.clearImg1D = createPipeline(dxvk_clear_image1d_f, m_clearImgPipeLayout); + m_clearPipesU32.clearImg1D = createPipeline(dxvk_clear_image1d_u, m_clearImgPipeLayout); + m_clearPipesF32.clearImg2D = createPipeline(dxvk_clear_image2d_f, m_clearImgPipeLayout); + m_clearPipesU32.clearImg2D = createPipeline(dxvk_clear_image2d_u, m_clearImgPipeLayout); + m_clearPipesF32.clearImg3D = createPipeline(dxvk_clear_image3d_f, m_clearImgPipeLayout); + m_clearPipesU32.clearImg3D = createPipeline(dxvk_clear_image3d_u, m_clearImgPipeLayout); + + m_clearPipesF32.clearImg1DArray = createPipeline(dxvk_clear_image1darr_f, m_clearImgPipeLayout); + m_clearPipesU32.clearImg1DArray = createPipeline(dxvk_clear_image1darr_u, m_clearImgPipeLayout); + m_clearPipesF32.clearImg2DArray = createPipeline(dxvk_clear_image2darr_f, m_clearImgPipeLayout); + m_clearPipesU32.clearImg2DArray = createPipeline(dxvk_clear_image2darr_u, m_clearImgPipeLayout); + } + + + DxvkMetaClearObjects::~DxvkMetaClearObjects() { + // Destroy pipelines + m_vkd->vkDestroyPipeline(m_vkd->device(), m_clearPipesF32.clearBuf, nullptr); + m_vkd->vkDestroyPipeline(m_vkd->device(), m_clearPipesU32.clearBuf, nullptr); + + m_vkd->vkDestroyPipeline(m_vkd->device(), m_clearPipesF32.clearImg1D, nullptr); + m_vkd->vkDestroyPipeline(m_vkd->device(), m_clearPipesU32.clearImg1D, nullptr); + m_vkd->vkDestroyPipeline(m_vkd->device(), m_clearPipesF32.clearImg2D, nullptr); + m_vkd->vkDestroyPipeline(m_vkd->device(), m_clearPipesU32.clearImg2D, nullptr); + m_vkd->vkDestroyPipeline(m_vkd->device(), m_clearPipesF32.clearImg3D, nullptr); + m_vkd->vkDestroyPipeline(m_vkd->device(), m_clearPipesU32.clearImg3D, nullptr); + + m_vkd->vkDestroyPipeline(m_vkd->device(), m_clearPipesF32.clearImg1DArray, nullptr); + m_vkd->vkDestroyPipeline(m_vkd->device(), m_clearPipesU32.clearImg1DArray, nullptr); + m_vkd->vkDestroyPipeline(m_vkd->device(), m_clearPipesF32.clearImg2DArray, nullptr); + m_vkd->vkDestroyPipeline(m_vkd->device(), m_clearPipesU32.clearImg2DArray, nullptr); + + // Destroy pipeline layouts + m_vkd->vkDestroyPipelineLayout(m_vkd->device(), m_clearBufPipeLayout, nullptr); + m_vkd->vkDestroyPipelineLayout(m_vkd->device(), m_clearImgPipeLayout, nullptr); + + // Destroy descriptor set layouts + m_vkd->vkDestroyDescriptorSetLayout(m_vkd->device(), m_clearBufDsetLayout, nullptr); + m_vkd->vkDestroyDescriptorSetLayout(m_vkd->device(), m_clearImgDsetLayout, nullptr); + } + + + DxvkMetaClearPipeline DxvkMetaClearObjects::getClearBufferPipeline( + DxvkFormatFlags formatFlags) const { + DxvkMetaClearPipeline result; + result.dsetLayout = m_clearBufDsetLayout; + result.pipeLayout = m_clearBufPipeLayout; + result.pipeline = m_clearPipesF32.clearBuf; + + if (formatFlags.any(DxvkFormatFlag::SampledUInt, DxvkFormatFlag::SampledSInt)) + result.pipeline = m_clearPipesU32.clearBuf; + + result.workgroupSize = VkExtent3D { 128, 1, 1 }; + return result; + } + + + DxvkMetaClearPipeline DxvkMetaClearObjects::getClearImagePipeline( + VkImageViewType viewType, + DxvkFormatFlags formatFlags) const { + const DxvkMetaClearPipelines& pipes = formatFlags.any( + DxvkFormatFlag::SampledUInt, DxvkFormatFlag::SampledSInt) + ? m_clearPipesU32 : m_clearPipesF32; + + DxvkMetaClearPipeline result; + result.dsetLayout = m_clearImgDsetLayout; + result.pipeLayout = m_clearImgPipeLayout; + + auto pipeInfo = [&pipes, viewType] () -> std::pair { + switch (viewType) { + case VK_IMAGE_VIEW_TYPE_1D: return { pipes.clearImg1D, VkExtent3D { 64, 1, 1 } }; + case VK_IMAGE_VIEW_TYPE_2D: return { pipes.clearImg2D, VkExtent3D { 8, 8, 1 } }; + case VK_IMAGE_VIEW_TYPE_3D: return { pipes.clearImg3D, VkExtent3D { 4, 4, 4 } }; + case VK_IMAGE_VIEW_TYPE_1D_ARRAY: return { pipes.clearImg1DArray, VkExtent3D { 64, 1, 1 } }; + case VK_IMAGE_VIEW_TYPE_2D_ARRAY: return { pipes.clearImg2DArray, VkExtent3D { 8, 8, 1 } }; + default: return { VkPipeline(VK_NULL_HANDLE), VkExtent3D { 0, 0, 0, } }; + } + }(); + + result.pipeline = pipeInfo.first; + result.workgroupSize = pipeInfo.second; + return result; + } + + + VkDescriptorSetLayout DxvkMetaClearObjects::createDescriptorSetLayout( + VkDescriptorType descriptorType) { + VkDescriptorSetLayoutBinding bindInfo; + bindInfo.binding = 0; + bindInfo.descriptorType = descriptorType; + bindInfo.descriptorCount = 1; + bindInfo.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; + bindInfo.pImmutableSamplers = nullptr; + + VkDescriptorSetLayoutCreateInfo dsetInfo; + dsetInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + dsetInfo.pNext = nullptr; + dsetInfo.flags = 0; + dsetInfo.bindingCount = 1; + dsetInfo.pBindings = &bindInfo; + + VkDescriptorSetLayout result = VK_NULL_HANDLE; + if (m_vkd->vkCreateDescriptorSetLayout(m_vkd->device(), + &dsetInfo, nullptr, &result) != VK_SUCCESS) + throw DxvkError("Dxvk: Failed to create meta clear descriptor set layout"); + return result; + } + + + VkPipelineLayout DxvkMetaClearObjects::createPipelineLayout( + VkDescriptorSetLayout dsetLayout) { + VkPushConstantRange pushInfo; + pushInfo.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; + pushInfo.offset = 0; + pushInfo.size = sizeof(DxvkMetaClearArgs); + + VkPipelineLayoutCreateInfo pipeInfo; + pipeInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + pipeInfo.pNext = nullptr; + pipeInfo.flags = 0; + pipeInfo.setLayoutCount = 1; + pipeInfo.pSetLayouts = &dsetLayout; + pipeInfo.pushConstantRangeCount = 1; + pipeInfo.pPushConstantRanges = &pushInfo; + + VkPipelineLayout result = VK_NULL_HANDLE; + if (m_vkd->vkCreatePipelineLayout(m_vkd->device(), + &pipeInfo, nullptr, &result) != VK_SUCCESS) + throw DxvkError("Dxvk: Failed to create meta clear pipeline layout"); + return result; + } + + + VkPipeline DxvkMetaClearObjects::createPipeline( + const SpirvCodeBuffer& spirvCode, + VkPipelineLayout pipeLayout) { + VkShaderModuleCreateInfo shaderInfo; + shaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + shaderInfo.pNext = nullptr; + shaderInfo.flags = 0; + shaderInfo.codeSize = spirvCode.size(); + shaderInfo.pCode = spirvCode.data(); + + VkShaderModule shaderModule = VK_NULL_HANDLE; + if (m_vkd->vkCreateShaderModule(m_vkd->device(), + &shaderInfo, nullptr, &shaderModule) != VK_SUCCESS) + throw DxvkError("Dxvk: Failed to create meta clear shader module"); + + VkPipelineShaderStageCreateInfo stageInfo; + stageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + stageInfo.pNext = nullptr; + stageInfo.flags = 0; + stageInfo.stage = VK_SHADER_STAGE_COMPUTE_BIT; + stageInfo.module = shaderModule; + stageInfo.pName = "main"; + stageInfo.pSpecializationInfo = nullptr; + + VkComputePipelineCreateInfo pipeInfo; + pipeInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; + pipeInfo.pNext = nullptr; + pipeInfo.flags = 0; + pipeInfo.stage = stageInfo; + pipeInfo.layout = pipeLayout; + pipeInfo.basePipelineHandle = VK_NULL_HANDLE; + pipeInfo.basePipelineIndex = -1; + + VkPipeline result = VK_NULL_HANDLE; + + const VkResult status = m_vkd->vkCreateComputePipelines( + m_vkd->device(), VK_NULL_HANDLE, 1, &pipeInfo, nullptr, &result); + + m_vkd->vkDestroyShaderModule(m_vkd->device(), shaderModule, nullptr); + + if (status != VK_SUCCESS) + throw DxvkError("Dxvk: Failed to create meta clear compute pipeline"); + return result; + } + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_clear.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_clear.h new file mode 100644 index 00000000000..eaf12adee91 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_clear.h @@ -0,0 +1,111 @@ +#pragma once + +#include "dxvk_format.h" +#include "dxvk_include.h" + +#include "../spirv/spirv_code_buffer.h" + +namespace dxvk { + + class DxvkDevice; + + /** + * \brief Clear args + * + * The data structure that can be passed + * to the clear shaders as push constants. + */ + struct DxvkMetaClearArgs { + VkClearColorValue clearValue; + VkOffset3D offset; uint32_t pad1; + VkExtent3D extent; uint32_t pad2; + }; + + + /** + * \brief Pipeline-related objects + * + * Use this to bind the pipeline + * and allocate a descriptor set. + */ + struct DxvkMetaClearPipeline { + VkDescriptorSetLayout dsetLayout; + VkPipelineLayout pipeLayout; + VkPipeline pipeline; + VkExtent3D workgroupSize; + }; + + + /** + * \brief Clear shaders and related objects + * + * Creates the shaders, pipeline layouts, and + * compute pipelines that are going to be used + * for clear operations. + */ + class DxvkMetaClearObjects { + + public: + + DxvkMetaClearObjects(const DxvkDevice* device); + ~DxvkMetaClearObjects(); + + /** + * \brief Retrieves objects to use for buffers + * + * Returns the pipeline, pipeline layout and descriptor + * set layout which are required to perform a meta clear + * operation on a buffer resource with the given format. + * \param [in] viewType The image virw type + */ + DxvkMetaClearPipeline getClearBufferPipeline( + DxvkFormatFlags formatFlags) const; + + /** + * \brief Retrieves objects for a given image view type + * + * Returns the pipeline, pipeline layout and descriptor + * set layout which are required to perform a meta clear + * operation on a resource with the given view type. + * \param [in] viewType The image virw type + * \returns The pipeline-related objects to use + */ + DxvkMetaClearPipeline getClearImagePipeline( + VkImageViewType viewType, + DxvkFormatFlags formatFlags) const; + + private: + + struct DxvkMetaClearPipelines { + VkPipeline clearBuf = VK_NULL_HANDLE; + VkPipeline clearImg1D = VK_NULL_HANDLE; + VkPipeline clearImg2D = VK_NULL_HANDLE; + VkPipeline clearImg3D = VK_NULL_HANDLE; + VkPipeline clearImg1DArray = VK_NULL_HANDLE; + VkPipeline clearImg2DArray = VK_NULL_HANDLE; + }; + + Rc m_vkd; + + VkDescriptorSetLayout m_clearBufDsetLayout = VK_NULL_HANDLE; + VkDescriptorSetLayout m_clearImgDsetLayout = VK_NULL_HANDLE; + + VkPipelineLayout m_clearBufPipeLayout = VK_NULL_HANDLE; + VkPipelineLayout m_clearImgPipeLayout = VK_NULL_HANDLE; + + DxvkMetaClearPipelines m_clearPipesF32; + DxvkMetaClearPipelines m_clearPipesU32; + + VkDescriptorSetLayout createDescriptorSetLayout( + VkDescriptorType descriptorType); + + VkPipelineLayout createPipelineLayout( + VkDescriptorSetLayout dsetLayout); + + VkPipeline createPipeline( + const SpirvCodeBuffer& spirvCode, + VkPipelineLayout pipeLayout); + + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_copy.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_copy.cpp new file mode 100644 index 00000000000..ed79bb4aeac --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_copy.cpp @@ -0,0 +1,695 @@ +#include "dxvk_device.h" +#include "dxvk_meta_copy.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace dxvk { + + DxvkMetaCopyRenderPass::DxvkMetaCopyRenderPass( + const Rc& vkd, + const Rc& dstImageView, + const Rc& srcImageView, + const Rc& srcStencilView, + bool discardDst) + : m_vkd (vkd), + m_dstImageView (dstImageView), + m_srcImageView (srcImageView), + m_srcStencilView(srcStencilView), + m_renderPass (createRenderPass(discardDst)), + m_framebuffer (createFramebuffer()) { + + } + + + DxvkMetaCopyRenderPass::~DxvkMetaCopyRenderPass() { + m_vkd->vkDestroyFramebuffer(m_vkd->device(), m_framebuffer, nullptr); + m_vkd->vkDestroyRenderPass (m_vkd->device(), m_renderPass, nullptr); + } + + + VkRenderPass DxvkMetaCopyRenderPass::createRenderPass(bool discard) const { + auto aspect = m_dstImageView->info().aspect; + + VkPipelineStageFlags cpyStages = 0; + VkAccessFlags cpyAccess = 0; + + VkAttachmentDescription attachment; + attachment.flags = 0; + attachment.format = m_dstImageView->info().format; + attachment.samples = m_dstImageView->imageInfo().sampleCount; + attachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; + attachment.initialLayout = m_dstImageView->imageInfo().layout; + attachment.finalLayout = m_dstImageView->imageInfo().layout; + + if (discard) { + attachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + } + + VkAttachmentReference attachmentRef; + attachmentRef.attachment = 0; + attachmentRef.layout = (aspect & VK_IMAGE_ASPECT_COLOR_BIT) + ? m_dstImageView->pickLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) + : m_dstImageView->pickLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + + VkSubpassDescription subpass; + subpass.flags = 0; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.inputAttachmentCount = 0; + subpass.pInputAttachments = nullptr; + subpass.colorAttachmentCount = 0; + subpass.pColorAttachments = nullptr; + subpass.pResolveAttachments = nullptr; + subpass.pDepthStencilAttachment = nullptr; + subpass.preserveAttachmentCount = 0; + subpass.pPreserveAttachments = nullptr; + + if (aspect & VK_IMAGE_ASPECT_COLOR_BIT) { + subpass.colorAttachmentCount = 1; + subpass.pColorAttachments = &attachmentRef; + + cpyStages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + cpyAccess |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + + if (!discard) + cpyAccess |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; + } else { + subpass.pDepthStencilAttachment = &attachmentRef; + + cpyStages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT + | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + cpyAccess |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + + if (!discard) + cpyAccess |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; + } + + // We have to be somewhat conservative here since we cannot assume + // that the backend blocks stages that are only used for meta ops + VkPipelineStageFlags extStages = m_dstImageView->imageInfo().stages | m_srcImageView->imageInfo().stages; + VkAccessFlags extAccess = m_dstImageView->imageInfo().access; + + std::array dependencies = {{ + { VK_SUBPASS_EXTERNAL, 0, extStages, cpyStages, 0, cpyAccess, 0 }, + { 0, VK_SUBPASS_EXTERNAL, cpyStages, extStages, cpyAccess, extAccess, 0 }, + }}; + + VkRenderPassCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.attachmentCount = 1; + info.pAttachments = &attachment; + info.subpassCount = 1; + info.pSubpasses = &subpass; + info.dependencyCount = dependencies.size(); + info.pDependencies = dependencies.data(); + + VkRenderPass result = VK_NULL_HANDLE; + if (m_vkd->vkCreateRenderPass(m_vkd->device(), &info, nullptr, &result) != VK_SUCCESS) + throw DxvkError("DxvkMetaCopyRenderPass: Failed to create render pass"); + return result; + } + + + VkFramebuffer DxvkMetaCopyRenderPass::createFramebuffer() const { + VkImageView dstViewHandle = m_dstImageView->handle(); + VkImageSubresourceRange dstSubresources = m_dstImageView->subresources(); + VkExtent3D dstExtent = m_dstImageView->mipLevelExtent(0); + + VkFramebufferCreateInfo fboInfo; + fboInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + fboInfo.pNext = nullptr; + fboInfo.flags = 0; + fboInfo.renderPass = m_renderPass; + fboInfo.attachmentCount = 1; + fboInfo.pAttachments = &dstViewHandle; + fboInfo.width = dstExtent.width; + fboInfo.height = dstExtent.height; + fboInfo.layers = dstSubresources.layerCount; + + VkFramebuffer result = VK_NULL_HANDLE; + if (m_vkd->vkCreateFramebuffer(m_vkd->device(), &fboInfo, nullptr, &result) != VK_SUCCESS) + throw DxvkError("DxvkMetaCopyRenderPass: Failed to create target framebuffer"); + return result; + } + + + DxvkMetaCopyObjects::DxvkMetaCopyObjects(const DxvkDevice* device) + : m_vkd (device->vkd()), + m_sampler (createSampler()), + m_color { + createShaderModule(dxvk_copy_color_1d), + createShaderModule(dxvk_copy_color_2d), + createShaderModule(dxvk_copy_color_ms) }, + m_depth { + createShaderModule(dxvk_copy_depth_1d), + createShaderModule(dxvk_copy_depth_2d), + createShaderModule(dxvk_copy_depth_ms) } { + if (device->extensions().extShaderViewportIndexLayer) { + m_shaderVert = createShaderModule(dxvk_fullscreen_layer_vert); + } else { + m_shaderVert = createShaderModule(dxvk_fullscreen_vert); + m_shaderGeom = createShaderModule(dxvk_fullscreen_geom); + } + + if (device->extensions().extShaderStencilExport) { + m_depthStencil = { + createShaderModule(dxvk_copy_depth_stencil_1d), + createShaderModule(dxvk_copy_depth_stencil_2d), + createShaderModule(dxvk_copy_depth_stencil_ms) }; + } + } + + + DxvkMetaCopyObjects::~DxvkMetaCopyObjects() { + m_vkd->vkDestroyPipeline(m_vkd->device(), m_copyBufferImagePipeline.pipeHandle, nullptr); + m_vkd->vkDestroyPipelineLayout(m_vkd->device(), m_copyBufferImagePipeline.pipeLayout, nullptr); + m_vkd->vkDestroyDescriptorSetLayout(m_vkd->device(), m_copyBufferImagePipeline.dsetLayout, nullptr); + + for (const auto& pair : m_pipelines) { + m_vkd->vkDestroyPipeline(m_vkd->device(), pair.second.pipeHandle, nullptr); + m_vkd->vkDestroyPipelineLayout(m_vkd->device(), pair.second.pipeLayout, nullptr); + m_vkd->vkDestroyDescriptorSetLayout (m_vkd->device(), pair.second.dsetLayout, nullptr); + m_vkd->vkDestroyRenderPass(m_vkd->device(), pair.second.renderPass, nullptr); + } + + m_vkd->vkDestroyShaderModule(m_vkd->device(), m_depthStencil.fragMs, nullptr); + m_vkd->vkDestroyShaderModule(m_vkd->device(), m_depthStencil.frag2D, nullptr); + m_vkd->vkDestroyShaderModule(m_vkd->device(), m_depthStencil.frag1D, nullptr); + m_vkd->vkDestroyShaderModule(m_vkd->device(), m_depth.fragMs, nullptr); + m_vkd->vkDestroyShaderModule(m_vkd->device(), m_depth.frag2D, nullptr); + m_vkd->vkDestroyShaderModule(m_vkd->device(), m_depth.frag1D, nullptr); + m_vkd->vkDestroyShaderModule(m_vkd->device(), m_color.fragMs, nullptr); + m_vkd->vkDestroyShaderModule(m_vkd->device(), m_color.frag2D, nullptr); + m_vkd->vkDestroyShaderModule(m_vkd->device(), m_color.frag1D, nullptr); + m_vkd->vkDestroyShaderModule(m_vkd->device(), m_shaderGeom, nullptr); + m_vkd->vkDestroyShaderModule(m_vkd->device(), m_shaderVert, nullptr); + + m_vkd->vkDestroySampler(m_vkd->device(), m_sampler, nullptr); + } + + + VkFormat DxvkMetaCopyObjects::getCopyDestinationFormat( + VkImageAspectFlags dstAspect, + VkImageAspectFlags srcAspect, + VkFormat srcFormat) const { + if (srcAspect == dstAspect) + return srcFormat; + + if (dstAspect == VK_IMAGE_ASPECT_COLOR_BIT + && srcAspect == VK_IMAGE_ASPECT_DEPTH_BIT) { + switch (srcFormat) { + case VK_FORMAT_D16_UNORM: return VK_FORMAT_R16_UNORM; + case VK_FORMAT_D32_SFLOAT: return VK_FORMAT_R32_SFLOAT; + default: return VK_FORMAT_UNDEFINED; + } + } + + if (dstAspect == VK_IMAGE_ASPECT_DEPTH_BIT + && srcAspect == VK_IMAGE_ASPECT_COLOR_BIT) { + switch (srcFormat) { + case VK_FORMAT_R16_UNORM: return VK_FORMAT_D16_UNORM; + case VK_FORMAT_R32_SFLOAT: return VK_FORMAT_D32_SFLOAT; + default: return VK_FORMAT_UNDEFINED; + } + } + + return VK_FORMAT_UNDEFINED; + } + + + DxvkMetaCopyPipeline DxvkMetaCopyObjects::getPipeline( + VkImageViewType viewType, + VkFormat dstFormat, + VkSampleCountFlagBits dstSamples) { + std::lock_guard lock(m_mutex); + + DxvkMetaCopyPipelineKey key; + key.viewType = viewType; + key.format = dstFormat; + key.samples = dstSamples; + + auto entry = m_pipelines.find(key); + if (entry != m_pipelines.end()) + return entry->second; + + DxvkMetaCopyPipeline pipeline = createPipeline(key); + m_pipelines.insert({ key, pipeline }); + return pipeline; + } + + + DxvkMetaCopyPipeline DxvkMetaCopyObjects::getCopyBufferImagePipeline() { + std::lock_guard lock(m_mutex); + + if (!m_copyBufferImagePipeline.pipeHandle) + m_copyBufferImagePipeline = createCopyBufferImagePipeline(); + + return m_copyBufferImagePipeline; + } + + + VkSampler DxvkMetaCopyObjects::createSampler() const { + VkSamplerCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.magFilter = VK_FILTER_NEAREST; + info.minFilter = VK_FILTER_NEAREST; + info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; + info.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + info.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + info.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + info.mipLodBias = 0.0f; + info.anisotropyEnable = VK_FALSE; + info.maxAnisotropy = 1.0f; + info.compareEnable = VK_FALSE; + info.compareOp = VK_COMPARE_OP_ALWAYS; + info.minLod = 0.0f; + info.maxLod = 0.0f; + info.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; + info.unnormalizedCoordinates = VK_FALSE; + + VkSampler result = VK_NULL_HANDLE; + if (m_vkd->vkCreateSampler(m_vkd->device(), &info, nullptr, &result) != VK_SUCCESS) + throw DxvkError("DxvkMetaCopyObjects: Failed to create sampler"); + return result; + } + + + VkShaderModule DxvkMetaCopyObjects::createShaderModule( + const SpirvCodeBuffer& code) const { + VkShaderModuleCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.codeSize = code.size(); + info.pCode = code.data(); + + VkShaderModule result = VK_NULL_HANDLE; + if (m_vkd->vkCreateShaderModule(m_vkd->device(), &info, nullptr, &result) != VK_SUCCESS) + throw DxvkError("DxvkMetaCopyObjects: Failed to create shader module"); + return result; + } + + + DxvkMetaCopyPipeline DxvkMetaCopyObjects::createCopyBufferImagePipeline() { + DxvkMetaCopyPipeline pipeline; + pipeline.renderPass = VK_NULL_HANDLE; + + std::array bindings = {{ + { 0, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr }, + { 1, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr }, + }}; + + VkDescriptorSetLayoutCreateInfo setLayoutInfo; + setLayoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + setLayoutInfo.pNext = nullptr; + setLayoutInfo.flags = 0; + setLayoutInfo.bindingCount = bindings.size(); + setLayoutInfo.pBindings = bindings.data(); + + if (m_vkd->vkCreateDescriptorSetLayout(m_vkd->device(), &setLayoutInfo, nullptr, &pipeline.dsetLayout) != VK_SUCCESS) + throw DxvkError("DxvkMetaCopyObjects: Failed to create descriptor set layout"); + + VkPushConstantRange pushRange = { VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(DxvkCopyBufferImageArgs) }; + + VkPipelineLayoutCreateInfo pipelineLayoutInfo; + pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + pipelineLayoutInfo.pNext = nullptr; + pipelineLayoutInfo.flags = 0; + pipelineLayoutInfo.setLayoutCount = 1; + pipelineLayoutInfo.pSetLayouts = &pipeline.dsetLayout; + pipelineLayoutInfo.pushConstantRangeCount = 1; + pipelineLayoutInfo.pPushConstantRanges = &pushRange; + + if (m_vkd->vkCreatePipelineLayout(m_vkd->device(), &pipelineLayoutInfo, nullptr, &pipeline.pipeLayout) != VK_SUCCESS) + throw DxvkError("DxvkMetaCopyObjects: Failed to create pipeline layout"); + + VkShaderModule shaderModule = createShaderModule(dxvk_copy_buffer_image); + + VkComputePipelineCreateInfo pipelineInfo; + pipelineInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; + pipelineInfo.pNext = nullptr; + pipelineInfo.flags = 0; + pipelineInfo.layout = pipeline.pipeLayout; + pipelineInfo.stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + pipelineInfo.stage.pNext = nullptr; + pipelineInfo.stage.flags = 0; + pipelineInfo.stage.stage = VK_SHADER_STAGE_COMPUTE_BIT; + pipelineInfo.stage.module = shaderModule; + pipelineInfo.stage.pName = "main"; + pipelineInfo.stage.pSpecializationInfo = nullptr; + pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; + pipelineInfo.basePipelineIndex = -1; + + if (m_vkd->vkCreateComputePipelines(m_vkd->device(), VK_NULL_HANDLE, + 1, &pipelineInfo, nullptr, &pipeline.pipeHandle) != VK_SUCCESS) + throw DxvkError("DxvkMetaCopyObjects: Failed to create compute pipeline"); + + m_vkd->vkDestroyShaderModule(m_vkd->device(), shaderModule, nullptr); + return pipeline; + } + + + DxvkMetaCopyPipeline DxvkMetaCopyObjects::createPipeline( + const DxvkMetaCopyPipelineKey& key) { + DxvkMetaCopyPipeline pipeline; + pipeline.renderPass = this->createRenderPass(key); + pipeline.dsetLayout = this->createDescriptorSetLayout(key); + pipeline.pipeLayout = this->createPipelineLayout(pipeline.dsetLayout); + pipeline.pipeHandle = this->createPipelineObject(key, pipeline.pipeLayout, pipeline.renderPass); + return pipeline; + } + + + VkRenderPass DxvkMetaCopyObjects::createRenderPass( + const DxvkMetaCopyPipelineKey& key) const { + auto aspect = imageFormatInfo(key.format)->aspectMask; + + VkAttachmentDescription attachment; + attachment.flags = 0; + attachment.format = key.format; + attachment.samples = key.samples; + attachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; + attachment.initialLayout = VK_IMAGE_LAYOUT_GENERAL; + attachment.finalLayout = VK_IMAGE_LAYOUT_GENERAL; + + VkAttachmentReference attachmentRef; + attachmentRef.attachment = 0; + attachmentRef.layout = (aspect & VK_IMAGE_ASPECT_COLOR_BIT) + ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL + : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + VkSubpassDescription subpass; + subpass.flags = 0; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.inputAttachmentCount = 0; + subpass.pInputAttachments = nullptr; + subpass.colorAttachmentCount = 0; + subpass.pColorAttachments = nullptr; + subpass.pResolveAttachments = nullptr; + subpass.pDepthStencilAttachment = nullptr; + subpass.preserveAttachmentCount = 0; + subpass.pPreserveAttachments = nullptr; + + if (aspect & VK_IMAGE_ASPECT_COLOR_BIT) { + subpass.colorAttachmentCount = 1; + subpass.pColorAttachments = &attachmentRef; + } else { + subpass.pDepthStencilAttachment = &attachmentRef; + } + + VkRenderPassCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.attachmentCount = 1; + info.pAttachments = &attachment; + info.subpassCount = 1; + info.pSubpasses = &subpass; + info.dependencyCount = 0; + info.pDependencies = nullptr; + + VkRenderPass result = VK_NULL_HANDLE; + if (m_vkd->vkCreateRenderPass(m_vkd->device(), &info, nullptr, &result) != VK_SUCCESS) + throw DxvkError("DxvkMetaCopyObjects: Failed to create render pass"); + return result; + } + + + VkDescriptorSetLayout DxvkMetaCopyObjects::createDescriptorSetLayout( + const DxvkMetaCopyPipelineKey& key) const { + std::array bindings; + + for (uint32_t i = 0; i < 2; i++) { + bindings[i].binding = i; + bindings[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + bindings[i].descriptorCount = 1; + bindings[i].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + bindings[i].pImmutableSamplers = &m_sampler; + } + + VkDescriptorSetLayoutCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.bindingCount = 1; + info.pBindings = bindings.data(); + + auto format = imageFormatInfo(key.format); + + if (format->aspectMask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) + info.bindingCount = 2; + + VkDescriptorSetLayout result = VK_NULL_HANDLE; + if (m_vkd->vkCreateDescriptorSetLayout(m_vkd->device(), &info, nullptr, &result) != VK_SUCCESS) + throw DxvkError("DxvkMetaCopyObjects: Failed to create descriptor set layout"); + return result; + } + + + VkPipelineLayout DxvkMetaCopyObjects::createPipelineLayout( + VkDescriptorSetLayout descriptorSetLayout) const { + VkPushConstantRange push; + push.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + push.offset = 0; + push.size = sizeof(VkOffset2D); + + VkPipelineLayoutCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.setLayoutCount = 1; + info.pSetLayouts = &descriptorSetLayout; + info.pushConstantRangeCount = 1; + info.pPushConstantRanges = &push; + + VkPipelineLayout result = VK_NULL_HANDLE; + if (m_vkd->vkCreatePipelineLayout(m_vkd->device(), &info, nullptr, &result) != VK_SUCCESS) + throw DxvkError("DxvkMetaCopyObjects: Failed to create pipeline layout"); + return result; + } + + + VkPipeline DxvkMetaCopyObjects::createPipelineObject( + const DxvkMetaCopyPipelineKey& key, + VkPipelineLayout pipelineLayout, + VkRenderPass renderPass) { + auto aspect = imageFormatInfo(key.format)->aspectMask; + + std::array stages; + uint32_t stageCount = 0; + + VkPipelineShaderStageCreateInfo& vsStage = stages[stageCount++]; + vsStage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + vsStage.pNext = nullptr; + vsStage.flags = 0; + vsStage.stage = VK_SHADER_STAGE_VERTEX_BIT; + vsStage.module = m_shaderVert; + vsStage.pName = "main"; + vsStage.pSpecializationInfo = nullptr; + + if (m_shaderGeom) { + VkPipelineShaderStageCreateInfo& gsStage = stages[stageCount++]; + gsStage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + gsStage.pNext = nullptr; + gsStage.flags = 0; + gsStage.stage = VK_SHADER_STAGE_GEOMETRY_BIT; + gsStage.module = m_shaderGeom; + gsStage.pName = "main"; + gsStage.pSpecializationInfo = nullptr; + } + + VkPipelineShaderStageCreateInfo& psStage = stages[stageCount++]; + psStage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + psStage.pNext = nullptr; + psStage.flags = 0; + psStage.stage = VK_SHADER_STAGE_FRAGMENT_BIT; + psStage.module = VK_NULL_HANDLE; + psStage.pName = "main"; + psStage.pSpecializationInfo = nullptr; + + std::array, 3> shaderSets = {{ + { &m_color, VK_IMAGE_ASPECT_COLOR_BIT }, + { &m_depth, VK_IMAGE_ASPECT_DEPTH_BIT }, + { &m_depthStencil, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT }, + }}; + + const FragShaders* shaderSet = nullptr; + + for (const auto& pair : shaderSets) { + if (pair.second == aspect) + shaderSet = pair.first; + } + + if (!shaderSet) + throw DxvkError("DxvkMetaCopyObjects: Unsupported aspect mask"); + + if (key.viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY) + psStage.module = shaderSet->frag1D; + else if (key.samples == VK_SAMPLE_COUNT_1_BIT) + psStage.module = shaderSet->frag2D; + else + psStage.module = shaderSet->fragMs; + + std::array dynStates = {{ + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR, + }}; + + VkPipelineDynamicStateCreateInfo dynState; + dynState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; + dynState.pNext = nullptr; + dynState.flags = 0; + dynState.dynamicStateCount = dynStates.size(); + dynState.pDynamicStates = dynStates.data(); + + VkPipelineVertexInputStateCreateInfo viState; + viState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + viState.pNext = nullptr; + viState.flags = 0; + viState.vertexBindingDescriptionCount = 0; + viState.pVertexBindingDescriptions = nullptr; + viState.vertexAttributeDescriptionCount = 0; + viState.pVertexAttributeDescriptions = nullptr; + + VkPipelineInputAssemblyStateCreateInfo iaState; + iaState.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + iaState.pNext = nullptr; + iaState.flags = 0; + iaState.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + iaState.primitiveRestartEnable = VK_FALSE; + + VkPipelineViewportStateCreateInfo vpState; + vpState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + vpState.pNext = nullptr; + vpState.flags = 0; + vpState.viewportCount = 1; + vpState.pViewports = nullptr; + vpState.scissorCount = 1; + vpState.pScissors = nullptr; + + VkPipelineRasterizationStateCreateInfo rsState; + rsState.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + rsState.pNext = nullptr; + rsState.flags = 0; + rsState.depthClampEnable = VK_TRUE; + rsState.rasterizerDiscardEnable = VK_FALSE; + rsState.polygonMode = VK_POLYGON_MODE_FILL; + rsState.cullMode = VK_CULL_MODE_NONE; + rsState.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; + rsState.depthBiasEnable = VK_FALSE; + rsState.depthBiasConstantFactor = 0.0f; + rsState.depthBiasClamp = 0.0f; + rsState.depthBiasSlopeFactor = 0.0f; + rsState.lineWidth = 1.0f; + + uint32_t msMask = 0xFFFFFFFF; + VkPipelineMultisampleStateCreateInfo msState; + msState.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + msState.pNext = nullptr; + msState.flags = 0; + msState.rasterizationSamples = key.samples; + msState.sampleShadingEnable = key.samples != VK_SAMPLE_COUNT_1_BIT; + msState.minSampleShading = 1.0f; + msState.pSampleMask = &msMask; + msState.alphaToCoverageEnable = VK_FALSE; + msState.alphaToOneEnable = VK_FALSE; + + VkPipelineColorBlendAttachmentState cbAttachment; + cbAttachment.blendEnable = VK_FALSE; + cbAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; + cbAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; + cbAttachment.colorBlendOp = VK_BLEND_OP_ADD; + cbAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; + cbAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; + cbAttachment.alphaBlendOp = VK_BLEND_OP_ADD; + cbAttachment.colorWriteMask = + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | + VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + + VkPipelineColorBlendStateCreateInfo cbState; + cbState.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + cbState.pNext = nullptr; + cbState.flags = 0; + cbState.logicOpEnable = VK_FALSE; + cbState.logicOp = VK_LOGIC_OP_NO_OP; + cbState.attachmentCount = 1; + cbState.pAttachments = &cbAttachment; + + for (uint32_t i = 0; i < 4; i++) + cbState.blendConstants[i] = 0.0f; + + VkStencilOpState stencilOp; + stencilOp.failOp = VK_STENCIL_OP_REPLACE; + stencilOp.passOp = VK_STENCIL_OP_REPLACE; + stencilOp.depthFailOp = VK_STENCIL_OP_REPLACE; + stencilOp.compareOp = VK_COMPARE_OP_ALWAYS; + stencilOp.compareMask = 0xFFFFFFFF; + stencilOp.writeMask = 0xFFFFFFFF; + stencilOp.reference = 0; + + VkPipelineDepthStencilStateCreateInfo dsState; + dsState.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + dsState.pNext = nullptr; + dsState.flags = 0; + dsState.depthTestEnable = VK_TRUE; + dsState.depthWriteEnable = VK_TRUE; + dsState.depthCompareOp = VK_COMPARE_OP_ALWAYS; + dsState.depthBoundsTestEnable = VK_FALSE; + dsState.stencilTestEnable = VK_TRUE; + dsState.front = stencilOp; + dsState.back = stencilOp; + dsState.minDepthBounds = 0.0f; + dsState.maxDepthBounds = 1.0f; + + VkGraphicsPipelineCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.stageCount = stageCount; + info.pStages = stages.data(); + info.pVertexInputState = &viState; + info.pInputAssemblyState = &iaState; + info.pTessellationState = nullptr; + info.pViewportState = &vpState; + info.pRasterizationState = &rsState; + info.pMultisampleState = &msState; + info.pColorBlendState = (aspect & VK_IMAGE_ASPECT_COLOR_BIT) ? &cbState : nullptr; + info.pDepthStencilState = (aspect & VK_IMAGE_ASPECT_COLOR_BIT) ? nullptr : &dsState; + info.pDynamicState = &dynState; + info.layout = pipelineLayout; + info.renderPass = renderPass; + info.subpass = 0; + info.basePipelineHandle = VK_NULL_HANDLE; + info.basePipelineIndex = -1; + + VkPipeline result = VK_NULL_HANDLE; + if (m_vkd->vkCreateGraphicsPipelines(m_vkd->device(), VK_NULL_HANDLE, 1, &info, nullptr, &result) != VK_SUCCESS) + throw DxvkError("DxvkMetaCopyObjects: Failed to create graphics pipeline"); + return result; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_copy.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_copy.h new file mode 100644 index 00000000000..c80b7f797cc --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_copy.h @@ -0,0 +1,209 @@ +#pragma once + +#include +#include + +#include "../spirv/spirv_code_buffer.h" + +#include "dxvk_barrier.h" +#include "dxvk_cmdlist.h" +#include "dxvk_hash.h" +#include "dxvk_resource.h" + +namespace dxvk { + + class DxvkDevice; + + /** + * \brief Push constants for buffer image copies + */ + struct DxvkCopyBufferImageArgs { + VkOffset3D dstOffset; uint32_t pad0; + VkOffset3D srcOffset; uint32_t pad1; + VkExtent3D extent; uint32_t pad2; + VkExtent2D dstSize; + VkExtent2D srcSize; + }; + + /** + * \brief Copy pipeline + * + * Stores the objects for a single pipeline + * that is used for fragment shader copies. + */ + struct DxvkMetaCopyPipeline { + VkRenderPass renderPass; + VkDescriptorSetLayout dsetLayout; + VkPipelineLayout pipeLayout; + VkPipeline pipeHandle; + }; + + /** + * \brief Copy pipeline key + * + * Used to look up copy pipelines based + * on the copy operation they support. + */ + struct DxvkMetaCopyPipelineKey { + VkImageViewType viewType; + VkFormat format; + VkSampleCountFlagBits samples; + + bool eq(const DxvkMetaCopyPipelineKey& other) const { + return this->viewType == other.viewType + && this->format == other.format + && this->samples == other.samples; + } + + size_t hash() const { + return (uint32_t(format) << 8) + ^ (uint32_t(samples) << 4) + ^ (uint32_t(viewType)); + } + }; + + /** + * \brief Copy framebuffer and render pass + * + * Creates a framebuffer and render + * pass object for an image view. + */ + class DxvkMetaCopyRenderPass : public DxvkResource { + + public: + + DxvkMetaCopyRenderPass( + const Rc& vkd, + const Rc& dstImageView, + const Rc& srcImageView, + const Rc& srcStencilView, + bool discardDst); + + ~DxvkMetaCopyRenderPass(); + + VkRenderPass renderPass() const { + return m_renderPass; + } + + VkFramebuffer framebuffer() const { + return m_framebuffer; + } + + private: + + Rc m_vkd; + + Rc m_dstImageView; + Rc m_srcImageView; + Rc m_srcStencilView; + + VkRenderPass m_renderPass = VK_NULL_HANDLE; + VkFramebuffer m_framebuffer = VK_NULL_HANDLE; + + VkRenderPass createRenderPass(bool discard) const; + + VkFramebuffer createFramebuffer() const; + + }; + + /** + * \brief Meta copy objects + * + * Meta copy operations are necessary in order + * to copy data between color and depth images. + */ + class DxvkMetaCopyObjects { + + public: + + DxvkMetaCopyObjects(const DxvkDevice* device); + ~DxvkMetaCopyObjects(); + + /** + * \brief Queries color format for d->c copies + * + * Returns the color format that we need to use + * as the destination image view format in case + * of depth to color image copies. + * \param [in] format Depth format + * \returns Corresponding color format + */ + VkFormat getCopyDestinationFormat( + VkImageAspectFlags dstAspect, + VkImageAspectFlags srcAspect, + VkFormat srcFormat) const; + + /** + * \brief Creates pipeline for meta copy operation + * + * \param [in] viewType Image view type + * \param [in] dstFormat Destination image format + * \param [in] dstSamples Destination sample count + * \returns Compatible pipeline for the operation + */ + DxvkMetaCopyPipeline getPipeline( + VkImageViewType viewType, + VkFormat dstFormat, + VkSampleCountFlagBits dstSamples); + + /** + * \brief Creates pipeline for buffer image copy + * \returns Compute pipeline for buffer image copies + */ + DxvkMetaCopyPipeline getCopyBufferImagePipeline(); + + private: + + struct FragShaders { + VkShaderModule frag1D = VK_NULL_HANDLE; + VkShaderModule frag2D = VK_NULL_HANDLE; + VkShaderModule fragMs = VK_NULL_HANDLE; + }; + + Rc m_vkd; + + VkSampler m_sampler; + + VkShaderModule m_shaderVert = VK_NULL_HANDLE; + VkShaderModule m_shaderGeom = VK_NULL_HANDLE; + + FragShaders m_color; + FragShaders m_depth; + FragShaders m_depthStencil; + + dxvk::mutex m_mutex; + + std::unordered_map< + DxvkMetaCopyPipelineKey, + DxvkMetaCopyPipeline, + DxvkHash, DxvkEq> m_pipelines; + + DxvkMetaCopyPipeline m_copyBufferImagePipeline = { }; + + VkSampler createSampler() const; + + VkShaderModule createShaderModule( + const SpirvCodeBuffer& code) const; + + DxvkMetaCopyPipeline createCopyBufferImagePipeline(); + + DxvkMetaCopyPipeline createPipeline( + const DxvkMetaCopyPipelineKey& key); + + VkRenderPass createRenderPass( + const DxvkMetaCopyPipelineKey& key) const; + + VkDescriptorSetLayout createDescriptorSetLayout( + const DxvkMetaCopyPipelineKey& key) const; + + VkPipelineLayout createPipelineLayout( + VkDescriptorSetLayout descriptorSetLayout) const; + + VkPipeline createPipelineObject( + const DxvkMetaCopyPipelineKey& key, + VkPipelineLayout pipelineLayout, + VkRenderPass renderPass); + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_mipgen.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_mipgen.cpp new file mode 100644 index 00000000000..297da07e750 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_mipgen.cpp @@ -0,0 +1,181 @@ +#include "dxvk_meta_mipgen.h" + +namespace dxvk { + + DxvkMetaMipGenRenderPass::DxvkMetaMipGenRenderPass( + const Rc& vkd, + const Rc& view) + : m_vkd(vkd), m_view(view), m_renderPass(createRenderPass()) { + // Determine view type based on image type + const std::array, 3> viewTypes = {{ + { VK_IMAGE_VIEW_TYPE_1D_ARRAY, VK_IMAGE_VIEW_TYPE_1D_ARRAY }, + { VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_IMAGE_VIEW_TYPE_2D_ARRAY }, + { VK_IMAGE_VIEW_TYPE_3D, VK_IMAGE_VIEW_TYPE_2D_ARRAY }, + }}; + + m_srcViewType = viewTypes.at(uint32_t(view->imageInfo().type)).first; + m_dstViewType = viewTypes.at(uint32_t(view->imageInfo().type)).second; + + // Create image views and framebuffers + m_passes.resize(view->info().numLevels - 1); + + for (uint32_t i = 0; i < m_passes.size(); i++) + m_passes.at(i) = this->createFramebuffer(i); + } + + + DxvkMetaMipGenRenderPass::~DxvkMetaMipGenRenderPass() { + for (const auto& pass : m_passes) { + m_vkd->vkDestroyFramebuffer(m_vkd->device(), pass.framebuffer, nullptr); + m_vkd->vkDestroyImageView(m_vkd->device(), pass.dstView, nullptr); + m_vkd->vkDestroyImageView(m_vkd->device(), pass.srcView, nullptr); + } + + m_vkd->vkDestroyRenderPass(m_vkd->device(), m_renderPass, nullptr); + } + + + VkExtent3D DxvkMetaMipGenRenderPass::passExtent(uint32_t passId) const { + VkExtent3D extent = m_view->mipLevelExtent(passId + 1); + + if (m_view->imageInfo().type != VK_IMAGE_TYPE_3D) + extent.depth = m_view->info().numLayers; + + return extent; + } + + + VkRenderPass DxvkMetaMipGenRenderPass::createRenderPass() const { + std::array subpassDeps = {{ + { VK_SUBPASS_EXTERNAL, 0, + m_view->imageInfo().stages, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + 0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 0 }, + { 0, VK_SUBPASS_EXTERNAL, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + m_view->imageInfo().stages, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + m_view->imageInfo().access, 0 }, + }}; + + VkAttachmentDescription attachment; + attachment.flags = 0; + attachment.format = m_view->info().format; + attachment.samples = VK_SAMPLE_COUNT_1_BIT; + attachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + attachment.finalLayout = m_view->imageInfo().layout; + + VkAttachmentReference attachmentRef; + attachmentRef.attachment = 0; + attachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + VkSubpassDescription subpass; + subpass.flags = 0; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.inputAttachmentCount = 0; + subpass.pInputAttachments = nullptr; + subpass.colorAttachmentCount = 1; + subpass.pColorAttachments = &attachmentRef; + subpass.pResolveAttachments = nullptr; + subpass.pDepthStencilAttachment = nullptr; + subpass.preserveAttachmentCount = 0; + subpass.pPreserveAttachments = nullptr; + + VkRenderPassCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.attachmentCount = 1; + info.pAttachments = &attachment; + info.subpassCount = 1; + info.pSubpasses = &subpass; + info.dependencyCount = subpassDeps.size(); + info.pDependencies = subpassDeps.data(); + + VkRenderPass result = VK_NULL_HANDLE; + if (m_vkd->vkCreateRenderPass(m_vkd->device(), &info, nullptr, &result) != VK_SUCCESS) + throw DxvkError("DxvkMetaMipGenRenderPass: Failed to create render pass"); + return result; + } + + + DxvkMetaBlitPass DxvkMetaMipGenRenderPass::createFramebuffer(uint32_t pass) const { + DxvkMetaBlitPass result; + result.srcView = VK_NULL_HANDLE; + result.dstView = VK_NULL_HANDLE; + result.renderPass = m_renderPass; + result.framebuffer = VK_NULL_HANDLE; + + // Common image view info + VkImageViewCreateInfo viewInfo; + viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + viewInfo.pNext = nullptr; + viewInfo.flags = 0; + viewInfo.image = m_view->imageHandle(); + viewInfo.format = m_view->info().format; + viewInfo.components = { + VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, + VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY }; + + // Create source image view, which points to + // the one mip level we're going to sample. + VkImageSubresourceRange srcSubresources; + srcSubresources.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + srcSubresources.baseMipLevel = m_view->info().minLevel + pass; + srcSubresources.levelCount = 1; + srcSubresources.baseArrayLayer = m_view->info().minLayer; + srcSubresources.layerCount = m_view->info().numLayers; + + viewInfo.viewType = m_srcViewType; + viewInfo.subresourceRange = srcSubresources; + + if (m_vkd->vkCreateImageView(m_vkd->device(), &viewInfo, nullptr, &result.srcView) != VK_SUCCESS) + throw DxvkError("DxvkMetaMipGenRenderPass: Failed to create source image view"); + + // Create destination image view, which points + // to the mip level we're going to render to. + VkExtent3D dstExtent = m_view->mipLevelExtent(pass + 1); + + VkImageSubresourceRange dstSubresources; + dstSubresources.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + dstSubresources.baseMipLevel = m_view->info().minLevel + pass + 1; + dstSubresources.levelCount = 1; + + if (m_view->imageInfo().type != VK_IMAGE_TYPE_3D) { + dstSubresources.baseArrayLayer = m_view->info().minLayer; + dstSubresources.layerCount = m_view->info().numLayers; + } else { + dstSubresources.baseArrayLayer = 0; + dstSubresources.layerCount = dstExtent.depth; + } + + viewInfo.viewType = m_dstViewType; + viewInfo.subresourceRange = dstSubresources; + + if (m_vkd->vkCreateImageView(m_vkd->device(), &viewInfo, nullptr, &result.dstView) != VK_SUCCESS) + throw DxvkError("DxvkMetaMipGenRenderPass: Failed to create target image view"); + + // Create framebuffer using the destination + // image view as its color attachment. + VkFramebufferCreateInfo fboInfo; + fboInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + fboInfo.pNext = nullptr; + fboInfo.flags = 0; + fboInfo.renderPass = m_renderPass; + fboInfo.attachmentCount = 1; + fboInfo.pAttachments = &result.dstView; + fboInfo.width = dstExtent.width; + fboInfo.height = dstExtent.height; + fboInfo.layers = dstSubresources.layerCount; + + if (m_vkd->vkCreateFramebuffer(m_vkd->device(), &fboInfo, nullptr, &result.framebuffer) != VK_SUCCESS) + throw DxvkError("DxvkMetaMipGenRenderPass: Failed to create target framebuffer"); + + return result; + } + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_mipgen.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_mipgen.h new file mode 100644 index 00000000000..a5d2d60f99c --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_mipgen.h @@ -0,0 +1,93 @@ +#pragma once + +#include + +#include "dxvk_meta_blit.h" + +namespace dxvk { + + /** + * \brief Mip map generation render pass + * + * Stores image views, framebuffer objects and + * a render pass object for mip map generation. + * This must be created per image view. + */ + class DxvkMetaMipGenRenderPass : public DxvkResource { + + public: + + DxvkMetaMipGenRenderPass( + const Rc& vkd, + const Rc& view); + + ~DxvkMetaMipGenRenderPass(); + + /** + * \brief Render pass handle + * \returns Render pass handle + */ + VkRenderPass renderPass() const { + return m_renderPass; + } + + /** + * \brief Source image view type + * + * Use this to figure out which type the + * resource descriptor needs to have. + * \returns Source image view type + */ + VkImageViewType viewType() const { + return m_srcViewType; + } + + /** + * \brief Render pass count + * + * Number of mip levels to generate. + * \returns Render pass count + */ + uint32_t passCount() const { + return m_passes.size(); + } + + /** + * \brief Framebuffer handles + * + * Returns image view and framebuffer handles + * required to generate a single mip level. + * \param [in] pass Render pass index + * \returns Object handles for the given pass + */ + DxvkMetaBlitPass pass(uint32_t passId) const { + return m_passes.at(passId); + } + + /** + * \brief Framebuffer size for a given pass + * + * Stores the width, height, and layer count + * of the framebuffer for the given pass ID. + */ + VkExtent3D passExtent(uint32_t passId) const; + + private: + + Rc m_vkd; + Rc m_view; + + VkRenderPass m_renderPass; + + VkImageViewType m_srcViewType; + VkImageViewType m_dstViewType; + + std::vector m_passes; + + VkRenderPass createRenderPass() const; + + DxvkMetaBlitPass createFramebuffer(uint32_t pass) const; + + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_pack.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_pack.cpp new file mode 100644 index 00000000000..dbf4999b357 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_pack.cpp @@ -0,0 +1,287 @@ +#include "dxvk_meta_pack.h" +#include "dxvk_device.h" + +#include +#include + +#include +#include +#include + +namespace dxvk { + + DxvkMetaPackObjects::DxvkMetaPackObjects(const DxvkDevice* device) + : m_vkd (device->vkd()), + m_sampler (createSampler()), + m_dsetLayoutPack (createPackDescriptorSetLayout()), + m_dsetLayoutUnpack(createUnpackDescriptorSetLayout()), + m_pipeLayoutPack (createPipelineLayout(m_dsetLayoutPack, sizeof(DxvkMetaPackArgs))), + m_pipeLayoutUnpack(createPipelineLayout(m_dsetLayoutUnpack, sizeof(DxvkMetaPackArgs))), + m_templatePack (createPackDescriptorUpdateTemplate()), + m_templateUnpack (createUnpackDescriptorUpdateTemplate()), + m_pipePackD24S8 (createPipeline(m_pipeLayoutPack, dxvk_pack_d24s8)), + m_pipePackD32S8 (createPipeline(m_pipeLayoutPack, dxvk_pack_d32s8)), + m_pipeUnpackD24S8AsD32S8(createPipeline(m_pipeLayoutUnpack, dxvk_unpack_d24s8_as_d32s8)), + m_pipeUnpackD24S8 (createPipeline(m_pipeLayoutUnpack, dxvk_unpack_d24s8)), + m_pipeUnpackD32S8 (createPipeline(m_pipeLayoutUnpack, dxvk_unpack_d32s8)) { + + } + + + DxvkMetaPackObjects::~DxvkMetaPackObjects() { + m_vkd->vkDestroyPipeline(m_vkd->device(), m_pipeUnpackD32S8, nullptr); + m_vkd->vkDestroyPipeline(m_vkd->device(), m_pipeUnpackD24S8, nullptr); + m_vkd->vkDestroyPipeline(m_vkd->device(), m_pipeUnpackD24S8AsD32S8, nullptr); + + m_vkd->vkDestroyPipeline(m_vkd->device(), m_pipePackD32S8, nullptr); + m_vkd->vkDestroyPipeline(m_vkd->device(), m_pipePackD24S8, nullptr); + + m_vkd->vkDestroyDescriptorUpdateTemplate(m_vkd->device(), m_templatePack, nullptr); + m_vkd->vkDestroyDescriptorUpdateTemplate(m_vkd->device(), m_templateUnpack, nullptr); + + m_vkd->vkDestroyPipelineLayout(m_vkd->device(), m_pipeLayoutPack, nullptr); + m_vkd->vkDestroyPipelineLayout(m_vkd->device(), m_pipeLayoutUnpack, nullptr); + + m_vkd->vkDestroyDescriptorSetLayout(m_vkd->device(), m_dsetLayoutPack, nullptr); + m_vkd->vkDestroyDescriptorSetLayout(m_vkd->device(), m_dsetLayoutUnpack, nullptr); + + m_vkd->vkDestroySampler(m_vkd->device(), m_sampler, nullptr); + } + + + DxvkMetaPackPipeline DxvkMetaPackObjects::getPackPipeline(VkFormat format) { + DxvkMetaPackPipeline result; + result.dsetTemplate = m_templatePack; + result.dsetLayout = m_dsetLayoutPack; + result.pipeLayout = m_pipeLayoutPack; + result.pipeHandle = VK_NULL_HANDLE; + + switch (format) { + case VK_FORMAT_D24_UNORM_S8_UINT: result.pipeHandle = m_pipePackD24S8; break; + case VK_FORMAT_D32_SFLOAT_S8_UINT: result.pipeHandle = m_pipePackD32S8; break; + default: Logger::err(str::format("DxvkMetaPackObjects: Unknown format: ", format)); + } + + return result; + } + + + DxvkMetaPackPipeline DxvkMetaPackObjects::getUnpackPipeline( + VkFormat dstFormat, + VkFormat srcFormat) { + DxvkMetaPackPipeline result; + result.dsetTemplate = m_templateUnpack; + result.dsetLayout = m_dsetLayoutUnpack; + result.pipeLayout = m_pipeLayoutUnpack; + result.pipeHandle = VK_NULL_HANDLE; + + std::array, 3> pipeSelector = {{ + { VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT, m_pipeUnpackD24S8 }, + { VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT, m_pipeUnpackD24S8AsD32S8 }, + { VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT, m_pipeUnpackD32S8 }, + }}; + + for (const auto& e : pipeSelector) { + if (std::get<0>(e) == dstFormat + && std::get<1>(e) == srcFormat) + result.pipeHandle = std::get<2>(e); + } + + return result; + } + + + VkSampler DxvkMetaPackObjects::createSampler() { + VkSamplerCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.magFilter = VK_FILTER_NEAREST; + info.minFilter = VK_FILTER_NEAREST; + info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; + info.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + info.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + info.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + info.mipLodBias = 0.0f; + info.anisotropyEnable = VK_FALSE; + info.maxAnisotropy = 1.0f; + info.compareEnable = VK_FALSE; + info.compareOp = VK_COMPARE_OP_ALWAYS; + info.minLod = 0.0f; + info.maxLod = 0.0f; + info.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; + info.unnormalizedCoordinates = VK_FALSE; + + VkSampler result = VK_NULL_HANDLE; + if (m_vkd->vkCreateSampler(m_vkd->device(), &info, nullptr, &result) != VK_SUCCESS) + throw DxvkError("DxvkMetaPackObjects: Failed to create sampler"); + return result; + } + + + VkDescriptorSetLayout DxvkMetaPackObjects::createPackDescriptorSetLayout() { + std::array bindings = {{ + { 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr }, + { 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_COMPUTE_BIT, &m_sampler }, + { 2, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_COMPUTE_BIT, &m_sampler }, + }}; + + VkDescriptorSetLayoutCreateInfo dsetInfo; + dsetInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + dsetInfo.pNext = nullptr; + dsetInfo.flags = 0; + dsetInfo.bindingCount = bindings.size(); + dsetInfo.pBindings = bindings.data(); + + VkDescriptorSetLayout result = VK_NULL_HANDLE; + if (m_vkd->vkCreateDescriptorSetLayout(m_vkd->device(), &dsetInfo, nullptr, &result) != VK_SUCCESS) + throw DxvkError("DxvkMetaPackObjects: Failed to create descriptor set layout"); + return result; + } + + + VkDescriptorSetLayout DxvkMetaPackObjects::createUnpackDescriptorSetLayout() { + std::array bindings = {{ + { 0, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr }, + { 1, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr }, + { 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr }, + }}; + + VkDescriptorSetLayoutCreateInfo dsetInfo; + dsetInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + dsetInfo.pNext = nullptr; + dsetInfo.flags = 0; + dsetInfo.bindingCount = bindings.size(); + dsetInfo.pBindings = bindings.data(); + + VkDescriptorSetLayout result = VK_NULL_HANDLE; + if (m_vkd->vkCreateDescriptorSetLayout(m_vkd->device(), &dsetInfo, nullptr, &result) != VK_SUCCESS) + throw DxvkError("DxvkMetaPackObjects: Failed to create descriptor set layout"); + return result; + } + + + VkPipelineLayout DxvkMetaPackObjects::createPipelineLayout( + VkDescriptorSetLayout dsetLayout, + size_t pushLayout) { + VkPushConstantRange push; + push.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; + push.offset = 0; + push.size = pushLayout; + + VkPipelineLayoutCreateInfo layoutInfo; + layoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + layoutInfo.pNext = nullptr; + layoutInfo.flags = 0; + layoutInfo.setLayoutCount = 1; + layoutInfo.pSetLayouts = &dsetLayout; + layoutInfo.pushConstantRangeCount = 1; + layoutInfo.pPushConstantRanges = &push; + + VkPipelineLayout result = VK_NULL_HANDLE; + if (m_vkd->vkCreatePipelineLayout(m_vkd->device(), &layoutInfo, nullptr, &result) != VK_SUCCESS) + throw DxvkError("DxvkMetaPackObjects: Failed to create pipeline layout"); + return result; + } + + + VkDescriptorUpdateTemplate DxvkMetaPackObjects::createPackDescriptorUpdateTemplate() { + std::array bindings = {{ + { 0, 0, 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, offsetof(DxvkMetaPackDescriptors, dstBuffer), 0 }, + { 1, 0, 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, offsetof(DxvkMetaPackDescriptors, srcDepth), 0 }, + { 2, 0, 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, offsetof(DxvkMetaPackDescriptors, srcStencil), 0 }, + }}; + + VkDescriptorUpdateTemplateCreateInfo templateInfo; + templateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO; + templateInfo.pNext = nullptr; + templateInfo.flags = 0; + templateInfo.descriptorUpdateEntryCount = bindings.size(); + templateInfo.pDescriptorUpdateEntries = bindings.data(); + templateInfo.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET; + templateInfo.descriptorSetLayout = m_dsetLayoutPack; + templateInfo.pipelineBindPoint = VK_PIPELINE_BIND_POINT_COMPUTE; + templateInfo.pipelineLayout = m_pipeLayoutPack; + templateInfo.set = 0; + + VkDescriptorUpdateTemplate result = VK_NULL_HANDLE; + if (m_vkd->vkCreateDescriptorUpdateTemplate(m_vkd->device(), + &templateInfo, nullptr, &result) != VK_SUCCESS) + throw DxvkError("DxvkMetaPackObjects: Failed to create descriptor update template"); + return result; + } + + + VkDescriptorUpdateTemplate DxvkMetaPackObjects::createUnpackDescriptorUpdateTemplate() { + std::array bindings = {{ + { 0, 0, 1, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, offsetof(DxvkMetaUnpackDescriptors, dstDepth), 0 }, + { 1, 0, 1, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, offsetof(DxvkMetaUnpackDescriptors, dstStencil), 0 }, + { 2, 0, 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, offsetof(DxvkMetaUnpackDescriptors, srcBuffer), 0 }, + }}; + + VkDescriptorUpdateTemplateCreateInfo templateInfo; + templateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO; + templateInfo.pNext = nullptr; + templateInfo.flags = 0; + templateInfo.descriptorUpdateEntryCount = bindings.size(); + templateInfo.pDescriptorUpdateEntries = bindings.data(); + templateInfo.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET; + templateInfo.descriptorSetLayout = m_dsetLayoutUnpack; + templateInfo.pipelineBindPoint = VK_PIPELINE_BIND_POINT_COMPUTE; + templateInfo.pipelineLayout = m_pipeLayoutUnpack; + templateInfo.set = 0; + + VkDescriptorUpdateTemplate result = VK_NULL_HANDLE; + if (m_vkd->vkCreateDescriptorUpdateTemplate(m_vkd->device(), + &templateInfo, nullptr, &result) != VK_SUCCESS) + throw DxvkError("DxvkMetaPackObjects: Failed to create descriptor update template"); + return result; + } + + + VkPipeline DxvkMetaPackObjects::createPipeline( + VkPipelineLayout pipeLayout, + const SpirvCodeBuffer& code) { + VkShaderModuleCreateInfo shaderInfo; + shaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + shaderInfo.pNext = nullptr; + shaderInfo.flags = 0; + shaderInfo.codeSize = code.size(); + shaderInfo.pCode = code.data(); + + VkShaderModule module = VK_NULL_HANDLE; + + if (m_vkd->vkCreateShaderModule(m_vkd->device(), &shaderInfo, nullptr, &module) != VK_SUCCESS) + throw DxvkError("DxvkMetaPackObjects: Failed to create shader module"); + + VkPipelineShaderStageCreateInfo stageInfo; + stageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + stageInfo.pNext = nullptr; + stageInfo.flags = 0; + stageInfo.stage = VK_SHADER_STAGE_COMPUTE_BIT; + stageInfo.module = module; + stageInfo.pName = "main"; + stageInfo.pSpecializationInfo = nullptr; + + VkComputePipelineCreateInfo pipeInfo; + pipeInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; + pipeInfo.pNext = nullptr; + pipeInfo.flags = 0; + pipeInfo.stage = stageInfo; + pipeInfo.layout = pipeLayout; + pipeInfo.basePipelineHandle = VK_NULL_HANDLE; + pipeInfo.basePipelineIndex = -1; + + VkPipeline result = VK_NULL_HANDLE; + + VkResult status = m_vkd->vkCreateComputePipelines( + m_vkd->device(), VK_NULL_HANDLE, 1, &pipeInfo, nullptr, &result); + + m_vkd->vkDestroyShaderModule(m_vkd->device(), module, nullptr); + + if (status != VK_SUCCESS) + throw DxvkError("DxvkMetaPackObjects: Failed to create pipeline"); + return result; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_pack.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_pack.h new file mode 100644 index 00000000000..7c69d8c3623 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_pack.h @@ -0,0 +1,133 @@ +#pragma once + +#include "../spirv/spirv_code_buffer.h" + +#include "dxvk_cmdlist.h" +#include "dxvk_resource.h" + +namespace dxvk { + + /** + * \brief Packing arguments + * + * Passed in as push constants + * to the compute shader. + */ + struct DxvkMetaPackArgs { + VkOffset2D srcOffset; + VkExtent2D srcExtent; + VkOffset2D dstOffset; + VkExtent2D dstExtent; + }; + + + /** + * \brief Packing pipeline + * + * Stores the objects for a single pipeline + * that is used to pack depth-stencil image + * data into a linear buffer. + */ + struct DxvkMetaPackPipeline { + VkDescriptorUpdateTemplateKHR dsetTemplate; + VkDescriptorSetLayout dsetLayout; + VkPipelineLayout pipeLayout; + VkPipeline pipeHandle; + }; + + + /** + * \brief Packing descriptors + */ + struct DxvkMetaPackDescriptors { + VkDescriptorBufferInfo dstBuffer; + VkDescriptorImageInfo srcDepth; + VkDescriptorImageInfo srcStencil; + }; + + + /** + * \brief Unpacking descriptors + */ + struct DxvkMetaUnpackDescriptors { + VkBufferView dstDepth; + VkBufferView dstStencil; + VkDescriptorBufferInfo srcBuffer; + }; + + + /** + * \brief Depth-stencil pack objects + * + * Stores compute shaders and related objects + * for depth-stencil image packing operations. + */ + class DxvkMetaPackObjects { + + public: + + DxvkMetaPackObjects(const DxvkDevice* device); + ~DxvkMetaPackObjects(); + + /** + * \brief Retrieves depth-stencil packing pipeline + * + * \param [in] format Destination format + * \returns Data packing pipeline + */ + DxvkMetaPackPipeline getPackPipeline(VkFormat format); + + /** + * \brief Retrieves depth-stencil unpacking pipeline + * + * \param [in] dstFormat Destination image format + * \param [in] srcFormat Source buffer format + * \returns Data unpacking pipeline + */ + DxvkMetaPackPipeline getUnpackPipeline( + VkFormat dstFormat, + VkFormat srcFormat); + + private: + + Rc m_vkd; + + VkSampler m_sampler; + + VkDescriptorSetLayout m_dsetLayoutPack; + VkDescriptorSetLayout m_dsetLayoutUnpack; + + VkPipelineLayout m_pipeLayoutPack; + VkPipelineLayout m_pipeLayoutUnpack; + + VkDescriptorUpdateTemplateKHR m_templatePack; + VkDescriptorUpdateTemplateKHR m_templateUnpack; + + VkPipeline m_pipePackD24S8; + VkPipeline m_pipePackD32S8; + + VkPipeline m_pipeUnpackD24S8AsD32S8; + VkPipeline m_pipeUnpackD24S8; + VkPipeline m_pipeUnpackD32S8; + + VkSampler createSampler(); + + VkDescriptorSetLayout createPackDescriptorSetLayout(); + + VkDescriptorSetLayout createUnpackDescriptorSetLayout(); + + VkPipelineLayout createPipelineLayout( + VkDescriptorSetLayout dsetLayout, + size_t pushLayout); + + VkDescriptorUpdateTemplateKHR createPackDescriptorUpdateTemplate(); + + VkDescriptorUpdateTemplateKHR createUnpackDescriptorUpdateTemplate(); + + VkPipeline createPipeline( + VkPipelineLayout pipeLayout, + const SpirvCodeBuffer& code); + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_resolve.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_resolve.cpp new file mode 100644 index 00000000000..55dde83c26e --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_resolve.cpp @@ -0,0 +1,714 @@ +#include "dxvk_device.h" +#include "dxvk_meta_resolve.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace dxvk { + + DxvkMetaResolveRenderPass::DxvkMetaResolveRenderPass( + const Rc& vkd, + const Rc& dstImageView, + const Rc& srcImageView, + const Rc& srcStencilView, + bool discardDst) + : m_vkd(vkd), + m_dstImageView(dstImageView), + m_srcImageView(srcImageView), + m_srcStencilView(srcStencilView), + m_renderPass (createShaderRenderPass(discardDst)), + m_framebuffer (createShaderFramebuffer()) { } + + + DxvkMetaResolveRenderPass::DxvkMetaResolveRenderPass( + const Rc& vkd, + const Rc& dstImageView, + const Rc& srcImageView, + VkResolveModeFlagBitsKHR modeD, + VkResolveModeFlagBitsKHR modeS) + : m_vkd(vkd), + m_dstImageView(dstImageView), + m_srcImageView(srcImageView), + m_renderPass (createAttachmentRenderPass(modeD, modeS)), + m_framebuffer (createAttachmentFramebuffer()) { } + + + DxvkMetaResolveRenderPass::~DxvkMetaResolveRenderPass() { + m_vkd->vkDestroyFramebuffer(m_vkd->device(), m_framebuffer, nullptr); + m_vkd->vkDestroyRenderPass (m_vkd->device(), m_renderPass, nullptr); + } + + + VkRenderPass DxvkMetaResolveRenderPass::createShaderRenderPass(bool discard) const { + auto formatInfo = m_dstImageView->formatInfo(); + bool isColorImage = (formatInfo->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT); + + VkAttachmentDescription attachment; + attachment.flags = 0; + attachment.format = m_dstImageView->info().format; + attachment.samples = VK_SAMPLE_COUNT_1_BIT; + attachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; + attachment.initialLayout = m_dstImageView->imageInfo().layout; + attachment.finalLayout = m_dstImageView->imageInfo().layout; + + if (discard) { + attachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + } + + VkImageLayout layout = isColorImage + ? m_dstImageView->pickLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) + : m_dstImageView->pickLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + + VkAttachmentReference dstRef; + dstRef.attachment = 0; + dstRef.layout = layout; + + VkSubpassDescription subpass; + subpass.flags = 0; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.inputAttachmentCount = 0; + subpass.pInputAttachments = nullptr; + subpass.colorAttachmentCount = isColorImage ? 1 : 0; + subpass.pColorAttachments = isColorImage ? &dstRef : nullptr; + subpass.pResolveAttachments = nullptr; + subpass.pDepthStencilAttachment = isColorImage ? nullptr : &dstRef; + subpass.preserveAttachmentCount = 0; + subpass.pPreserveAttachments = nullptr; + + VkPipelineStageFlags cpyStages = 0; + VkAccessFlags cpyAccess = 0; + + if (isColorImage) { + cpyStages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + cpyAccess |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + + if (!discard) + cpyAccess |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; + } else { + cpyStages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT + | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + cpyAccess |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + + if (!discard) + cpyAccess |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; + } + + // Resolve targets are required to be render targets + VkPipelineStageFlags extStages = m_dstImageView->imageInfo().stages | m_srcImageView->imageInfo().stages; + VkAccessFlags extAccess = m_dstImageView->imageInfo().access; + + std::array dependencies = {{ + { VK_SUBPASS_EXTERNAL, 0, cpyStages, cpyStages, 0, cpyAccess, 0 }, + { 0, VK_SUBPASS_EXTERNAL, cpyStages, extStages, cpyAccess, extAccess, 0 }, + }}; + + VkRenderPassCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.attachmentCount = 1; + info.pAttachments = &attachment; + info.subpassCount = 1; + info.pSubpasses = &subpass; + info.dependencyCount = dependencies.size(); + info.pDependencies = dependencies.data(); + + VkRenderPass result = VK_NULL_HANDLE; + if (m_vkd->vkCreateRenderPass(m_vkd->device(), &info, nullptr, &result) != VK_SUCCESS) + throw DxvkError("DxvkMetaResolveRenderPass: Failed to create render pass"); + return result; + } + + + VkRenderPass DxvkMetaResolveRenderPass::createAttachmentRenderPass( + VkResolveModeFlagBitsKHR modeD, + VkResolveModeFlagBitsKHR modeS) const { + std::array attachments; + attachments[0].sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2_KHR; + attachments[0].pNext = nullptr; + attachments[0].flags = 0; + attachments[0].format = m_srcImageView->info().format; + attachments[0].samples = m_srcImageView->imageInfo().sampleCount; + attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; + attachments[0].initialLayout = m_srcImageView->imageInfo().layout; + attachments[0].finalLayout = m_srcImageView->imageInfo().layout; + + attachments[1].sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2_KHR; + attachments[1].pNext = nullptr; + attachments[1].flags = 0; + attachments[1].format = m_dstImageView->info().format; + attachments[1].samples = VK_SAMPLE_COUNT_1_BIT; + attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; + attachments[1].initialLayout = m_dstImageView->imageInfo().layout; + attachments[1].finalLayout = m_dstImageView->imageInfo().layout; + + if (modeD != VK_RESOLVE_MODE_NONE_KHR && modeS != VK_RESOLVE_MODE_NONE_KHR) { + attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + } + + VkAttachmentReference2KHR srcRef; + srcRef.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR; + srcRef.pNext = nullptr; + srcRef.attachment = 0; + srcRef.layout = m_srcImageView->pickLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + srcRef.aspectMask = m_srcImageView->formatInfo()->aspectMask; + + VkAttachmentReference2KHR dstRef; + dstRef.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR; + dstRef.pNext = nullptr; + dstRef.attachment = 1; + dstRef.layout = m_dstImageView->pickLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + dstRef.aspectMask = m_dstImageView->formatInfo()->aspectMask; + + VkSubpassDescriptionDepthStencilResolveKHR subpassResolve; + subpassResolve.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE_KHR; + subpassResolve.pNext = nullptr; + subpassResolve.depthResolveMode = modeD; + subpassResolve.stencilResolveMode = modeS; + subpassResolve.pDepthStencilResolveAttachment = &dstRef; + + VkSubpassDescription2KHR subpass; + subpass.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR; + subpass.pNext = &subpassResolve; + subpass.flags = 0; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.viewMask = 0; + subpass.inputAttachmentCount = 0; + subpass.pInputAttachments = nullptr; + subpass.colorAttachmentCount = 0; + subpass.pColorAttachments = nullptr; + subpass.pResolveAttachments = nullptr; + subpass.pDepthStencilAttachment = &srcRef; + subpass.preserveAttachmentCount = 0; + subpass.pPreserveAttachments = nullptr; + + VkPipelineStageFlags cpyStages = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + VkPipelineStageFlags extStages = m_dstImageView->imageInfo().stages | m_srcImageView->imageInfo().stages; + VkAccessFlags cpyAccess = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; + VkAccessFlags extAccess = m_dstImageView->imageInfo().access; + + std::array dependencies = {{ + { VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2_KHR, nullptr, VK_SUBPASS_EXTERNAL, 0, cpyStages, cpyStages, 0, cpyAccess, 0 }, + { VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2_KHR, nullptr, 0, VK_SUBPASS_EXTERNAL, cpyStages, extStages, cpyAccess, extAccess, 0 }, + }}; + + VkRenderPassCreateInfo2KHR info; + info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR; + info.pNext = nullptr; + info.flags = 0; + info.attachmentCount = attachments.size(); + info.pAttachments = attachments.data(); + info.subpassCount = 1; + info.pSubpasses = &subpass; + info.dependencyCount = dependencies.size(); + info.pDependencies = dependencies.data(); + info.correlatedViewMaskCount = 0; + info.pCorrelatedViewMasks = nullptr; + + VkRenderPass result = VK_NULL_HANDLE; + if (m_vkd->vkCreateRenderPass2KHR(m_vkd->device(), &info, nullptr, &result) != VK_SUCCESS) + throw DxvkError("DxvkMetaResolveRenderPass: Failed to create render pass"); + return result; + } + + + VkFramebuffer DxvkMetaResolveRenderPass::createShaderFramebuffer() const { + VkImageSubresourceRange dstSubresources = m_dstImageView->subresources(); + VkExtent3D dstExtent = m_dstImageView->mipLevelExtent(0); + VkImageView dstHandle = m_dstImageView->handle(); + + VkFramebufferCreateInfo fboInfo; + fboInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + fboInfo.pNext = nullptr; + fboInfo.flags = 0; + fboInfo.renderPass = m_renderPass; + fboInfo.attachmentCount = 1; + fboInfo.pAttachments = &dstHandle; + fboInfo.width = dstExtent.width; + fboInfo.height = dstExtent.height; + fboInfo.layers = dstSubresources.layerCount; + + VkFramebuffer result = VK_NULL_HANDLE; + if (m_vkd->vkCreateFramebuffer(m_vkd->device(), &fboInfo, nullptr, &result) != VK_SUCCESS) + throw DxvkError("DxvkMetaResolveRenderPass: Failed to create target framebuffer"); + return result; + } + + + VkFramebuffer DxvkMetaResolveRenderPass::createAttachmentFramebuffer() const { + VkImageSubresourceRange dstSubresources = m_dstImageView->subresources(); + VkExtent3D dstExtent = m_dstImageView->mipLevelExtent(0); + + std::array handles = {{ + m_srcImageView->handle(), + m_dstImageView->handle(), + }}; + + VkFramebufferCreateInfo fboInfo; + fboInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + fboInfo.pNext = nullptr; + fboInfo.flags = 0; + fboInfo.renderPass = m_renderPass; + fboInfo.attachmentCount = handles.size(); + fboInfo.pAttachments = handles.data(); + fboInfo.width = dstExtent.width; + fboInfo.height = dstExtent.height; + fboInfo.layers = dstSubresources.layerCount; + + VkFramebuffer result = VK_NULL_HANDLE; + if (m_vkd->vkCreateFramebuffer(m_vkd->device(), &fboInfo, nullptr, &result) != VK_SUCCESS) + throw DxvkError("DxvkMetaResolveRenderPass: Failed to create target framebuffer"); + return result; + } + + + + DxvkMetaResolveObjects::DxvkMetaResolveObjects(const DxvkDevice* device) + : m_vkd (device->vkd()), + m_sampler (createSampler()), + m_shaderFragF (device->extensions().amdShaderFragmentMask + ? createShaderModule(dxvk_resolve_frag_f_amd) + : createShaderModule(dxvk_resolve_frag_f)), + m_shaderFragU (createShaderModule(dxvk_resolve_frag_u)), + m_shaderFragI (createShaderModule(dxvk_resolve_frag_i)), + m_shaderFragD (createShaderModule(dxvk_resolve_frag_d)) { + if (device->extensions().extShaderStencilExport) + m_shaderFragDS = createShaderModule(dxvk_resolve_frag_ds); + + if (device->extensions().extShaderViewportIndexLayer) { + m_shaderVert = createShaderModule(dxvk_fullscreen_layer_vert); + } else { + m_shaderVert = createShaderModule(dxvk_fullscreen_vert); + m_shaderGeom = createShaderModule(dxvk_fullscreen_geom); + } + } + + + DxvkMetaResolveObjects::~DxvkMetaResolveObjects() { + for (const auto& pair : m_pipelines) { + m_vkd->vkDestroyPipeline(m_vkd->device(), pair.second.pipeHandle, nullptr); + m_vkd->vkDestroyPipelineLayout(m_vkd->device(), pair.second.pipeLayout, nullptr); + m_vkd->vkDestroyDescriptorSetLayout(m_vkd->device(), pair.second.dsetLayout, nullptr); + m_vkd->vkDestroyRenderPass(m_vkd->device(), pair.second.renderPass, nullptr); + } + + m_vkd->vkDestroyShaderModule(m_vkd->device(), m_shaderFragDS, nullptr); + m_vkd->vkDestroyShaderModule(m_vkd->device(), m_shaderFragD, nullptr); + m_vkd->vkDestroyShaderModule(m_vkd->device(), m_shaderFragF, nullptr); + m_vkd->vkDestroyShaderModule(m_vkd->device(), m_shaderFragI, nullptr); + m_vkd->vkDestroyShaderModule(m_vkd->device(), m_shaderFragU, nullptr); + m_vkd->vkDestroyShaderModule(m_vkd->device(), m_shaderGeom, nullptr); + m_vkd->vkDestroyShaderModule(m_vkd->device(), m_shaderVert, nullptr); + + m_vkd->vkDestroySampler(m_vkd->device(), m_sampler, nullptr); + } + + + DxvkMetaResolvePipeline DxvkMetaResolveObjects::getPipeline( + VkFormat format, + VkSampleCountFlagBits samples, + VkResolveModeFlagBitsKHR depthResolveMode, + VkResolveModeFlagBitsKHR stencilResolveMode) { + std::lock_guard lock(m_mutex); + + DxvkMetaResolvePipelineKey key; + key.format = format; + key.samples = samples; + key.modeD = depthResolveMode; + key.modeS = stencilResolveMode; + + auto entry = m_pipelines.find(key); + if (entry != m_pipelines.end()) + return entry->second; + + DxvkMetaResolvePipeline pipeline = createPipeline(key); + m_pipelines.insert({ key, pipeline }); + return pipeline; + } + + + VkSampler DxvkMetaResolveObjects::createSampler() const { + VkSamplerCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.magFilter = VK_FILTER_NEAREST; + info.minFilter = VK_FILTER_NEAREST; + info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; + info.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + info.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + info.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + info.mipLodBias = 0.0f; + info.anisotropyEnable = VK_FALSE; + info.maxAnisotropy = 1.0f; + info.compareEnable = VK_FALSE; + info.compareOp = VK_COMPARE_OP_ALWAYS; + info.minLod = 0.0f; + info.maxLod = 0.0f; + info.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; + info.unnormalizedCoordinates = VK_FALSE; + + VkSampler result = VK_NULL_HANDLE; + if (m_vkd->vkCreateSampler(m_vkd->device(), &info, nullptr, &result) != VK_SUCCESS) + throw DxvkError("DxvkMetaResolveObjects: Failed to create sampler"); + return result; + } + + + VkShaderModule DxvkMetaResolveObjects::createShaderModule( + const SpirvCodeBuffer& code) const { + VkShaderModuleCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.codeSize = code.size(); + info.pCode = code.data(); + + VkShaderModule result = VK_NULL_HANDLE; + if (m_vkd->vkCreateShaderModule(m_vkd->device(), &info, nullptr, &result) != VK_SUCCESS) + throw DxvkError("DxvkMetaCopyObjects: Failed to create shader module"); + return result; + } + + + DxvkMetaResolvePipeline DxvkMetaResolveObjects::createPipeline( + const DxvkMetaResolvePipelineKey& key) { + DxvkMetaResolvePipeline pipeline; + pipeline.renderPass = this->createRenderPass(key); + pipeline.dsetLayout = this->createDescriptorSetLayout(key); + pipeline.pipeLayout = this->createPipelineLayout(pipeline.dsetLayout); + pipeline.pipeHandle = this->createPipelineObject(key, pipeline.pipeLayout, pipeline.renderPass); + return pipeline; + } + + + VkRenderPass DxvkMetaResolveObjects::createRenderPass( + const DxvkMetaResolvePipelineKey& key) { + auto formatInfo = imageFormatInfo(key.format); + bool isColorImage = (formatInfo->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT); + + VkAttachmentDescription attachment; + attachment.flags = 0; + attachment.format = key.format; + attachment.samples = VK_SAMPLE_COUNT_1_BIT; + attachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; + attachment.initialLayout = VK_IMAGE_LAYOUT_GENERAL; + attachment.finalLayout = VK_IMAGE_LAYOUT_GENERAL; + + VkImageLayout layout = isColorImage + ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL + : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + VkAttachmentReference attachmentRef; + attachmentRef.attachment = 0; + attachmentRef.layout = layout; + + VkSubpassDescription subpass; + subpass.flags = 0; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.inputAttachmentCount = 0; + subpass.pInputAttachments = nullptr; + subpass.colorAttachmentCount = isColorImage ? 1 : 0; + subpass.pColorAttachments = isColorImage ? &attachmentRef : nullptr; + subpass.pResolveAttachments = nullptr; + subpass.pDepthStencilAttachment = isColorImage ? nullptr : &attachmentRef; + subpass.preserveAttachmentCount = 0; + subpass.pPreserveAttachments = nullptr; + + VkRenderPassCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.attachmentCount = 1; + info.pAttachments = &attachment; + info.subpassCount = 1; + info.pSubpasses = &subpass; + info.dependencyCount = 0; + info.pDependencies = nullptr; + + VkRenderPass result = VK_NULL_HANDLE; + if (m_vkd->vkCreateRenderPass(m_vkd->device(), &info, nullptr, &result) != VK_SUCCESS) + throw DxvkError("DxvkMetaResolveObjects: Failed to create render pass"); + return result; + } + + + VkDescriptorSetLayout DxvkMetaResolveObjects::createDescriptorSetLayout( + const DxvkMetaResolvePipelineKey& key) { + auto formatInfo = imageFormatInfo(key.format); + + std::array bindings = {{ + { 0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, &m_sampler }, + { 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, &m_sampler }, + }}; + + VkDescriptorSetLayoutCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.bindingCount = 1; + info.pBindings = bindings.data(); + + if ((formatInfo->aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) && key.modeS != VK_RESOLVE_MODE_NONE_KHR) + info.bindingCount = 2; + + VkDescriptorSetLayout result = VK_NULL_HANDLE; + if (m_vkd->vkCreateDescriptorSetLayout(m_vkd->device(), &info, nullptr, &result) != VK_SUCCESS) + throw DxvkError("DxvkMetaResolveObjects: Failed to create descriptor set layout"); + return result; + } + + + VkPipelineLayout DxvkMetaResolveObjects::createPipelineLayout( + VkDescriptorSetLayout descriptorSetLayout) { + VkPushConstantRange push; + push.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + push.offset = 0; + push.size = sizeof(VkOffset2D); + + VkPipelineLayoutCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.setLayoutCount = 1; + info.pSetLayouts = &descriptorSetLayout; + info.pushConstantRangeCount = 1; + info.pPushConstantRanges = &push; + + VkPipelineLayout result = VK_NULL_HANDLE; + if (m_vkd->vkCreatePipelineLayout(m_vkd->device(), &info, nullptr, &result) != VK_SUCCESS) + throw DxvkError("DxvkMetaCopyObjects: Failed to create pipeline layout"); + return result; + } + + + VkPipeline DxvkMetaResolveObjects::createPipelineObject( + const DxvkMetaResolvePipelineKey& key, + VkPipelineLayout pipelineLayout, + VkRenderPass renderPass) { + auto formatInfo = imageFormatInfo(key.format); + bool isColorImage = formatInfo->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT; + + std::array stages; + uint32_t stageCount = 0; + + std::array specEntries = {{ + { 0, offsetof(DxvkMetaResolvePipelineKey, samples), sizeof(VkSampleCountFlagBits) }, + { 1, offsetof(DxvkMetaResolvePipelineKey, modeD), sizeof(VkResolveModeFlagBitsKHR) }, + { 2, offsetof(DxvkMetaResolvePipelineKey, modeS), sizeof(VkResolveModeFlagBitsKHR) }, + }}; + + VkSpecializationInfo specInfo; + specInfo.mapEntryCount = specEntries.size(); + specInfo.pMapEntries = specEntries.data(); + specInfo.dataSize = sizeof(key); + specInfo.pData = &key; + + VkPipelineShaderStageCreateInfo& vsStage = stages[stageCount++]; + vsStage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + vsStage.pNext = nullptr; + vsStage.flags = 0; + vsStage.stage = VK_SHADER_STAGE_VERTEX_BIT; + vsStage.module = m_shaderVert; + vsStage.pName = "main"; + vsStage.pSpecializationInfo = nullptr; + + if (m_shaderGeom) { + VkPipelineShaderStageCreateInfo& gsStage = stages[stageCount++]; + gsStage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + gsStage.pNext = nullptr; + gsStage.flags = 0; + gsStage.stage = VK_SHADER_STAGE_GEOMETRY_BIT; + gsStage.module = m_shaderGeom; + gsStage.pName = "main"; + gsStage.pSpecializationInfo = nullptr; + } + + VkPipelineShaderStageCreateInfo& psStage = stages[stageCount++]; + psStage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + psStage.pNext = nullptr; + psStage.flags = 0; + psStage.stage = VK_SHADER_STAGE_FRAGMENT_BIT; + psStage.module = VK_NULL_HANDLE; + psStage.pName = "main"; + psStage.pSpecializationInfo = &specInfo; + + if ((formatInfo->aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) && key.modeS != VK_RESOLVE_MODE_NONE_KHR) { + if (m_shaderFragDS) { + psStage.module = m_shaderFragDS; + } else { + psStage.module = m_shaderFragD; + Logger::err("DXVK: Stencil export not supported by device, skipping stencil resolve"); + } + } else if (formatInfo->aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) + psStage.module = m_shaderFragD; + else if (formatInfo->flags.test(DxvkFormatFlag::SampledUInt)) + psStage.module = m_shaderFragU; + else if (formatInfo->flags.test(DxvkFormatFlag::SampledSInt)) + psStage.module = m_shaderFragI; + else + psStage.module = m_shaderFragF; + + std::array dynStates = {{ + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR, + }}; + + VkPipelineDynamicStateCreateInfo dynState; + dynState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; + dynState.pNext = nullptr; + dynState.flags = 0; + dynState.dynamicStateCount = dynStates.size(); + dynState.pDynamicStates = dynStates.data(); + + VkPipelineVertexInputStateCreateInfo viState; + viState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + viState.pNext = nullptr; + viState.flags = 0; + viState.vertexBindingDescriptionCount = 0; + viState.pVertexBindingDescriptions = nullptr; + viState.vertexAttributeDescriptionCount = 0; + viState.pVertexAttributeDescriptions = nullptr; + + VkPipelineInputAssemblyStateCreateInfo iaState; + iaState.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + iaState.pNext = nullptr; + iaState.flags = 0; + iaState.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + iaState.primitiveRestartEnable = VK_FALSE; + + VkPipelineViewportStateCreateInfo vpState; + vpState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + vpState.pNext = nullptr; + vpState.flags = 0; + vpState.viewportCount = 1; + vpState.pViewports = nullptr; + vpState.scissorCount = 1; + vpState.pScissors = nullptr; + + VkPipelineRasterizationStateCreateInfo rsState; + rsState.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + rsState.pNext = nullptr; + rsState.flags = 0; + rsState.depthClampEnable = VK_TRUE; + rsState.rasterizerDiscardEnable = VK_FALSE; + rsState.polygonMode = VK_POLYGON_MODE_FILL; + rsState.cullMode = VK_CULL_MODE_NONE; + rsState.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; + rsState.depthBiasEnable = VK_FALSE; + rsState.depthBiasConstantFactor = 0.0f; + rsState.depthBiasClamp = 0.0f; + rsState.depthBiasSlopeFactor = 0.0f; + rsState.lineWidth = 1.0f; + + uint32_t msMask = 0xFFFFFFFF; + VkPipelineMultisampleStateCreateInfo msState; + msState.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + msState.pNext = nullptr; + msState.flags = 0; + msState.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + msState.sampleShadingEnable = VK_FALSE; + msState.minSampleShading = 1.0f; + msState.pSampleMask = &msMask; + msState.alphaToCoverageEnable = VK_FALSE; + msState.alphaToOneEnable = VK_FALSE; + + VkPipelineColorBlendAttachmentState cbAttachment; + cbAttachment.blendEnable = VK_FALSE; + cbAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; + cbAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; + cbAttachment.colorBlendOp = VK_BLEND_OP_ADD; + cbAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; + cbAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; + cbAttachment.alphaBlendOp = VK_BLEND_OP_ADD; + cbAttachment.colorWriteMask = + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | + VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + + VkPipelineColorBlendStateCreateInfo cbState; + cbState.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + cbState.pNext = nullptr; + cbState.flags = 0; + cbState.logicOpEnable = VK_FALSE; + cbState.logicOp = VK_LOGIC_OP_NO_OP; + cbState.attachmentCount = 1; + cbState.pAttachments = &cbAttachment; + + for (uint32_t i = 0; i < 4; i++) + cbState.blendConstants[i] = 0.0f; + + VkStencilOpState stencilOp; + stencilOp.failOp = VK_STENCIL_OP_REPLACE; + stencilOp.passOp = VK_STENCIL_OP_REPLACE; + stencilOp.depthFailOp = VK_STENCIL_OP_REPLACE; + stencilOp.compareOp = VK_COMPARE_OP_ALWAYS; + stencilOp.compareMask = 0xFFFFFFFF; + stencilOp.writeMask = 0xFFFFFFFF; + stencilOp.reference = 0; + + VkPipelineDepthStencilStateCreateInfo dsState; + dsState.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + dsState.pNext = nullptr; + dsState.flags = 0; + dsState.depthTestEnable = key.modeD != VK_RESOLVE_MODE_NONE_KHR; + dsState.depthWriteEnable = key.modeD != VK_RESOLVE_MODE_NONE_KHR; + dsState.depthCompareOp = VK_COMPARE_OP_ALWAYS; + dsState.depthBoundsTestEnable = VK_FALSE; + dsState.stencilTestEnable = key.modeS != VK_RESOLVE_MODE_NONE_KHR; + dsState.front = stencilOp; + dsState.back = stencilOp; + dsState.minDepthBounds = 0.0f; + dsState.maxDepthBounds = 1.0f; + + VkGraphicsPipelineCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.stageCount = stageCount; + info.pStages = stages.data(); + info.pVertexInputState = &viState; + info.pInputAssemblyState = &iaState; + info.pTessellationState = nullptr; + info.pViewportState = &vpState; + info.pRasterizationState = &rsState; + info.pMultisampleState = &msState; + info.pColorBlendState = isColorImage ? &cbState : nullptr; + info.pDepthStencilState = isColorImage ? nullptr : &dsState; + info.pDynamicState = &dynState; + info.layout = pipelineLayout; + info.renderPass = renderPass; + info.subpass = 0; + info.basePipelineHandle = VK_NULL_HANDLE; + info.basePipelineIndex = -1; + + VkPipeline result = VK_NULL_HANDLE; + if (m_vkd->vkCreateGraphicsPipelines(m_vkd->device(), VK_NULL_HANDLE, 1, &info, nullptr, &result) != VK_SUCCESS) + throw DxvkError("DxvkMetaCopyObjects: Failed to create graphics pipeline"); + return result; + } + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_resolve.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_resolve.h new file mode 100644 index 00000000000..72161325b0a --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_meta_resolve.h @@ -0,0 +1,185 @@ +#pragma once + +#include +#include + +#include "../spirv/spirv_code_buffer.h" + +#include "dxvk_barrier.h" +#include "dxvk_cmdlist.h" +#include "dxvk_resource.h" + +namespace dxvk { + + /** + * \brief Resolve pipeline + * + * Stores the objects for a single pipeline + * that is used for fragment shader resolve. + */ + struct DxvkMetaResolvePipeline { + VkRenderPass renderPass; + VkDescriptorSetLayout dsetLayout; + VkPipelineLayout pipeLayout; + VkPipeline pipeHandle; + }; + + /** + * \brief Copy pipeline key + * + * Used to look up copy pipelines based + * on the copy operation they support. + */ + struct DxvkMetaResolvePipelineKey { + VkFormat format; + VkSampleCountFlagBits samples; + VkResolveModeFlagBitsKHR modeD; + VkResolveModeFlagBitsKHR modeS; + + bool eq(const DxvkMetaResolvePipelineKey& other) const { + return this->format == other.format + && this->samples == other.samples + && this->modeD == other.modeD + && this->modeS == other.modeS; + } + + size_t hash() const { + return (uint32_t(format) << 4) + ^ (uint32_t(samples) << 0) + ^ (uint32_t(modeD) << 12) + ^ (uint32_t(modeS) << 16); + } + }; + + /** + * \brief Meta resolve render pass + * + * Stores a framebuffer and image view objects + * for a meta resolve operation. Can be tracked. + */ + class DxvkMetaResolveRenderPass : public DxvkResource { + + public: + + DxvkMetaResolveRenderPass( + const Rc& vkd, + const Rc& dstImageView, + const Rc& srcImageView, + const Rc& srcStencilView, + bool discardDst); + + DxvkMetaResolveRenderPass( + const Rc& vkd, + const Rc& dstImageView, + const Rc& srcImageView, + VkResolveModeFlagBitsKHR modeD, + VkResolveModeFlagBitsKHR modeS); + + ~DxvkMetaResolveRenderPass(); + + VkRenderPass renderPass() const { + return m_renderPass; + } + + VkFramebuffer framebuffer() const { + return m_framebuffer; + } + + private: + + const Rc m_vkd; + + const Rc m_dstImageView; + const Rc m_srcImageView; + const Rc m_srcStencilView; + + VkRenderPass m_renderPass = VK_NULL_HANDLE; + VkFramebuffer m_framebuffer = VK_NULL_HANDLE; + + VkRenderPass createShaderRenderPass(bool discard) const; + + VkRenderPass createAttachmentRenderPass( + VkResolveModeFlagBitsKHR modeD, + VkResolveModeFlagBitsKHR modeS) const; + + VkFramebuffer createShaderFramebuffer() const; + + VkFramebuffer createAttachmentFramebuffer() const; + + }; + + + /** + * \brief Meta resolve objects + * + * Implements resolve operations in fragment + * shaders when using different formats. + */ + class DxvkMetaResolveObjects { + + public: + + DxvkMetaResolveObjects(const DxvkDevice* device); + ~DxvkMetaResolveObjects(); + + /** + * \brief Creates pipeline for meta copy operation + * + * \param [in] format Destination image format + * \param [in] samples Destination sample count + * \param [in] depthResolveMode Depth resolve mode + * \param [in] stencilResolveMode Stencil resolve mode + * \returns Compatible pipeline for the operation + */ + DxvkMetaResolvePipeline getPipeline( + VkFormat format, + VkSampleCountFlagBits samples, + VkResolveModeFlagBitsKHR depthResolveMode, + VkResolveModeFlagBitsKHR stencilResolveMode); + + private: + + Rc m_vkd; + + VkSampler m_sampler; + + VkShaderModule m_shaderVert = VK_NULL_HANDLE; + VkShaderModule m_shaderGeom = VK_NULL_HANDLE; + VkShaderModule m_shaderFragF = VK_NULL_HANDLE; + VkShaderModule m_shaderFragU = VK_NULL_HANDLE; + VkShaderModule m_shaderFragI = VK_NULL_HANDLE; + VkShaderModule m_shaderFragD = VK_NULL_HANDLE; + VkShaderModule m_shaderFragDS = VK_NULL_HANDLE; + + dxvk::mutex m_mutex; + + std::unordered_map< + DxvkMetaResolvePipelineKey, + DxvkMetaResolvePipeline, + DxvkHash, DxvkEq> m_pipelines; + + VkSampler createSampler() const; + + VkShaderModule createShaderModule( + const SpirvCodeBuffer& code) const; + + DxvkMetaResolvePipeline createPipeline( + const DxvkMetaResolvePipelineKey& key); + + VkRenderPass createRenderPass( + const DxvkMetaResolvePipelineKey& key); + + VkDescriptorSetLayout createDescriptorSetLayout( + const DxvkMetaResolvePipelineKey& key); + + VkPipelineLayout createPipelineLayout( + VkDescriptorSetLayout descriptorSetLayout); + + VkPipeline createPipelineObject( + const DxvkMetaResolvePipelineKey& key, + VkPipelineLayout pipelineLayout, + VkRenderPass renderPass); + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_objects.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_objects.h new file mode 100644 index 00000000000..aaa9e19bfa4 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_objects.h @@ -0,0 +1,100 @@ +#pragma once + +#include "dxvk_gpu_event.h" +#include "dxvk_gpu_query.h" +#include "dxvk_memory.h" +#include "dxvk_meta_blit.h" +#include "dxvk_meta_clear.h" +#include "dxvk_meta_copy.h" +#include "dxvk_meta_mipgen.h" +#include "dxvk_meta_pack.h" +#include "dxvk_meta_resolve.h" +#include "dxvk_pipemanager.h" +#include "dxvk_renderpass.h" +#include "dxvk_unbound.h" + +#include "../util/util_lazy.h" + +namespace dxvk { + + class DxvkObjects { + + public: + + DxvkObjects(DxvkDevice* device) + : m_device (device), + m_memoryManager (device), + m_renderPassPool (device), + m_pipelineManager (device, &m_renderPassPool), + m_eventPool (device), + m_queryPool (device), + m_dummyResources (device) { + + } + + DxvkMemoryAllocator& memoryManager() { + return m_memoryManager; + } + + DxvkRenderPassPool& renderPassPool() { + return m_renderPassPool; + } + + DxvkPipelineManager& pipelineManager() { + return m_pipelineManager; + } + + DxvkGpuEventPool& eventPool() { + return m_eventPool; + } + + DxvkGpuQueryPool& queryPool() { + return m_queryPool; + } + + DxvkUnboundResources& dummyResources() { + return m_dummyResources; + } + + DxvkMetaBlitObjects& metaBlit() { + return m_metaBlit.get(m_device); + } + + DxvkMetaClearObjects& metaClear() { + return m_metaClear.get(m_device); + } + + DxvkMetaCopyObjects& metaCopy() { + return m_metaCopy.get(m_device); + } + + DxvkMetaResolveObjects& metaResolve() { + return m_metaResolve.get(m_device); + } + + DxvkMetaPackObjects& metaPack() { + return m_metaPack.get(m_device); + } + + private: + + DxvkDevice* m_device; + + DxvkMemoryAllocator m_memoryManager; + DxvkRenderPassPool m_renderPassPool; + DxvkPipelineManager m_pipelineManager; + + DxvkGpuEventPool m_eventPool; + DxvkGpuQueryPool m_queryPool; + + DxvkUnboundResources m_dummyResources; + + Lazy m_metaBlit; + Lazy m_metaClear; + Lazy m_metaCopy; + Lazy m_metaResolve; + Lazy m_metaPack; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_openvr.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_openvr.cpp new file mode 100644 index 00000000000..48b0dea91f6 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_openvr.cpp @@ -0,0 +1,327 @@ +#include "dxvk_instance.h" +#include "dxvk_openvr.h" + +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wnon-virtual-dtor" +#endif + +#include + +using VR_InitInternalProc = vr::IVRSystem* (VR_CALLTYPE *)(vr::EVRInitError*, vr::EVRApplicationType); +using VR_ShutdownInternalProc = void (VR_CALLTYPE *)(); +using VR_GetGenericInterfaceProc = void* (VR_CALLTYPE *)(const char*, vr::EVRInitError*); + +namespace dxvk { + + struct VrFunctions { + VR_InitInternalProc initInternal = nullptr; + VR_ShutdownInternalProc shutdownInternal = nullptr; + VR_GetGenericInterfaceProc getGenericInterface = nullptr; + }; + + VrFunctions g_vrFunctions; + VrInstance VrInstance::s_instance; + + VrInstance:: VrInstance() { + m_no_vr = env::getEnvVar("DXVK_NO_VR") == "1"; + } + VrInstance::~VrInstance() { } + + + std::string_view VrInstance::getName() { + return "OpenVR"; + } + + + DxvkNameSet VrInstance::getInstanceExtensions() { + std::lock_guard lock(m_mutex); + return m_insExtensions; + } + + + DxvkNameSet VrInstance::getDeviceExtensions(uint32_t adapterId) { + std::lock_guard lock(m_mutex); + + if (adapterId < m_devExtensions.size()) + return m_devExtensions[adapterId]; + + return DxvkNameSet(); + } + + + void VrInstance::initInstanceExtensions() { + std::lock_guard lock(m_mutex); + + if (m_no_vr || m_initializedDevExt) + return; + + if (!m_vr_key) + { + LSTATUS status; + + if ((status = RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Wine\\VR", 0, KEY_READ, &m_vr_key))) + Logger::info(str::format("OpenVR: could not open registry key, status ", status)); + } + + if (!m_vr_key && !m_compositor) + m_compositor = this->getCompositor(); + + if (!m_vr_key && !m_compositor) + return; + + m_insExtensions = this->queryInstanceExtensions(); + m_initializedInsExt = true; + } + + + void VrInstance::initDeviceExtensions(const DxvkInstance* instance) { + std::lock_guard lock(m_mutex); + + if (m_no_vr || (!m_vr_key && !m_compositor) || m_initializedDevExt) + return; + + for (uint32_t i = 0; instance->enumAdapters(i) != nullptr; i++) { + m_devExtensions.push_back(this->queryDeviceExtensions( + instance->enumAdapters(i))); + } + + m_initializedDevExt = true; + this->shutdown(); + } + + bool VrInstance::waitVrKeyReady() const { + DWORD type, value, wait_status, size; + LSTATUS status; + HANDLE event; + + size = sizeof(value); + if ((status = RegQueryValueExA(m_vr_key, "state", nullptr, &type, reinterpret_cast(&value), &size))) + { + Logger::err(str::format("OpenVR: could not query value, status ", status)); + return false; + } + if (type != REG_DWORD) + { + Logger::err(str::format("OpenVR: unexpected value type ", type)); + return false; + } + + if (value) + return value == 1; + + event = CreateEventA(nullptr, FALSE, FALSE, nullptr); + while (1) + { + if (RegNotifyChangeKeyValue(m_vr_key, FALSE, REG_NOTIFY_CHANGE_LAST_SET, event, TRUE)) + { + Logger::err("Error registering registry change notification"); + goto done; + } + size = sizeof(value); + if ((status = RegQueryValueExA(m_vr_key, "state", nullptr, &type, reinterpret_cast(&value), &size))) + { + Logger::err(str::format("OpenVR: could not query value, status ", status)); + goto done; + } + if (value) + break; + while ((wait_status = WaitForSingleObject(event, 1000)) == WAIT_TIMEOUT) + Logger::warn("VR state wait timeout (retrying)"); + + if (wait_status != WAIT_OBJECT_0) + { + Logger::err(str::format("Got unexpected wait status ", wait_status)); + break; + } + } + + done: + CloseHandle(event); + return value == 1; + } + + DxvkNameSet VrInstance::queryInstanceExtensions() const { + std::vector extensionList; + DWORD len; + + if (m_vr_key) + { + LSTATUS status; + DWORD type; + + if (!this->waitVrKeyReady()) + return DxvkNameSet(); + + len = 0; + if ((status = RegQueryValueExA(m_vr_key, "openvr_vulkan_instance_extensions", nullptr, &type, nullptr, &len))) + { + Logger::err(str::format("OpenVR: could not query value, status ", status)); + return DxvkNameSet(); + } + extensionList.resize(len); + if ((status = RegQueryValueExA(m_vr_key, "openvr_vulkan_instance_extensions", nullptr, &type, reinterpret_cast(extensionList.data()), &len))) + { + Logger::err(str::format("OpenVR: could not query value, status ", status)); + return DxvkNameSet(); + } + } + else + { + len = m_compositor->GetVulkanInstanceExtensionsRequired(nullptr, 0); + extensionList.resize(len); + len = m_compositor->GetVulkanInstanceExtensionsRequired(extensionList.data(), len); + } + return parseExtensionList(std::string(extensionList.data(), len)); + } + + + DxvkNameSet VrInstance::queryDeviceExtensions(Rc adapter) const { + std::vector extensionList; + DWORD len; + + if (m_vr_key) + { + LSTATUS status; + char name[256]; + DWORD type; + + if (!this->waitVrKeyReady()) + return DxvkNameSet(); + + sprintf(name, "PCIID:%04x:%04x", adapter->deviceProperties().vendorID, adapter->deviceProperties().deviceID); + len = 0; + if ((status = RegQueryValueExA(m_vr_key, name, nullptr, &type, nullptr, &len))) + { + Logger::err(str::format("OpenVR: could not query value, status ", status)); + return DxvkNameSet(); + } + extensionList.resize(len); + if ((status = RegQueryValueExA(m_vr_key, name, nullptr, &type, reinterpret_cast(extensionList.data()), &len))) + { + Logger::err(str::format("OpenVR: could not query value, status ", status)); + return DxvkNameSet(); + } + } + else + { + len = m_compositor->GetVulkanDeviceExtensionsRequired(adapter->handle(), nullptr, 0); + extensionList.resize(len); + len = m_compositor->GetVulkanDeviceExtensionsRequired(adapter->handle(), extensionList.data(), len); + } + return parseExtensionList(std::string(extensionList.data(), len)); + } + + + DxvkNameSet VrInstance::parseExtensionList(const std::string& str) const { + DxvkNameSet result; + + std::stringstream strstream(str); + std::string section; + + while (std::getline(strstream, section, ' ')) + result.add(section.c_str()); + + return result; + } + + + vr::IVRCompositor* VrInstance::getCompositor() { + // Skip OpenVR initialization if requested + + // Locate the OpenVR DLL if loaded by the process. Some + // applications may not have OpenVR loaded at the time + // they create the DXGI instance, so we try our own DLL. + m_ovrApi = this->loadLibrary(); + + if (!m_ovrApi) { + Logger::info("OpenVR: Failed to locate module"); + return nullptr; + } + + // Load method used to retrieve the IVRCompositor interface + g_vrFunctions.initInternal = reinterpret_cast (this->getSym("VR_InitInternal")); + g_vrFunctions.shutdownInternal = reinterpret_cast (this->getSym("VR_ShutdownInternal")); + g_vrFunctions.getGenericInterface = reinterpret_cast(this->getSym("VR_GetGenericInterface")); + + if (!g_vrFunctions.getGenericInterface) { + Logger::warn("OpenVR: VR_GetGenericInterface not found"); + return nullptr; + } + + // Retrieve the compositor interface + vr::EVRInitError error = vr::VRInitError_None; + + vr::IVRCompositor* compositor = reinterpret_cast( + g_vrFunctions.getGenericInterface(vr::IVRCompositor_Version, &error)); + + if (error != vr::VRInitError_None || !compositor) { + if (!g_vrFunctions.initInternal + || !g_vrFunctions.shutdownInternal) { + Logger::warn("OpenVR: VR_InitInternal or VR_ShutdownInternal not found"); + return nullptr; + } + + // If the app has not initialized OpenVR yet, we need + // to do it now in order to grab a compositor instance + g_vrFunctions.initInternal(&error, vr::VRApplication_Background); + m_initializedOpenVr = error == vr::VRInitError_None; + + if (error != vr::VRInitError_None) { + Logger::warn("OpenVR: Failed to initialize OpenVR"); + return nullptr; + } + + compositor = reinterpret_cast( + g_vrFunctions.getGenericInterface(vr::IVRCompositor_Version, &error)); + + if (error != vr::VRInitError_None || !compositor) { + Logger::warn("OpenVR: Failed to query compositor interface"); + this->shutdown(); + return nullptr; + } + } + + Logger::info("OpenVR: Compositor interface found"); + return compositor; + } + + + void VrInstance::shutdown() { + if (m_vr_key) + { + RegCloseKey(m_vr_key); + m_vr_key = nullptr; + } + + if (m_initializedOpenVr) + g_vrFunctions.shutdownInternal(); + + if (m_loadedOvrApi) + this->freeLibrary(); + + m_initializedOpenVr = false; + m_loadedOvrApi = false; + } + + + HMODULE VrInstance::loadLibrary() { + HMODULE handle = nullptr; + if (!(handle = ::GetModuleHandle("openvr_api.dll"))) { + handle = ::LoadLibrary("openvr_api_dxvk.dll"); + m_loadedOvrApi = handle != nullptr; + } + return handle; + } + + + void VrInstance::freeLibrary() { + ::FreeLibrary(m_ovrApi); + } + + + void* VrInstance::getSym(const char* sym) { + return reinterpret_cast( + ::GetProcAddress(m_ovrApi, sym)); + } + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_openvr.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_openvr.h new file mode 100644 index 00000000000..a7d1042c4a0 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_openvr.h @@ -0,0 +1,83 @@ +#pragma once + +#include +#include + +#include "dxvk_extension_provider.h" + +namespace vr { + class IVRCompositor; + class IVRSystem; +} + +namespace dxvk { + + class DxvkInstance; + + /** + * \brief OpenVR instance + * + * Loads Initializes OpenVR to provide + * access to Vulkan extension queries. + */ + class VrInstance : public DxvkExtensionProvider { + + public: + + VrInstance(); + ~VrInstance(); + + std::string_view getName(); + + DxvkNameSet getInstanceExtensions(); + + DxvkNameSet getDeviceExtensions( + uint32_t adapterId); + + void initInstanceExtensions(); + + void initDeviceExtensions( + const DxvkInstance* instance); + + static VrInstance s_instance; + + private: + + dxvk::mutex m_mutex; + HKEY m_vr_key = nullptr; + vr::IVRCompositor* m_compositor = nullptr; + HMODULE m_ovrApi = nullptr; + + bool m_no_vr; + bool m_loadedOvrApi = false; + bool m_initializedOpenVr = false; + bool m_initializedInsExt = false; + bool m_initializedDevExt = false; + + DxvkNameSet m_insExtensions; + std::vector m_devExtensions; + + DxvkNameSet queryInstanceExtensions() const; + + DxvkNameSet queryDeviceExtensions( + Rc adapter) const; + + DxvkNameSet parseExtensionList( + const std::string& str) const; + + vr::IVRCompositor* getCompositor(); + + void shutdown(); + + HMODULE loadLibrary(); + + void freeLibrary(); + + void* getSym(const char* sym); + + bool waitVrKeyReady() const; + }; + + extern VrInstance g_vrInstance; + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_openxr.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_openxr.cpp new file mode 100644 index 00000000000..98f2dd9aa42 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_openxr.cpp @@ -0,0 +1,168 @@ +#include "dxvk_instance.h" +#include "dxvk_openxr.h" + +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wnon-virtual-dtor" +#endif + +using PFN___wineopenxr_GetVulkanInstanceExtensions = int (WINAPI *)(uint32_t, uint32_t *, char *); +using PFN___wineopenxr_GetVulkanDeviceExtensions = int (WINAPI *)(uint32_t, uint32_t *, char *); + +namespace dxvk { + + struct WineXrFunctions { + PFN___wineopenxr_GetVulkanInstanceExtensions __wineopenxr_GetVulkanInstanceExtensions = nullptr; + PFN___wineopenxr_GetVulkanDeviceExtensions __wineopenxr_GetVulkanDeviceExtensions = nullptr; + }; + + WineXrFunctions g_winexrFunctions; + DxvkXrProvider DxvkXrProvider::s_instance; + + DxvkXrProvider:: DxvkXrProvider() { } + + DxvkXrProvider::~DxvkXrProvider() { } + + + std::string_view DxvkXrProvider::getName() { + return "OpenXR"; + } + + + DxvkNameSet DxvkXrProvider::getInstanceExtensions() { + std::lock_guard lock(m_mutex); + return m_insExtensions; + } + + + DxvkNameSet DxvkXrProvider::getDeviceExtensions(uint32_t adapterId) { + std::lock_guard lock(m_mutex); + return m_devExtensions; + } + + + void DxvkXrProvider::initInstanceExtensions() { + std::lock_guard lock(m_mutex); + + if (!m_wineOxr) + m_wineOxr = this->loadLibrary(); + + if (!m_wineOxr || m_initializedInsExt) + return; + + if (!this->loadFunctions()) { + this->shutdown(); + return; + } + + m_insExtensions = this->queryInstanceExtensions(); + m_initializedInsExt = true; + } + + + bool DxvkXrProvider::loadFunctions() { + g_winexrFunctions.__wineopenxr_GetVulkanInstanceExtensions = + reinterpret_cast(this->getSym("__wineopenxr_GetVulkanInstanceExtensions")); + g_winexrFunctions.__wineopenxr_GetVulkanDeviceExtensions = + reinterpret_cast(this->getSym("__wineopenxr_GetVulkanDeviceExtensions")); + return g_winexrFunctions.__wineopenxr_GetVulkanInstanceExtensions != nullptr + && g_winexrFunctions.__wineopenxr_GetVulkanDeviceExtensions != nullptr; + } + + + void DxvkXrProvider::initDeviceExtensions(const DxvkInstance* instance) { + std::lock_guard lock(m_mutex); + + if (!m_wineOxr || m_initializedDevExt) + return; + + m_devExtensions = this->queryDeviceExtensions(); + m_initializedDevExt = true; + + this->shutdown(); + } + + + DxvkNameSet DxvkXrProvider::queryInstanceExtensions() const { + int res; + uint32_t len; + + res = g_winexrFunctions.__wineopenxr_GetVulkanInstanceExtensions(0, &len, nullptr); + if (res != 0) { + Logger::warn("OpenXR: Unable to get required Vulkan instance extensions size"); + return DxvkNameSet(); + } + + std::vector extensionList(len); + res = g_winexrFunctions.__wineopenxr_GetVulkanInstanceExtensions(len, &len, &extensionList[0]); + if (res != 0) { + Logger::warn("OpenXR: Unable to get required Vulkan instance extensions"); + return DxvkNameSet(); + } + + return parseExtensionList(std::string(extensionList.data(), len)); + } + + + DxvkNameSet DxvkXrProvider::queryDeviceExtensions() const { + int res; + + uint32_t len; + res = g_winexrFunctions.__wineopenxr_GetVulkanDeviceExtensions(0, &len, nullptr); + if (res != 0) { + Logger::warn("OpenXR: Unable to get required Vulkan Device extensions size"); + return DxvkNameSet(); + } + + std::vector extensionList(len); + res = g_winexrFunctions.__wineopenxr_GetVulkanDeviceExtensions(len, &len, &extensionList[0]); + if (res != 0) { + Logger::warn("OpenXR: Unable to get required Vulkan Device extensions"); + return DxvkNameSet(); + } + + return parseExtensionList(std::string(extensionList.data(), len)); + } + + + DxvkNameSet DxvkXrProvider::parseExtensionList(const std::string& str) const { + DxvkNameSet result; + + std::stringstream strstream(str); + std::string section; + + while (std::getline(strstream, section, ' ')) + result.add(section.c_str()); + + return result; + } + + + void DxvkXrProvider::shutdown() { + if (m_loadedOxrApi) + this->freeLibrary(); + + m_loadedOxrApi = false; + m_wineOxr = nullptr; + } + + + HMODULE DxvkXrProvider::loadLibrary() { + HMODULE handle = nullptr; + if (!(handle = ::GetModuleHandle("wineopenxr.dll"))) { + handle = ::LoadLibrary("wineopenxr.dll"); + m_loadedOxrApi = handle != nullptr; + } + return handle; + } + + + void DxvkXrProvider::freeLibrary() { + ::FreeLibrary(m_wineOxr); + } + + + void* DxvkXrProvider::getSym(const char* sym) { + return reinterpret_cast( + ::GetProcAddress(m_wineOxr, sym)); + } +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_openxr.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_openxr.h new file mode 100644 index 00000000000..a3680350fe9 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_openxr.h @@ -0,0 +1,69 @@ +#pragma once + +#include +#include + +#include "dxvk_extension_provider.h" + +namespace dxvk { + + class DxvkInstance; + + /** + * \brief OpenXR instance + * + * Loads OpenXR to provide access to Vulkan extension queries. + */ + class DxvkXrProvider : public DxvkExtensionProvider { + + public: + + DxvkXrProvider(); + ~DxvkXrProvider(); + + std::string_view getName(); + + DxvkNameSet getInstanceExtensions(); + + DxvkNameSet getDeviceExtensions( + uint32_t adapterId); + + void initInstanceExtensions(); + + void initDeviceExtensions( + const DxvkInstance* instance); + + static DxvkXrProvider s_instance; + + private: + + dxvk::mutex m_mutex; + HMODULE m_wineOxr = nullptr; + + bool m_loadedOxrApi = false; + bool m_initializedInsExt = false; + bool m_initializedDevExt = false; + + DxvkNameSet m_insExtensions; + DxvkNameSet m_devExtensions; + + DxvkNameSet queryInstanceExtensions() const; + + DxvkNameSet queryDeviceExtensions() const; + + DxvkNameSet parseExtensionList( + const std::string& str) const; + + bool loadFunctions(); + + void shutdown(); + + HMODULE loadLibrary(); + + void freeLibrary(); + + void* getSym(const char* sym); + + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_options.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_options.cpp new file mode 100644 index 00000000000..ea82eedc76c --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_options.cpp @@ -0,0 +1,14 @@ +#include "dxvk_options.h" + +namespace dxvk { + + DxvkOptions::DxvkOptions(const Config& config) { + enableDebugUtils = config.getOption ("dxvk.enableDebugUtils", false); + enableStateCache = config.getOption ("dxvk.enableStateCache", true); + numCompilerThreads = config.getOption ("dxvk.numCompilerThreads", 0); + useRawSsbo = config.getOption("dxvk.useRawSsbo", Tristate::Auto); + shrinkNvidiaHvvHeap = config.getOption("dxvk.shrinkNvidiaHvvHeap", Tristate::Auto); + hud = config.getOption("dxvk.hud", ""); + } + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_options.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_options.h new file mode 100644 index 00000000000..992ec764a99 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_options.h @@ -0,0 +1,31 @@ +#pragma once + +#include "../util/config/config.h" + +namespace dxvk { + + struct DxvkOptions { + DxvkOptions() { } + DxvkOptions(const Config& config); + + /// Enable debug utils (alternative to DXVK_PERF_EVENTS=1) + bool enableDebugUtils; + + /// Enable state cache + bool enableStateCache; + + /// Number of compiler threads + /// when using the state cache + int32_t numCompilerThreads; + + /// Shader-related options + Tristate useRawSsbo; + + /// Workaround for NVIDIA driver bug 3114283 + Tristate shrinkNvidiaHvvHeap; + + /// HUD elements + std::string hud; + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_pipecache.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_pipecache.cpp new file mode 100644 index 00000000000..3085e8b8da6 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_pipecache.cpp @@ -0,0 +1,5 @@ +#include "dxvk_pipecache.h" + +namespace dxvk { + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_pipecache.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_pipecache.h new file mode 100644 index 00000000000..03619e5364c --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_pipecache.h @@ -0,0 +1,37 @@ +#pragma once + +#include +#include +#include + +#include "dxvk_include.h" + +#include "../util/sha1/sha1_util.h" +#include "../util/util_env.h" +#include "../util/util_time.h" + +namespace dxvk { + + /** + * \brief Pipeline cache + * + * Allows the Vulkan implementation to + * re-use previously compiled pipelines. + */ + class DxvkPipelineCache : public RcObject { + + public: + + DxvkPipelineCache(const Rc& vkd) { } + + /** + * \brief Pipeline cache handle + * \returns Pipeline cache handle + */ + VkPipelineCache handle() const { + return VK_NULL_HANDLE; + } + + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_pipelayout.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_pipelayout.cpp new file mode 100644 index 00000000000..72b319a1469 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_pipelayout.cpp @@ -0,0 +1,197 @@ +#include + +#include "dxvk_descriptor.h" +#include "dxvk_limits.h" +#include "dxvk_pipelayout.h" + +namespace dxvk { + + DxvkDescriptorSlotMapping:: DxvkDescriptorSlotMapping() { } + DxvkDescriptorSlotMapping::~DxvkDescriptorSlotMapping() { } + + + void DxvkDescriptorSlotMapping::defineSlot( + VkShaderStageFlagBits stage, + const DxvkResourceSlot& desc) { + uint32_t bindingId = this->getBindingId(desc.slot); + + if (bindingId != InvalidBinding) { + m_descriptorSlots[bindingId].stages |= stage; + m_descriptorSlots[bindingId].access |= desc.access; + } else { + DxvkDescriptorSlot slotInfo; + slotInfo.slot = desc.slot; + slotInfo.type = desc.type; + slotInfo.view = desc.view; + slotInfo.stages = stage; + slotInfo.access = desc.access; + m_descriptorSlots.push_back(slotInfo); + } + } + + + void DxvkDescriptorSlotMapping::definePushConstRange( + VkShaderStageFlagBits stage, + uint32_t offset, + uint32_t size) { + m_pushConstRange.stageFlags |= stage; + m_pushConstRange.size = std::max( + m_pushConstRange.size, offset + size); + } + + + uint32_t DxvkDescriptorSlotMapping::getBindingId(uint32_t slot) const { + // This won't win a performance competition, but the number + // of bindings used by a shader is usually much smaller than + // the number of resource slots available to the system. + for (uint32_t i = 0; i < m_descriptorSlots.size(); i++) { + if (m_descriptorSlots[i].slot == slot) + return i; + } + + return InvalidBinding; + } + + + void DxvkDescriptorSlotMapping::makeDescriptorsDynamic( + uint32_t uniformBuffers, + uint32_t storageBuffers) { + if (this->countDescriptors(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) <= uniformBuffers) + this->replaceDescriptors(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC); + } + + + uint32_t DxvkDescriptorSlotMapping::countDescriptors( + VkDescriptorType type) const { + uint32_t count = 0; + + for (const auto& slot : m_descriptorSlots) + count += slot.type == type ? 1 : 0; + + return count; + } + + + void DxvkDescriptorSlotMapping::replaceDescriptors( + VkDescriptorType oldType, + VkDescriptorType newType) { + for (auto& slot : m_descriptorSlots) { + if (slot.type == oldType) + slot.type = newType; + } + } + + + DxvkPipelineLayout::DxvkPipelineLayout( + const Rc& vkd, + const DxvkDescriptorSlotMapping& slotMapping, + VkPipelineBindPoint pipelineBindPoint) + : m_vkd (vkd), + m_pushConstRange(slotMapping.pushConstRange()), + m_bindingSlots (slotMapping.bindingCount()) { + + auto bindingCount = slotMapping.bindingCount(); + auto bindingInfos = slotMapping.bindingInfos(); + + if (bindingCount > MaxNumActiveBindings) + throw DxvkError(str::format("Too many active bindings in pipeline layout (", bindingCount, ")")); + + for (uint32_t i = 0; i < bindingCount; i++) + m_bindingSlots[i] = bindingInfos[i]; + + std::vector bindings(bindingCount); + std::vector tEntries(bindingCount); + + for (uint32_t i = 0; i < bindingCount; i++) { + bindings[i].binding = i; + bindings[i].descriptorType = bindingInfos[i].type; + bindings[i].descriptorCount = 1; + bindings[i].stageFlags = bindingInfos[i].stages; + bindings[i].pImmutableSamplers = nullptr; + + tEntries[i].dstBinding = i; + tEntries[i].dstArrayElement = 0; + tEntries[i].descriptorCount = 1; + tEntries[i].descriptorType = bindingInfos[i].type; + tEntries[i].offset = sizeof(DxvkDescriptorInfo) * i; + tEntries[i].stride = 0; + + if (bindingInfos[i].type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) + m_dynamicSlots.push_back(i); + + m_descriptorTypes.set(bindingInfos[i].type); + } + + // Create descriptor set layout. We do not need to + // create one if there are no active resource bindings. + if (bindingCount > 0) { + VkDescriptorSetLayoutCreateInfo dsetInfo; + dsetInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + dsetInfo.pNext = nullptr; + dsetInfo.flags = 0; + dsetInfo.bindingCount = bindings.size(); + dsetInfo.pBindings = bindings.data(); + + if (m_vkd->vkCreateDescriptorSetLayout(m_vkd->device(), + &dsetInfo, nullptr, &m_descriptorSetLayout) != VK_SUCCESS) + throw DxvkError("DxvkPipelineLayout: Failed to create descriptor set layout"); + } + + // Create pipeline layout with the given descriptor set layout + VkPipelineLayoutCreateInfo pipeInfo; + pipeInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + pipeInfo.pNext = nullptr; + pipeInfo.flags = 0; + pipeInfo.setLayoutCount = bindingCount > 0 ? 1 : 0; + pipeInfo.pSetLayouts = &m_descriptorSetLayout; + pipeInfo.pushConstantRangeCount = 0; + pipeInfo.pPushConstantRanges = nullptr; + + if (m_pushConstRange.size) { + pipeInfo.pushConstantRangeCount = 1; + pipeInfo.pPushConstantRanges = &m_pushConstRange; + } + + if (m_vkd->vkCreatePipelineLayout(m_vkd->device(), + &pipeInfo, nullptr, &m_pipelineLayout) != VK_SUCCESS) { + m_vkd->vkDestroyDescriptorSetLayout(m_vkd->device(), m_descriptorSetLayout, nullptr); + throw DxvkError("DxvkPipelineLayout: Failed to create pipeline layout"); + } + + // Create descriptor update template. If there are no active + // resource bindings, there won't be any descriptors to update. + if (bindingCount > 0) { + VkDescriptorUpdateTemplateCreateInfo templateInfo; + templateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO; + templateInfo.pNext = nullptr; + templateInfo.flags = 0; + templateInfo.descriptorUpdateEntryCount = tEntries.size(); + templateInfo.pDescriptorUpdateEntries = tEntries.data(); + templateInfo.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET; + templateInfo.descriptorSetLayout = m_descriptorSetLayout; + templateInfo.pipelineBindPoint = pipelineBindPoint; + templateInfo.pipelineLayout = m_pipelineLayout; + templateInfo.set = 0; + + if (m_vkd->vkCreateDescriptorUpdateTemplate( + m_vkd->device(), &templateInfo, nullptr, &m_descriptorTemplate) != VK_SUCCESS) { + m_vkd->vkDestroyDescriptorSetLayout(m_vkd->device(), m_descriptorSetLayout, nullptr); + m_vkd->vkDestroyPipelineLayout(m_vkd->device(), m_pipelineLayout, nullptr); + throw DxvkError("DxvkPipelineLayout: Failed to create descriptor update template"); + } + } + } + + + DxvkPipelineLayout::~DxvkPipelineLayout() { + m_vkd->vkDestroyDescriptorUpdateTemplate( + m_vkd->device(), m_descriptorTemplate, nullptr); + + m_vkd->vkDestroyPipelineLayout( + m_vkd->device(), m_pipelineLayout, nullptr); + + m_vkd->vkDestroyDescriptorSetLayout( + m_vkd->device(), m_descriptorSetLayout, nullptr); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_pipelayout.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_pipelayout.h new file mode 100644 index 00000000000..9e96b34b4ad --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_pipelayout.h @@ -0,0 +1,281 @@ +#pragma once + +#include + +#include "dxvk_include.h" + +namespace dxvk { + + /** + * \brief Resource slot + * + * Describes the type of a single resource + * binding that a shader can access. + */ + struct DxvkResourceSlot { + uint32_t slot; + VkDescriptorType type; + VkImageViewType view; + VkAccessFlags access; + }; + + /** + * \brief Shader interface binding + * + * Corresponds to a single descriptor binding in + * Vulkan. DXVK does not use descriptor arrays. + * Instead, each binding stores one descriptor. + */ + struct DxvkDescriptorSlot { + uint32_t slot; ///< Resource slot index for the context + VkDescriptorType type; ///< Descriptor type (aka resource type) + VkImageViewType view; ///< Compatible image view type + VkShaderStageFlags stages; ///< Stages that can use the resource + VkAccessFlags access; ///< Access flags + }; + + + /** + * \brief Descriptor slot mapping + * + * Convenience class that generates descriptor slot + * index to binding index mappings. This is required + * when generating Vulkan pipeline and descriptor set + * layouts. + */ + class DxvkDescriptorSlotMapping { + constexpr static uint32_t InvalidBinding = 0xFFFFFFFFu; + public: + + DxvkDescriptorSlotMapping(); + ~DxvkDescriptorSlotMapping(); + + /** + * \brief Number of descriptor bindings + * \returns Descriptor binding count + */ + uint32_t bindingCount() const { + return m_descriptorSlots.size(); + } + + /** + * \brief Descriptor binding infos + * \returns Descriptor binding infos + */ + const DxvkDescriptorSlot* bindingInfos() const { + return m_descriptorSlots.data(); + } + + /** + * \brief Push constant range + * \returns Push constant range + */ + VkPushConstantRange pushConstRange() const { + return m_pushConstRange; + } + + /** + * \brief Defines a new slot + * + * Adds a slot to the mapping. If the slot is already + * defined by another shader stage, this will extend + * the stage mask by the given stage. Otherwise, an + * entirely new binding is added. + * \param [in] stage Shader stage + * \param [in] desc Slot description + */ + void defineSlot( + VkShaderStageFlagBits stage, + const DxvkResourceSlot& desc); + + /** + * \brief Defines new push constant range + * + * \param [in] stage Shader stage + * \param [in] offset Range offset + * \param [in] size Range size + */ + void definePushConstRange( + VkShaderStageFlagBits stage, + uint32_t offset, + uint32_t size); + + /** + * \brief Gets binding ID for a slot + * + * \param [in] slot Resource slot + * \returns Binding index, or \c InvalidBinding + */ + uint32_t getBindingId( + uint32_t slot) const; + + /** + * \brief Makes static descriptors dynamic + * + * Replaces static uniform and storage buffer bindings by + * their dynamic equivalent if the number of bindings of + * the respective type lies within supported device limits. + * Using dynamic descriptor types may improve performance. + * \param [in] uniformBuffers Max number of uniform buffers + * \param [in] storageBuffers Max number of storage buffers + */ + void makeDescriptorsDynamic( + uint32_t uniformBuffers, + uint32_t storageBuffers); + + private: + + std::vector m_descriptorSlots; + VkPushConstantRange m_pushConstRange = { }; + + uint32_t countDescriptors( + VkDescriptorType type) const; + + void replaceDescriptors( + VkDescriptorType oldType, + VkDescriptorType newType); + + }; + + + /** + * \brief Shader interface + * + * Describes shader resource bindings + * for a graphics or compute pipeline. + */ + class DxvkPipelineLayout : public RcObject { + + public: + + DxvkPipelineLayout( + const Rc& vkd, + const DxvkDescriptorSlotMapping& slotMapping, + VkPipelineBindPoint pipelineBindPoint); + + ~DxvkPipelineLayout(); + + /** + * \brief Number of resource bindings + * \returns Resource binding count + */ + uint32_t bindingCount() const { + return m_bindingSlots.size(); + } + + /** + * \brief Resource binding info + * + * \param [in] id Binding index + * \returns Resource binding info + */ + const DxvkDescriptorSlot& binding(uint32_t id) const { + return m_bindingSlots[id]; + } + + /** + * \brief Resource binding info + * \returns Resource binding info + */ + const DxvkDescriptorSlot* bindings() const { + return m_bindingSlots.data(); + } + + /** + * \brief Push constant range + * \returns Push constant range + */ + const VkPushConstantRange& pushConstRange() const { + return m_pushConstRange; + } + + /** + * \brief Descriptor set layout handle + * \returns Descriptor set layout handle + */ + VkDescriptorSetLayout descriptorSetLayout() const { + return m_descriptorSetLayout; + } + + /** + * \brief Pipeline layout handle + * \returns Pipeline layout handle + */ + VkPipelineLayout pipelineLayout() const { + return m_pipelineLayout; + } + + /** + * \brief Descriptor update template + * \returns Descriptor update template + */ + VkDescriptorUpdateTemplateKHR descriptorTemplate() const { + return m_descriptorTemplate; + } + + /** + * \brief Number of dynamic bindings + * \returns Dynamic binding count + */ + uint32_t dynamicBindingCount() const { + return m_dynamicSlots.size(); + } + + /** + * \brief Returns a dynamic binding + * + * \param [in] id Dynamic binding ID + * \returns Reference to that binding + */ + const DxvkDescriptorSlot& dynamicBinding(uint32_t id) const { + return this->binding(m_dynamicSlots[id]); + } + + /** + * \brief Checks for static buffer bindings + * + * Returns \c true if there is at least one + * descriptor of the static uniform buffer + * type. + */ + bool hasStaticBufferBindings() const { + return m_descriptorTypes.test( + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); + } + + /** + * \brief Checks whether buffers or images are written to + * + * It is assumed that storage images and buffers + * will be written to if they are present. Used + * for synchronization purposes. + * \param [in] stages Shader stages to check + */ + VkShaderStageFlags getStorageDescriptorStages() const { + VkShaderStageFlags stages = 0; + + for (const auto& slot : m_bindingSlots) { + if (slot.access & VK_ACCESS_SHADER_WRITE_BIT) + stages |= slot.stages; + } + + return stages; + } + + private: + + Rc m_vkd; + + VkPushConstantRange m_pushConstRange = { }; + VkDescriptorSetLayout m_descriptorSetLayout = VK_NULL_HANDLE; + VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE; + VkDescriptorUpdateTemplateKHR m_descriptorTemplate = VK_NULL_HANDLE; + + std::vector m_bindingSlots; + std::vector m_dynamicSlots; + + Flags m_descriptorTypes; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_pipemanager.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_pipemanager.cpp new file mode 100644 index 00000000000..4c5ea32fb8e --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_pipemanager.cpp @@ -0,0 +1,88 @@ +#include "dxvk_device.h" +#include "dxvk_pipemanager.h" +#include "dxvk_state_cache.h" + +namespace dxvk { + + DxvkPipelineManager::DxvkPipelineManager( + DxvkDevice* device, + DxvkRenderPassPool* passManager) + : m_device (device), + m_cache (new DxvkPipelineCache(device->vkd())) { + std::string useStateCache = env::getEnvVar("DXVK_STATE_CACHE"); + + if (useStateCache != "0" && device->config().enableStateCache) + m_stateCache = new DxvkStateCache(device, this, passManager); + } + + + DxvkPipelineManager::~DxvkPipelineManager() { + + } + + + DxvkComputePipeline* DxvkPipelineManager::createComputePipeline( + const DxvkComputePipelineShaders& shaders) { + if (shaders.cs == nullptr) + return nullptr; + + std::lock_guard lock(m_mutex); + + auto pair = m_computePipelines.find(shaders); + if (pair != m_computePipelines.end()) + return &pair->second; + + auto iter = m_computePipelines.emplace( + std::piecewise_construct, + std::tuple(shaders), + std::tuple(this, shaders)); + return &iter.first->second; + } + + + DxvkGraphicsPipeline* DxvkPipelineManager::createGraphicsPipeline( + const DxvkGraphicsPipelineShaders& shaders) { + if (shaders.vs == nullptr) + return nullptr; + + std::lock_guard lock(m_mutex); + + auto pair = m_graphicsPipelines.find(shaders); + if (pair != m_graphicsPipelines.end()) + return &pair->second; + + auto iter = m_graphicsPipelines.emplace( + std::piecewise_construct, + std::tuple(shaders), + std::tuple(this, shaders)); + return &iter.first->second; + } + + + void DxvkPipelineManager::registerShader( + const Rc& shader) { + if (m_stateCache != nullptr) + m_stateCache->registerShader(shader); + } + + + DxvkPipelineCount DxvkPipelineManager::getPipelineCount() const { + DxvkPipelineCount result; + result.numComputePipelines = m_numComputePipelines.load(); + result.numGraphicsPipelines = m_numGraphicsPipelines.load(); + return result; + } + + + bool DxvkPipelineManager::isCompilingShaders() const { + return m_stateCache != nullptr + && m_stateCache->isCompilingShaders(); + } + + + void DxvkPipelineManager::stopWorkerThreads() const { + if (m_stateCache != nullptr) + m_stateCache->stopWorkerThreads(); + } + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_pipemanager.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_pipemanager.h new file mode 100644 index 00000000000..08c79e0a8d9 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_pipemanager.h @@ -0,0 +1,121 @@ + +#pragma once + +#include +#include + +#include "dxvk_compute.h" +#include "dxvk_graphics.h" + +namespace dxvk { + + class DxvkStateCache; + + /** + * \brief Pipeline count + * + * Stores number of graphics and + * compute pipelines, individually. + */ + struct DxvkPipelineCount { + uint32_t numGraphicsPipelines; + uint32_t numComputePipelines; + }; + + + /** + * \brief Pipeline manager + * + * Creates and stores graphics pipelines and compute + * pipelines for each combination of shaders that is + * used within the application. This is necessary + * because DXVK does not expose the concept of shader + * pipeline objects to the client API. + */ + class DxvkPipelineManager { + friend class DxvkComputePipeline; + friend class DxvkGraphicsPipeline; + public: + + DxvkPipelineManager( + DxvkDevice* device, + DxvkRenderPassPool* passManager); + + ~DxvkPipelineManager(); + + /** + * \brief Retrieves a compute pipeline object + * + * If a pipeline for the given shader stage object + * already exists, it will be returned. Otherwise, + * a new pipeline will be created. + * \param [in] shaders Shaders for the pipeline + * \returns Compute pipeline object + */ + DxvkComputePipeline* createComputePipeline( + const DxvkComputePipelineShaders& shaders); + + /** + * \brief Retrieves a graphics pipeline object + * + * If a pipeline for the given shader stage objects + * already exists, it will be returned. Otherwise, + * a new pipeline will be created. + * \param [in] shaders Shaders for the pipeline + * \returns Graphics pipeline object + */ + DxvkGraphicsPipeline* createGraphicsPipeline( + const DxvkGraphicsPipelineShaders& shaders); + + /* + * \brief Registers a shader + * + * Starts compiling pipelines asynchronously + * in case the state cache contains state + * vectors for this shader. + * \param [in] shader Newly compiled shader + */ + void registerShader( + const Rc& shader); + + /** + * \brief Retrieves total pipeline count + * \returns Number of compute/graphics pipelines + */ + DxvkPipelineCount getPipelineCount() const; + + /** + * \brief Checks whether async compiler is busy + * \returns \c true if shaders are being compiled + */ + bool isCompilingShaders() const; + + /** + * \brief Stops async compiler threads + */ + void stopWorkerThreads() const; + + private: + + DxvkDevice* m_device; + Rc m_cache; + Rc m_stateCache; + + std::atomic m_numComputePipelines = { 0 }; + std::atomic m_numGraphicsPipelines = { 0 }; + + dxvk::mutex m_mutex; + + std::unordered_map< + DxvkComputePipelineShaders, + DxvkComputePipeline, + DxvkHash, DxvkEq> m_computePipelines; + + std::unordered_map< + DxvkGraphicsPipelineShaders, + DxvkGraphicsPipeline, + DxvkHash, DxvkEq> m_graphicsPipelines; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_platform_exts.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_platform_exts.h new file mode 100644 index 00000000000..f6f030675e5 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_platform_exts.h @@ -0,0 +1,26 @@ +#pragma once + +#include "dxvk_extension_provider.h" + +namespace dxvk { + + class DxvkPlatformExts : public DxvkExtensionProvider { + + public: + + std::string_view getName(); + + DxvkNameSet getInstanceExtensions(); + + DxvkNameSet getDeviceExtensions( + uint32_t adapterId); + + void initInstanceExtensions(); + + void initDeviceExtensions( + const DxvkInstance* instance); + + static DxvkPlatformExts s_instance; + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_queue.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_queue.cpp new file mode 100644 index 00000000000..86f0b4e3536 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_queue.cpp @@ -0,0 +1,192 @@ +#include "dxvk_device.h" +#include "dxvk_queue.h" + +namespace dxvk { + + DxvkSubmissionQueue::DxvkSubmissionQueue(DxvkDevice* device) + : m_device(device), + m_submitThread([this] () { submitCmdLists(); }), + m_finishThread([this] () { finishCmdLists(); }) { + + } + + + DxvkSubmissionQueue::~DxvkSubmissionQueue() { + { std::unique_lock lock(m_mutex); + m_stopped.store(true); + } + + m_appendCond.notify_all(); + m_submitCond.notify_all(); + + m_submitThread.join(); + m_finishThread.join(); + } + + + void DxvkSubmissionQueue::submit(DxvkSubmitInfo submitInfo) { + std::unique_lock lock(m_mutex); + + m_finishCond.wait(lock, [this] { + return m_submitQueue.size() + m_finishQueue.size() <= MaxNumQueuedCommandBuffers; + }); + + DxvkSubmitEntry entry = { }; + entry.submit = std::move(submitInfo); + + m_pending += 1; + m_submitQueue.push(std::move(entry)); + m_appendCond.notify_all(); + } + + + void DxvkSubmissionQueue::present(DxvkPresentInfo presentInfo, DxvkSubmitStatus* status) { + std::unique_lock lock(m_mutex); + + DxvkSubmitEntry entry = { }; + entry.status = status; + entry.present = std::move(presentInfo); + + m_submitQueue.push(std::move(entry)); + m_appendCond.notify_all(); + } + + + void DxvkSubmissionQueue::synchronizeSubmission( + DxvkSubmitStatus* status) { + std::unique_lock lock(m_mutex); + + m_submitCond.wait(lock, [status] { + return status->result.load() != VK_NOT_READY; + }); + } + + + void DxvkSubmissionQueue::synchronize() { + std::unique_lock lock(m_mutex); + + m_submitCond.wait(lock, [this] { + return m_submitQueue.empty(); + }); + } + + + void DxvkSubmissionQueue::lockDeviceQueue() { + m_mutexQueue.lock(); + } + + + void DxvkSubmissionQueue::unlockDeviceQueue() { + m_mutexQueue.unlock(); + } + + + void DxvkSubmissionQueue::submitCmdLists() { + env::setThreadName("dxvk-submit"); + + std::unique_lock lock(m_mutex); + + while (!m_stopped.load()) { + m_appendCond.wait(lock, [this] { + return m_stopped.load() || !m_submitQueue.empty(); + }); + + if (m_stopped.load()) + return; + + DxvkSubmitEntry entry = std::move(m_submitQueue.front()); + lock.unlock(); + + // Submit command buffer to device + VkResult status = VK_NOT_READY; + + if (m_lastError != VK_ERROR_DEVICE_LOST) { + std::lock_guard lock(m_mutexQueue); + + if (entry.submit.cmdList != nullptr) { + status = entry.submit.cmdList->submit( + entry.submit.waitSync, + entry.submit.wakeSync); + } else if (entry.present.presenter != nullptr) { + status = entry.present.presenter->presentImage(); + } + } else { + // Don't submit anything after device loss + // so that drivers get a chance to recover + status = VK_ERROR_DEVICE_LOST; + } + + if (entry.status) + entry.status->result = status; + + // On success, pass it on to the queue thread + lock = std::unique_lock(m_mutex); + + if (status == VK_SUCCESS) { + if (entry.submit.cmdList != nullptr) + m_finishQueue.push(std::move(entry)); + } else if (status == VK_ERROR_DEVICE_LOST || entry.submit.cmdList != nullptr) { + Logger::err(str::format("DxvkSubmissionQueue: Command submission failed: ", status)); + m_lastError = status; + m_device->waitForIdle(); + } + + m_submitQueue.pop(); + m_submitCond.notify_all(); + } + } + + + void DxvkSubmissionQueue::finishCmdLists() { + env::setThreadName("dxvk-queue"); + + while (!m_stopped.load()) { + std::unique_lock lock(m_mutex); + + if (m_finishQueue.empty()) { + auto t0 = dxvk::high_resolution_clock::now(); + + m_submitCond.wait(lock, [this] { + return m_stopped.load() || !m_finishQueue.empty(); + }); + + auto t1 = dxvk::high_resolution_clock::now(); + m_gpuIdle += std::chrono::duration_cast(t1 - t0).count(); + } + + if (m_stopped.load()) + return; + + DxvkSubmitEntry entry = std::move(m_finishQueue.front()); + lock.unlock(); + + VkResult status = m_lastError.load(); + + if (status != VK_ERROR_DEVICE_LOST) + status = entry.submit.cmdList->synchronize(); + + if (status != VK_SUCCESS) { + Logger::err(str::format("DxvkSubmissionQueue: Failed to sync fence: ", status)); + m_lastError = status; + m_device->waitForIdle(); + } + + // Release resources and signal events, then immediately wake + // up any thread that's currently waiting on a resource in + // order to reduce delays as much as possible. + entry.submit.cmdList->notifyObjects(); + + lock.lock(); + m_pending -= 1; + + m_finishQueue.pop(); + m_finishCond.notify_all(); + lock.unlock(); + + // Free the command list and associated objects now + entry.submit.cmdList->reset(); + m_device->recycleCommandList(entry.submit.cmdList); + } + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_queue.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_queue.h new file mode 100644 index 00000000000..374da55edb1 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_queue.h @@ -0,0 +1,210 @@ +#pragma once + +#include +#include +#include + +#include "../util/thread.h" + +#include "../vulkan/vulkan_presenter.h" + +#include "dxvk_cmdlist.h" + +namespace dxvk { + + class DxvkDevice; + + /** + * \brief Submission status + * + * Stores the result of a queue + * submission or a present call. + */ + struct DxvkSubmitStatus { + std::atomic result = { VK_SUCCESS }; + }; + + + /** + * \brief Queue submission info + * + * Stores parameters used to submit + * a command buffer to the device. + */ + struct DxvkSubmitInfo { + Rc cmdList; + VkSemaphore waitSync; + VkSemaphore wakeSync; + }; + + + /** + * \brief Present info + * + * Stores parameters used to present + * a swap chain image on the device. + */ + struct DxvkPresentInfo { + Rc presenter; + }; + + + /** + * \brief Submission queue entry + */ + struct DxvkSubmitEntry { + DxvkSubmitStatus* status; + DxvkSubmitInfo submit; + DxvkPresentInfo present; + }; + + + /** + * \brief Submission queue + */ + class DxvkSubmissionQueue { + + public: + + DxvkSubmissionQueue(DxvkDevice* device); + ~DxvkSubmissionQueue(); + + /** + * \brief Number of pending submissions + * + * A return value of 0 indicates + * that the GPU is currently idle. + * \returns Pending submission count + */ + uint32_t pendingSubmissions() const { + return m_pending.load(); + } + + /** + * \brief Retrieves estimated GPU idle time + * + * This is a monotonically increasing counter + * which can be evaluated periodically in order + * to calculate the GPU load. + * \returns Accumulated GPU idle time, in us + */ + uint64_t gpuIdleTicks() const { + return m_gpuIdle.load(); + } + + /** + * \brief Retrieves last submission error + * + * In case an error occured during asynchronous command + * submission, it will be returned by this function. + * \returns Last error from command submission + */ + VkResult getLastError() const { + return m_lastError.load(); + } + + /** + * \brief Submits a command list asynchronously + * + * Queues a command list for submission on the + * dedicated submission thread. Use this to take + * the submission overhead off the calling thread. + * \param [in] submitInfo Submission parameters + */ + void submit( + DxvkSubmitInfo submitInfo); + + /** + * \brief Presents an image synchronously + * + * Waits for queued command lists to be submitted + * and then presents the current swap chain image + * of the presenter. May stall the calling thread. + * \param [in] present Present parameters + * \returns Status of the operation + */ + void present( + DxvkPresentInfo presentInfo, + DxvkSubmitStatus* status); + + /** + * \brief Synchronizes with one queue submission + * + * Waits for the result of the given submission + * or present operation to become available. + * \param [in,out] status Submission status + */ + void synchronizeSubmission( + DxvkSubmitStatus* status); + + /** + * \brief Synchronizes with queue submissions + * + * Waits for all pending command lists to be + * submitted to the GPU before returning. + */ + void synchronize(); + + /** + * \brief Synchronizes until a given condition becomes true + * + * Useful to wait for the GPU without busy-waiting. + * \param [in] pred Predicate to check + */ + template + void synchronizeUntil(const Pred& pred) { + std::unique_lock lock(m_mutex); + m_finishCond.wait(lock, pred); + } + + /** + * \brief Locks device queue + * + * Locks the mutex that protects the Vulkan queue + * that DXVK uses for command buffer submission. + * This is needed when the app submits its own + * command buffers to the queue. + */ + void lockDeviceQueue(); + + /** + * \brief Unlocks device queue + * + * Unlocks the mutex that protects the Vulkan + * queue used for command buffer submission. + */ + void unlockDeviceQueue(); + + private: + + DxvkDevice* m_device; + + std::atomic m_lastError = { VK_SUCCESS }; + + std::atomic m_stopped = { false }; + std::atomic m_pending = { 0u }; + std::atomic m_gpuIdle = { 0ull }; + + dxvk::mutex m_mutex; + dxvk::mutex m_mutexQueue; + + dxvk::condition_variable m_appendCond; + dxvk::condition_variable m_submitCond; + dxvk::condition_variable m_finishCond; + + std::queue m_submitQueue; + std::queue m_finishQueue; + + dxvk::thread m_submitThread; + dxvk::thread m_finishThread; + + VkResult submitToQueue( + const DxvkSubmitInfo& submission); + + void submitCmdLists(); + + void finishCmdLists(); + + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_recycler.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_recycler.h new file mode 100644 index 00000000000..b90befd4fc3 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_recycler.h @@ -0,0 +1,63 @@ +#pragma once + +#include +#include + +namespace dxvk { + + /** + * \brief Object recycler + * + * Implements a thread-safe buffer that can store up to + * a given number of objects of a certain type. This way, + * DXVK can efficiently reuse and reset objects instead + * of destroying them and creating them anew. + * \tparam T Type of the objects to store + * \tparam N Maximum number of objects to store + */ + template + class DxvkRecycler { + + public: + + /** + * \brief Retrieves an object if possible + * + * Returns an object that was returned to the recycler + * earier. In case no objects are available, this will + * return \c nullptr and a new object has to be created. + * \return An object, or \c nullptr + */ + Rc retrieveObject() { + std::lock_guard lock(m_mutex); + + if (m_objectId == 0) + return nullptr; + + return m_objects.at(--m_objectId); + } + + /** + * \brief Returns an object to the recycler + * + * If the buffer is full, the object will be destroyed + * once the last reference runs out of scope. No further + * action needs to be taken in this case. + * \param [in] object The object to return + */ + void returnObject(const Rc& object) { + std::lock_guard lock(m_mutex); + + if (m_objectId < N) + m_objects.at(m_objectId++) = object; + } + + private: + + dxvk::mutex m_mutex; + std::array, N> m_objects; + size_t m_objectId = 0; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_renderpass.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_renderpass.cpp new file mode 100644 index 00000000000..2bac17087f4 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_renderpass.cpp @@ -0,0 +1,332 @@ +#include + +#include "dxvk_device.h" +#include "dxvk_renderpass.h" + +namespace dxvk { + + bool DxvkRenderPassFormat::eq(const DxvkRenderPassFormat& fmt) const { + bool eq = sampleCount == fmt.sampleCount; + + for (uint32_t i = 0; i < MaxNumRenderTargets && eq; i++) { + eq &= color[i].format == fmt.color[i].format + && color[i].layout == fmt.color[i].layout; + } + + eq &= depth.format == fmt.depth.format + && depth.layout == fmt.depth.layout; + + return eq; + } + + + size_t DxvkRenderPassFormat::hash() const { + DxvkHashState state; + state.add(uint32_t(sampleCount)); + + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { + state.add(uint32_t(color[i].format)); + state.add(uint32_t(color[i].layout)); + } + + state.add(uint32_t(depth.format)); + state.add(uint32_t(depth.layout)); + return state; + } + + + DxvkRenderPass::DxvkRenderPass( + const Rc& vkd, + const DxvkRenderPassFormat& fmt) + : m_vkd(vkd), m_format(fmt), + m_default(createRenderPass(DxvkRenderPassOps())) { + + } + + + DxvkRenderPass::~DxvkRenderPass() { + m_vkd->vkDestroyRenderPass(m_vkd->device(), m_default, nullptr); + + for (const auto& i : m_instances) { + m_vkd->vkDestroyRenderPass( + m_vkd->device(), i.handle, nullptr); + } + } + + + bool DxvkRenderPass::hasCompatibleFormat(const DxvkRenderPassFormat& fmt) const { + return m_format.eq(fmt); + } + + + VkRenderPass DxvkRenderPass::getHandle(const DxvkRenderPassOps& ops) { + VkRenderPass handle = this->findHandle(ops); + + if (unlikely(!handle)) { + std::lock_guard lock(m_mutex); + handle = this->findHandle(ops); + + if (!handle) { + handle = this->createRenderPass(ops); + m_instances.insert({ ops, handle }); + } + } + + return handle; + } + + + VkRenderPass DxvkRenderPass::findHandle(const DxvkRenderPassOps& ops) { + for (const auto& i : m_instances) { + if (compareOps(i.ops, ops)) + return i.handle; + } + + return VK_NULL_HANDLE; + } + + + VkRenderPass DxvkRenderPass::createRenderPass(const DxvkRenderPassOps& ops) { + std::vector attachments; + + VkAttachmentReference depthRef; + std::array colorRef; + + // Render passes may not require the previous + // contents of the attachments to be preserved. + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { + if (m_format.color[i].format != VK_FORMAT_UNDEFINED) { + VkAttachmentDescription desc; + desc.flags = 0; + desc.format = m_format.color[i].format; + desc.samples = m_format.sampleCount; + desc.loadOp = ops.colorOps[i].loadOp; + desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + desc.initialLayout = ops.colorOps[i].loadLayout; + desc.finalLayout = ops.colorOps[i].storeLayout; + + colorRef[i].attachment = attachments.size(); + colorRef[i].layout = m_format.color[i].layout; + + attachments.push_back(desc); + } else { + colorRef[i].attachment = VK_ATTACHMENT_UNUSED; + colorRef[i].layout = VK_IMAGE_LAYOUT_UNDEFINED; + } + } + + if (m_format.depth.format != VK_FORMAT_UNDEFINED) { + VkAttachmentDescription desc; + desc.flags = 0; + desc.format = m_format.depth.format; + desc.samples = m_format.sampleCount; + desc.loadOp = ops.depthOps.loadOpD; + desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + desc.stencilLoadOp = ops.depthOps.loadOpS; + desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; + desc.initialLayout = ops.depthOps.loadLayout; + desc.finalLayout = ops.depthOps.storeLayout; + + depthRef.attachment = attachments.size(); + depthRef.layout = m_format.depth.layout; + + attachments.push_back(desc); + } else { + depthRef.attachment = VK_ATTACHMENT_UNUSED; + depthRef.layout = VK_IMAGE_LAYOUT_UNDEFINED; + } + + VkSubpassDescription subpass; + subpass.flags = 0; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.inputAttachmentCount = 0; + subpass.pInputAttachments = nullptr; + subpass.colorAttachmentCount = colorRef.size(); + subpass.pColorAttachments = colorRef.data(); + subpass.pResolveAttachments = nullptr; + subpass.pDepthStencilAttachment = &depthRef; + subpass.preserveAttachmentCount = 0; + subpass.pPreserveAttachments = nullptr; + + if (m_format.depth.format == VK_FORMAT_UNDEFINED) + subpass.pDepthStencilAttachment = nullptr; + + std::array subpassDeps; + uint32_t subpassDepCount = 0; + + VkPipelineStageFlags renderStages = 0; + VkAccessFlags renderAccess = 0; + + if (m_format.depth.format) { + renderStages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT + | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + + VkImageAspectFlags loadAspects = 0; + + if (ops.depthOps.loadOpD == VK_ATTACHMENT_LOAD_OP_LOAD) + loadAspects |= VK_IMAGE_ASPECT_DEPTH_BIT; + if (ops.depthOps.loadOpS == VK_ATTACHMENT_LOAD_OP_LOAD) + loadAspects |= VK_IMAGE_ASPECT_STENCIL_BIT; + + if (loadAspects & imageFormatInfo(m_format.depth.format)->aspectMask) + renderAccess |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; + + if (m_format.depth.layout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL) + renderAccess |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + + if (m_format.depth.layout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { + renderStages |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + renderAccess |= VK_ACCESS_SHADER_READ_BIT; + } + } + + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { + if (!m_format.color[i].format) + continue; + + renderStages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + renderAccess |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + + if (ops.colorOps[i].loadOp == VK_ATTACHMENT_LOAD_OP_LOAD) + renderAccess |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; + } + + if (renderStages) { + subpassDeps[subpassDepCount++] = { + VK_SUBPASS_EXTERNAL, 0, + renderStages, renderStages, + 0, renderAccess }; + } + + if (ops.barrier.srcStages & ( + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | + VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT)) { + subpassDeps[subpassDepCount++] = { 0, 0, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT, + VK_DEPENDENCY_BY_REGION_BIT }; + } + + if (ops.barrier.srcStages && ops.barrier.dstStages) { + subpassDeps[subpassDepCount++] = { + 0, VK_SUBPASS_EXTERNAL, + ops.barrier.srcStages, + ops.barrier.dstStages, + ops.barrier.srcAccess, + ops.barrier.dstAccess, 0 }; + } + + VkRenderPassCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.attachmentCount = attachments.size(); + info.pAttachments = attachments.data(); + info.subpassCount = 1; + info.pSubpasses = &subpass; + info.dependencyCount = subpassDepCount; + info.pDependencies = subpassDepCount ? subpassDeps.data() : nullptr; + + VkRenderPass renderPass = VK_NULL_HANDLE; + + if (m_vkd->vkCreateRenderPass(m_vkd->device(), &info, nullptr, &renderPass) != VK_SUCCESS) { + Logger::err("DxvkRenderPass: Failed to create render pass object"); + return VK_NULL_HANDLE; + } + + return renderPass; + } + + + bool DxvkRenderPass::compareOps( + const DxvkRenderPassOps& a, + const DxvkRenderPassOps& b) { + bool eq = a.barrier.srcStages == b.barrier.srcStages + && a.barrier.srcAccess == b.barrier.srcAccess + && a.barrier.dstStages == b.barrier.dstStages + && a.barrier.dstAccess == b.barrier.dstAccess; + + if (eq) { + eq &= a.depthOps.loadOpD == b.depthOps.loadOpD + && a.depthOps.loadOpS == b.depthOps.loadOpS + && a.depthOps.loadLayout == b.depthOps.loadLayout + && a.depthOps.storeLayout == b.depthOps.storeLayout; + } + + for (uint32_t i = 0; i < MaxNumRenderTargets && eq; i++) { + eq &= a.colorOps[i].loadOp == b.colorOps[i].loadOp + && a.colorOps[i].loadLayout == b.colorOps[i].loadLayout + && a.colorOps[i].storeLayout == b.colorOps[i].storeLayout; + } + + return eq; + } + + + DxvkRenderPassPool::DxvkRenderPassPool(const DxvkDevice* device) + : m_device(device) { + + } + + + DxvkRenderPassPool::~DxvkRenderPassPool() { + + } + + + DxvkRenderPass* DxvkRenderPassPool::getRenderPass(const DxvkRenderPassFormat& fmt) { + std::lock_guard lock(m_mutex); + + auto entry = m_renderPasses.find(fmt); + if (entry != m_renderPasses.end()) + return &entry->second; + + auto result = m_renderPasses.emplace(std::piecewise_construct, + std::tuple(fmt), + std::tuple(m_device->vkd(), fmt)); + return &result.first->second; + } + + + bool DxvkRenderPassPool::validateRenderPassFormat( + const DxvkRenderPassFormat& fmt) { + Rc adapter = m_device->adapter(); + + if (fmt.depth.format) { + VkFormatProperties depthInfo = adapter->formatProperties(fmt.depth.format); + VkFormatFeatureFlags depthFlags = depthInfo.linearTilingFeatures | depthInfo.optimalTilingFeatures; + + if (!(depthFlags & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) + return false; + + if (fmt.depth.layout != VK_IMAGE_LAYOUT_GENERAL + && fmt.depth.layout != VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL + && fmt.depth.layout != VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL + && fmt.depth.layout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL + && fmt.depth.layout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL) + return false; + } + + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { + if (fmt.color[i].format) { + VkFormatProperties colorInfo = adapter->formatProperties(fmt.color[i].format); + VkFormatFeatureFlags colorFlags = colorInfo.linearTilingFeatures | colorInfo.optimalTilingFeatures; + + if (!(colorFlags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) + return false; + + if (fmt.color[i].layout != VK_IMAGE_LAYOUT_GENERAL + && fmt.color[i].layout != VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) + return false; + } + } + + return true; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_renderpass.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_renderpass.h new file mode 100644 index 00000000000..2dff8788072 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_renderpass.h @@ -0,0 +1,244 @@ +#pragma once + +#include +#include +#include + +#include "../util/sync/sync_list.h" + +#include "dxvk_hash.h" +#include "dxvk_include.h" +#include "dxvk_limits.h" + +namespace dxvk { + + class DxvkDevice; + + /** + * \brief Format and layout for a render target + * + * Stores the image format of the attachment and + * the image layout that is used while rendering. + */ + struct DxvkAttachmentFormat { + VkFormat format = VK_FORMAT_UNDEFINED; + VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED; + }; + + + /** + * \brief Render pass format + * + * Stores the attachment formats for all depth and + * color attachments, as well as the sample count. + */ + struct DxvkRenderPassFormat { + VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT; + DxvkAttachmentFormat depth; + DxvkAttachmentFormat color[MaxNumRenderTargets]; + + bool eq(const DxvkRenderPassFormat& fmt) const; + + size_t hash() const; + }; + + + /** + * \brief Color attachment transitions + * + * Stores the load/store ops and the initial + * and final layout of a single attachment. + */ + struct DxvkColorAttachmentOps { + VkAttachmentLoadOp loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + VkImageLayout loadLayout = VK_IMAGE_LAYOUT_UNDEFINED; + VkImageLayout storeLayout = VK_IMAGE_LAYOUT_GENERAL; + }; + + + /** + * \brief Depth attachment transitions + * + * Stores the load/store ops and the initial and + * final layout of the depth-stencil attachment. + */ + struct DxvkDepthAttachmentOps { + VkAttachmentLoadOp loadOpD = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + VkAttachmentLoadOp loadOpS = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + VkImageLayout loadLayout = VK_IMAGE_LAYOUT_UNDEFINED; + VkImageLayout storeLayout = VK_IMAGE_LAYOUT_GENERAL; + }; + + + /** + * \brief Render pass barrier + * + * External subpass dependency that is to be + * executed after a render pass has completed. + */ + struct DxvkRenderPassBarrier { + VkPipelineStageFlags srcStages = 0; + VkAccessFlags srcAccess = 0; + VkPipelineStageFlags dstStages = 0; + VkAccessFlags dstAccess = 0; + }; + + + /** + * \brief Render pass transitions + * + * Stores transitions for all depth and color attachments. + * This is used to select a specific render pass object + * from a group of render passes with the same format. + */ + struct DxvkRenderPassOps { + DxvkRenderPassBarrier barrier; + DxvkDepthAttachmentOps depthOps; + DxvkColorAttachmentOps colorOps[MaxNumRenderTargets]; + }; + + + /** + * \brief Render pass object + * + * Manages a set of compatible render passes, i.e. + * render passes which share the same format but + * may differ in their attachment operations. + */ + class DxvkRenderPass { + + public: + + DxvkRenderPass( + const Rc& vkd, + const DxvkRenderPassFormat& fmt); + + ~DxvkRenderPass(); + + /** + * \brief Retrieves render pass format + * \returns The render pass format + */ + DxvkRenderPassFormat format() const { + return m_format; + } + + /** + * \brief Checks whether a format is compatible + * + * Two render pass formats are considered compatible + * if all the relevant attachment formats match. + * \param [in] fmt The render pass format to check + * \returns \c true if this render pass is compatible. + */ + bool hasCompatibleFormat( + const DxvkRenderPassFormat& fmt) const; + + /** + * \brief Retrieves sample count + * + * If no sample count has been explicitly specitied, + * this will return \c VK_SAMPLE_COUNT_1_BIT. + * \returns Sample count + */ + VkSampleCountFlagBits getSampleCount() const { + return m_format.sampleCount; + } + + /** + * \brief Returns handle of default render pass + * + * The default render pass handle should be used to + * create pipelines and framebuffer objects. It can + * \e not be used for \c vkCmdBeginRenderPass calls. + * \returns The default render pass handle + */ + VkRenderPass getDefaultHandle() const { + return m_default; + } + + /** + * \brief Returns handle to a specialized render pass + * + * Returns a handle to a render pass with the given + * set of parameters. This should be used for calls + * to \c vkCmdBeginRenderPass. + * \param [in] ops Attachment ops + * \returns Render pass handle + */ + VkRenderPass getHandle( + const DxvkRenderPassOps& ops); + + private: + + struct Instance { + DxvkRenderPassOps ops; + VkRenderPass handle; + }; + + Rc m_vkd; + DxvkRenderPassFormat m_format; + VkRenderPass m_default; + + dxvk::mutex m_mutex; + sync::List m_instances; + + VkRenderPass findHandle( + const DxvkRenderPassOps& ops); + + VkRenderPass createRenderPass( + const DxvkRenderPassOps& ops); + + static bool compareOps( + const DxvkRenderPassOps& a, + const DxvkRenderPassOps& b); + + }; + + + /** + * \brief Render pass pool + * + * Manages render pass objects. For each render + * pass format, a new render pass object will + * be created, but no two render pass objects + * will have the same format. + */ + class DxvkRenderPassPool { + + public: + + DxvkRenderPassPool(const DxvkDevice* device); + ~DxvkRenderPassPool(); + + /** + * \brief Retrieves a render pass object + * + * \param [in] fmt The render pass format + * \returns Matching render pass object + */ + DxvkRenderPass* getRenderPass( + const DxvkRenderPassFormat& fmt); + + /** + * \brief Validates render pass format + * + * \param [in] fmt The render pass format + * \returns \c true if the format is supported + */ + bool validateRenderPassFormat( + const DxvkRenderPassFormat& fmt); + + private: + + const DxvkDevice* m_device; + + dxvk::mutex m_mutex; + std::unordered_map< + DxvkRenderPassFormat, + DxvkRenderPass, + DxvkHash, DxvkEq> m_renderPasses; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_resource.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_resource.cpp new file mode 100644 index 00000000000..af7a2ea4ec4 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_resource.cpp @@ -0,0 +1,9 @@ +#include "dxvk_resource.h" + +namespace dxvk { + + DxvkResource::~DxvkResource() { + + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_resource.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_resource.h new file mode 100644 index 00000000000..9a73ed818bb --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_resource.h @@ -0,0 +1,93 @@ +#pragma once + +#include "dxvk_include.h" + +namespace dxvk { + + enum class DxvkAccess { + Read = 0, + Write = 1, + None = 2, + }; + + using DxvkAccessFlags = Flags; + + /** + * \brief DXVK resource + * + * Keeps track of whether the resource is currently in use + * by the GPU. As soon as a command that uses the resource + * is recorded, it will be marked as 'in use'. + */ + class DxvkResource : public RcObject { + + public: + + virtual ~DxvkResource(); + + /** + * \brief Checks whether resource is in use + * + * Returns \c true if there are pending accesses to + * the resource by the GPU matching the given access + * type. Note that checking for reads will also return + * \c true if the resource is being written to. + * \param [in] access Access type to check for + * \returns \c true if the resource is in use + */ + bool isInUse(DxvkAccess access = DxvkAccess::Read) const { + bool result = m_useCountW.load() != 0; + if (access == DxvkAccess::Read) + result |= m_useCountR.load() != 0; + return result; + } + + /** + * \brief Acquires resource + * + * Increments use count for the given access type. + * \param Access Resource access type + */ + void acquire(DxvkAccess access) { + if (access != DxvkAccess::None) { + (access == DxvkAccess::Read + ? m_useCountR + : m_useCountW) += 1; + } + } + + /** + * \brief Releases resource + * + * Decrements use count for the given access type. + * \param Access Resource access type + */ + void release(DxvkAccess access) { + if (access != DxvkAccess::None) { + (access == DxvkAccess::Read + ? m_useCountR + : m_useCountW) -= 1; + } + } + + /** + * \brief Waits for resource to become unused + * + * Blocks calling thread until the GPU finishes + * using the resource with the given access type. + * \param [in] access Access type to check for + */ + void waitIdle(DxvkAccess access = DxvkAccess::Read) const { + sync::spin(50000, [this, access] { + return !isInUse(access); + }); + } + + private: + + std::atomic m_useCountR = { 0u }; + std::atomic m_useCountW = { 0u }; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_sampler.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_sampler.cpp new file mode 100644 index 00000000000..c10e82d0291 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_sampler.cpp @@ -0,0 +1,84 @@ +#include "dxvk_sampler.h" +#include "dxvk_device.h" + +namespace dxvk { + + DxvkSampler::DxvkSampler( + DxvkDevice* device, + const DxvkSamplerCreateInfo& info) + : m_vkd(device->vkd()) { + VkSamplerCustomBorderColorCreateInfoEXT borderColorInfo; + borderColorInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT; + borderColorInfo.pNext = nullptr; + borderColorInfo.customBorderColor = info.borderColor; + borderColorInfo.format = VK_FORMAT_UNDEFINED; + + VkSamplerCreateInfo samplerInfo; + samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + samplerInfo.pNext = nullptr; + samplerInfo.flags = info.nonSeamless ? VK_SAMPLER_CREATE_NON_SEAMLESS_CUBE_MAP_BIT_EXT : 0; + samplerInfo.magFilter = info.magFilter; + samplerInfo.minFilter = info.minFilter; + samplerInfo.mipmapMode = info.mipmapMode; + samplerInfo.addressModeU = info.addressModeU; + samplerInfo.addressModeV = info.addressModeV; + samplerInfo.addressModeW = info.addressModeW; + samplerInfo.mipLodBias = info.mipmapLodBias; + samplerInfo.anisotropyEnable = info.useAnisotropy; + samplerInfo.maxAnisotropy = info.maxAnisotropy; + samplerInfo.compareEnable = info.compareToDepth; + samplerInfo.compareOp = info.compareOp; + samplerInfo.minLod = info.mipmapLodMin; + samplerInfo.maxLod = info.mipmapLodMax; + samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; + samplerInfo.unnormalizedCoordinates = info.usePixelCoord; + + if (!device->features().core.features.samplerAnisotropy) + samplerInfo.anisotropyEnable = VK_FALSE; + + if (samplerInfo.addressModeU == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER + || samplerInfo.addressModeV == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER + || samplerInfo.addressModeW == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER) + samplerInfo.borderColor = getBorderColor(device, info); + + if (samplerInfo.borderColor == VK_BORDER_COLOR_FLOAT_CUSTOM_EXT) + samplerInfo.pNext = &borderColorInfo; + + if (m_vkd->vkCreateSampler(m_vkd->device(), + &samplerInfo, nullptr, &m_sampler) != VK_SUCCESS) + throw DxvkError("DxvkSampler::DxvkSampler: Failed to create sampler"); + } + + + DxvkSampler::~DxvkSampler() { + m_vkd->vkDestroySampler( + m_vkd->device(), m_sampler, nullptr); + } + + + VkBorderColor DxvkSampler::getBorderColor(const Rc& device, const DxvkSamplerCreateInfo& info) { + static const std::array, 3> s_borderColors = {{ + { { { 0.0f, 0.0f, 0.0f, 0.0f } }, VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK }, + { { { 0.0f, 0.0f, 0.0f, 1.0f } }, VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK }, + { { { 1.0f, 1.0f, 1.0f, 1.0f } }, VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE }, + }}; + + // Ignore G/B/A components for shadow samplers + size_t size = !info.compareToDepth + ? sizeof(VkClearColorValue) + : sizeof(float); + + for (const auto& e : s_borderColors) { + if (!std::memcmp(&e.first, &info.borderColor, size)) + return e.second; + } + + if (!device->features().extCustomBorderColor.customBorderColorWithoutFormat) { + Logger::warn("DXVK: Custom border colors not supported"); + return VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; + } + + return VK_BORDER_COLOR_FLOAT_CUSTOM_EXT; + } + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_sampler.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_sampler.h new file mode 100644 index 00000000000..e2e421b35de --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_sampler.h @@ -0,0 +1,82 @@ +#pragma once + +#include "dxvk_resource.h" + +namespace dxvk { + + class DxvkDevice; + + /** + * \brief Sampler properties + */ + struct DxvkSamplerCreateInfo { + /// Texture filter propertoes + VkFilter magFilter; + VkFilter minFilter; + + /// Mipmapping properties + VkSamplerMipmapMode mipmapMode; + float mipmapLodBias; + float mipmapLodMin; + float mipmapLodMax; + + /// Anisotropic filtering + VkBool32 useAnisotropy; + float maxAnisotropy; + + /// Address modes + VkSamplerAddressMode addressModeU; + VkSamplerAddressMode addressModeV; + VkSamplerAddressMode addressModeW; + + /// Compare op for shadow textures + VkBool32 compareToDepth; + VkCompareOp compareOp; + + /// Texture border color + VkClearColorValue borderColor; + + /// Enables unnormalized coordinates + VkBool32 usePixelCoord; + + /// Enables non seamless cube map filtering + VkBool32 nonSeamless; + }; + + + /** + * \brief Sampler + * + * Manages a sampler object that can be bound to + * a pipeline. Sampler objects provide parameters + * for texture lookups within a shader. + */ + class DxvkSampler : public DxvkResource { + + public: + + DxvkSampler( + DxvkDevice* device, + const DxvkSamplerCreateInfo& info); + ~DxvkSampler(); + + /** + * \brief Sampler handle + * \returns Sampler handle + */ + VkSampler handle() const { + return m_sampler; + } + + private: + + Rc m_vkd; + VkSampler m_sampler = VK_NULL_HANDLE; + + static VkBorderColor getBorderColor( + const Rc& device, + const DxvkSamplerCreateInfo& info); + + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_shader.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_shader.cpp new file mode 100644 index 00000000000..2d9793f4512 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_shader.cpp @@ -0,0 +1,379 @@ +#include "dxvk_shader.h" + +#include +#include +#include + +namespace dxvk { + + DxvkShaderModule::DxvkShaderModule() + : m_vkd(nullptr), m_stage() { + + } + + + DxvkShaderModule::DxvkShaderModule(DxvkShaderModule&& other) + : m_vkd(std::move(other.m_vkd)) { + this->m_stage = other.m_stage; + other.m_stage = VkPipelineShaderStageCreateInfo(); + } + + + DxvkShaderModule::DxvkShaderModule( + const Rc& vkd, + const Rc& shader, + const SpirvCodeBuffer& code) + : m_vkd(vkd), m_stage() { + m_stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + m_stage.pNext = nullptr; + m_stage.flags = 0; + m_stage.stage = shader->info().stage; + m_stage.module = VK_NULL_HANDLE; + m_stage.pName = "main"; + m_stage.pSpecializationInfo = nullptr; + + VkShaderModuleCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.codeSize = code.size(); + info.pCode = code.data(); + + if (m_vkd->vkCreateShaderModule(m_vkd->device(), &info, nullptr, &m_stage.module) != VK_SUCCESS) + throw DxvkError("DxvkComputePipeline::DxvkComputePipeline: Failed to create shader module"); + } + + + DxvkShaderModule::~DxvkShaderModule() { + if (m_vkd != nullptr) { + m_vkd->vkDestroyShaderModule( + m_vkd->device(), m_stage.module, nullptr); + } + } + + + DxvkShaderModule& DxvkShaderModule::operator = (DxvkShaderModule&& other) { + this->m_vkd = std::move(other.m_vkd); + this->m_stage = other.m_stage; + other.m_stage = VkPipelineShaderStageCreateInfo(); + return *this; + } + + + DxvkShader::DxvkShader( + const DxvkShaderCreateInfo& info, + SpirvCodeBuffer&& spirv) + : m_info(info), m_code(spirv) { + m_info.resourceSlots = nullptr; + m_info.uniformData = nullptr; + + // Copy resource binding slot infos + if (info.resourceSlotCount) { + m_slots.resize(info.resourceSlotCount); + for (uint32_t i = 0; i < info.resourceSlotCount; i++) + m_slots[i] = info.resourceSlots[i]; + m_info.resourceSlots = m_slots.data(); + } + + // Copy uniform buffer data + if (info.uniformSize) { + m_uniformData.resize(info.uniformSize); + std::memcpy(m_uniformData.data(), info.uniformData, info.uniformSize); + m_info.uniformData = m_uniformData.data(); + } + + // Run an analysis pass over the SPIR-V code to gather some + // info that we may need during pipeline compilation. + SpirvCodeBuffer code = std::move(spirv); + uint32_t o1VarId = 0; + + for (auto ins : code) { + if (ins.opCode() == spv::OpDecorate) { + if (ins.arg(2) == spv::DecorationBinding + || ins.arg(2) == spv::DecorationSpecId) + m_idOffsets.push_back(ins.offset() + 3); + + if (ins.arg(2) == spv::DecorationLocation && ins.arg(3) == 1) { + m_o1LocOffset = ins.offset() + 3; + o1VarId = ins.arg(1); + } + + if (ins.arg(2) == spv::DecorationIndex && ins.arg(1) == o1VarId) + m_o1IdxOffset = ins.offset() + 3; + } + + if (ins.opCode() == spv::OpExecutionMode) { + if (ins.arg(2) == spv::ExecutionModeStencilRefReplacingEXT) + m_flags.set(DxvkShaderFlag::ExportsStencilRef); + + if (ins.arg(2) == spv::ExecutionModeXfb) + m_flags.set(DxvkShaderFlag::HasTransformFeedback); + } + + if (ins.opCode() == spv::OpCapability) { + if (ins.arg(1) == spv::CapabilitySampleRateShading) + m_flags.set(DxvkShaderFlag::HasSampleRateShading); + + if (ins.arg(1) == spv::CapabilityShaderViewportIndexLayerEXT) + m_flags.set(DxvkShaderFlag::ExportsViewportIndexLayerFromVertexStage); + } + } + } + + + DxvkShader::~DxvkShader() { + + } + + + void DxvkShader::defineResourceSlots( + DxvkDescriptorSlotMapping& mapping) const { + for (const auto& slot : m_slots) + mapping.defineSlot(m_info.stage, slot); + + if (m_info.pushConstSize) { + mapping.definePushConstRange(m_info.stage, + m_info.pushConstOffset, + m_info.pushConstSize); + } + } + + + DxvkShaderModule DxvkShader::createShaderModule( + const Rc& vkd, + const DxvkDescriptorSlotMapping& mapping, + const DxvkShaderModuleCreateInfo& info) { + SpirvCodeBuffer spirvCode = m_code.decompress(); + uint32_t* code = spirvCode.data(); + + // Remap resource binding IDs + for (uint32_t ofs : m_idOffsets) { + if (code[ofs] < MaxNumResourceSlots) + code[ofs] = mapping.getBindingId(code[ofs]); + } + + // For dual-source blending we need to re-map + // location 1, index 0 to location 0, index 1 + if (info.fsDualSrcBlend && m_o1IdxOffset && m_o1LocOffset) + std::swap(code[m_o1IdxOffset], code[m_o1LocOffset]); + + // Replace undefined input variables with zero + for (uint32_t u : bit::BitMask(info.undefinedInputs)) + eliminateInput(spirvCode, u); + + return DxvkShaderModule(vkd, this, spirvCode); + } + + + void DxvkShader::dump(std::ostream& outputStream) const { + m_code.decompress().store(outputStream); + } + + + void DxvkShader::eliminateInput(SpirvCodeBuffer& code, uint32_t location) { + struct SpirvTypeInfo { + spv::Op op = spv::OpNop; + uint32_t baseTypeId = 0; + uint32_t compositeSize = 0; + spv::StorageClass storageClass = spv::StorageClassMax; + }; + + std::unordered_map types; + std::unordered_map constants; + std::unordered_set candidates; + + // Find the input variable in question + size_t inputVarOffset = 0; + uint32_t inputVarTypeId = 0; + uint32_t inputVarId = 0; + + for (auto ins : code) { + if (ins.opCode() == spv::OpDecorate) { + if (ins.arg(2) == spv::DecorationLocation + && ins.arg(3) == location) + candidates.insert(ins.arg(1)); + } + + if (ins.opCode() == spv::OpConstant) + constants.insert({ ins.arg(2), ins.arg(3) }); + + if (ins.opCode() == spv::OpTypeFloat || ins.opCode() == spv::OpTypeInt) + types.insert({ ins.arg(1), { ins.opCode(), 0, ins.arg(2), spv::StorageClassMax }}); + + if (ins.opCode() == spv::OpTypeVector) + types.insert({ ins.arg(1), { ins.opCode(), ins.arg(2), ins.arg(3), spv::StorageClassMax }}); + + if (ins.opCode() == spv::OpTypeArray) { + auto constant = constants.find(ins.arg(3)); + if (constant == constants.end()) + continue; + types.insert({ ins.arg(1), { ins.opCode(), ins.arg(2), constant->second, spv::StorageClassMax }}); + } + + if (ins.opCode() == spv::OpTypePointer) + types.insert({ ins.arg(1), { ins.opCode(), ins.arg(3), 0, spv::StorageClass(ins.arg(2)) }}); + + if (ins.opCode() == spv::OpVariable && spv::StorageClass(ins.arg(3)) == spv::StorageClassInput) { + if (candidates.find(ins.arg(2)) != candidates.end()) { + inputVarOffset = ins.offset(); + inputVarTypeId = ins.arg(1); + inputVarId = ins.arg(2); + break; + } + } + } + + if (!inputVarId) + return; + + // Declare private pointer types + auto pointerType = types.find(inputVarTypeId); + if (pointerType == types.end()) + return; + + code.beginInsertion(inputVarOffset); + std::vector> privateTypes; + + for (auto p = types.find(pointerType->second.baseTypeId); + p != types.end(); + p = types.find(p->second.baseTypeId)) { + std::pair info = *p; + info.first = 0; + info.second.baseTypeId = p->first; + info.second.storageClass = spv::StorageClassPrivate; + + for (auto t : types) { + if (t.second.op == info.second.op + && t.second.baseTypeId == info.second.baseTypeId + && t.second.storageClass == info.second.storageClass) + info.first = t.first; + } + + if (!info.first) { + info.first = code.allocId(); + + code.putIns(spv::OpTypePointer, 4); + code.putWord(info.first); + code.putWord(info.second.storageClass); + code.putWord(info.second.baseTypeId); + } + + privateTypes.push_back(info); + } + + // Define zero constants + uint32_t constantId = 0; + + for (auto i = privateTypes.rbegin(); i != privateTypes.rend(); i++) { + if (constantId) { + uint32_t compositeSize = i->second.compositeSize; + uint32_t compositeId = code.allocId(); + + code.putIns(spv::OpConstantComposite, 3 + compositeSize); + code.putWord(i->second.baseTypeId); + code.putWord(compositeId); + + for (uint32_t i = 0; i < compositeSize; i++) + code.putWord(constantId); + + constantId = compositeId; + } else { + constantId = code.allocId(); + + code.putIns(spv::OpConstant, 4); + code.putWord(i->second.baseTypeId); + code.putWord(constantId); + code.putWord(0); + } + } + + // Erase and re-declare variable + code.erase(4); + + code.putIns(spv::OpVariable, 5); + code.putWord(privateTypes[0].first); + code.putWord(inputVarId); + code.putWord(spv::StorageClassPrivate); + code.putWord(constantId); + + code.endInsertion(); + + // Remove variable from interface list + for (auto ins : code) { + if (ins.opCode() == spv::OpEntryPoint) { + uint32_t argIdx = 2 + code.strLen(ins.chr(2)); + + while (argIdx < ins.length()) { + if (ins.arg(argIdx) == inputVarId) { + ins.setArg(0, spv::OpEntryPoint | ((ins.length() - 1) << spv::WordCountShift)); + + code.beginInsertion(ins.offset() + argIdx); + code.erase(1); + code.endInsertion(); + break; + } + + argIdx += 1; + } + } + } + + // Remove location and other declarations + for (auto iter = code.begin(); iter != code.end(); ) { + auto ins = *(iter++); + + if (ins.opCode() == spv::OpDecorate && ins.arg(1) == inputVarId) { + uint32_t numWords; + + switch (ins.arg(2)) { + case spv::DecorationLocation: + case spv::DecorationFlat: + case spv::DecorationNoPerspective: + case spv::DecorationCentroid: + case spv::DecorationPatch: + case spv::DecorationSample: + numWords = ins.length(); + break; + + default: + numWords = 0; + } + + if (numWords) { + code.beginInsertion(ins.offset()); + code.erase(numWords); + + iter = SpirvInstructionIterator(code.data(), code.endInsertion(), code.dwords()); + } + } + + if (ins.opCode() == spv::OpFunction) + break; + } + + // Fix up pointer types used in access chain instructions + std::unordered_map accessChainIds; + + for (auto ins : code) { + if (ins.opCode() == spv::OpAccessChain + || ins.opCode() == spv::OpInBoundsAccessChain) { + uint32_t depth = ins.length() - 4; + + if (ins.arg(3) == inputVarId) { + // Access chains accessing the variable directly + ins.setArg(1, privateTypes.at(depth).first); + accessChainIds.insert({ ins.arg(2), depth }); + } else { + // Access chains derived from the variable + auto entry = accessChainIds.find(ins.arg(2)); + if (entry != accessChainIds.end()) { + depth += entry->second; + ins.setArg(1, privateTypes.at(depth).first); + accessChainIds.insert({ ins.arg(2), depth }); + } + } + } + } + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_shader.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_shader.h new file mode 100644 index 00000000000..0be8b496be4 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_shader.h @@ -0,0 +1,275 @@ +#pragma once + +#include + +#include "dxvk_include.h" +#include "dxvk_limits.h" +#include "dxvk_pipelayout.h" +#include "dxvk_shader_key.h" + +#include "../spirv/spirv_code_buffer.h" +#include "../spirv/spirv_compression.h" + +namespace dxvk { + + class DxvkShader; + class DxvkShaderModule; + + /** + * \brief Built-in specialization constants + * + * These specialization constants allow the SPIR-V + * shaders to access some pipeline state like D3D + * shaders do. They need to be filled in by the + * implementation at pipeline compilation time. + */ + enum class DxvkSpecConstantId : uint32_t { + /// Special constant ranges that do not count + /// towards the spec constant min/max values + ColorComponentMappings = MaxNumResourceSlots, + + // Specialization constants for pipeline state + SpecConstantRangeStart = ColorComponentMappings + MaxNumRenderTargets, + RasterizerSampleCount = SpecConstantRangeStart + 0, + FirstPipelineConstant + }; + + /** + * \brief Shader flags + * + * Provides extra information about the features + * used by a shader. + */ + enum DxvkShaderFlag : uint64_t { + HasSampleRateShading, + HasTransformFeedback, + ExportsStencilRef, + ExportsViewportIndexLayerFromVertexStage, + }; + + using DxvkShaderFlags = Flags; + + /** + * \brief Shader info + */ + struct DxvkShaderCreateInfo { + /// Shader stage + VkShaderStageFlagBits stage; + /// Descriptor info + uint32_t resourceSlotCount = 0; + const DxvkResourceSlot* resourceSlots = nullptr; + /// Input and output register mask + uint32_t inputMask = 0; + uint32_t outputMask = 0; + /// Push constant range + uint32_t pushConstOffset = 0; + uint32_t pushConstSize = 0; + /// Uniform buffer data + uint32_t uniformSize = 0; + const char* uniformData = nullptr; + /// Rasterized stream, or -1 + int32_t xfbRasterizedStream = 0; + /// Transform feedback vertex strides + uint32_t xfbStrides[MaxNumXfbBuffers] = { }; + }; + + + /** + * \brief Shader module create info + */ + struct DxvkShaderModuleCreateInfo { + bool fsDualSrcBlend = false; + uint32_t undefinedInputs = 0; + }; + + + /** + * \brief Shader object + * + * Stores a SPIR-V shader and information on the + * bindings that the shader uses. In order to use + * the shader with a pipeline, a shader module + * needs to be created from he shader object. + */ + class DxvkShader : public RcObject { + + public: + + DxvkShader( + const DxvkShaderCreateInfo& info, + SpirvCodeBuffer&& spirv); + + ~DxvkShader(); + + /** + * \brief Shader info + * \returns Shader info + */ + const DxvkShaderCreateInfo& info() const { + return m_info; + } + + /** + * \brief Retrieves shader flags + * \returns Shader flags + */ + DxvkShaderFlags flags() const { + return m_flags; + } + + /** + * \brief Adds resource slots definitions to a mapping + * + * Used to generate the exact descriptor set layout when + * compiling a graphics or compute pipeline. Slot indices + * have to be mapped to actual binding numbers. + */ + void defineResourceSlots( + DxvkDescriptorSlotMapping& mapping) const; + + /** + * \brief Creates a shader module + * + * Maps the binding slot numbers + * \param [in] vkd Vulkan device functions + * \param [in] mapping Resource slot mapping + * \param [in] info Module create info + * \returns The shader module + */ + DxvkShaderModule createShaderModule( + const Rc& vkd, + const DxvkDescriptorSlotMapping& mapping, + const DxvkShaderModuleCreateInfo& info); + + /** + * \brief Dumps SPIR-V shader + * + * Can be used to store the SPIR-V code in a file. + * \param [in] outputStream Stream to write to + */ + void dump(std::ostream& outputStream) const; + + /** + * \brief Sets the shader key + * \param [in] key Unique key + */ + void setShaderKey(const DxvkShaderKey& key) { + m_key = key; + m_hash = key.hash(); + } + + /** + * \brief Retrieves shader key + * \returns The unique shader key + */ + DxvkShaderKey getShaderKey() const { + return m_key; + } + + /** + * \brief Get lookup hash + * + * Retrieves a non-unique hash value derived from the + * shader key which can be used to perform lookups. + * This is better than relying on the pointer value. + * \returns Hash value for map lookups + */ + size_t getHash() const { + return m_hash; + } + + /** + * \brief Retrieves debug name + * \returns The shader's name + */ + std::string debugName() const { + return m_key.toString(); + } + + /** + * \brief Get lookup hash for a shader + * + * Convenience method that returns \c 0 for a null + * pointer, and the shader's lookup hash otherwise. + * \param [in] shader The shader + * \returns The shader's lookup hash, or 0 + */ + static size_t getHash(const Rc& shader) { + return shader != nullptr ? shader->getHash() : 0; + } + + private: + + DxvkShaderCreateInfo m_info; + SpirvCompressedBuffer m_code; + + DxvkShaderFlags m_flags; + DxvkShaderKey m_key; + size_t m_hash = 0; + + size_t m_o1IdxOffset = 0; + size_t m_o1LocOffset = 0; + + std::vector m_slots; + std::vector m_uniformData; + std::vector m_idOffsets; + + static void eliminateInput(SpirvCodeBuffer& code, uint32_t location); + + }; + + + /** + * \brief Shader module object + * + * Manages a Vulkan shader module. This will not + * perform any shader compilation. Instead, the + * context will create pipeline objects on the + * fly when executing draw calls. + */ + class DxvkShaderModule { + + public: + + DxvkShaderModule(); + + DxvkShaderModule(DxvkShaderModule&& other); + + DxvkShaderModule( + const Rc& vkd, + const Rc& shader, + const SpirvCodeBuffer& code); + + ~DxvkShaderModule(); + + DxvkShaderModule& operator = (DxvkShaderModule&& other); + + /** + * \brief Shader stage creation info + * + * \param [in] specInfo Specialization info + * \returns Shader stage create info + */ + VkPipelineShaderStageCreateInfo stageInfo( + const VkSpecializationInfo* specInfo) const { + VkPipelineShaderStageCreateInfo stage = m_stage; + stage.pSpecializationInfo = specInfo; + return stage; + } + + /** + * \brief Checks whether module is valid + * \returns \c true if module is valid + */ + operator bool () const { + return m_stage.module != VK_NULL_HANDLE; + } + + private: + + Rc m_vkd; + VkPipelineShaderStageCreateInfo m_stage; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_shader_key.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_shader_key.cpp new file mode 100644 index 00000000000..0272a071156 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_shader_key.cpp @@ -0,0 +1,43 @@ +#include "dxvk_shader_key.h" + +namespace dxvk { + + DxvkShaderKey::DxvkShaderKey() + : m_type(0), + m_sha1(Sha1Hash::compute(nullptr, 0)) { } + + + std::string DxvkShaderKey::toString() const { + const char* prefix = nullptr; + + switch (m_type) { + case VK_SHADER_STAGE_VERTEX_BIT: prefix = "VS_"; break; + case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: prefix = "TCS_"; break; + case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: prefix = "TES_"; break; + case VK_SHADER_STAGE_GEOMETRY_BIT: prefix = "GS_"; break; + case VK_SHADER_STAGE_FRAGMENT_BIT: prefix = "FS_"; break; + case VK_SHADER_STAGE_COMPUTE_BIT: prefix = "CS_"; break; + default: prefix = ""; + } + + return str::format(prefix, m_sha1.toString()); + } + + + size_t DxvkShaderKey::hash() const { + DxvkHashState result; + result.add(uint32_t(m_type)); + + for (uint32_t i = 0; i < 5; i++) + result.add(m_sha1.dword(i)); + + return result; + } + + + bool DxvkShaderKey::eq(const DxvkShaderKey& key) const { + return m_type == key.m_type + && m_sha1 == key.m_sha1; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_shader_key.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_shader_key.h new file mode 100644 index 00000000000..4a66e5285cd --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_shader_key.h @@ -0,0 +1,76 @@ +#pragma once + +#include "dxvk_hash.h" +#include "dxvk_include.h" + +namespace dxvk { + + /** + * \brief Shader key + * + * Provides a unique key that can be used + * to look up a specific shader within a + * structure. This consists of the shader + * stage and the source hash, which should + * be generated from the original code. + */ + class DxvkShaderKey { + + public: + + /** + * \brief Creates default shader key + */ + DxvkShaderKey(); + + /** + * \brief Creates shader key + * + * \param [in] stage Shader stage + * \param [in] hash Shader hash + */ + DxvkShaderKey( + VkShaderStageFlagBits stage, + Sha1Hash hash) + : m_type(stage), m_sha1(hash) { } + + /** + * \brief Generates string from shader key + * \returns String representation of the key + */ + std::string toString() const; + + /** + * \brief Computes lookup hash + * \returns Lookup hash + */ + size_t hash() const; + + /** + * \brief Shader type + * \returns Shader type + */ + VkShaderStageFlags type() const { return m_type; } + + /** + * \brief Shader SHA1 + * \returns Shader SHA1 + */ + const Sha1Hash& sha1() const { return m_sha1; } + + /** + * \brief Checks whether two keys are equal + * + * \param [in] key The shader key to compare to + * \returns \c true if the two keys are equal + */ + bool eq(const DxvkShaderKey& key) const; + + private: + + VkShaderStageFlags m_type; + Sha1Hash m_sha1; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_signal.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_signal.cpp new file mode 100644 index 00000000000..3bb87452d57 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_signal.cpp @@ -0,0 +1,30 @@ +#include "dxvk_signal.h" + +namespace dxvk { + + DxvkSignalTracker::DxvkSignalTracker() { + + } + + + DxvkSignalTracker::~DxvkSignalTracker() { + + } + + + void DxvkSignalTracker::add(const Rc& signal, uint64_t value) { + m_signals.push_back({ signal, value }); + } + + + void DxvkSignalTracker::notify() { + for (const auto& pair : m_signals) + pair.first->signal(pair.second); + } + + + void DxvkSignalTracker::reset() { + m_signals.clear(); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_signal.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_signal.h new file mode 100644 index 00000000000..fa99f7810dc --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_signal.h @@ -0,0 +1,41 @@ +#pragma once + +#include "dxvk_include.h" + +namespace dxvk { + + /** + * \brief Signal tracker + */ + class DxvkSignalTracker { + + public: + + DxvkSignalTracker(); + ~DxvkSignalTracker(); + + /** + * \brief Adds a signal to track + * + * \param [in] signal The signal + * \param [in] value Target value + */ + void add(const Rc& signal, uint64_t value); + + /** + * \brief Notifies tracked signals + */ + void notify(); + + /** + * \brief Resets signal tracker + */ + void reset(); + + private: + + std::vector, uint64_t>> m_signals; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_spec_const.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_spec_const.cpp new file mode 100644 index 00000000000..eec6d8ae5dc --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_spec_const.cpp @@ -0,0 +1,36 @@ +#include "dxvk_spec_const.h" + +namespace dxvk { + + DxvkSpecConstants::DxvkSpecConstants() { + + } + + + DxvkSpecConstants::~DxvkSpecConstants() { + + } + + + VkSpecializationInfo DxvkSpecConstants::getSpecInfo() const { + VkSpecializationInfo specInfo; + specInfo.mapEntryCount = m_map.size(); + specInfo.pMapEntries = m_map.data(); + specInfo.dataSize = m_data.size() * sizeof(uint32_t); + specInfo.pData = m_data.data(); + return specInfo; + } + + + void DxvkSpecConstants::setAsUint32(uint32_t specId, uint32_t value) { + uint32_t index = m_data.size(); + m_data.push_back(value); + + VkSpecializationMapEntry mapEntry; + mapEntry.constantID = specId; + mapEntry.offset = sizeof(uint32_t) * index; + mapEntry.size = sizeof(uint32_t); + m_map.push_back(mapEntry); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_spec_const.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_spec_const.h new file mode 100644 index 00000000000..df4f041cb25 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_spec_const.h @@ -0,0 +1,91 @@ +#pragma once + +#include "dxvk_limits.h" +#include "dxvk_shader.h" + +namespace dxvk { + + /** + * \briefS Specialization constant entry + * + * Used to pass a list of user-defined + * specialization constants to shaders. + */ + struct DxvkSpecConstant { + uint32_t specId; + uint32_t value; + }; + + + /** + * \brief Specialization constant info + * + * Accumulates specialization constant data for + * constants that use non-default values. + */ + class DxvkSpecConstants { + + public: + + DxvkSpecConstants(); + + ~DxvkSpecConstants(); + + /** + * \brief Sets specialization constant value + * + * If the given value is different from the constant's + * default value, this will store the new value and add + * a map entry so that it gets applied properly. Each + * constant may only be set once. + * \param [in] specId Specialization constant ID + * \param [in] value Specialization constant value + * \param [in] defaultValue Default value + */ + template + void set(uint32_t specId, T value, T defaultValue) { + if (value != defaultValue) + setAsUint32(specId, uint32_t(value)); + } + + /** + * \brief Sets specialization constant value + * + * Always passes the constant value to the driver. + * \param [in] specId Specialization constant ID + * \param [in] value Specialization constant value + */ + template + void set(uint32_t specId, T value) { + setAsUint32(specId, uint32_t(value)); + } + + /** + * \brief Generates specialization info structure + * \returns Specialization info for shader module + */ + VkSpecializationInfo getSpecInfo() const; + + private: + + std::vector m_data = { }; + std::vector m_map = { }; + + void setAsUint32(uint32_t specId, uint32_t value); + + }; + + + /** + * \brief Computes specialization constant ID + * + * Computest the specId to use within shaders + * for a given pipeline specialization constant. + * \param [in] index Spec constant index + * \returns Specialization constant ID + */ + inline uint32_t getSpecId(uint32_t index) { + return uint32_t(DxvkSpecConstantId::FirstPipelineConstant) + index; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_staging.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_staging.cpp new file mode 100644 index 00000000000..0daa725c001 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_staging.cpp @@ -0,0 +1,61 @@ +#include "dxvk_device.h" +#include "dxvk_staging.h" + +namespace dxvk { + + DxvkStagingBuffer::DxvkStagingBuffer( + const Rc& device, + VkDeviceSize size) + : m_device(device), m_offset(0), m_size(size) { + + } + + + DxvkStagingBuffer::~DxvkStagingBuffer() { + + } + + + DxvkBufferSlice DxvkStagingBuffer::alloc(VkDeviceSize align, VkDeviceSize size) { + DxvkBufferCreateInfo info; + info.size = size; + info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT + | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT + | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT + | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT + | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + info.access = VK_ACCESS_TRANSFER_READ_BIT + | VK_ACCESS_SHADER_READ_BIT; + + VkDeviceSize alignedSize = dxvk::align(size, align); + VkDeviceSize alignedOffset = dxvk::align(m_offset, align); + + if (2 * alignedSize > m_size) { + return DxvkBufferSlice(m_device->createBuffer(info, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)); + } + + if (alignedOffset + alignedSize > m_size || m_buffer == nullptr) { + info.size = m_size; + + // Free resources first if possible, in some rare + // situations this may help avoid a memory allocation. + m_buffer = nullptr; + m_buffer = m_device->createBuffer(info, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + alignedOffset = 0; + } + + DxvkBufferSlice slice(m_buffer, alignedOffset, size); + m_offset = alignedOffset + alignedSize; + return slice; + } + + + void DxvkStagingBuffer::reset() { + m_buffer = nullptr; + m_offset = 0; + } + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_staging.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_staging.h new file mode 100644 index 00000000000..b2346fe367e --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_staging.h @@ -0,0 +1,61 @@ +#pragma once + +#include + +#include "dxvk_buffer.h" + +namespace dxvk { + + class DxvkDevice; + + /** + * \brief Staging buffer + * + * Provides a simple linear staging buffer + * allocator for data uploads. + */ + class DxvkStagingBuffer { + + public: + + /** + * \brief Creates staging buffer + * + * \param [in] device DXVK device + * \param [in] size Buffer size + */ + DxvkStagingBuffer( + const Rc& device, + VkDeviceSize size); + + /** + * \brief Frees staging buffer + */ + ~DxvkStagingBuffer(); + + /** + * \brief Allocates staging buffer memory + * + * Tries to suballocate from existing buffer, + * or creates a new buffer if necessary. + * \param [in] align Minimum alignment + * \param [in] size Number of bytes to allocate + * \returns Allocated slice + */ + DxvkBufferSlice alloc(VkDeviceSize align, VkDeviceSize size); + + /** + * \brief Resets staging buffer and allocator + */ + void reset(); + + private: + + Rc m_device; + Rc m_buffer; + VkDeviceSize m_offset; + VkDeviceSize m_size; + + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_state_cache.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_state_cache.cpp new file mode 100644 index 00000000000..3cbf09295f3 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_state_cache.cpp @@ -0,0 +1,1066 @@ +#include "dxvk_device.h" +#include "dxvk_pipemanager.h" +#include "dxvk_state_cache.h" + +namespace dxvk { + + static const Sha1Hash g_nullHash = Sha1Hash::compute(nullptr, 0); + static const DxvkShaderKey g_nullShaderKey = DxvkShaderKey(); + + + /** + * \brief Packed entry header + */ + struct DxvkStateCacheEntryHeader { + uint32_t stageMask : 8; + uint32_t entrySize : 24; + }; + + + /** + * \brief State cache entry data + * + * Stores data for a single cache entry and + * provides convenience methods to access it. + */ + class DxvkStateCacheEntryData { + constexpr static size_t MaxSize = 1024; + public: + + size_t size() const { + return m_size; + } + + const char* data() const { + return m_data; + } + + Sha1Hash computeHash() const { + return Sha1Hash::compute(m_data, m_size); + } + + template + bool read(T& data, uint32_t version) { + return read(data); + } + + bool read(DxvkBindingMask& data, uint32_t version) { + if (version < 9) { + DxvkBindingMaskV8 v8; + + if (!read(v8)) + return false; + + data = v8.convert(); + return true; + } + + return read(data); + } + + bool read(DxvkIlBinding& data, uint32_t version) { + if (version < 10) { + DxvkIlBindingV9 v9; + + if (!read(v9)) + return false; + + data = v9.convert(); + return true; + } + + return read(data); + } + + template + bool write(const T& data) { + if (m_size + sizeof(T) > MaxSize) + return false; + + std::memcpy(&m_data[m_size], &data, sizeof(T)); + m_size += sizeof(T); + return true; + } + + bool readFromStream(std::istream& stream, size_t size) { + if (size > MaxSize) + return false; + + if (!stream.read(m_data, size)) + return false; + + m_size = size; + m_read = 0; + return true; + } + + private: + + size_t m_size = 0; + size_t m_read = 0; + char m_data[MaxSize]; + + template + bool read(T& data) { + if (m_read + sizeof(T) > m_size) + return false; + + std::memcpy(&data, &m_data[m_read], sizeof(T)); + m_read += sizeof(T); + return true; + } + + }; + + + template + bool readCacheEntryTyped(std::istream& stream, T& entry) { + auto data = reinterpret_cast(&entry); + auto size = sizeof(entry); + + if (!stream.read(data, size)) + return false; + + Sha1Hash expectedHash = std::exchange(entry.hash, g_nullHash); + Sha1Hash computedHash = Sha1Hash::compute(entry); + return expectedHash == computedHash; + } + + + bool DxvkStateCacheKey::eq(const DxvkStateCacheKey& key) const { + return this->vs.eq(key.vs) + && this->tcs.eq(key.tcs) + && this->tes.eq(key.tes) + && this->gs.eq(key.gs) + && this->fs.eq(key.fs) + && this->cs.eq(key.cs); + } + + + size_t DxvkStateCacheKey::hash() const { + DxvkHashState hash; + hash.add(this->vs.hash()); + hash.add(this->tcs.hash()); + hash.add(this->tes.hash()); + hash.add(this->gs.hash()); + hash.add(this->fs.hash()); + hash.add(this->cs.hash()); + return hash; + } + + + DxvkStateCache::DxvkStateCache( + DxvkDevice* device, + DxvkPipelineManager* pipeManager, + DxvkRenderPassPool* passManager) + : m_device (device), + m_pipeManager (pipeManager), + m_passManager (passManager) { + bool newFile = !readCacheFile(); + + if (newFile) { + Logger::warn("DXVK: Creating new state cache file"); + + // Start with an empty file + std::ofstream file(getCacheFileName().c_str(), + std::ios_base::binary | + std::ios_base::trunc); + + if (!file && env::createDirectory(getCacheDir())) { + file = std::ofstream(getCacheFileName().c_str(), + std::ios_base::binary | + std::ios_base::trunc); + } + + // Write header with the current version number + DxvkStateCacheHeader header; + + auto data = reinterpret_cast(&header); + auto size = sizeof(header); + + file.write(data, size); + + // Write all valid entries to the cache file in + // case we're recovering a corrupted cache file + for (auto& e : m_entries) + writeCacheEntry(file, e); + } + } + + + DxvkStateCache::~DxvkStateCache() { + this->stopWorkerThreads(); + } + + + void DxvkStateCache::addGraphicsPipeline( + const DxvkStateCacheKey& shaders, + const DxvkGraphicsPipelineStateInfo& state, + const DxvkRenderPassFormat& format) { + if (shaders.vs.eq(g_nullShaderKey)) + return; + + // Do not add an entry that is already in the cache + auto entries = m_entryMap.equal_range(shaders); + + for (auto e = entries.first; e != entries.second; e++) { + const DxvkStateCacheEntry& entry = m_entries[e->second]; + + if (entry.format.eq(format) && entry.gpState == state) + return; + } + + // Queue a job to write this pipeline to the cache + std::unique_lock lock(m_writerLock); + + m_writerQueue.push({ shaders, state, + DxvkComputePipelineStateInfo(), + format, g_nullHash }); + m_writerCond.notify_one(); + + createWriter(); + } + + + void DxvkStateCache::addComputePipeline( + const DxvkStateCacheKey& shaders, + const DxvkComputePipelineStateInfo& state) { + if (shaders.cs.eq(g_nullShaderKey)) + return; + + // Do not add an entry that is already in the cache + auto entries = m_entryMap.equal_range(shaders); + + for (auto e = entries.first; e != entries.second; e++) { + if (m_entries[e->second].cpState == state) + return; + } + + // Queue a job to write this pipeline to the cache + std::unique_lock lock(m_writerLock); + + m_writerQueue.push({ shaders, + DxvkGraphicsPipelineStateInfo(), state, + DxvkRenderPassFormat(), g_nullHash }); + m_writerCond.notify_one(); + + createWriter(); + } + + + void DxvkStateCache::registerShader(const Rc& shader) { + DxvkShaderKey key = shader->getShaderKey(); + + if (key.eq(g_nullShaderKey)) + return; + + // Add the shader so we can look it up by its key + std::unique_lock entryLock(m_entryLock); + m_shaderMap.insert({ key, shader }); + + // Deferred lock, don't stall workers unless we have to + std::unique_lock workerLock; + + auto pipelines = m_pipelineMap.equal_range(key); + + for (auto p = pipelines.first; p != pipelines.second; p++) { + WorkerItem item; + + if (!getShaderByKey(p->second.vs, item.gp.vs) + || !getShaderByKey(p->second.tcs, item.gp.tcs) + || !getShaderByKey(p->second.tes, item.gp.tes) + || !getShaderByKey(p->second.gs, item.gp.gs) + || !getShaderByKey(p->second.fs, item.gp.fs) + || !getShaderByKey(p->second.cs, item.cp.cs)) + continue; + + if (!workerLock) + workerLock = std::unique_lock(m_workerLock); + + m_workerQueue.push(item); + } + + if (workerLock) { + m_workerCond.notify_all(); + createWorkers(); + } + } + + + void DxvkStateCache::stopWorkerThreads() { + { std::lock_guard workerLock(m_workerLock); + std::lock_guard writerLock(m_writerLock); + + if (m_stopThreads.exchange(true)) + return; + + m_workerCond.notify_all(); + m_writerCond.notify_all(); + } + + for (auto& worker : m_workerThreads) + worker.join(); + + if (m_writerThread.joinable()) + m_writerThread.join(); + } + + + DxvkShaderKey DxvkStateCache::getShaderKey(const Rc& shader) const { + return shader != nullptr ? shader->getShaderKey() : g_nullShaderKey; + } + + + bool DxvkStateCache::getShaderByKey( + const DxvkShaderKey& key, + Rc& shader) const { + if (key.eq(g_nullShaderKey)) + return true; + + auto entry = m_shaderMap.find(key); + if (entry == m_shaderMap.end()) + return false; + + shader = entry->second; + return true; + } + + + void DxvkStateCache::mapPipelineToEntry( + const DxvkStateCacheKey& key, + size_t entryId) { + m_entryMap.insert({ key, entryId }); + } + + + void DxvkStateCache::mapShaderToPipeline( + const DxvkShaderKey& shader, + const DxvkStateCacheKey& key) { + if (!shader.eq(g_nullShaderKey)) + m_pipelineMap.insert({ shader, key }); + } + + + void DxvkStateCache::compilePipelines(const WorkerItem& item) { + DxvkStateCacheKey key; + key.vs = getShaderKey(item.gp.vs); + key.tcs = getShaderKey(item.gp.tcs); + key.tes = getShaderKey(item.gp.tes); + key.gs = getShaderKey(item.gp.gs); + key.fs = getShaderKey(item.gp.fs); + key.cs = getShaderKey(item.cp.cs); + + if (item.cp.cs == nullptr) { + auto pipeline = m_pipeManager->createGraphicsPipeline(item.gp); + auto entries = m_entryMap.equal_range(key); + + for (auto e = entries.first; e != entries.second; e++) { + const auto& entry = m_entries[e->second]; + + if (m_passManager->validateRenderPassFormat(entry.format)) { + auto rp = m_passManager->getRenderPass(entry.format); + pipeline->compilePipeline(entry.gpState, rp); + } + } + } else { + auto pipeline = m_pipeManager->createComputePipeline(item.cp); + auto entries = m_entryMap.equal_range(key); + + for (auto e = entries.first; e != entries.second; e++) { + const auto& entry = m_entries[e->second]; + pipeline->compilePipeline(entry.cpState); + } + } + } + + + bool DxvkStateCache::readCacheFile() { + // Open state file and just fail if it doesn't exist + std::ifstream ifile(getCacheFileName().c_str(), std::ios_base::binary); + + if (!ifile) { + Logger::warn("DXVK: No state cache file found"); + return false; + } + + // The header stores the state cache version, + // we need to regenerate it if it's outdated + DxvkStateCacheHeader newHeader; + DxvkStateCacheHeader curHeader; + + if (!readCacheHeader(ifile, curHeader)) { + Logger::warn("DXVK: Failed to read state cache header"); + return false; + } + + // Struct size hasn't changed between v2 and v4 + size_t expectedSize = newHeader.entrySize; + + if (curHeader.version <= 4) + expectedSize = sizeof(DxvkStateCacheEntryV4); + else if (curHeader.version <= 5) + expectedSize = sizeof(DxvkStateCacheEntryV5); + else if (curHeader.version <= 6) + expectedSize = sizeof(DxvkStateCacheEntryV6); + else if (curHeader.version <= 7) + expectedSize = sizeof(DxvkStateCacheEntry); + + if (curHeader.entrySize != expectedSize) { + Logger::warn("DXVK: State cache entry size changed"); + return false; + } + + // Discard caches of unsupported versions + if (curHeader.version < 2 || curHeader.version > newHeader.version) { + Logger::warn("DXVK: State cache version not supported"); + return false; + } + + // Notify user about format conversion + if (curHeader.version != newHeader.version) + Logger::warn(str::format("DXVK: Updating state cache version to v", newHeader.version)); + + // Read actual cache entries from the file. + // If we encounter invalid entries, we should + // regenerate the entire state cache file. + uint32_t numInvalidEntries = 0; + + while (ifile) { + DxvkStateCacheEntry entry; + + if (readCacheEntry(curHeader.version, ifile, entry)) { + size_t entryId = m_entries.size(); + m_entries.push_back(entry); + + mapPipelineToEntry(entry.shaders, entryId); + + mapShaderToPipeline(entry.shaders.vs, entry.shaders); + mapShaderToPipeline(entry.shaders.tcs, entry.shaders); + mapShaderToPipeline(entry.shaders.tes, entry.shaders); + mapShaderToPipeline(entry.shaders.gs, entry.shaders); + mapShaderToPipeline(entry.shaders.fs, entry.shaders); + mapShaderToPipeline(entry.shaders.cs, entry.shaders); + } else if (ifile) { + numInvalidEntries += 1; + } + } + + Logger::info(str::format( + "DXVK: Read ", m_entries.size(), + " valid state cache entries")); + + if (numInvalidEntries) { + Logger::warn(str::format( + "DXVK: Skipped ", numInvalidEntries, + " invalid state cache entries")); + return false; + } + + // Rewrite entire state cache if it is outdated + return curHeader.version == newHeader.version; + } + + + bool DxvkStateCache::readCacheHeader( + std::istream& stream, + DxvkStateCacheHeader& header) const { + DxvkStateCacheHeader expected; + + auto data = reinterpret_cast(&header); + auto size = sizeof(header); + + if (!stream.read(data, size)) + return false; + + for (uint32_t i = 0; i < 4; i++) { + if (expected.magic[i] != header.magic[i]) + return false; + } + + return true; + } + + + bool DxvkStateCache::readCacheEntryV7( + uint32_t version, + std::istream& stream, + DxvkStateCacheEntry& entry) const { + if (version <= 6) { + DxvkStateCacheEntryV6 v6; + + if (version <= 4) { + DxvkStateCacheEntryV4 v4; + + if (!readCacheEntryTyped(stream, v4)) + return false; + + if (version == 2) + convertEntryV2(v4); + + if (!convertEntryV4(v4, v6)) + return false; + } else if (version <= 5) { + DxvkStateCacheEntryV5 v5; + + if (!readCacheEntryTyped(stream, v5)) + return false; + + if (!convertEntryV5(v5, v6)) + return false; + } else { + if (!readCacheEntryTyped(stream, v6)) + return false; + } + + return convertEntryV6(v6, entry); + } else { + return readCacheEntryTyped(stream, entry); + } + } + + + bool DxvkStateCache::readCacheEntry( + uint32_t version, + std::istream& stream, + DxvkStateCacheEntry& entry) const { + if (version < 8) + return readCacheEntryV7(version, stream, entry); + + // Read entry metadata and actual data + DxvkStateCacheEntryHeader header; + DxvkStateCacheEntryData data; + Sha1Hash hash; + + if (!stream.read(reinterpret_cast(&header), sizeof(header)) + || !stream.read(reinterpret_cast(&hash), sizeof(hash)) + || !data.readFromStream(stream, header.entrySize)) + return false; + + // Validate hash, skip entry if invalid + if (hash != data.computeHash()) + return false; + + // Read shader hashes + VkShaderStageFlags stageMask = VkShaderStageFlags(header.stageMask); + auto keys = &entry.shaders.vs; + + for (uint32_t i = 0; i < 6; i++) { + if (stageMask & VkShaderStageFlagBits(1 << i)) + data.read(keys[i], version); + else + keys[i] = g_nullShaderKey; + } + + if (stageMask & VK_SHADER_STAGE_COMPUTE_BIT) { + if (!data.read(entry.cpState.bsBindingMask, version)) + return false; + } else { + // Read packed render pass format + uint8_t sampleCount = 0; + uint8_t imageFormat = 0; + uint8_t imageLayout = 0; + + if (!data.read(sampleCount, version) + || !data.read(imageFormat, version) + || !data.read(imageLayout, version)) + return false; + + entry.format.sampleCount = VkSampleCountFlagBits(sampleCount); + entry.format.depth.format = VkFormat(imageFormat); + entry.format.depth.layout = unpackImageLayout(imageLayout); + + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { + if (!data.read(imageFormat, version) + || !data.read(imageLayout, version)) + return false; + + entry.format.color[i].format = VkFormat(imageFormat); + entry.format.color[i].layout = unpackImageLayout(imageLayout); + } + + if (!validateRenderPassFormat(entry.format)) + return false; + + // Read common pipeline state + if (!data.read(entry.gpState.bsBindingMask, version) + || !data.read(entry.gpState.ia, version) + || !data.read(entry.gpState.il, version) + || !data.read(entry.gpState.rs, version) + || !data.read(entry.gpState.ms, version) + || !data.read(entry.gpState.ds, version) + || !data.read(entry.gpState.om, version) + || !data.read(entry.gpState.dsFront, version) + || !data.read(entry.gpState.dsBack, version)) + return false; + + if (entry.gpState.il.attributeCount() > MaxNumVertexAttributes + || entry.gpState.il.bindingCount() > MaxNumVertexBindings) + return false; + + // Read render target swizzles + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { + if (!data.read(entry.gpState.omSwizzle[i], version)) + return false; + } + + // Read render target blend info + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { + if (!data.read(entry.gpState.omBlend[i], version)) + return false; + } + + // Read defined vertex attributes + for (uint32_t i = 0; i < entry.gpState.il.attributeCount(); i++) { + if (!data.read(entry.gpState.ilAttributes[i], version)) + return false; + } + + // Read defined vertex bindings + for (uint32_t i = 0; i < entry.gpState.il.bindingCount(); i++) { + if (!data.read(entry.gpState.ilBindings[i], version)) + return false; + } + } + + // Read non-zero spec constants + auto& sc = (stageMask & VK_SHADER_STAGE_COMPUTE_BIT) + ? entry.cpState.sc + : entry.gpState.sc; + + uint32_t specConstantMask = 0; + + if (!data.read(specConstantMask, version)) + return false; + + for (uint32_t i = 0; i < MaxNumSpecConstants; i++) { + if (specConstantMask & (1 << i)) { + if (!data.read(sc.specConstants[i], version)) + return false; + } + } + + return true; + } + + + void DxvkStateCache::writeCacheEntry( + std::ostream& stream, + DxvkStateCacheEntry& entry) const { + DxvkStateCacheEntryData data; + VkShaderStageFlags stageMask = 0; + + // Write shader hashes + auto keys = &entry.shaders.vs; + + for (uint32_t i = 0; i < 6; i++) { + if (!keys[i].eq(g_nullShaderKey)) { + stageMask |= VkShaderStageFlagBits(1 << i); + data.write(keys[i]); + } + } + + if (stageMask & VK_SHADER_STAGE_COMPUTE_BIT) { + // Nothing else here to write out + data.write(entry.cpState.bsBindingMask); + } else { + // Pack render pass format + data.write(uint8_t(entry.format.sampleCount)); + data.write(uint8_t(entry.format.depth.format)); + data.write(packImageLayout(entry.format.depth.layout)); + + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { + data.write(uint8_t(entry.format.color[i].format)); + data.write(packImageLayout(entry.format.color[i].layout)); + } + + // Write out common pipeline state + data.write(entry.gpState.bsBindingMask); + data.write(entry.gpState.ia); + data.write(entry.gpState.il); + data.write(entry.gpState.rs); + data.write(entry.gpState.ms); + data.write(entry.gpState.ds); + data.write(entry.gpState.om); + data.write(entry.gpState.dsFront); + data.write(entry.gpState.dsBack); + + // Write out render target swizzles and blend info + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) + data.write(entry.gpState.omSwizzle[i]); + + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) + data.write(entry.gpState.omBlend[i]); + + // Write out input layout for defined attributes + for (uint32_t i = 0; i < entry.gpState.il.attributeCount(); i++) + data.write(entry.gpState.ilAttributes[i]); + + for (uint32_t i = 0; i < entry.gpState.il.bindingCount(); i++) + data.write(entry.gpState.ilBindings[i]); + } + + // Write out all non-zero spec constants + auto& sc = (stageMask & VK_SHADER_STAGE_COMPUTE_BIT) + ? entry.cpState.sc + : entry.gpState.sc; + + uint32_t specConstantMask = 0; + + for (uint32_t i = 0; i < MaxNumSpecConstants; i++) + specConstantMask |= sc.specConstants[i] ? (1 << i) : 0; + + data.write(specConstantMask); + + for (uint32_t i = 0; i < MaxNumSpecConstants; i++) { + if (specConstantMask & (1 << i)) + data.write(sc.specConstants[i]); + } + + // General layout: header -> hash -> data + DxvkStateCacheEntryHeader header; + header.stageMask = uint8_t(stageMask); + header.entrySize = data.size(); + + Sha1Hash hash = data.computeHash(); + + stream.write(reinterpret_cast(&header), sizeof(header)); + stream.write(reinterpret_cast(&hash), sizeof(hash)); + stream.write(data.data(), data.size()); + stream.flush(); + } + + + bool DxvkStateCache::convertEntryV2( + DxvkStateCacheEntryV4& entry) const { + // Semantics changed: + // v2: rsDepthClampEnable + // v3: rsDepthClipEnable + entry.gpState.rsDepthClipEnable = !entry.gpState.rsDepthClipEnable; + + // Frontend changed: Depth bias + // will typically be disabled + entry.gpState.rsDepthBiasEnable = VK_FALSE; + return true; + } + + + bool DxvkStateCache::convertEntryV4( + const DxvkStateCacheEntryV4& in, + DxvkStateCacheEntryV6& out) const { + out.shaders = in.shaders; + out.format = in.format; + out.hash = in.hash; + + out.cpState.bsBindingMask = in.cpState.bsBindingMask; + out.gpState.bsBindingMask = in.gpState.bsBindingMask; + + out.gpState.iaPrimitiveTopology = in.gpState.iaPrimitiveTopology; + out.gpState.iaPrimitiveRestart = in.gpState.iaPrimitiveRestart; + out.gpState.iaPatchVertexCount = in.gpState.iaPatchVertexCount; + + out.gpState.ilAttributeCount = in.gpState.ilAttributeCount; + out.gpState.ilBindingCount = in.gpState.ilBindingCount; + + for (uint32_t i = 0; i < in.gpState.ilAttributeCount; i++) + out.gpState.ilAttributes[i] = in.gpState.ilAttributes[i]; + + for (uint32_t i = 0; i < in.gpState.ilBindingCount; i++) { + out.gpState.ilBindings[i] = in.gpState.ilBindings[i]; + out.gpState.ilDivisors[i] = in.gpState.ilDivisors[i]; + } + + out.gpState.rsDepthClipEnable = in.gpState.rsDepthClipEnable; + out.gpState.rsDepthBiasEnable = in.gpState.rsDepthBiasEnable; + out.gpState.rsPolygonMode = in.gpState.rsPolygonMode; + out.gpState.rsCullMode = in.gpState.rsCullMode; + out.gpState.rsFrontFace = in.gpState.rsFrontFace; + out.gpState.rsViewportCount = in.gpState.rsViewportCount; + out.gpState.rsSampleCount = in.gpState.rsSampleCount; + + out.gpState.msSampleCount = in.gpState.msSampleCount; + out.gpState.msSampleMask = in.gpState.msSampleMask; + out.gpState.msEnableAlphaToCoverage = in.gpState.msEnableAlphaToCoverage; + + out.gpState.dsEnableDepthTest = in.gpState.dsEnableDepthTest; + out.gpState.dsEnableDepthWrite = in.gpState.dsEnableDepthWrite; + out.gpState.dsEnableStencilTest = in.gpState.dsEnableStencilTest; + out.gpState.dsDepthCompareOp = in.gpState.dsDepthCompareOp; + out.gpState.dsStencilOpFront = in.gpState.dsStencilOpFront; + out.gpState.dsStencilOpBack = in.gpState.dsStencilOpBack; + + out.gpState.omEnableLogicOp = in.gpState.omEnableLogicOp; + out.gpState.omLogicOp = in.gpState.omLogicOp; + + for (uint32_t i = 0; i < 8; i++) { + out.gpState.omBlendAttachments[i] = in.gpState.omBlendAttachments[i]; + out.gpState.omComponentMapping[i] = in.gpState.omComponentMapping[i]; + } + + return true; + } + + + bool DxvkStateCache::convertEntryV5( + const DxvkStateCacheEntryV5& in, + DxvkStateCacheEntryV6& out) const { + out.shaders = in.shaders; + out.gpState = in.gpState; + out.format = in.format; + out.hash = in.hash; + + out.cpState.bsBindingMask = in.cpState.bsBindingMask; + return true; + } + + + bool DxvkStateCache::convertEntryV6( + const DxvkStateCacheEntryV6& in, + DxvkStateCacheEntry& out) const { + out.shaders = in.shaders; + out.format = in.format; + out.hash = in.hash; + + if (in.shaders.cs.eq(g_nullShaderKey)) { + // Binding mask + out.gpState.bsBindingMask = in.gpState.bsBindingMask.convert(); + + // Graphics state + out.gpState.ia = DxvkIaInfo( + in.gpState.iaPrimitiveTopology, + in.gpState.iaPrimitiveRestart, + in.gpState.iaPatchVertexCount); + + out.gpState.il = DxvkIlInfo( + in.gpState.ilAttributeCount, + in.gpState.ilBindingCount); + + for (uint32_t i = 0; i < in.gpState.ilAttributeCount; i++) { + out.gpState.ilAttributes[i] = DxvkIlAttribute( + in.gpState.ilAttributes[i].location, + in.gpState.ilAttributes[i].binding, + in.gpState.ilAttributes[i].format, + in.gpState.ilAttributes[i].offset); + } + + for (uint32_t i = 0; i < in.gpState.ilBindingCount; i++) { + out.gpState.ilBindings[i] = DxvkIlBinding( + in.gpState.ilBindings[i].binding, + in.gpState.ilBindings[i].stride, + in.gpState.ilBindings[i].inputRate, + in.gpState.ilDivisors[i]); + } + + out.gpState.rs = DxvkRsInfo( + in.gpState.rsDepthClipEnable, + in.gpState.rsDepthBiasEnable, + in.gpState.rsPolygonMode, + in.gpState.rsCullMode, + in.gpState.rsFrontFace, + in.gpState.rsViewportCount, + in.gpState.rsSampleCount, + VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT); + + out.gpState.ms = DxvkMsInfo( + in.gpState.msSampleCount, + in.gpState.msSampleMask, + in.gpState.msEnableAlphaToCoverage); + + out.gpState.ds = DxvkDsInfo( + in.gpState.dsEnableDepthTest, + in.gpState.dsEnableDepthWrite, + in.gpState.dsEnableDepthBoundsTest, + in.gpState.dsEnableStencilTest, + in.gpState.dsDepthCompareOp); + + out.gpState.dsFront = DxvkDsStencilOp(in.gpState.dsStencilOpFront); + out.gpState.dsBack = DxvkDsStencilOp(in.gpState.dsStencilOpBack); + + out.gpState.om = DxvkOmInfo( + in.gpState.omEnableLogicOp, + in.gpState.omLogicOp); + + for (uint32_t i = 0; i < 8 && i < MaxNumRenderTargets; i++) { + out.gpState.omBlend[i] = DxvkOmAttachmentBlend( + in.gpState.omBlendAttachments[i].blendEnable, + in.gpState.omBlendAttachments[i].srcColorBlendFactor, + in.gpState.omBlendAttachments[i].dstColorBlendFactor, + in.gpState.omBlendAttachments[i].colorBlendOp, + in.gpState.omBlendAttachments[i].srcAlphaBlendFactor, + in.gpState.omBlendAttachments[i].dstAlphaBlendFactor, + in.gpState.omBlendAttachments[i].alphaBlendOp, + in.gpState.omBlendAttachments[i].colorWriteMask); + + out.gpState.omSwizzle[i] = DxvkOmAttachmentSwizzle( + in.gpState.omComponentMapping[i]); + } + + // Specialization constants + for (uint32_t i = 0; i < 8 && i < MaxNumSpecConstants; i++) + out.cpState.sc.specConstants[i] = in.cpState.scSpecConstants[i]; + } else { + // Binding mask + out.cpState.bsBindingMask = in.cpState.bsBindingMask.convert(); + + for (uint32_t i = 0; i < 8 && i < MaxNumSpecConstants; i++) + out.gpState.sc.specConstants[i] = in.gpState.scSpecConstants[i]; + } + + return true; + } + + + void DxvkStateCache::workerFunc() { + env::setThreadName("dxvk-shader"); + + while (!m_stopThreads.load()) { + WorkerItem item; + + { std::unique_lock lock(m_workerLock); + + if (m_workerQueue.empty()) { + m_workerBusy -= 1; + m_workerCond.wait(lock, [this] () { + return m_workerQueue.size() + || m_stopThreads.load(); + }); + + if (!m_workerQueue.empty()) + m_workerBusy += 1; + } + + if (m_workerQueue.empty()) + break; + + item = m_workerQueue.front(); + m_workerQueue.pop(); + } + + compilePipelines(item); + } + } + + + void DxvkStateCache::writerFunc() { + env::setThreadName("dxvk-writer"); + + std::ofstream file; + + while (!m_stopThreads.load()) { + DxvkStateCacheEntry entry; + + { std::unique_lock lock(m_writerLock); + + m_writerCond.wait(lock, [this] () { + return m_writerQueue.size() + || m_stopThreads.load(); + }); + + if (m_writerQueue.size() == 0) + break; + + entry = m_writerQueue.front(); + m_writerQueue.pop(); + } + + if (!file.is_open()) { + file.open(getCacheFileName().c_str(), + std::ios_base::binary | + std::ios_base::app); + } + + writeCacheEntry(file, entry); + } + } + + + void DxvkStateCache::createWorkers() { + if (m_workerThreads.empty()) { + // Use half the available CPU cores for pipeline compilation + uint32_t numCpuCores = dxvk::thread::hardware_concurrency(); + uint32_t numWorkers = ((std::max(1u, numCpuCores) - 1) * 5) / 7; + + if (numWorkers < 1) numWorkers = 1; + if (numWorkers > 32) numWorkers = 32; + + if (m_device->config().numCompilerThreads > 0) + numWorkers = m_device->config().numCompilerThreads; + + Logger::info(str::format("DXVK: Using ", numWorkers, " compiler threads")); + + // Start the worker threads and the file writer + m_workerBusy.store(numWorkers); + + for (uint32_t i = 0; i < numWorkers; i++) { + m_workerThreads.emplace_back([this] () { workerFunc(); }); + m_workerThreads[i].set_priority(ThreadPriority::Lowest); + } + } + } + + + void DxvkStateCache::createWriter() { + if (!m_writerThread.joinable()) + m_writerThread = dxvk::thread([this] () { writerFunc(); }); + } + + + std::wstring DxvkStateCache::getCacheFileName() const { + std::string path = getCacheDir(); + + if (!path.empty() && *path.rbegin() != '/') + path += '/'; + + std::string exeName = env::getExeBaseName(); + path += exeName + ".dxvk-cache"; + return str::tows(path.c_str()); + } + + + std::string DxvkStateCache::getCacheDir() const { + return env::getEnvVar("DXVK_STATE_CACHE_PATH"); + } + + + uint8_t DxvkStateCache::packImageLayout( + VkImageLayout layout) { + switch (layout) { + case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL: return 0x80; + case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL: return 0x81; + default: return uint8_t(layout); + } + } + + + VkImageLayout DxvkStateCache::unpackImageLayout( + uint8_t layout) { + switch (layout) { + case 0x80: return VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL; + case 0x81: return VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL; + default: return VkImageLayout(layout); + } + } + + + bool DxvkStateCache::validateRenderPassFormat( + const DxvkRenderPassFormat& format) { + bool valid = true; + + if (format.depth.format) { + valid &= format.depth.layout == VK_IMAGE_LAYOUT_GENERAL + || format.depth.layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL + || format.depth.layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL + || format.depth.layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL + || format.depth.layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL; + } + + for (uint32_t i = 0; i < MaxNumRenderTargets && valid; i++) { + if (format.color[i].format) { + valid &= format.color[i].layout == VK_IMAGE_LAYOUT_GENERAL + || format.color[i].layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + } + } + + return valid; + } + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_state_cache.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_state_cache.h new file mode 100644 index 00000000000..f23c85f059f --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_state_cache.h @@ -0,0 +1,204 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include "dxvk_state_cache_types.h" + +namespace dxvk { + + class DxvkDevice; + + /** + * \brief State cache + * + * The shader state cache stores state vectors and + * render pass formats of all pipelines used in a + * game, which allows DXVK to compile them ahead + * of time instead of compiling them on the first + * draw. + */ + class DxvkStateCache : public RcObject { + + public: + + DxvkStateCache( + DxvkDevice* device, + DxvkPipelineManager* pipeManager, + DxvkRenderPassPool* passManager); + + ~DxvkStateCache(); + + /** + * Adds a graphics pipeline to the cache + * + * If the pipeline is not already cached, this + * will write a new pipeline to the cache file. + * \param [in] shaders Shader keys + * \param [in] state Graphics pipeline state + * \param [in] format Render pass format + */ + void addGraphicsPipeline( + const DxvkStateCacheKey& shaders, + const DxvkGraphicsPipelineStateInfo& state, + const DxvkRenderPassFormat& format); + + /** + * Adds a compute pipeline to the cache + * + * If the pipeline is not already cached, this + * will write a new pipeline to the cache file. + * \param [in] shaders Shader keys + * \param [in] state Compute pipeline state + */ + void addComputePipeline( + const DxvkStateCacheKey& shaders, + const DxvkComputePipelineStateInfo& state); + + /** + * \brief Registers a newly compiled shader + * + * Makes the shader available to the pipeline + * compiler, and starts compiling all pipelines + * for which all shaders become available. + * \param [in] shader The shader to add + */ + void registerShader( + const Rc& shader); + + /** + * \brief Explicitly stops worker threads + */ + void stopWorkerThreads(); + + /** + * \brief Checks whether compiler threads are busy + * \returns \c true if we're compiling shaders + */ + bool isCompilingShaders() { + return m_workerBusy.load() > 0; + } + + private: + + using WriterItem = DxvkStateCacheEntry; + + struct WorkerItem { + DxvkGraphicsPipelineShaders gp; + DxvkComputePipelineShaders cp; + }; + + DxvkDevice* m_device; + DxvkPipelineManager* m_pipeManager; + DxvkRenderPassPool* m_passManager; + + std::vector m_entries; + std::atomic m_stopThreads = { false }; + + dxvk::mutex m_entryLock; + + std::unordered_multimap< + DxvkStateCacheKey, size_t, + DxvkHash, DxvkEq> m_entryMap; + + std::unordered_multimap< + DxvkShaderKey, DxvkStateCacheKey, + DxvkHash, DxvkEq> m_pipelineMap; + + std::unordered_map< + DxvkShaderKey, Rc, + DxvkHash, DxvkEq> m_shaderMap; + + dxvk::mutex m_workerLock; + dxvk::condition_variable m_workerCond; + std::queue m_workerQueue; + std::atomic m_workerBusy; + std::vector m_workerThreads; + + dxvk::mutex m_writerLock; + dxvk::condition_variable m_writerCond; + std::queue m_writerQueue; + dxvk::thread m_writerThread; + + DxvkShaderKey getShaderKey( + const Rc& shader) const; + + bool getShaderByKey( + const DxvkShaderKey& key, + Rc& shader) const; + + void mapPipelineToEntry( + const DxvkStateCacheKey& key, + size_t entryId); + + void mapShaderToPipeline( + const DxvkShaderKey& shader, + const DxvkStateCacheKey& key); + + void compilePipelines( + const WorkerItem& item); + + bool readCacheFile(); + + bool readCacheHeader( + std::istream& stream, + DxvkStateCacheHeader& header) const; + + bool readCacheEntryV7( + uint32_t version, + std::istream& stream, + DxvkStateCacheEntry& entry) const; + + bool readCacheEntry( + uint32_t version, + std::istream& stream, + DxvkStateCacheEntry& entry) const; + + void writeCacheEntry( + std::ostream& stream, + DxvkStateCacheEntry& entry) const; + + bool convertEntryV2( + DxvkStateCacheEntryV4& entry) const; + + bool convertEntryV4( + const DxvkStateCacheEntryV4& in, + DxvkStateCacheEntryV6& out) const; + + bool convertEntryV5( + const DxvkStateCacheEntryV5& in, + DxvkStateCacheEntryV6& out) const; + + bool convertEntryV6( + const DxvkStateCacheEntryV6& in, + DxvkStateCacheEntry& out) const; + + void workerFunc(); + + void writerFunc(); + + void createWorkers(); + + void createWriter(); + + std::wstring getCacheFileName() const; + + std::string getCacheDir() const; + + static uint8_t packImageLayout( + VkImageLayout layout); + + static VkImageLayout unpackImageLayout( + uint8_t layout); + + static bool validateRenderPassFormat( + const DxvkRenderPassFormat& format); + + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_state_cache_types.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_state_cache_types.h new file mode 100644 index 00000000000..41ff4d470cc --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_state_cache_types.h @@ -0,0 +1,233 @@ +#pragma once + +#include "dxvk_pipemanager.h" +#include "dxvk_renderpass.h" + +namespace dxvk { + + /** + * \brief State cache entry key + * + * Stores the shader keys for all + * graphics shader stages. Used to + * look up cached state entries. + */ + struct DxvkStateCacheKey { + DxvkShaderKey vs; + DxvkShaderKey tcs; + DxvkShaderKey tes; + DxvkShaderKey gs; + DxvkShaderKey fs; + DxvkShaderKey cs; + + bool eq(const DxvkStateCacheKey& key) const; + + size_t hash() const; + }; + + + /** + * \brief State entry + * + * Stores the shaders used in a pipeline, as well + * as the full state vector, including its render + * pass format. This also includes a SHA-1 hash + * that is used as a check sum to verify integrity. + */ + struct DxvkStateCacheEntry { + DxvkStateCacheKey shaders; + DxvkGraphicsPipelineStateInfo gpState; + DxvkComputePipelineStateInfo cpState; + DxvkRenderPassFormat format; + Sha1Hash hash; + }; + + + /** + * \brief State cache header + * + * Stores the state cache format version. If an + * existing cache file is incompatible to the + * current version, it will be discarded. + */ + struct DxvkStateCacheHeader { + char magic[4] = { 'D', 'X', 'V', 'K' }; + uint32_t version = 10; + uint32_t entrySize = 0; /* no longer meaningful */ + }; + + static_assert(sizeof(DxvkStateCacheHeader) == 12); + + + class DxvkBindingMaskV8 : DxvkBindingSet<128> { + + public: + + DxvkBindingMask convert() const { + DxvkBindingMask result = { }; + for (uint32_t i = 0; i < 128; i++) + result.set(i, test(i)); + return result; + } + + }; + + class DxvkIlBindingV9 { + + public: + + uint32_t m_binding : 5; + uint32_t m_stride : 12; + uint32_t m_inputRate : 1; + uint32_t m_reserved : 14; + uint32_t m_divisor; + + DxvkIlBinding convert() const { + return DxvkIlBinding(m_binding, m_stride, + VkVertexInputRate(m_inputRate), m_divisor); + } + + }; + + /** + * \brief Version 4 graphics pipeline state + */ + struct DxvkGraphicsPipelineStateInfoV4 { + DxvkBindingMaskV8 bsBindingMask; + + VkPrimitiveTopology iaPrimitiveTopology; + VkBool32 iaPrimitiveRestart; + uint32_t iaPatchVertexCount; + + uint32_t ilAttributeCount; + uint32_t ilBindingCount; + VkVertexInputAttributeDescription ilAttributes[32]; + VkVertexInputBindingDescription ilBindings[32]; + uint32_t ilDivisors[32]; + + VkBool32 rsDepthClipEnable; + VkBool32 rsDepthBiasEnable; + VkPolygonMode rsPolygonMode; + VkCullModeFlags rsCullMode; + VkFrontFace rsFrontFace; + uint32_t rsViewportCount; + VkSampleCountFlags rsSampleCount; + + VkSampleCountFlags msSampleCount; + uint32_t msSampleMask; + VkBool32 msEnableAlphaToCoverage; + + VkCompareOp xsAlphaCompareOp; + + VkBool32 dsEnableDepthTest; + VkBool32 dsEnableDepthWrite; + VkBool32 dsEnableStencilTest; + VkCompareOp dsDepthCompareOp; + VkStencilOpState dsStencilOpFront; + VkStencilOpState dsStencilOpBack; + + VkBool32 omEnableLogicOp; + VkLogicOp omLogicOp; + VkPipelineColorBlendAttachmentState omBlendAttachments[8]; + VkComponentMapping omComponentMapping[8]; + }; + + + /** + * \brief Version 6 graphics pipeline state + */ + struct DxvkGraphicsPipelineStateInfoV6 { + DxvkBindingMaskV8 bsBindingMask; + + VkPrimitiveTopology iaPrimitiveTopology; + VkBool32 iaPrimitiveRestart; + uint32_t iaPatchVertexCount; + + uint32_t ilAttributeCount; + uint32_t ilBindingCount; + VkVertexInputAttributeDescription ilAttributes[32]; + VkVertexInputBindingDescription ilBindings[32]; + uint32_t ilDivisors[32]; + + VkBool32 rsDepthClipEnable; + VkBool32 rsDepthBiasEnable; + VkPolygonMode rsPolygonMode; + VkCullModeFlags rsCullMode; + VkFrontFace rsFrontFace; + uint32_t rsViewportCount; + VkSampleCountFlags rsSampleCount; + + VkSampleCountFlags msSampleCount; + uint32_t msSampleMask; + VkBool32 msEnableAlphaToCoverage; + + VkBool32 dsEnableDepthTest; + VkBool32 dsEnableDepthWrite; + VkBool32 dsEnableDepthBoundsTest; + VkBool32 dsEnableStencilTest; + VkCompareOp dsDepthCompareOp; + VkStencilOpState dsStencilOpFront; + VkStencilOpState dsStencilOpBack; + + VkBool32 omEnableLogicOp; + VkLogicOp omLogicOp; + VkPipelineColorBlendAttachmentState omBlendAttachments[8]; + VkComponentMapping omComponentMapping[8]; + + uint32_t scSpecConstants[8]; + }; + + + /** + * \brief Version 5 compute pipeline state + */ + struct DxvkComputePipelineStateInfoV5 { + DxvkBindingMaskV8 bsBindingMask; + }; + + + /** + * \brief Version 6 compute pipeline state + */ + struct DxvkComputePipelineStateInfoV6 { + DxvkBindingMaskV8 bsBindingMask; + uint32_t scSpecConstants[8]; + }; + + + /** + * \brief Version 4 state cache entry + */ + struct DxvkStateCacheEntryV4 { + DxvkStateCacheKey shaders; + DxvkGraphicsPipelineStateInfoV4 gpState; + DxvkComputePipelineStateInfoV5 cpState; + DxvkRenderPassFormat format; + Sha1Hash hash; + }; + + + /** + * \brief Version 5 state cache entry + */ + struct DxvkStateCacheEntryV5 { + DxvkStateCacheKey shaders; + DxvkGraphicsPipelineStateInfoV6 gpState; + DxvkComputePipelineStateInfoV5 cpState; + DxvkRenderPassFormat format; + Sha1Hash hash; + }; + + + /** + * \brief Version 6 state cache entry + */ + struct DxvkStateCacheEntryV6 { + DxvkStateCacheKey shaders; + DxvkGraphicsPipelineStateInfoV6 gpState; + DxvkComputePipelineStateInfoV6 cpState; + DxvkRenderPassFormat format; + Sha1Hash hash; + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_stats.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_stats.cpp new file mode 100644 index 00000000000..72e6f8a78dd --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_stats.cpp @@ -0,0 +1,34 @@ +#include "dxvk_stats.h" + +namespace dxvk { + + DxvkStatCounters::DxvkStatCounters() { + this->reset(); + } + + + DxvkStatCounters::~DxvkStatCounters() { + + } + + + DxvkStatCounters DxvkStatCounters::diff(const DxvkStatCounters& other) const { + DxvkStatCounters result; + for (size_t i = 0; i < m_counters.size(); i++) + result.m_counters[i] = m_counters[i] - other.m_counters[i]; + return result; + } + + + void DxvkStatCounters::merge(const DxvkStatCounters& other) { + for (size_t i = 0; i < m_counters.size(); i++) + m_counters[i] += other.m_counters[i]; + } + + + void DxvkStatCounters::reset() { + for (size_t i = 0; i < m_counters.size(); i++) + m_counters[i] = 0; + } + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_stats.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_stats.h new file mode 100644 index 00000000000..9138c7c6fb2 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_stats.h @@ -0,0 +1,115 @@ +#pragma once + +#include "dxvk_include.h" + +namespace dxvk { + + /** + * \brief Named stat counters + * + * Enumerates available stat counters. Used + * thogether with \ref DxvkStatCounters. + */ + enum class DxvkStatCounter : uint32_t { + CmdDrawCalls, ///< Number of draw calls + CmdDispatchCalls, ///< Number of compute calls + CmdRenderPassCount, ///< Number of render passes + CmdBarrierCount, ///< Number of pipeline barriers + PipeCountGraphics, ///< Number of graphics pipelines + PipeCountCompute, ///< Number of compute pipelines + PipeCompilerBusy, ///< Boolean indicating compiler activity + QueueSubmitCount, ///< Number of command buffer submissions + QueuePresentCount, ///< Number of present calls / frames + GpuSyncCount, ///< Number of GPU synchronizations + GpuSyncTicks, ///< Time spent waiting for GPU + GpuIdleTicks, ///< GPU idle time in microseconds + CsSyncCount, ///< CS thread synchronizations + CsSyncTicks, ///< Time spent waiting on CS + CsChunkCount, ///< Submitted CS chunks + NumCounters, ///< Number of counters available + }; + + + /** + * \brief Stat counters + * + * Collects various statistics that may be + * useful to identify performance bottlenecks. + */ + class DxvkStatCounters { + + public: + + DxvkStatCounters(); + ~DxvkStatCounters(); + + /** + * \brief Retrieves a counter value + * + * \param [in] ctr The counter + * \returns Counter value + */ + uint64_t getCtr(DxvkStatCounter ctr) const { + return m_counters[uint32_t(ctr)]; + } + + /** + * \brief Sets a counter value + * + * \param [in] ctr The counter + * \param [in] val Counter value + */ + void setCtr(DxvkStatCounter ctr, uint64_t val) { + m_counters[uint32_t(ctr)] = val; + } + + /** + * \brief Increments a counter value + * + * \param [in] ctr Counter to increment + * \param [in] val Number to add to counter value + */ + void addCtr(DxvkStatCounter ctr, uint64_t val) { + m_counters[uint32_t(ctr)] += val; + } + + /** + * \brief Resets a counter + * \param [in] ctr The counter + */ + void clrCtr(DxvkStatCounter ctr) { + m_counters[uint32_t(ctr)] = 0; + } + + /** + * \brief Computes difference + * + * Computes difference between counter values. + * \param [in] other Counters to subtract + * \returns Difference between counter sets + */ + DxvkStatCounters diff(const DxvkStatCounters& other) const; + + /** + * \brief Merges counters + * + * Adds counter values from another set + * of counters to this set of counters. + * \param [in] other Counters to add + */ + void merge(const DxvkStatCounters& other); + + /** + * \brief Resets counters + * + * Sets all counters to zero. + */ + void reset(); + + private: + + std::array m_counters; + + }; + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_swapchain_blitter.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_swapchain_blitter.cpp new file mode 100644 index 00000000000..611ec115e83 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_swapchain_blitter.cpp @@ -0,0 +1,388 @@ +#include "dxvk_swapchain_blitter.h" + +#include +#include +#include +#include +#include + +namespace dxvk { + + DxvkSwapchainBlitter::DxvkSwapchainBlitter(const Rc& device) + : m_device(device) { + this->createSampler(); + this->createShaders(); + } + + + DxvkSwapchainBlitter::~DxvkSwapchainBlitter() { + + } + + + void DxvkSwapchainBlitter::presentImage( + DxvkContext* ctx, + const Rc& dstView, + VkRect2D dstRect, + const Rc& srcView, + VkRect2D srcRect) { + if (m_gammaDirty) + this->updateGammaTexture(ctx); + + // Fix up default present areas if necessary + if (!dstRect.extent.width || !dstRect.extent.height) { + dstRect.offset = { 0, 0 }; + dstRect.extent = { + dstView->imageInfo().extent.width, + dstView->imageInfo().extent.height }; + } + + if (!srcRect.extent.width || !srcRect.extent.height) { + srcRect.offset = { 0, 0 }; + srcRect.extent = { + srcView->imageInfo().extent.width, + srcView->imageInfo().extent.height }; + } + + bool sameSize = dstRect.extent == srcRect.extent; + bool usedResolveImage = false; + + if (srcView->imageInfo().sampleCount == VK_SAMPLE_COUNT_1_BIT) { + this->draw(ctx, sameSize ? m_fsCopy : m_fsBlit, + dstView, dstRect, srcView, srcRect); + } else if (sameSize) { + this->draw(ctx, m_fsResolve, + dstView, dstRect, srcView, srcRect); + } else { + if (m_resolveImage == nullptr + || m_resolveImage->info().extent != srcView->imageInfo().extent + || m_resolveImage->info().format != srcView->imageInfo().format) + this->createResolveImage(srcView->imageInfo()); + + this->resolve(ctx, m_resolveView, srcView); + this->draw(ctx, m_fsBlit, dstView, dstRect, m_resolveView, srcRect); + + usedResolveImage = true; + } + + if (!usedResolveImage) + this->destroyResolveImage(); + } + + + void DxvkSwapchainBlitter::setGammaRamp( + uint32_t cpCount, + const DxvkGammaCp* cpData) { + VkDeviceSize size = cpCount * sizeof(*cpData); + + if (cpCount) { + if (m_gammaBuffer == nullptr || m_gammaBuffer->info().size < size) { + DxvkBufferCreateInfo bufInfo; + bufInfo.size = size; + bufInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + bufInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT; + bufInfo.access = VK_ACCESS_TRANSFER_READ_BIT; + + m_gammaBuffer = m_device->createBuffer(bufInfo, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | + VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + } + + if (!m_gammaSlice.handle) + m_gammaSlice = m_gammaBuffer->allocSlice(); + + std::memcpy(m_gammaSlice.mapPtr, cpData, size); + } else { + m_gammaBuffer = nullptr; + m_gammaSlice = DxvkBufferSliceHandle(); + } + + m_gammaCpCount = cpCount; + m_gammaDirty = true; + } + + + void DxvkSwapchainBlitter::draw( + DxvkContext* ctx, + const Rc& fs, + const Rc& dstView, + VkRect2D dstRect, + const Rc& srcView, + VkRect2D srcRect) { + DxvkInputAssemblyState iaState; + iaState.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; + iaState.primitiveRestart = VK_FALSE; + iaState.patchVertexCount = 0; + ctx->setInputAssemblyState(iaState); + ctx->setInputLayout(0, nullptr, 0, nullptr); + + DxvkRasterizerState rsState; + rsState.polygonMode = VK_POLYGON_MODE_FILL; + rsState.cullMode = VK_CULL_MODE_BACK_BIT; + rsState.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; + rsState.depthClipEnable = VK_FALSE; + rsState.depthBiasEnable = VK_FALSE; + rsState.conservativeMode = VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT; + rsState.sampleCount = VK_SAMPLE_COUNT_1_BIT; + ctx->setRasterizerState(rsState); + + DxvkMultisampleState msState; + msState.sampleMask = 0xffffffff; + msState.enableAlphaToCoverage = VK_FALSE; + ctx->setMultisampleState(msState); + + VkStencilOpState stencilOp; + stencilOp.failOp = VK_STENCIL_OP_KEEP; + stencilOp.passOp = VK_STENCIL_OP_KEEP; + stencilOp.depthFailOp = VK_STENCIL_OP_KEEP; + stencilOp.compareOp = VK_COMPARE_OP_ALWAYS; + stencilOp.compareMask = 0xFFFFFFFF; + stencilOp.writeMask = 0xFFFFFFFF; + stencilOp.reference = 0; + + DxvkDepthStencilState dsState; + dsState.enableDepthTest = VK_FALSE; + dsState.enableDepthWrite = VK_FALSE; + dsState.enableStencilTest = VK_FALSE; + dsState.depthCompareOp = VK_COMPARE_OP_ALWAYS; + dsState.stencilOpFront = stencilOp; + dsState.stencilOpBack = stencilOp; + ctx->setDepthStencilState(dsState); + + DxvkLogicOpState loState; + loState.enableLogicOp = VK_FALSE; + loState.logicOp = VK_LOGIC_OP_NO_OP; + ctx->setLogicOpState(loState); + + DxvkBlendMode blendMode; + blendMode.enableBlending = VK_FALSE; + blendMode.colorSrcFactor = VK_BLEND_FACTOR_ONE; + blendMode.colorDstFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + blendMode.colorBlendOp = VK_BLEND_OP_ADD; + blendMode.alphaSrcFactor = VK_BLEND_FACTOR_ONE; + blendMode.alphaDstFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + blendMode.alphaBlendOp = VK_BLEND_OP_ADD; + blendMode.writeMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT + | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + ctx->setBlendMode(0, blendMode); + + VkViewport viewport; + viewport.x = float(dstRect.offset.x); + viewport.y = float(dstRect.offset.y); + viewport.width = float(dstRect.extent.width); + viewport.height = float(dstRect.extent.height); + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + ctx->setViewports(1, &viewport, &dstRect); + + DxvkRenderTargets renderTargets; + renderTargets.color[0].view = dstView; + renderTargets.color[0].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + ctx->bindRenderTargets(renderTargets); + + VkExtent2D dstExtent = { + dstView->imageInfo().extent.width, + dstView->imageInfo().extent.height }; + + if (dstRect.extent == dstExtent) + ctx->discardImageView(dstView, VK_IMAGE_ASPECT_COLOR_BIT); + else + ctx->clearRenderTarget(dstView, VK_IMAGE_ASPECT_COLOR_BIT, VkClearValue()); + + ctx->bindResourceSampler(BindingIds::Image, m_samplerPresent); + ctx->bindResourceSampler(BindingIds::Gamma, m_samplerGamma); + + ctx->bindResourceView(BindingIds::Image, srcView, nullptr); + ctx->bindResourceView(BindingIds::Gamma, m_gammaView, nullptr); + + ctx->bindShader(VK_SHADER_STAGE_VERTEX_BIT, m_vs); + ctx->bindShader(VK_SHADER_STAGE_FRAGMENT_BIT, fs); + + PresenterArgs args; + args.srcOffset = srcRect.offset; + + if (dstRect.extent == srcRect.extent) + args.dstOffset = dstRect.offset; + else + args.srcExtent = srcRect.extent; + + ctx->pushConstants(0, sizeof(args), &args); + + ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, 0, srcView->imageInfo().sampleCount); + ctx->draw(3, 1, 0, 0); + ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, 0, 0); + } + + void DxvkSwapchainBlitter::resolve( + DxvkContext* ctx, + const Rc& dstView, + const Rc& srcView) { + VkImageResolve resolve; + resolve.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; + resolve.srcOffset = { 0, 0, 0 }; + resolve.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; + resolve.dstOffset = { 0, 0, 0 }; + resolve.extent = dstView->imageInfo().extent; + ctx->resolveImage(dstView->image(), srcView->image(), resolve, VK_FORMAT_UNDEFINED); + } + + + void DxvkSwapchainBlitter::updateGammaTexture(DxvkContext* ctx) { + uint32_t n = m_gammaCpCount; + + if (n) { + // Reuse existing image if possible + if (m_gammaImage == nullptr || m_gammaImage->info().extent.width != n) { + DxvkImageCreateInfo imgInfo; + imgInfo.type = VK_IMAGE_TYPE_1D; + imgInfo.format = VK_FORMAT_R16G16B16A16_UNORM; + imgInfo.flags = 0; + imgInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT; + imgInfo.extent = { n, 1, 1 }; + imgInfo.numLayers = 1; + imgInfo.mipLevels = 1; + imgInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_SAMPLED_BIT; + imgInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT + | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + imgInfo.access = VK_ACCESS_TRANSFER_WRITE_BIT + | VK_ACCESS_SHADER_READ_BIT; + imgInfo.tiling = VK_IMAGE_TILING_OPTIMAL; + imgInfo.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + + m_gammaImage = m_device->createImage( + imgInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + + DxvkImageViewCreateInfo viewInfo; + viewInfo.type = VK_IMAGE_VIEW_TYPE_1D; + viewInfo.format = VK_FORMAT_R16G16B16A16_UNORM; + viewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT; + viewInfo.aspect = VK_IMAGE_ASPECT_COLOR_BIT; + viewInfo.minLevel = 0; + viewInfo.numLevels = 1; + viewInfo.minLayer = 0; + viewInfo.numLayers = 1; + + m_gammaView = m_device->createImageView(m_gammaImage, viewInfo); + } + + ctx->invalidateBuffer(m_gammaBuffer, m_gammaSlice); + ctx->copyBufferToImage(m_gammaImage, + VkImageSubresourceLayers { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }, + VkOffset3D { 0, 0, 0 }, + VkExtent3D { n, 1, 1 }, + m_gammaBuffer, 0, 0, 0); + + m_gammaSlice = DxvkBufferSliceHandle(); + } else { + m_gammaImage = nullptr; + m_gammaView = nullptr; + } + + m_gammaDirty = false; + } + + + void DxvkSwapchainBlitter::createSampler() { + DxvkSamplerCreateInfo samplerInfo; + samplerInfo.magFilter = VK_FILTER_LINEAR; + samplerInfo.minFilter = VK_FILTER_LINEAR; + samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; + samplerInfo.mipmapLodBias = 0.0f; + samplerInfo.mipmapLodMin = 0.0f; + samplerInfo.mipmapLodMax = 0.0f; + samplerInfo.useAnisotropy = VK_FALSE; + samplerInfo.maxAnisotropy = 1.0f; + samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; + samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; + samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; + samplerInfo.compareToDepth = VK_FALSE; + samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS; + samplerInfo.borderColor = VkClearColorValue(); + samplerInfo.usePixelCoord = VK_TRUE; + samplerInfo.nonSeamless = VK_FALSE; + m_samplerPresent = m_device->createSampler(samplerInfo); + + samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerInfo.usePixelCoord = VK_FALSE; + m_samplerGamma = m_device->createSampler(samplerInfo); + } + + void DxvkSwapchainBlitter::createShaders() { + SpirvCodeBuffer vsCode(dxvk_present_vert); + SpirvCodeBuffer fsCodeBlit(dxvk_present_frag_blit); + SpirvCodeBuffer fsCodeCopy(dxvk_present_frag); + SpirvCodeBuffer fsCodeResolve(dxvk_present_frag_ms); + SpirvCodeBuffer fsCodeResolveAmd(dxvk_present_frag_ms_amd); + + const std::array fsResourceSlots = {{ + { BindingIds::Image, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_IMAGE_VIEW_TYPE_2D }, + { BindingIds::Gamma, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_IMAGE_VIEW_TYPE_1D }, + }}; + + DxvkShaderCreateInfo vsInfo; + vsInfo.stage = VK_SHADER_STAGE_VERTEX_BIT; + vsInfo.outputMask = 0x1; + m_vs = new DxvkShader(vsInfo, std::move(vsCode)); + + DxvkShaderCreateInfo fsInfo; + fsInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT; + fsInfo.resourceSlotCount = fsResourceSlots.size(); + fsInfo.resourceSlots = fsResourceSlots.data(); + fsInfo.pushConstSize = sizeof(PresenterArgs); + fsInfo.inputMask = 0x1; + fsInfo.outputMask = 0x1; + m_fsBlit = new DxvkShader(fsInfo, std::move(fsCodeBlit)); + + fsInfo.inputMask = 0; + m_fsCopy = new DxvkShader(fsInfo, std::move(fsCodeCopy)); + m_fsResolve = new DxvkShader(fsInfo, m_device->extensions().amdShaderFragmentMask + ? std::move(fsCodeResolveAmd) + : std::move(fsCodeResolve)); + } + + void DxvkSwapchainBlitter::createResolveImage(const DxvkImageCreateInfo& info) { + DxvkImageCreateInfo newInfo; + newInfo.type = VK_IMAGE_TYPE_2D; + newInfo.format = info.format; + newInfo.flags = 0; + newInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT; + newInfo.extent = info.extent; + newInfo.numLayers = 1; + newInfo.mipLevels = 1; + newInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_SAMPLED_BIT; + newInfo.stages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT + | VK_PIPELINE_STAGE_TRANSFER_BIT + | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + newInfo.access = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT + | VK_ACCESS_TRANSFER_WRITE_BIT + | VK_ACCESS_SHADER_READ_BIT; + newInfo.tiling = VK_IMAGE_TILING_OPTIMAL; + newInfo.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + m_resolveImage = m_device->createImage(newInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + + DxvkImageViewCreateInfo viewInfo; + viewInfo.type = VK_IMAGE_VIEW_TYPE_2D; + viewInfo.format = info.format; + viewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT; + viewInfo.aspect = VK_IMAGE_ASPECT_COLOR_BIT; + viewInfo.minLevel = 0; + viewInfo.numLevels = 1; + viewInfo.minLayer = 0; + viewInfo.numLayers = 1; + m_resolveView = m_device->createImageView(m_resolveImage, viewInfo); + } + + + void DxvkSwapchainBlitter::destroyResolveImage() { + m_resolveImage = nullptr; + m_resolveView = nullptr; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_swapchain_blitter.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_swapchain_blitter.h new file mode 100644 index 00000000000..915bb53e10b --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_swapchain_blitter.h @@ -0,0 +1,118 @@ +#pragma once + +#include "../dxvk/dxvk_device.h" +#include "../dxvk/dxvk_context.h" + +namespace dxvk { + + /** + * \brief Gamma control point + */ + struct DxvkGammaCp { + uint16_t r, g, b, a; + }; + + /** + * \brief Swap chain blitter + * + * Provides common rendering code for blitting + * rendered images to a swap chain image. + */ + class DxvkSwapchainBlitter : public RcObject { + + public: + + DxvkSwapchainBlitter(const Rc& device); + ~DxvkSwapchainBlitter(); + + /** + * \brief Records presentation commands + * + * \param [in] ctx Context + * \param [in] dstView Swap chain image view + * \param [in] srcView Image to present + * \param [in] dstRect Destination rectangle + * \param [in] srcRect Back buffer rectangle + */ + void presentImage( + DxvkContext* ctx, + const Rc& dstView, + VkRect2D dstRect, + const Rc& srcView, + VkRect2D srcRect); + + /** + * \brief Sets gamma ramp + * + * If the number of control points is non-zero, this + * will create a texture containing a gamma ramp that + * will be used for presentation. + * \param [in] cpCount Number of control points + * \param [in] cpData Control point data + */ + void setGammaRamp( + uint32_t cpCount, + const DxvkGammaCp* cpData); + + private: + + enum BindingIds : uint32_t { + Image = 0, + Gamma = 1, + }; + + struct PresenterArgs { + VkOffset2D srcOffset; + union { + VkExtent2D srcExtent; + VkOffset2D dstOffset; + }; + }; + + Rc m_device; + + Rc m_fsCopy; + Rc m_fsBlit; + Rc m_fsResolve; + Rc m_vs; + + Rc m_gammaBuffer; + Rc m_gammaImage; + Rc m_gammaView; + uint32_t m_gammaCpCount = 0; + bool m_gammaDirty = false; + DxvkBufferSliceHandle m_gammaSlice = { }; + + Rc m_resolveImage; + Rc m_resolveView; + + Rc m_samplerPresent; + Rc m_samplerGamma; + + void draw( + DxvkContext* ctx, + const Rc& fs, + const Rc& dstView, + VkRect2D dstRect, + const Rc& srcView, + VkRect2D srcRect); + + void resolve( + DxvkContext* ctx, + const Rc& dstView, + const Rc& srcView); + + void updateGammaTexture(DxvkContext* ctx); + + void createSampler(); + + void createShaders(); + + void createResolveImage( + const DxvkImageCreateInfo& info); + + void destroyResolveImage(); + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_unbound.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_unbound.cpp new file mode 100644 index 00000000000..abb093bd503 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_unbound.cpp @@ -0,0 +1,198 @@ +#include "dxvk_device.h" + +namespace dxvk { + + DxvkUnboundResources::DxvkUnboundResources(DxvkDevice* dev) + : m_sampler (createSampler(dev)), + m_buffer (createBuffer(dev)), + m_bufferView (createBufferView(dev, m_buffer)), + m_image1D (createImage(dev, VK_IMAGE_TYPE_1D, 1)), + m_image2D (createImage(dev, VK_IMAGE_TYPE_2D, 6)), + m_image3D (createImage(dev, VK_IMAGE_TYPE_3D, 1)), + m_viewsSampled (createImageViews(dev, VK_FORMAT_R32_SFLOAT)), + m_viewsStorage (createImageViews(dev, VK_FORMAT_R32_UINT)) { + + } + + + DxvkUnboundResources::~DxvkUnboundResources() { + + } + + + void DxvkUnboundResources::clearResources(DxvkDevice* dev) { + const Rc ctx = dev->createContext(); + ctx->beginRecording(dev->createCommandList()); + + this->clearBuffer(ctx, m_buffer); + this->clearImage(ctx, m_image1D); + this->clearImage(ctx, m_image2D); + this->clearImage(ctx, m_image3D); + + dev->submitCommandList( + ctx->endRecording(), + VK_NULL_HANDLE, + VK_NULL_HANDLE); + } + + + Rc DxvkUnboundResources::createSampler(DxvkDevice* dev) { + DxvkSamplerCreateInfo info; + info.minFilter = VK_FILTER_LINEAR; + info.magFilter = VK_FILTER_LINEAR; + info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + info.mipmapLodBias = 0.0f; + info.mipmapLodMin = -256.0f; + info.mipmapLodMax = 256.0f; + info.useAnisotropy = VK_FALSE; + info.maxAnisotropy = 1.0f; + info.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + info.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + info.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + info.compareToDepth = VK_FALSE; + info.compareOp = VK_COMPARE_OP_NEVER; + info.borderColor = VkClearColorValue(); + info.usePixelCoord = VK_FALSE; + info.nonSeamless = VK_FALSE; + + return dev->createSampler(info); + } + + + Rc DxvkUnboundResources::createBuffer(DxvkDevice* dev) { + DxvkBufferCreateInfo info; + info.size = MaxUniformBufferSize; + info.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT + | VK_BUFFER_USAGE_INDEX_BUFFER_BIT + | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT + | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT + | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT + | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT + | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT; + info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT + | dev->getShaderPipelineStages(); + info.access = VK_ACCESS_UNIFORM_READ_BIT + | VK_ACCESS_SHADER_READ_BIT + | VK_ACCESS_SHADER_WRITE_BIT; + + return dev->createBuffer(info, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + } + + + Rc DxvkUnboundResources::createBufferView( + DxvkDevice* dev, + const Rc& buffer) { + DxvkBufferViewCreateInfo info; + info.format = VK_FORMAT_R32_UINT; + info.rangeOffset = 0; + info.rangeLength = buffer->info().size; + + return dev->createBufferView(buffer, info); + } + + + Rc DxvkUnboundResources::createImage( + DxvkDevice* dev, + VkImageType type, + uint32_t layers) { + DxvkImageCreateInfo info; + info.type = type; + info.format = VK_FORMAT_R32_UINT; + info.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; + info.sampleCount = VK_SAMPLE_COUNT_1_BIT; + info.extent = { 1, 1, 1 }; + info.numLayers = layers; + info.mipLevels = 1; + info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_SAMPLED_BIT + | VK_IMAGE_USAGE_STORAGE_BIT; + info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT + | dev->getShaderPipelineStages(); + info.access = VK_ACCESS_SHADER_READ_BIT; + info.layout = VK_IMAGE_LAYOUT_GENERAL; + info.tiling = VK_IMAGE_TILING_OPTIMAL; + + if (type == VK_IMAGE_TYPE_2D) + info.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; + + return dev->createImage(info, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + } + + + Rc DxvkUnboundResources::createImageView( + DxvkDevice* dev, + const Rc& image, + VkFormat format, + VkImageViewType type, + uint32_t layers) { + DxvkImageViewCreateInfo info; + info.type = type; + info.format = format; + info.usage = VK_IMAGE_USAGE_SAMPLED_BIT + | VK_IMAGE_USAGE_STORAGE_BIT; + info.aspect = VK_IMAGE_ASPECT_COLOR_BIT; + info.minLevel = 0; + info.numLevels = 1; + info.minLayer = 0; + info.numLayers = layers; + info.swizzle = VkComponentMapping { + VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO, + VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO }; + + return dev->createImageView(image, info); + } + + + DxvkUnboundResources::UnboundViews DxvkUnboundResources::createImageViews(DxvkDevice* dev, VkFormat format) { + UnboundViews result; + result.view1D = createImageView(dev, m_image1D, format, VK_IMAGE_VIEW_TYPE_1D, 1); + result.view1DArr = createImageView(dev, m_image1D, format, VK_IMAGE_VIEW_TYPE_1D_ARRAY, 1); + result.view2D = createImageView(dev, m_image2D, format, VK_IMAGE_VIEW_TYPE_2D, 1); + result.view2DArr = createImageView(dev, m_image2D, format, VK_IMAGE_VIEW_TYPE_2D_ARRAY, 1); + result.viewCube = createImageView(dev, m_image2D, format, VK_IMAGE_VIEW_TYPE_CUBE, 6); + result.viewCubeArr = createImageView(dev, m_image2D, format, VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, 6); + result.view3D = createImageView(dev, m_image3D, format, VK_IMAGE_VIEW_TYPE_3D, 1); + return result; + } + + + const DxvkImageView* DxvkUnboundResources::getImageView(VkImageViewType type, bool sampled) const { + auto views = sampled ? &m_viewsSampled : &m_viewsStorage; + + switch (type) { + case VK_IMAGE_VIEW_TYPE_1D: return views->view1D.ptr(); + case VK_IMAGE_VIEW_TYPE_1D_ARRAY: return views->view1DArr.ptr(); + // When implicit samplers are unbound -- we assume 2D in the shader. + case VK_IMAGE_VIEW_TYPE_MAX_ENUM: + case VK_IMAGE_VIEW_TYPE_2D: return views->view2D.ptr(); + case VK_IMAGE_VIEW_TYPE_2D_ARRAY: return views->view2DArr.ptr(); + case VK_IMAGE_VIEW_TYPE_CUBE: return views->viewCube.ptr(); + case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: return views->viewCubeArr.ptr(); + case VK_IMAGE_VIEW_TYPE_3D: return views->view3D.ptr(); + default: return nullptr; + } + } + + + void DxvkUnboundResources::clearBuffer( + const Rc& ctx, + const Rc& buffer) { + ctx->initBuffer(buffer); + } + + + void DxvkUnboundResources::clearImage( + const Rc& ctx, + const Rc& image) { + ctx->initImage(image, + VkImageSubresourceRange { + VK_IMAGE_ASPECT_COLOR_BIT, + 0, image->info().mipLevels, + 0, image->info().numLayers }, + VK_IMAGE_LAYOUT_UNDEFINED); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_unbound.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_unbound.h new file mode 100644 index 00000000000..d9ae01e0ca0 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_unbound.h @@ -0,0 +1,191 @@ +#pragma once + +#include "dxvk_buffer.h" +#include "dxvk_image.h" +#include "dxvk_sampler.h" + +namespace dxvk { + + class DxvkContext; + + /** + * \brief Unbound resources + * + * Creates dummy resources that will be used + * for descriptor sets when the client API did + * not bind a compatible resource to a slot. + */ + class DxvkUnboundResources { + + public: + + DxvkUnboundResources(DxvkDevice* dev); + ~DxvkUnboundResources(); + + /** + * \brief Dummy buffer handle + * + * Returns a handle to a buffer filled + * with zeroes. Use for unbound vertex + * and index buffers. + * \returns Dummy buffer handle + */ + VkBuffer bufferHandle() const { + return m_buffer->getSliceHandle().handle; + } + + /** + * \brief Dummy buffer descriptor + * + * Points to a small buffer filled with zeroes. + * Do not write to this buffer, and do not use + * it if out-of-bounds read access is possible. + * \returns Dummy buffer descriptor + */ + VkDescriptorBufferInfo bufferDescriptor() const { + auto slice = m_buffer->getSliceHandle(); + + VkDescriptorBufferInfo result; + result.buffer = slice.handle; + result.offset = slice.offset; + result.range = slice.length; + return result; + } + + /** + * \brief Dummy buffer view + * + * Returns an \c R32_UINT view into the + * dummy buffer, which will contain one + * element with undefined value. + * \returns Dummy buffer view + */ + VkBufferView bufferViewDescriptor() const { + return m_bufferView->handle(); + } + + /** + * \brief Dummy sampler descriptor + * + * Points to a sampler which was created with + * reasonable default values. Client APIs may + * still require different behaviour. + * \returns Dummy sampler descriptor + */ + VkDescriptorImageInfo samplerDescriptor() const { + VkDescriptorImageInfo result; + result.sampler = m_sampler->handle(); + result.imageView = VK_NULL_HANDLE; + result.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED; + return result; + } + + /** + * \brief Dummy combined image sampler descriptor + * + * Contains both an image view and a sampler + * descriptor for the given image view type. + * \param [in] type Image view type + * \returns Dummy image view descriptor + */ + VkDescriptorImageInfo imageSamplerDescriptor(VkImageViewType type) const { + auto view = getImageView(type, true); + + VkDescriptorImageInfo result; + result.sampler = m_sampler->handle(); + result.imageView = view->handle(); + result.imageLayout = view->imageInfo().layout; + return result; + } + + /** + * \brief Dummy image view descriptor + * + * Points to an image view which, instead of + * reading image data, will return zeroes for + * all components unconditionally. + * \param [in] type Image view type + * \param [in] sampled Format selector + * \returns Dummy image view descriptor + */ + VkDescriptorImageInfo imageViewDescriptor(VkImageViewType type, bool sampled) const { + auto view = getImageView(type, sampled); + + VkDescriptorImageInfo result; + result.sampler = VK_NULL_HANDLE; + result.imageView = view->handle(); + result.imageLayout = view->imageInfo().layout; + return result; + } + + /** + * \brief Clears the resources + * + * Initializes all images and buffers to zero. + * \param [in] dev The DXVK device handle + */ + void clearResources(DxvkDevice* dev); + + private: + + struct UnboundViews { + Rc view1D; + Rc view1DArr; + Rc view2D; + Rc view2DArr; + Rc viewCube; + Rc viewCubeArr; + Rc view3D; + }; + + Rc m_sampler; + + Rc m_buffer; + Rc m_bufferView; + + Rc m_image1D; + Rc m_image2D; + Rc m_image3D; + + UnboundViews m_viewsSampled; + UnboundViews m_viewsStorage; + + Rc createSampler(DxvkDevice* dev); + + Rc createBuffer(DxvkDevice* dev); + + Rc createBufferView( + DxvkDevice* dev, + const Rc& buffer); + + Rc createImage( + DxvkDevice* dev, + VkImageType type, + uint32_t layers); + + Rc createImageView( + DxvkDevice* dev, + const Rc& image, + VkFormat format, + VkImageViewType type, + uint32_t layers); + + UnboundViews createImageViews( + DxvkDevice* dev, + VkFormat format); + + const DxvkImageView* getImageView( + VkImageViewType type, + bool sampled) const; + + void clearBuffer( + const Rc& ctx, + const Rc& buffer); + + void clearImage( + const Rc& ctx, + const Rc& image); + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_util.cpp b/utils/dxvk-1.10.3/src/dxvk/dxvk_util.cpp new file mode 100644 index 00000000000..5086869672e --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_util.cpp @@ -0,0 +1,327 @@ +#include + +#include "dxvk_format.h" +#include "dxvk_util.h" + +namespace dxvk::util { + + uint32_t computeMipLevelCount(VkExtent3D imageSize) { + uint32_t maxDim = std::max(imageSize.width, imageSize.height); + maxDim = std::max(imageSize.depth, maxDim); + uint32_t mipCnt = 0; + + while (maxDim > 0) { + mipCnt += 1; + maxDim /= 2; + } + + return mipCnt; + } + + + void packImageData( + void* dstBytes, + const void* srcBytes, + VkExtent3D blockCount, + VkDeviceSize blockSize, + VkDeviceSize pitchPerRow, + VkDeviceSize pitchPerLayer) { + auto dstData = reinterpret_cast< char*>(dstBytes); + auto srcData = reinterpret_cast(srcBytes); + + const VkDeviceSize bytesPerRow = blockCount.width * blockSize; + const VkDeviceSize bytesPerLayer = blockCount.height * bytesPerRow; + const VkDeviceSize bytesTotal = blockCount.depth * bytesPerLayer; + + const bool directCopy = ((bytesPerRow == pitchPerRow ) || (blockCount.height == 1)) + && ((bytesPerLayer == pitchPerLayer) || (blockCount.depth == 1)); + + if (directCopy) { + std::memcpy(dstData, srcData, bytesTotal); + } else { + for (uint32_t i = 0; i < blockCount.depth; i++) { + for (uint32_t j = 0; j < blockCount.height; j++) { + std::memcpy( + dstData + j * bytesPerRow, + srcData + j * pitchPerRow, + bytesPerRow); + } + + srcData += pitchPerLayer; + dstData += bytesPerLayer; + } + } + } + + + void packImageData( + void* dstBytes, + const void* srcBytes, + VkDeviceSize srcRowPitch, + VkDeviceSize srcSlicePitch, + VkDeviceSize dstRowPitchIn, + VkDeviceSize dstSlicePitchIn, + VkImageType imageType, + VkExtent3D imageExtent, + uint32_t imageLayers, + const DxvkFormatInfo* formatInfo, + VkImageAspectFlags aspectMask) { + for (uint32_t i = 0; i < imageLayers; i++) { + auto dstData = reinterpret_cast< char*>(dstBytes); + auto srcData = reinterpret_cast(srcBytes); + + for (auto aspects = aspectMask; aspects; ) { + auto aspect = vk::getNextAspect(aspects); + auto extent = imageExtent; + auto elementSize = formatInfo->elementSize; + + if (formatInfo->flags.test(DxvkFormatFlag::MultiPlane)) { + auto plane = &formatInfo->planes[vk::getPlaneIndex(aspect)]; + extent.width /= plane->blockSize.width; + extent.height /= plane->blockSize.height; + elementSize = plane->elementSize; + } + + auto blockCount = computeBlockCount(extent, formatInfo->blockSize); + + VkDeviceSize bytesPerRow = blockCount.width * elementSize; + VkDeviceSize bytesPerSlice = blockCount.height * bytesPerRow; + VkDeviceSize bytesTotal = blockCount.depth * bytesPerSlice; + + VkDeviceSize dstRowPitch = dstRowPitchIn ? dstRowPitchIn : bytesPerRow; + VkDeviceSize dstSlicePitch = dstSlicePitchIn ? dstSlicePitchIn : bytesPerSlice; + + const bool directCopy = ((bytesPerRow == srcRowPitch && bytesPerRow == dstRowPitch ) || (blockCount.height == 1)) + && ((bytesPerSlice == srcSlicePitch && bytesPerSlice == dstSlicePitch) || (blockCount.depth == 1)); + + if (directCopy) { + std::memcpy(dstData, srcData, bytesTotal); + + switch (imageType) { + case VK_IMAGE_TYPE_1D: + srcData += srcRowPitch; + dstData += dstRowPitch; + break; + case VK_IMAGE_TYPE_2D: + srcData += blockCount.height * srcRowPitch; + dstData += blockCount.height * dstRowPitch; + break; + case VK_IMAGE_TYPE_3D: + srcData += blockCount.depth * srcSlicePitch; + dstData += blockCount.depth * dstSlicePitch; + break; + default: ; + } + } else { + for (uint32_t i = 0; i < blockCount.depth; i++) { + for (uint32_t j = 0; j < blockCount.height; j++) { + std::memcpy( + dstData + j * dstRowPitch, + srcData + j * srcRowPitch, + bytesPerRow); + } + + switch (imageType) { + case VK_IMAGE_TYPE_1D: + srcData += srcRowPitch; + dstData += dstRowPitch; + break; + case VK_IMAGE_TYPE_2D: + srcData += blockCount.height * srcRowPitch; + dstData += blockCount.height * dstRowPitch; + break; + case VK_IMAGE_TYPE_3D: + srcData += srcSlicePitch; + dstData += dstSlicePitch; + break; + default: ; + } + } + } + } + } + } + + + VkDeviceSize computeImageDataSize(VkFormat format, VkExtent3D extent) { + const DxvkFormatInfo* formatInfo = imageFormatInfo(format); + + VkDeviceSize size = 0; + + for (auto aspects = formatInfo->aspectMask; aspects; ) { + auto aspect = vk::getNextAspect(aspects); + auto elementSize = formatInfo->elementSize; + auto planeExtent = extent; + + if (formatInfo->flags.test(DxvkFormatFlag::MultiPlane)) { + auto plane = &formatInfo->planes[vk::getPlaneIndex(aspect)]; + planeExtent.width /= plane->blockSize.width; + planeExtent.height /= plane->blockSize.height; + elementSize = plane->elementSize; + } + + size += elementSize * flattenImageExtent(computeBlockCount(planeExtent, formatInfo->blockSize)); + } + + return size; + } + + + static VkColorComponentFlags remapComponentFlag( + VkColorComponentFlags mask, + VkComponentSwizzle swizzle, + VkColorComponentFlagBits identity) { + VkColorComponentFlags bit; + + switch (swizzle) { + case VK_COMPONENT_SWIZZLE_IDENTITY: bit = identity; break; + case VK_COMPONENT_SWIZZLE_R: bit = VK_COLOR_COMPONENT_R_BIT; break; + case VK_COMPONENT_SWIZZLE_G: bit = VK_COLOR_COMPONENT_G_BIT; break; + case VK_COMPONENT_SWIZZLE_B: bit = VK_COLOR_COMPONENT_B_BIT; break; + case VK_COMPONENT_SWIZZLE_A: bit = VK_COLOR_COMPONENT_A_BIT; break; + default: bit = 0; /* SWIZZLE_ZERO, SWIZZLE_ONE */ + } + + return (mask & bit) ? identity : 0; + } + + + VkColorComponentFlags remapComponentMask( + VkColorComponentFlags mask, + VkComponentMapping mapping) { + VkColorComponentFlags result = 0; + result |= remapComponentFlag(mask, mapping.r, VK_COLOR_COMPONENT_R_BIT); + result |= remapComponentFlag(mask, mapping.g, VK_COLOR_COMPONENT_G_BIT); + result |= remapComponentFlag(mask, mapping.b, VK_COLOR_COMPONENT_B_BIT); + result |= remapComponentFlag(mask, mapping.a, VK_COLOR_COMPONENT_A_BIT); + return result; + } + + + static VkComponentSwizzle findComponentSwizzle( + VkComponentSwizzle swizzle, + VkComponentSwizzle identity, + VkComponentMapping mapping) { + if (identity == VK_COMPONENT_SWIZZLE_IDENTITY) + return VK_COMPONENT_SWIZZLE_IDENTITY; + + if (mapping.r == swizzle) + return VK_COMPONENT_SWIZZLE_R; + if (mapping.g == swizzle) + return VK_COMPONENT_SWIZZLE_G; + if (mapping.b == swizzle) + return VK_COMPONENT_SWIZZLE_B; + if (mapping.a == swizzle) + return VK_COMPONENT_SWIZZLE_A; + + return VK_COMPONENT_SWIZZLE_ZERO; + } + + + VkComponentMapping invertComponentMapping(VkComponentMapping mapping) { + VkComponentMapping result; + result.r = findComponentSwizzle(VK_COMPONENT_SWIZZLE_R, mapping.r, mapping); + result.g = findComponentSwizzle(VK_COMPONENT_SWIZZLE_G, mapping.g, mapping); + result.b = findComponentSwizzle(VK_COMPONENT_SWIZZLE_B, mapping.b, mapping); + result.a = findComponentSwizzle(VK_COMPONENT_SWIZZLE_A, mapping.a, mapping); + return result; + } + + + static VkComponentMapping normalizeComponentMapping( + VkComponentMapping mapping) { + mapping.r = mapping.r == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_R : mapping.r; + mapping.g = mapping.g == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_G : mapping.g; + mapping.b = mapping.b == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_B : mapping.b; + mapping.a = mapping.a == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_A : mapping.a; + return mapping; + } + + + static VkComponentSwizzle resolveComponentSwizzle( + VkComponentSwizzle swizzle, + VkComponentMapping dstMapping, + VkComponentMapping srcMapping) { + VkComponentSwizzle dstSwizzle = VK_COMPONENT_SWIZZLE_IDENTITY; + if (dstMapping.r == swizzle) dstSwizzle = VK_COMPONENT_SWIZZLE_R; + if (dstMapping.g == swizzle) dstSwizzle = VK_COMPONENT_SWIZZLE_G; + if (dstMapping.b == swizzle) dstSwizzle = VK_COMPONENT_SWIZZLE_B; + if (dstMapping.a == swizzle) dstSwizzle = VK_COMPONENT_SWIZZLE_A; + + switch (dstSwizzle) { + case VK_COMPONENT_SWIZZLE_R: return srcMapping.r; + case VK_COMPONENT_SWIZZLE_G: return srcMapping.g; + case VK_COMPONENT_SWIZZLE_B: return srcMapping.b; + case VK_COMPONENT_SWIZZLE_A: return srcMapping.a; + default: return VK_COMPONENT_SWIZZLE_IDENTITY; + } + } + + + VkComponentMapping resolveSrcComponentMapping( + VkComponentMapping dstMapping, + VkComponentMapping srcMapping) { + dstMapping = normalizeComponentMapping(dstMapping); + + VkComponentMapping result; + result.r = resolveComponentSwizzle(VK_COMPONENT_SWIZZLE_R, dstMapping, srcMapping); + result.g = resolveComponentSwizzle(VK_COMPONENT_SWIZZLE_G, dstMapping, srcMapping); + result.b = resolveComponentSwizzle(VK_COMPONENT_SWIZZLE_B, dstMapping, srcMapping); + result.a = resolveComponentSwizzle(VK_COMPONENT_SWIZZLE_A, dstMapping, srcMapping); + return result; + } + + + bool isIdentityMapping( + VkComponentMapping mapping) { + return (mapping.r == VK_COMPONENT_SWIZZLE_R || mapping.r == VK_COMPONENT_SWIZZLE_IDENTITY) + && (mapping.g == VK_COMPONENT_SWIZZLE_G || mapping.g == VK_COMPONENT_SWIZZLE_IDENTITY) + && (mapping.b == VK_COMPONENT_SWIZZLE_B || mapping.b == VK_COMPONENT_SWIZZLE_IDENTITY) + && (mapping.a == VK_COMPONENT_SWIZZLE_A || mapping.a == VK_COMPONENT_SWIZZLE_IDENTITY); + } + + + uint32_t getComponentIndex( + VkComponentSwizzle component, + uint32_t identity) { + switch (component) { + case VK_COMPONENT_SWIZZLE_R: return 0; + case VK_COMPONENT_SWIZZLE_G: return 1; + case VK_COMPONENT_SWIZZLE_B: return 2; + case VK_COMPONENT_SWIZZLE_A: return 3; + default: return identity; /* identity, zero, one */ + } + } + + + VkClearColorValue swizzleClearColor( + VkClearColorValue color, + VkComponentMapping mapping) { + VkClearColorValue result; + auto swizzles = &mapping.r; + + for (uint32_t i = 0; i < 4; i++) { + uint32_t index = getComponentIndex(swizzles[i], i); + result.uint32[i] = color.uint32[index]; + } + + return result; + } + + + bool isBlendConstantBlendFactor(VkBlendFactor factor) { + return factor == VK_BLEND_FACTOR_CONSTANT_COLOR + || factor == VK_BLEND_FACTOR_CONSTANT_ALPHA + || factor == VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR + || factor == VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA; + } + + + bool isDualSourceBlendFactor(VkBlendFactor factor) { + return factor == VK_BLEND_FACTOR_SRC1_COLOR + || factor == VK_BLEND_FACTOR_SRC1_ALPHA + || factor == VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR + || factor == VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA; + } + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/dxvk_util.h b/utils/dxvk-1.10.3/src/dxvk/dxvk_util.h new file mode 100644 index 00000000000..94fd06ddf11 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/dxvk_util.h @@ -0,0 +1,355 @@ +#pragma once + +#include "dxvk_include.h" + +namespace dxvk::util { + + /** + * \brief Gets pipeline stage flags for shader stages + * + * \param [in] shaderStages Shader stage flags + * \returns Corresponding pipeline stage flags + */ + inline VkPipelineStageFlags pipelineStages( + VkShaderStageFlags shaderStages) { + return (shaderStages & VK_SHADER_STAGE_ALL_GRAPHICS) << 3 + | (shaderStages & VK_SHADER_STAGE_COMPUTE_BIT) << 6; + } + + /** + * \brief Computes number of mip levels for an image + * + * \param [in] imageSize Size of the image + * \returns Number of mipmap layers + */ + uint32_t computeMipLevelCount(VkExtent3D imageSize); + + /** + * \brief Writes tightly packed image data to a buffer + * + * \param [in] dstBytes Destination buffer pointer + * \param [in] srcBytes Pointer to source data + * \param [in] blockCount Number of blocks to copy + * \param [in] blockSize Number of bytes per block + * \param [in] pitchPerRow Number of bytes between rows + * \param [in] pitchPerLayer Number of bytes between layers + */ + void packImageData( + void* dstBytes, + const void* srcBytes, + VkExtent3D blockCount, + VkDeviceSize blockSize, + VkDeviceSize pitchPerRow, + VkDeviceSize pitchPerLayer); + + /** + * \brief Repacks image data to a buffer + * + * Note that passing destination pitches of 0 means that the data is + * tightly packed, while a source pitch of 0 will not show this behaviour + * in order to match client API behaviour for initialization. + * \param [in] dstBytes Destination buffer pointer + * \param [in] srcBytes Pointer to source data + * \param [in] srcRowPitch Number of bytes between rows to read + * \param [in] srcSlicePitch Number of bytes between layers to read + * \param [in] dstRowPitch Number of bytes between rows to write + * \param [in] dstSlicePitch Number of bytes between layers to write + * \param [in] imageType Image type (2D, 3D etc) + * \param [in] imageExtent Image extent, in pixels + * \param [in] imageLayers Image layer count + * \param [in] formatInfo Image format info + * \param [in] aspectMask Image aspects to pack + */ + void packImageData( + void* dstBytes, + const void* srcBytes, + VkDeviceSize srcRowPitch, + VkDeviceSize srcSlicePitch, + VkDeviceSize dstRowPitchIn, + VkDeviceSize dstSlicePitchIn, + VkImageType imageType, + VkExtent3D imageExtent, + uint32_t imageLayers, + const DxvkFormatInfo* formatInfo, + VkImageAspectFlags aspectMask); + + /** + * \brief Computes minimum extent + * + * \param [in] a First value + * \param [in] b Second value + * \returns Component-wise \c min + */ + inline VkExtent3D minExtent3D(VkExtent3D a, VkExtent3D b) { + return VkExtent3D { + std::min(a.width, b.width), + std::min(a.height, b.height), + std::min(a.depth, b.depth) }; + } + + /** + * \brief Checks whether an offset is block-aligned + * + * An offset is considered block-aligned if it is + * a multiple of the block size. Only non-negative + * offset values are valid. + * \param [in] offset The offset to check + * \param [in] blockSize Block size + * \returns \c true if \c offset is aligned + */ + inline bool isBlockAligned(VkOffset3D offset, VkExtent3D blockSize) { + return (offset.x % blockSize.width == 0) + && (offset.y % blockSize.height == 0) + && (offset.z % blockSize.depth == 0); + } + + /** + * \brief Checks whether an offset and extent are block-aligned + * + * A block-aligned extent can be used for image copy + * operations that involve block-compressed images. + * \param [in] offset The base offset + * \param [in] extent The extent to check + * \param [in] blockSize Compressed block size + * \param [in] imageSize Image size + * \returns \c true if all components of \c extent + * are aligned or touch the image border. + */ + inline bool isBlockAligned(VkOffset3D offset, VkExtent3D extent, VkExtent3D blockSize, VkExtent3D imageSize) { + return ((extent.width % blockSize.width == 0) || (uint32_t(offset.x + extent.width) == imageSize.width)) + && ((extent.height % blockSize.height == 0) || (uint32_t(offset.y + extent.height) == imageSize.height)) + && ((extent.depth % blockSize.depth == 0) || (uint32_t(offset.z + extent.depth) == imageSize.depth)) + && isBlockAligned(offset, blockSize); + } + + /** + * \brief Computes mip level extent + * + * \param [in] size Base mip level extent + * \param [in] level mip level to compute + * \returns Extent of the given mip level + */ + inline VkExtent3D computeMipLevelExtent(VkExtent3D size, uint32_t level) { + size.width = std::max(1u, size.width >> level); + size.height = std::max(1u, size.height >> level); + size.depth = std::max(1u, size.depth >> level); + return size; + } + + /** + * \brief Computes offset in a given mip level + * + * \param [in] size Base mip level offset + * \param [in] level mip level to compute + * \returns Offset on the given mip level + */ + inline VkOffset3D computeMipLevelOffset(VkOffset3D offset, uint32_t level) { + offset.x = offset.x >> level; + offset.y = offset.y >> level; + offset.z = offset.z >> level; + return offset; + } + + /** + * \brief Computes mip level extent + * + * This function variant takes into account planar formats. + * \param [in] size Base mip level extent + * \param [in] level Mip level to compute + * \param [in] format Image format + * \param [in] aspect Image aspect to consider + * \returns Extent of the given mip level + */ + inline VkExtent3D computeMipLevelExtent(VkExtent3D size, uint32_t level, VkFormat format, VkImageAspectFlags aspect) { + if (unlikely(!(aspect & (VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)))) { + auto plane = &imageFormatInfo(format)->planes[vk::getPlaneIndex(aspect)]; + size.width /= plane->blockSize.width; + size.height /= plane->blockSize.height; + } + + size.width = std::max(1u, size.width >> level); + size.height = std::max(1u, size.height >> level); + size.depth = std::max(1u, size.depth >> level); + return size; + } + + /** + * \brief Computes block offset for compressed images + * + * Convenience function to compute the block position + * within a compressed image based on the block size. + * \param [in] offset The offset + * \param [in] blockSize Size of a pixel block + * \returns The block offset + */ + inline VkOffset3D computeBlockOffset(VkOffset3D offset, VkExtent3D blockSize) { + return VkOffset3D { + offset.x / int32_t(blockSize.width), + offset.y / int32_t(blockSize.height), + offset.z / int32_t(blockSize.depth) }; + } + + /** + * \brief Computes block count for compressed images + * + * Convenience function to compute the size, in + * blocks, of compressed images subresources. + * \param [in] extent The image size + * \param [in] blockSize Size of a pixel block + * \returns Number of blocks in the image + */ + inline VkExtent3D computeBlockCount(VkExtent3D extent, VkExtent3D blockSize) { + return VkExtent3D { + (extent.width + blockSize.width - 1) / blockSize.width, + (extent.height + blockSize.height - 1) / blockSize.height, + (extent.depth + blockSize.depth - 1) / blockSize.depth }; + } + + /** + * \brief Computes block count for compressed images + * + * Given an aligned offset, this computes + * Convenience function to compute the size, in + * blocks, of compressed images subresources. + * \param [in] extent The image size + * \param [in] blockSize Size of a pixel block + * \returns Number of blocks in the image + */ + inline VkExtent3D computeMaxBlockCount(VkOffset3D offset, VkExtent3D extent, VkExtent3D blockSize) { + return VkExtent3D { + (extent.width + blockSize.width - offset.x - 1) / blockSize.width, + (extent.height + blockSize.height - offset.y - 1) / blockSize.height, + (extent.depth + blockSize.depth - offset.z - 1) / blockSize.depth }; + } + + /** + * \brief Snaps block-aligned image extent to image edges + * + * Fixes up an image extent that is aligned to a compressed + * block so that it no longer exceeds the given image size. + * \param [in] offset Aligned pixel offset + * \param [in] extent Extent to clamp + * \param [in] imageExtent Image size + * \returns Number of blocks in the image + */ + inline VkExtent3D snapExtent3D(VkOffset3D offset, VkExtent3D extent, VkExtent3D imageExtent) { + return VkExtent3D { + std::min(extent.width, imageExtent.width - uint32_t(offset.x)), + std::min(extent.height, imageExtent.height - uint32_t(offset.y)), + std::min(extent.depth, imageExtent.depth - uint32_t(offset.z)) }; + } + + /** + * \brief Computes block extent for compressed images + * + * \param [in] blockCount The number of blocks + * \param [in] blockSize Size of a pixel block + * \returns Extent of the given blocks + */ + inline VkExtent3D computeBlockExtent(VkExtent3D blockCount, VkExtent3D blockSize) { + return VkExtent3D { + blockCount.width * blockSize.width, + blockCount.height * blockSize.height, + blockCount.depth * blockSize.depth }; + } + + /** + * \brief Computes number of pixels or blocks of an image + * + * Basically returns the product of width, height and depth. + * \param [in] extent Image extent, in pixels or blocks + * \returns Flattened number of pixels or blocks + */ + inline uint32_t flattenImageExtent(VkExtent3D extent) { + return extent.width * extent.height * extent.depth; + } + + /** + * \brief Checks whether the depth aspect is read-only in a layout + * + * \param [in] layout Image layout. Must be a valid depth-stencil attachment laoyut. + * \returns \c true if the depth aspect for images in this layout is read-only. + */ + inline bool isDepthReadOnlyLayout(VkImageLayout layout) { + return layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL + || layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL; + } + + /** + * \brief Computes image data size, in bytes + * + * Convenience method that can be used to compute the number + * of bytes required to store image data in a given format. + * \param [in] format The image format + * \param [in] extent Image size, in pixels + * \returns Data size, in bytes + */ + VkDeviceSize computeImageDataSize(VkFormat format, VkExtent3D extent); + + /** + * \brief Applies a component mapping to a component mask + * + * For each component, the component specified in the mapping + * is used to look up the flag of the original component mask. + * If the component mapping is zero or one, the corresponding + * mask bit will be set to zero. + * \param [in] mask The original component mask + * \param [in] mapping Component mapping to apply + * \returns Remapped component mask + */ + VkColorComponentFlags remapComponentMask( + VkColorComponentFlags mask, + VkComponentMapping mapping); + + /** + * \brief Inverts a component mapping + * + * Transforms a component mapping so that components can + * be mapped back to their original location. Requires + * that each component is used only once. + * + * For example. when given a mapping of (0,0,0,R), + * this function will return the mapping (A,0,0,0). + * \returns Inverted component mapping + */ + VkComponentMapping invertComponentMapping( + VkComponentMapping mapping); + + /** + * \brief Resolves source component mapping + * + * Returns the source component mapping after rearranging + * the destination mapping to be the identity mapping. + * \param [in] dstMapping Destination mapping + * \param [in] srcMapping Source mapping + * \returns Adjusted src component mapping + */ + VkComponentMapping resolveSrcComponentMapping( + VkComponentMapping dstMapping, + VkComponentMapping srcMapping); + + bool isIdentityMapping( + VkComponentMapping mapping); + + /** + * \brief Computes component index for a component swizzle + * + * \param [in] component The component swizzle + * \param [in] identity Value for SWIZZLE_IDENTITY + * \returns Component index + */ + uint32_t getComponentIndex( + VkComponentSwizzle component, + uint32_t identity); + + VkClearColorValue swizzleClearColor( + VkClearColorValue color, + VkComponentMapping mapping); + + bool isBlendConstantBlendFactor( + VkBlendFactor factor); + + bool isDualSourceBlendFactor( + VkBlendFactor factor); + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/hud/dxvk_hud.cpp b/utils/dxvk-1.10.3/src/dxvk/hud/dxvk_hud.cpp new file mode 100644 index 00000000000..003c19156b3 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/hud/dxvk_hud.cpp @@ -0,0 +1,113 @@ +#include + +#include "dxvk_hud.h" + +namespace dxvk::hud { + + Hud::Hud( + const Rc& device) + : m_device (device), + m_renderer (device), + m_hudItems (device), + m_scale (m_hudItems.getOption("scale", 1.0f)) { + // Sanitize scaling factor + if (m_scale < 0.01f) + m_scale = 1.0f; + + // Set up constant state + m_rsState.polygonMode = VK_POLYGON_MODE_FILL; + m_rsState.cullMode = VK_CULL_MODE_BACK_BIT; + m_rsState.frontFace = VK_FRONT_FACE_CLOCKWISE; + m_rsState.depthClipEnable = VK_FALSE; + m_rsState.depthBiasEnable = VK_FALSE; + m_rsState.conservativeMode = VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT; + m_rsState.sampleCount = VK_SAMPLE_COUNT_1_BIT; + + m_blendMode.enableBlending = VK_TRUE; + m_blendMode.colorSrcFactor = VK_BLEND_FACTOR_ONE; + m_blendMode.colorDstFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + m_blendMode.colorBlendOp = VK_BLEND_OP_ADD; + m_blendMode.alphaSrcFactor = VK_BLEND_FACTOR_ONE; + m_blendMode.alphaDstFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + m_blendMode.alphaBlendOp = VK_BLEND_OP_ADD; + m_blendMode.writeMask = VK_COLOR_COMPONENT_R_BIT + | VK_COLOR_COMPONENT_G_BIT + | VK_COLOR_COMPONENT_B_BIT + | VK_COLOR_COMPONENT_A_BIT; + + addItem("version", -1); + addItem("devinfo", -1, m_device); + addItem("fps", -1); + addItem("frametimes", -1); + addItem("submissions", -1, device); + addItem("drawcalls", -1, device); + addItem("pipelines", -1, device); + addItem("memory", -1, device); + addItem("cs", -1, device); + addItem("gpuload", -1, device); + addItem("compiler", -1, device); + } + + + Hud::~Hud() { + + } + + + void Hud::update() { + m_hudItems.update(); + } + + + void Hud::render( + const Rc& ctx, + VkSurfaceFormatKHR surfaceFormat, + VkExtent2D surfaceSize) { + this->setupRendererState(ctx, surfaceFormat, surfaceSize); + this->renderHudElements(ctx); + this->resetRendererState(ctx); + } + + + Rc Hud::createHud(const Rc& device) { + return new Hud(device); + } + + + void Hud::setupRendererState( + const Rc& ctx, + VkSurfaceFormatKHR surfaceFormat, + VkExtent2D surfaceSize) { + bool isSrgb = imageFormatInfo(surfaceFormat.format)->flags.test(DxvkFormatFlag::ColorSpaceSrgb); + + VkViewport viewport; + viewport.x = 0.0f; + viewport.y = 0.0f; + viewport.width = float(surfaceSize.width); + viewport.height = float(surfaceSize.height); + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + VkRect2D scissor; + scissor.offset = { 0, 0 }; + scissor.extent = surfaceSize; + + ctx->setViewports(1, &viewport, &scissor); + ctx->setRasterizerState(m_rsState); + ctx->setBlendMode(0, m_blendMode); + + ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, 0, isSrgb); + m_renderer.beginFrame(ctx, surfaceSize, m_scale); + } + + + void Hud::resetRendererState(const Rc& ctx) { + ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, 0, 0); + } + + + void Hud::renderHudElements(const Rc& ctx) { + m_hudItems.render(m_renderer); + } + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/hud/dxvk_hud.h b/utils/dxvk-1.10.3/src/dxvk/hud/dxvk_hud.h new file mode 100644 index 00000000000..d6217b8c0e5 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/hud/dxvk_hud.h @@ -0,0 +1,101 @@ +#pragma once + +#include "../dxvk_device.h" + +#include "dxvk_hud_item.h" +#include "dxvk_hud_renderer.h" + +namespace dxvk::hud { + + /** + * \brief HUD uniform data + * Shader data for the HUD. + */ + struct HudUniformData { + VkExtent2D surfaceSize; + }; + + /** + * \brief DXVK HUD + * + * Can be used by the presentation backend to + * display performance and driver information. + */ + class Hud : public RcObject { + + public: + + Hud(const Rc& device); + + ~Hud(); + + /** + * \brief Update HUD + * + * Updates the data to display. + * Should be called once per frame. + */ + void update(); + + /** + * \brief Render HUD + * + * Renders the HUD to the given context. + * \param [in] ctx Device context + * \param [in] surfaceSize Image size, in pixels + */ + void render( + const Rc& ctx, + VkSurfaceFormatKHR surfaceFormat, + VkExtent2D surfaceSize); + + /** + * \brief Adds a HUD item if enabled + * + * \tparam T The HUD item type + * \param [in] name HUD item name + * \param [in] args Constructor arguments + */ + template + void addItem(const char* name, int32_t at, Args... args) { + m_hudItems.add(name, at, std::forward(args)...); + } + + /** + * \brief Creates the HUD + * + * Creates and initializes the HUD if the + * \c DXVK_HUD environment variable is set. + * \param [in] device The DXVK device + * \returns HUD object, if it was created. + */ + static Rc createHud( + const Rc& device); + + private: + + const Rc m_device; + + DxvkRasterizerState m_rsState; + DxvkBlendMode m_blendMode; + + HudUniformData m_uniformData; + HudRenderer m_renderer; + HudItemSet m_hudItems; + + float m_scale; + + void setupRendererState( + const Rc& ctx, + VkSurfaceFormatKHR surfaceFormat, + VkExtent2D surfaceSize); + + void resetRendererState( + const Rc& ctx); + + void renderHudElements( + const Rc& ctx); + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/hud/dxvk_hud_font.cpp b/utils/dxvk-1.10.3/src/dxvk/hud/dxvk_hud_font.cpp new file mode 100644 index 00000000000..ea7d4abb969 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/hud/dxvk_hud_font.cpp @@ -0,0 +1,1872 @@ +#include "dxvk_hud_font.h" + +namespace dxvk::hud { + + // Data structures and character map generated with: + // https://evanw.github.io/font-texture-generator/ + // + // Font texture and metadata generated from: + // 'Source Code Pro' by Adobe Systems Inc. + // SIL Open Font License Version 1.1 + // + // See: https://github.com/adobe-fonts/source-code-pro + const HudGlyph g_hudFontGlyphs[] = { + {' ', 488, 144, 12, 12, 6, 6}, + {'!', 309, 44, 19, 34, 0, 27}, + {'"', 294, 144, 26, 24, 3, 28}, + {'#', 27, 111, 27, 33, 4, 27}, + {'$', 262, 0, 27, 39, 4, 30}, + {'%', 450, 44, 30, 33, 5, 27}, + {'&', 0, 44, 30, 34, 5, 27}, + {'\'', 320, 144, 18, 24, -1, 28}, + {'(', 41, 0, 22, 41, 0, 29}, + {')', 63, 0, 21, 41, 2, 29}, + {'*', 221, 144, 27, 27, 4, 24}, + {'+', 194, 144, 27, 27, 4, 24}, + {',', 248, 144, 20, 26, 0, 13}, + {'-', 461, 144, 27, 15, 4, 18}, + {'.', 365, 144, 20, 20, 4, 13}, + {'/', 111, 0, 27, 40, 4, 29}, + {'0', 88, 78, 28, 33, 4, 27}, + {'1', 244, 111, 27, 32, 3, 26}, + {'2', 396, 78, 28, 33, 4, 27}, + {'3', 424, 78, 28, 33, 5, 27}, + {'4', 187, 111, 29, 32, 5, 26}, + {'5', 284, 78, 28, 33, 4, 26}, + {'6', 116, 78, 28, 33, 4, 27}, + {'7', 216, 111, 28, 32, 4, 26}, + {'8', 172, 78, 28, 33, 4, 27}, + {'9', 368, 78, 28, 33, 4, 27}, + {':', 320, 111, 20, 30, 0, 23}, + {';', 342, 0, 20, 36, 0, 23}, + {'<', 271, 111, 25, 31, 2, 26}, + {'=', 338, 144, 27, 23, 4, 22}, + {'>', 296, 111, 24, 31, 3, 26}, + {'?', 284, 44, 25, 34, 3, 28}, + {'@', 289, 0, 29, 38, 5, 27}, + {'A', 328, 44, 31, 33, 6, 27}, + {'B', 144, 78, 28, 33, 4, 27}, + {'C', 59, 44, 29, 34, 4, 27}, + {'D', 200, 78, 28, 33, 4, 27}, + {'E', 479, 78, 27, 33, 3, 27}, + {'F', 161, 111, 26, 33, 3, 27}, + {'G', 174, 44, 28, 34, 5, 27}, + {'H', 54, 111, 27, 33, 4, 27}, + {'I', 108, 111, 27, 33, 4, 27}, + {'J', 452, 78, 27, 33, 4, 27}, + {'K', 59, 78, 29, 33, 4, 27}, + {'L', 135, 111, 26, 33, 3, 27}, + {'M', 228, 78, 28, 33, 4, 27}, + {'N', 0, 111, 27, 33, 4, 27}, + {'O', 117, 44, 29, 34, 5, 27}, + {'P', 312, 78, 28, 33, 4, 27}, + {'Q', 232, 0, 30, 39, 5, 27}, + {'R', 30, 78, 29, 33, 4, 27}, + {'S', 202, 44, 28, 34, 4, 27}, + {'T', 480, 44, 30, 33, 5, 27}, + {'U', 81, 111, 27, 33, 4, 27}, + {'V', 0, 78, 30, 33, 5, 27}, + {'W', 359, 44, 31, 33, 6, 27}, + {'X', 420, 44, 30, 33, 5, 27}, + {'Y', 390, 44, 30, 33, 5, 27}, + {'Z', 340, 78, 28, 33, 4, 27}, + {'[', 210, 0, 22, 40, 0, 29}, + {'\\', 84, 0, 27, 40, 4, 29}, + {']', 188, 0, 22, 40, 3, 29}, + {'^', 268, 144, 26, 25, 3, 27}, + {'_', 433, 144, 28, 16, 4, 4}, + {'`', 385, 144, 20, 20, 2, 32}, + {'a', 396, 111, 28, 29, 4, 22}, + {'b', 391, 0, 28, 35, 4, 28}, + {'c', 452, 111, 27, 29, 4, 22}, + {'d', 475, 0, 27, 35, 4, 28}, + {'e', 368, 111, 28, 29, 4, 22}, + {'f', 447, 0, 28, 35, 3, 29}, + {'g', 362, 0, 29, 35, 4, 22}, + {'h', 230, 44, 27, 34, 4, 28}, + {'i', 318, 0, 24, 36, 3, 30}, + {'j', 16, 0, 25, 43, 5, 30}, + {'k', 30, 44, 29, 34, 4, 28}, + {'l', 419, 0, 28, 35, 4, 28}, + {'m', 58, 144, 29, 28, 5, 22}, + {'n', 114, 144, 27, 28, 4, 22}, + {'o', 424, 111, 28, 29, 4, 22}, + {'p', 146, 44, 28, 34, 4, 22}, + {'q', 257, 44, 27, 34, 4, 22}, + {'r', 168, 144, 26, 28, 2, 22}, + {'s', 340, 111, 28, 29, 4, 22}, + {'t', 256, 78, 28, 33, 4, 27}, + {'u', 87, 144, 27, 28, 4, 22}, + {'v', 29, 144, 29, 28, 5, 22}, + {'w', 479, 111, 31, 28, 6, 22}, + {'x', 0, 144, 29, 28, 5, 22}, + {'y', 88, 44, 29, 34, 5, 22}, + {'z', 141, 144, 27, 28, 4, 22}, + {'{', 138, 0, 25, 40, 3, 29}, + {'|', 0, 0, 16, 44, -2, 30}, + {'}', 163, 0, 25, 40, 3, 29}, + {'~', 405, 144, 28, 18, 4, 20}, + }; + + const uint8_t g_hudFontImage[] = + { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x0a,0x11,0x12,0x0e,0x06,0x02,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e + ,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12,0x12,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x02,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x0a,0x11,0x12,0x12,0x12,0x12,0x11,0x0a,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x06,0x0e,0x12,0x11,0x0a,0x04,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x0e,0x07,0x06,0x06,0x06,0x06,0x06,0x04,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x0a,0x11,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x05,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06 + ,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x10,0x19 + ,0x21,0x28,0x2a,0x25,0x1d,0x15,0x0a,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x25,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x1b,0x25,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a + ,0x2a,0x2a,0x25,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x10,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1d,0x15,0x0a,0x01 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0a,0x15,0x1d,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1d,0x15,0x0b,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x28,0x21,0x14 + ,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x10,0x19,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x19,0x10,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0b,0x15 + ,0x1d,0x25,0x2a,0x28,0x21,0x19,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0b,0x15,0x1d,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1e + ,0x1e,0x1e,0x1e,0x1e,0x1e,0x19,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a + ,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x19,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x1c,0x15,0x0a,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x36,0x40,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x26,0x30,0x37,0x40,0x42,0x3c,0x34,0x2b,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x27,0x36,0x40,0x42,0x3c,0x2f,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x25,0x31 + ,0x3c,0x42,0x40,0x36,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x42,0x3c,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x04,0x16,0x27,0x36,0x40,0x43,0x43,0x43,0x42,0x3c,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x26,0x31,0x3c,0x42,0x43,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42 + ,0x43,0x43,0x43,0x43,0x42,0x3c,0x34,0x2b,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43 + ,0x43,0x43,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x1e,0x2b,0x34,0x3c,0x42,0x43,0x43,0x43,0x42,0x3c,0x34,0x2b,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02 + ,0x14,0x27,0x36,0x40,0x43,0x43,0x43,0x40,0x36,0x27,0x16,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x1b,0x26,0x30,0x37,0x40,0x43,0x43,0x43,0x43,0x40,0x37,0x30,0x26,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x2b,0x34,0x3c,0x42,0x40,0x37,0x30,0x25,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x42,0x3c,0x31,0x25,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21 + ,0x2b,0x34,0x3c,0x42,0x43,0x43,0x43,0x42,0x3c,0x37,0x37,0x37,0x37,0x37,0x36,0x30,0x25,0x16,0x04,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x02,0x14,0x27,0x36,0x40,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0a,0x17,0x25,0x30,0x37,0x40,0x43,0x43,0x43,0x43,0x43,0x40,0x38,0x34 + ,0x2b,0x1e,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x42,0x3c,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x5b + ,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x46,0x4e,0x57,0x5a,0x51,0x4b,0x40,0x2f,0x1e,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x27,0x38,0x49,0x57,0x5a,0x51,0x40,0x2f,0x1e,0x0d + ,0x01,0x00,0x00,0x00,0x00,0x05,0x16,0x27,0x38,0x46,0x51,0x5a,0x57,0x49,0x38,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x2b,0x16,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x25,0x38,0x49,0x57,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x2b,0x15,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2f,0x3c,0x46,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36 + ,0x21,0x0a,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x4b,0x40,0x2f,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00 + ,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x25,0x31,0x40,0x4b,0x51,0x5a,0x5b,0x5b,0x5b,0x5a,0x51,0x4b,0x41,0x36,0x27,0x16,0x05,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x57,0x49,0x38,0x25,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x25,0x31,0x3c,0x46,0x4e,0x57,0x5b,0x5b,0x5b,0x5b,0x57,0x4e,0x46 + ,0x3c,0x2f,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x36,0x41,0x4b,0x51,0x5a,0x57,0x4e,0x46,0x38,0x27,0x16,0x04,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2f,0x40,0x51,0x5a,0x5b,0x5b,0x5a,0x51,0x46,0x38,0x27,0x16,0x04 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x27,0x36,0x41,0x4b,0x51,0x5a,0x5b,0x5b,0x5b,0x5a,0x51,0x4f,0x4f,0x4f,0x4f,0x4f,0x4e,0x46,0x38,0x25,0x10,0x00,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2b,0x38,0x46 + ,0x4e,0x57,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x4f,0x4b,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x2b,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x16,0x2b,0x40,0x51,0x5c,0x65,0x6b,0x71,0x67,0x61,0x51,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x27 + ,0x38,0x49,0x5a,0x6a,0x71,0x62,0x51,0x40,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x02,0x14,0x27,0x38,0x49,0x5a,0x66,0x71,0x6a,0x5a,0x49,0x38,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x71,0x61,0x4c,0x36,0x21,0x0a + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x31,0x46,0x5a,0x6a,0x73,0x73,0x73,0x71,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x51,0x5c + ,0x66,0x71,0x73,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x71,0x67,0x61,0x51,0x40,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x73 + ,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x27,0x38,0x46,0x52,0x61,0x67,0x71,0x73,0x73,0x73,0x71,0x67 + ,0x61,0x57,0x49,0x38,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x73,0x6a,0x5a,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x27,0x38,0x46,0x51 + ,0x5c,0x65,0x6b,0x73,0x73,0x73,0x73,0x6b,0x65,0x5c,0x51,0x40,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x21,0x36,0x49,0x57,0x61,0x67,0x71,0x6b,0x65,0x5a,0x49,0x38,0x25,0x10,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x40,0x51,0x62 + ,0x71,0x73,0x73,0x71,0x66,0x5a,0x49,0x38,0x25,0x10,0x00,0x00,0x00,0x00,0x00,0x04,0x16,0x27,0x38,0x49,0x57,0x61,0x67,0x71,0x73,0x73,0x73,0x71,0x67,0x67,0x67,0x67,0x67,0x67,0x65,0x5a,0x46,0x30,0x19,0x04,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73 + ,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x40,0x4c,0x5a,0x65,0x6b,0x73,0x73,0x73,0x73,0x73,0x6b,0x67,0x61,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x71,0x61,0x4b,0x34 + ,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x89,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x4c,0x61,0x71,0x7b,0x7f,0x84,0x7f,0x72,0x62,0x51,0x3c,0x25,0x0e + ,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x16,0x27,0x38,0x49,0x5a,0x6a,0x7b,0x84,0x72,0x62,0x51,0x40,0x2b,0x15,0x02,0x00,0x00,0x0a,0x21,0x36,0x49,0x5a,0x6a,0x7b,0x84,0x7b,0x6a,0x5a,0x49,0x36,0x21,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67 + ,0x7f,0x8a,0x8c,0x8c,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x66,0x7b,0x8a,0x8c,0x8c,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x10,0x26,0x3c,0x51,0x62,0x71,0x7b,0x84,0x8c,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x8c,0x84,0x7f,0x72,0x62,0x51,0x40,0x2b,0x15,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x06 + ,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x38,0x49 + ,0x5a,0x66,0x72,0x7f,0x84,0x8c,0x8c,0x8c,0x84,0x7f,0x74,0x6a,0x5a,0x49,0x38,0x27,0x16,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x89,0x8c,0x8a,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x02,0x14,0x27,0x38,0x49,0x5a,0x66,0x71,0x7b,0x7f,0x8a,0x8c,0x8c,0x8a,0x7f,0x7b,0x71,0x62,0x51,0x40,0x2b,0x17,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x41,0x57,0x6a,0x74,0x7f,0x84,0x7f,0x7b,0x6a,0x5a,0x46,0x30,0x19 + ,0x04,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x62,0x72,0x84,0x8c,0x8c,0x84,0x7b,0x6a,0x5a,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x10,0x25,0x38,0x49,0x5a,0x6a,0x74,0x7f,0x84,0x8c,0x8c,0x8c,0x84,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7b,0x65,0x4e,0x36,0x1e,0x06 + ,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x89,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x16,0x2b,0x40,0x51,0x61,0x6b,0x7b,0x7f,0x8a,0x8c,0x8c,0x8c,0x8a,0x7f,0x7f,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f + ,0x67,0x7f,0x8c,0x8c,0x8c,0x8c,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa1,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f + ,0x8e,0x97,0x99,0x93,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x25,0x38,0x49,0x5a,0x6a,0x7b,0x8c,0x94,0x84,0x72,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x7b,0x8c,0x97,0x8c,0x7b,0x6a,0x57,0x41,0x2f,0x1e,0x0a + ,0x00,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x74,0x8c,0x9f,0x9d,0x8a,0x73,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2c,0x43,0x5a,0x71,0x84,0x98,0xa1 + ,0x8e,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x71,0x84,0x8e,0x98,0x9d,0x98,0x98,0x98,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x95,0x98,0x98,0x9d,0x99,0x93,0x84,0x72,0x61,0x4b + ,0x34,0x1c,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x95,0x98,0x98,0x98,0x98,0x9b,0xa2,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa2,0x9b,0x98,0x98,0x98,0x98,0x98,0x8c,0x73,0x5b,0x43,0x2a + ,0x12,0x00,0x00,0x00,0x00,0x0b,0x21,0x36,0x49,0x5a,0x6a,0x7b,0x84,0x93,0x99,0xa2,0xa4,0xa2,0x99,0x93,0x8a,0x7b,0x6a,0x5a,0x49,0x38,0x25,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x1b,0x2b,0x43,0x5b,0x73,0x8c,0xa1,0x97,0x7f,0x67,0x4f + ,0x37,0x22,0x16,0x0a,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x21,0x36,0x49,0x5a,0x6a,0x7b,0x84,0x8e,0x97,0x9b,0x9e,0x9e,0x9b,0x97,0x8e,0x84,0x72,0x61,0x4c,0x38,0x25,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x74 + ,0x89,0x93,0x99,0x97,0x8c,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x72,0x84,0x94,0xa2,0xa2,0x98,0x8c,0x7b,0x65,0x4e,0x37,0x21,0x0a,0x00,0x00,0x00,0x06,0x1b,0x31,0x46,0x5a,0x6a,0x7b,0x8a,0x93,0x99,0x9f,0x9e,0x9f,0x99,0x98,0x98 + ,0x98,0x98,0x98,0x95,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x15,0x12,0x11,0x0a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa1,0xa4,0xa4,0xa4 + ,0xa4,0xa4,0xa4,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x21,0x36,0x4c,0x61,0x72,0x7f,0x8c,0x97,0x9d,0xa4,0xa4,0xa4,0x9d,0x97,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x03,0x0a,0x11,0x12,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0xa4,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8a,0x9d,0xad,0xb0,0xa2,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x31,0x46,0x5a,0x6a,0x7b,0x8c,0x9c,0x9c,0x8c,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84 + ,0x94,0xa2,0x9c,0x8a,0x74,0x62,0x51,0x40,0x2b,0x16,0x03,0x00,0x00,0x00,0x00,0x02,0x15,0x2c,0x43,0x5a,0x71,0x84,0x98,0xa3,0x8e,0x7b,0x65,0x4e,0x37,0x21,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x06,0x1d,0x34,0x4b,0x61,0x74,0x8c,0xa2,0x9d,0x8a,0x73,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8e,0xa1,0x9d,0x8e,0x84,0x7f,0x7f,0x7f,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b + ,0x7f,0x7f,0x84,0x8e,0x9c,0xa2,0x93,0x7f,0x67,0x4f,0x37,0x1e,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x7f,0x7f,0x7f,0x7f,0x7f,0x8e,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x8e + ,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x03,0x16,0x2b,0x41,0x57,0x6a,0x7b,0x8c,0x98,0xa4,0xa9,0xa4,0xa4,0xa4,0xa9,0xa8,0x9c,0x8c,0x7b,0x6a,0x5a,0x46,0x31,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x25,0x31 + ,0x3c,0x48,0x5b,0x73,0x8c,0xa4,0x98,0x7f,0x67,0x50,0x41,0x36,0x2b,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x2f,0x41,0x57,0x6a,0x7b,0x8c,0x98,0x9b,0x93,0x8c,0x8c,0x8c,0x8c,0x94,0x9f,0x93,0x7f,0x6b,0x5a,0x46,0x30,0x19,0x04,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x93,0xa6,0xb0,0xab,0x97,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x93,0xa4,0xb5,0xb8,0xac,0x97,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x66,0x7b + ,0x8c,0x9c,0xa5,0x9d,0x93,0x8c,0x93,0x9d,0xa9,0xb0,0xa9,0xa4,0xa4,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2d,0x2a,0x2a,0x28,0x21,0x16,0x0b,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x12,0x2a,0x43,0x5b,0x73,0x8c,0x98,0x98,0x98,0x98,0x9d,0xae,0xb7,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x17,0x2b,0x41,0x57,0x6b,0x7f,0x92,0x9d,0xaa,0xa6,0xa4,0x9d,0x99,0xa2,0x99,0x84,0x71 + ,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0b,0x16,0x21,0x28,0x2a,0x2a,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c + ,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x06,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa2,0xb5,0xb5,0xa2,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x3c,0x51,0x66,0x7b,0x8c,0x9c,0x9d,0x8c,0x7b,0x6a,0x5a,0x46,0x30 + ,0x19,0x04,0x00,0x00,0x0e,0x25,0x3c,0x51,0x62,0x72,0x84,0x94,0xa1,0x94,0x84,0x72,0x61,0x4c,0x36,0x21,0x0b,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x66,0x7b,0x8e,0xa3,0x97,0x7f,0x6b,0x57,0x41,0x2b,0x15,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x26,0x3c,0x51,0x67,0x7f,0x93,0xa2,0x93,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x97,0xa8,0x98,0x7f,0x71,0x67,0x67,0x67,0x61,0x51,0x3c + ,0x25,0x0e,0x00,0x00,0x04,0x19,0x30,0x46,0x5a,0x65,0x67,0x67,0x71,0x7b,0x8e,0xa4,0x98,0x7f,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5a,0x65,0x67,0x67,0x67,0x67,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00 + ,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x8c,0x73,0x67,0x67,0x67,0x67,0x67,0x61,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x0a,0x21,0x36,0x4c,0x61,0x74,0x8a,0x9c,0xac,0xab,0x9c,0x8e,0x8c,0x8e,0x98,0xa4,0xab,0x9c,0x8c,0x7b,0x66,0x51,0x3c,0x25,0x0e,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x38,0x46,0x51,0x5c,0x65,0x73,0x8c,0xa4,0x98,0x7f,0x6a,0x61,0x57,0x4c,0x40,0x2f,0x1e,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x62,0x74,0x8a,0x9c,0x9c,0x8c,0x7f,0x74,0x73,0x73,0x74,0x84,0x94,0x9b + ,0x8c,0x7b,0x65,0x4e,0x37,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x02,0x05,0x09,0x1e,0x37,0x4f,0x67,0x7f,0x97,0xac,0xba,0xac,0x97,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xc5,0xc9,0xb3,0x9d,0x8a,0x73,0x5b,0x43,0x2a + ,0x12,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x98,0xaa,0x9d,0x8c,0x7f,0x76,0x7f,0x8c,0x9c,0xab,0x9d,0x8e,0x8c,0x8c,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x46,0x43,0x43,0x43,0x40,0x36 + ,0x2b,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x7f,0x7f,0x7f,0x7f,0x7f,0x8e,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x34,0x4b,0x61,0x74,0x8a,0x9d + ,0xae,0xa4,0x94,0x8c,0x8a,0x84,0x8c,0x8c,0x7f,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x2b,0x36,0x40,0x43,0x43,0x43,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x19,0x1e,0x1e,0x2a,0x42,0x5a,0x71,0x84,0x94,0xa2,0xa2,0x94,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x49,0x5c,0x71 + ,0x84,0x98,0xa2,0x93,0x7f,0x6b,0x5a,0x49,0x38,0x25,0x10,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x51,0x62,0x72,0x84,0x98,0xa2,0x93,0x7f,0x6b,0x57,0x41,0x2b,0x16,0x03,0x00,0x00,0x00,0x00,0x06,0x1b,0x31,0x46,0x5c,0x73,0x8a,0x9d,0x9d,0x8a,0x74,0x61,0x4b,0x34 + ,0x1d,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x71,0x84,0x99,0xa2,0x8c,0x74,0x61,0x4c,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98 + ,0xaa,0x98,0x7f,0x67,0x53,0x4f,0x4f,0x4b,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x10,0x25,0x38,0x46,0x4e,0x4f,0x51,0x5e,0x73,0x8c,0xa4,0x99,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x25,0x38,0x46,0x4e,0x4f,0x4f,0x4f,0x5b,0x73 + ,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x8c,0x73,0x5b,0x4f,0x4f,0x4f,0x4f,0x4b,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x93,0xa8,0xae,0x9c,0x8c,0x7b,0x73,0x7b,0x84,0x94 + ,0xa8,0xac,0x98,0x84,0x71,0x5a,0x43,0x2c,0x15,0x02,0x00,0x00,0x00,0x00,0x00,0x0d,0x21,0x36,0x49,0x5a,0x66,0x71,0x7b,0x7f,0x8e,0xa4,0x99,0x84,0x7f,0x74,0x6b,0x61,0x51,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x03,0x16,0x2c,0x43,0x5a,0x71,0x84,0x94,0x9c + ,0x8c,0x7b,0x6b,0x61,0x5b,0x5b,0x62,0x72,0x84,0x98,0x97,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x01,0x0a,0x15,0x1c,0x1e,0x21,0x36,0x4e,0x65,0x7b,0x8c,0x9c,0xa4,0x9c,0x8c,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x97 + ,0xac,0xbe,0xc5,0xb0,0x99,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa2,0xae,0x98,0x7f,0x6c,0x64,0x6b,0x7b,0x8e,0xa4,0x99,0x84,0x76,0x73,0x71,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0 + ,0xa4,0x8c,0x73,0x5c,0x5a,0x5b,0x5b,0x5b,0x57,0x4c,0x41,0x36,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x61,0x67,0x67,0x67,0x67,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c + ,0x1e,0x2f,0x3c,0x42,0x43,0x4f,0x67,0x7f,0x93,0xa8,0xa8,0x94,0x84,0x74,0x73,0x71,0x73,0x73,0x71,0x61,0x4b,0x34,0x1d,0x06,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x27,0x36,0x41,0x4c,0x57,0x5b,0x5b,0x5b,0x5a,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37 + ,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x04,0x16,0x25,0x30,0x36,0x37,0x37,0x3e,0x51,0x62,0x72,0x84,0x8c,0x8c,0x84,0x72,0x62,0x51,0x3c,0x25,0x0e + ,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x7b,0x8e,0xa1,0x98,0x84,0x72,0x61,0x4c,0x38,0x27,0x16,0x04,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2f,0x40,0x52,0x66,0x7b,0x8c,0x9d,0x9d,0x8a,0x74,0x61,0x4c,0x36,0x21,0x0b,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40 + ,0x57,0x6b,0x7f,0x97,0xa5,0x93,0x7f,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x37,0x4e,0x65,0x7b,0x8e,0xa2,0x99,0x84,0x71,0x5a,0x43,0x2c,0x16,0x03,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xaa,0x98,0x7f,0x67,0x4f,0x3a,0x37,0x34,0x2b,0x1e,0x0c,0x00,0x00,0x00,0x00,0x04,0x16,0x25,0x30,0x36,0x37,0x43,0x5b,0x73,0x8c,0xa4,0x98,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x04,0x16,0x25,0x30,0x36,0x37,0x37,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x8c,0x73,0x5b,0x43,0x37,0x37,0x37,0x34,0x2b,0x1e,0x0c,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x73,0x8a + ,0x9d,0xb0,0xa3,0x8e,0x7b,0x6a,0x5e,0x66,0x74,0x8a,0x9d,0xb0,0xa2,0x8c,0x74,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x00,0x00,0x06,0x1b,0x2f,0x41,0x57,0x6a,0x7b,0x84,0x8e,0x97,0x9d,0xae,0xa4,0x99,0x93,0x8a,0x7f,0x72,0x62,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00 + ,0x00,0x0a,0x21,0x36,0x4c,0x61,0x74,0x8c,0x9f,0x93,0x7f,0x6b,0x5a,0x4c,0x43,0x44,0x52,0x66,0x7b,0x8e,0x9b,0x8a,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x0c,0x1e,0x2b,0x34,0x37,0x37,0x39,0x46,0x5a,0x6a,0x7b,0x8a,0x8c,0x8a,0x7b,0x6a,0x5a,0x46,0x30,0x19 + ,0x04,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8c,0x9c,0xac,0xae,0xa3,0x93,0x7f,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x51,0x5c,0x73,0x8c,0xa4,0xa2,0x8c,0x73,0x5e,0x5a,0x51,0x40,0x2b,0x15,0x02 + ,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x66,0x71,0x73,0x73,0x73,0x6b,0x61,0x57,0x49,0x38,0x27,0x16,0x04,0x00,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x4b,0x4f,0x4f,0x4f,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x51,0x5a,0x5b,0x5b,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x74,0x64,0x61,0x60,0x61,0x60,0x5b,0x51,0x40,0x2b,0x15,0x02,0x00,0x00,0x00,0x00,0x04,0x16,0x27,0x38,0x49,0x57,0x61,0x6b,0x73,0x73,0x73,0x71 + ,0x6a,0x7f,0x93,0xa8,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x10,0x25,0x38,0x46,0x4e,0x4f,0x4f,0x4f,0x4f,0x55,0x62 + ,0x71,0x73,0x73,0x71,0x62,0x51,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x06,0x1b,0x31,0x46,0x5c,0x73,0x8a,0x9c,0xa1,0x8e,0x7b,0x66,0x52,0x40,0x2b,0x17,0x05,0x00,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x31,0x46,0x5a,0x6b,0x7f,0x93,0xa2,0x93,0x7f,0x6b,0x57,0x41 + ,0x2b,0x15,0x02,0x00,0x00,0x00,0x00,0x0a,0x21,0x37,0x4e,0x65,0x7b,0x8e,0xa2,0x99,0x84,0x71,0x5a,0x43,0x2c,0x16,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x97,0xa5,0x93,0x7f + ,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xaa,0x98,0x7f,0x67,0x4f,0x37,0x21,0x1c,0x15,0x0a,0x01,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x19,0x1e,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0x98,0x7f,0x67,0x4f + ,0x38,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x19,0x1e,0x1e,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x1e,0x1e,0x1c,0x15,0x0a,0x01 + ,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8e,0xa4,0xb0,0x99,0x84,0x71,0x5c,0x4b,0x57,0x6b,0x7f,0x97,0xad,0xa8,0x93,0x7f,0x67,0x4f,0x38,0x21,0x0a,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x62,0x74,0x8a,0x98,0xa3,0xa7,0xa4,0xa4,0xa4,0xa4,0xa5,0x9d + ,0x93,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x93,0x9c,0x8a,0x74,0x61,0x4c,0x42,0x46,0x4e,0x51,0x5f,0x73,0x8c,0x9e,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1b,0x2f,0x40,0x4b,0x4f,0x4f,0x4f,0x4f,0x51,0x5b + ,0x6a,0x73,0x73,0x73,0x6a,0x5a,0x49,0x38,0x25,0x10,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5a,0x6a,0x7b,0x8c,0x97,0x97,0x8e,0x84,0x72,0x61,0x4b,0x34,0x1d,0x06,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x56,0x61,0x74,0x8c,0xa4 + ,0xa4,0x8c,0x73,0x5b,0x45,0x3c,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x76,0x7b,0x84,0x8c,0x8c,0x8a,0x7f,0x74,0x6a,0x5a,0x49,0x38,0x25,0x10,0x00,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2b,0x34,0x37,0x37,0x43,0x5b,0x73 + ,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x62,0x71,0x73,0x73,0x73,0x7f,0x98,0xb0,0xa4,0x8c,0x76,0x73,0x73,0x73,0x73,0x71,0x61,0x4b,0x35,0x20,0x0a,0x00,0x00,0x00,0x00,0x00,0x10,0x25 + ,0x38,0x49,0x5a,0x6a,0x74,0x7f,0x8a,0x8c,0x8c,0x84,0x7b,0x77,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x04,0x19 + ,0x30,0x46,0x5a,0x65,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x65,0x5a,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x66,0x7b,0x8e,0xa3,0x98,0x84,0x71,0x5c,0x46,0x31,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0x25,0x38 + ,0x4c,0x61,0x74,0x8a,0x9d,0x9d,0x8a,0x74,0x61,0x4b,0x34,0x1d,0x06,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x71,0x84,0x99,0xa2,0x8c,0x74,0x61,0x4c,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06 + ,0x1b,0x31,0x46,0x5c,0x73,0x8a,0x9d,0x9d,0x8a,0x74,0x61,0x4b,0x34,0x1d,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xaa,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x08,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x12 + ,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x06,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x8c + ,0x73,0x5b,0x43,0x2a,0x12,0x06,0x05,0x02,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x97,0xad,0xa8,0x93,0x7f,0x67,0x51,0x3f,0x4e,0x65,0x7b,0x8e,0xa4,0xb0,0x98,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84 + ,0x94,0xa8,0xa4,0x98,0x8e,0x8c,0x8c,0x8e,0x98,0xa3,0x98,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8a,0x9d,0x97,0x7f,0x6b,0x57,0x4b,0x57,0x5c,0x65,0x67,0x71,0x76,0x8c,0x9e,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x0e + ,0x25,0x3c,0x51,0x61,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x61,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x10,0x25,0x38,0x49,0x5a,0x6a,0x7b,0x7f,0x7f,0x7b,0x71,0x62,0x51,0x40,0x2b,0x15,0x02,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8a + ,0x9d,0xac,0x99,0x84,0x72,0x68,0x71,0x7f,0x93,0xa6,0x9d,0x8a,0x73,0x5b,0x43,0x2b,0x1b,0x0c,0x01,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8e,0x84,0x8e,0x98,0xa2,0xa4,0x9d,0x93,0x8a,0x7b,0x6a,0x5a,0x46,0x31,0x1b,0x06,0x00,0x00,0x00 + ,0x00,0x01,0x0a,0x15,0x1c,0x1e,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x8c,0x8c,0x8c,0x8e,0x9d,0xb3,0xa8,0x94,0x8c,0x8c,0x8c,0x8c,0x8c,0x7f,0x67,0x4f + ,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x06,0x1b,0x31,0x46,0x5a,0x6a,0x7b,0x8a,0x93,0x9d,0xa4,0xa2,0x98,0x8e,0x84,0x8e,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c + ,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x98,0xa3,0x8e,0x7b,0x66,0x51,0x3c,0x26,0x10,0x01,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x17,0x2b,0x41,0x57,0x6b,0x7f,0x97,0xa5,0x93,0x7f,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x10,0x26,0x3c,0x51,0x67,0x7f,0x93,0xa2,0x93,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x66,0x7b,0x8e,0xa3,0x97,0x7f,0x6b,0x57,0x41,0x2b,0x15,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x19,0x21,0x37,0x4f,0x67,0x7f,0x98,0xaa,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0x98,0x7f,0x67,0x4f,0x37,0x21,0x19,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00 + ,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x38,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x74,0x61,0x4b,0x38,0x46,0x5c,0x73,0x8c,0xa4,0xb1,0x9d,0x8a,0x73,0x5b,0x43,0x2a,0x12 + ,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa2,0xae,0x99,0x84,0x7b,0x73,0x73,0x7b,0x84,0x8e,0x8c,0x7b,0x66,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x73,0x8c,0x9e,0x8e,0x7b,0x65,0x54,0x5c,0x6a,0x73,0x7b,0x7f,0x84,0x8c,0x94 + ,0xa0,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x00,0x04,0x16,0x27,0x38,0x49,0x5a,0x65,0x67,0x67,0x65,0x5c,0x51,0x40,0x2f,0x1e,0x0a + ,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x93,0xa4,0xa4,0x94,0x84,0x7f,0x84,0x8e,0x9d,0xa4,0x93,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xae,0x9d,0x99,0x9e,0xa2,0xa4,0xa4,0xab,0xa8,0x9c + ,0x8c,0x7b,0x66,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x05,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa0,0xa4,0xa4,0xa4,0xae,0xbe + ,0xb5,0xa8,0xa4,0xa4,0xa4,0xa4,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x10,0x26,0x3c,0x51,0x66,0x7b,0x8c,0x9c,0xa8,0xab,0xa4,0xa4,0xa2,0x9e,0x99,0x9d,0xae,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x95,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x95,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x73,0x8c,0xa2 + ,0x9d,0x8a,0x73,0x5c,0x46,0x31,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x21,0x37,0x4e,0x65,0x7b,0x8e,0xa4,0x99,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x06,0x1d,0x34,0x4b,0x61,0x74,0x8c,0xa2,0x9d,0x8a,0x73,0x5c + ,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2c,0x43,0x5a,0x71,0x84,0x98,0xa3,0x8e,0x7b,0x65,0x4e,0x37,0x21,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x16,0x25,0x30,0x36,0x3a,0x4f,0x67,0x7f,0x93 + ,0xa6,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0x98,0x7f,0x67,0x4f,0x3a,0x36,0x30,0x25,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73 + ,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x31,0x43,0x5b,0x73 + ,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x6d,0x62,0x5f,0x66,0x71,0x7b,0x7b,0x6a,0x5a,0x46,0x31,0x1b,0x06,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8e,0x9e,0x8c,0x73 + ,0x5e,0x62,0x71,0x7b,0x8a,0x8e,0x97,0x98,0x9e,0xa5,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x38,0x49,0x57 + ,0x61,0x67,0x67,0x65,0x5c,0x51,0x40,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x4c,0x61,0x72,0x84,0x99,0xa6,0x9f,0x98,0x98,0x99,0x9e,0x9d,0x93,0x84,0x72,0x61,0x4c,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0 + ,0xb5,0xa4,0x98,0x8e,0x8c,0x8c,0x8e,0x9c,0xad,0xac,0x98,0x84,0x71,0x5a,0x43,0x2c,0x15,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a + ,0x43,0x5b,0x73,0x8c,0x98,0x98,0x98,0x9d,0xad,0xbb,0xae,0x9d,0x98,0x98,0x98,0x98,0x95,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x71,0x84,0x98,0xac,0xad,0x9c,0x8e,0x8c,0x8c,0x8e,0x98,0xa4,0xb7,0xb0,0x98,0x7f,0x67,0x4f,0x37 + ,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0xa4,0xa4,0xa4,0xa4,0xa9,0xb0,0xad,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06 + ,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8e,0xa4,0x98,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x73,0x8c,0xa4,0xa2,0x8c,0x73,0x5b,0x43,0x2c,0x15,0x00,0x00,0x00,0x00,0x00,0x02,0x15 + ,0x2c,0x43,0x5a,0x71,0x84,0x98,0xa3,0x8e,0x7b,0x65,0x4e,0x37,0x21,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1d,0x34,0x4b,0x61,0x74,0x8c,0xa2,0x9d,0x8a,0x73,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x10,0x25,0x38,0x46,0x4e,0x4f,0x53,0x66,0x7b,0x8e,0xa4,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0x98,0x7f,0x67,0x57,0x4f,0x4e,0x46,0x38,0x27,0x14,0x02,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8a,0x9d + ,0xb1,0xa4,0x8c,0x73,0x5b,0x43,0x31,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa2,0xaf,0x9d,0x8c,0x7b,0x73,0x6b,0x65,0x61,0x65,0x65,0x5a,0x49,0x38,0x25,0x10,0x00,0x00,0x00,0x00 + ,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x97,0xa2,0x8c,0x73,0x61,0x71,0x84,0x8e,0x9a,0x98,0x93,0x8c,0x8e,0x9d,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa1,0xa4,0xa4,0xa4,0xa4,0xa6,0xad,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12 + ,0x00,0x00,0x00,0x00,0x0b,0x21,0x36,0x49,0x5a,0x6a,0x74,0x7f,0x7f,0x7b,0x71,0x62,0x51,0x40,0x2b,0x16,0x03,0x00,0x00,0x00,0x0a,0x21,0x36,0x4c,0x61,0x72,0x84,0x99,0x94,0x8c,0x8e,0x97,0x93,0x8c,0x8a,0x7f,0x72,0x62,0x51,0x40,0x2b,0x17,0x06,0x00,0x00,0x00 + ,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa8,0x94,0x84,0x7b,0x73,0x73,0x7b,0x8c,0x9d,0xb0,0xa2,0x8c,0x74,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x7f,0x7f,0x7f,0x7f,0x8c,0x9d,0xb2,0xa4,0x8e,0x7f,0x7f,0x7f,0x7f,0x7f,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x00,0x0a,0x21,0x37,0x4e,0x65,0x7b,0x8e,0xa3,0xb0,0x9d,0x8c,0x7b,0x73,0x73 + ,0x7b,0x84,0x99,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x8c,0x8c,0x8e + ,0x9c,0xae,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x97,0xa8,0x98,0x7f,0x67,0x4f,0x38,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8a,0x9d,0xa4,0x8c,0x74,0x61 + ,0x4b,0x34,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x66,0x7b,0x8e,0xa3,0x97,0x7f,0x6b,0x57,0x41,0x2b,0x15,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x26,0x3c,0x51,0x67,0x7f,0x93,0xa2,0x93,0x7f,0x6b,0x57 + ,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5a,0x65,0x67,0x67,0x72,0x84,0x98,0xa5,0x93,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa2,0x99,0x84,0x74,0x6b + ,0x67,0x65,0x5a,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x99,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x31,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x94,0xa6,0xab,0x9c,0x8e,0x8a,0x7f,0x7b,0x71,0x66 + ,0x5c,0x51,0x40,0x2f,0x1e,0x0d,0x01,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa2,0x8c,0x73,0x66,0x7b,0x8e,0x9f,0x94,0x84,0x7f,0x74,0x7f,0x98,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x89,0x8c,0x8c,0x8c,0x8c,0x8c + ,0x94,0xa4,0xb4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x02,0x15,0x2b,0x41,0x57,0x6a,0x7b,0x8a,0x93,0x97,0x8e,0x84,0x72,0x61,0x4c,0x36,0x21,0x0a,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x93,0x9f,0x8c,0x76,0x7b,0x7f,0x7f,0x74,0x73,0x6b + ,0x61,0x53,0x46,0x3c,0x31,0x25,0x16,0x05,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x74,0x66,0x5c,0x5c,0x6b,0x7f,0x98,0xb0,0xa8,0x93,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73 + ,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x61,0x67,0x67,0x67,0x6c,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x67,0x67,0x67,0x67,0x65,0x5a,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x11,0x28,0x40,0x57 + ,0x6b,0x7f,0x97,0xad,0xa8,0x93,0x7f,0x6b,0x5c,0x5c,0x69,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x05,0x1c + ,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x73,0x7b,0x8e,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xaa,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11 + ,0x28,0x40,0x57,0x6b,0x7f,0x98,0xa6,0x93,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x31,0x46,0x5c,0x73,0x8a,0x9d,0x9d,0x8a,0x74,0x61,0x4b,0x34,0x1d,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x19,0x30 + ,0x46,0x5c,0x71,0x84,0x99,0xa2,0x8c,0x74,0x61,0x4c,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x7f,0x7f,0x84,0x94,0x9f,0x98,0x8a,0x74,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12 + ,0x2a,0x42,0x5a,0x71,0x84,0x93,0x9b,0x94,0x8a,0x7f,0x7f,0x7b,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x8c + ,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5c,0x46,0x33,0x43,0x5b,0x73,0x8c,0xa4,0xb4,0xa2,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x62,0x74 + ,0x89,0x94,0xa3,0xa8,0xa4,0x9d,0x97,0x8e,0x84,0x7b,0x71,0x62,0x51,0x40,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0x99,0x84,0x71,0x67,0x7f,0x97,0x9d,0x8a,0x74,0x67,0x69,0x7f,0x98,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x11 + ,0x28,0x40,0x57,0x6a,0x73,0x73,0x73,0x73,0x73,0x74,0x84,0x99,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x74,0x8a,0x9c,0xa8,0xad,0xa3,0x93,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8a + ,0x9d,0xa4,0x8c,0x74,0x6c,0x6d,0x6d,0x69,0x67,0x67,0x67,0x61,0x5a,0x51,0x46,0x38,0x27,0x16,0x04,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x48,0x4f,0x67,0x7f,0x93,0xa8,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x4b,0x4f,0x4f,0x52,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x4f,0x4f,0x4f,0x4e,0x46,0x38 + ,0x25,0x10,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8a,0x9d,0xb1,0xa4,0x8c,0x74,0x61,0x4c,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c + ,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5e,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa6,0x93,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x38,0x4f,0x67,0x7f,0x98,0xaa,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x93,0xa2,0x93,0x7f,0x67,0x51,0x3c,0x26,0x10,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x21,0x37,0x4e,0x65,0x7b,0x8e,0xa1,0x98,0x84,0x71,0x5a,0x43,0x2c,0x16,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x95,0x98,0x99,0x9b,0x8e,0x84,0x7b,0x6a,0x57,0x41,0x2b,0x15,0x02,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x62,0x72,0x7f,0x8c,0x9c,0x9d,0x98,0x97,0x8a,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00 + ,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8e,0x7b,0x65,0x4e,0x39,0x46,0x5c,0x73,0x8c,0xa4,0xb0,0x99,0x84,0x71,0x5a,0x42,0x2a,0x12 + ,0x00,0x00,0x00,0x00,0x06,0x1b,0x2f,0x41,0x57,0x6a,0x74,0x84,0x8e,0x98,0xa3,0xaa,0xaa,0xa3,0x98,0x8e,0x84,0x72,0x62,0x51,0x40,0x2b,0x15,0x02,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0x99,0x84,0x71,0x71,0x84,0x99,0x98,0x7f,0x6f,0x5f,0x6b,0x7f,0x98 + ,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x5b,0x5b,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x93,0xa8,0xbc,0xc3,0xb3,0x9d,0x8a,0x73,0x5b,0x43,0x2a + ,0x12,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa2,0xa7,0x94,0x84,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x74,0x71,0x66,0x5a,0x49,0x38,0x25,0x10,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x4b,0x61,0x74,0x8c,0xa4 + ,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2b,0x34,0x37,0x3a,0x4f,0x67,0x7f,0x98,0xb0 + ,0xa4,0x8c,0x73,0x5b,0x43,0x37,0x37,0x36,0x30,0x25,0x16,0x04,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x46,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4 + ,0x8c,0x76,0x64,0x4e,0x36,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xaa,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x4c,0x61,0x74,0x8c,0xa2,0x99,0x84 + ,0x71,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x41,0x57,0x6b,0x7f,0x97,0xa3,0x8e,0x7b,0x66,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x95,0x99,0xa2,0x99,0x84 + ,0x7f,0x72,0x62,0x51,0x3c,0x26,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x62,0x72,0x7f,0x84,0x99,0xa4,0x9d,0x98,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73 + ,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x97,0xad,0xad,0x97,0x7f,0x67,0x51,0x3f,0x4e,0x65,0x7b + ,0x8e,0xa4,0xb0,0x98,0x7f,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x0d,0x21,0x36,0x49,0x57,0x62,0x71,0x7b,0x84,0x8e,0x97,0x9d,0xa8,0xaa,0xa3,0x94,0x84,0x72,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa2,0x8c,0x73 + ,0x6b,0x7f,0x98,0x9d,0x8c,0x7b,0x73,0x7b,0x8c,0x9d,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x02,0x14,0x27,0x36,0x40,0x43,0x43,0x43,0x43,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8e + ,0xa3,0xb5,0xbc,0xb9,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x94,0xa4,0xa4,0x99,0x98,0x98,0x98,0x98,0x98,0x98,0x93,0x8c,0x84,0x7b,0x6a,0x5a,0x46,0x30,0x19,0x04,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0 + ,0xa4,0x8c,0x73,0x5b,0x43,0x44,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x15,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x01 + ,0x0a,0x15,0x1c,0x21,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x1e,0x1e,0x19,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37 + ,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2d,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06 + ,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa6,0x93,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xaa,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x03,0x16,0x2c,0x43,0x5a,0x71,0x84,0x99,0xa2,0x8e,0x7b,0x65,0x4e,0x37,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1d,0x34,0x4b,0x61,0x74,0x8a,0x9d,0x9d,0x8a,0x73,0x5c,0x46,0x31,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06 + ,0x1e,0x36,0x4e,0x65,0x7b,0x7f,0x84,0x8e,0x97,0x98,0x93,0x84,0x71,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x93,0x99,0x9a,0x8e,0x8a,0x7f,0x7f,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8e + ,0xa4,0xb0,0x99,0x84,0x71,0x5c,0x49,0x57,0x6b,0x7f,0x97,0xad,0xa8,0x93,0x7f,0x67,0x4f,0x37,0x1e,0x07,0x00,0x00,0x00,0x00,0x01,0x10,0x25,0x38,0x49,0x57,0x5b,0x5d,0x66,0x71,0x7b,0x7f,0x8a,0x93,0x9d,0xab,0xa4,0x93,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00 + ,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x93,0xa0,0x8c,0x73,0x67,0x7f,0x93,0xa2,0x9c,0x8e,0x8c,0x8e,0x96,0x99,0x9f,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12 + ,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x71,0x84,0x94,0xa2,0xa4,0xae,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x11,0x28,0x3d,0x51,0x62,0x72,0x84,0x99,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa6,0xa6,0xa2,0x98,0x8c,0x7b,0x65,0x4e,0x37,0x21,0x0a + ,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x4b,0x61,0x74,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2d,0x2a + ,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x08,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x06,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x4f + ,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x15,0x2a,0x43,0x5b,0x73 + ,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xaa,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x67,0x7f,0x98,0xa6,0x93,0x7f,0x67 + ,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x67,0x7f,0x93,0xa5,0x97,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x67,0x7f,0x93,0xa5,0x97,0x7f,0x6b,0x57,0x40,0x28 + ,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5a,0x65,0x67,0x71,0x7b,0x84,0x99,0xa2,0x8e,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa2,0x9d,0x8c,0x7b,0x73 + ,0x6b,0x67,0x61,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x73,0x8a,0x9d,0xb0,0xa3,0x8e,0x7b,0x68,0x5e,0x66,0x74,0x8a,0x9d,0xad,0x9d,0x8a,0x74,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x00,0x00,0x0a,0x1e,0x31,0x46,0x5a,0x6a,0x71,0x62,0x5b,0x5d,0x65,0x6b,0x74,0x7f,0x8e,0xa4 + ,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x74,0x8c,0x9e,0x8c,0x74,0x66,0x72,0x84,0x94,0xa1,0x9e,0x9b,0x93,0x84,0x84,0x95,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x1e,0x37,0x4f,0x67 + ,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x10,0x26,0x3c,0x51,0x62,0x72,0x84,0x8c,0x8e,0x9d,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1b,0x31,0x46,0x5a,0x6a,0x7b,0x8c,0x98,0x8e,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x93 + ,0x9d,0xab,0xac,0x97,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x47,0x52,0x67,0x7f,0x93,0xa8,0xad,0x97,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73 + ,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x46,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b + ,0x73,0x8a,0x9d,0xb1,0xa4,0x8c,0x74,0x61,0x4c,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xaa,0x98,0x7f,0x67,0x4f,0x38,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12 + ,0x2a,0x42,0x5a,0x71,0x84,0x99,0xa4,0x8c,0x74,0x61,0x4b,0x34,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1d,0x34,0x4b,0x61,0x74,0x8a,0x9d,0x9d,0x8a,0x73,0x5c,0x46,0x31,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x16,0x2c,0x43,0x5a + ,0x71,0x84,0x99,0xa2,0x8e,0x7b,0x65,0x4e,0x37,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x25,0x38,0x46,0x4e,0x51,0x5c,0x69,0x7f,0x93,0xa5,0x97,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12 + ,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0x98,0x7f,0x6b,0x5c,0x57,0x4f,0x4b,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x8c + ,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x93,0xa4,0xac,0x98,0x84,0x7b,0x73,0x7b,0x84,0x94,0xa8,0xa8,0x93,0x7f,0x6b,0x57,0x41,0x2b,0x15,0x02,0x00,0x00,0x00,0x03,0x16,0x2b,0x40,0x52,0x66,0x7b + ,0x84,0x74,0x71,0x66,0x5c,0x5e,0x64,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x02,0x15,0x2c,0x43,0x5b,0x73,0x8c,0x9f,0x93,0x7f,0x67,0x62,0x72,0x84,0x8c,0x8c,0x8a,0x7f,0x72,0x7b,0x7f,0x7f,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x51,0x62,0x71,0x73,0x7f,0x98,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x0e,0x25,0x3c,0x51,0x66,0x7b,0x8c + ,0x9b,0x93,0x7f,0x73,0x73,0x73,0x73,0x73,0x74,0x7f,0x8c,0x9d,0xac,0x9a,0x88,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x74,0x62,0x5b,0x62,0x72,0x84,0x99,0xb0,0xa4,0x8e,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8a,0x9d,0xb1,0xa4,0x8c,0x74,0x62,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x98,0xb0,0xa8,0x93,0x7f,0x6b,0x5c,0x5c,0x6b,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c + ,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x93,0xa6,0x98,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x16,0x2c,0x43,0x5b,0x73,0x8c,0xa2,0xa2,0x8c,0x73,0x5b,0x43,0x2c,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x41,0x57,0x6b,0x7f,0x97,0xa3,0x8e,0x7b,0x66,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x4c,0x61,0x74,0x8c,0xa2,0x99,0x84,0x71,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x16,0x25,0x30,0x36,0x3d,0x4e,0x65,0x7b,0x8e,0xa4,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0x98,0x7f,0x67,0x4f,0x40,0x38,0x34,0x2b,0x1e,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00 + ,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x4c,0x61,0x72,0x84,0x98,0xab,0xa4,0x98,0x8e,0x8c,0x8e,0x98,0xa4,0xab,0x9c,0x8a,0x74,0x61,0x4c,0x36,0x21,0x0b,0x00 + ,0x00,0x00,0x00,0x0a,0x21,0x36,0x4c,0x61,0x72,0x84,0x91,0x8c,0x84,0x7b,0x73,0x73,0x73,0x7b,0x8e,0xa4,0xad,0x97,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x98,0x99,0x84,0x71,0x5d,0x62,0x71,0x73,0x73,0x73,0x6b,0x61,0x65 + ,0x67,0x67,0x61,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x04,0x16,0x27,0x37,0x45,0x53,0x5f,0x71,0x84,0x99,0x9d,0x8a,0x73,0x5b,0x43,0x2a + ,0x12,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x98,0xa2,0x8c,0x74,0x63,0x5e,0x5b,0x5b,0x5e,0x64,0x71,0x84,0x99,0xa9,0x97,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa8,0x94,0x84,0x74,0x73,0x74,0x84,0x94,0xa4,0xb0 + ,0x9d,0x8a,0x73,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x98,0xb0,0xa8,0x94,0x84,0x74,0x73,0x73,0x73,0x6a,0x57,0x41,0x2b,0x15,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0 + ,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x38,0x4f,0x67,0x7f,0x93,0xa8,0xb1,0x9d,0x8c,0x7b,0x73,0x73,0x7b,0x8c,0x9d,0xb3,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x74,0x8c,0xa2 + ,0x9d,0x8a,0x73,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x4c,0x61,0x74,0x8c,0xa4,0x99,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x21,0x37,0x4e,0x65,0x7b,0x8e,0xa3 + ,0x98,0x84,0x71,0x5a,0x43,0x2c,0x15,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x93,0xa2,0x93,0x7f,0x67,0x51,0x3c,0x26,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x19,0x21,0x37,0x4f,0x67,0x7f,0x97 + ,0xa8,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0x98,0x7f,0x67,0x4f,0x37,0x22,0x1c,0x15,0x0a,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73 + ,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x16,0x2b,0x40,0x52,0x66,0x7b,0x8c,0x98,0xa3,0xa8,0xa4,0xa4,0xa4,0xab,0xa8 + ,0x9c,0x8c,0x7b,0x6a,0x57,0x41,0x2b,0x19,0x06,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x93,0xa3,0xa2,0x98,0x8e,0x8c,0x8c,0x8c,0x8e,0x9c,0xab,0xa3,0x8e,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x66,0x7b,0x8e,0x9e,0x8e + ,0x7b,0x66,0x56,0x5a,0x5b,0x5b,0x5b,0x57,0x4d,0x4e,0x4f,0x4f,0x4b,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x10,0x25,0x38,0x49,0x57,0x61 + ,0x6b,0x7b,0x8e,0xa0,0x93,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8a,0x9d,0xa4,0x8e,0x7b,0x73,0x6b,0x67,0x67,0x6b,0x73,0x7b,0x8e,0xa3,0xa3,0x8e,0x7b,0x65,0x4e,0x37,0x21,0x0a,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0 + ,0xad,0x9f,0x94,0x8c,0x8c,0x8c,0x94,0xa4,0xb1,0xa4,0x93,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x38,0x4f,0x67,0x7f,0x93,0xa4,0xb2,0xa4,0x94,0x8c,0x8c,0x8c,0x89,0x74,0x61,0x4b,0x34,0x1d,0x06,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x74,0x8a,0x9c,0xad,0xad,0x9c,0x8e,0x8c,0x8c,0x8e,0x9b,0xa3,0xae,0xb0,0x98,0x7f,0x67,0x4f,0x37 + ,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06 + ,0x00,0x00,0x02,0x15,0x2c,0x43,0x5a,0x71,0x84,0x99,0xa4,0x8e,0x7b,0x65,0x4e,0x37,0x21,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x29,0x40,0x57,0x6b,0x7f,0x93,0xa2,0x93,0x7f,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x73,0x8a,0x9d,0xa2,0x8c,0x74,0x61,0x4b,0x34,0x1d,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x73,0x8a,0x9d,0xa2,0x8c,0x74,0x61,0x4b,0x34,0x1d,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x07,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xaa,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x08,0x02,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x31,0x46,0x5a + ,0x6a,0x7b,0x84,0x8e,0x98,0xa4,0xb5,0xb5,0xa4,0x94,0x8a,0x7b,0x6a,0x5a,0x4b,0x41,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x7f,0x8c,0x98,0xa2,0xa5,0xa4,0xa4,0xa4,0xa4,0xa4,0xa5,0x9d,0x93,0x84,0x71,0x5c,0x46,0x30,0x19,0x04,0x00,0x00 + ,0x00,0x06,0x1b,0x31,0x46,0x5c,0x73,0x8a,0x9c,0x98,0x84,0x72,0x62,0x57,0x4d,0x49,0x4a,0x4e,0x57,0x5b,0x57,0x49,0x3b,0x2d,0x1e,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12 + ,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5a,0x6a,0x74,0x7f,0x8c,0x9c,0x9c,0x8a,0x74,0x61,0x4c,0x36,0x21,0x0a,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x97,0xa5,0x9c,0x8e,0x8a,0x7f,0x7f,0x7f,0x7f,0x8a,0x8e,0x9c,0xa1,0x94,0x84,0x71,0x5c,0x46,0x30,0x19,0x04 + ,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa9,0x9c,0x8e,0x94,0x9f,0xa4,0xa4,0xa8,0xab,0xa3,0x94,0x84,0x72,0x61,0x4c,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x72,0x84,0x98,0xa8,0xae,0xa8,0xa4,0xa4,0xa2,0x93 + ,0x7f,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x41,0x57,0x6a,0x7b,0x8c,0x9c,0xac,0xab,0xa4,0xa4,0xa2 + ,0x9b,0x93,0x8e,0x9d,0xab,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x06,0x06,0x12,0x2a,0x43,0x5b,0x73 + ,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x67,0x7f,0x93,0xa5,0x97,0x7f,0x6b,0x57,0x41,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x21,0x36,0x49,0x5c,0x73,0x8a,0x9d,0xa2,0x8c,0x74,0x61,0x4b + ,0x34,0x1d,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x93,0xa2,0x93,0x7f,0x67,0x51,0x3c,0x26,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x21,0x37,0x4e,0x65,0x7b,0x8e,0xa3,0x98,0x84,0x71,0x5a,0x43,0x2c,0x15,0x02 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xaa,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x15,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0x98,0x7f,0x67,0x4f + ,0x37,0x1e,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x15,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x15,0x12,0x11,0x0a,0x02,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0x25,0x38,0x49,0x5a,0x66,0x71,0x7b,0x84,0x98,0xad,0xb0,0x99,0x84,0x74,0x6a,0x5b,0x54,0x5a,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x61,0x6b,0x7b,0x84,0x8c,0x93,0x98,0x9d,0xae,0xa4,0x99,0x93,0x8a + ,0x7f,0x72,0x62,0x51,0x3c,0x26,0x10,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x7b,0x8e,0x9f,0x94,0x84,0x74,0x6b,0x61,0x5b,0x5c,0x65,0x6b,0x73,0x6a,0x5a,0x46,0x31,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67 + ,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8a,0x93,0x9c,0x9c,0x8c,0x7b,0x6a,0x57,0x41,0x2b,0x16,0x03,0x00,0x00,0x0a,0x21,0x37,0x4e,0x65,0x7b,0x8a,0x93,0x9d,0x9f,0x9d,0x98,0x98,0x98,0x98,0x9b,0x9b + ,0x97,0x8e,0x84,0x72,0x62,0x51,0x3c,0x26,0x10,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x95,0x98,0x8e,0x7b,0x84,0x93,0x99,0xa2,0xa2,0x98,0x8e,0x84,0x72,0x62,0x51,0x40,0x2b,0x16,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x40,0x52 + ,0x66,0x7b,0x8a,0x93,0x99,0xa2,0xa4,0xa2,0x99,0x95,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x21,0x36 + ,0x49,0x5a,0x6a,0x7b,0x8c,0x97,0x9d,0xa4,0x9d,0x97,0x8c,0x7f,0x7f,0x95,0x98,0x95,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00 + ,0x04,0x10,0x19,0x1e,0x1e,0x1b,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x06,0x1d,0x34,0x4b,0x61,0x74,0x8a,0x9d,0x9d,0x8a,0x74,0x62,0x51,0x3c,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x2f,0x41 + ,0x57,0x6a,0x7b,0x8e,0xa3,0x98,0x84,0x71,0x5a,0x43,0x2c,0x15,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x4c,0x61,0x74,0x8c,0xa2,0x99,0x84,0x71,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x41,0x57,0x6b,0x7f + ,0x97,0xa3,0x8e,0x7b,0x66,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xaa,0x98,0x7f,0x67,0x4f,0x37,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a + ,0x2d,0x43,0x5b,0x73,0x8c,0xa4,0x98,0x7f,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2d,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x8c + ,0x73,0x5b,0x43,0x2d,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x16,0x27,0x38,0x46,0x51,0x5c,0x68,0x7b,0x8e,0xa3,0xaf,0x9d,0x8c,0x7b,0x71,0x67,0x67,0x71,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x4c,0x5a,0x66 + ,0x71,0x74,0x7f,0x7f,0x8e,0xa4,0x99,0x84,0x7f,0x74,0x6b,0x61,0x51,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x49,0x5c,0x71,0x84,0x94,0x9f,0x94,0x8a,0x7f,0x74,0x73,0x73,0x7b,0x7f,0x88,0x7b,0x66,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xad,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8e,0x9c,0x93,0x8a,0x7b,0x6a,0x5a,0x49,0x36,0x21,0x0b,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5a,0x6a,0x74 + ,0x7f,0x8a,0x8e,0x97,0x98,0x98,0x98,0x93,0x8c,0x8a,0x7f,0x7b,0x71,0x62,0x51,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x7f,0x7f,0x7f,0x71,0x72,0x7f,0x84,0x8c,0x8c,0x84,0x7b,0x71,0x62,0x51,0x40,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x31,0x46,0x5a,0x6a,0x74,0x7f,0x84,0x8c,0x8c,0x8c,0x84,0x7f,0x7b,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x38,0x49,0x5a,0x6a,0x7b,0x7f,0x8a,0x8c,0x8a,0x7f,0x7b,0x6d,0x7b,0x7f,0x7f,0x7f,0x7b,0x65,0x4e,0x36,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c + ,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x04,0x16,0x25,0x30,0x36,0x36,0x30,0x2d,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x02,0x15,0x2b,0x41,0x57,0x6b,0x7f,0x93,0xa2,0x94,0x84,0x71,0x5c,0x49,0x38,0x27,0x16 + ,0x04,0x00,0x00,0x00,0x00,0x05,0x16,0x27,0x3c,0x51,0x62,0x74,0x8a,0x9c,0xa1,0x8e,0x7b,0x66,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x16,0x2c,0x43,0x5a,0x71,0x84,0x99,0xa2,0x8e,0x7b,0x65,0x4e,0x37,0x21,0x0a,0x00 + ,0x00,0x00,0x00,0x06,0x1d,0x34,0x4b,0x61,0x74,0x8a,0x9d,0x9d,0x8a,0x73,0x5c,0x46,0x31,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xaa,0x98,0x7f,0x67,0x4f,0x43,0x43,0x40,0x36,0x27 + ,0x14,0x02,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x48,0x5b,0x73,0x8c,0xa4,0x99,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x46,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00 + ,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x8c,0x73,0x5b,0x46,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x25,0x31,0x3c,0x48,0x5c,0x71,0x84,0x94,0xa4,0xab,0x9c,0x8e,0x84,0x7f,0x7f,0x82,0x73,0x5b,0x43,0x2c,0x15 + ,0x02,0x00,0x00,0x00,0x0c,0x1e,0x2b,0x38,0x46,0x51,0x5a,0x61,0x67,0x73,0x8c,0xa4,0x98,0x7f,0x6a,0x61,0x57,0x4c,0x40,0x2f,0x1e,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x3c,0x51,0x62,0x72,0x84,0x8e,0x9b,0x9c,0x93,0x8c,0x8c,0x8c,0x8e,0x97,0x96 + ,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x95,0x98,0x98,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x73,0x8a,0x8a,0x7f,0x74,0x6a,0x5a,0x49,0x38,0x27,0x14,0x02 + ,0x00,0x00,0x00,0x00,0x10,0x25,0x38,0x49,0x57,0x61,0x6b,0x73,0x7b,0x7f,0x7f,0x7f,0x7f,0x7f,0x74,0x73,0x6b,0x65,0x5c,0x51,0x40,0x2f,0x1e,0x0c,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5a,0x65,0x67,0x67,0x67,0x61,0x61,0x67,0x71,0x73,0x73,0x71,0x66,0x5c + ,0x51,0x40,0x2f,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0x25,0x38,0x49,0x57,0x61,0x67,0x71,0x73,0x73,0x73,0x71,0x67,0x65,0x5a,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73 + ,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x27,0x38,0x49,0x5a,0x65,0x6b,0x73,0x73,0x73,0x6b,0x65,0x5e,0x65,0x67,0x67,0x67,0x65,0x5a,0x46,0x30,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x10,0x25,0x38,0x46,0x4e,0x4e,0x46,0x42,0x47,0x5c,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x0b,0x21,0x36,0x4c,0x61,0x74 + ,0x8a,0x9c,0xa1,0x8e,0x7b,0x6a,0x5a,0x49,0x38,0x25,0x10,0x00,0x00,0x00,0x02,0x14,0x27,0x38,0x49,0x5c,0x71,0x84,0x94,0xa2,0x94,0x84,0x71,0x5c,0x46,0x31,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x67,0x7f + ,0x93,0xa5,0x97,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x67,0x7f,0x93,0xa5,0x97,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98 + ,0xaa,0x98,0x7f,0x69,0x5c,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5c,0x66,0x74,0x8c,0xa4,0x98,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5e,0x73 + ,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x8c,0x73,0x5e,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x1b,0x27,0x3c,0x51,0x62,0x72,0x84,0x94,0xa3,0xa8 + ,0xa3,0x99,0x98,0x98,0x8c,0x74,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x00,0x01,0x0a,0x17,0x25,0x31,0x3c,0x43,0x4c,0x5b,0x73,0x8c,0xa4,0x98,0x7f,0x67,0x50,0x41,0x36,0x2b,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x51,0x62,0x71 + ,0x7b,0x8a,0x93,0x98,0x98,0x9d,0x98,0x97,0x8e,0x8a,0x7f,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x7f,0x7f,0x7f,0x7f,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x7b + ,0x74,0x6b,0x61,0x57,0x49,0x38,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x04,0x16,0x27,0x36,0x41,0x4c,0x57,0x5c,0x65,0x67,0x67,0x67,0x67,0x67,0x61,0x5b,0x57,0x4e,0x46,0x3c,0x2f,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x10,0x25,0x38,0x46,0x4e,0x4f,0x4f + ,0x4f,0x4b,0x4b,0x51,0x5a,0x5b,0x5b,0x5a,0x51,0x46,0x3c,0x2f,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x16,0x27,0x36,0x41,0x4b,0x51,0x5a,0x5b,0x5b,0x5b,0x5a,0x51,0x4e,0x46,0x38,0x27,0x14,0x02,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x27,0x38,0x46,0x4e,0x57,0x5b,0x5b,0x5b,0x57,0x4e,0x49,0x4e,0x4f,0x4f,0x4f,0x4e,0x46,0x38,0x25 + ,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x06,0x1b,0x31,0x46,0x5a,0x65,0x65,0x5c,0x5a,0x5a,0x66,0x7b,0x8e,0xa4,0xad,0x97,0x7f,0x67,0x4f,0x37,0x1e,0x06 + ,0x00,0x00,0x00,0x00,0x03,0x16,0x2b,0x41,0x57,0x6a,0x7b,0x8e,0xa1,0x9c,0x8c,0x7b,0x6a,0x5a,0x46,0x30,0x19,0x04,0x00,0x00,0x0a,0x21,0x36,0x49,0x5a,0x6a,0x7b,0x8e,0xa1,0x9c,0x8a,0x74,0x62,0x51,0x3c,0x26,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x06,0x1d,0x34,0x4b,0x61,0x74,0x8a,0x9d,0x9d,0x8a,0x73,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x02,0x15,0x2c,0x43,0x5a,0x71,0x84,0x99,0xa2,0x8e,0x7b,0x65,0x4e,0x37,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x93,0xa6,0x99,0x84,0x7b,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x7b,0x84,0x94,0xa5,0x97,0x7f,0x67,0x4f,0x38,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x05 + ,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x76,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x8c,0x76,0x73,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x08,0x1b,0x2f,0x40,0x51,0x62,0x72,0x84,0x8e,0x98,0xa2,0xa4,0xa5,0xa1,0x93,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x1b,0x25,0x2e,0x43,0x5b,0x73,0x8c,0xa4,0x98,0x7f,0x67,0x4f,0x37,0x22,0x16,0x0a,0x01,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2f,0x40,0x51,0x5c,0x6a,0x74,0x7f,0x7f,0x84,0x8c,0x84,0x7f,0x7b,0x73,0x6b,0x61,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5a,0x65,0x67,0x67,0x67,0x67,0x61,0x51,0x3c,0x25,0x0e + ,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x49,0x5a,0x65,0x61,0x57,0x4c,0x41,0x36,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x2b,0x36,0x40,0x46,0x4e,0x4f,0x4f,0x4f,0x4f,0x4f,0x4b,0x43,0x40,0x37,0x30,0x26,0x1b,0x0c,0x01,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x04,0x16,0x25,0x30,0x36,0x37,0x37,0x37,0x34,0x34,0x3c,0x42,0x43,0x43,0x42,0x3c,0x31,0x26,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x2b,0x34,0x3c,0x42,0x43,0x43,0x43,0x42,0x3c + ,0x36,0x30,0x25,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x25,0x30,0x37,0x40,0x43,0x43,0x43,0x40 + ,0x37,0x33,0x36,0x37,0x37,0x37,0x36,0x30,0x25,0x16,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x66,0x7b,0x7b,0x73,0x71,0x71,0x74,0x84 + ,0x98,0xad,0xa4,0x8e,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x0b,0x21,0x36,0x49,0x5c,0x71,0x84,0x94,0xa2,0x9c,0x8c,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x7b,0x8c,0x9c,0x9c,0x8c,0x7b,0x6a,0x57,0x41,0x2f,0x1b + ,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x41,0x57,0x6b,0x7f,0x97,0xa1,0x8e,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x74,0x8c,0x9f,0x98,0x84,0x71,0x5c,0x46,0x30,0x19,0x04,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x74,0x8a,0x98,0x9f,0x98,0x8e,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8e,0x98,0x9f,0x9c,0x8c,0x7b,0x65,0x4e + ,0x36,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x8c,0x8c,0x94,0xa6,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa6,0x94,0x8c,0x8c,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a + ,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2f,0x40,0x51,0x62,0x71,0x7b,0x84,0x8c,0x8c,0x90,0x8c,0x8c,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x13,0x2a,0x43,0x5b,0x73,0x8c,0x98,0x95,0x7f,0x67,0x4f + ,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2f,0x3c,0x49,0x57,0x61,0x67,0x67,0x71,0x73,0x71,0x67,0x65,0x5c,0x57,0x4c,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x25,0x38,0x46 + ,0x4e,0x4f,0x4f,0x4f,0x4f,0x4b,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x38,0x46,0x4e,0x4b,0x41,0x36,0x2b,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0b,0x16,0x21,0x28,0x30,0x36,0x37,0x37,0x37,0x37,0x37,0x34,0x2c + ,0x28,0x21,0x19,0x10,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x19,0x1e,0x1e,0x1e,0x1e,0x1c,0x1d,0x25,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x10,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02 + ,0x0b,0x15,0x1d,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1e,0x19,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x04,0x10,0x19,0x21,0x28,0x2a,0x2a,0x2a,0x28,0x21,0x1b,0x1e,0x1e,0x1e,0x1e,0x1e,0x19,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x02,0x15,0x2c + ,0x43,0x5a,0x71,0x84,0x8e,0x8c,0x84,0x84,0x8c,0x94,0xa4,0xab,0x9c,0x8a,0x73,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x3c,0x51,0x62,0x72,0x84,0x94,0x98,0x8c,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x7f + ,0x8c,0x98,0x8c,0x7b,0x6a,0x5a,0x49,0x36,0x21,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x21,0x37,0x4e,0x65,0x7b,0x8a,0x8c,0x8c,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8a,0x8c + ,0x8a,0x7b,0x66,0x51,0x3c,0x26,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x41,0x57,0x6a,0x7b,0x84,0x8e,0x97,0x98,0x98,0x98,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f + ,0x95,0x98,0x98,0x97,0x8e,0x8a,0x7b,0x6a,0x5a,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x95,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x95,0x98,0x98 + ,0x98,0x98,0x98,0x98,0x98,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2f,0x40,0x51,0x5c,0x66,0x71,0x73,0x74,0x7f,0x74,0x73,0x71,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12 + ,0x2a,0x42,0x5a,0x71,0x7f,0x7f,0x7f,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x27,0x36,0x41,0x4b,0x4f,0x51,0x5a,0x5b,0x5a,0x51,0x4e,0x46,0x40,0x36,0x2b,0x1e,0x0c,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x16,0x25,0x30,0x36,0x37,0x37,0x37,0x37,0x34,0x2b,0x1e,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x25,0x30,0x36,0x34,0x2b,0x21,0x16,0x0b,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0a + ,0x11,0x19,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1c,0x15,0x11,0x0a,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x06,0x06,0x06,0x06,0x05,0x06,0x0e,0x12,0x12,0x12,0x12,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x0e,0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x0a,0x11,0x12,0x12,0x12,0x11,0x0a,0x05,0x06,0x06,0x06,0x06,0x06,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c + ,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x74,0x8c,0xa0,0xa2,0x99,0x99,0xa2,0xa6,0xa7,0x9c,0x8c,0x7b,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x51,0x62,0x72,0x84,0x84,0x7b,0x6a,0x5a,0x46,0x30 + ,0x19,0x04,0x00,0x00,0x0e,0x25,0x3c,0x51,0x61,0x6b,0x7b,0x88,0x7b,0x6a,0x5a,0x49,0x38,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5a,0x6a,0x73,0x73,0x73,0x71,0x61,0x4b,0x34,0x1c,0x05 + ,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x6a,0x5a,0x46,0x31,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x21,0x36,0x49,0x5a,0x66,0x71,0x7b,0x7f,0x7f,0x7f,0x7f,0x7f,0x71,0x5a,0x42 + ,0x2a,0x12,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x7f,0x7f,0x7f,0x7f,0x7b,0x73,0x6a,0x5a,0x49,0x38,0x25,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x71,0x5a,0x42,0x2a,0x12,0x00 + ,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2f,0x3c,0x46,0x51,0x5a,0x5b,0x61,0x67,0x61,0x5b,0x5a,0x51,0x40,0x2b,0x15 + ,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x61,0x67,0x67,0x67,0x65,0x5a,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x14,0x21,0x2b,0x34,0x37,0x3c,0x42,0x43,0x42,0x3c,0x36,0x30 + ,0x28,0x21,0x16,0x0a,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x19,0x1e,0x1e,0x1e,0x1e,0x1e,0x1c,0x15,0x0a,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x19,0x1e,0x1c,0x15,0x0b,0x03,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x97,0x9d,0xa4,0xa4,0xa2,0x99,0x93,0x8a,0x7b,0x6a,0x5a,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2f + ,0x40,0x51,0x62,0x71,0x71,0x66,0x5a,0x49,0x38,0x25,0x10,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x4c,0x5a,0x6a,0x73,0x6a,0x5a,0x49,0x38,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x25,0x38,0x49 + ,0x57,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x2b,0x15,0x02,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x57,0x49,0x38,0x25,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x38,0x46,0x51 + ,0x5c,0x65,0x67,0x67,0x67,0x67,0x67,0x61,0x51,0x3c,0x25,0x0e,0x00,0x00,0x04,0x19,0x30,0x46,0x5a,0x65,0x67,0x67,0x67,0x67,0x65,0x5c,0x57,0x49,0x38,0x27,0x16,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5a,0x65,0x67,0x67,0x67,0x67,0x67 + ,0x67,0x67,0x67,0x67,0x61,0x51,0x3c,0x25,0x0e,0x00,0x00,0x04,0x19,0x30,0x46,0x5a,0x65,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x61,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x26,0x31,0x3c,0x42 + ,0x43,0x4b,0x4f,0x4b,0x43,0x42,0x3c,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x4b,0x4f,0x4f,0x4f,0x4e,0x46,0x38,0x25,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0b + ,0x15,0x1c,0x1e,0x25,0x2a,0x2a,0x2a,0x25,0x1e,0x19,0x11,0x0a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa1,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x7b,0x7f,0x8a,0x8c,0x8c,0x8c,0x84,0x7f,0x74,0x6a,0x5a,0x49,0x38,0x27,0x14,0x02,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2f,0x40,0x51,0x5a,0x5a,0x51,0x46,0x38,0x27,0x16,0x04,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2b,0x38,0x49,0x57,0x5b,0x57,0x49,0x38,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x16,0x27,0x36,0x40,0x43,0x43,0x43,0x42,0x3c,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x40,0x36,0x27,0x16,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x25,0x31,0x3c,0x46,0x4e,0x4f,0x4f,0x4f,0x4f,0x4f,0x4b,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x10,0x25,0x38,0x46,0x4e,0x4f,0x4f,0x4f,0x4f,0x4e,0x46,0x40,0x36,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x10,0x25,0x38,0x46,0x4e,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4b,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x10,0x25,0x38,0x46,0x4e,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4b,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x06,0x10,0x1b,0x25,0x2a,0x2c,0x34,0x37,0x34,0x2c,0x2a,0x25,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2b,0x34,0x37,0x37,0x37,0x36,0x30,0x25,0x16,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x05,0x07,0x0e,0x12,0x12,0x12,0x0e,0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x89,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5c,0x65,0x6b,0x73,0x73,0x73,0x73,0x71 + ,0x67,0x61,0x57,0x49,0x38,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2f,0x3c,0x42,0x42,0x3c,0x31,0x25,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x01,0x0a,0x17,0x27,0x36,0x40,0x43,0x40,0x36,0x27,0x16,0x05,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x1b,0x26,0x30,0x36,0x37,0x37,0x37,0x37,0x37,0x34,0x2b,0x1e,0x0c,0x00,0x00,0x00,0x00,0x04,0x16,0x25,0x30,0x36,0x37,0x37,0x37,0x37,0x36,0x30,0x28,0x21,0x14,0x05 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x16,0x25,0x30,0x36,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x34,0x2b,0x1e,0x0c,0x00,0x00,0x00,0x00,0x04,0x16,0x25,0x30,0x36,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x34,0x2b,0x1e,0x0c + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x15,0x1c,0x1e,0x1c,0x15,0x12,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0a,0x15,0x1c,0x1e,0x1e,0x1e,0x1e,0x19,0x10 + ,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x0a,0x1e + ,0x2f,0x3c,0x46,0x4e,0x57,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x4b,0x41,0x36,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x25,0x1b,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21 + ,0x28,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12,0x12,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12 + ,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x10,0x19,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1c,0x15,0x0a,0x01,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x19,0x1e + ,0x1e,0x1e,0x1e,0x1e,0x1e,0x19,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x19,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1c,0x15,0x0a,0x01,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x19,0x1e,0x1e,0x1e,0x1e + ,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1c,0x15,0x0a,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x5b + ,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x01,0x0c,0x1b,0x26,0x30,0x37,0x40,0x43,0x43,0x43,0x43,0x42,0x3c,0x34,0x2b,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x0e,0x06,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x02,0x14,0x27,0x36,0x40,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x06,0x10,0x19,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1d,0x15,0x0b,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x0a,0x11,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x0a,0x11,0x12,0x12,0x12,0x11,0x0a,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x0a,0x11,0x12,0x12,0x12,0x12,0x11,0x0a,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12,0x12,0x12,0x0e + ,0x06,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x04,0x06,0x06,0x06,0x06,0x05,0x06,0x0e,0x12,0x12,0x12,0x12,0x11,0x0a,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x05,0x0a,0x11,0x12,0x12,0x12,0x12,0x11,0x0a,0x04,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x0e,0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0a,0x11,0x12,0x12,0x12,0x12,0x0e,0x06,0x06,0x06,0x06,0x06,0x06,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x06,0x0a,0x11,0x12,0x11,0x0a,0x06 + ,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12,0x12 + ,0x12,0x11,0x0a,0x02,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x06,0x06,0x06,0x06,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12 + ,0x12,0x12,0x12,0x12,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x19,0x21,0x28,0x2a,0x2a,0x2a,0x28,0x21,0x19,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a + ,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x10,0x19,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x19,0x10,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x0c,0x02,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0a,0x15,0x1d,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1d,0x15,0x0b,0x02,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x19,0x1e,0x1e,0x1e,0x1e,0x1c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x19,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0a,0x15,0x1c,0x21,0x28,0x2a,0x2a + ,0x2a,0x2a,0x28,0x21,0x19,0x10,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0b,0x15,0x1d,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1e,0x19,0x10,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a + ,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0b,0x16,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x25,0x1d,0x1e,0x1e,0x1e,0x1e,0x1e,0x19,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x06,0x10,0x19,0x1e,0x21,0x28,0x2a,0x28,0x21,0x1e,0x19,0x10,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25 + ,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00 + ,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x0c,0x1b,0x25,0x2a,0x2a + ,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x10,0x19,0x1e,0x1e,0x1e,0x1e,0x19,0x10,0x06,0x00,0x00,0x00,0x00,0x04,0x06,0x06,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a + ,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x25,0x30,0x37,0x40,0x43,0x43,0x43,0x40,0x37,0x30,0x25,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x1b,0x26,0x30,0x37,0x40,0x43,0x43,0x43,0x43,0x40,0x37,0x30 + ,0x26,0x1b,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x36,0x40,0x43,0x43,0x43,0x43,0x42,0x3c,0x2f,0x1e,0x10,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x1e,0x2b,0x34,0x3c,0x42 + ,0x43,0x43,0x43,0x42,0x3c,0x34,0x2b,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x16,0x25,0x30,0x36,0x37,0x37,0x37,0x34,0x31,0x3c,0x42,0x43,0x43,0x43,0x40,0x37,0x30,0x25,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x04,0x10,0x1e,0x2b,0x34,0x38,0x40,0x43,0x43,0x43,0x43,0x40,0x37,0x30,0x26,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0a,0x16,0x21,0x2b,0x34,0x3c,0x42,0x43,0x43,0x43,0x42,0x3c,0x36,0x30,0x26,0x1b,0x0d,0x02,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x2b,0x36,0x40,0x43,0x43,0x43,0x42,0x3c,0x33,0x36,0x37,0x37,0x37,0x36,0x30 + ,0x25,0x16,0x04,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x1b,0x26,0x30,0x36,0x38,0x40,0x43,0x40,0x38,0x36,0x30,0x26,0x1b,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x43,0x42,0x3c,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x36,0x40,0x43,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x0a,0x1e,0x2f,0x3c,0x42 + ,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x02,0x14,0x27,0x36,0x40,0x43,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x16,0x14,0x27,0x36,0x40,0x43,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43 + ,0x43,0x43,0x40,0x36,0x27,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x42,0x3c,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x26,0x30,0x36,0x37,0x37,0x36,0x30,0x26,0x1b,0x10,0x04,0x04,0x10,0x19,0x1e,0x1e,0x19,0x10,0x04,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x42,0x3c,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x27,0x38,0x46,0x4e,0x57,0x5b,0x5b,0x5b,0x57,0x4e,0x46,0x38,0x27 + ,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x25,0x31,0x3c + ,0x46,0x4e,0x57,0x5b,0x5b,0x5b,0x5b,0x57,0x4e,0x46,0x3c,0x31,0x25,0x16,0x05,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x2f,0x1e,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x05,0x16,0x25,0x31,0x40,0x4b,0x51,0x5a,0x5b,0x5b,0x5b,0x5a,0x51,0x4b,0x41,0x36,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x25,0x38,0x46,0x4e,0x4f,0x4f,0x4f,0x4b,0x46,0x51,0x5a,0x5b,0x5b,0x5b,0x57,0x4e,0x46,0x38,0x27,0x16,0x05 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x25,0x31,0x40,0x4b,0x4f,0x57,0x5b,0x5b,0x5b,0x5b,0x57,0x4e,0x46,0x3c,0x2f,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2b,0x36,0x41,0x4b,0x51,0x5a,0x5b,0x5b,0x5b,0x5a,0x51 + ,0x4e,0x46,0x3c,0x2f,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x27,0x36,0x41,0x4c,0x57,0x5b,0x5b + ,0x5b,0x5a,0x51,0x49,0x4e,0x4f,0x4f,0x4f,0x4e,0x46,0x38,0x25,0x10,0x00,0x00,0x00,0x00,0x05,0x16,0x25,0x31,0x3c,0x46,0x4e,0x4f,0x57,0x5b,0x57,0x4f,0x4e,0x46,0x3c,0x31,0x25,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b + ,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x2b,0x16,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x5b,0x5b + ,0x57,0x49,0x36,0x21,0x0a,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x38,0x25,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00 + ,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x2b,0x15,0x02,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2f,0x3c,0x46,0x4e,0x4f,0x4f,0x4e,0x46,0x3c,0x31,0x25,0x16,0x16,0x25 + ,0x30,0x36,0x36,0x30,0x25,0x16,0x05,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x2b,0x15,0x02,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x38,0x49,0x5a + ,0x65,0x6b,0x73,0x73,0x73,0x6b,0x65,0x5a,0x49,0x38,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x05,0x16,0x27,0x38,0x46,0x51,0x5c,0x65,0x6b,0x73,0x73,0x73,0x73,0x6b,0x65,0x5c,0x51,0x46,0x38,0x27,0x16,0x04,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x73,0x73,0x71,0x62,0x51,0x3c,0x27,0x34,0x4b,0x61,0x71,0x73,0x73,0x73 + ,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x27,0x38,0x46,0x52,0x61,0x67,0x71,0x73,0x73,0x73,0x71,0x67,0x61,0x57,0x49,0x38,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5a,0x65,0x67,0x67,0x67,0x61,0x5c,0x66,0x71 + ,0x73,0x73,0x73,0x6b,0x65,0x5a,0x49,0x38,0x27,0x16,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x27,0x38,0x46,0x52,0x61,0x67,0x6b,0x73,0x73,0x73,0x73,0x6b,0x65,0x5c,0x51,0x40,0x2f,0x1e,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2f,0x40 + ,0x4c,0x57,0x61,0x67,0x71,0x73,0x73,0x73,0x71,0x67,0x65,0x5c,0x51,0x41,0x36,0x27,0x16,0x04,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x04,0x16,0x27,0x38,0x49,0x57,0x61,0x6b,0x73,0x73,0x73,0x71,0x66,0x5e,0x65,0x67,0x67,0x67,0x65,0x5a,0x46,0x30,0x19,0x00,0x00,0x00,0x04,0x16,0x27,0x38,0x46,0x51,0x5c,0x65,0x67,0x6b,0x73,0x6b,0x67,0x65,0x5c,0x51,0x46,0x38,0x27,0x14,0x02,0x00,0x00,0x00 + ,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1d,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x73,0x71,0x61,0x4c,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x73,0x73,0x73,0x6a,0x5a,0x46,0x31,0x2b,0x41,0x57,0x6a,0x73 + ,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x73,0x6a,0x57,0x41,0x36,0x4c,0x61,0x71,0x73,0x73,0x73,0x73,0x71,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2f,0x40,0x51,0x5c,0x65 + ,0x67,0x67,0x65,0x5c,0x51,0x46,0x38,0x25,0x27,0x38,0x46,0x4e,0x4e,0x46,0x38,0x27,0x16,0x05,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x71,0x61,0x4b,0x34,0x1c,0x05,0x00 + ,0x00,0x00,0x00,0x00,0x0b,0x21,0x36,0x49,0x5a,0x6a,0x7b,0x7f,0x8a,0x8c,0x8a,0x7f,0x7b,0x6a,0x5a,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x27,0x38,0x49,0x5a,0x66,0x71,0x7b,0x7f,0x8a,0x8c,0x8c,0x8a,0x7f,0x7b,0x71,0x66,0x5a,0x49,0x38,0x25,0x10,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x82,0x8c,0x8c,0x8c,0x84,0x71 + ,0x5c,0x46,0x30,0x3c,0x51,0x67,0x7f,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x38,0x49,0x5a,0x66,0x72,0x7f,0x84,0x8c,0x8c,0x8c,0x84,0x7f,0x74,0x6a,0x5a,0x49,0x38,0x27,0x16,0x04,0x00,0x00,0x00,0x00,0x06,0x1e,0x36 + ,0x4e,0x65,0x7b,0x7f,0x7f,0x7f,0x72,0x71,0x7b,0x84,0x8c,0x8c,0x8a,0x7f,0x7b,0x6a,0x5a,0x49,0x38,0x25,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x27,0x38,0x49,0x5a,0x66,0x72,0x7f,0x7f,0x8a,0x8c,0x8c,0x8a,0x7f,0x7b,0x71,0x62,0x51,0x40,0x2f,0x1b + ,0x06,0x00,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x51,0x61,0x6b,0x74,0x7f,0x84,0x8c,0x8c,0x8c,0x84,0x7f,0x7b,0x71,0x62,0x57,0x49,0x38,0x25,0x10,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x25,0x38,0x49,0x5a,0x6a,0x74,0x7f,0x8a,0x8c,0x8c,0x84,0x7b,0x71,0x7b,0x7f,0x7f,0x7f,0x7b,0x65,0x4e,0x36,0x1e,0x00,0x00,0x00,0x10,0x25,0x38,0x49,0x5a,0x66,0x71,0x7b,0x7f,0x7f,0x88,0x7f,0x7f,0x7b + ,0x71,0x66,0x5a,0x49,0x36,0x21,0x0b,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x67,0x7f,0x8c,0x8c,0x8c,0x8c,0x8c,0x7f,0x6b,0x57,0x40 + ,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x87,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x82,0x8c,0x8c,0x8c + ,0x8a,0x7b,0x66,0x51,0x3c,0x34,0x4b,0x61,0x74,0x89,0x8c,0x8c,0x8c,0x87,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x89,0x8c,0x8c,0x8c,0x89,0x74,0x61,0x4c,0x41,0x57,0x6b,0x7f,0x8c,0x8c,0x8c,0x8a,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00 + ,0x00,0x00,0x06,0x1b,0x2f,0x40,0x51,0x62,0x71,0x7b,0x7f,0x7f,0x7b,0x71,0x66,0x5a,0x46,0x31,0x38,0x49,0x5a,0x65,0x65,0x5a,0x49,0x38,0x27,0x14,0x02,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c + ,0x8c,0x8c,0x8c,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x41,0x57,0x6a,0x7b,0x8c,0x97,0x9c,0x9e,0x9c,0x97,0x8c,0x7b,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0xa1 + ,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x05,0x06,0x06,0x06,0x06,0x06,0x05,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x38,0x49,0x5a,0x6a,0x7b,0x84,0x8e,0x97,0x9d,0xa4,0xa4,0x9d,0x97,0x8e,0x84,0x7b,0x6a,0x5a,0x46,0x30,0x19,0x04,0x00,0x00,0x0e + ,0x25,0x3c,0x51,0x67,0x7f,0x93,0xa1,0xa1,0x8e,0x7b,0x65,0x4e,0x37,0x43,0x5a,0x71,0x84,0x99,0xa2,0x98,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x00,0x0b,0x21,0x36,0x49,0x5a,0x6a,0x7b,0x84,0x93,0x99,0xa2,0xa4,0xa2,0x99,0x93,0x8a,0x7b,0x6a,0x5a,0x49 + ,0x38,0x25,0x10,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x95,0x98,0x92,0x7f,0x84,0x8e,0x98,0xa2,0xa4,0x9d,0x97,0x8c,0x7b,0x6a,0x5a,0x46,0x31,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x38,0x49,0x5a,0x6a,0x7b,0x84,0x93,0x98,0x9d,0xa4 + ,0xa4,0x9d,0x97,0x8e,0x84,0x72,0x62,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x10,0x26,0x3c,0x51,0x62,0x72,0x7f,0x8a,0x93,0x99,0xa2,0xa4,0xa2,0x99,0x97,0x8e,0x84,0x74,0x6a,0x5a,0x46,0x30,0x19,0x04,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0xa1 + ,0x8c,0x73,0x5b,0x43,0x2a,0x15,0x12,0x12,0x11,0x0a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x31,0x46,0x5a,0x6a,0x7b,0x8a,0x93,0x9d,0xa4,0xa2,0x98,0x8e,0x84,0x7f,0x95,0x98,0x95,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x04,0x19,0x30,0x46,0x5a + ,0x6a,0x7b,0x84,0x8e,0x97,0x98,0x9a,0x98,0x97,0x8e,0x84,0x7b,0x6a,0x57,0x41,0x2b,0x16,0x03,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71 + ,0x84,0x99,0xa4,0xa4,0xa4,0x9d,0x8a,0x73,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x98,0xa4,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x1e,0x21,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x9f,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00 + ,0x00,0x0e,0x25,0x3c,0x51,0x66,0x7b,0x8e,0x9f,0xa4,0x98,0x84,0x71,0x5a,0x43,0x3c,0x51,0x67,0x7f,0x93,0xa2,0xa1,0x93,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x71,0x84,0x98,0xa2,0xa2,0x93,0x7f,0x6b,0x57,0x4c,0x61,0x74,0x8a,0x9d + ,0xa4,0x9b,0x8a,0x74,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x00,0x10,0x26,0x3c,0x51,0x62,0x72,0x84,0x8e,0x97,0x97,0x8e,0x84,0x7b,0x66,0x52,0x40,0x49,0x5a,0x6a,0x7b,0x7b,0x6a,0x5a,0x49,0x36,0x21,0x0a,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0xa4 + ,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x74,0x8a,0x9c,0xa2,0x94,0x8c,0x94,0xa2,0x9c,0x8a,0x73,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x18,0x1c,0x1e,0x1e,0x1e,0x1e,0x1e,0x1c,0x15,0x0a,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x21,0x36,0x49,0x5a,0x6a,0x7b,0x8c,0x98,0xa3,0xaa,0xa6,0xa4,0xa4,0xa4,0xa7,0xa3,0x98 + ,0x8c,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x06,0x1d,0x34,0x4b,0x61,0x74,0x8a,0x9d,0xaa,0x97,0x7f,0x6b,0x57,0x41,0x4b,0x61,0x74,0x8c,0xa2,0xa4,0x8e,0x7b,0x66,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x03,0x16,0x2b,0x41,0x57,0x6a,0x7b,0x8c,0x98,0xa4,0xa9 + ,0xa4,0xa4,0xa4,0xa9,0xa8,0x9c,0x8c,0x7b,0x6a,0x5a,0x46,0x31,0x1b,0x06,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xab,0x9d,0x8e,0x94,0x9e,0xa2,0xa4,0xa4,0xab,0xac,0x9c,0x8c,0x7b,0x66,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x0b,0x21,0x36 + ,0x49,0x5a,0x6a,0x7b,0x8c,0x98,0xa4,0xab,0xa6,0xa4,0xa4,0xa4,0xa7,0xa3,0x94,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x06,0x1b,0x31,0x46,0x5c,0x71,0x84,0x93,0x9d,0xa7,0xa6,0xa4,0xa4,0xa4,0xa6,0xa9,0xa3,0x94,0x8a,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00 + ,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2d,0x2a,0x2a,0x2a,0x28,0x21,0x16,0x0a,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x26,0x3c,0x51,0x66,0x7b,0x8c,0x9c,0xa8,0xab,0xa4,0xa4,0xa2,0x9e,0x94,0x8e,0x9d,0xab,0x98,0x7f,0x67 + ,0x4f,0x37,0x1e,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8c,0x98,0xa1,0xa3,0xa4,0xa4,0xa6,0xaa,0xa3,0x98,0x8a,0x74,0x61,0x4c,0x36,0x21,0x0a,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x73,0x8c,0xa2,0xb0,0xb0,0xb1,0xa4,0x8e,0x7b,0x65,0x4e,0x36,0x1e,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x38,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x37,0x37,0x37,0x3a,0x4f,0x67,0x7f + ,0x98,0xaa,0x99,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x06,0x1b,0x31,0x46,0x5c,0x71,0x84,0x98,0xac,0xa2,0x8c,0x74,0x61,0x4c,0x46,0x5c,0x71,0x84,0x99,0xac,0x9d,0x8a,0x74,0x61,0x4c,0x36,0x21,0x0a,0x00,0x00,0x00,0x10,0x26,0x3c,0x51,0x66,0x7b,0x8e,0xa3 + ,0xaf,0x9d,0x8a,0x74,0x61,0x57,0x6b,0x7f,0x93,0xa8,0xa4,0x93,0x7f,0x6b,0x57,0x41,0x2b,0x15,0x02,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x71,0x84,0x94,0x9a,0x8e,0x8e,0x9a,0x97,0x84,0x72,0x61,0x4e,0x5a,0x6a,0x7b,0x8c,0x8c,0x7b,0x6a,0x57,0x40,0x28,0x11,0x00 + ,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0xa4,0xa4,0xa4,0xa4,0xae,0xb8,0xb8,0xae,0xa4,0xa4,0xa4,0xa4,0xa4,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x93,0xa5,0x98,0x84,0x76,0x84,0x98,0xa3,0x8e,0x7b,0x65 + ,0x4e,0x36,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2b,0x2b,0x34,0x37,0x37,0x37,0x37,0x37,0x34,0x2b,0x1e,0x0c,0x00,0x00,0x00,0x00,0x00,0x03,0x16,0x2b,0x41,0x57,0x6a,0x7b,0x8c,0x9c + ,0xaa,0xa8,0x9d,0x93,0x8c,0x8c,0x8e,0x98,0xa0,0x94,0x84,0x72,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x02,0x15,0x2b,0x41,0x57,0x6b,0x7f,0x93,0xa6,0x9d,0x8a,0x74,0x61,0x4b,0x51,0x67,0x7f,0x93,0xa6,0x9d,0x8a,0x73,0x5c,0x46,0x31,0x1b,0x06,0x00,0x00,0x00,0x0a + ,0x21,0x36,0x4c,0x61,0x74,0x8a,0x9c,0xac,0xab,0x9c,0x8e,0x8c,0x8e,0x98,0xa4,0xab,0x9c,0x8c,0x7b,0x66,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xad,0x9f,0x98,0x8e,0x8c,0x8c,0x8e,0x9c,0xad,0xac,0x98,0x84,0x71,0x5a,0x43 + ,0x2c,0x15,0x02,0x00,0x00,0x00,0x03,0x16,0x2b,0x41,0x57,0x6a,0x7b,0x8c,0x9c,0xaa,0xa8,0x9d,0x93,0x8c,0x8c,0x8e,0x98,0x9f,0x8e,0x7b,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x66,0x7b,0x8e,0xa3,0xaf,0xa4,0x94,0x8c,0x8c,0x8c,0x93,0x99 + ,0xa3,0x98,0x84,0x72,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x44,0x42,0x43,0x43,0x43,0x40,0x36,0x2b,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x71,0x84,0x98,0xac,0xad,0x9c,0x8e + ,0x8c,0x8c,0x8e,0x98,0x9f,0xae,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8c,0x9c,0x98,0x8e,0x8c,0x8c,0x93,0x9d,0xac,0xa8,0x93,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xae,0xa2 + ,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x37,0x4e,0x65,0x7b,0x8e,0xa3,0x9d,0x98,0x9d,0xa8,0x97,0x7f,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x97,0xad,0xa4,0x8c + ,0x74,0x61,0x4f,0x4f,0x4f,0x4f,0x4e,0x51,0x67,0x7f,0x98,0xaa,0x98,0x7f,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x10,0x26,0x3c,0x51,0x66,0x7b,0x8e,0xa3,0xa8,0x93,0x7f,0x6b,0x57,0x4e,0x65,0x7b,0x8e,0xa3,0xa8,0x93,0x7f,0x6b,0x57,0x41,0x2b,0x16,0x03,0x00 + ,0x00,0x00,0x06,0x1b,0x31,0x46,0x5c,0x71,0x84,0x94,0xa8,0xa8,0x93,0x7f,0x6b,0x61,0x74,0x8a,0x9d,0xaa,0x98,0x84,0x72,0x61,0x4c,0x36,0x21,0x0b,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8e,0x9b,0x8c,0x7b,0x7b,0x8c,0x9b,0x93,0x7f,0x67,0x56,0x66,0x7b + ,0x8c,0x9c,0x98,0x88,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x8c,0x8c,0x8e,0x9d,0xb3,0xb3,0x9d,0x8e,0x8c,0x8c,0x8c,0x8c,0x8c,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98 + ,0xa4,0x8e,0x7b,0x6b,0x7b,0x8e,0xa3,0x97,0x7f,0x67,0x4f,0x37,0x1e,0x09,0x05,0x02,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x32,0x40,0x4b,0x4f,0x4f,0x4f,0x4f,0x4f,0x4b,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00 + ,0x00,0x0a,0x21,0x36,0x4c,0x61,0x74,0x8a,0x9c,0xab,0xa4,0x94,0x8a,0x7f,0x74,0x73,0x7b,0x84,0x8e,0x84,0x72,0x62,0x51,0x40,0x2b,0x15,0x02,0x00,0x00,0x00,0x0b,0x21,0x36,0x4c,0x61,0x74,0x8a,0x9d,0xa6,0x93,0x7f,0x67,0x51,0x5a,0x71,0x84,0x99,0xa9,0x97,0x7f + ,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x93,0xa8,0xae,0x9c,0x8c,0x7b,0x73,0x7b,0x84,0x94,0xa8,0xac,0x98,0x84,0x71,0x5a,0x43,0x2c,0x15,0x02,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa8,0x94,0x84,0x7b,0x73 + ,0x73,0x7b,0x8c,0x9d,0xb0,0xa2,0x8c,0x74,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x00,0x0a,0x21,0x36,0x4c,0x61,0x74,0x8a,0x9c,0xad,0xa8,0x94,0x8a,0x7f,0x74,0x73,0x7b,0x84,0x90,0x84,0x71,0x5c,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84 + ,0x98,0xad,0xa8,0x94,0x84,0x74,0x73,0x74,0x7f,0x84,0x8e,0x8c,0x7b,0x66,0x52,0x40,0x2b,0x15,0x02,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x51,0x5a,0x5b,0x5b,0x5b,0x57,0x4c,0x40,0x2f,0x1e,0x0d,0x01,0x00,0x00,0x00,0x0a,0x21 + ,0x37,0x4e,0x65,0x7b,0x8e,0xa3,0xb0,0x9d,0x8c,0x7b,0x73,0x73,0x7b,0x84,0x99,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x04,0x19,0x30,0x46,0x5a,0x6a,0x7b,0x8c,0x84,0x7b,0x73,0x74,0x7f,0x8e,0xa3,0xb0,0x9d,0x8a,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00 + ,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xaa,0x99,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x97,0xa3,0x8e,0x7f,0x8e,0xa4,0x99,0x84,0x71,0x5a,0x43,0x2c,0x15,0x02,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8e,0xa4,0xa8,0x93,0x7f,0x67,0x61,0x67,0x67,0x67,0x65,0x5f,0x71,0x84,0x99,0xaa,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x07,0x00,0x00,0x00,0x06,0x1b,0x31,0x46,0x5c,0x71,0x84,0x98,0xaa,0x9d,0x8a,0x73,0x5c,0x57,0x6b,0x7f,0x97,0xaa + ,0x9d,0x8a,0x74,0x61,0x4c,0x36,0x21,0x0b,0x00,0x00,0x00,0x00,0x00,0x10,0x26,0x3c,0x51,0x62,0x74,0x8a,0x9d,0xad,0x9d,0x8a,0x74,0x69,0x7f,0x93,0xa8,0xa3,0x8e,0x7b,0x66,0x52,0x40,0x2b,0x16,0x03,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x97,0x98,0x7f + ,0x6b,0x6b,0x7f,0x98,0x98,0x7f,0x67,0x62,0x72,0x84,0x98,0x9c,0x8c,0x7b,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x73,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x73,0x73,0x73,0x73,0x73,0x71,0x61,0x4b,0x34,0x1c,0x05,0x00 + ,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x8c,0x73,0x68,0x7f,0x93,0xa2,0x93,0x7f,0x67,0x4f,0x37,0x21,0x1e,0x1c,0x15,0x0a,0x01,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x40,0x51,0x61,0x67,0x67,0x67 + ,0x67,0x67,0x61,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x93,0xa8,0xad,0x98,0x84,0x74,0x6b,0x61,0x5c,0x66,0x71,0x7b,0x72,0x62,0x51,0x40,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x03,0x16,0x2b,0x41,0x57,0x6b,0x7f,0x97,0xa9,0x99 + ,0x84,0x71,0x5a,0x61,0x74,0x8c,0xa2,0xa3,0x8e,0x7b,0x65,0x4e,0x37,0x21,0x0a,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x73,0x8a,0x9d,0xb0,0xa3,0x8e,0x7b,0x6a,0x5e,0x66,0x74,0x8a,0x9d,0xb0,0xa2,0x8c,0x74,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x06,0x1e,0x37 + ,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x74,0x66,0x5c,0x5c,0x6b,0x7f,0x98,0xb0,0xa8,0x93,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x93,0xa8,0xae,0x9c,0x8a,0x76,0x6b,0x61,0x5c,0x66,0x72,0x7f,0x72,0x62,0x51,0x3c,0x27,0x14 + ,0x02,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa2,0xb0,0x9d,0x8a,0x74,0x62,0x5b,0x61,0x67,0x71,0x7b,0x7b,0x6a,0x5a,0x46,0x31,0x1e,0x0a,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x63,0x67,0x71,0x73,0x73,0x73,0x6b,0x61 + ,0x51,0x40,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x97,0xad,0xa8,0x93,0x7f,0x6b,0x5c,0x5c,0x69,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x10,0x25,0x38,0x49,0x5a,0x6a,0x7b,0x72,0x66,0x5c,0x61,0x71,0x84,0x99 + ,0xae,0xa2,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xaa,0x98,0x7f,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x73,0x8a,0x9d,0xa2,0x8c,0x79,0x8c,0xa2,0xa2,0x8c,0x74,0x61 + ,0x4b,0x34,0x1d,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x71,0x7f,0x7f,0x7f,0x7b,0x66,0x73,0x8c,0xa2,0xab,0x97,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x10,0x26,0x3c,0x51,0x66,0x7b,0x8e + ,0xa3,0xa4,0x8e,0x7b,0x66,0x61,0x74,0x8a,0x9d,0xa6,0x93,0x7f,0x6b,0x57,0x41,0x2b,0x16,0x03,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x2f,0x41,0x57,0x6b,0x7f,0x93,0xa8,0xa8,0x93,0x7f,0x73,0x84,0x99,0xa9,0x98,0x84,0x71,0x5c,0x46,0x31,0x1e,0x0a,0x00,0x00,0x00 + ,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0x98,0x7f,0x67,0x67,0x7f,0x98,0x99,0x84,0x71,0x72,0x84,0x94,0x94,0x8a,0x7b,0x6a,0x5a,0x49,0x36,0x21,0x0a,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x5b + ,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x2b,0x15,0x02,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x8e,0x7b,0x72,0x84,0x99,0xa2,0x8c,0x74,0x61,0x4b,0x39,0x37,0x37,0x34,0x2b,0x1e,0x0c,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4 + ,0x8c,0x73,0x5b,0x47,0x51,0x62,0x72,0x7f,0x7f,0x7f,0x7f,0x7f,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x73,0x8a,0x9d,0xb0,0xa3,0x8e,0x7b,0x66,0x57,0x4c,0x46,0x51,0x5c,0x65,0x61,0x51,0x40,0x2f,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00 + ,0x00,0x0b,0x21,0x37,0x4e,0x65,0x7b,0x8e,0xa3,0xa2,0x8c,0x74,0x61,0x67,0x7f,0x93,0xa6,0x99,0x84,0x71,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8e,0xa4,0xb0,0x99,0x84,0x71,0x5c,0x4b,0x57,0x6b,0x7f,0x97,0xad,0xa8,0x93,0x7f + ,0x67,0x4f,0x38,0x21,0x0a,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x48,0x4f,0x67,0x7f,0x93,0xa8,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x02,0x15,0x2c,0x43,0x5b,0x73,0x8a,0x9d,0xb0,0xa3,0x8e,0x7b,0x6a,0x58,0x4c + ,0x46,0x52,0x61,0x67,0x61,0x51,0x41,0x34,0x25,0x16,0x04,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x99,0x84,0x72,0x62,0x5a,0x54,0x53,0x5c,0x65,0x65,0x5a,0x49,0x38,0x25,0x10,0x01,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4 + ,0x8c,0x74,0x74,0x7f,0x84,0x8c,0x8c,0x8a,0x7f,0x72,0x62,0x51,0x40,0x2b,0x16,0x03,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8a,0x9d,0xb1,0xa4,0x8c,0x74,0x61,0x4c,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x04,0x16,0x27,0x38 + ,0x49,0x5a,0x65,0x61,0x52,0x4b,0x5c,0x71,0x84,0x99,0xa9,0x98,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xaa,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x37,0x4e,0x65,0x7b,0x8e + ,0xa4,0x99,0x84,0x76,0x84,0x99,0xa6,0x93,0x7f,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x73,0x8c,0x98,0x95,0x7f,0x67,0x73,0x8c,0xa4,0xa4,0x8e,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00 + ,0x00,0x00,0x00,0x06,0x1b,0x31,0x46,0x5c,0x71,0x84,0x99,0xa9,0x98,0x84,0x71,0x6b,0x7f,0x93,0xa6,0x9d,0x8a,0x74,0x61,0x4c,0x36,0x21,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x21,0x36,0x4c,0x61,0x74,0x8a,0x9c,0xab,0x9d,0x8a,0x7c,0x8e,0xa3,0xa3,0x8e + ,0x7b,0x66,0x51,0x3c,0x26,0x10,0x01,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0x98,0x7f,0x67,0x67,0x7f,0x98,0x98,0x7f,0x73,0x84,0x94,0x94,0x84,0x74,0x6a,0x5a,0x49,0x38,0x27,0x14,0x02,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43 + ,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x43,0x43,0x43,0x42,0x3c,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x93,0xa5,0x97,0x7f,0x84,0x94,0xa0,0x94,0x84,0x71,0x5a,0x4f,0x4f,0x4f,0x4f,0x4b,0x40,0x2f,0x1b,0x06,0x00 + ,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x51,0x62,0x72,0x84,0x93,0x98,0x95,0x8b,0x7b,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8e,0xa4,0xb0,0x99,0x84,0x71,0x5c,0x46,0x36,0x31,0x3c,0x46,0x4e,0x4b + ,0x40,0x2f,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x71,0x84,0x98,0xa5,0x93,0x7f,0x67,0x6b,0x7f,0x98,0xa6,0x93,0x7f,0x67,0x51,0x3c,0x26,0x10,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x97,0xad,0xad,0x97,0x7f,0x67 + ,0x51,0x3f,0x4e,0x65,0x7b,0x8e,0xa4,0xb0,0x98,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x4b,0x61,0x74,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61 + ,0x74,0x8c,0xa4,0xb0,0x99,0x84,0x71,0x5c,0x4b,0x4e,0x4f,0x4f,0x53,0x55,0x53,0x4f,0x4e,0x46,0x38,0x25,0x10,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8a,0x9d,0xb0,0xa4,0x94,0x84,0x74,0x71,0x66,0x5c,0x53,0x53,0x4e,0x46,0x38,0x27,0x16,0x04,0x00,0x00,0x00 + ,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x7c,0x8a,0x93,0x99,0xa2,0xa4,0x9d,0x93,0x84,0x72,0x61,0x4c,0x36,0x21,0x0a,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67 + ,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x05,0x16,0x27,0x38,0x46,0x4e,0x4b,0x4b,0x5a,0x6a,0x7b,0x8e,0xa3,0xa3,0x8e,0x7b,0x66,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xaa,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x97,0xa7,0x97,0x7f,0x6d,0x7f,0x97,0xa9,0x99,0x84,0x71,0x5a,0x43,0x2c,0x15,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa2,0xae,0x98,0x7f,0x6c,0x7b,0x8e,0xa4,0x99,0x84,0x71,0x73,0x8c + ,0xa4,0xa4,0x8c,0x73,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x00,0x10,0x26,0x3c,0x51,0x67,0x7f,0x93,0xa8,0xa2,0x8c,0x74,0x73,0x8a,0x9d,0xa6,0x93,0x7f,0x6b,0x57,0x41,0x2b,0x16,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x16,0x2b,0x41,0x57,0x6a + ,0x7b,0x8e,0xa3,0xa8,0x94,0x8e,0x9c,0xa5,0x94,0x84,0x71,0x5c,0x46,0x31,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x93,0x99,0x84,0x72,0x72,0x84,0x99,0x93,0x7f,0x73,0x8a,0x94,0x84,0x72,0x62,0x57,0x49,0x38,0x27,0x16,0x05,0x00,0x00 + ,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x2a,0x2a,0x2a,0x25,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x74,0x8c,0xa2,0x9d,0x8e,0x94,0xa0,0x94,0x84,0x72,0x62,0x61 + ,0x67,0x67,0x67,0x67,0x61,0x51,0x3c,0x25,0x0e,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5c,0x62,0x72,0x84,0x94,0xa2,0x9c,0x8c,0x7b,0x6a,0x5a,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x97,0xad,0xa8,0x93 + ,0x7f,0x67,0x51,0x3c,0x26,0x1b,0x26,0x30,0x36,0x34,0x2b,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x26,0x3c,0x51,0x66,0x7b,0x8e,0xa4,0x99,0x84,0x71,0x73,0x8a,0x9d,0x9d,0x8a,0x74,0x61,0x4b,0x34,0x1d,0x06,0x00,0x00,0x00,0x00,0x07,0x1e + ,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8e,0x7b,0x65,0x4e,0x39,0x46,0x5c,0x73,0x8c,0xa4,0xb1,0x9d,0x8a,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x46,0x5c,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f + ,0x37,0x1e,0x06,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x93,0xa8,0xb0,0x98,0x7f,0x67,0x54,0x5a,0x65,0x67,0x67,0x67,0x67,0x67,0x67,0x65,0x5a,0x46,0x30,0x19,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x97,0xac,0xb3,0xa4,0x94,0x8c,0x84,0x7b,0x71,0x67 + ,0x61,0x57,0x49,0x3c,0x2f,0x1e,0x0c,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa8,0x94,0x8e,0x9b,0xa0,0xa4,0xa4,0xae,0xb1,0xa4,0x93,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b + ,0x43,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x25,0x31,0x3c,0x49,0x5a,0x6a,0x7b,0x8c,0x9c,0xa2,0x94,0x84,0x71,0x5c,0x46,0x31,0x1b,0x06,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x93,0xa6,0x98 + ,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2c,0x43,0x5b,0x73,0x8a,0x9d,0xa4,0x8e,0x7b,0x6b,0x7b,0x8e,0xa4,0xa2,0x8c,0x74,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x99,0xaa,0x98 + ,0x7f,0x6d,0x7f,0x97,0xad,0xa2,0x8c,0x73,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1d,0x34,0x4b,0x61,0x74,0x8a,0x9d,0xa6,0x93,0x7f,0x7b,0x8e,0xa4,0x9d,0x8a,0x74,0x61,0x4c,0x36,0x21,0x0b,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x0b,0x21,0x36,0x49,0x5c,0x71,0x84,0x98,0xab,0xa8,0xa4,0xab,0x9d,0x8a,0x74,0x62,0x51,0x3c,0x26,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x74,0x8a,0x9a,0x94,0x84,0x84,0x94,0x9a,0x8a,0x74,0x6a,0x7b,0x84,0x72 + ,0x62,0x51,0x41,0x36,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x12,0x12,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x1e,0x31,0x44,0x5a,0x71,0x84 + ,0x99,0xaa,0xa4,0xa1,0x94,0x84,0x72,0x62,0x5d,0x71,0x7f,0x7f,0x7f,0x7f,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x64,0x72,0x84,0x94,0xa4,0xa3,0x8e,0x7b,0x6a,0x5a,0x49,0x38,0x27,0x14,0x02,0x00,0x00,0x00 + ,0x0a,0x21,0x38,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x74,0x61,0x4b,0x34,0x1d,0x0a,0x10,0x19,0x1e,0x1c,0x15,0x0a,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x31,0x46,0x5c,0x73,0x8a,0x9d,0xa2,0x8c,0x74,0x7b,0x8e,0xa3,0x97,0x7f,0x6b,0x57 + ,0x41,0x2b,0x15,0x02,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5c,0x46,0x33,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43 + ,0x4e,0x65,0x7b,0x8e,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x58,0x6a,0x7b,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7b,0x65,0x4e,0x36,0x1e,0x00,0x00,0x00,0x0a,0x21,0x37,0x4e,0x65,0x7b + ,0x8c,0x9c,0xac,0xb2,0xa8,0xa2,0x98,0x8e,0x84,0x7f,0x74,0x6a,0x5c,0x51,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb5,0xa5,0x9b,0x93,0x8c,0x8c,0x8e,0x9c,0xae,0xb3,0x9d,0x8a,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a + ,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1b,0x31,0x46,0x5a,0x6a,0x7b,0x8c,0x9c,0xa2,0x94,0x84,0x72,0x62,0x51,0x3c,0x26,0x10,0x00,0x00,0x00 + ,0x00,0x05,0x1c,0x34,0x4b,0x61,0x74,0x8c,0xa4,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1d,0x34,0x4b,0x61,0x74,0x8c,0xa4,0xa2,0x8c,0x73,0x62,0x73,0x8c,0xa2,0xa8,0x93,0x7f,0x67,0x4f,0x38,0x21,0x0a,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x0e,0x25,0x3c,0x51,0x67,0x7f,0x98,0xaa,0x98,0x7f,0x6e,0x7f,0x98,0xad,0xa4,0x8e,0x7b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x41,0x57,0x6b,0x7f,0x93,0xa6,0x9d,0x8c,0x84,0x98,0xa5,0x93,0x7f + ,0x6b,0x57,0x41,0x2b,0x16,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x3c,0x51,0x66,0x7b,0x8e,0xa4,0xb9,0xb9,0xa8,0x93,0x7f,0x6b,0x57,0x41,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x41,0x57,0x6a,0x7b,0x8c,0x97 + ,0x98,0x98,0x97,0x8c,0x7b,0x6a,0x5d,0x6a,0x71,0x64,0x5b,0x51,0x4b,0x40,0x2f,0x1e,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x06,0x1b,0x2f,0x40,0x51,0x62,0x72,0x84,0x99,0xb0,0xb0,0x99,0x84,0x72,0x62,0x55,0x65,0x7b,0x8e,0x98,0x97,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x71,0x84,0x94,0xa4,0xa4,0x94,0x84,0x71 + ,0x5c,0x49,0x38,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2c,0x15,0x02,0x00,0x04,0x06,0x05,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x93 + ,0xa2,0x93,0x7f,0x7f,0x97,0xa3,0x8e,0x7b,0x65,0x4e,0x37,0x21,0x0b,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x99,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x31,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37 + ,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x47,0x52,0x67,0x7f,0x97,0xad,0xad,0x97,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x5b,0x73,0x8a,0x97,0x98,0x98,0x98,0x98,0x95,0x7f,0x67,0x4f,0x37 + ,0x1e,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5a,0x6a,0x7b,0x8c,0x98,0xa3,0xad,0xb0,0xad,0xa3,0x99,0x93,0x8a,0x7b,0x71,0x62,0x51,0x3c,0x26,0x10,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xae,0x9c,0x8c,0x7f,0x74,0x73,0x7b,0x8e,0xa3,0xb4,0xa4 + ,0x8c,0x73,0x5b,0x43,0x2c,0x15,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8a,0x9d,0xb1,0xa4,0x8c,0x74,0x61,0x4c,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x66,0x7b,0x8c,0x9c,0xa2,0x94,0x84 + ,0x72,0x62,0x51,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x02,0x15,0x2c,0x43,0x5b,0x73,0x8c,0xa4,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x67,0x7f,0x93,0xa6,0x99,0x84,0x71,0x60,0x71,0x84,0x99,0xaa,0x98,0x7f + ,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xaa,0x98,0x7f,0x73,0x8a,0x9b,0x99,0x9d,0x97,0x7f,0x73,0x8c,0xa4,0x9d,0x8a,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x21,0x36,0x4c,0x61 + ,0x74,0x8a,0x9d,0xaa,0x9d,0x99,0xa4,0x9d,0x8a,0x74,0x61,0x4c,0x36,0x21,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x25,0x38,0x4c,0x61,0x74,0x8c,0xa4,0xbc,0xbc,0xa4,0x8c,0x76,0x65,0x51,0x3c,0x26,0x12,0x01,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x0b,0x21,0x36,0x49,0x5a,0x6a,0x7b,0x84,0x8c,0x8c,0x84,0x7b,0x6a,0x5e,0x66,0x71,0x73,0x73,0x71,0x67,0x61,0x51,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f + ,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x26,0x3c,0x51,0x62,0x72,0x84,0x94,0xa4,0xae,0xaf,0x9d,0x8c,0x7b,0x6a,0x5c,0x6b,0x7f,0x97,0xa8,0x99,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4 + ,0x8c,0x74,0x7b,0x8e,0xa3,0xa4,0x94,0x84,0x72,0x62,0x51,0x3c,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x99,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2c,0x15,0x02,0x02,0x0a,0x11,0x12,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x0a,0x21,0x36,0x4c,0x61,0x74,0x8a,0x9d,0x99,0x84,0x8c,0x9d,0x9d,0x8a,0x73,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x99,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x31,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c + ,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x62,0x5b,0x62,0x72,0x84,0x99,0xb0,0xa4,0x8e,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x5b,0x73,0x8c + ,0xa4,0xaa,0xaa,0xae,0xad,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x10,0x25,0x38,0x49,0x5a,0x6a,0x7b,0x84,0x8e,0x97,0x9d,0xa8,0xb0,0xb0,0xa8,0x9c,0x8e,0x84,0x71,0x5c,0x46,0x31,0x1b,0x06,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4 + ,0x8e,0x7b,0x6b,0x61,0x5e,0x71,0x84,0x99,0xb0,0xa4,0x8c,0x74,0x61,0x4b,0x34,0x1c,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x98,0xb0,0xa8,0x93,0x7f,0x6b,0x5c,0x5c,0x6b,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x12 + ,0x2a,0x42,0x5a,0x71,0x84,0x98,0xa8,0x98,0x84,0x72,0x62,0x51,0x40,0x2f,0x1e,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa0,0x93,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2c,0x43,0x5a,0x71,0x84,0x99,0xaa + ,0x98,0x7f,0x6a,0x67,0x6a,0x7f,0x98,0xab,0x9d,0x8a,0x73,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x97,0xa8,0x98,0x7f,0x74,0x8c,0x98,0x84,0x8e,0x98,0x7f,0x74,0x8c,0xa4,0x98,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x03,0x16,0x2b,0x41,0x57,0x6b,0x7f,0x93,0xa8,0xb2,0xb0,0xab,0x97,0x7f,0x6b,0x57,0x41,0x2b,0x16,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x31,0x46,0x5a,0x6b,0x7f,0x93,0xa8,0xb0,0xb2,0xa8,0x94,0x84,0x71 + ,0x5c,0x46,0x31,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x38,0x49,0x5a,0x66,0x71,0x73,0x73,0x71,0x66,0x5e,0x6a,0x7b,0x84,0x8c,0x8c,0x84,0x7f,0x72,0x62,0x51,0x3c,0x26,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37 + ,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x71,0x84,0x94,0xa4,0xa4,0x99,0x9d,0xa9,0x9c,0x8a,0x76,0x6a,0x73,0x8a,0x9d,0xa6,0x93,0x7f,0x67,0x51,0x3c,0x25,0x0e,0x00 + ,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x7c,0x8c,0x9c,0xa9,0x99,0x84,0x72,0x62,0x51,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x74,0x61,0x4b,0x34,0x1d,0x0a,0x14,0x21,0x28,0x2a + ,0x25,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x16,0x2b,0x41,0x57,0x6b,0x7f,0x93,0xa1,0x99,0x9d,0xa5,0x93,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5c + ,0x46,0x33,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8e,0x7f,0x74,0x73,0x74,0x84,0x94,0xa4,0xb0,0x9d,0x8a,0x73,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67 + ,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x5b,0x73,0x8c,0x98,0x98,0x99,0xa4,0xae,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x04,0x16,0x27,0x38,0x49,0x5a,0x66,0x71,0x7b,0x7f,0x8a,0x93,0x9d,0xa8,0xb3,0xae,0xa1,0x8e,0x7b,0x66,0x51,0x3c,0x25,0x0e,0x00 + ,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5c,0x4c,0x51,0x67,0x7f,0x98,0xb0,0xa8,0x93,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x0a,0x21,0x38,0x4f,0x67,0x7f,0x93,0xa8,0xb1,0x9d,0x8c,0x7b,0x73,0x73,0x7b,0x8c,0x9d,0xb3,0xb0,0x98,0x7f,0x67 + ,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0x9f,0xa1,0x8e,0x7b,0x66,0x52,0x40,0x2f,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0x98,0x8c,0x74,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x00,0x00 + ,0x00,0x06,0x1d,0x34,0x4b,0x61,0x74,0x8c,0xa2,0xae,0x99,0x84,0x7f,0x7f,0x7f,0x84,0x99,0xb0,0xa4,0x8e,0x7b,0x65,0x4e,0x37,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8e,0xa4,0x98,0x7f,0x7f,0x93,0x93,0x7f,0x8c,0x9b,0x8a,0x79,0x8c + ,0xa4,0x98,0x7f,0x67,0x4f,0x38,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x21,0x36,0x4c,0x61,0x74,0x8a,0x9d,0xb3,0xb8,0xa3,0x8e,0x7b,0x65,0x4e,0x37,0x21,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0x26,0x3c,0x51,0x66 + ,0x7b,0x8c,0x9d,0xa4,0x99,0x9d,0xab,0xa3,0x8e,0x7b,0x66,0x51,0x3c,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x27,0x38,0x46,0x52,0x5f,0x6a,0x7b,0x7b,0x6a,0x6a,0x7b,0x8c,0x97,0x98,0x97,0x96,0x93,0x84,0x71,0x5c,0x46,0x30,0x19,0x04,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8e,0xa3,0xa7,0x94,0x84,0x8c,0x9c,0xa5,0x94,0x8a,0x7b,0x7b,0x8e + ,0xa4,0x9d,0x8a,0x74,0x61,0x4b,0x34,0x1d,0x06,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa8,0x94,0x8e,0x9c,0xad,0xb0,0x98,0x7f,0x6b,0x5a,0x47,0x34,0x23,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa8,0x93 + ,0x7f,0x67,0x51,0x3c,0x26,0x1b,0x27,0x36,0x40,0x42,0x3c,0x2f,0x1e,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x21,0x36,0x4c,0x61,0x74,0x8c,0xa2,0xae,0xb0,0xa2,0x8c,0x74,0x61,0x4c,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x1e + ,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8e,0x7b,0x65,0x4e,0x39,0x46,0x5c,0x73,0x8c,0xa4,0xb1,0x9d,0x8a,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xae,0x9d,0x93,0x8c,0x8c,0x8c,0x94,0xa4,0xb1,0xa4,0x93,0x7f,0x6b,0x57,0x40 + ,0x28,0x11,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x97,0xad,0xb0,0x98,0x7f,0x67,0x5b,0x71,0x7f,0x7f,0x7f,0x84,0x99,0xaa,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2f,0x3f,0x4a,0x51,0x5c,0x65,0x6b,0x74,0x7f,0x8a,0x94,0xa4 + ,0xb5,0xad,0x98,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x74,0x8a,0x9c,0xad,0xad,0x9c,0x8e + ,0x8c,0x8c,0x8e,0x9c,0xab,0xba,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x89,0x8c,0x8c,0x89,0x73,0x5c,0x46,0x31,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x7f,0x7f,0x7f + ,0x71,0x5a,0x43,0x2c,0x15,0x02,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x67,0x7f,0x93,0xa8,0xb6,0xa4,0x99,0x98,0x98,0x98,0x99,0xa4,0xb8,0xad,0x97,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x73,0x8c,0xa4,0x98 + ,0x7f,0x7f,0x98,0x8c,0x79,0x8c,0x9d,0x8c,0x79,0x8c,0xa4,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x16,0x2b,0x41,0x57,0x6b,0x7f,0x98,0xb0,0xb0,0x99,0x84,0x71,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x0a,0x1e,0x31,0x46,0x5c,0x71,0x84,0x98,0xa8,0x98,0x84,0x8c,0x9d,0xaa,0x98,0x84,0x71,0x5c,0x49,0x36,0x21,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x27,0x38,0x49,0x5a,0x6a,0x7b,0x8c,0x8c,0x7b,0x74,0x8a,0x9b,0x94,0x84,0x7f + ,0x8c,0x9b,0x8e,0x7b,0x65,0x4e,0x37,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x97,0xab,0xa2 + ,0x8c,0x74,0x7b,0x8e,0xa3,0xa7,0x9c,0x8c,0x84,0x98,0xa5,0x93,0x7f,0x6b,0x57,0x41,0x2b,0x15,0x02,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb5,0xa8,0xa4,0xa5,0xa4,0xab,0x9d,0x8c,0x7b,0x66,0x52,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x93,0xa8,0xb0,0x99,0x84,0x71,0x5c,0x46,0x36,0x31,0x3c,0x49,0x57,0x5a,0x51,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0a,0x15,0x1e,0x2c,0x43,0x5a,0x71,0x84,0x98,0xad,0xad,0x98,0x84,0x71,0x5a,0x43,0x2c + ,0x16,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x97,0xad,0xad,0x97,0x7f,0x67,0x51,0x3f,0x4e,0x65,0x7b,0x8e,0xa4,0xb0,0x98,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xae,0x9d,0x99,0x9f,0xa4 + ,0xa4,0xa8,0xab,0xa3,0x94,0x84,0x72,0x61,0x4c,0x36,0x21,0x0a,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8e,0xa4,0xb0,0x99,0x84,0x71,0x5d,0x61,0x67,0x67,0x6a,0x7f,0x98,0xaa,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2f,0x40,0x51 + ,0x5a,0x5a,0x53,0x50,0x57,0x61,0x6b,0x74,0x84,0x94,0xa4,0xb3,0xa2,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x02,0x15 + ,0x2b,0x41,0x57,0x6a,0x7b,0x8c,0x9c,0xac,0xab,0xa4,0xa4,0xa2,0x9b,0x98,0x9d,0xae,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x12,0x01,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x06,0x1b,0x2f,0x41,0x55,0x63,0x6c,0x6d,0x6c,0x63,0x55,0x41,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x99,0xb0,0xae,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xae,0xb2,0x9d,0x8a,0x73,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x00 + ,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0x98,0x7f,0x84,0x98,0x8c,0x77,0x84,0x98,0x8e,0x7c,0x8c,0xa0,0x93,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x21,0x38,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x51 + ,0x3c,0x26,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x16,0x2b,0x40,0x52,0x66,0x7b,0x8e,0xa3,0xa3,0x8e,0x7b,0x7f,0x93,0xa8,0xa3,0x8e,0x7b,0x6a,0x57,0x41,0x2b,0x16,0x03,0x00,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2f,0x3c,0x49,0x5a,0x6a,0x7b + ,0x8c,0x98,0x8c,0x7b,0x7f,0x93,0x9c,0x8a,0x74,0x6c,0x7f,0x98,0x97,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xaa,0x99,0x84,0x71,0x71,0x84,0x94,0xa4,0xab,0x9d,0x99,0xa4,0x9d,0x8a,0x74,0x61,0x4c,0x3a,0x27,0x14,0x02,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xc2,0xb7,0xa4,0x94,0x8e,0x9c,0xa8,0x98,0x84,0x72,0x62 + ,0x51,0x3c,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x74,0x8c,0xa2,0xb3,0xa3,0x8e,0x7b,0x66,0x57,0x4c,0x46,0x51,0x5c,0x6a,0x71,0x62,0x51,0x3c,0x27,0x16,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2b,0x34,0x37,0x3e,0x51,0x66 + ,0x7b,0x8e,0xa4,0xa4,0x8e,0x7b,0x66,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8e,0xa4,0xb0,0x99,0x84,0x71,0x5c,0x4a,0x57,0x6b,0x7f,0x97,0xad,0xa8,0x93,0x7f,0x67,0x4f,0x38,0x21,0x0a,0x00,0x00,0x06,0x1e,0x37 + ,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8e,0x84,0x93,0x99,0xa2,0xa2,0x98,0x8e,0x84,0x72,0x62,0x51,0x40,0x2b,0x16,0x03,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x73,0x8a,0x9d,0xb0,0xa3,0x8e,0x7b,0x66,0x55,0x53,0x52,0x67,0x7f,0x98,0xaa,0x98,0x7f,0x67,0x4f,0x37 + ,0x1e,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x40,0x51,0x62,0x71,0x71,0x66,0x5c,0x51,0x51,0x57,0x62,0x72,0x84,0x99,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x4f,0x67,0x7f,0x98,0xb0,0xb0 + ,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x0b,0x21,0x36,0x49,0x5a,0x6a,0x7b,0x8c,0x97,0x9d,0xa4,0x9d,0x97,0x8c,0x7f,0x8e,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x03,0x16,0x2b,0x40,0x51,0x61,0x6b,0x73,0x73,0x71,0x62,0x51 + ,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x26,0x3c,0x51,0x62,0x71,0x7b,0x7f,0x7b,0x71,0x62,0x51,0x40,0x2b,0x15,0x02,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x73,0x8c,0xa2,0xac,0x9c,0x8e,0x8c,0x8c,0x8c,0x8c,0x8c,0x8e,0x9c,0xae,0xa4 + ,0x8e,0x7b,0x65,0x4e,0x36,0x1e,0x07,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8a,0x9d,0x98,0x7f,0x8c,0x9a,0x8a,0x73,0x7f,0x98,0x97,0x7f,0x8c,0x9e,0x8c,0x74,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37 + ,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x21,0x36,0x4c,0x61,0x72,0x84,0x98,0xa9,0x99,0x84,0x71,0x74,0x8a,0x9d,0xab,0x9c,0x8a,0x74,0x61,0x4c,0x36,0x21,0x0d,0x00,0x00,0x00 + ,0x00,0x06,0x1b,0x2f,0x40,0x51,0x5c,0x6a,0x7b,0x8c,0x98,0x8c,0x7b,0x6e,0x7f,0x98,0x98,0x7f,0x6b,0x67,0x7f,0x98,0x9d,0x8a,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f + ,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xab,0x9d,0x8a,0x73,0x64,0x72,0x84,0x94,0xa4,0xb0,0xb0,0xae,0x98,0x7f,0x6f,0x61,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xbd + ,0xac,0x98,0x84,0x7b,0x8c,0x9d,0xa4,0x94,0x84,0x71,0x5c,0x49,0x36,0x21,0x0d,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2c,0x43,0x5a,0x71,0x84,0x98,0xac,0xad,0x98,0x84,0x74,0x6b,0x61,0x5c,0x66,0x71,0x7b,0x84,0x71,0x5c,0x49,0x38,0x25,0x10,0x00,0x00,0x00,0x00 + ,0x00,0x06,0x1b,0x2f,0x40,0x4b,0x4f,0x4e,0x57,0x6b,0x7f,0x93,0xa6,0x9d,0x8a,0x73,0x5c,0x46,0x31,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x73,0x8a,0x9d,0xb0,0xa3,0x8e,0x7b,0x6a,0x5e,0x66,0x74,0x8a,0x9d,0xaf,0xa2,0x8c,0x74 + ,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x77,0x7f,0x84,0x8c,0x8c,0x84,0x7b,0x71,0x62,0x51,0x40,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x93,0xa8,0xad,0x98,0x84,0x72,0x67,0x61 + ,0x5c,0x6b,0x7f,0x98,0xaa,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x62,0x72,0x84,0x84,0x7b,0x71,0x67,0x61,0x5b,0x62,0x72,0x84,0x99,0xae,0xa2,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4 + ,0x8c,0x73,0x5b,0x43,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x02,0x14,0x27,0x38,0x49,0x5a,0x6a,0x7b,0x7f,0x8a,0x8c,0x8a,0x7f,0x7b,0x76,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x0a,0x21 + ,0x36,0x4c,0x61,0x72,0x7f,0x8a,0x8c,0x84,0x72,0x62,0x51,0x3c,0x26,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x71,0x84,0x8e,0x97,0x8e,0x84,0x72,0x61,0x4b,0x34,0x1d,0x06,0x00,0x00,0x00,0x0a,0x21,0x37,0x4e,0x65,0x7b,0x8e,0xa4,0xa4,0x8e + ,0x7b,0x73,0x73,0x73,0x73,0x73,0x7b,0x8e,0xa4,0xad,0x97,0x7f,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x98,0x9d,0x8e,0x94,0x98,0x7f,0x6e,0x7f,0x97,0x9d,0x8e,0x94,0xa0,0x8c,0x73,0x5b,0x43,0x2c,0x15,0x02,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x16,0x2b,0x41,0x57,0x6b,0x7f,0x93,0xa4,0xa4,0x93,0x7f,0x67,0x6b,0x7f,0x93,0xa8,0xa8 + ,0x93,0x7f,0x6b,0x57,0x41,0x2f,0x1b,0x06,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x62,0x71,0x7b,0x8c,0x9a,0x93,0x7f,0x6b,0x67,0x7f,0x98,0x98,0x7f,0x67,0x67,0x7f,0x98,0xa2,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37 + ,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x97,0xad,0xa4,0x8e,0x7b,0x71,0x69,0x76,0x84,0x99,0xb0,0xbc,0xb2,0x9d,0x8c,0x7f,0x74,0x6a,0x57,0x40,0x28,0x11,0x00 + ,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xae,0x9c,0x8c,0x7b,0x6e,0x7f,0x93,0xa7,0xa3,0x8e,0x7b,0x6a,0x57,0x41,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x66,0x7b,0x8c,0x9d,0xb0,0xa4,0x94,0x8a,0x7f,0x74,0x73,0x7b,0x84,0x8e,0x8e + ,0x7b,0x6a,0x5a,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x10,0x26,0x3c,0x51,0x61,0x67,0x65,0x67,0x74,0x8a,0x9d,0xa6,0x93,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x93,0xa4,0xac,0x9c,0x8c + ,0x7b,0x73,0x7b,0x84,0x94,0xa8,0xa8,0x94,0x84,0x71,0x5a,0x43,0x2c,0x15,0x02,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x67,0x71,0x73,0x73,0x71,0x66,0x5c,0x51,0x40,0x2f,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x4c + ,0x61,0x74,0x8a,0x9c,0xac,0xa4,0x94,0x84,0x7f,0x74,0x73,0x7b,0x8c,0x9d,0xab,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x72,0x84,0x94,0x98,0x8e,0x84,0x7f,0x74,0x73,0x74,0x84,0x94,0xa4,0xac,0x98,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00 + ,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x05,0x16,0x27,0x38,0x49,0x5a,0x65,0x6b,0x73,0x73,0x73,0x6b,0x6a,0x7f,0x93,0xa8,0xb0,0x98,0x7f,0x67 + ,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x92,0x9d,0xa2,0x94,0x84,0x71,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8e,0xa1,0xaa,0xa3,0x93,0x7f,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00 + ,0x11,0x28,0x40,0x57,0x6b,0x7f,0x97,0xab,0xa2,0x8c,0x73,0x5e,0x5b,0x5b,0x5b,0x5e,0x73,0x8c,0xa2,0xae,0x99,0x84,0x71,0x5a,0x43,0x2c,0x15,0x02,0x00,0x00,0x00,0x00,0x0a,0x21,0x38,0x4f,0x67,0x7f,0x98,0xaa,0xa4,0xa5,0x97,0x7f,0x6c,0x7b,0x8e,0xa3,0xa4,0xa8 + ,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x21,0x36,0x4c,0x61,0x74,0x8a,0x9d + ,0xaa,0x98,0x84,0x72,0x61,0x61,0x74,0x8a,0x9d,0xad,0x9d,0x8a,0x74,0x62,0x51,0x3c,0x26,0x10,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x8e,0x9a,0x94,0x84,0x72,0x61,0x67,0x7f,0x97,0x99,0x84,0x71,0x67,0x7f,0x98,0x99,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8e,0xa3,0xab,0x9c,0x8e,0x84,0x7f,0x84,0x8e,0x9d,0xaa,0xa4,0xa8 + ,0xaa,0x9d,0x93,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8e,0x7b,0x6a,0x62,0x74,0x8a,0x9c,0xa9,0x9c,0x8a,0x74,0x62,0x51,0x3c,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x06,0x1b,0x31,0x46,0x5a,0x6b,0x7f,0x93,0xa3 + ,0xad,0xa8,0x9d,0x93,0x8c,0x8c,0x8e,0x98,0xa3,0x9c,0x8c,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x71,0x7f,0x7b,0x7f,0x84,0x94,0xa6,0x9d,0x8a,0x74,0x61,0x4c,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a + ,0x21,0x36,0x4c,0x61,0x72,0x84,0x98,0xac,0xad,0x9c,0x8e,0x8c,0x8e,0x98,0xa4,0xab,0x9c,0x8a,0x74,0x62,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5c,0x5a,0x5b,0x5b,0x5a,0x51,0x46,0x3c,0x2f,0x1e,0x0d,0x01 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x16,0x2b,0x41,0x57,0x6a,0x7b,0x8e,0x9d,0xab,0xa4,0x99,0x93,0x8c,0x8c,0x8e,0x9c,0xad,0xac,0x97,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x93,0xa1,0xaa,0xa3,0x99,0x93,0x8c,0x8c,0x8c,0x94,0xa4 + ,0xb1,0xa3,0x8e,0x7b,0x66,0x51,0x3c,0x25,0x0e,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x27,0x38,0x46,0x4e,0x57,0x5b,0x5b + ,0x5b,0x58,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8a,0x9d,0xb1,0xb5,0xa3,0x8e,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x97,0xad,0xbf,0xb0 + ,0x99,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x73,0x8a,0x9d,0xac,0x99,0x84,0x71,0x5a,0x45,0x43,0x45,0x5a,0x71,0x84,0x99,0xae,0xa2,0x8c,0x74,0x61,0x4b,0x34,0x1d,0x06,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0 + ,0xb6,0xa4,0x8e,0x7b,0x66,0x73,0x8c,0xa4,0xb6,0xb2,0x9d,0x8a,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x06,0x1b,0x2f,0x41,0x57,0x6b,0x7f,0x93,0xa8,0xa3,0x8e,0x7b,0x66,0x52,0x57,0x6b,0x7f,0x93,0xa8,0xa8,0x94,0x84,0x71,0x5c,0x46,0x31,0x1b,0x06,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x7b,0x8c,0x96,0x84,0x72,0x62,0x55,0x65,0x7b,0x8e,0x9e,0x8e,0x7b,0x74 + ,0x84,0x99,0x93,0x7f,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x71,0x84,0x94,0xa3 + ,0xa8,0xa3,0x99,0x98,0x99,0xa1,0xa1,0x98,0x8e,0x93,0x9d,0xa6,0x9d,0x8a,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5c,0x57,0x6a,0x7b,0x8e,0xa3,0xa7,0x94,0x84,0x71,0x5c,0x49,0x36,0x21,0x0b,0x00,0x00,0x00 + ,0x00,0x00,0x10,0x25,0x38,0x4c,0x61,0x72,0x84,0x8e,0x9c,0xa8,0xac,0xa8,0xa4,0xa4,0xa4,0xa7,0xa3,0x98,0x8c,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x00,0x07,0x1e,0x36,0x4e,0x65,0x7b,0x8c,0x8e,0x97,0x99,0xa4,0xa4,0x93,0x7f,0x6b,0x57,0x41,0x2b,0x16,0x03 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x16,0x2b,0x40,0x52,0x66,0x7b,0x8c,0x98,0xa4,0xa9,0xa4,0xa4,0xa4,0xa9,0xa8,0x9c,0x8c,0x7b,0x6a,0x57,0x41,0x2f,0x1b,0x06,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x46 + ,0x43,0x43,0x42,0x3c,0x31,0x26,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x21,0x36,0x49,0x5c,0x71,0x7f,0x8c,0x9c,0xa8,0xaa,0xa8,0xa4,0xa4,0xa4,0xa8,0xa3,0x98,0x8c,0x7b,0x65,0x4e,0x36,0x1e,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8a + ,0x93,0x9d,0xa8,0xaa,0xa8,0xa4,0xa4,0xa4,0xa6,0xa7,0x9d,0x93,0x84,0x71,0x5c,0x46,0x31,0x1b,0x06,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x05,0x16,0x25,0x30,0x37,0x40,0x43,0x43,0x43,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa2,0xb8,0xbd,0xa8,0x93,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00 + ,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x93,0xa8,0xb7,0xac,0x97,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8e,0xa1,0xa4,0x97,0x7f,0x67,0x51,0x3c,0x2d,0x3c,0x51,0x67,0x7f,0x97,0xa4,0xa1,0x93,0x7f,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00 + ,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x93,0xa2,0xa4,0xa1,0x8c,0x73,0x61,0x73,0x8a,0x9d,0xa4,0xa4,0x98,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0xa4,0x98,0x7f,0x67,0x4f + ,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x62,0x74,0x8a,0x9b,0xa4,0x98,0x84,0x71,0x5c,0x46,0x4c,0x61,0x74,0x8a,0x9d,0xa4,0x9f,0x8e,0x7b,0x66,0x51,0x3c,0x25,0x0e,0x00,0x00,0x0a,0x21,0x36,0x49,0x5a,0x6a,0x7b,0x88,0x7b + ,0x66,0x52,0x48,0x5c,0x71,0x84,0x94,0x9a,0x8e,0x8c,0x94,0x97,0x8a,0x74,0x61,0x4b,0x34,0x1d,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0xa4,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x10,0x26,0x3c,0x51,0x62,0x72,0x84,0x8e,0x97,0x9d,0xa4,0xa4,0x9d,0x97,0x8e,0x84,0x7b,0x7f,0x8a,0x93,0x95,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xad,0xa4,0x8c,0x73,0x5b,0x4b,0x5c,0x71,0x84,0x94,0xa7,0xa2 + ,0x8e,0x7b,0x6a,0x57,0x41,0x2b,0x15,0x02,0x00,0x00,0x00,0x00,0x04,0x17,0x2b,0x40,0x51,0x62,0x71,0x7b,0x8a,0x93,0x99,0xa2,0xa4,0xa4,0x9d,0x97,0x8e,0x84,0x7b,0x6a,0x5a,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x67,0x7f,0x97,0xa4,0xa7,0xa4 + ,0x9d,0x93,0x84,0x72,0x61,0x4c,0x36,0x21,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x31,0x46,0x5a,0x6a,0x7b,0x84,0x93,0x99,0xa2,0xa4,0xa2,0x99,0x93,0x8a,0x7b,0x6a,0x5a,0x49,0x36,0x21,0x0d,0x00,0x00,0x00,0x00,0x06,0x1e,0x37 + ,0x4f,0x67,0x7f,0x98,0xad,0xa4,0x8c,0x73,0x5b,0x43,0x2d,0x2a,0x2a,0x25,0x1b,0x10,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x3c,0x51,0x61,0x6b,0x7b,0x8a,0x93,0x99,0xa2,0xa4,0xa4,0x9d,0x97,0x8e,0x84,0x7b,0x6a,0x5a,0x46,0x30 + ,0x19,0x00,0x00,0x04,0x19,0x30,0x46,0x5a,0x6a,0x74,0x7f,0x8a,0x93,0x99,0xa2,0xa4,0xa4,0xa2,0x99,0x93,0x8a,0x7f,0x72,0x62,0x51,0x3c,0x26,0x10,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xad,0xa4,0x8c,0x73,0x5b,0x43,0x4f,0x67,0x7f,0x98,0xad,0xad + ,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x19,0x21,0x28,0x2a,0x2a,0x37,0x4f,0x67,0x7f,0x98,0xad,0xad,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x98,0xa8,0xac,0x9c,0x8a,0x74 + ,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x74,0x8a,0x98,0xa2,0x9c,0x8c,0x7b,0x65,0x4e,0x37,0x21,0x0a,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x8a,0x7b,0x65,0x4e,0x36,0x24,0x36,0x4e,0x65,0x7b,0x8a,0x8c + ,0x8c,0x8c,0x82,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x74,0x89,0x8c,0x8c,0x8c,0x89,0x73,0x5e,0x6b,0x7f,0x8c,0x8c,0x8c,0x8c,0x7f,0x67,0x4f,0x38,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37 + ,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x8c,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x82,0x8a,0x8c,0x8c,0x8a,0x7b,0x66,0x51,0x3c,0x41,0x57,0x6b,0x7f,0x8c,0x8c,0x8c,0x8c,0x82,0x71,0x5a,0x42,0x2a,0x12,0x00 + ,0x00,0x02,0x14,0x27,0x38,0x49,0x5a,0x6a,0x73,0x6a,0x5a,0x46,0x3c,0x51,0x62,0x72,0x84,0x8e,0x97,0x97,0x8e,0x84,0x7b,0x6a,0x57,0x41,0x2b,0x15,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x8c,0x7f,0x67,0x4f + ,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x51,0x62,0x71,0x7b,0x7f,0x8a,0x8c,0x8c,0x8a,0x7f,0x7b,0x71,0x66,0x6b,0x74,0x7f,0x84,0x7b,0x65,0x4e,0x37,0x21,0x0a,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x95,0x98,0x98 + ,0x8c,0x73,0x5b,0x45,0x51,0x62,0x74,0x8a,0x97,0x98,0x95,0x8a,0x74,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x40,0x51,0x5c,0x6a,0x74,0x7f,0x84,0x8c,0x8c,0x8c,0x8a,0x7f,0x7b,0x71,0x66,0x5a,0x49,0x38,0x25,0x10,0x00,0x00,0x00,0x00 + ,0x12,0x2a,0x42,0x5a,0x71,0x82,0x92,0x98,0x97,0x8e,0x8a,0x7f,0x72,0x62,0x51,0x40,0x2b,0x16,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0x25,0x38,0x49,0x5a,0x66,0x72,0x7f,0x84,0x8c,0x8c,0x8c,0x84,0x7f,0x74,0x6a,0x5a,0x49,0x38 + ,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x95,0x98,0x98,0x8c,0x73,0x5b,0x43,0x2a,0x15,0x12,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x4c,0x5a,0x6a,0x74,0x7f,0x84,0x8c,0x8c + ,0x8c,0x8a,0x7f,0x7b,0x71,0x66,0x5a,0x49,0x38,0x25,0x10,0x00,0x00,0x00,0x10,0x25,0x38,0x49,0x57,0x61,0x6b,0x74,0x7f,0x84,0x8c,0x8c,0x8c,0x8c,0x84,0x7f,0x74,0x6b,0x61,0x51,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x95,0x98,0x98 + ,0x8c,0x73,0x5b,0x43,0x4f,0x67,0x7f,0x95,0x98,0x98,0x95,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x0a,0x11,0x12,0x1e,0x37,0x4f,0x67,0x7f,0x95,0x98,0x98,0x95,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x00,0x0e,0x25 + ,0x3c,0x51,0x66,0x7b,0x8a,0x93,0x97,0x8c,0x7b,0x6a,0x57,0x41,0x2b,0x15,0x02,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x41,0x57,0x6a,0x7b,0x84,0x8c,0x8a,0x7b,0x6a,0x5a,0x46,0x30,0x19,0x04,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x6a + ,0x5a,0x46,0x30,0x1f,0x30,0x46,0x5a,0x6a,0x73,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x41,0x57,0x6a,0x73,0x73,0x73,0x73,0x73,0x6a,0x57,0x61,0x71,0x73,0x73,0x73,0x73,0x71,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x71,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x73,0x73,0x73,0x6a,0x5a,0x46,0x31,0x36,0x4c,0x61,0x71,0x73 + ,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x05,0x16,0x27,0x38,0x49,0x57,0x5b,0x57,0x49,0x38,0x2f,0x40,0x51,0x62,0x71,0x7b,0x7f,0x7f,0x7b,0x71,0x66,0x5a,0x49,0x36,0x21,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x1c,0x34 + ,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x71,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2f,0x40,0x51,0x5c,0x65,0x6b,0x73,0x73,0x73,0x73,0x6b,0x65,0x5c,0x51,0x57,0x61,0x67,0x71,0x6a,0x5a,0x46,0x30,0x19,0x04,0x00 + ,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x7f,0x7f,0x7f,0x7f,0x71,0x5a,0x42,0x41,0x57,0x6a,0x7b,0x7f,0x7f,0x7f,0x7f,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2f,0x3c,0x49,0x57,0x61,0x67,0x71,0x73,0x73,0x73,0x73,0x6b,0x65,0x5c + ,0x51,0x46,0x38,0x27,0x16,0x04,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x74,0x7f,0x7f,0x7f,0x7b,0x73,0x6b,0x61,0x51,0x40,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x16,0x27,0x38,0x46,0x52,0x61,0x67,0x71 + ,0x73,0x73,0x73,0x71,0x67,0x61,0x57,0x49,0x38,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x7f,0x7f,0x7f,0x7f,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c + ,0x1e,0x2b,0x38,0x49,0x57,0x61,0x67,0x71,0x73,0x73,0x73,0x73,0x6b,0x65,0x5c,0x51,0x46,0x38,0x27,0x16,0x04,0x00,0x00,0x00,0x04,0x16,0x27,0x36,0x41,0x4c,0x57,0x61,0x67,0x71,0x73,0x73,0x73,0x73,0x71,0x67,0x61,0x57,0x4c,0x40,0x2f,0x1e,0x0c,0x00,0x00,0x00 + ,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x7f,0x7f,0x7f,0x7f,0x71,0x5a,0x42,0x4e,0x65,0x7b,0x7f,0x7f,0x7f,0x7f,0x7b,0x65,0x4e,0x36,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x7f,0x7f,0x7f,0x7f,0x7b,0x65 + ,0x4e,0x36,0x1e,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x31,0x46,0x5a,0x6a,0x74,0x7f,0x7f,0x7b,0x6a,0x5a,0x49,0x36,0x21,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x21,0x36,0x49,0x5a,0x66,0x71,0x73,0x73,0x6a,0x5a,0x49,0x38,0x25,0x10,0x00,0x00,0x00,0x02 + ,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x38,0x25,0x16,0x25,0x38,0x49,0x57,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x0b,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x51,0x5a,0x5b,0x5b,0x5b + ,0x5b,0x5a,0x51,0x40,0x2b,0x15,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x2b,0x15,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x5b + ,0x5b,0x57,0x49,0x38,0x25,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x05,0x16,0x27,0x36,0x40,0x43,0x40,0x36,0x27,0x1e,0x2f,0x40,0x51,0x5c,0x65,0x67,0x67,0x65,0x5c,0x51,0x46,0x38,0x27,0x14,0x02,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x2b,0x15,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2f,0x3c,0x46,0x4e,0x57,0x5b,0x5b,0x5b,0x5b,0x57,0x4e,0x46,0x3c,0x41 + ,0x4b,0x51,0x5a,0x57,0x49,0x38,0x25,0x10,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5a,0x65,0x67,0x67,0x67,0x67,0x61,0x51,0x3c,0x36,0x49,0x5a,0x65,0x67,0x67,0x67,0x67,0x65,0x5a,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x27,0x36,0x41 + ,0x4b,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x57,0x4e,0x46,0x3c,0x31,0x25,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x61,0x67,0x67,0x67,0x65,0x5c,0x57,0x4c,0x40,0x2f,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x05,0x16,0x25,0x31,0x40,0x4b,0x51,0x5a,0x5b,0x5b,0x5b,0x5a,0x51,0x4b,0x41,0x36,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5a,0x65,0x67,0x67,0x67,0x67,0x61,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0a,0x17,0x27,0x36,0x41,0x4b,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x57,0x4e,0x46,0x3c,0x31,0x25,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x2b,0x36,0x41,0x4b,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5a,0x51 + ,0x4b,0x41,0x36,0x2b,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5a,0x65,0x67,0x67,0x67,0x67,0x61,0x51,0x3c,0x46,0x5a,0x65,0x67,0x67,0x67,0x67,0x65,0x5a,0x46,0x30,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x19 + ,0x30,0x46,0x5a,0x65,0x67,0x67,0x67,0x67,0x65,0x5a,0x46,0x30,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x25,0x38,0x49,0x57,0x61,0x67,0x67,0x65,0x5a,0x49,0x38,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x38,0x46,0x51,0x5a,0x5b,0x5b + ,0x57,0x49,0x38,0x27,0x16,0x04,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x16,0x08,0x16,0x27,0x36,0x40,0x43,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x36,0x40,0x43,0x43 + ,0x43,0x43,0x43,0x40,0x36,0x3c,0x42,0x43,0x43,0x43,0x43,0x42,0x3c,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x42,0x3c,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x02,0x14,0x27,0x36,0x40,0x43,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x16,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x28,0x21,0x14,0x0d,0x1e,0x2f,0x3c,0x46,0x4e,0x4f,0x4f + ,0x4e,0x46,0x3c,0x31,0x25,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x42,0x3c,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x26,0x30,0x37 + ,0x40,0x43,0x43,0x43,0x43,0x40,0x37,0x30,0x26,0x2b,0x34,0x3c,0x42,0x40,0x36,0x27,0x16,0x04,0x00,0x00,0x00,0x00,0x10,0x25,0x38,0x46,0x4e,0x4f,0x4f,0x4f,0x4f,0x4b,0x40,0x2f,0x27,0x38,0x46,0x4e,0x4f,0x4f,0x4f,0x4f,0x4e,0x46,0x38,0x25,0x10,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x14,0x21,0x2b,0x34,0x3c,0x42,0x43,0x43,0x43,0x43,0x40,0x37,0x30,0x26,0x1b,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x36,0x41,0x4b,0x4f,0x4f,0x4f,0x4e,0x46,0x40,0x36,0x2b,0x1e,0x0d,0x01,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x1e,0x2b,0x34,0x3c,0x42,0x43,0x43,0x43,0x42,0x3c,0x34,0x2b,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x25,0x38,0x46,0x4e,0x4f,0x4f,0x4f,0x4f,0x4b,0x40,0x2f + ,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x2b,0x34,0x3c,0x42,0x43,0x43,0x43,0x43,0x40,0x37,0x30,0x26,0x1b,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0b,0x16,0x21 + ,0x2b,0x34,0x3c,0x42,0x43,0x43,0x43,0x43,0x42,0x3c,0x34,0x2b,0x21,0x16,0x0a,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x25,0x38,0x46,0x4e,0x4f,0x4f,0x4f,0x4f,0x4b,0x40,0x2f,0x38,0x46,0x4e,0x4f,0x4f,0x4f,0x4f,0x4e,0x46,0x38,0x25,0x10,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x25,0x38,0x46,0x4e,0x4f,0x4f,0x4f,0x4f,0x4e,0x46,0x38,0x25,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x16,0x27,0x36,0x41,0x4b,0x4f,0x4f,0x4e,0x46,0x38,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x05,0x16,0x25,0x31,0x3c,0x42,0x43,0x43,0x40,0x36,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1b + ,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x11 + ,0x0a,0x02,0x01,0x0c,0x1b,0x26,0x30,0x36,0x37,0x37,0x36,0x30,0x26,0x1b,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x10,0x19,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x19,0x10,0x15,0x1d,0x25,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x04,0x16,0x25,0x30,0x36,0x37,0x37,0x37,0x37,0x34,0x2b,0x1e,0x16,0x25,0x30,0x36,0x37,0x37 + ,0x37,0x37,0x36,0x30,0x25,0x16,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0b,0x15,0x1d,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x19,0x10,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x2b,0x34,0x37,0x37,0x37,0x36 + ,0x30,0x28,0x21,0x16,0x0a,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0a,0x15,0x1d,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1d,0x15,0x0b,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x16 + ,0x25,0x30,0x36,0x37,0x37,0x37,0x37,0x34,0x2b,0x1e,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0b,0x15,0x1d,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x19,0x10,0x06,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0b,0x15,0x1d,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1d,0x15,0x0b,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x16,0x25,0x30,0x36,0x37,0x37,0x37,0x37,0x34,0x2b,0x1e,0x25,0x30,0x36,0x37,0x37,0x37 + ,0x37,0x36,0x30,0x25,0x16,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x16,0x25,0x30,0x36,0x37,0x37,0x37,0x37,0x36,0x30,0x25,0x16,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x2b,0x34,0x37,0x37,0x36,0x30,0x25 + ,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x1b,0x25,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x12 + ,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x10,0x19,0x1e,0x1e,0x1e,0x1e,0x19,0x10,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x0e,0x06 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x0a,0x11,0x12,0x12,0x12,0x12,0x11,0x0a,0x04,0x00,0x02,0x06,0x0e,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x19,0x1e,0x1e,0x1e,0x1e + ,0x1e,0x1c,0x15,0x0a,0x04,0x10,0x19,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x19,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x02,0x0b,0x15,0x1c,0x1e,0x1e,0x1e,0x1e,0x19,0x11,0x0a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x02,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x19,0x1e,0x1e,0x1e,0x1e,0x1e,0x1c,0x15,0x0a,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x06,0x0e,0x12,0x12,0x12 + ,0x12,0x12,0x11,0x0a,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x19,0x1e,0x1e,0x1e,0x1e + ,0x1e,0x1c,0x15,0x0a,0x10,0x19,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x19,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x19,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x19,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x02,0x0b,0x15,0x1c,0x1e,0x1e,0x1e,0x19,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12,0x12 + ,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x02,0x0a,0x11,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0a,0x11,0x12,0x12,0x12,0x12,0x11,0x0a,0x04,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0a,0x11,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12 + ,0x12,0x0e,0x06,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x0a,0x11,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12,0x12 + ,0x12,0x12,0x12,0x12,0x12,0x0e,0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x02,0x0a,0x11,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12,0x12,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12 + ,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x0a,0x11,0x12,0x12,0x12 + ,0x12,0x12,0x0e,0x06,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x05,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11 + ,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1d,0x15 + ,0x0b,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0b,0x16,0x21,0x28 + ,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x19,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0b,0x16,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1d,0x15,0x0b,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25 + ,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1d,0x15,0x0b,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x10,0x19,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1d,0x15,0x0a,0x01,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1e,0x19,0x10,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a + ,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a + ,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1d,0x15,0x0b,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a + ,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0b,0x15,0x1d,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1d,0x15,0x0b,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x06,0x10,0x19,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1d,0x15,0x0b,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0b,0x15,0x1d,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x1c,0x15,0x0b,0x02,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a + ,0x25,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x36,0x40,0x43,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x0c,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x02,0x14,0x27,0x36,0x40,0x43,0x43,0x43,0x43 + ,0x43,0x43,0x43,0x43,0x43,0x43,0x42,0x3c,0x34,0x2b,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x36,0x40,0x43,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x27,0x36,0x40,0x43,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x2b,0x36,0x40,0x43,0x43,0x43,0x43,0x40,0x37,0x30,0x25,0x17,0x0a,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0a,0x16,0x21,0x2b,0x36,0x40,0x43,0x43,0x43,0x43,0x42,0x3c,0x34,0x2b,0x21,0x16,0x0a + ,0x01,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x42,0x3c,0x34,0x2b,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x26,0x30,0x37,0x40,0x43,0x43,0x43,0x43,0x42,0x3c + ,0x34,0x2b,0x1e,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x36,0x40,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x42,0x3c,0x36,0x30,0x26,0x1b,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x42 + ,0x3c,0x2f,0x27,0x36,0x40,0x43,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x36,0x40,0x43,0x43,0x43,0x42,0x3c,0x2f,0x1e,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x27 + ,0x36,0x40,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x42,0x3c,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x42,0x3c,0x34,0x2b,0x21,0x16,0x0a,0x01,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x02,0x14,0x27,0x36,0x40,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x2b,0x34,0x3c,0x42,0x43,0x43,0x43,0x42,0x3c,0x34,0x2b,0x21,0x14,0x05 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0d,0x1b,0x26,0x30,0x37,0x40,0x43,0x43,0x43,0x43,0x42,0x3c,0x34,0x2b,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0a,0x16,0x21,0x2b,0x34,0x3c,0x42,0x43,0x43,0x43,0x43 + ,0x40,0x38,0x34,0x2b,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x36,0x40,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43 + ,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x42,0x3c,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x1b,0x2f,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00 + ,0x00,0x0a,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x4b,0x41,0x36,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x38,0x49,0x57,0x5b,0x5b,0x5b,0x5b + ,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x27,0x36,0x41,0x4c,0x57,0x5b,0x5b,0x5b,0x5b,0x57,0x4e,0x46,0x38,0x2b,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2b,0x36,0x41,0x4c,0x57,0x5b + ,0x5b,0x5b,0x5b,0x5a,0x51,0x4b,0x41,0x36,0x2b,0x1e,0x0d,0x01,0x00,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x4b,0x41,0x36,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2f + ,0x3c,0x46,0x4e,0x57,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x4b,0x40,0x31,0x25,0x16,0x04,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x4e,0x46,0x3c,0x31,0x25,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x02 + ,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x38,0x49,0x57,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x2b,0x15,0x02,0x00,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5a,0x51 + ,0x4b,0x41,0x36,0x2b,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x27,0x36,0x41,0x4b,0x51,0x5a + ,0x5b,0x5b,0x5b,0x5a,0x51,0x4b,0x41,0x36,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x2f,0x3c,0x46,0x4e,0x57,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x4b,0x41,0x36,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e + ,0x2b,0x36,0x41,0x4b,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x57,0x4f,0x4b,0x41,0x36,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00 + ,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x2b,0x15,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x73,0x73,0x73,0x6a,0x57,0x41,0x2b,0x25,0x3c,0x51,0x62,0x71 + ,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x71,0x67,0x61,0x57,0x49,0x38,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x73,0x73,0x73 + ,0x6a,0x57,0x40,0x46,0x5a,0x6a,0x73,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x27,0x38,0x49,0x57,0x61,0x6b,0x73,0x73,0x73,0x73,0x6b,0x65,0x5a,0x4c,0x40,0x2f,0x1e,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x01,0x0d,0x1e,0x2f,0x40,0x4c,0x57,0x61,0x6b,0x73,0x73,0x73,0x73,0x71,0x67,0x61,0x57,0x4c,0x40,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x71,0x67,0x61,0x57,0x49,0x38,0x27,0x16,0x04,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2f,0x40,0x51,0x5c,0x65,0x6b,0x73,0x73,0x73,0x73,0x71,0x67,0x61,0x52,0x46,0x38,0x25,0x10,0x01,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x71,0x67,0x65,0x5c,0x51,0x46 + ,0x38,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x71,0x61,0x4b,0x46,0x5a,0x6a,0x73,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x73 + ,0x71,0x62,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x71,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73 + ,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x71,0x67,0x61,0x57,0x4c,0x40,0x2f,0x1e,0x0c,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00 + ,0x00,0x05,0x16,0x27,0x38,0x49,0x57,0x61,0x67,0x71,0x73,0x73,0x73,0x71,0x67,0x61,0x57,0x49,0x38,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x16,0x27,0x36,0x41,0x51,0x5c,0x65,0x6b,0x73,0x73,0x73,0x73,0x71,0x67,0x61,0x57,0x49,0x38,0x27,0x16,0x04 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2f,0x40,0x4c,0x57,0x61,0x67,0x71,0x73,0x73,0x73,0x73,0x6b,0x67,0x61,0x57,0x49,0x38,0x27,0x16,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73 + ,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x71,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x87,0x8c,0x8c,0x8c + ,0x89,0x74,0x61,0x4b,0x34,0x2a,0x42,0x5a,0x71,0x84,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x89,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x84,0x7f,0x74,0x6a,0x5a,0x49,0x38,0x27,0x14,0x02,0x00,0x00,0x00,0x00 + ,0x12,0x2a,0x43,0x5b,0x73,0x89,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x47,0x52,0x66,0x7b,0x8a,0x8c,0x8c,0x8c,0x87,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x38,0x49,0x5a,0x6a,0x74,0x7f,0x8a,0x8c,0x8c,0x8a,0x7f,0x7b,0x6b,0x61,0x51,0x40 + ,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x40,0x51,0x61,0x6b,0x74,0x7f,0x8a,0x8c,0x8c,0x8c,0x84,0x7f,0x74,0x6b,0x61,0x51,0x40,0x2b,0x15,0x02,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c + ,0x84,0x7f,0x74,0x6a,0x5a,0x49,0x38,0x25,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x51,0x62,0x71,0x7b,0x7f,0x8a,0x8c,0x8c,0x8c,0x84,0x7f,0x72,0x66,0x5a,0x46,0x31,0x1e,0x0a,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x89,0x8c,0x8c,0x8c + ,0x8c,0x8c,0x8c,0x8c,0x84,0x7f,0x7b,0x71,0x66,0x5a,0x49,0x38,0x27,0x16,0x04,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x8c,0x7f,0x67,0x51,0x4e,0x65,0x7b,0x8a,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x02 + ,0x0a,0x11,0x1a,0x30,0x46,0x5c,0x73,0x89,0x8c,0x8c,0x84,0x71,0x5a,0x42,0x2a,0x15,0x12,0x12,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x89,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x7f,0x67,0x4f,0x37,0x1e,0x06 + ,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x84,0x7f,0x74,0x6b,0x61,0x51,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x89,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c + ,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x02,0x14,0x27,0x38,0x49,0x5a,0x6a,0x74,0x7f,0x84,0x8c,0x8c,0x8c,0x84,0x7f,0x74,0x6a,0x5a,0x49,0x38,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x10,0x25,0x38,0x49,0x57,0x62,0x71,0x7b,0x7f,0x8a,0x8c,0x8c + ,0x8c,0x84,0x7f,0x74,0x6a,0x5a,0x49,0x38,0x25,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x51,0x61,0x6b,0x74,0x7f,0x84,0x8c,0x8c,0x8c,0x8a,0x7f,0x7f,0x74,0x6a,0x5a,0x49,0x38,0x25,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73 + ,0x89,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x97,0xa2,0xa2,0x93,0x7f,0x67,0x4f,0x38,0x30,0x46,0x5c,0x73,0x8c,0xa0,0xa4,0x98,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa1,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa2,0x99,0x93,0x8a,0x7b + ,0x6a,0x5a,0x49,0x36,0x21,0x0b,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa1,0xa4,0xa1,0x8c,0x73,0x5b,0x51,0x62,0x72,0x84,0x98,0xa4,0x9b,0x8c,0x7b,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x0b,0x21,0x36,0x49,0x5a,0x6a,0x7b,0x8a,0x93 + ,0x9d,0xa4,0xa4,0x9d,0x97,0x8c,0x7f,0x72,0x62,0x51,0x3c,0x26,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x16,0x2b,0x40,0x51,0x62,0x72,0x7f,0x8a,0x93,0x9d,0xa4,0xa4,0xa2,0x99,0x93,0x8a,0x7f,0x72,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67 + ,0x7f,0x98,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa2,0x99,0x93,0x8a,0x7b,0x6a,0x5a,0x46,0x31,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x10,0x26,0x3c,0x51,0x62,0x72,0x84,0x8e,0x97,0x9d,0xa4,0xa4,0xa2,0x99,0x93,0x84,0x7b,0x66,0x52,0x40,0x2b,0x15,0x02,0x00,0x00 + ,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa1,0xa4,0xa4,0xa4,0xa4,0xa4,0xa2,0x99,0x97,0x8e,0x84,0x7b,0x6a,0x5a,0x49,0x38,0x25,0x10,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0xa4,0x99,0x84,0x71,0x5a,0x51,0x67,0x7f,0x97,0xa4,0xa4,0xa1,0x8c + ,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x36,0x4e,0x65,0x7b,0x8e,0xa1,0xa0,0x8c,0x73,0x5b,0x43,0x2d,0x2a,0x2a,0x2a,0x25,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa1,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4 + ,0xa4,0xa4,0xa4,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa2,0x99,0x93,0x8a,0x7f,0x72,0x62,0x51,0x3c,0x26,0x10,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa1,0xa4 + ,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x0b,0x21,0x36,0x49,0x5a,0x6a,0x7b,0x8a,0x93,0x99,0xa2,0xa4,0xa2,0x99,0x93,0x8a,0x7b,0x6a,0x5a,0x49,0x36,0x21,0x0b,0x00,0x00,0x00,0x00,0x04,0x19,0x30 + ,0x46,0x5a,0x6a,0x74,0x84,0x8e,0x97,0x9d,0xa4,0xa4,0xa2,0x99,0x93,0x8a,0x7b,0x6a,0x5a,0x46,0x31,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x62,0x72,0x7f,0x8a,0x93,0x99,0xa2,0xa4,0xa4,0x9d,0x98,0x93,0x8a,0x7b,0x6a,0x5a,0x46,0x31,0x1b,0x06 + ,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa1,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0x98,0x7f + ,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x37,0x4e,0x65,0x7b,0x8e,0xa4,0xb0,0x98,0x7f,0x6b,0x57,0x40,0x36,0x4e,0x65,0x7b,0x8e,0xa4,0xa8,0x93,0x7f,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb7,0xae + ,0x9d,0x98,0x98,0x9d,0xa4,0xa4,0xa6,0xa7,0x9c,0x8c,0x7b,0x6a,0x57,0x41,0x2b,0x15,0x02,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x5c,0x71,0x84,0x94,0xa4,0xa4,0x93,0x7f,0x6b,0x5a,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00 + ,0x03,0x16,0x2b,0x41,0x57,0x6a,0x7b,0x8c,0x9c,0xa5,0xa3,0x99,0x98,0x9d,0xa5,0x9d,0x93,0x84,0x71,0x5c,0x46,0x31,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x0b,0x21,0x36,0x4c,0x61,0x72,0x84,0x93,0x9d,0xa5,0xa4,0xa4,0xa4,0xa4,0xa4,0xa5,0x9c,0x8f,0x7f,0x67,0x4f + ,0x37,0x1e,0x06,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xae,0x9d,0x98,0x98,0x98,0x9d,0xa4,0xa9,0xa8,0x9c,0x8c,0x7b,0x66,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x71,0x84,0x94,0xa3,0xa2,0x99,0x98,0x98,0x98,0x9d,0xa2 + ,0x97,0x84,0x72,0x61,0x4b,0x34,0x1d,0x06,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb8,0xb3,0xa8,0xa4,0xa4,0xa4,0xa6,0xaa,0xa3,0x98,0x8c,0x7b,0x6a,0x5a,0x46,0x31,0x1b,0x06,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb7,0xa2,0x8c + ,0x73,0x5c,0x5a,0x71,0x84,0x99,0xb0,0xb9,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x02,0x14,0x27,0x36,0x40,0x43,0x43,0x4f,0x67,0x7f,0x97,0xad,0xa4,0x8c,0x73,0x5b,0x46,0x43,0x43,0x43,0x42,0x3c,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43 + ,0x5b,0x73,0x8c,0xa4,0xb3,0xa8,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb3,0xa4,0x99,0x98,0x99,0xa2,0xa4,0xa6,0xa7,0x9d,0x93,0x84,0x71,0x5c,0x46,0x30,0x19,0x04,0x00 + ,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa0,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa8,0xb3,0xb9,0xae,0x9c,0x8a,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x02,0x15,0x2b,0x41,0x57,0x6a,0x7b,0x8c,0x9c,0xa5,0xa2,0x99,0x98,0x99,0xa2,0xa5,0x9c,0x8c,0x7b,0x6a,0x57 + ,0x41,0x2b,0x16,0x03,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8a,0x94,0xa1,0xa3,0xa2,0x99,0x9d,0xa4,0xa6,0xa7,0x9c,0x8c,0x7b,0x66,0x51,0x3c,0x26,0x10,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x93,0x9d,0xa5,0xa4,0x9d,0x98,0x9d,0xa4 + ,0xa9,0xa8,0x9c,0x8c,0x7b,0x66,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa1,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xae,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb3,0xa8 + ,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0x97,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x73,0x8a,0x9d,0xad,0x9d,0x8a,0x73,0x5b,0x43,0x3c,0x51,0x67,0x7f,0x97,0xad,0xa4,0x8c,0x74,0x61,0x4b,0x34,0x1d,0x06,0x00 + ,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8e,0x7f,0x7f,0x8a,0x8c,0x8c,0x94,0xa4,0xab,0x9c,0x8a,0x74,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5e,0x6a,0x7b,0x8e,0xa3,0xa7,0x94,0x84,0x72 + ,0x61,0x4c,0x38,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x4c,0x61,0x74,0x8a,0x9c,0xa9,0x9c,0x8e,0x84,0x7f,0x8a,0x94,0xa4,0xa3,0x8e,0x7b,0x66,0x51,0x3c,0x26,0x10,0x00,0x00,0x00,0x00,0x03,0x16,0x2b,0x41,0x57,0x6b,0x7f,0x93,0xa4,0xaa,0x9c,0x8e + ,0x8c,0x8c,0x8c,0x8e,0x98,0x94,0x84,0x72,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8e,0x7f,0x7f,0x7f,0x8a,0x8e,0x9c,0xad,0xac,0x98,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b + ,0x8e,0xa3,0xa4,0x94,0x84,0x7f,0x7f,0x7f,0x8c,0x9d,0xa4,0x93,0x7f,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb7,0xa8,0x94,0x8c,0x8c,0x8c,0x93,0x9d,0xab,0xac,0x9c,0x8c,0x7b,0x66,0x51,0x3c,0x26,0x10,0x00,0x00,0x00,0x06 + ,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xae,0xb0,0xa4,0x8e,0x7b,0x65,0x5c,0x73,0x8c,0xa2,0xaf,0xb5,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5e,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x40 + ,0x2b,0x15,0x02,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa8,0x94,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa8,0x94,0x84,0x7f,0x84,0x8c,0x8c,0x94,0xa4 + ,0xaf,0xa3,0x8e,0x7b,0x65,0x4e,0x37,0x21,0x0a,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x94,0xa8,0xb5,0xa3,0x8e,0x7b,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x74,0x8a,0x9c,0xa9,0x9c,0x8e + ,0x84,0x7f,0x84,0x8e,0x9c,0xa9,0x9c,0x8a,0x74,0x61,0x4c,0x36,0x21,0x0a,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x93,0xa1,0x9c,0x8e,0x8c,0x84,0x8a,0x8c,0x94,0xa4,0xab,0x98,0x84,0x71,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57 + ,0x6a,0x7b,0x8e,0x9f,0x98,0x8e,0x8a,0x7f,0x8a,0x8e,0x9c,0xad,0xac,0x98,0x84,0x71,0x5a,0x43,0x2c,0x15,0x02,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x89,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8e,0x9d,0xb1,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00 + ,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa8,0x94,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8a,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x98,0xb0,0xa4,0x8c,0x74,0x61,0x4b,0x42,0x5a,0x71,0x84,0x99 + ,0xac,0x9d,0x8a,0x73,0x5b,0x43,0x2c,0x15,0x02,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x6b,0x73,0x73,0x74,0x84,0x94,0xa8,0xa8,0x93,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c + ,0x73,0x64,0x74,0x8a,0x9c,0xa9,0x9c,0x8a,0x74,0x62,0x51,0x40,0x2b,0x17,0x05,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x93,0xa5,0x9c,0x8c,0x7b,0x71,0x6b,0x74,0x84,0x98,0xa8,0x98,0x84,0x71,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x0a,0x21 + ,0x36,0x4c,0x61,0x74,0x8a,0x9d,0xaa,0x9c,0x8c,0x7b,0x73,0x73,0x73,0x7b,0x84,0x84,0x72,0x62,0x51,0x40,0x2b,0x15,0x02,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x67,0x6b,0x73,0x7b,0x8c,0x9d,0xb0,0xa2,0x8c,0x73,0x5b,0x43,0x2a,0x12 + ,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x97,0xa9,0x99,0x84,0x72,0x67,0x67,0x6c,0x7f,0x93,0xa6,0x99,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x76,0x73,0x74,0x7f,0x8c,0x9c,0xad,0xac,0x98 + ,0x84,0x71,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x99,0x9d,0x97,0x7f,0x67,0x65,0x7b,0x8e,0x9b,0x99,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x73,0x73,0x7f,0x98,0xb0,0xa4 + ,0x8c,0x76,0x73,0x73,0x73,0x73,0x73,0x71,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x76,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x71,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98 + ,0xb0,0xa4,0x8c,0x74,0x68,0x71,0x73,0x74,0x84,0x94,0xa8,0xad,0x97,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x62,0x71,0x73,0x73,0x73,0x73,0x73,0x73,0x74,0x7c,0x8e,0xa4,0xa8,0x94,0x84,0x71,0x5c,0x49,0x36,0x21,0x0a,0x00,0x00,0x07 + ,0x1e,0x37,0x4f,0x67,0x7f,0x93,0xa8,0xa3,0x8e,0x7b,0x71,0x68,0x71,0x7b,0x8c,0x9d,0xa6,0x93,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x72,0x84,0x93,0x8c,0x7b,0x73,0x71,0x73,0x74,0x84,0x98,0xac,0xa3,0x8e,0x7b,0x65,0x4e,0x36 + ,0x1e,0x06,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x49,0x5c,0x71,0x84,0x8e,0x84,0x7b,0x73,0x6f,0x73,0x7b,0x8c,0x9d,0xb0,0xa2,0x8c,0x74,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x7f,0x98 + ,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x76,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x6a,0x5a,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x38,0x4f,0x67,0x7f,0x93,0xa8 + ,0xa8,0x93,0x7f,0x67,0x4f,0x46,0x5c,0x73,0x8c,0xa2,0xab,0x97,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5d,0x5b,0x5b,0x62,0x74,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00 + ,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x72,0x84,0x94,0xa6,0x9d,0x8c,0x7b,0x6a,0x57,0x41,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x73,0x8a,0x9d,0xa4,0x8e,0x7b,0x6a,0x5c,0x57,0x66,0x7b,0x8e,0xa3,0xa3,0x8e,0x7b + ,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x93,0xa6,0x9d,0x8c,0x7b,0x6a,0x5c,0x5b,0x5c,0x66,0x71,0x71,0x62,0x51,0x40,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x57,0x5c,0x6b + ,0x7f,0x98,0xae,0xa2,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xaa,0x98,0x7f,0x67,0x53,0x4f,0x61,0x74,0x8c,0xa4,0xa0,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4 + ,0x8c,0x73,0x5e,0x61,0x6b,0x7b,0x8c,0x9d,0xb0,0xa3,0x8e,0x7b,0x65,0x4e,0x36,0x1e,0x07,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0x99,0x84,0x8e,0x98,0x84,0x71,0x6b,0x7f,0x97,0x8e,0x84,0x99,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x43 + ,0x5b,0x73,0x89,0x8c,0x8c,0x8c,0x8e,0x9d,0xb3,0xa8,0x94,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5e,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x2b,0x15,0x02 + ,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5c,0x5a,0x5b,0x62,0x74,0x8a,0x9d,0xad,0x9d,0x8a,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5c,0x64,0x74,0x8a,0x9c,0xa9,0x9c,0x8a + ,0x74,0x62,0x51,0x3c,0x27,0x14,0x02,0x00,0x00,0x0e,0x25,0x3c,0x51,0x67,0x7f,0x98,0xaa,0x99,0x84,0x71,0x5d,0x54,0x5c,0x6b,0x7f,0x93,0xa6,0x9d,0x8a,0x73,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x62,0x72,0x7f,0x7b,0x6a,0x5c,0x5a,0x5b + ,0x66,0x7b,0x8e,0xa4,0xad,0x97,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x3c,0x51,0x62,0x72,0x7b,0x71,0x66,0x5c,0x59,0x5c,0x6b,0x7f,0x98,0xb0,0xa8,0x93,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x49,0x57 + ,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5e,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x38,0x25,0x10,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x74,0x8c,0xa2,0xae,0x98,0x7f,0x6b,0x57,0x4e,0x65,0x7b,0x8e,0xa4,0xa4,0x8e,0x7b,0x65,0x4e,0x37,0x21,0x0a,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x46,0x46,0x5b,0x73,0x8c,0xa4,0xb0 + ,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x74,0x7f,0x93,0xa4,0xa4,0x93,0x7f,0x6b,0x5a,0x49,0x36,0x21,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8e,0xa4,0xa2,0x8c,0x73 + ,0x5e,0x5a,0x5a,0x5d,0x71,0x84,0x99,0xa9,0x97,0x7f,0x67,0x4f,0x38,0x21,0x0a,0x00,0x00,0x02,0x15,0x2c,0x43,0x5b,0x73,0x8a,0x9d,0xaa,0x97,0x7f,0x6b,0x5b,0x57,0x5b,0x5a,0x57,0x5a,0x5a,0x51,0x40,0x2f,0x1e,0x0d,0x01,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67 + ,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x4f,0x5a,0x6b,0x7f,0x98,0xaa,0x99,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x97,0xa8,0x98,0x7f,0x6b,0x5b,0x51,0x61,0x74,0x8c,0xa4,0x99,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00 + ,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x4d,0x5a,0x6b,0x7f,0x93,0xa8,0xad,0x97,0x7f,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0x9d,0x8a,0x84,0x98,0x8c,0x74,0x73,0x8a,0x98,0x8a,0x7f,0x98,0xa4,0x8c + ,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa1,0xa4,0xa4,0xa4,0xae,0xbe,0xb5,0xa8,0xa4,0xa4,0xa4,0xa4,0xa4,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x67,0x67,0x67 + ,0x65,0x5c,0x57,0x4d,0x46,0x3c,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x46,0x44,0x56,0x6b,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2f,0x3c,0x42,0x43,0x43 + ,0x44,0x4b,0x5c,0x71,0x84,0x94,0xa7,0xa3,0x8e,0x7b,0x6a,0x57,0x41,0x2f,0x1b,0x06,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x99,0xaa,0x98,0x7f,0x67,0x51,0x40,0x4c,0x61,0x74,0x8c,0xa4,0xa4,0x8e,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x00,0x0a,0x1e + ,0x2f,0x40,0x51,0x61,0x67,0x65,0x5a,0x49,0x42,0x48,0x5c,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x51,0x61,0x65,0x5c,0x51,0x4a,0x4c,0x53,0x67,0x7f,0x98,0xb0,0xa4,0x8e,0x7b,0x65,0x4e,0x36,0x1e + ,0x06,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x36,0x40,0x43,0x43,0x43,0x43,0x43,0x43,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5e,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x4a + ,0x3a,0x27,0x16,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2c,0x43,0x5a,0x71,0x84,0x99,0xac,0x9d,0x8a,0x73,0x5b,0x51,0x67,0x7f,0x97,0xaa,0x9d,0x8a,0x73,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4 + ,0x8c,0x73,0x5b,0x4e,0x51,0x61,0x74,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x7c,0x8c,0x9d,0xac,0x99,0x84,0x72,0x61,0x4c,0x38,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x06 + ,0x1e,0x37,0x4f,0x67,0x7f,0x97,0xa9,0x99,0x84,0x71,0x66,0x71,0x71,0x66,0x68,0x7f,0x98,0xaa,0x98,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x74,0x8c,0xa4,0xa4,0x8e,0x7b,0x68,0x67,0x6b,0x73,0x71,0x67,0x65,0x5c,0x51,0x40,0x2f,0x1e + ,0x0c,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x67,0x67,0x6b,0x7b,0x8c,0x9d,0xa4,0x93,0x7f,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8e,0xa3,0x9d,0x8c,0x7b,0x71,0x67,0x6b,0x7f,0x93 + ,0xa1,0x93,0x7f,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x44,0x4c,0x61,0x74,0x8c,0xa4,0xb0,0x99,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x8c,0x7f,0x97 + ,0x93,0x7f,0x74,0x8c,0x98,0x7f,0x84,0x99,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0x98,0x98,0x98,0x9d,0xae,0xbd,0xae,0x9d,0x98,0x98,0x98,0x98,0x98,0x95,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e + ,0x65,0x7b,0x8e,0xa4,0xa4,0x8c,0x7c,0x7f,0x7f,0x7f,0x7b,0x73,0x6b,0x61,0x51,0x40,0x2f,0x1e,0x0c,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x46,0x47,0x5c,0x71,0x84,0x99,0xae,0xa2,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00 + ,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2b,0x33,0x46,0x5a,0x6a,0x7b,0x8e,0xa3,0xa7,0x94,0x84,0x71,0x5c,0x49,0x36,0x21,0x0d,0x00,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x99,0xaa,0x98,0x7f,0x67,0x52,0x44,0x49,0x5c,0x73,0x8c,0xa4,0xad,0x97,0x7f + ,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2f,0x40,0x4b,0x4f,0x4e,0x46,0x38,0x33,0x46,0x5c,0x73,0x8c,0xa4,0xad,0x97,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2f,0x40,0x4b,0x51,0x57,0x5b,0x5b,0x61,0x67,0x72 + ,0x84,0x99,0xa9,0x9c,0x8a,0x73,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c + ,0x76,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x67,0x7f,0x93,0xa8,0xa4,0x8c,0x74,0x61,0x5a,0x71,0x84,0x99,0xaa,0x98,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00 + ,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5f,0x65,0x67,0x71,0x7f,0x93,0xa8,0xa8,0x93,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8e,0x84,0x98,0xac,0xb0,0x98,0x7f,0x68,0x55,0x41,0x2b + ,0x17,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xaa,0x98,0x7f,0x6e,0x7b,0x84,0x84,0x7b,0x6e,0x7f,0x98,0xab,0x9d,0x8a,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x93,0xa8,0xa4,0x8c,0x73,0x72,0x7f + ,0x7f,0x8a,0x84,0x7f,0x7b,0x71,0x62,0x51,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8e,0x7f,0x7f,0x7f,0x7f,0x8c,0x9a,0x99,0x93,0x84,0x72,0x61,0x4b,0x34,0x1d,0x06,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x71 + ,0x84,0x94,0xa2,0x9c,0x8e,0x84,0x7f,0x7b,0x8c,0x9b,0x94,0x84,0x72,0x61,0x4b,0x34,0x1d,0x06,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x43,0x5b,0x73,0x8c,0xa4,0xb4,0xa2,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06 + ,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x8c,0x7c,0x8e,0x98,0x7f,0x7f,0x93,0x93,0x7f,0x8c,0xa2,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x7f,0x7f,0x7f,0x7f,0x8e,0xa4,0xb6,0xa4,0x8e,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7b,0x65,0x4e + ,0x36,0x1e,0x06,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x97,0xad,0xa8,0x94,0x8e,0x97,0x98,0x97,0x8e,0x8a,0x7f,0x72,0x62,0x51,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5e,0x5b,0x5c,0x68,0x7b,0x8e + ,0xa3,0xae,0x99,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x19,0x2b,0x40,0x52,0x66,0x7b,0x8c,0x9c,0xa9,0x9c,0x8a,0x74,0x62,0x51,0x3c,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x67,0x7f,0x98,0xaa,0x99,0x84,0x72 + ,0x62,0x5b,0x61,0x6b,0x7b,0x8e,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2b,0x34,0x37,0x36,0x30,0x2e,0x40,0x52,0x66,0x7b,0x8e,0xa4,0xa3,0x8e,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0d + ,0x1e,0x2d,0x40,0x57,0x6a,0x73,0x73,0x74,0x7f,0x84,0x94,0xa1,0x9c,0x8c,0x7b,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12,0x12,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00 + ,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa8,0x94,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1d,0x34,0x4b,0x61,0x74,0x8c,0xa4,0xa8,0x93,0x7f,0x67,0x5c,0x73,0x8c,0xa2,0xa8 + ,0x93,0x7f,0x67,0x4f,0x38,0x21,0x0a,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x76,0x73,0x7b,0x7f,0x84,0x8e,0x9d,0xaf,0xa2,0x8c,0x74,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb9,0xae,0x9d + ,0x99,0xa4,0xb8,0xb0,0x99,0x84,0x71,0x5c,0x46,0x31,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xaa,0x98,0x7f,0x73,0x8a,0x98,0x98,0x8c,0x7b,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37 + ,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x7c,0x84,0x93,0x98,0x9d,0x99,0x97,0x8e,0x84,0x72,0x62,0x51,0x3c,0x26,0x10,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xae,0x9d,0x98,0x98,0x98,0x98,0x9d,0x99,0x84,0x7f,0x72,0x63,0x56,0x44,0x31,0x1e,0x0a + ,0x00,0x00,0x00,0x00,0x00,0x10,0x26,0x3c,0x51,0x62,0x72,0x84,0x94,0xa5,0xa3,0x99,0x93,0x8e,0x9b,0x94,0x84,0x72,0x62,0x51,0x40,0x2b,0x15,0x02,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x43,0x5b,0x73,0x8c,0xa4,0xb6 + ,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x8c,0x79,0x8c,0x98,0x84,0x7f,0x97,0x8c,0x79,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x0e,0x25,0x3c,0x51,0x61,0x67,0x67,0x67,0x73,0x8c,0xa4,0xb6,0xa4 + ,0x8c,0x73,0x67,0x67,0x67,0x67,0x67,0x65,0x5a,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x97,0xa9,0xa8,0xa0,0x9e,0xa2,0xa4,0xa5,0xa4,0x9d,0x93,0x84,0x72,0x62,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98 + ,0xb0,0xa4,0x8c,0x76,0x73,0x73,0x73,0x7b,0x84,0x98,0xac,0xa4,0x93,0x7f,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0x25,0x38,0x4c,0x61,0x72,0x84,0x98,0xaa,0xa3,0x8e,0x7b,0x6a,0x57,0x41,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x07 + ,0x1e,0x37,0x4f,0x67,0x7f,0x93,0xa8,0xa4,0x94,0x84,0x74,0x73,0x74,0x7f,0x8c,0x9c,0xae,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x01,0x0a,0x15,0x1c,0x1e,0x1f,0x27,0x38,0x4c,0x61,0x72,0x84,0x98,0xa8,0x98,0x84,0x71,0x5c,0x46,0x30 + ,0x19,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x12,0x2a,0x43,0x5b,0x73,0x89,0x8c,0x8c,0x93,0x99,0xa1,0x94,0x8a,0x7b,0x6a,0x5a,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98 + ,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb5,0xa8,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2c,0x43,0x5b,0x73,0x8a + ,0x9d,0xab,0x98,0x7f,0x6b,0x65,0x7b,0x8e,0xa4,0xa2,0x8c,0x74,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb7,0xa8,0x94,0x8c,0x8c,0x8e,0x97,0x99,0xa3,0xa9,0xa3,0x94,0x84,0x71,0x5a,0x43,0x2c,0x15,0x02,0x00,0x00,0x00 + ,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xbc,0xbe,0xb3,0xb0,0xb0,0xb0,0xb4,0xa3,0x8e,0x7b,0x66,0x52,0x40,0x2b,0x16,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xaa,0x98,0x7f,0x7b,0x8e,0xa4,0xa9,0x97,0x7f,0x7f,0x98,0xb0,0xa4,0x8c + ,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa8,0x94,0x8e,0x97,0x98,0x98,0x98,0x9d,0xa5,0xa3,0x94,0x84,0x71,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb5,0xa8,0xa4,0xa4,0xa4,0xa4,0xa4 + ,0x9c,0x8e,0x84,0x7b,0x71,0x62,0x51,0x40,0x2b,0x16,0x03,0x00,0x00,0x00,0x02,0x14,0x27,0x38,0x49,0x5a,0x69,0x76,0x8c,0xa1,0xa4,0xa6,0xa6,0xa4,0xa3,0x8e,0x7b,0x71,0x62,0x51,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4 + ,0x8c,0x73,0x5b,0x43,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x8c,0x77,0x84,0x98,0x94,0x8e,0x96,0x84,0x77,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1b,0x2f + ,0x40,0x4b,0x4f,0x4f,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x4f,0x4f,0x4f,0x4f,0x4e,0x46,0x38,0x25,0x10,0x00,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8a,0x94,0x93,0x8c,0x8c,0x8c,0x8c,0x93,0x9d,0xaa,0xa4,0x94,0x84,0x71,0x5a,0x43,0x2c,0x15 + ,0x02,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa8,0x94,0x8c,0x8c,0x8c,0x8c,0x8e,0x98,0xa4,0xa8,0x98,0x84,0x72,0x61,0x4b,0x34,0x1d,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x31,0x46,0x5a,0x6b,0x7f,0x93,0xa4,0xa4,0x94,0x84,0x71,0x5c,0x49 + ,0x36,0x21,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x74,0x8a,0x9c,0xaa,0xa4,0x94,0x8c,0x8c,0x8c,0x93,0x96,0x99,0xa4,0xae,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x09,0x16,0x27,0x38,0x49,0x5a,0x6b + ,0x7f,0x93,0xa4,0xa3,0x8e,0x7b,0x66,0x51,0x3c,0x26,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa1,0xa4,0xa6,0xac,0xa4,0x8c,0x79,0x6f,0x62,0x51,0x40,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04 + ,0x06,0x06,0x04,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb5,0xa8,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x97,0xaa,0x9d,0x8a,0x73,0x67,0x7f,0x97,0xa9,0x99,0x84,0x71,0x5a,0x43,0x2c,0x15,0x02,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xbb,0xb5,0xa8,0xa4,0xa4,0xa4,0xad,0xb0,0xac,0x9c,0x8e,0x84 + ,0x72,0x62,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xbc,0xcb,0xbe,0xad,0x9d,0x99,0xa4,0xab,0x98,0x84,0x72,0x61,0x4c,0x36,0x21,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xaa,0x98,0x7f,0x74 + ,0x8a,0x9c,0x9d,0x8e,0x7b,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb1,0xa1,0x98,0x8e,0x84,0x7f,0x7f,0x8a,0x94,0xa7,0xa3,0x8e,0x7b,0x65,0x4e,0x37,0x21,0x0a,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67 + ,0x7f,0x98,0xb0,0xa8,0x94,0x8c,0x8c,0x8c,0x8c,0x8c,0x94,0x9f,0x98,0x8e,0x84,0x72,0x61,0x4c,0x36,0x21,0x0a,0x00,0x00,0x00,0x0b,0x21,0x36,0x49,0x5a,0x6a,0x7b,0x84,0x94,0x94,0x8c,0x93,0x99,0xa3,0xa9,0x9c,0x8e,0x84,0x72,0x62,0x51,0x3c,0x26,0x10,0x00,0x00 + ,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x8c,0x73,0x7f,0x93,0xa4,0xa2,0x93,0x7f,0x73,0x8c,0xa4,0xa4,0x8c + ,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x0c,0x1e,0x2b,0x34,0x37,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x37,0x37,0x37,0x36,0x30,0x25,0x16,0x04,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5a,0x6a,0x74,0x84,0x7f,0x74,0x73,0x73,0x74,0x7f + ,0x8c,0x9d,0xaf,0xa2,0x8c,0x74,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb5,0xa8,0xa4,0xa4,0xa4,0xa4,0xa4,0xa5,0xa2,0x94,0x8a,0x7b,0x66,0x52,0x40,0x2b,0x15,0x02,0x00,0x00,0x00,0x00,0x00,0x04,0x17,0x2b,0x40,0x52,0x66 + ,0x7b,0x8c,0x9d,0xaa,0x98,0x84,0x72,0x62,0x51,0x3c,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x41,0x57,0x6a,0x7b,0x8c,0x98,0xa2,0xa0,0xa0,0x9e,0x9b,0x93,0x84,0x84,0x99,0xaa,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x06,0x16,0x27,0x38,0x49,0x5a,0x6a,0x7b,0x8c,0x9d,0xa4,0x94,0x84,0x71,0x5c,0x46,0x31,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x12,0x2a,0x43,0x5b,0x73,0x8a,0x97,0x98,0x98,0x9d,0xa4,0x94,0x8a,0x7f,0x72,0x62,0x51,0x40,0x2b,0x16 + ,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x19,0x1e,0x1e,0x19,0x11,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa8,0x94,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x89,0x73,0x5b + ,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x37,0x4e,0x65,0x7b,0x8e,0xa4,0xa4,0x8c,0x74,0x71,0x84,0x99,0xa9,0x97,0x7f,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb9,0xae + ,0x9d,0x98,0x98,0x99,0xa4,0xb4,0xa4,0x8e,0x7b,0x71,0x62,0x51,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xbc,0xbe,0xad,0x9c,0x8c,0x84,0x94,0xa8,0xa4,0x93,0x7f,0x6b,0x57,0x41,0x2b,0x16,0x03,0x00,0x00,0x00,0x00,0x00,0x06 + ,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xaa,0x98,0x7f,0x6e,0x7b,0x8a,0x8a,0x7f,0x71,0x7f,0x98,0xab,0x9d,0x8a,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa8,0x94,0x84,0x7b,0x71,0x67,0x6b,0x76,0x8a,0x9d,0xaa,0x97,0x7f,0x6b,0x57 + ,0x40,0x28,0x11,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x76,0x73,0x73,0x73,0x74,0x84,0x94,0xa2,0xa3,0x93,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x02,0x15,0x2b,0x41,0x57,0x6a,0x7b,0x8c,0x98,0x94,0x84,0x76,0x7f,0x84,0x8e,0x98,0xa2 + ,0xa3,0x94,0x84,0x71,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x46,0x5c,0x73,0x8c,0xa4,0xb4,0xa2,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x8c,0x73,0x74 + ,0x8c,0xa2,0xa2,0x8c,0x74,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x01,0x0a,0x15,0x1c,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x1e,0x1e,0x1e,0x19,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x25,0x38 + ,0x49,0x57,0x62,0x71,0x6b,0x61,0x5b,0x5b,0x61,0x6c,0x7f,0x97,0xad,0xa8,0x93,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb5,0xa4,0x99,0x98,0x98,0x98,0x98,0x93,0x8c,0x84,0x74,0x6a,0x5a,0x46,0x31,0x1e,0x0a,0x00,0x00 + ,0x00,0x00,0x00,0x01,0x10,0x25,0x38,0x4c,0x61,0x72,0x84,0x98,0xaa,0x9d,0x8c,0x7b,0x66,0x52,0x40,0x2f,0x1c,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x0b,0x21,0x36,0x49,0x5a,0x6a,0x7b,0x84,0x8c,0x8e,0x93,0x8c,0x8a,0x7f,0x76,0x84,0x99,0xaa,0x98,0x7f + ,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x27,0x38,0x49,0x5a,0x6a,0x7b,0x8c,0x9c,0xa2,0x94,0x84,0x72,0x62,0x51,0x3c,0x26,0x10,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x2c,0x40,0x57,0x6a,0x7b,0x7f,0x7f,0x7f,0x8a + ,0x93,0x9c,0x9d,0x93,0x84,0x72,0x61,0x4c,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x25,0x30,0x36,0x36,0x30,0x25,0x21,0x38,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c + ,0x76,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x73,0x8a,0x9d,0xa6,0x93,0x7f,0x73,0x8c,0xa2,0xa4,0x8e,0x7b,0x65,0x4e,0x36,0x1e,0x07,0x00,0x00,0x00,0x00 + ,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8e,0x7f,0x7f,0x84,0x94,0xa8,0xa8,0x93,0x7f,0x6b,0x57,0x44,0x31,0x1e,0x0c,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xbb,0xb3,0x9d,0x8c,0x7b,0x74,0x8a,0x9d,0xad,0x9d,0x8a,0x74,0x61 + ,0x4c,0x36,0x21,0x0b,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xaa,0x98,0x7f,0x6b,0x6a,0x73,0x73,0x6b,0x69,0x7f,0x98,0xaa,0x98,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x97,0xad,0xa4,0x8c,0x74,0x66,0x5c + ,0x51,0x58,0x6b,0x7f,0x98,0xab,0x9d,0x8a,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5e,0x5b,0x5b,0x62,0x72,0x84,0x99,0xac,0x9d,0x8a,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x74,0x8a + ,0x9c,0x9d,0x8a,0x74,0x65,0x67,0x71,0x7b,0x84,0x94,0xa7,0xa3,0x8e,0x7b,0x65,0x4e,0x36,0x1e,0x07,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x44,0x4e,0x65,0x7b,0x8e,0xa4,0xb0,0x99,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x06 + ,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x8c,0x73,0x71,0x84,0x99,0x99,0x84,0x71,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x02,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x1e,0x1e,0x1e,0x19,0x10 + ,0x04,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0x25,0x38,0x46,0x4e,0x55,0x5a,0x57,0x4c,0x43,0x43,0x50,0x65,0x7b,0x8e,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa8,0x94,0x84,0x7f,0x7f,0x7f,0x7f,0x7f,0x74 + ,0x71,0x62,0x57,0x49,0x38,0x25,0x10,0x01,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x31,0x46,0x5a,0x6b,0x7f,0x93,0xa4,0xa4,0x93,0x7f,0x6b,0x5a,0x46,0x33,0x2b,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x38,0x49,0x5a,0x66,0x71,0x73,0x7b + ,0x7f,0x74,0x73,0x6b,0x73,0x8c,0xa2,0xa8,0x93,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2f,0x3c,0x49,0x5a,0x6a,0x7b,0x8c,0x9c,0xa5,0x94,0x84,0x72,0x62,0x51,0x40,0x31,0x26,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x04,0x16,0x27 + ,0x36,0x40,0x43,0x4b,0x5a,0x65,0x67,0x67,0x6b,0x74,0x7f,0x8e,0xa4,0xa4,0x93,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x05,0x16,0x27,0x38,0x46,0x4e,0x4e,0x46,0x38,0x2e,0x40,0x57,0x6b,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00 + ,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5e,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x22,0x0f,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x98,0xaa,0x98,0x7f,0x7b,0x8e,0xa4,0x9d,0x8a + ,0x73,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x67,0x74,0x8a,0x9d,0xad,0x9d,0x8a,0x74,0x61,0x4c,0x38,0x25,0x10,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb7,0xa8,0x93 + ,0x7f,0x6b,0x6b,0x7f,0x93,0xa8,0xa8,0x93,0x7f,0x6b,0x57,0x41,0x2b,0x16,0x03,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x93,0xa6,0x9d,0x8a,0x73,0x5f,0x5b,0x5b,0x5d,0x71,0x84,0x99,0xa9,0x97,0x7f,0x67,0x4f,0x38,0x21,0x0a,0x00,0x00,0x06,0x1e,0x36 + ,0x4e,0x65,0x7b,0x8e,0xa4,0xa4,0x8c,0x74,0x61,0x4d,0x3e,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x47,0x48,0x55,0x68,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a + ,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x93,0xa6,0x98,0x7f,0x6b,0x57,0x51,0x5c,0x66,0x74,0x8a,0x9d,0xaa,0x97,0x7f,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x4d,0x5a,0x6b,0x7f,0x97,0xad,0xad + ,0x97,0x7f,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x8e,0x7b,0x6c,0x7f,0x92,0x95,0x7f,0x67,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4 + ,0x8c,0x73,0x5b,0x43,0x35,0x37,0x37,0x36,0x30,0x25,0x16,0x04,0x00,0x00,0x00,0x00,0x0a,0x1e,0x31,0x46,0x5a,0x65,0x67,0x61,0x52,0x46,0x43,0x43,0x50,0x65,0x7b,0x8e,0xa4,0xad,0x97,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98 + ,0xb0,0xa4,0x8c,0x74,0x67,0x67,0x67,0x67,0x67,0x61,0x5a,0x51,0x41,0x36,0x27,0x16,0x04,0x00,0x00,0x00,0x00,0x00,0x04,0x17,0x2b,0x40,0x52,0x66,0x7b,0x8c,0x9d,0xaa,0x98,0x84,0x72,0x61,0x4d,0x44,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00 + ,0x00,0x08,0x1a,0x2b,0x3c,0x4c,0x55,0x5a,0x5c,0x65,0x67,0x61,0x5c,0x66,0x7b,0x8e,0xa4,0xa4,0x8c,0x74,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2f,0x40,0x51,0x5c,0x6a,0x7b,0x8c,0x9c,0xa2,0x98,0x8a,0x74,0x62,0x51,0x47,0x43,0x42,0x3c,0x2f + ,0x1e,0x0a,0x00,0x00,0x00,0x00,0x01,0x10,0x25,0x38,0x49,0x57,0x5b,0x5a,0x52,0x4e,0x4f,0x4f,0x57,0x62,0x73,0x8a,0x9d,0xad,0x9d,0x8a,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x04,0x16,0x27,0x38,0x49,0x5a,0x65,0x65,0x5a,0x4c,0x41,0x43,0x5b,0x73,0x8a,0x9d + ,0xb1,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x49,0x49,0x49,0x49,0x49,0x49,0x47,0x43,0x3c,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x38,0x4f,0x67 + ,0x7f,0x93,0xa6,0x9d,0x8a,0x7f,0x97,0xa7,0x97,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5e,0x6b,0x7f,0x93,0xa8,0xa8,0x93,0x7f,0x6b,0x5a,0x46,0x31,0x1b,0x06,0x00,0x00,0x00,0x00 + ,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x74,0x61,0x61,0x74,0x8a,0x9d,0xad,0x9d,0x8a,0x74,0x61,0x4c,0x36,0x21,0x0d,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x74,0x8c,0xa2,0xa4,0x8e,0x7b,0x66,0x52,0x4d,0x61,0x74,0x8c,0xa2,0xa4,0x8e,0x7b + ,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x73,0x8a,0x9d,0xa6,0x93,0x7f,0x67,0x53,0x47,0x52,0x67,0x7f,0x98,0xab,0x9d,0x8a,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x51,0x5a,0x61 + ,0x71,0x84,0x99,0xae,0xa2,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xaa,0x98,0x7f,0x67,0x52,0x45,0x4a,0x57,0x6b,0x7f,0x98,0xaa,0x99,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4 + ,0x8c,0x73,0x5e,0x61,0x6b,0x7b,0x8c,0x9d,0xaf,0xa3,0x8e,0x7b,0x65,0x4e,0x36,0x1e,0x07,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa8,0x97,0x7f,0x69,0x72,0x7f,0x7f,0x7b,0x66,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa2,0xb4,0xa4,0x8c,0x73,0x5c,0x4e,0x4b,0x4f,0x4f,0x4e,0x46,0x38,0x25,0x10,0x00,0x00,0x00,0x03,0x16,0x2b,0x40,0x52,0x66,0x7b,0x7f,0x72,0x66,0x5c,0x5b,0x5b,0x61,0x6c,0x7f,0x97,0xad,0xa4,0x8e,0x7b,0x65,0x4e,0x36,0x1e + ,0x06,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x4f,0x4f,0x4f,0x4f,0x4b,0x43,0x3c,0x2f,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x25,0x38,0x4c,0x61,0x72,0x84,0x98,0xaa,0x9d,0x8c,0x7b,0x66,0x5c,0x5b,0x5b,0x5b,0x5b + ,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x02,0x14,0x27,0x38,0x49,0x5a,0x65,0x65,0x5c,0x56,0x55,0x54,0x5d,0x71,0x84,0x98,0xaa,0x9d,0x8a,0x73,0x5b,0x43,0x2c,0x15,0x02,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x40,0x51,0x62,0x71,0x7b,0x8c,0x9c,0xa2,0x94 + ,0x84,0x7b,0x6a,0x5d,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x2b,0x15,0x02,0x00,0x00,0x00,0x0a,0x1e,0x31,0x46,0x5a,0x6a,0x73,0x71,0x62,0x57,0x4f,0x4f,0x51,0x5d,0x71,0x84,0x99,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x10,0x25,0x38,0x49,0x5a,0x6a + ,0x7b,0x7b,0x6b,0x61,0x57,0x51,0x61,0x74,0x8c,0xa4,0xb1,0x9d,0x8a,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5e,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x2b,0x15,0x02,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x74,0x8c,0xa2,0xa4,0x8e,0x84,0x99,0xa4,0x8e,0x7b,0x65,0x4e,0x37,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x61,0x74,0x8a,0x9d,0xad,0x9d,0x8c + ,0x7b,0x66,0x51,0x3c,0x26,0x10,0x01,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x57,0x6b,0x7f,0x93,0xa8,0xa8,0x93,0x7f,0x6b,0x57,0x41,0x2f,0x1b,0x06,0x00,0x00,0x00,0x02,0x15,0x2c,0x43,0x5a,0x71,0x84,0x98,0xa8,0x98,0x84 + ,0x72,0x66,0x61,0x6c,0x7f,0x93,0xa6,0x9d,0x8a,0x73,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x97,0xa9,0x99,0x84,0x72,0x66,0x5e,0x66,0x72,0x84,0x99,0xa9,0x97,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67 + ,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x67,0x67,0x71,0x74,0x7f,0x8e,0xa3,0xae,0x99,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x97,0xa9,0x99,0x84,0x72,0x62,0x5b,0x5b,0x61,0x71,0x84,0x99,0xaa,0x98,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00 + ,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x76,0x73,0x74,0x7f,0x8c,0x9c,0xad,0xa8,0x94,0x84,0x71,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xaa,0x98,0x7f,0x67,0x61,0x67,0x67,0x65,0x5f,0x73,0x8c,0xa4,0xa4,0x8c + ,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x99,0xb0,0xa4,0x8e,0x7b,0x6b,0x65,0x61,0x67,0x67,0x65,0x5a,0x46,0x30,0x19,0x04,0x00,0x00,0x0a,0x21,0x36,0x4c,0x61,0x72,0x84,0x91,0x84,0x7b,0x73,0x73,0x73,0x74,0x7f + ,0x8c,0x9d,0xad,0x9d,0x8a,0x73,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x37,0x37,0x37,0x34,0x2c,0x25,0x1b,0x0d,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5a,0x6b,0x7f,0x93,0xa4 + ,0xae,0x98,0x7f,0x74,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x0b,0x21,0x36,0x49,0x5a,0x6a,0x7b,0x7b,0x71,0x67,0x67,0x67,0x71,0x7b,0x8e,0xa3,0xa8,0x93,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x02,0x15,0x2b + ,0x40,0x51,0x62,0x72,0x84,0x8e,0x9c,0xa9,0x99,0x84,0x77,0x73,0x73,0x73,0x73,0x73,0x73,0x71,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x02,0x15,0x2b,0x40,0x52,0x66,0x7b,0x8a,0x84,0x74,0x6b,0x67,0x67,0x67,0x71,0x7b,0x8e,0xa3,0xb0,0x9d,0x8a,0x73,0x5b,0x43,0x2a + ,0x12,0x00,0x00,0x04,0x19,0x30,0x46,0x5a,0x6a,0x7b,0x8c,0x8c,0x7f,0x74,0x6b,0x67,0x71,0x7f,0x93,0xa8,0xad,0x97,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x76,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x71 + ,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2c,0x43,0x5a,0x71,0x84,0x99,0xa9,0x9d,0x99,0xa4,0xa2,0x8c,0x73,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4 + ,0x8c,0x73,0x5b,0x57,0x6b,0x7f,0x93,0xa8,0xac,0x98,0x84,0x71,0x5c,0x46,0x31,0x1e,0x0a,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x4d,0x61,0x74,0x8a,0x9d,0xad,0x9d,0x8a,0x74,0x62,0x51,0x3c,0x26,0x10,0x00,0x00,0x00,0x00 + ,0x0e,0x25,0x3c,0x51,0x66,0x7b,0x8e,0xa3,0xa4,0x94,0x84,0x7b,0x74,0x7f,0x8c,0x9d,0xa4,0x93,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x0a,0x21,0x37,0x4e,0x65,0x7b,0x8c,0x9d,0xa4,0x94,0x84,0x7b,0x73,0x7b,0x84,0x94,0xa4,0xa3,0x8e,0x7b,0x65,0x4e + ,0x37,0x21,0x0a,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8e,0x7f,0x7f,0x7f,0x84,0x8c,0x93,0x9d,0xab,0xa4,0x93,0x7f,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8e,0xa3,0xa4,0x94,0x84,0x74,0x73,0x73,0x74,0x7f,0x8e + ,0xa3,0xa8,0x93,0x7f,0x67,0x4f,0x38,0x21,0x0a,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb7,0xa8,0x94,0x8c,0x8c,0x8c,0x93,0x9d,0xab,0xac,0x9c,0x8a,0x74,0x62,0x51,0x3c,0x26,0x10,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xaa,0x98,0x7f,0x67 + ,0x51,0x4f,0x4f,0x4e,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x67,0x7f,0x93,0xa8,0xae,0x9c,0x8c,0x7f,0x7b,0x74,0x7f,0x7f,0x7b,0x65,0x4e,0x37,0x21,0x0a,0x00,0x00,0x11,0x28,0x40,0x57,0x6b + ,0x7f,0x93,0xa0,0x98,0x8e,0x8c,0x8c,0x8c,0x8c,0x93,0x9d,0xaa,0xa4,0x93,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x1e,0x1e,0x1c,0x15,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8c,0x9d,0xb3,0xb3,0x9d,0x8e,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x02,0x15,0x2b,0x41,0x57,0x6a,0x7b,0x8c,0x8e,0x84,0x7f,0x7f,0x7f,0x84,0x8e,0x9c,0xa9,0x9c,0x8a,0x74,0x61 + ,0x4c,0x36,0x21,0x0a,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x72,0x84,0x94,0xa3,0xae,0xb3,0x9d,0x8e,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x72,0x84,0x98,0x94,0x8a,0x7f,0x7f,0x7f,0x7f,0x84 + ,0x8e,0x9c,0xae,0xa8,0x93,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8c,0x9c,0x9d,0x93,0x8a,0x7f,0x7f,0x84,0x8e,0x9d,0xb0,0xa3,0x8e,0x7b,0x65,0x4e,0x37,0x21,0x0a,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa8,0x94 + ,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x67,0x7f,0x93,0xa8,0xb1,0xb0,0xae,0x99,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x4d,0x61,0x74,0x8a,0x9d,0xb0,0xa3,0x8e,0x7b,0x66,0x52,0x40,0x2b,0x15,0x02,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x47,0x57,0x6b,0x7f,0x93,0xa8,0xa8,0x94 + ,0x84,0x71,0x5c,0x46,0x31,0x1b,0x06,0x00,0x00,0x00,0x06,0x1b,0x31,0x46,0x5c,0x71,0x84,0x94,0xa4,0xa4,0x98,0x8e,0x8c,0x93,0x9d,0xa5,0x98,0x84,0x72,0x61,0x4c,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5a,0x6b,0x7f,0x93,0xa3,0xa2,0x98,0x8e + ,0x8c,0x8e,0x98,0xa4,0xa4,0x94,0x84,0x71,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xae,0x9d,0x98,0x98,0x98,0x99,0xa2,0xa6,0xaa,0xa3,0x94,0x84,0x72,0x61,0x4b,0x34,0x1d,0x06,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x71,0x84 + ,0x97,0xa4,0xa4,0x94,0x8c,0x8c,0x8c,0x8c,0x93,0x9d,0xa5,0x9c,0x8a,0x74,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb8,0xb3,0xa8,0xa4,0xa4,0xa4,0xa6,0xaa,0xa3,0x98,0x8c,0x7b,0x6a,0x57,0x41,0x2f,0x1b,0x06,0x00,0x00,0x00,0x06 + ,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xaa,0x98,0x7f,0x67,0x4f,0x3a,0x37,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1d,0x34,0x4b,0x61,0x74,0x8a,0x9c,0xad,0xad,0x9d,0x97,0x8e,0x8c,0x93,0x95,0x7f,0x6b,0x57 + ,0x40,0x28,0x11,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x8e,0x98,0xa1,0xa3,0xa4,0xa4,0xa4,0xa4,0xa6,0xa6,0x9d,0x93,0x84,0x72,0x61,0x4c,0x36,0x21,0x0a,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x06,0x05 + ,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x97,0xac,0xb8,0xb8,0xae,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x74,0x8a,0x9c,0xa3,0x99,0x98 + ,0x98,0x98,0x99,0xa3,0xa8,0x9c,0x8c,0x7b,0x6a,0x57,0x41,0x2b,0x16,0x03,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x93,0xa4,0xb3,0xb9,0xb8,0xae,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67 + ,0x7f,0x90,0x9f,0xa5,0x9d,0x98,0x98,0x98,0x98,0x99,0xa3,0xab,0xaa,0x9c,0x8a,0x74,0x61,0x4c,0x36,0x21,0x0a,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8c,0x9c,0xaa,0xa8,0x9d,0x98,0x98,0x99,0xa3,0xab,0xa4,0x97,0x84,0x71,0x5c,0x46,0x30,0x19,0x04,0x00,0x00 + ,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb3,0xa8,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1d,0x34,0x4b,0x61,0x74,0x8c,0xa1,0xa4,0xa4,0xa2,0x93,0x7f,0x67 + ,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa1,0xa4,0xa1,0x8c,0x73,0x5b,0x47,0x57,0x6b,0x7f,0x93,0xa2,0xa2,0x98,0x84,0x72,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa1,0xa4,0xa1,0x8c + ,0x73,0x5b,0x43,0x4c,0x61,0x74,0x8a,0x9d,0xa4,0x9f,0x8e,0x7b,0x66,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x10,0x26,0x3c,0x51,0x62,0x72,0x84,0x93,0x9d,0xa5,0xa4,0xa4,0xa2,0xa2,0x94,0x8a,0x7b,0x66,0x52,0x40,0x2b,0x16,0x03,0x00,0x00,0x00,0x00,0x00,0x10 + ,0x25,0x38,0x4c,0x61,0x72,0x84,0x8e,0x98,0xa1,0xa3,0xa4,0xa3,0xa3,0x9d,0x93,0x84,0x72,0x62,0x51,0x3c,0x26,0x10,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa2,0x99,0x97,0x8e,0x84,0x72,0x62,0x51,0x40,0x2b,0x15 + ,0x02,0x00,0x00,0x00,0x10,0x26,0x3c,0x51,0x66,0x7b,0x84,0x93,0x9d,0xa0,0xa2,0xa4,0xa4,0xa2,0xa0,0x9d,0x93,0x8a,0x7b,0x6a,0x57,0x41,0x2b,0x15,0x02,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa1,0xa4,0xa4,0xa4,0xa4,0xa4,0xa2,0x99,0x97,0x8e,0x84,0x7b,0x6a + ,0x5a,0x49,0x36,0x21,0x0d,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0x98,0x7f,0x67,0x4f,0x37,0x2a,0x43,0x5b,0x73,0x8c,0xa1,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x41,0x57,0x6a,0x7b,0x8c,0x9c + ,0xa4,0xaa,0xa8,0xa4,0xa2,0xa0,0x9b,0x8a,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x0e,0x25,0x3c,0x51,0x62,0x71,0x7b,0x84,0x8e,0x97,0x9d,0xa4,0xa4,0xa2,0x99,0x93,0x8a,0x7f,0x72,0x62,0x51,0x40,0x2b,0x16,0x03,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98 + ,0xa4,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06 + ,0x1e,0x36,0x4e,0x65,0x7b,0x84,0x93,0x9d,0xa4,0xa6,0xaa,0xaa,0xa6,0xa2,0x98,0x8c,0x7b,0x6a,0x5a,0x49,0x36,0x21,0x0b,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0x98,0x7f,0x67,0x4f + ,0x37,0x1e,0x06,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x72,0x84,0x8e,0x98,0xa2,0xa4,0xa8,0xaa,0xaa,0xa9,0xa4,0x9d,0x93,0x8a,0x7b,0x6a,0x57,0x41,0x2b,0x16,0x03,0x00,0x00,0x04,0x19,0x30,0x46,0x5a,0x6a,0x7b,0x8c,0x98,0xa2,0xa6,0xaa,0xaa,0xa9,0xa4,0x9d,0x93 + ,0x84,0x7b,0x66,0x51,0x3c,0x26,0x10,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2c,0x43 + ,0x5b,0x73,0x89,0x8c,0x8c,0x8c,0x8c,0x89,0x74,0x61,0x4b,0x34,0x1d,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x89,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x4c,0x61,0x72,0x84,0x8c,0x8c,0x8c,0x8a,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00 + ,0x12,0x2a,0x43,0x5b,0x73,0x89,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x41,0x57,0x6b,0x7f,0x8c,0x8c,0x8c,0x8c,0x82,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x51,0x62,0x72,0x7f,0x8a,0x93,0x98,0x98,0x93,0x8c,0x84,0x74,0x6a,0x5a,0x46 + ,0x31,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x17,0x2b,0x40,0x51,0x62,0x71,0x7b,0x84,0x8e,0x97,0x98,0x97,0x8e,0x8a,0x7f,0x72,0x62,0x51,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c + ,0x84,0x7f,0x7b,0x71,0x62,0x51,0x40,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x06,0x1b,0x31,0x46,0x5a,0x66,0x72,0x7f,0x8a,0x8e,0x97,0x98,0x98,0x97,0x8e,0x8a,0x7f,0x74,0x6a,0x5a,0x49,0x36,0x21,0x0b,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x89,0x8c,0x8c,0x8c + ,0x8c,0x8c,0x8c,0x8c,0x84,0x7f,0x7b,0x71,0x66,0x5a,0x49,0x38,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x7f,0x67,0x4f,0x37,0x2a,0x43,0x5b,0x73,0x89,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x0b,0x21,0x36,0x49,0x5a,0x6a,0x7b,0x8a,0x8e,0x97,0x98,0x98,0x97,0x8e,0x8c,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x06,0x1b,0x2f,0x40,0x51,0x5c,0x66,0x71,0x7b,0x7f,0x8a,0x8c,0x8c,0x8c,0x84,0x7f,0x74,0x6b,0x61,0x51,0x40,0x2f,0x1e,0x0a,0x00 + ,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c + ,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x04,0x19,0x30,0x46,0x5a,0x66,0x72,0x7f,0x8a,0x8c,0x93,0x98,0x98,0x93,0x8c,0x84,0x7b,0x6a,0x5a,0x49,0x38,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c + ,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x62,0x71,0x7b,0x84,0x8c,0x8e,0x97,0x98,0x98,0x97,0x8e,0x8a,0x7f,0x74,0x6a,0x5a,0x49,0x36,0x21,0x0b,0x00,0x00,0x00,0x00,0x10,0x25,0x38,0x49,0x5a,0x6a + ,0x7b,0x84,0x8c,0x93,0x98,0x98,0x97,0x8e,0x8a,0x7f,0x72,0x66,0x5a,0x46,0x31,0x1b,0x06,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x73,0x73,0x73,0x73,0x6a,0x57,0x41,0x2b,0x15,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x40,0x51,0x62,0x71,0x73,0x73 + ,0x73,0x73,0x71,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x36,0x4c,0x61,0x71,0x73,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2f,0x40,0x51,0x61,0x6b,0x74 + ,0x7f,0x7f,0x7f,0x7f,0x74,0x71,0x62,0x57,0x49,0x38,0x25,0x10,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x40,0x51,0x5c,0x66,0x71,0x7b,0x7f,0x7f,0x7f,0x7b,0x73,0x6b,0x61,0x51,0x40,0x2f,0x1e,0x0c,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61 + ,0x71,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x71,0x67,0x65,0x5c,0x51,0x40,0x2f,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x10,0x25,0x38,0x46,0x52,0x61,0x6b,0x73,0x7b,0x7f,0x7f,0x7f,0x7f,0x7b,0x73,0x6b,0x61,0x57,0x49,0x38,0x27,0x14,0x02,0x00,0x00 + ,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x71,0x67,0x65,0x5c,0x51,0x46,0x38,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x71,0x61,0x4b,0x34,0x28,0x40,0x57,0x6a,0x73,0x73,0x73,0x73 + ,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x38,0x49,0x5a,0x6a,0x73,0x7b,0x7f,0x7f,0x7f,0x7f,0x7b,0x73,0x71,0x62,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x0c,0x1e,0x2f,0x3c,0x46,0x51,0x5c,0x65,0x6b,0x73,0x73,0x73,0x73,0x71 + ,0x67,0x61,0x57,0x4c,0x40,0x2f,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73 + ,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x10,0x25,0x38,0x46,0x52,0x61,0x6b,0x73,0x74,0x7f,0x7f,0x7f,0x7f,0x74,0x71,0x66,0x5a,0x49,0x38,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x05,0x1c,0x34 + ,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x71,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x40,0x51,0x5c,0x66,0x71,0x73,0x7b,0x7f,0x7f,0x7f,0x7f,0x7b,0x73,0x6b,0x61,0x57,0x49,0x38,0x27,0x14,0x02 + ,0x00,0x00,0x00,0x00,0x04,0x16,0x27,0x38,0x49,0x5a,0x66,0x71,0x74,0x7f,0x7f,0x7f,0x7f,0x7b,0x73,0x6b,0x61,0x52,0x46,0x38,0x25,0x10,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x71 + ,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x5b + ,0x5b,0x57,0x49,0x36,0x2f,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x2b,0x15,0x02,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x00 + ,0x00,0x00,0x01,0x0d,0x1e,0x2f,0x40,0x4c,0x57,0x61,0x67,0x67,0x67,0x67,0x61,0x5a,0x51,0x41,0x36,0x27,0x16,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2f,0x3c,0x46,0x51,0x5c,0x65,0x67,0x67,0x67,0x65,0x5c,0x57,0x4c,0x40,0x2f,0x1e,0x0d + ,0x01,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x4e,0x46,0x3c,0x2f,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x16,0x25,0x31,0x40,0x4c,0x57,0x5c,0x65,0x67,0x67,0x67,0x67,0x65,0x5c + ,0x57,0x4c,0x41,0x36,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x4e,0x46,0x3c,0x31,0x25,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5a,0x51 + ,0x40,0x2b,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x27,0x38,0x49,0x57,0x5c,0x65,0x67,0x67,0x67,0x67,0x65,0x5c,0x5a,0x51,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x01,0x0c,0x1b,0x26 + ,0x31,0x3c,0x46,0x4e,0x57,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x4b,0x41,0x36,0x2b,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x04,0x16,0x25,0x31,0x40,0x4c,0x57,0x5b,0x61,0x67,0x67,0x67,0x67,0x61,0x5a,0x51,0x46,0x38,0x27,0x16 + ,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x2b,0x15,0x02,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2f,0x3c,0x46,0x51,0x5a,0x5c,0x65,0x67,0x67,0x67,0x67 + ,0x65,0x5c,0x57,0x4c,0x41,0x36,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x27,0x38,0x46,0x51,0x5a,0x61,0x67,0x67,0x67,0x67,0x65,0x5c,0x57,0x4c,0x40,0x31,0x25,0x16,0x04,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b + ,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x2b,0x15,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x36,0x40,0x43,0x43,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x02,0x14,0x27,0x36,0x40,0x43,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x42,0x3c,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x02,0x14,0x27,0x36,0x40,0x43,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43 + ,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2b,0x36,0x41,0x4b,0x4f,0x4f,0x4f,0x4f,0x4b,0x43,0x3c,0x2f,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x26,0x31,0x3c,0x46,0x4e,0x4f + ,0x4f,0x4f,0x4e,0x46,0x40,0x36,0x2b,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x42,0x3c,0x36,0x30,0x26,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x1e,0x2b + ,0x36,0x40,0x46,0x4e,0x4f,0x4f,0x4f,0x4f,0x4e,0x46,0x40,0x36,0x2b,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x36,0x40,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x42,0x3c,0x36,0x30,0x26,0x1b,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x42,0x3c,0x2f,0x1e,0x14,0x27,0x36,0x40,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x27,0x36,0x40,0x46,0x4e,0x4f,0x4f,0x4f,0x4f,0x4e,0x46,0x42,0x3c,0x2f + ,0x1e,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x10,0x1b,0x26,0x30,0x37,0x40,0x43,0x43,0x43,0x43,0x42,0x3c,0x34,0x2b,0x21,0x16,0x0a,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x04,0x10,0x1e,0x2b,0x36,0x40,0x43,0x4b,0x4f + ,0x4f,0x4f,0x4f,0x4b,0x43,0x3c,0x31,0x25,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x42,0x3c,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b + ,0x26,0x31,0x3c,0x42,0x46,0x4e,0x4f,0x4f,0x4f,0x4f,0x4e,0x46,0x40,0x36,0x2b,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x25,0x31,0x3c,0x43,0x4b,0x4f,0x4f,0x4f,0x4f,0x4e,0x46,0x40,0x36,0x2b,0x1e,0x10,0x04,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x42,0x3c,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21 + ,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a + ,0x28,0x21,0x14,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0a,0x16,0x21,0x2b,0x34,0x37,0x37,0x37,0x37,0x34,0x2c,0x25,0x1b,0x0d,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x06,0x10,0x1b,0x26,0x30,0x36,0x37,0x37,0x37,0x36,0x30,0x28,0x21,0x16,0x0a,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1e,0x19,0x10,0x06,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0a,0x16,0x21,0x28,0x30,0x36,0x37,0x37,0x37,0x37,0x36,0x30,0x28,0x21,0x16,0x0b,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1e,0x19,0x10,0x06 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x0c,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x30 + ,0x36,0x37,0x37,0x37,0x37,0x36,0x30,0x2a,0x25,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x10,0x19,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1d,0x15,0x0b,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a + ,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x01,0x0a,0x16,0x21,0x28,0x2c,0x34,0x37,0x37,0x37,0x37,0x34,0x2c,0x25,0x1b,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1b + ,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x10,0x1b,0x25,0x2a,0x30,0x36,0x37,0x37,0x37,0x37,0x36,0x30,0x28,0x21,0x16,0x0b,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x1b,0x25,0x2c,0x34,0x37,0x37,0x37,0x37,0x36,0x30,0x28 + ,0x21,0x16,0x0a,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02 + ,0x0a,0x11,0x12,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0b,0x15,0x1c,0x1e,0x1e,0x1e,0x1e,0x1c,0x15,0x0e,0x06,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x10,0x19,0x1e,0x1e,0x1e,0x1e,0x1e,0x19,0x11,0x0a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12 + ,0x12,0x0e,0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0a,0x11,0x19,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x19,0x11,0x0a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12,0x12 + ,0x12,0x12,0x12,0x12,0x12,0x0e,0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x19,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x19,0x12,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x0a,0x11,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12 + ,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0a,0x11,0x15,0x1c,0x1e,0x1e,0x1e,0x1e,0x1c,0x15,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12 + ,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x19,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x19,0x11,0x0a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06 + ,0x0e,0x15,0x1c,0x1e,0x1e,0x1e,0x1e,0x1e,0x19,0x11,0x0a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x11,0x0a,0x0e,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x01,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x01,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x11 + ,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12 + ,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12 + ,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x05,0x06,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x05,0x06,0x05,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12 + ,0x12,0x12,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x0a,0x11,0x12,0x12,0x12,0x12,0x12,0x0e,0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x06,0x0e + ,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x05,0x0a,0x11,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x04,0x0a,0x11,0x12,0x12,0x12,0x12,0x11,0x0a,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x0a,0x11,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x1b,0x25,0x2a,0x2a,0x2a,0x2a + ,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x28,0x21,0x25,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x11,0x1b,0x25 + ,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x11,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a + ,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a + ,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c + ,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x06,0x0a,0x11,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0b,0x15,0x1c,0x1e,0x19,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x01,0x0a,0x15,0x1c,0x1e,0x1c,0x15,0x0a,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x10,0x19,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1e,0x19,0x10,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x02,0x0b,0x15,0x1d,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1d,0x15,0x0b,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0b,0x15,0x1c,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1d,0x15,0x0b,0x02,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x10,0x19,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x19,0x10,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x10,0x19,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a + ,0x25,0x1d,0x15,0x0b,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x0c,0x01,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x02,0x14,0x27,0x36,0x40,0x43,0x43,0x43,0x43 + ,0x43,0x40,0x36,0x27,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x40,0x36,0x3c,0x42,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x36,0x40 + ,0x43,0x43,0x43,0x43,0x42,0x3c,0x2f,0x23,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x02,0x14,0x27,0x36,0x40,0x43,0x43,0x43,0x43,0x42,0x3c,0x2f,0x23,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00 + ,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x43,0x42,0x3c,0x2f + ,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x42,0x3c,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x19,0x1e,0x21,0x28,0x31,0x3c,0x42,0x43,0x43,0x43 + ,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0a,0x16,0x21,0x2b,0x34,0x36,0x30,0x25,0x16,0x04,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2b,0x34,0x37,0x34,0x2b,0x1e,0x10,0x04,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x42,0x3c,0x31,0x25,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x1b,0x26,0x30,0x37,0x40,0x43,0x43,0x43,0x43,0x42,0x3c,0x36,0x30 + ,0x26,0x1b,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x2b,0x34,0x3c,0x42,0x43,0x43,0x43,0x42,0x3c,0x34,0x2b,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0b,0x16,0x21,0x2b,0x34,0x38,0x40,0x43,0x43 + ,0x43,0x43,0x42,0x3c,0x34,0x2b,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x26,0x30,0x37,0x40,0x43,0x43,0x43,0x43,0x40,0x37,0x30,0x26,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10 + ,0x1b,0x26,0x30,0x37,0x40,0x43,0x43,0x43,0x43,0x42,0x3c,0x34,0x2b,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x36,0x40,0x43,0x43,0x43,0x43,0x42,0x3c,0x2f,0x1e,0x12,0x12,0x12,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00 + ,0x00,0x0a,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x38,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x57,0x49,0x51,0x5a,0x5b,0x5b,0x57,0x49,0x36,0x21 + ,0x0a,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x31,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x31,0x40,0x51,0x5a,0x5b,0x5b + ,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21 + ,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x40 + ,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x2b,0x15,0x02,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x2b,0x15,0x02,0x00,0x00,0x00,0x00,0x05,0x16,0x25 + ,0x30,0x36,0x38,0x40,0x46,0x51,0x5a,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x1e,0x2b,0x36,0x41,0x4b,0x4e,0x46,0x38,0x25,0x10,0x00,0x00,0x00,0x06,0x1b,0x2f + ,0x40,0x4b,0x4f,0x4b,0x40,0x31,0x25,0x17,0x0b,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2f,0x40,0x51,0x5a,0x5b,0x5b,0x5a,0x51,0x46,0x38,0x27,0x16,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x25,0x31,0x3c,0x46 + ,0x4e,0x57,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x4e,0x46,0x3c,0x31,0x25,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x27,0x36,0x41,0x4b,0x51,0x5a,0x5b,0x5b,0x5b,0x5a,0x51,0x4b,0x41,0x36,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05 + ,0x14,0x21,0x2b,0x36,0x41,0x4b,0x4f,0x57,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x4b,0x41,0x36,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2f,0x3c,0x46,0x4e,0x57,0x5b,0x5b,0x5b,0x5b,0x57,0x4e,0x46,0x3c,0x2f,0x1e,0x0d,0x01,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x25,0x31,0x3c,0x46,0x4e,0x57,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x4b,0x41,0x36,0x27,0x16,0x05,0x00,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x2f,0x2a,0x2a,0x2a,0x2d,0x40,0x51,0x5a + ,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x73,0x73,0x73,0x6a,0x5a,0x46,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73 + ,0x6a,0x57,0x61,0x71,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x73,0x73,0x71,0x61,0x4b,0x3a,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x73 + ,0x73,0x71,0x61,0x4b,0x3a,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x05,0x1c,0x34,0x4b + ,0x61,0x71,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x04,0x17,0x2b,0x40,0x51,0x62,0x71,0x73,0x73,0x73,0x73,0x73,0x71,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x71,0x61,0x4b + ,0x34,0x1c,0x05,0x00,0x00,0x00,0x02,0x14,0x27,0x38,0x46,0x4e,0x4f,0x57,0x5c,0x66,0x71,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0a,0x17,0x25,0x31,0x40,0x4c,0x57,0x61,0x65 + ,0x5a,0x46,0x30,0x19,0x04,0x00,0x00,0x0e,0x25,0x3c,0x51,0x61,0x67,0x61,0x52,0x46,0x38,0x2b,0x21,0x14,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x40,0x51,0x62,0x71,0x73,0x73,0x71,0x66,0x5a,0x49,0x38,0x25,0x10,0x00,0x00 + ,0x00,0x00,0x00,0x02,0x14,0x27,0x38,0x46,0x51,0x5c,0x65,0x6b,0x73,0x73,0x73,0x73,0x71,0x67,0x65,0x5c,0x51,0x46,0x38,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x27,0x38,0x49,0x57,0x61,0x67,0x71,0x73,0x73,0x73,0x71,0x67,0x61,0x57,0x49,0x38 + ,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x36,0x41,0x4c,0x57,0x61,0x67,0x6b,0x73,0x73,0x73,0x73,0x71,0x67,0x61,0x57,0x49,0x38,0x27,0x16,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2f,0x40,0x51,0x5c,0x65,0x6b,0x73,0x73,0x73,0x73 + ,0x6b,0x65,0x5c,0x51,0x40,0x2f,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x27,0x38,0x46,0x51,0x5c,0x65,0x6b,0x73,0x73,0x73,0x73,0x71,0x67,0x61,0x57,0x49,0x38,0x27,0x14,0x02,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x73,0x73,0x71 + ,0x62,0x51,0x41,0x43,0x43,0x43,0x42,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x89,0x8c,0x8c,0x8c,0x8a,0x7b,0x65,0x4e,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x0a,0x21,0x38,0x4f,0x67,0x7f,0x8c,0x89,0x73,0x5b,0x67,0x7f,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x89,0x8c,0x8c,0x8c,0x7f,0x67,0x4f,0x3d,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12 + ,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x89,0x8c,0x8c,0x8c,0x7f,0x67,0x4f,0x3d,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x89,0x73 + ,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c + ,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0x25,0x38,0x4c,0x61,0x72,0x84,0x8c,0x8c,0x8c,0x8c,0x8c,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c + ,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x0a,0x21,0x36,0x49,0x5a,0x65,0x67,0x6b,0x73,0x7b,0x84,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04 + ,0x10,0x1e,0x2b,0x38,0x46,0x52,0x61,0x6b,0x74,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x7f,0x72,0x66,0x5a,0x4c,0x41,0x36,0x27,0x1b,0x0d,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x62,0x72,0x84,0x8c + ,0x8c,0x84,0x7b,0x6a,0x5a,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x0b,0x21,0x36,0x49,0x5a,0x66,0x71,0x7b,0x7f,0x8a,0x8c,0x8c,0x8c,0x84,0x7f,0x7b,0x71,0x66,0x5a,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x04,0x16,0x27,0x38,0x49,0x5a,0x6a,0x74,0x7f + ,0x84,0x8c,0x8c,0x8c,0x84,0x7f,0x74,0x6a,0x5a,0x49,0x38,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x61,0x6b,0x74,0x7f,0x7f,0x8a,0x8c,0x8c,0x8c,0x84,0x7f,0x74,0x6a,0x5a,0x49,0x38,0x25,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f + ,0x40,0x51,0x62,0x71,0x7b,0x7f,0x8a,0x8c,0x8c,0x8a,0x7f,0x7b,0x71,0x62,0x51,0x40,0x2f,0x1e,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x16,0x27,0x38,0x49,0x5a,0x66,0x71,0x7b,0x7f,0x8a,0x8c,0x8c,0x8c,0x84,0x7f,0x74,0x6a,0x5a,0x49,0x36,0x21,0x0a,0x00,0x00 + ,0x12,0x2a,0x43,0x5b,0x73,0x87,0x8c,0x8c,0x8c,0x84,0x71,0x5a,0x57,0x5b,0x5b,0x5b,0x5a,0x54,0x67,0x7f,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa1,0xa4,0xa4,0x97,0x7f,0x6b,0x57,0x4f,0x67,0x7f,0x98,0xa4,0xa1 + ,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x01,0x0a,0x16,0x28,0x40,0x57,0x6b,0x7f,0x98,0x8c,0x73,0x5c,0x67,0x7f,0x98,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x01,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa1,0xa4,0x98,0x7f,0x67,0x4f,0x3d,0x4f,0x67 + ,0x7f,0x98,0xa4,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa1,0xa4,0x98,0x7f,0x67,0x4f,0x3d,0x4f,0x67,0x7f,0x98,0xa4,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0xa4,0xa4,0xa4 + ,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4 + ,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x31,0x46,0x5a,0x6b,0x7f,0x93,0xa2,0xa4,0xa4,0xa4,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x06,0x1e,0x37 + ,0x4f,0x67,0x7f,0x98,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x7b,0x7f,0x7f,0x8a,0x8e,0x98,0xa2,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0a,0x17,0x25,0x31,0x40,0x4c,0x5a,0x66,0x72,0x7f,0x8a,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8a,0x84,0x7b,0x6b,0x61,0x57,0x49,0x3c,0x2f,0x21,0x14,0x06,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x05,0x1c,0x34,0x4b,0x61,0x72,0x84,0x94,0xa2,0xa2,0x98,0x8c,0x7b,0x65,0x4e,0x37,0x21,0x0a,0x00,0x00,0x00,0x02,0x15,0x2b,0x41,0x57,0x6a,0x7b,0x84,0x8e,0x97,0x9d,0xa4,0xa4,0xa2,0x99,0x97,0x8e,0x84,0x7b,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00 + ,0x00,0x10,0x25,0x38,0x49,0x5a,0x6a,0x7b,0x8a,0x93,0x99,0xa2,0xa4,0xa2,0x99,0x93,0x8a,0x7b,0x6a,0x5a,0x49,0x36,0x21,0x0b,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x74,0x7f,0x8a,0x93,0x98,0x9d,0xa4,0xa4,0xa2,0x99,0x93,0x8a,0x7b,0x6a,0x5a,0x46,0x31 + ,0x1b,0x06,0x00,0x00,0x00,0x00,0x04,0x17,0x2b,0x40,0x51,0x62,0x72,0x84,0x8e,0x97,0x9d,0xa4,0xa4,0x9d,0x97,0x8e,0x84,0x72,0x62,0x51,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x10,0x25,0x38,0x49,0x5a,0x6a,0x7b,0x84,0x8e,0x97,0x9d,0xa4,0xa4,0xa2,0x99 + ,0x93,0x8a,0x7b,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x98,0xa4,0xa0,0x8c,0x73,0x5e,0x6a,0x73,0x73,0x73,0x71,0x61,0x67,0x7f,0x98,0xa4,0x9b,0x8a,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb9,0xb3 + ,0x9d,0x8a,0x74,0x61,0x53,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2b,0x34,0x43,0x5b,0x73,0x8a,0x9a,0x8c,0x73,0x60,0x71,0x84,0x98,0x8c,0x73,0x5b,0x43,0x2d,0x1e,0x0c,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73 + ,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x3d,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x3d,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06 + ,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0xa4,0xa4,0xa8,0xb3,0xbb,0xb3,0xa8,0xa4,0xa4,0xa4,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb3,0xa8,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x17,0x2b,0x40,0x52,0x66,0x7b,0x8c,0x9d,0xae,0xb1,0xb8,0xb0,0x98,0x7f,0x67,0x4f + ,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xae,0xb6,0xac,0x97,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8a,0x97,0x98,0x9d,0xa4,0xad,0xb5,0xa4,0x8c + ,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x10,0x1e,0x2b,0x38,0x46,0x52,0x61,0x6b,0x7b,0x84,0x93,0x95,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0x98,0x8c,0x7f,0x74,0x6a,0x5c,0x51 + ,0x41,0x36,0x27,0x1b,0x0d,0x02,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x93,0xa4,0xb5,0xb8,0xac,0x97,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x06,0x1d,0x34,0x4b,0x61,0x74,0x8a,0x98,0xa3,0xa2,0x99,0x98,0x98,0x98,0x9d,0xa3,0xa1,0x96 + ,0x88,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x06,0x1b,0x31,0x46,0x5a,0x6a,0x7b,0x8c,0x9c,0xa5,0xa2,0x99,0x98,0x99,0xa2,0xa5,0x9c,0x8c,0x7b,0x6a,0x57,0x41,0x2b,0x15,0x02,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x82,0x92,0x9d,0xa2,0xa4,0xa4,0xa4 + ,0xa4,0xa4,0xa9,0xa8,0x9c,0x8c,0x7b,0x66,0x51,0x3c,0x26,0x10,0x00,0x00,0x00,0x00,0x10,0x25,0x38,0x4c,0x61,0x72,0x84,0x94,0xa3,0xa8,0xa4,0xa4,0xa4,0xa4,0xa7,0xa3,0x94,0x84,0x72,0x62,0x51,0x3c,0x26,0x10,0x00,0x00,0x00,0x00,0x06,0x1b,0x31,0x46,0x5a,0x6a + ,0x7b,0x8c,0x98,0xa3,0xa7,0xa4,0xa4,0xa4,0xa4,0xa4,0xa3,0x98,0x88,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x0a,0x21,0x38,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x61,0x73,0x89,0x8c,0x8c,0x7f,0x67,0x67,0x7f,0x98,0xaa,0x98,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00 + ,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xbc,0xbd,0xa8,0x93,0x7f,0x67,0x56,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x4b,0x4f,0x5b,0x73,0x8c,0x98,0x84,0x71,0x60,0x73,0x8c,0x9a,0x8a,0x73,0x5b,0x4c,0x40 + ,0x2f,0x1b,0x06,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x3d,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x3d,0x4f,0x67,0x7f,0x98,0xb0 + ,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x8c,0x94,0xa8,0xb9,0xa8,0x94,0x8c,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a + ,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa8,0x94,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0x25,0x38,0x4c,0x61,0x72,0x84 + ,0x98,0xa2,0x99,0x9d,0xae,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8e,0x9d,0xab,0x9c,0x8c,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b + ,0x73,0x8c,0xa1,0xa4,0xa4,0xa4,0xae,0xb8,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x26,0x31,0x40,0x4c,0x5a,0x66,0x72,0x7f,0x8c,0x98,0xa2,0x97,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x12,0x2a,0x43 + ,0x5b,0x73,0x8c,0x9f,0x9d,0x93,0x8a,0x7b,0x71,0x62,0x57,0x49,0x3c,0x2f,0x21,0x14,0x06,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xc5,0xc9,0xb3,0x9d,0x8a,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x67,0x7f,0x93,0xa8 + ,0xa8,0x94,0x84,0x7f,0x7f,0x7f,0x8a,0x8e,0x98,0x8e,0x7b,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x10,0x26,0x3c,0x51,0x66,0x7b,0x8c,0x9c,0xa9,0x9c,0x8e,0x84,0x7f,0x84,0x8e,0x9c,0xa9,0x9c,0x8a,0x74,0x61,0x4b,0x34,0x1d,0x06,0x00,0x00,0x00,0x0e,0x25 + ,0x3c,0x51,0x66,0x7b,0x8e,0x9c,0x93,0x8c,0x8c,0x8c,0x8c,0x8e,0x98,0xa4,0xab,0x98,0x84,0x71,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x04,0x19,0x30,0x46,0x5a,0x6b,0x7f,0x93,0xa4,0xab,0x9c,0x8e,0x8c,0x8c,0x8e,0x98,0xa4,0xa4,0x94,0x84,0x71,0x5c,0x46,0x31,0x1b + ,0x06,0x00,0x00,0x00,0x10,0x26,0x3c,0x51,0x66,0x7b,0x8c,0x9c,0xaa,0xa4,0x98,0x8e,0x8c,0x8c,0x8c,0x8e,0x97,0x8c,0x7b,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x93,0xa8,0xa4,0x8c,0x73,0x66,0x7b,0x8e,0xa1,0x98,0x7f,0x6b,0x6b,0x7f + ,0x98,0xaa,0x98,0x7f,0x67,0x4f,0x38,0x21,0x0a,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb8,0xb3,0xad,0x99,0x84,0x71,0x5c,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x61,0x67,0x67,0x73,0x8c,0x98,0x7f + ,0x6a,0x67,0x73,0x8c,0x98,0x7f,0x6e,0x67,0x61,0x51,0x3c,0x25,0x0e,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x3d,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0 + ,0x98,0x7f,0x67,0x4f,0x3d,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x76,0x8c,0xa4,0xb6,0xa4,0x8c,0x76,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x06,0x1e,0x37,0x4f + ,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x76,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x0a,0x1e,0x31,0x46,0x5a,0x6b,0x7f,0x93,0xa1,0x94,0x84,0x8e,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x77,0x84,0x99,0xa2,0x8e,0x7b,0x6a,0x5a,0x46 + ,0x30,0x19,0x04,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x89,0x8c,0x8c,0x8c,0x8e,0x9d,0xb1,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2f,0x3c,0x46,0x52,0x61,0x6b,0x7b,0x84,0x93,0x9d,0xa2,0x98,0x8c,0x7b + ,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x8e,0x9c,0xa2,0x9c,0x8e,0x84,0x74,0x6a,0x5c,0x51,0x41,0x36,0x27,0x1b,0x0c,0x01,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x97,0xac,0xbe,0xc5,0xb0,0x99,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00 + ,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x99,0xb0,0xa4,0x8c,0x74,0x67,0x67,0x6b,0x73,0x7b,0x84,0x84,0x71,0x5c,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x71,0x84,0x98,0xaa,0x9d,0x8c,0x7b,0x71,0x68,0x71,0x7b,0x8c,0x9d,0xa6,0x93,0x7f + ,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x06,0x1b,0x31,0x46,0x5c,0x71,0x84,0x8a,0x7f,0x74,0x73,0x73,0x73,0x7b,0x84,0x98,0xac,0xa3,0x8e,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x07,0x1e,0x36,0x4e,0x65,0x7b,0x8c,0x9d,0xad,0x9d,0x8c,0x7b,0x73,0x73,0x7b + ,0x84,0x98,0xab,0xa3,0x8e,0x7b,0x66,0x51,0x3c,0x25,0x0e,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x71,0x84,0x98,0xab,0xa4,0x94,0x84,0x7b,0x73,0x73,0x73,0x7b,0x84,0x7f,0x6b,0x5a,0x49,0x36,0x21,0x0a,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x74,0x8c,0xa4,0xa4,0x8e + ,0x7b,0x6c,0x7f,0x97,0xae,0x9d,0x8a,0x73,0x73,0x8a,0x9d,0xaa,0x97,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xae,0x9d,0x99,0x9f,0x8e,0x7b,0x66,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x12 + ,0x2a,0x42,0x5a,0x71,0x7f,0x7f,0x7f,0x8e,0x99,0x84,0x7f,0x7f,0x7f,0x8e,0x99,0x84,0x7f,0x7f,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x43,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12 + ,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x3d,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5e,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5e,0x5b,0x5b,0x5b,0x57 + ,0x49,0x36,0x21,0x0a,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5e,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b + ,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x05,0x17,0x2b,0x40,0x52,0x66,0x7b,0x8c,0x9d,0x9c,0x8a,0x79,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5f + ,0x6b,0x7f,0x93,0xa1,0x94,0x84,0x71,0x5c,0x49,0x38,0x25,0x10,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x73,0x73,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2f,0x40,0x51,0x5c,0x66 + ,0x72,0x7f,0x8c,0x98,0xa1,0x9d,0x93,0x84,0x7b,0x6a,0x5a,0x46,0x30,0x19,0x04,0x00,0x00,0x0e,0x25,0x3c,0x51,0x62,0x71,0x7b,0x8a,0x94,0xa1,0xa1,0x94,0x8a,0x7b,0x71,0x62,0x57,0x49,0x3c,0x2f,0x1e,0x0a,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8c,0x9c,0xac + ,0xae,0xa3,0x93,0x7f,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x99,0xb0,0xa4,0x8e,0x7b,0x73,0x71,0x67,0x64,0x66,0x71,0x71,0x62,0x51,0x3c,0x27,0x14,0x02,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8e,0xa3,0xa8,0x93,0x7f + ,0x6b,0x61,0x5d,0x61,0x6b,0x7f,0x98,0xaa,0x99,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x00,0x10,0x26,0x3c,0x51,0x62,0x71,0x73,0x6b,0x64,0x66,0x67,0x67,0x6e,0x7c,0x8e,0xa4,0xad,0x97,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x0e,0x25,0x3c,0x51,0x67 + ,0x7f,0x97,0xac,0xa8,0x93,0x7f,0x6b,0x5c,0x5c,0x68,0x7b,0x8e,0xa4,0xad,0x98,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x07,0x1e,0x36,0x4e,0x65,0x7b,0x8e,0xa3,0xae,0x99,0x84,0x72,0x66,0x5c,0x5b,0x5c,0x66,0x71,0x71,0x61,0x4c,0x38,0x27,0x14,0x02,0x00,0x00 + ,0x02,0x15,0x2c,0x43,0x5b,0x73,0x8c,0xa4,0xad,0x97,0x7f,0x6e,0x7f,0x98,0xa4,0xa1,0x8c,0x73,0x73,0x8c,0xa4,0xa4,0x8e,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8e,0x84,0x98,0x98,0x84,0x71,0x67,0x7f,0x98,0xb0,0xa4 + ,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0x98,0x98,0x9d,0xa4,0x99,0x98,0x98,0x98,0x9d,0xa4,0x99,0x98,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x5b,0x5b,0x5b,0x67 + ,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x3d,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x46,0x5b,0x73,0x8c + ,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x46,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0 + ,0xa4,0x8c,0x73,0x5b,0x49,0x49,0x49,0x49,0x49,0x49,0x47,0x41,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x38,0x4c,0x61,0x72,0x84,0x98,0xa1,0x8e,0x7b,0x74,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e + ,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x44,0x51,0x66,0x7b,0x8c,0x9d,0x9c,0x8a,0x74,0x62,0x51,0x3c,0x27,0x16,0x04,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x06,0x1b,0x2f,0x40,0x51,0x62,0x71,0x7b,0x84,0x93,0x9d,0xa1,0x94,0x8a,0x7f,0x72,0x66,0x5a,0x49,0x38,0x25,0x10,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x51,0x5c,0x6a,0x74,0x84,0x8e,0x98,0xa1,0x9c,0x8e,0x84,0x74,0x6a,0x5c,0x51,0x40,0x2b,0x15,0x00 + ,0x00,0x04,0x19,0x30,0x46,0x5a,0x6a,0x7b,0x8c,0x97,0x97,0x8e,0x84,0x72,0x61,0x4b,0x34,0x1d,0x06,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x67,0x7f,0x93,0xa8,0xae,0x9c,0x8e,0x8c,0x84,0x7f,0x74,0x73,0x6b,0x63,0x59,0x49,0x38,0x27,0x16,0x04,0x00,0x00,0x00,0x06 + ,0x1e,0x37,0x4f,0x67,0x7f,0x97,0xad,0xa4,0x8c,0x77,0x73,0x73,0x73,0x73,0x73,0x7f,0x98,0xae,0xa2,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x0d,0x20,0x33,0x45,0x56,0x60,0x66,0x71,0x73,0x7b,0x7f,0x7f,0x7f,0x8a,0x94,0xa8,0xb0,0x98,0x7f,0x67,0x4f + ,0x37,0x1e,0x06,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x99,0xb0,0xa4,0x8c,0x74,0x61,0x4c,0x48,0x5c,0x73,0x8c,0xa2,0xb3,0xa2,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x0e,0x25,0x3c,0x51,0x67,0x7f,0x97,0xad,0xa8,0x93,0x7f,0x67,0x53,0x46,0x43,0x46,0x51 + ,0x5a,0x5a,0x51,0x40,0x2b,0x17,0x05,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8a,0x9d,0xab,0x98,0x7f,0x73,0x8a,0x98,0x8e,0x94,0x8e,0x7b,0x73,0x8c,0xa4,0xa4,0x8c,0x73,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8c + ,0x7c,0x8e,0x9e,0x8c,0x74,0x69,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0x98,0x99,0xa4,0x9d,0x98,0x98,0x98,0x99,0xa4,0x9d,0x98,0x98,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73 + ,0x8c,0xa4,0xb0,0x98,0x7f,0x73,0x73,0x73,0x73,0x73,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x3d,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00 + ,0x01,0x0c,0x1b,0x25,0x2a,0x2d,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2d,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5e,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x0d,0x21,0x36,0x49,0x5a,0x6b,0x7f,0x93,0xa1,0x94,0x84,0x71,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f + ,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x33,0x46,0x5c,0x71,0x84,0x98,0xa1,0x8e,0x7b,0x6a,0x57,0x41,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x36,0x40,0x43,0x43,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c + ,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x62,0x72,0x84,0x8e,0x98,0xa1,0x9c,0x8e,0x84,0x74,0x6b,0x61,0x52,0x46,0x38,0x27,0x16,0x04,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2f,0x3c,0x49,0x57,0x62,0x71,0x7b,0x84,0x93,0x9d + ,0xa1,0x94,0x8a,0x7b,0x71,0x61,0x4b,0x34,0x1c,0x00,0x00,0x00,0x10,0x25,0x38,0x49,0x5a,0x6a,0x7b,0x7f,0x7f,0x7b,0x71,0x62,0x51,0x40,0x2b,0x15,0x02,0x00,0x00,0x00,0x06,0x1d,0x34,0x4b,0x61,0x74,0x8a,0x98,0xa3,0xa8,0xa4,0xa2,0x99,0x93,0x8c,0x8a,0x7f,0x74 + ,0x6a,0x5a,0x49,0x38,0x25,0x10,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa8,0x94,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8e,0x9d,0xb1,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x51,0x62,0x71,0x7b,0x84,0x8c,0x8e,0x97 + ,0x98,0x98,0x9b,0xa2,0xb1,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa2,0xb4,0xa4,0x8c,0x73,0x5b,0x43,0x42,0x5a,0x71,0x84,0x99,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x99 + ,0xb0,0xa4,0x8c,0x74,0x61,0x4b,0x35,0x2a,0x31,0x3c,0x42,0x42,0x3c,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x98,0xaa,0x98,0x7f,0x73,0x8c,0x97,0x7f,0x8c,0x97,0x7f,0x74,0x8c,0xa4,0xa2,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00 + ,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8e,0x7c,0x8a,0x9c,0x93,0x7f,0x6e,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x7f,0x7f,0x84,0x99,0x8e,0x7f,0x7f,0x7f,0x84,0x99,0x8e,0x7f,0x7f,0x7f,0x71,0x5a + ,0x42,0x2a,0x12,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb1,0x9d,0x8e,0x8c,0x8c,0x8c,0x8c,0x8c,0x8e,0x9d,0xb1,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x3d,0x4f,0x67,0x7f,0x98,0xb0 + ,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x15,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x15,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a + ,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x76,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x06,0x1b,0x2f,0x41,0x57,0x6a,0x7b,0x8c,0x9d,0x9c,0x8a + ,0x74,0x64,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x22,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x15,0x26,0x3c,0x51,0x66,0x7b,0x8e,0xa1,0x98,0x84,0x71,0x5c,0x49,0x36,0x21,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21 + ,0x28,0x2a,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x94,0xa1,0x9d,0x93,0x8a,0x7b,0x71,0x62,0x57,0x4c,0x40,0x31,0x25,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x01,0x0c + ,0x1b,0x27,0x36,0x41,0x51,0x5c,0x66,0x72,0x7f,0x8c,0x98,0xa1,0x9c,0x8e,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x04,0x16,0x27,0x38,0x49,0x5a,0x65,0x67,0x67,0x65,0x5c,0x51,0x40,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x41,0x57,0x6a,0x7b,0x84 + ,0x8e,0x98,0xa2,0xa4,0xa9,0xa6,0xa4,0x9d,0x93,0x8a,0x7b,0x6a,0x5a,0x46,0x30,0x19,0x04,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb1,0xa2,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0xa2,0xa4,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x10,0x26 + ,0x3c,0x51,0x62,0x72,0x84,0x8e,0x98,0x9d,0x98,0x98,0x93,0x8c,0x8c,0x94,0xa8,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x3e,0x54,0x68,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a + ,0x12,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa0,0xb3,0xa4,0x8c,0x73,0x5b,0x43,0x2c,0x19,0x21,0x2b,0x30,0x30,0x2c,0x23,0x15,0x05,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x38,0x4f,0x67,0x7f,0x98,0xaa,0x99,0x84,0x77,0x8c,0x8e,0x7c,0x8c,0x98,0x7f,0x7f,0x93 + ,0xa6,0x99,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xad,0x97,0x7f,0x7f,0x93,0x9c,0x8a,0x73,0x7f,0x97,0xad,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x02,0x14,0x29,0x3d,0x51,0x61,0x67,0x6e,0x7f,0x98,0x8c,0x73 + ,0x67,0x6a,0x7f,0x98,0x8c,0x73,0x67,0x67,0x61,0x51,0x3c,0x25,0x0e,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb8,0xae,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xae,0xb8,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0 + ,0x98,0x7f,0x67,0x4f,0x3d,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f + ,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa8,0x94,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x02,0x14 + ,0x27,0x3c,0x51,0x62,0x74,0x8a,0x9c,0xa1,0x8e,0x7b,0x6a,0x5e,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x31,0x46,0x5c,0x71,0x84,0x98,0xa3,0x8e,0x7b,0x66,0x51,0x3c,0x27,0x14,0x02 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa2,0xa4,0x8e,0x7f,0x74,0x6a,0x5c,0x51,0x41,0x36,0x2b,0x1e + ,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x14,0x21,0x2f,0x3c,0x46,0x52,0x61,0x6b,0x7b,0x84,0x99,0xa9,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x04,0x16,0x27,0x38,0x49,0x5a,0x65,0x67,0x67,0x65,0x5c,0x51,0x40,0x2f,0x1e,0x0a,0x00,0x00 + ,0x00,0x00,0x00,0x0e,0x22,0x36,0x49,0x5a,0x66,0x71,0x7b,0x84,0x8c,0x8e,0x97,0x99,0xa3,0xab,0xa8,0x9c,0x8c,0x7b,0x65,0x4e,0x36,0x1e,0x07,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa8,0x94,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x89 + ,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x71,0x84,0x94,0xa3,0x9d,0x8e,0x84,0x7f,0x7f,0x74,0x76,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa2,0xb4,0xa4,0x8c,0x73,0x5b,0x43,0x42,0x5a + ,0x71,0x84,0x99,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x99,0xb0,0xa4,0x8c,0x73,0x5c,0x44,0x31,0x2a,0x31,0x3c,0x42,0x43,0x40,0x36,0x27,0x16,0x04,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x93,0xa8,0xa2 + ,0x8c,0x7f,0x93,0x8c,0x79,0x8c,0x9b,0x8a,0x7f,0x98,0xaa,0x98,0x7f,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x74,0x8c,0x9e,0x8e,0x7b,0x7b,0x8e,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x0a,0x21 + ,0x36,0x49,0x57,0x5b,0x5e,0x73,0x8a,0x9a,0x8c,0x73,0x60,0x71,0x84,0x98,0x8c,0x73,0x5e,0x5a,0x53,0x44,0x30,0x1b,0x06,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xbb,0xb5,0xa8,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xae,0xb8,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12 + ,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x3d,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb5,0xa8,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa1,0x8c + ,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x0a,0x21,0x36,0x49,0x5c,0x71,0x84,0x94,0xa2,0x94,0x84,0x71,0x5f,0x5e,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x66,0x7b,0x8e + ,0xa3,0x9d,0x8a,0x73,0x5c,0x46,0x31,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa1,0xa5 + ,0x94,0x84,0x7b,0x6b,0x61,0x57,0x49,0x3c,0x2f,0x21,0x16,0x0a,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0d,0x1b,0x26,0x31,0x40,0x4c,0x5a,0x66,0x71,0x7b,0x8c,0x9d,0xa9,0x97,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x10,0x25,0x38,0x49,0x5a,0x6a,0x7b,0x7f + ,0x7f,0x7b,0x71,0x62,0x51,0x40,0x2b,0x15,0x02,0x00,0x00,0x00,0x04,0x17,0x2b,0x40,0x51,0x61,0x65,0x61,0x66,0x71,0x73,0x7b,0x7f,0x84,0x8e,0x9c,0xae,0xac,0x97,0x7f,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x97,0xad,0xa4,0x8c,0x77 + ,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8e,0xa3,0xa7,0x93,0x7f,0x71,0x67,0x67,0x63,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71 + ,0x84,0x99,0xb0,0xa4,0x8c,0x74,0x61,0x4c,0x48,0x5c,0x73,0x8c,0xa2,0xb3,0xa2,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x0e,0x25,0x3c,0x51,0x67,0x7f,0x98,0xb0,0xa4,0x8e,0x7b,0x66,0x52,0x46,0x43,0x46,0x51,0x5a,0x5b,0x57,0x49,0x38,0x25,0x10,0x00,0x00,0x00 + ,0x00,0x05,0x1c,0x34,0x4b,0x61,0x74,0x8c,0xa4,0xa4,0x8c,0x7f,0x98,0x8c,0x79,0x8a,0x9b,0x8c,0x7f,0x98,0xaa,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x07,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x71,0x84,0x98,0x98,0x84,0x77,0x8c,0xa4,0xa4 + ,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x76,0x8c,0x98,0x84,0x76,0x73,0x76,0x8c,0x9d,0x8c,0x76,0x73,0x71,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb4,0xa4,0x94,0x8c,0x8c,0x8c,0x8c,0x8c + ,0x8e,0x9d,0xb1,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x3d,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c + ,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0 + ,0xb5,0xa8,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x7b,0x8e,0xa3,0xa4,0x8c,0x77,0x73,0x73,0x73,0x76,0x8c,0xa4,0xb0,0x98,0x7f,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x02,0x15,0x2c,0x43,0x5a,0x71,0x84,0x98,0xa9,0x98,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x05,0x09,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x04,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x8e,0x9c,0xa1,0x98,0x8c,0x7f,0x74,0x6a,0x5c,0x51,0x41,0x36,0x2b,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x2f,0x3c,0x46,0x52,0x61,0x6b,0x7b,0x84,0x8e,0x9c,0xa2,0x98,0x8c,0x7b,0x65,0x4e,0x36,0x1e,0x00 + ,0x00,0x04,0x19,0x30,0x46,0x5a,0x6a,0x7b,0x8c,0x97,0x97,0x8e,0x84,0x72,0x61,0x4b,0x34,0x1d,0x06,0x00,0x00,0x00,0x10,0x25,0x38,0x4c,0x61,0x72,0x7b,0x71,0x66,0x61,0x61,0x65,0x67,0x71,0x7b,0x8e,0xa4,0xb0,0x99,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x06 + ,0x1e,0x36,0x4e,0x65,0x7b,0x8e,0xa3,0xa8,0x93,0x7f,0x6c,0x63,0x5e,0x5b,0x5e,0x61,0x66,0x67,0x63,0x5c,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x97,0xad,0xa4,0x8c,0x74,0x62,0x5a,0x5c,0x66,0x74,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f + ,0x37,0x1e,0x06,0x00,0x00,0x0e,0x25,0x3c,0x51,0x67,0x7f,0x97,0xac,0xa8,0x93,0x7f,0x6b,0x5c,0x5c,0x68,0x7b,0x8e,0xa4,0xad,0x98,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x07,0x1e,0x37,0x4f,0x67,0x7f,0x93,0xa8,0xad,0x98,0x84,0x72,0x66,0x5c,0x5b,0x5c,0x66 + ,0x71,0x73,0x6a,0x5a,0x46,0x31,0x1b,0x06,0x00,0x00,0x00,0x02,0x15,0x2c,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8e,0x84,0x98,0x8c,0x74,0x7f,0x98,0x8e,0x84,0x99,0xa6,0x93,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98 + ,0x7f,0x6c,0x7b,0x8e,0x9e,0x8c,0x79,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x89,0x8c,0x8c,0x94,0x9d,0x8e,0x8c,0x8c,0x8c,0x94,0xa2,0x94,0x8c,0x8c,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73 + ,0x8c,0xa4,0xb0,0x99,0x84,0x74,0x73,0x73,0x73,0x73,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x51,0x3f,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00 + ,0x00,0x00,0x06,0x0e,0x15,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x15,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x15,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x00,0x00 + ,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa8,0x94,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8a,0x9c,0xae,0xa8,0x94,0x8c,0x8c,0x8c,0x8c,0x8c,0x94,0xa8,0xb3,0x9d,0x8e,0x8c,0x89 + ,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x74,0x8c,0xa2,0xa8,0x93,0x7f,0x67,0x4f,0x38,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0a,0x15,0x1c,0x1e,0x21,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c + ,0x73,0x5b,0x43,0x2a,0x1e,0x19,0x10,0x04,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x62,0x71,0x7b,0x8a,0x94,0xa1,0x9d,0x93,0x8a,0x7b,0x71,0x62,0x57,0x4c,0x40,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x02,0x14,0x27,0x36,0x41,0x51,0x5c,0x66,0x72,0x7f,0x8c,0x98,0xa0 + ,0x9d,0x93,0x84,0x7b,0x6a,0x5a,0x46,0x30,0x19,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8c,0x9c,0xac,0xad,0xa3,0x93,0x7f,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00,0x04,0x19,0x30,0x46,0x5a,0x6b,0x7f,0x8d,0x84,0x7b,0x73,0x71,0x67,0x67,0x6b,0x76,0x8c,0xa4,0xb0 + ,0x98,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x71,0x84,0x98,0xaa,0x9d,0x8c,0x7f,0x74,0x6b,0x67,0x6b,0x73,0x7b,0x7f,0x72,0x61,0x4c,0x3a,0x27,0x14,0x02,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8e,0x7b,0x71,0x6b + ,0x73,0x7b,0x84,0x94,0xa8,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x07,0x1e,0x36,0x4e,0x65,0x7b,0x8c,0x9d,0xad,0x9d,0x8c,0x7b,0x73,0x73,0x7b,0x84,0x98,0xab,0xa3,0x8e,0x7b,0x66,0x51,0x3c,0x25,0x0e,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x74,0x8a + ,0x9c,0xac,0xa4,0x94,0x84,0x7b,0x73,0x73,0x73,0x7b,0x84,0x8a,0x7b,0x66,0x51,0x3c,0x26,0x10,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8a,0x9d,0xab,0x9d,0x99,0x98,0x84,0x71,0x7f,0x98,0x9d,0x99,0xa4,0xa4,0x8c,0x74,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00 + ,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x73,0x8a,0x9c,0x93,0x7f,0x8c,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0x9e,0x9e,0xa5,0xa9,0x9f,0x9e,0x9e,0x9e,0xa5,0xab,0xa0,0x9e,0x98,0x7f,0x67,0x4f + ,0x37,0x1e,0x06,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x5b,0x5b,0x5b,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x99,0x84,0x71,0x5a,0x42,0x4f,0x67,0x7f,0x98,0xb0 + ,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2d,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2d,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2d + ,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x0c,0x01,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x76,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0xad,0xa6,0xa4,0xa4 + ,0xa4,0xa4,0xa4,0xa8,0xb5,0xbe,0xae,0xa4,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x1e,0x37,0x4f,0x67,0x7f,0x93,0xa8,0xa4,0x8c,0x74,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2b,0x34 + ,0x37,0x37,0x3a,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x37,0x36,0x30,0x25,0x16,0x05,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x51,0x5c,0x6a,0x74,0x84,0x8e,0x9c,0xa2,0x9c,0x8e,0x84,0x74,0x6b,0x61,0x51,0x40,0x2b,0x15,0x02,0x00,0x00,0x0a,0x21,0x36 + ,0x49,0x57,0x62,0x71,0x7b,0x84,0x93,0x9d,0xa1,0x94,0x8a,0x7f,0x72,0x66,0x5a,0x49,0x38,0x25,0x10,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x97,0xac,0xbe,0xc2,0xb0,0x99,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8c,0x9c,0x98 + ,0x8e,0x8c,0x84,0x7f,0x7f,0x7f,0x8a,0x94,0xa7,0xa4,0x93,0x7f,0x67,0x4f,0x38,0x21,0x0a,0x00,0x00,0x00,0x10,0x26,0x3c,0x51,0x66,0x7b,0x8c,0x9c,0xa9,0x9d,0x93,0x8a,0x7f,0x7f,0x7f,0x8a,0x8e,0x92,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x06,0x1e,0x37 + ,0x4f,0x67,0x7f,0x93,0xa8,0xae,0x9c,0x8e,0x84,0x7f,0x8a,0x8e,0x98,0x9f,0xad,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x04,0x19,0x30,0x46,0x5a,0x6b,0x7f,0x93,0xa4,0xab,0x9c,0x8e,0x8c,0x8c,0x8e,0x98,0xa4,0xa4,0x94,0x84,0x71,0x5c,0x46,0x31,0x1b + ,0x06,0x00,0x00,0x02,0x15,0x2b,0x41,0x57,0x6a,0x7b,0x8e,0xa1,0xad,0xa4,0x98,0x8e,0x8c,0x8c,0x8c,0x8e,0x98,0x98,0x84,0x71,0x5c,0x46,0x30,0x19,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x98,0xb0,0xb1,0xad,0x98,0x7f,0x6d,0x7f,0x93,0xa6,0xb0,0xb4 + ,0xa4,0x8c,0x73,0x5b,0x43,0x2c,0x15,0x02,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x6b,0x7f,0x93,0x9c,0x8e,0x94,0xa8,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x89,0x8c,0x8e,0x9d,0x9d,0x8e,0x8c + ,0x8c,0x8e,0x9d,0x9d,0x8e,0x8c,0x8c,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x43,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa2,0xb3 + ,0xa2,0x8c,0x73,0x5b,0x45,0x51,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x46,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x46,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x06,0x1e,0x37,0x4f + ,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x46,0x43,0x43,0x43,0x43,0x43,0x43,0x42,0x3c,0x2f,0x1e,0x0a,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5e,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x12,0x2a + ,0x43,0x5b,0x73,0x8c,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x9d,0xae,0xb8,0xa4,0x99,0x98,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2c,0x15,0x02,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x4b,0x4f,0x4f,0x4f,0x52,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x4f,0x4f,0x4e,0x46,0x38,0x27,0x14,0x02,0x00,0x00,0x00,0x0c,0x1e,0x2f,0x3c,0x49,0x57,0x62,0x71,0x7b,0x8a,0x93,0x9d,0xa1,0x94,0x8a,0x7f,0x72 + ,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x74,0x84,0x8e,0x98,0xa1,0x9c,0x8e,0x84,0x74,0x6b,0x61,0x52,0x46,0x38,0x27,0x16,0x04,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xc5,0xcb,0xb3,0x9d,0x8a,0x73,0x5b,0x43,0x2a,0x12,0x00 + ,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8e,0x98,0xa1,0xa3,0xa2,0x99,0x98,0x98,0x98,0x9d,0xa5,0xa3,0x94,0x84,0x72,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x00,0x06,0x1b,0x31,0x46,0x5a,0x6a,0x7b,0x8c,0x9c,0xa6,0xa6,0x9d,0x98,0x98,0x98,0x9d,0xa0,0x99,0x8a,0x73 + ,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x74,0x8a,0x9c,0xac,0xab,0xa3,0x99,0x98,0x9c,0x9a,0x8e,0x8e,0x9d,0xab,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x10,0x25,0x38,0x4c,0x61,0x72,0x84,0x94,0xa3,0xa8,0xa4,0xa4,0xa4,0xa4 + ,0xa7,0xa3,0x94,0x84,0x72,0x62,0x51,0x3c,0x26,0x10,0x00,0x00,0x00,0x00,0x0b,0x21,0x36,0x49,0x5c,0x71,0x84,0x8e,0x9c,0xa8,0xa9,0xa4,0xa4,0xa4,0xa4,0xa3,0xa3,0x9c,0x8a,0x7b,0x65,0x4e,0x36,0x1e,0x00,0x00,0x00,0x00,0x0a,0x21,0x38,0x4f,0x67,0x7f,0x98,0xa4 + ,0xa4,0xa4,0x97,0x7f,0x69,0x74,0x8c,0xa1,0xa4,0xa4,0x9d,0x8a,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x61,0x74,0x8a,0x9d,0xa4,0xa8,0xb3,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x11,0x28 + ,0x40,0x57,0x6a,0x73,0x73,0x7f,0x98,0x93,0x7f,0x73,0x73,0x7f,0x98,0x97,0x7f,0x73,0x73,0x71,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x3d,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12 + ,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x99,0xb0,0xa4,0x8c,0x74,0x62,0x55,0x5d,0x71,0x84,0x99,0xae,0xa2,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5e,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5e,0x5b,0x5b,0x5b,0x57 + ,0x49,0x36,0x21,0x0a,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5e,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x2b,0x15,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x46,0x43,0x43,0x43,0x43,0x43 + ,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x8e,0xa4,0xb0,0x99,0x84,0x7f,0x7f,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x99,0xac + ,0x9d,0x8a,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x61,0x67,0x67,0x67,0x67,0x6a,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x67,0x67,0x67,0x65,0x5a,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x01,0x0c,0x1b,0x27,0x36,0x41,0x51 + ,0x5c,0x6a,0x74,0x7f,0x8c,0x98,0xa1,0x9d,0x92,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x89,0x94,0xa1,0xa1,0x94,0x8a,0x7b,0x71,0x62,0x57,0x4c,0x40,0x31,0x25,0x16,0x05,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x93,0xa4,0xb5 + ,0xbb,0xac,0x97,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x7b,0x84,0x8e,0x97,0x99,0xa2,0xa4,0xa4,0xa2,0x99,0x97,0x8e,0x84,0x72,0x62,0x51,0x40,0x2b,0x15,0x02,0x00,0x00,0x00,0x00,0x10,0x25,0x38,0x49,0x5a,0x6a,0x7b,0x8a,0x93 + ,0x98,0x9d,0xa4,0xa4,0x9d,0x98,0x93,0x8a,0x7f,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x02,0x15,0x2b,0x41,0x57,0x6a,0x7b,0x8c,0x97,0x9d,0xa4,0xa2,0x99,0x93,0x8a,0x7b,0x7f,0x95,0x98,0x95,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x04,0x17,0x2b,0x40 + ,0x51,0x62,0x72,0x84,0x8e,0x97,0x9d,0xa4,0xa4,0x9d,0x97,0x8e,0x84,0x72,0x62,0x51,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x3c,0x51,0x62,0x71,0x7b,0x8a,0x93,0x99,0xa2,0xa4,0xa4,0x9d,0x97,0x8e,0x8a,0x7b,0x71,0x61,0x4b,0x34,0x1c,0x00,0x00 + ,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x8c,0x8a,0x7b,0x66,0x73,0x89,0x8c,0x8c,0x8c,0x8c,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x58,0x6b,0x7f,0x97,0xad,0xbc,0xbb,0xa4 + ,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x5b,0x67,0x7f,0x98,0x8c,0x74,0x62,0x67,0x7f,0x98,0x8e,0x7b,0x65,0x5b,0x5a,0x51,0x40,0x2b,0x15,0x02,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x3d,0x4f,0x67 + ,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x0e,0x25,0x3c,0x51,0x67,0x7f,0x93,0xa8,0xa8,0x94,0x84,0x72,0x68,0x71,0x7b,0x8e,0xa3,0xae,0x99,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x76,0x8c + ,0xa4,0xb6,0xa4,0x8c,0x76,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x76,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x71,0x61,0x4b,0x34,0x1c,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0 + ,0xa4,0x8c,0x73,0x5b,0x43,0x2d,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x61,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x6a,0x67,0x61,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa2,0xae,0x98,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x7f,0x7f,0x7f,0x7f,0x7f,0x84,0x99,0xb0,0xa4,0x8e,0x7f,0x7f,0x7f,0x7f,0x7b,0x6a,0x57,0x40,0x28,0x11 + ,0x00,0x00,0x00,0x00,0x00,0x06,0x14,0x21,0x2f,0x3c,0x49,0x57,0x61,0x6b,0x7b,0x84,0x93,0x9d,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa0,0x9c,0x8e,0x84,0x74,0x6a,0x5c,0x51,0x41,0x36,0x2b,0x1e,0x10,0x04,0x00,0x00,0x00 + ,0x00,0x05,0x1c,0x34,0x4b,0x61,0x72,0x84,0x94,0xa2,0xa2,0x98,0x8c,0x7b,0x65,0x4e,0x37,0x21,0x0a,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5c,0x66,0x71,0x7b,0x7f,0x84,0x8c,0x8c,0x8c,0x8c,0x84,0x7f,0x7b,0x71,0x62,0x51,0x40,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00 + ,0x00,0x04,0x16,0x27,0x38,0x49,0x5a,0x6a,0x74,0x7f,0x7f,0x8a,0x8c,0x8c,0x8a,0x7f,0x7f,0x74,0x6b,0x61,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x0b,0x21,0x36,0x49,0x5a,0x6a,0x7b,0x7f,0x8a,0x8c,0x8c,0x84,0x7f,0x74,0x6d,0x7b,0x7f,0x7f,0x7f,0x7b,0x65,0x4e + ,0x36,0x1e,0x06,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x40,0x51,0x62,0x71,0x7b,0x7f,0x8a,0x8c,0x8c,0x8a,0x7f,0x7b,0x71,0x62,0x51,0x40,0x2f,0x1e,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x51,0x5c,0x6a,0x74,0x7f,0x84,0x8c,0x8c,0x8c,0x8a,0x7f + ,0x7b,0x73,0x6a,0x5c,0x51,0x40,0x2b,0x15,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x73,0x6a,0x5d,0x6a,0x73,0x73,0x73,0x73,0x73,0x71,0x61,0x4c,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98 + ,0x7f,0x67,0x54,0x65,0x7b,0x8e,0xa3,0xb8,0xbc,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x02,0x14,0x27,0x36,0x44,0x57,0x6b,0x7f,0x98,0x8c,0x73,0x5c,0x67,0x7f,0x98,0x8c,0x73,0x5c,0x48,0x42,0x3c,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73 + ,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x3d,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1d,0x34,0x4b,0x61,0x74,0x8c,0xa2,0xb1,0xa4,0x94,0x84,0x7f,0x84,0x8e,0x9c,0xac,0xa4,0x93,0x7f,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00,0x06 + ,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x8c,0x94,0xa8,0xb9,0xa8,0x94,0x8c,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa8,0x94,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x7f,0x67,0x4f,0x37,0x1e + ,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x15,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x4b,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x52 + ,0x4b,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x38,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0x98,0x98,0x98,0x98,0x99,0xa4,0xb8,0xae,0x9d + ,0x98,0x98,0x98,0x97,0x8a,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0d,0x1b,0x27,0x36,0x41,0x4c,0x5a,0x66,0x72,0x7f,0x8c,0x94,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0x94,0x8a,0x7b,0x71,0x62,0x57,0x49 + ,0x3c,0x2f,0x21,0x16,0x0a,0x01,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x62,0x72,0x84,0x8c,0x8c,0x84,0x7b,0x6a,0x5a,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x46,0x51,0x5c,0x65,0x67,0x71,0x73,0x73,0x73,0x73,0x71,0x67,0x65,0x5c + ,0x51,0x40,0x2f,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x27,0x38,0x49,0x57,0x61,0x67,0x6b,0x73,0x73,0x73,0x73,0x6b,0x67,0x61,0x57,0x4c,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x38,0x49,0x5a,0x65,0x6b,0x73,0x73,0x73,0x71 + ,0x67,0x61,0x5c,0x65,0x67,0x67,0x67,0x65,0x5a,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2f,0x40,0x51,0x5c,0x65,0x6b,0x73,0x73,0x73,0x73,0x6b,0x65,0x5c,0x51,0x40,0x2f,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2f,0x3c + ,0x49,0x57,0x61,0x67,0x71,0x73,0x73,0x73,0x73,0x6b,0x65,0x5c,0x57,0x49,0x3c,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x4d,0x57,0x5b,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x2b,0x16,0x03,0x00,0x00,0x00 + ,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x50,0x5c,0x71,0x84,0x99,0xb0,0xb9,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x05,0x15,0x2a,0x43,0x5b,0x73,0x8a,0x9b,0x8c,0x73,0x60,0x71,0x84,0x98,0x8c,0x73,0x5b,0x43,0x2d,0x25,0x1b + ,0x0c,0x01,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x3d,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x02,0x15,0x2c,0x43,0x5a,0x71,0x84,0x94,0xa4,0xaf,0xa4,0x99,0x98,0x99,0xa3,0xab,0xa9,0x98 + ,0x84,0x72,0x61,0x4b,0x34,0x1d,0x06,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0xa4,0xa4,0xa8,0xb3,0xbb,0xb3,0xa8,0xa4,0xa4,0xa4,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb3,0xa8,0xa4,0xa4,0xa4,0xa4 + ,0xa4,0xa4,0xa4,0xa4,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2b,0x34,0x37,0x37,0x37,0x37,0x37,0x37,0x37 + ,0x43,0x5b,0x73,0x8c,0xa4,0xad,0x98,0x7f,0x67,0x4f,0x39,0x2b,0x1e,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x73,0x8c,0xa4,0xad,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73 + ,0x8c,0xa4,0xaa,0xaa,0xaa,0xaa,0xae,0xb0,0xb0,0xab,0xaa,0xaa,0xaa,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x14,0x21,0x2b,0x38,0x46,0x52,0x61,0x6b,0x7b,0x84,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x12,0x2a,0x43 + ,0x5b,0x73,0x89,0x84,0x74,0x6a,0x5c,0x51,0x41,0x36,0x27,0x1b,0x0d,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x40,0x51,0x62,0x71,0x73,0x73,0x71,0x66,0x5a,0x49,0x38,0x25,0x10,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x26,0x31,0x3c,0x46,0x4e + ,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x4e,0x46,0x3c,0x2f,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x27,0x36,0x41,0x4b,0x4f,0x57,0x5b,0x5b,0x5b,0x5b,0x57,0x4f,0x4b,0x41,0x36,0x2b,0x1e,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x05 + ,0x16,0x27,0x38,0x46,0x4e,0x57,0x5b,0x5b,0x5b,0x5a,0x51,0x4b,0x46,0x4e,0x4f,0x4f,0x4f,0x4e,0x46,0x38,0x25,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2f,0x3c,0x46,0x4e,0x57,0x5b,0x5b,0x5b,0x5b,0x57,0x4e,0x46,0x3c,0x2f,0x1e,0x0d,0x01,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x27,0x36,0x41,0x4b,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x57,0x4e,0x46,0x40,0x36,0x27,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x43,0x40,0x39,0x40,0x43,0x43,0x43,0x43 + ,0x43,0x42,0x3c,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa1,0xa4,0x98,0x7f,0x67,0x4f,0x51,0x67,0x7f,0x93,0xa2,0xa4,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0x9b,0x8a,0x73,0x61 + ,0x73,0x8c,0x9d,0x8c,0x73,0x5b,0x43,0x2a,0x13,0x06,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa1,0xa4,0x98,0x7f,0x67,0x4f,0x3d,0x4f,0x67,0x7f,0x98,0xa4,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x62,0x72,0x84 + ,0x93,0x9d,0xa4,0xa9,0xaa,0xaa,0xa8,0xa2,0x94,0x8a,0x7b,0x66,0x52,0x40,0x2b,0x15,0x02,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f + ,0x67,0x7f,0x98,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 + ,0x0a,0x15,0x1c,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x2a,0x43,0x5b,0x73,0x8c,0x98,0x98,0x95,0x7f,0x67,0x4f,0x37,0x1e,0x0b,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8d,0x98,0x98,0x95,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0b,0x17,0x25,0x31,0x40,0x4c,0x5a,0x66,0x72,0x7b + ,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x7b,0x71,0x62,0x57,0x49,0x3c,0x2f,0x21,0x14,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2f,0x40,0x51,0x5a,0x5b,0x5b,0x5a,0x51,0x46,0x38,0x27,0x16,0x04,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x06,0x10,0x1b,0x26,0x30,0x36,0x3c,0x42,0x43,0x43,0x43,0x43,0x42,0x3c,0x36,0x30,0x26,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x2b,0x34,0x38,0x40,0x43,0x43,0x43,0x43,0x40,0x38,0x34,0x2b,0x21 + ,0x16,0x0a,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x25,0x30,0x37,0x40,0x43,0x43,0x43,0x42,0x3c,0x34,0x30,0x36,0x37,0x37,0x37,0x36,0x30,0x25,0x16,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x26,0x30,0x37,0x40,0x43,0x43,0x43,0x43 + ,0x40,0x37,0x30,0x26,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x14,0x21,0x2b,0x34,0x3c,0x42,0x43,0x43,0x43,0x43,0x40,0x37,0x30,0x28,0x21,0x14,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a + ,0x2a,0x2a,0x2a,0x28,0x23,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x89,0x8c,0x8c,0x8c,0x7f,0x67,0x4f,0x4b,0x61,0x74,0x89,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00 + ,0x12,0x2a,0x43,0x5b,0x73,0x89,0x8c,0x7f,0x6b,0x5e,0x73,0x89,0x8c,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x89,0x8c,0x8c,0x8c,0x7f,0x67,0x4f,0x3d,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12 + ,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x51,0x62,0x72,0x7f,0x8a,0x8e,0x97,0x98,0x98,0x93,0x8c,0x84,0x74,0x6a,0x5a,0x46,0x31,0x1e,0x0a,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x89,0x73 + ,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x05,0x06,0x06,0x06,0x06,0x06,0x12,0x2a,0x42,0x5a,0x71,0x7f,0x7f,0x7f,0x7f,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x7f,0x7f,0x7f + ,0x7f,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x04,0x10,0x1e,0x2b,0x38,0x46,0x52,0x61,0x65,0x5a,0x46,0x30,0x19,0x04,0x00,0x00,0x0e,0x25,0x3c,0x51,0x61,0x65,0x5c,0x51,0x41,0x36,0x27,0x1b,0x0d,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2f,0x3c,0x42,0x43 + ,0x43,0x42,0x3c,0x31,0x25,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x10,0x19,0x1e,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1e,0x19,0x10,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0b,0x15,0x1c,0x21 + ,0x28,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x1c,0x15,0x0b,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x19,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x25,0x1d,0x19,0x1e,0x1e,0x1e,0x1e,0x1e,0x19,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x06,0x10,0x19,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x19,0x10,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0b,0x15,0x1d,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x19,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x11,0x0c,0x11,0x12,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x73,0x73,0x71,0x61,0x4b,0x41,0x57,0x6a,0x73,0x73,0x73,0x73 + ,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x71,0x61,0x57,0x6a,0x73,0x73,0x71,0x62,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x73,0x73,0x71,0x61,0x4b,0x3a,0x4b,0x61 + ,0x71,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2f,0x40,0x51,0x61,0x6b,0x73,0x7b,0x7f,0x7f,0x7f,0x7f,0x74,0x71,0x62,0x57,0x49,0x38,0x25,0x10,0x01,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x73 + ,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x71,0x61,0x4b,0x34,0x1c,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73 + ,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x61,0x67,0x67,0x67,0x67,0x65,0x5a,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x04,0x19,0x30,0x46,0x5a,0x65,0x67,0x67,0x67,0x67,0x65,0x5a,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x61,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x61,0x51,0x3c,0x25,0x0e + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0a,0x17,0x25,0x31,0x40,0x4b,0x4e,0x46,0x38,0x25,0x10,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x4b,0x4e,0x46,0x3c,0x2f,0x21,0x14,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x07,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x0e,0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x05,0x0a,0x11,0x12,0x12,0x12,0x12,0x11,0x0a,0x05,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x0a,0x11,0x12,0x12,0x12,0x12,0x0e,0x06,0x04,0x06,0x06,0x06,0x06,0x06,0x04,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x0a,0x11,0x12,0x12,0x12,0x12,0x11,0x0a,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x11 + ,0x0a,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x5b + ,0x5a,0x51,0x40,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5a,0x51,0x49,0x57,0x5b,0x5b,0x5a,0x51,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x49,0x57 + ,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x31,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2f,0x40,0x4c,0x57,0x5c,0x65,0x67,0x67,0x67,0x67,0x61,0x5a,0x51,0x41,0x36,0x27,0x16,0x04,0x00,0x00,0x00,0x00,0x02 + ,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x2b,0x15 + ,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x4b,0x4f,0x4f,0x4f,0x4f,0x4e,0x46,0x38 + ,0x25,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x25,0x38,0x46,0x4e,0x4f,0x4f,0x4f,0x4f,0x4e,0x46,0x38,0x25,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x4b,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f + ,0x4f,0x4f,0x4f,0x4f,0x4f,0x4b,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x1e,0x2b,0x34,0x36,0x30,0x25,0x16,0x04,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2b,0x34,0x36,0x30,0x26,0x1b,0x0d,0x02,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x02,0x14,0x27,0x36,0x40,0x43,0x43,0x43,0x43,0x42,0x3c,0x2f,0x27,0x36,0x40,0x43,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x36,0x40,0x43,0x43,0x42,0x3c,0x36,0x40,0x43,0x43,0x42,0x3c,0x2f,0x1e,0x0c,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x36,0x40,0x43,0x43,0x43,0x43,0x42,0x3c,0x2f,0x23,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2b,0x36,0x40,0x46,0x4e,0x4f,0x4f,0x4f,0x4f,0x4b,0x43,0x3c + ,0x2f,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43 + ,0x43,0x43,0x43,0x43,0x43,0x42,0x3c,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c + ,0x1e,0x2b,0x34,0x37,0x37,0x37,0x37,0x36,0x30,0x25,0x16,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x16,0x25,0x30,0x36,0x37,0x37,0x37,0x37,0x36,0x30,0x25,0x16,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2b,0x34 + ,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x34,0x2b,0x1e,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0a,0x15,0x1c,0x1e,0x19,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x01,0x0a + ,0x15,0x1c,0x1e,0x19,0x10,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x25,0x21 + ,0x28,0x2a,0x2a,0x2a,0x25,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x11,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0a,0x16,0x21 + ,0x28,0x30,0x36,0x37,0x37,0x37,0x37,0x34,0x2c,0x25,0x1b,0x0d,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b + ,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x0c,0x01,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0a,0x15,0x1c,0x1e,0x1e,0x1e,0x1e,0x1e,0x19,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x19,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x19,0x10,0x04,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0a,0x15,0x1c,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1c,0x15,0x0a,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x02,0x0a,0x11,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12,0x0e,0x0a,0x11,0x12,0x12,0x12,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x01,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0a,0x11,0x19,0x1e,0x1e,0x1e,0x1e,0x1e,0x1c,0x15,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x11 + ,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x01,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x06,0x0e,0x12,0x12,0x12 + ,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x05,0x06,0x06,0x06,0x06,0x0a,0x11,0x12,0x12,0x12,0x0e,0x08,0x0e,0x12,0x12,0x12,0x11,0x0a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x11,0x0a + ,0x02,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x06,0x06,0x06,0x06,0x05,0x03,0x06,0x0e,0x12,0x12,0x12,0x12,0x11,0x0a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x12 + ,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x05,0x06,0x06,0x06,0x06,0x05,0x02,0x03,0x0a,0x11,0x12,0x12,0x12,0x12,0x11,0x0a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x02,0x05,0x06,0x06,0x06,0x06,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x06,0x06,0x06,0x05,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x03,0x0a,0x11,0x12,0x12,0x12,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11 + ,0x12,0x12,0x12,0x12,0x12,0x12,0x0e,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12,0x12,0x12,0x12 + ,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x06,0x06,0x06,0x06,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x05,0x06,0x04,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x05,0x06,0x06,0x06,0x04,0x00,0x00,0x00,0x02,0x05,0x06,0x05,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12 + ,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x11,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a + ,0x28,0x21,0x14,0x05,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x01,0x0a,0x15,0x1c,0x1e,0x1e,0x1e,0x1e,0x21,0x28,0x2a,0x2a,0x2a,0x25,0x1e,0x25,0x2a,0x2a,0x2a,0x28,0x21,0x16,0x0a,0x01,0x00,0x00,0x00,0x00,0x00,0x01 + ,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x04,0x10,0x19,0x1e,0x1e,0x1e,0x1e,0x1c,0x18,0x1d,0x25,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x16,0x0a,0x01,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x01,0x0a,0x15,0x1c,0x1e,0x1e,0x1e,0x1e,0x1c,0x15,0x16,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x16 + ,0x0a,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0a,0x15,0x1c,0x1e,0x1e,0x1e,0x1e,0x19,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x19,0x1e,0x1e,0x1e,0x1c,0x15,0x0a,0x01 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0a,0x16,0x21,0x28,0x2a,0x2a,0x2a,0x25,0x1b,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00 + ,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x19,0x1e,0x1e,0x1e,0x1e,0x19,0x10,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x01,0x0a,0x15,0x1c,0x1e,0x19,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0b,0x15,0x1c,0x1e,0x1e,0x1e,0x19,0x10,0x06,0x0a,0x15,0x1c,0x1e,0x1c,0x15,0x0b,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a + ,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x42,0x3c,0x2f,0x23,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x42,0x3c,0x2f,0x1e,0x0a,0x00,0x00,0x00 + ,0x02,0x14,0x27,0x36,0x40,0x43,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x0c,0x1e,0x2b,0x34,0x37,0x37,0x37,0x36,0x36,0x40,0x43,0x43,0x42,0x3c,0x33,0x3c,0x42,0x43,0x43,0x40 + ,0x36,0x2b,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x42,0x3c,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x04,0x16,0x25,0x30,0x36,0x37,0x37,0x37,0x34,0x2e,0x34,0x3c,0x42,0x43 + ,0x43,0x43,0x40,0x36,0x2b,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x36,0x40,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x0c,0x1e,0x2b,0x34,0x37,0x37,0x37,0x37,0x34,0x2b + ,0x2b,0x36,0x40,0x43,0x43,0x43,0x43,0x40,0x36,0x2b,0x1e,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2b,0x34,0x37,0x37,0x37,0x36,0x30,0x25,0x16,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04 + ,0x16,0x25,0x30,0x36,0x37,0x37,0x34,0x2b,0x1e,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2b,0x36,0x40,0x43,0x43,0x42,0x3c,0x31,0x25,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x36,0x40,0x43 + ,0x43,0x43,0x43,0x40,0x36,0x27,0x16,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x36,0x40,0x43,0x43,0x43,0x43,0x43,0x42,0x3c,0x3c,0x42,0x43,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43 + ,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x02,0x14,0x27,0x36,0x40,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x25,0x30,0x36,0x37,0x37,0x36,0x30,0x26,0x1b + ,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2b,0x34,0x36,0x30,0x25,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x2b,0x34,0x37,0x37,0x36,0x30,0x26,0x1b,0x1e,0x2b,0x34,0x37,0x34,0x2b,0x21,0x16,0x0a + ,0x01,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x0c,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43 + ,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x32,0x40,0x51,0x5a,0x5b,0x5b + ,0x5b,0x5b,0x5a,0x51,0x40,0x2b,0x15,0x02,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x06,0x1b,0x2f,0x40,0x4b,0x4f,0x4f,0x4f,0x4e,0x4b,0x57 + ,0x5b,0x5b,0x5a,0x51,0x49,0x51,0x5a,0x5b,0x5b,0x57,0x4c,0x40,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x2b,0x15,0x00,0x00,0x00,0x10,0x25,0x38,0x46 + ,0x4e,0x4f,0x4f,0x4f,0x4b,0x44,0x4b,0x51,0x5a,0x5b,0x5b,0x5b,0x57,0x4c,0x40,0x2f,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x06 + ,0x1b,0x2f,0x40,0x4b,0x4f,0x4f,0x4f,0x4f,0x4b,0x40,0x41,0x4c,0x57,0x5b,0x5b,0x5b,0x5b,0x57,0x4c,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x4b,0x4f,0x4f,0x4f,0x4e,0x46,0x38,0x25,0x10,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x25,0x38,0x46,0x4e,0x4f,0x4f,0x4b,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2f,0x40,0x4c,0x57,0x5b,0x5b,0x5a,0x51,0x46,0x38,0x27,0x16,0x04,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x0b,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x38,0x25,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00 + ,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x05,0x16 + ,0x27,0x38,0x46,0x4e,0x4f,0x4f,0x4e,0x46,0x3c,0x2f,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2f,0x40,0x4b,0x4e,0x46,0x38,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x27,0x36,0x41,0x4b,0x4f,0x4f,0x4e,0x46,0x3c + ,0x31,0x2f,0x40,0x4b,0x4f,0x4b,0x41,0x36,0x2b,0x1e,0x0c,0x00,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x06,0x1b,0x2f,0x40,0x51,0x5a,0x5b,0x5b + ,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73 + ,0x73,0x71,0x62,0x51,0x40,0x4c,0x61,0x71,0x73,0x73,0x73,0x73,0x71,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x0e + ,0x25,0x3c,0x51,0x61,0x67,0x67,0x67,0x65,0x5e,0x6a,0x73,0x73,0x71,0x66,0x5e,0x66,0x71,0x73,0x73,0x6b,0x61,0x51,0x40,0x2b,0x16,0x03,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x71,0x61 + ,0x4b,0x34,0x1c,0x00,0x00,0x04,0x19,0x30,0x46,0x5a,0x65,0x67,0x67,0x67,0x61,0x57,0x61,0x67,0x71,0x73,0x73,0x73,0x6b,0x61,0x51,0x40,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73 + ,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x0e,0x25,0x3c,0x51,0x61,0x67,0x67,0x67,0x67,0x61,0x51,0x57,0x61,0x6b,0x73,0x73,0x73,0x73,0x6b,0x61,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x61,0x67,0x67,0x67,0x65 + ,0x5a,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x31,0x46,0x5a,0x65,0x67,0x67,0x61,0x51,0x3c,0x25,0x0e,0x06,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x51,0x61,0x6b,0x73,0x73,0x71 + ,0x66,0x5a,0x49,0x38,0x25,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x41,0x57,0x6a,0x73,0x73,0x73,0x73,0x6a,0x5a,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x73,0x73,0x73,0x71,0x61,0x61,0x71,0x73 + ,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x6a + ,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x04,0x16,0x27,0x38,0x49,0x5a,0x65,0x67,0x67,0x65,0x5c,0x51,0x40,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2f,0x40,0x51,0x61,0x65,0x5a,0x49,0x38,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x16 + ,0x27,0x38,0x49,0x57,0x61,0x67,0x67,0x65,0x5c,0x51,0x46,0x3f,0x51,0x61,0x67,0x61,0x57,0x4c,0x40,0x2f,0x1b,0x06,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11 + ,0x00,0x00,0x0e,0x25,0x3c,0x51,0x62,0x71,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x87,0x8c,0x8c,0x8c,0x84,0x72,0x61,0x4c,0x57,0x6b,0x7f,0x8c,0x8c,0x8c,0x89,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x82,0x8c,0x8c,0x8c,0x89,0x73,0x5c,0x46,0x30,0x3c,0x51,0x67,0x7f,0x8c,0x8c + ,0x8c,0x87,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x7f,0x7f,0x7f,0x7b,0x6f,0x7b,0x8a,0x8c,0x84,0x7b,0x6d,0x7b,0x84,0x8c,0x8a,0x7f,0x72,0x61,0x4c,0x36,0x21,0x0a,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x89,0x73,0x5b + ,0x43,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x8c,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x7f,0x7f,0x7f,0x72,0x6a,0x74,0x7f,0x84,0x8c,0x8c,0x8a,0x7f,0x72,0x62,0x51,0x40,0x2b,0x16,0x03,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x89,0x8c + ,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x7f,0x7f,0x7f,0x7f,0x71,0x5f,0x6a,0x74,0x7f,0x8a,0x8c,0x8c,0x8a,0x7f,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x12,0x2a,0x42,0x5a,0x71,0x7f,0x7f,0x7f,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x13,0x25,0x3c,0x51,0x66,0x7b,0x7f,0x7f,0x71,0x5a,0x42,0x2a,0x1d,0x1e,0x19,0x10,0x04,0x00,0x00,0x00,0x00,0x00 + ,0x10,0x26,0x3c,0x51,0x62,0x72,0x7f,0x8a,0x8c,0x84,0x7b,0x6a,0x5a,0x46,0x31,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1d,0x34,0x4b,0x61,0x74,0x89,0x8c,0x8c,0x8a,0x7b,0x65,0x4e,0x37,0x21,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73 + ,0x89,0x8c,0x8c,0x8c,0x8c,0x7f,0x67,0x67,0x7f,0x8c,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x89,0x8c,0x8c,0x8c,0x8c,0x8c + ,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x10,0x25,0x38,0x49,0x5a,0x6a,0x7b,0x7f,0x7f,0x7b,0x71,0x62,0x51,0x40,0x2b,0x15,0x02,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x40,0x51,0x62,0x72,0x7b,0x6a,0x5a,0x49,0x36,0x21 + ,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x27,0x38,0x49,0x5a,0x6a,0x74,0x7f,0x7f,0x7b,0x71,0x66,0x5a,0x4e,0x5c,0x71,0x7f,0x74,0x6b,0x61,0x51,0x3c,0x25,0x0e,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c + ,0x8c,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5a,0x6b,0x7f,0x93,0x9f,0xa2,0x93,0x7f,0x6b,0x5a,0x62,0x74,0x8a,0x9d,0xa1,0x94,0x84,0x71,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x0e,0x25,0x3c,0x51,0x67,0x7f,0x93,0xa1,0xa1,0x8e + ,0x7b,0x65,0x4e,0x37,0x43,0x5a,0x71,0x84,0x99,0xa2,0x97,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0x98,0x97,0x8a,0x7c,0x8c,0x9c,0xa2,0x97,0x84,0x7b,0x8c,0x98,0xa2,0x9d,0x92,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x06,0x1e + ,0x37,0x4f,0x67,0x7f,0x98,0xa4,0xa1,0x8c,0x73,0x5b,0x43,0x4f,0x67,0x7f,0x98,0xa4,0xa4,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x95,0x98,0x92,0x7f,0x7b,0x8a,0x93,0x99,0xa2,0xa4,0x9d,0x93,0x84,0x72,0x61,0x4c,0x36,0x21,0x0a + ,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa1,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0x98,0x98,0x8c,0x73,0x6a,0x7b,0x8a,0x93,0x9d,0xa4,0xa4,0x99,0x8a,0x73,0x5b + ,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x15,0x2a,0x43,0x5b,0x73,0x8c,0x98,0x95,0x7f,0x67,0x4f,0x37,0x1e,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2d,0x42,0x5a,0x71,0x84,0x95,0x8c,0x73,0x5b,0x43,0x2f + ,0x34,0x36,0x30,0x25,0x16,0x04,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x71,0x84,0x93,0x9d,0xa2,0x98,0x8c,0x7b,0x66,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x26,0x3c,0x51,0x67,0x7f,0x93,0xa2,0xa4,0x97,0x7f,0x6b,0x57,0x41,0x2b,0x15,0x02 + ,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa1,0xa4,0xa4,0x98,0x7f,0x67,0x67,0x7f,0x98,0xa4,0xa4,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xa4,0xa4,0x9b,0x8a,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12 + ,0x2a,0x43,0x5b,0x73,0x8c,0xa1,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x04,0x19,0x30,0x46,0x5a,0x6a,0x7b,0x8c,0x97,0x97,0x8e,0x84,0x72,0x61,0x4b,0x34,0x1d,0x06,0x00,0x00,0x02,0x15,0x2b,0x40 + ,0x51,0x62,0x72,0x84,0x8c,0x7b,0x6a,0x57,0x41,0x2f,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x0b,0x21,0x36,0x49,0x5a,0x6a,0x7b,0x8a,0x93,0x97,0x8e,0x84,0x7b,0x6b,0x61,0x6a,0x7b,0x8c,0x8a,0x7f,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f + ,0x98,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa0,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x25,0x38,0x4c,0x61,0x72,0x84,0x98,0xaa,0x9d,0x8c,0x7b,0x66,0x71,0x84,0x94,0xa7,0x9d,0x8a,0x74,0x62,0x51,0x3c,0x26,0x10,0x00,0x00,0x00 + ,0x06,0x1d,0x34,0x4b,0x61,0x74,0x8c,0xa2,0xab,0x97,0x7f,0x6b,0x57,0x40,0x4b,0x61,0x74,0x8c,0xa2,0xa4,0x8e,0x7b,0x65,0x4e,0x37,0x21,0x0a,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa7,0x94,0x8e,0x9a,0xa3,0xac,0xa3,0x8e,0x84,0x98,0xa3,0xae,0xb0,0x9d + ,0x8a,0x73,0x5c,0x46,0x30,0x19,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xaa,0x99,0x84,0x8c,0x9b,0xa0,0xa4,0xa4 + ,0xae,0xb1,0xa4,0x93,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0x98,0x98,0x98,0x98,0x98,0x98,0x9d,0xae,0xba,0xb8,0xad,0x9c,0x8a,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xa4,0x8e,0x7b,0x7b + ,0x8c,0x9c,0xa5,0xa4,0xa4,0xa4,0x98,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2d,0x43,0x5b,0x73,0x8c,0xa4,0x98,0x7f,0x67,0x4f,0x37,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43 + ,0x45,0x5b,0x73,0x8c,0x9d,0x8c,0x73,0x5b,0x45,0x43,0x4b,0x4e,0x46,0x38,0x25,0x10,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8e,0xa3,0xb3,0xb8,0xac,0x98,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x71,0x84,0x99 + ,0xad,0xad,0x9d,0x8a,0x74,0x61,0x4b,0x34,0x1d,0x06,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb8,0xb0,0x98,0x7f,0x67,0x67,0x7f,0x97,0xad,0xb7,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb0 + ,0x98,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8a,0x97,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8c,0x9c,0xac,0xad,0xa3,0x93,0x7f,0x67 + ,0x51,0x3c,0x25,0x0e,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x72,0x84,0x94,0x9c,0x8a,0x74,0x62,0x51,0x40,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x02,0x15,0x2b,0x41,0x57,0x6a,0x7b,0x8c,0x9c,0xa0,0xa2,0x9e,0x98,0x8c,0x7f,0x74,0x7b,0x8c,0x9b,0x93,0x7f,0x6b,0x57,0x40 + ,0x28,0x11,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x95,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98 + ,0x98,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x17,0x2b,0x40,0x52,0x66,0x7b,0x8c,0x9d,0xaa,0x98,0x84,0x71,0x74,0x8c,0xa2,0xa4,0x93 + ,0x7f,0x6b,0x57,0x41,0x2f,0x1b,0x06,0x00,0x00,0x00,0x02,0x15,0x2c,0x43,0x5a,0x71,0x84,0x98,0xaa,0x9d,0x8a,0x73,0x5c,0x46,0x51,0x67,0x7f,0x93,0xa6,0x9d,0x8a,0x73,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb3,0xa6,0x9a,0x8e + ,0x8e,0x9c,0xa9,0x9d,0x96,0x8e,0x8e,0x9c,0xae,0xa4,0x8e,0x7b,0x65,0x4e,0x36,0x1e,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67 + ,0x7f,0x98,0xae,0xa4,0x99,0x98,0x93,0x8c,0x8c,0x8e,0x9c,0xae,0xb3,0x9d,0x8a,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x8e,0xa4,0xb8,0xad,0x9c,0x8c,0x7b,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x12 + ,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xad,0x98,0x84,0x8c,0x9b,0x9d,0x97,0x8e,0x8c,0x8e,0x92,0x7f,0x67,0x4f,0x38,0x21,0x0a,0x00,0x00,0x00,0x0c,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x46,0x5b,0x73,0x8c,0xa4,0x98,0x7f,0x67,0x4f,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02 + ,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x57,0x5b,0x73,0x8c,0x9e,0x8c,0x73,0x5b,0x57,0x5b,0x61,0x65,0x5a,0x46,0x31,0x1b,0x06,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x93,0xa8,0xbd,0xc5,0xb8,0xa2,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00 + ,0x00,0x00,0x0a,0x21,0x37,0x4e,0x65,0x7b,0x8e,0xa1,0x9d,0x99,0xa1,0x93,0x7f,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8a,0x9d,0xb3,0xb0,0x98,0x7f,0x67,0x65,0x7b,0x8e,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00 + ,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x38,0x21,0x0a,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x7b,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f + ,0x67,0x7f,0x97,0xac,0xbe,0xc2,0xb0,0x99,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x90,0xa0,0xa7,0x94,0x84,0x72,0x62,0x51,0x40,0x2b,0x16,0x03,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x74,0x8a,0x9c,0x9c,0x8e,0x8c,0x8e,0x9c,0x9c + ,0x93,0x8c,0x8e,0x9c,0x9c,0x8a,0x74,0x61,0x4c,0x36,0x21,0x0a,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x7f,0x7f,0x7f + ,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x31,0x46,0x5a,0x6b,0x7f + ,0x93,0xa4,0xa3,0x8e,0x7b,0x7f,0x93,0xa5,0x98,0x84,0x72,0x61,0x4c,0x36,0x21,0x0d,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x66,0x7b,0x8e,0xa4,0xa4,0x8e,0x7b,0x65,0x4e,0x5a,0x71,0x84,0x99,0xa9,0x97,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x12 + ,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb4,0xa3,0x8e,0x7b,0x7b,0x8e,0xa4,0xa3,0x8e,0x7b,0x7b,0x8e,0xa4,0xad,0x97,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67 + ,0x4f,0x37,0x1e,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xae,0x9c,0x8c,0x7f,0x74,0x73,0x7b,0x8e,0xa3,0xb4,0xa4,0x8c,0x73,0x5b,0x43,0x2c,0x15,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x61,0x67,0x67,0x67,0x67,0x67,0x6e,0x7b,0x8e,0xa4,0xb1,0x9d,0x8c + ,0x7b,0x6a,0x5a,0x49,0x36,0x21,0x0a,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb4,0xa4,0x99,0x9b,0x94,0x8a,0x7f,0x7b,0x73,0x7b,0x7f,0x72,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x06,0x1b,0x2f,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5e,0x73,0x8c,0xa4,0x98,0x7f + ,0x67,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x06,0x1d,0x34,0x4b,0x61,0x71,0x73,0x73,0x6b,0x67,0x73,0x8c,0x9e,0x8c,0x73,0x67,0x6b,0x73,0x74,0x7b,0x66,0x51,0x3c,0x25,0x0e,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x74,0x8a,0x9c,0xac,0xb0,0xb5 + ,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x97,0x9d,0x8c,0x84,0x99,0x99,0x84,0x71,0x5a,0x43,0x2c,0x16,0x03,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x98,0xb0,0xad,0x97,0x7f,0x67,0x5c,0x73,0x8c + ,0xa4,0xb4,0xa2,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x0a,0x21,0x36,0x49,0x5a,0x65,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x61 + ,0x51,0x3c,0x25,0x0e,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xc5,0xcb,0xb3,0x9d,0x8a,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x72,0x84,0x94,0xa4,0xa4,0x94,0x84,0x72,0x61,0x4c,0x36,0x21,0x0a,0x00,0x00,0x06,0x1e,0x37,0x4f + ,0x67,0x7f,0x91,0x9b,0x8c,0x7b,0x73,0x7b,0x8a,0x93,0x9c,0xa0,0x9f,0x9c,0x8c,0x7b,0x6a,0x57,0x41,0x2b,0x16,0x03,0x00,0x00,0x04,0x19,0x30,0x46,0x5a,0x65,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x61,0x51,0x3c,0x25,0x0e + ,0x00,0x00,0x0e,0x25,0x3c,0x51,0x61,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x61,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x01,0x10,0x25,0x38,0x4c,0x61,0x72,0x84,0x98,0xa8,0x9c,0x8e,0x8e,0x9d,0x9d,0x8c,0x7b,0x66,0x52,0x40,0x2b,0x16,0x03,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x31,0x46,0x5c,0x73,0x8a,0x9d,0xaa,0x97,0x7f,0x6b,0x57,0x61,0x74,0x8c,0xa2,0xa3,0x8e + ,0x7b,0x65,0x4e,0x37,0x21,0x0a,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x99,0x84,0x71,0x73,0x8c,0xa4,0x99,0x84,0x71,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b + ,0x43,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8e,0x7b,0x6b,0x61,0x5e,0x71,0x84,0x99,0xb0,0xa4,0x8c,0x74,0x61,0x4b,0x34,0x1c,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x4b,0x4f,0x4f + ,0x4f,0x55,0x62,0x74,0x8a,0x9c,0xab,0xa4,0x93,0x7f,0x6b,0x5a,0x49,0x38,0x27,0x14,0x02,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xbb,0xb4,0xa4,0x94,0x84,0x74,0x6b,0x65,0x5e,0x65,0x67,0x61,0x51,0x40,0x2b,0x15,0x02,0x00,0x00,0x0e,0x25,0x3c,0x51,0x62 + ,0x71,0x73,0x73,0x73,0x73,0x76,0x8c,0xa4,0x98,0x7f,0x73,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x0e,0x25,0x3c,0x51,0x67,0x7f,0x8c,0x8a,0x7f,0x7f,0x77,0x8c,0x9e,0x8c,0x77,0x7f,0x7f,0x8a,0x8c,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x02 + ,0x15,0x2b,0x41,0x57,0x6a,0x7b,0x8c,0x97,0x99,0xa4,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x06,0x1b,0x31,0x46,0x5c,0x73,0x8a,0x9d,0x97,0x7f,0x7f,0x93,0x9f,0x8c,0x74,0x61,0x4c,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x0a,0x21,0x38,0x4f,0x67 + ,0x7f,0x98,0xb0,0xa4,0x8e,0x7b,0x65,0x5b,0x73,0x8c,0xa4,0xb0,0x99,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x93,0xa8,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x06,0x1b,0x2f,0x40,0x4e,0x54,0x55,0x55,0x55,0x55,0x55 + ,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x51,0x45,0x33,0x1e,0x08,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x93,0xa4,0xb5,0xbb,0xac,0x97,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x62,0x72,0x84,0x93,0x9d,0xa2,0x93,0x7f,0x6b + ,0x57,0x40,0x28,0x11,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x84,0x8d,0x7f,0x6b,0x5e,0x6a,0x74,0x7f,0x8a,0x93,0x8e,0x8a,0x7b,0x6a,0x5a,0x49,0x36,0x21,0x0b,0x00,0x00,0x00,0x00,0x10,0x25,0x38,0x46,0x4e,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f + ,0x4f,0x4f,0x4f,0x4f,0x4f,0x4b,0x40,0x2f,0x1b,0x06,0x00,0x00,0x06,0x1b,0x2f,0x40,0x4b,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4b,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x17,0x2b,0x40,0x52,0x66,0x7b,0x8c,0x9d,0xab,0xa4,0xa4,0xa5,0x93,0x7f,0x6b,0x5a,0x46,0x31,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x97,0xaa + ,0x9d,0x8a,0x73,0x5c,0x67,0x7f,0x93,0xa6,0x99,0x84,0x71,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x73,0x8c,0xa4,0x98,0x7f,0x67,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x06,0x1e + ,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5c,0x4c,0x51,0x67,0x7f,0x98,0xb0,0xa8,0x93,0x7f,0x67,0x4f,0x37,0x1e + ,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2b,0x34,0x38,0x42,0x51,0x62,0x72,0x84,0x94,0xa7,0xa4,0x94,0x84,0x72,0x61,0x4c,0x38,0x27,0x16,0x05,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb9,0xad,0x98,0x84,0x72,0x62,0x57,0x4e,0x49,0x4e,0x4f,0x4b,0x40,0x2f + ,0x1e,0x0a,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x8c,0x8c,0x8c,0x8c,0x8c,0x94,0xa8,0x9d,0x8e,0x8c,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x82,0x92,0x98,0x98,0x93,0x8c,0x94,0xa2,0x94,0x8c,0x93,0x98,0x98 + ,0x97,0x8a,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x0b,0x21,0x36,0x49,0x5a,0x6a,0x7b,0x7f,0x84,0x99,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x66,0x7b,0x8e,0x9f,0x8e,0x7b,0x74,0x8c,0x9f,0x93,0x7f,0x6b,0x57,0x40,0x28 + ,0x11,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5c,0x5b,0x73,0x8c,0xa2,0xae,0x98,0x7f,0x67,0x51,0x3c,0x25,0x0e,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x74,0x8c,0xa4,0xad,0x97,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00,0x00,0x0e + ,0x25,0x3c,0x51,0x61,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x61,0x51,0x3c,0x25,0x0e,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x72,0x84,0x94,0xa2,0xa2,0x98,0x8c,0x7b,0x65,0x4e,0x37,0x21,0x0a,0x00,0x00,0x00,0x0a,0x1e,0x2f + ,0x40,0x51,0x62,0x72,0x7f,0x8c,0x9c,0x94,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x04,0x19,0x30,0x46,0x5a,0x66,0x71,0x7b,0x72,0x61,0x4f,0x57,0x61,0x6b,0x74,0x7f,0x7b,0x73,0x6a,0x5a,0x49,0x38,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x04,0x16,0x25,0x30,0x36 + ,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x34,0x2b,0x1e,0x0c,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2b,0x34,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x34,0x2b,0x1e,0x0c,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x31,0x46,0x5a,0x6b,0x7f,0x98,0xb0,0xbc,0xb2,0x9d,0x8a,0x74,0x61,0x4c,0x38,0x25,0x10,0x01,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x0a,0x21,0x37,0x4e,0x65,0x7b,0x8e,0xa3,0xa4,0x8e,0x7b,0x65,0x71,0x84,0x99,0xa6,0x93,0x7f,0x67,0x51,0x3c,0x26,0x10,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x73,0x8c,0xa4,0x98,0x7f,0x67,0x73,0x8c,0xa4,0xb0 + ,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x4f,0x67 + ,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x28,0x3c,0x51,0x62,0x72,0x84,0x94,0xa4,0xa7,0x94,0x84,0x72,0x62,0x51,0x40,0x2b,0x17,0x05,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8e,0x7b + ,0x66,0x52,0x41,0x37,0x33,0x36,0x37,0x34,0x2b,0x1e,0x0d,0x01,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa0,0xa4,0xa4,0xa4,0xa4,0xa8,0xb5,0xae,0xa4,0xa4,0xa4,0xa4,0xa1,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x74,0x7f,0x8a + ,0x93,0x9c,0xa0,0xa8,0xb1,0xa8,0xa2,0x9c,0x93,0x8a,0x7f,0x7b,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x03,0x14,0x27,0x38,0x49,0x5a,0x65,0x6e,0x7f,0x98,0xa2,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x03,0x16,0x2c,0x43,0x5a,0x71,0x84,0x98,0x9d,0x8a + ,0x73,0x71,0x84,0x99,0x9d,0x8a,0x73,0x5c,0x46,0x31,0x1b,0x06,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x93,0xa8,0xa4,0x8c,0x73,0x5b,0x5a,0x71,0x84,0x99,0xaa,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x07,0x00,0x00,0x02,0x15,0x2c,0x43,0x5b,0x73,0x8c,0xa4,0xa4 + ,0x8e,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x62,0x72,0x84,0x8c,0x8c,0x84,0x7b,0x6a,0x5a + ,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2f,0x40,0x51,0x61,0x6b,0x7b,0x8c,0x84,0x72,0x62,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x10,0x25,0x38,0x46,0x51,0x5c,0x65,0x61,0x51,0x40,0x41,0x4c,0x57,0x61,0x67,0x65,0x5c,0x57,0x49,0x38,0x27,0x16,0x05 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x19,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1c,0x15,0x0a,0x01,0x00,0x00,0x00,0x00,0x01,0x0a,0x15,0x1c,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e + ,0x1e,0x1e,0x1c,0x15,0x0a,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0x25,0x38,0x4c,0x61,0x72,0x84,0x99,0xad,0xb0,0xae,0x99,0x84,0x71,0x5c + ,0x49,0x38,0x25,0x10,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x71,0x84,0x99,0xa9,0x97,0x7f,0x69,0x74,0x8c,0xa2,0xa2,0x8c,0x74,0x61,0x4b,0x34,0x1d,0x06,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67 + ,0x73,0x8c,0xa4,0x98,0x7f,0x67,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67 + ,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x00,0x04,0x16,0x27,0x38,0x49,0x5c,0x71,0x84,0x94,0xa4,0xab,0x9c,0x8a,0x74,0x62,0x51,0x40,0x2f,0x23,0x19,0x10,0x04,0x00,0x00,0x00,0x12 + ,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5c,0x46,0x31,0x21,0x1b,0x1e,0x1e,0x1c,0x15,0x0a,0x01,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0x98,0x98,0x98,0x98,0x98,0x9d,0xae,0xa4,0x99,0x98,0x98,0x98,0x98,0x8c,0x73,0x5b,0x43,0x2a,0x12 + ,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x61,0x6b,0x74,0x7f,0x8a,0x94,0xa8,0xba,0xb3,0x9d,0x8c,0x7f,0x74,0x6b,0x65,0x5a,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x40,0x4c,0x57,0x62,0x74,0x8a,0x9d,0x98,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00 + ,0x0a,0x21,0x36,0x4c,0x61,0x74,0x8c,0xa1,0x97,0x7f,0x6b,0x67,0x7f,0x93,0xa0,0x8e,0x7b,0x66,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x74,0x8c,0xa4,0x9d,0x8a,0x73,0x5b,0x51,0x67,0x7f,0x98,0xa6,0x93,0x7f,0x67,0x4f,0x37,0x1e,0x06,0x00 + ,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa2,0xa4,0x8c,0x73,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x0a,0x1e,0x2f + ,0x40,0x51,0x62,0x71,0x73,0x73,0x71,0x66,0x5a,0x49,0x38,0x25,0x10,0x00,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2f,0x40,0x4c,0x5a,0x6a,0x7b,0x72,0x62,0x51,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x04,0x16,0x25,0x31,0x3c,0x46,0x4e,0x4b,0x40,0x2f,0x2b,0x36,0x41 + ,0x4b,0x4f,0x4e,0x46,0x40,0x36,0x27,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x05,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x31,0x46,0x5a,0x6b + ,0x7f,0x93,0xa2,0x9d,0x99,0xa4,0xa3,0x8e,0x7b,0x6a,0x5a,0x46,0x31,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x26,0x3c,0x51,0x67,0x7f,0x93,0xa6,0x99,0x84,0x71,0x7f,0x93,0xa6,0x99,0x84,0x71,0x5a,0x43,0x2c,0x15,0x02,0x00,0x00,0x00,0x00,0x12 + ,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x73,0x8c,0xa4,0x98,0x7f,0x67,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x74,0x61,0x4b,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67 + ,0x4f,0x37,0x1e,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x01,0x10,0x25,0x38,0x49,0x5a,0x6a,0x7b,0x8e,0xa3,0xab,0x9c,0x8c,0x7b,0x6a,0x57,0x42 + ,0x38,0x37,0x36,0x30,0x25,0x16,0x04,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x05,0x06,0x06,0x05,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x8e,0xa4,0x99,0x84 + ,0x7f,0x7f,0x7f,0x7f,0x7f,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x02,0x14,0x27,0x36,0x41,0x4c,0x57,0x61,0x6f,0x7c,0x8e,0xa3,0xa4,0xa6,0x98,0x7f,0x6f,0x62,0x57,0x4e,0x46,0x38,0x27,0x14,0x02,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x61,0x6b,0x74,0x84,0x94,0xa0 + ,0x8e,0x7b,0x66,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x93,0xa0,0x8e,0x7b,0x65,0x61,0x74,0x8c,0xa1,0x98,0x84,0x71,0x5a,0x43,0x2c,0x16,0x03,0x00,0x00,0x02,0x15,0x2c,0x43,0x5b,0x73,0x8c,0xa4,0x98,0x7f,0x6b,0x57,0x4f,0x67,0x7f + ,0x98,0xa4,0x8c,0x74,0x61,0x4b,0x34,0x1c,0x05,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x99,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa0,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa1,0x8c,0x73 + ,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2f,0x40,0x51,0x5a,0x5b,0x5b,0x5a,0x51,0x46,0x38,0x27,0x16,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2b,0x38,0x49,0x5a,0x65,0x61,0x51,0x40,0x2f,0x1e,0x0c,0x00,0x00,0x00,0x00,0x00,0x04,0x10 + ,0x1b,0x26,0x30,0x36,0x34,0x2b,0x1e,0x16,0x21,0x2b,0x34,0x37,0x36,0x30,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x04,0x17,0x2b,0x40,0x52,0x66,0x7b,0x8c,0x9d,0xa3,0x8e,0x84,0x98,0xa8,0x9c,0x8c,0x7b,0x66,0x52,0x40,0x2b,0x17,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1d,0x34,0x4b,0x61,0x74,0x8c,0xa2,0xa2,0x8c,0x74,0x7f,0x98,0xa6,0x93,0x7f,0x67 + ,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x73,0x8c,0xa4,0x98,0x7f,0x67,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa8,0x93,0x7f,0x67 + ,0x56,0x5c,0x6b,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x0c,0x1e,0x31,0x46,0x5a,0x6a,0x7b + ,0x8c,0x9c,0xa9,0x9c,0x8c,0x7b,0x6a,0x5b,0x51,0x4f,0x4f,0x4f,0x4e,0x46,0x38,0x25,0x10,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x61 + ,0x67,0x67,0x67,0x67,0x67,0x73,0x8c,0xa4,0x98,0x7f,0x6a,0x67,0x67,0x67,0x67,0x61,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x05,0x14,0x21,0x2d,0x3c,0x4c,0x61,0x74,0x8a,0x9c,0x9c,0x8e,0x94,0x9c,0x8c,0x7b,0x66,0x51,0x3e,0x31,0x25,0x16,0x05,0x00,0x00,0x00,0x05 + ,0x1c,0x34,0x4b,0x61,0x72,0x7f,0x8a,0x94,0xa0,0x94,0x84,0x71,0x5c,0x46,0x31,0x1b,0x06,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x73,0x8a,0x9d,0x9d,0x8a,0x73,0x5c,0x5a,0x71,0x84,0x99,0xa2,0x8c,0x74,0x61,0x4c,0x36,0x21,0x0a,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b + ,0x73,0x8a,0x9d,0x98,0x7f,0x67,0x4f,0x4f,0x67,0x7f,0x93,0x9f,0x8c,0x73,0x5b,0x43,0x2c,0x15,0x02,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x67,0x7f,0x98,0x9d,0x8a,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x8c,0x8c,0x8c,0x8c,0x8c + ,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x42,0x3c,0x31,0x25,0x16,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0a,0x17,0x27,0x38,0x46,0x4e,0x4b,0x40,0x2f + ,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x10,0x19,0x1e,0x1c,0x15,0x0a,0x03,0x0b,0x15,0x1c,0x1e,0x1e,0x19,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0x25,0x38,0x4c,0x61,0x72,0x84,0x98,0xa8,0x98,0x84,0x7b,0x8c,0x9d,0xaa,0x98,0x84,0x72,0x61,0x4c,0x38,0x25,0x10,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2c,0x43,0x5a,0x71,0x84 + ,0x98,0xa5,0x93,0x7f,0x8a,0x9d,0x9d,0x8a,0x74,0x61,0x4b,0x34,0x1d,0x06,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x73,0x8c,0xa4,0x98,0x7f,0x67,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x06,0x1e + ,0x37,0x4f,0x67,0x7f,0x97,0xad,0xb0,0x98,0x7f,0x71,0x68,0x71,0x7b,0x8c,0x9d,0xb3,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e + ,0x00,0x00,0x06,0x1b,0x2f,0x40,0x52,0x66,0x7b,0x8c,0x9c,0xad,0xa4,0x8e,0x7b,0x6e,0x67,0x67,0x67,0x67,0x67,0x67,0x65,0x5a,0x46,0x30,0x19,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x4b,0x4f,0x4f,0x4f,0x4f,0x5b,0x73,0x8c,0xa4,0x98,0x7f,0x67,0x52,0x4f,0x4f,0x4f,0x4b,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x07,0x1b,0x31,0x46,0x5a,0x6b,0x7f,0x93,0x9b,0x8c,0x7c,0x8a,0x9c,0x98,0x84,0x71 + ,0x5c,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8f,0x9d,0xa0,0x94,0x84,0x72,0x62,0x51,0x3c,0x26,0x10,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8d,0x98,0x95,0x7f,0x6b,0x57,0x51,0x67,0x7f,0x92,0x98,0x91,0x7f,0x6b,0x57 + ,0x40,0x28,0x11,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x8c,0x8c,0x7f,0x67,0x4f,0x4b,0x61,0x74,0x89,0x8c,0x89,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x07,0x1e,0x37,0x4f,0x67,0x7f,0x8c,0x8c,0x7f,0x6b,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x0e + ,0x25,0x3c,0x51,0x62,0x71,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x05,0x16,0x25,0x30,0x36,0x34,0x2b,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x31,0x46,0x5a,0x6b,0x7f,0x93,0xa4,0x9d,0x8c,0x7b,0x6e,0x7f,0x93,0xa4,0xa4,0x93,0x7f,0x6b,0x5a,0x46,0x31,0x1e,0x0c,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x66,0x7b,0x8e,0xa4,0x99,0x84,0x8e,0xa3,0x97,0x7f,0x6b,0x57,0x41,0x2b,0x15,0x02,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x73,0x8c,0xa4,0x98,0x7f,0x67,0x73,0x8c,0xa4,0xb0 + ,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x8e,0xa4,0xb2,0x9d,0x8e,0x84,0x7f,0x84,0x8e,0x9a,0xa5,0xb5,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x4f,0x67 + ,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x0e,0x25,0x3c,0x51,0x62,0x72,0x84,0x98,0xac,0xb8,0xa4,0x8e,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7b,0x65,0x4e,0x36,0x1e,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73 + ,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2b,0x34,0x37,0x37,0x37,0x43,0x5b,0x73,0x8c,0xa4,0x98,0x7f,0x67,0x4f,0x3a,0x37,0x37,0x34,0x2b,0x1e,0x0c,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x66,0x7b + ,0x8c,0x98,0x8c,0x7b,0x6f,0x7b,0x8c,0x9a,0x8e,0x7b,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x74,0x8c,0x97,0x8e,0x84,0x72,0x62,0x51,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x7f,0x7f,0x7f,0x7b,0x65 + ,0x4e,0x4b,0x61,0x72,0x7f,0x7f,0x7f,0x7f,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x0a,0x21,0x36,0x4c,0x61,0x71,0x73,0x73,0x71,0x61,0x4b,0x41,0x57,0x6a,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73 + ,0x71,0x61,0x4c,0x36,0x21,0x0a,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x0e,0x06,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x19,0x1e,0x1c,0x15,0x0a,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x40,0x52,0x66,0x7b,0x8c,0x9d,0xa6,0x93,0x7f,0x6b,0x62,0x72,0x84,0x98,0xaa,0x9d + ,0x8c,0x7b,0x66,0x52,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x31,0x46,0x5c,0x73,0x8a,0x9d,0xa4,0x99,0x9d,0xa3,0x8e,0x7b,0x65,0x4e,0x37,0x21,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67 + ,0x73,0x8c,0xa4,0x98,0x7f,0x67,0x73,0x8c,0xa4,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x04,0x19,0x30,0x46,0x5c,0x73,0x8a,0x9d,0xb1,0xae,0xa3,0x99,0x98,0x99,0x9a,0x8e,0x94,0xa8,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67 + ,0x7f,0x98,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x4f,0x67,0x7f,0x98,0xb0,0xb0,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x94,0xa4,0xb5,0xba,0xae,0x9d,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x95,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x12 + ,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb6,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0a,0x15,0x1c,0x1e,0x1e,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0x98,0x7f,0x67,0x4f,0x37,0x21,0x1e,0x1c,0x15,0x0a,0x01,0x00 + ,0x00,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x84,0x97,0x93,0x7f,0x6b,0x5e,0x6a,0x7b,0x8c,0x98,0x8a,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x02,0x15,0x2c,0x43,0x5a,0x71,0x84,0x7f,0x7b,0x71,0x62,0x51,0x40,0x2f,0x1e,0x0c,0x00,0x00,0x00,0x00,0x04 + ,0x19,0x30,0x46,0x5a,0x65,0x67,0x67,0x67,0x65,0x5a,0x46,0x40,0x51,0x61,0x67,0x67,0x67,0x67,0x61,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x03,0x16,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5a,0x51,0x40,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00 + ,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5a,0x51,0x40,0x2b,0x16,0x03,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x72,0x84,0x98,0xa2 + ,0x9d,0x8a,0x74,0x61,0x54,0x66,0x7b,0x8c,0x9d,0xa2,0x98,0x84,0x72,0x62,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x97,0xa4,0xa4,0xa4,0x9d,0x8a,0x73,0x5c,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x12 + ,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xad,0x98,0x7f,0x67,0x73,0x8c,0xa4,0x98,0x7f,0x67,0x73,0x8c,0xa4,0xad,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x11,0x28,0x40,0x57,0x6b,0x7f,0x92,0x9d,0xa8,0xae,0xa9,0xa2,0x98,0x8c,0x7c,0x8a,0x9d,0xa4,0x98,0x7f,0x67 + ,0x4f,0x37,0x1e,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x98,0xad,0xa4,0x8c,0x73,0x5b,0x43,0x4f,0x67,0x7f,0x98,0xad,0xad,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0x9f,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4 + ,0xa4,0x98,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0xa4,0xb0,0xa4,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x05,0x06,0x12,0x2a,0x43,0x5b,0x73,0x8c,0x98,0x95,0x7f + ,0x67,0x4f,0x37,0x1e,0x09,0x05,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x7f,0x8c,0x84,0x72,0x61,0x4f,0x5a,0x6b,0x7f,0x8d,0x84,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x62,0x71,0x6b,0x65,0x5c,0x51 + ,0x40,0x2f,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x10,0x25,0x38,0x46,0x4e,0x4f,0x4f,0x4f,0x4e,0x46,0x38,0x2f,0x40,0x4b,0x4f,0x4f,0x4f,0x4f,0x4b,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x42,0x3c,0x2f,0x27,0x36,0x40 + ,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x42,0x3c,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x28 + ,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x8a,0x8c,0x8c,0x8c,0x7f,0x6b,0x57,0x49,0x5a,0x6b,0x7f,0x8c,0x8c,0x8c,0x8a,0x82,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x21,0x37,0x4e,0x65,0x7b,0x8a,0x8c,0x8c,0x8c,0x8c,0x7f,0x6b,0x57,0x40 + ,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0x98,0x98,0x95,0x7f,0x67,0x73,0x8c,0x98,0x95,0x7f,0x67,0x73,0x8c,0x98,0x98,0x95,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x00,0x0a,0x21,0x36,0x4c,0x61,0x72,0x7f,0x8a,0x93,0x98,0x97 + ,0x8e,0x84,0x7b,0x6f,0x7f,0x8c,0x8c,0x8c,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x06,0x1e,0x37,0x4f,0x67,0x7f,0x95,0x98,0x98,0x8c,0x73,0x5b,0x43,0x4f,0x67,0x7f,0x95,0x98,0x98,0x95,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x89,0x8c,0x8c + ,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x7f,0x67,0x4f,0x37,0x1e,0x00,0x00,0x12,0x2a,0x43,0x5b,0x73,0x8c,0x98,0x98,0x98,0x8c,0x73,0x5b,0x43,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x12,0x2a,0x42,0x5a,0x71,0x7f,0x7f,0x7f,0x7b,0x65,0x4e,0x36,0x1e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x61,0x6b,0x7b,0x72,0x62,0x51,0x41,0x4c,0x61,0x72,0x7b,0x71,0x62,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00 + ,0x06,0x1b,0x2f,0x40,0x51,0x5a,0x57,0x4e,0x46,0x3c,0x2f,0x1e,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x16,0x25,0x30,0x36,0x37,0x37,0x37,0x36,0x30,0x25,0x1e,0x2b,0x34,0x37,0x37,0x37,0x37,0x34,0x2b,0x1e,0x0c,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b + ,0x25,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12 + ,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x1c,0x34,0x4b,0x61,0x71,0x73,0x73,0x73,0x73,0x71,0x61,0x4c,0x3c,0x4c,0x61,0x71,0x73,0x73,0x73,0x73,0x73,0x6a,0x57,0x40,0x28,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x19,0x30,0x46,0x5a + ,0x6a,0x73,0x73,0x73,0x73,0x73,0x71,0x61,0x4c,0x36,0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x7f,0x7f,0x7f,0x7f,0x7b,0x65,0x71,0x7f,0x7f,0x7f,0x7b,0x65,0x71,0x7f,0x7f,0x7f,0x7f,0x7b,0x65,0x4e,0x36,0x1e,0x00,0x00,0x00,0x03 + ,0x16,0x2b,0x40,0x51,0x61,0x6b,0x74,0x7f,0x7f,0x7f,0x7b,0x71,0x66,0x62,0x71,0x73,0x73,0x73,0x71,0x61,0x4b,0x34,0x1c,0x00,0x00,0x06,0x1e,0x36,0x4e,0x65,0x7b,0x7f,0x7f,0x7f,0x7f,0x71,0x5a,0x42,0x4e,0x65,0x7b,0x7f,0x7f,0x7f,0x7f,0x7b,0x65,0x4e,0x36,0x1e + ,0x00,0x00,0x11,0x28,0x40,0x57,0x6a,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x71,0x61,0x4b,0x34,0x1c,0x00,0x00,0x12,0x2a,0x42,0x5a,0x71,0x7f,0x7f,0x7f,0x7f,0x7f,0x71,0x5a,0x42,0x2a,0x12,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x61,0x67,0x67,0x67,0x65,0x5a,0x46,0x30,0x19,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x4c,0x5a,0x65,0x61,0x51,0x40,0x32,0x40,0x51,0x61,0x65,0x5c + ,0x51,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2f,0x3c,0x42,0x40,0x37,0x30,0x26,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x19,0x1e,0x1e,0x1e,0x1e,0x1e,0x19,0x10,0x0a,0x15,0x1c,0x1e,0x1e,0x1e,0x1e,0x1c,0x15 + ,0x0a,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x0e,0x06,0x02,0x0a,0x11,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0x2b,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x31,0x40,0x51,0x5a,0x5b,0x5b,0x5b,0x5b,0x5b,0x57,0x49,0x36,0x21,0x0a,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x25,0x38,0x49,0x57,0x5b,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x2b,0x16,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x25,0x3c,0x51,0x61,0x67,0x67,0x67,0x67,0x65,0x5a,0x61,0x67,0x67,0x67,0x65,0x5a,0x61,0x67,0x67,0x67 + ,0x67,0x65,0x5a,0x46,0x30,0x19,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x40,0x4c,0x57,0x61,0x67,0x67,0x67,0x65,0x5c,0x51,0x51,0x5a,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x2b,0x15,0x00,0x00,0x04,0x19,0x30,0x46,0x5a,0x65,0x67,0x67,0x67,0x67,0x61,0x51,0x3c,0x46,0x5a + ,0x65,0x67,0x67,0x67,0x67,0x65,0x5a,0x46,0x30,0x19,0x00,0x00,0x0a,0x21,0x36,0x49,0x57,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5a,0x51,0x40,0x2b,0x15,0x00,0x00,0x0e,0x25,0x3c,0x51,0x61,0x67,0x67,0x67,0x67,0x67,0x61 + ,0x51,0x3c,0x25,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x4b,0x4f,0x4f,0x4f,0x4e,0x46,0x38,0x25,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2b,0x38,0x46 + ,0x4e,0x4b,0x40,0x2f,0x23,0x2f,0x40,0x4b,0x4e,0x46,0x3c,0x2f,0x1e,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x28,0x21,0x19,0x10,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x06,0x06,0x06,0x06,0x06,0x04 + ,0x00,0x00,0x02,0x05,0x06,0x06,0x06,0x06,0x05,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1e,0x2f,0x3c,0x42,0x43,0x43,0x43,0x43,0x42,0x3c,0x2f,0x23,0x2f,0x3c,0x42,0x43,0x43 + ,0x43,0x43,0x43,0x40,0x36,0x27,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x16,0x27,0x36,0x40,0x43,0x43,0x43,0x43,0x43,0x42,0x3c,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1b,0x2f,0x40,0x4b,0x4f,0x4f,0x4f,0x4f,0x4e,0x46 + ,0x4b,0x4f,0x4f,0x4f,0x4e,0x46,0x4b,0x4f,0x4f,0x4f,0x4f,0x4e,0x46,0x38,0x25,0x10,0x00,0x00,0x00,0x00,0x01,0x0d,0x1e,0x2b,0x36,0x41,0x4b,0x4f,0x4f,0x4f,0x4e,0x46,0x3c,0x3c,0x42,0x43,0x43,0x43,0x42,0x3c,0x2f,0x1e,0x0a,0x00,0x00,0x00,0x10,0x25,0x38,0x46 + ,0x4e,0x4f,0x4f,0x4f,0x4f,0x4b,0x40,0x2f,0x38,0x46,0x4e,0x4f,0x4f,0x4f,0x4f,0x4e,0x46,0x38,0x25,0x10,0x00,0x00,0x02,0x14,0x27,0x36,0x40,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x42,0x3c,0x2f,0x1e,0x0a,0x00,0x00,0x06 + ,0x1b,0x2f,0x40,0x4b,0x4f,0x4f,0x4f,0x4f,0x4f,0x4b,0x40,0x2f,0x1b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x1e,0x2b,0x34,0x37,0x37,0x37,0x36,0x30,0x25,0x16,0x04,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x01,0x0a,0x17,0x25,0x30,0x36,0x34,0x2b,0x1e,0x11,0x1e,0x2b,0x34,0x36,0x30,0x26,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x11,0x0a,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0c,0x1b,0x25,0x2a,0x2a,0x2a,0x2a + ,0x2a,0x2a,0x25,0x1b,0x11,0x1b,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x28,0x21,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x1b,0x0c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x0c,0x1e,0x2b,0x34,0x37,0x37,0x37,0x37,0x36,0x30,0x34,0x37,0x37,0x37,0x36,0x30,0x34,0x37,0x37,0x37,0x37,0x36,0x30,0x25,0x16,0x04,0x00,0x00,0x00,0x00,0x00,0x01,0x0a,0x16,0x21,0x2b,0x34,0x37,0x37,0x37,0x36,0x30,0x26,0x25,0x2a,0x2a,0x2a,0x2a,0x2a,0x25 + ,0x1b,0x0c,0x01,0x00,0x00,0x00,0x04,0x16,0x25,0x30,0x36,0x37,0x37,0x37,0x37,0x34,0x2b,0x1e,0x25,0x30,0x36,0x37,0x37,0x37,0x37,0x36,0x30,0x25,0x16,0x04,0x00,0x00,0x00,0x05,0x14,0x21,0x28,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a + ,0x2a,0x2a,0x2a,0x25,0x1b,0x0c,0x01,0x00,0x00,0x00,0x0c,0x1e,0x2b,0x34,0x37,0x37,0x37,0x37,0x37,0x34,0x2b,0x1e,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0a,0x15,0x1c,0x1e,0x1e,0x1e,0x1e + ,0x19,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x19,0x1e,0x1c,0x15,0x0a,0x02,0x0a,0x15,0x1c,0x1e,0x19,0x10,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x01,0x06,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x11,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0a,0x15,0x1c,0x1e,0x1e,0x1e,0x1e,0x1e,0x19,0x1c,0x1e,0x1e,0x1e,0x1e,0x19,0x1c,0x1e,0x1e,0x1e,0x1e,0x1e,0x19,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0b,0x15,0x1c,0x1e,0x1e,0x1e + ,0x1e,0x19,0x10,0x0e,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x19,0x1e,0x1e,0x1e,0x1e,0x1e,0x1c,0x15,0x0a,0x10,0x19,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x19,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x02,0x0a,0x11,0x12,0x12,0x12 + ,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x0e,0x06,0x00,0x00,0x00,0x00,0x00,0x01,0x0a,0x15,0x1c,0x1e,0x1e,0x1e,0x1e,0x1e,0x1c,0x15,0x0a,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + }; + + const HudFont g_hudFont = { 32, 510, 172, 5, 24, 95, g_hudFontGlyphs, g_hudFontImage }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/hud/dxvk_hud_font.h b/utils/dxvk-1.10.3/src/dxvk/hud/dxvk_hud_font.h new file mode 100644 index 00000000000..d9530b3f639 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/hud/dxvk_hud_font.h @@ -0,0 +1,31 @@ +#pragma once + +#include + +namespace dxvk::hud { + + struct HudGlyph { + uint32_t codePoint; + int32_t x; + int32_t y; + int32_t w; + int32_t h; + int32_t originX; + int32_t originY; + }; + + struct HudFont { + int32_t size; + uint32_t width; + uint32_t height; + uint32_t falloff; + uint32_t advance; + uint32_t charCount; + + const HudGlyph* glyphs; + const uint8_t* texture; + }; + + extern const HudFont g_hudFont; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/hud/dxvk_hud_item.cpp b/utils/dxvk-1.10.3/src/dxvk/hud/dxvk_hud_item.cpp new file mode 100644 index 00000000000..d236287a8e2 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/hud/dxvk_hud_item.cpp @@ -0,0 +1,722 @@ +#include "dxvk_hud_item.h" + +#include +#include + +namespace dxvk::hud { + + HudItem::~HudItem() { + + } + + + void HudItem::update(dxvk::high_resolution_clock::time_point time) { + // Do nothing by default. Some items won't need this. + } + + + HudItemSet::HudItemSet(const Rc& device) { + std::string configStr = env::getEnvVar("DXVK_HUD"); + + if (configStr.empty()) + configStr = device->config().hud; + + std::string::size_type pos = 0; + std::string::size_type end = 0; + std::string::size_type mid = 0; + + while (pos < configStr.size()) { + end = configStr.find(',', pos); + mid = configStr.find('=', pos); + + if (end == std::string::npos) + end = configStr.size(); + + if (mid != std::string::npos && mid < end) { + m_options.insert({ + configStr.substr(pos, mid - pos), + configStr.substr(mid + 1, end - mid - 1) }); + } else { + m_enabled.insert(configStr.substr(pos, end - pos)); + } + + pos = end + 1; + } + + if (m_enabled.find("full") != m_enabled.end()) + m_enableFull = true; + + if (m_enabled.find("1") != m_enabled.end()) { + m_enabled.insert("devinfo"); + m_enabled.insert("fps"); + } + } + + + HudItemSet::~HudItemSet() { + + } + + + void HudItemSet::update() { + auto time = dxvk::high_resolution_clock::now(); + + for (const auto& item : m_items) + item->update(time); + } + + + void HudItemSet::render(HudRenderer& renderer) { + HudPos position = { 8.0f, 8.0f }; + + for (const auto& item : m_items) + position = item->render(renderer, position); + } + + + void HudItemSet::parseOption(const std::string& str, float& value) { + try { + value = std::stof(str); + } catch (const std::invalid_argument&) { + return; + } + } + + + HudPos HudVersionItem::render( + HudRenderer& renderer, + HudPos position) { + position.y += 16.0f; + + renderer.drawText(16.0f, + { position.x, position.y }, + { 1.0f, 1.0f, 1.0f, 1.0f }, + "DXVK " DXVK_VERSION); + + position.y += 8.0f; + return position; + } + + + HudClientApiItem::HudClientApiItem(std::string api) + : m_api(api) { + + } + + + HudClientApiItem::~HudClientApiItem() { + + } + + + HudPos HudClientApiItem::render( + HudRenderer& renderer, + HudPos position) { + position.y += 16.0f; + + renderer.drawText(16.0f, + { position.x, position.y }, + { 1.0f, 1.0f, 1.0f, 1.0f }, + m_api); + + position.y += 8.0f; + return position; + } + + + HudDeviceInfoItem::HudDeviceInfoItem(const Rc& device) { + VkPhysicalDeviceProperties props = device->adapter()->deviceProperties(); + + m_deviceName = props.deviceName; + m_driverVer = str::format("Driver: ", + VK_VERSION_MAJOR(props.driverVersion), ".", + VK_VERSION_MINOR(props.driverVersion), ".", + VK_VERSION_PATCH(props.driverVersion)); + m_vulkanVer = str::format("Vulkan: ", + VK_VERSION_MAJOR(props.apiVersion), ".", + VK_VERSION_MINOR(props.apiVersion), ".", + VK_VERSION_PATCH(props.apiVersion)); + } + + + HudDeviceInfoItem::~HudDeviceInfoItem() { + + } + + + HudPos HudDeviceInfoItem::render( + HudRenderer& renderer, + HudPos position) { + position.y += 16.0f; + renderer.drawText(16.0f, + { position.x, position.y }, + { 1.0f, 1.0f, 1.0f, 1.0f }, + m_deviceName); + + position.y += 24.0f; + renderer.drawText(16.0f, + { position.x, position.y }, + { 1.0f, 1.0f, 1.0f, 1.0f }, + m_driverVer); + + position.y += 20.0f; + renderer.drawText(16.0f, + { position.x, position.y }, + { 1.0f, 1.0f, 1.0f, 1.0f }, + m_vulkanVer); + + position.y += 8.0f; + return position; + } + + + HudFpsItem::HudFpsItem() { } + HudFpsItem::~HudFpsItem() { } + + + void HudFpsItem::update(dxvk::high_resolution_clock::time_point time) { + m_frameCount += 1; + + auto elapsed = std::chrono::duration_cast(time - m_lastUpdate); + + if (elapsed.count() >= UpdateInterval) { + int64_t fps = (10'000'000ll * m_frameCount) / elapsed.count(); + + m_frameRate = str::format(fps / 10, ".", fps % 10); + m_frameCount = 0; + m_lastUpdate = time; + } + } + + + HudPos HudFpsItem::render( + HudRenderer& renderer, + HudPos position) { + position.y += 16.0f; + + renderer.drawText(16.0f, + { position.x, position.y }, + { 1.0f, 0.25f, 0.25f, 1.0f }, + "FPS:"); + + renderer.drawText(16.0f, + { position.x + 60.0f, position.y }, + { 1.0f, 1.0f, 1.0f, 1.0f }, + m_frameRate); + + position.y += 8.0f; + return position; + } + + + HudFrameTimeItem::HudFrameTimeItem() { } + HudFrameTimeItem::~HudFrameTimeItem() { } + + + void HudFrameTimeItem::update(dxvk::high_resolution_clock::time_point time) { + auto elapsed = std::chrono::duration_cast(time - m_lastUpdate); + + m_dataPoints[m_dataPointId] = float(elapsed.count()); + m_dataPointId = (m_dataPointId + 1) % NumDataPoints; + + m_lastUpdate = time; + } + + + HudPos HudFrameTimeItem::render( + HudRenderer& renderer, + HudPos position) { + std::array points; + + // 60 FPS = optimal, 10 FPS = worst + const float targetUs = 16'666.6f; + const float minUs = 5'000.0f; + const float maxUs = 100'000.0f; + + // Ten times the maximum/minimum number + // of milliseconds for a single frame + uint32_t minMs = 0xFFFFFFFFu; + uint32_t maxMs = 0x00000000u; + + // Paint the time points + for (uint32_t i = 0; i < NumDataPoints; i++) { + float us = m_dataPoints[(m_dataPointId + i) % NumDataPoints]; + + minMs = std::min(minMs, uint32_t(us / 100.0f)); + maxMs = std::max(maxMs, uint32_t(us / 100.0f)); + + float r = std::min(std::max(-1.0f + us / targetUs, 0.0f), 1.0f); + float g = std::min(std::max( 3.0f - us / targetUs, 0.0f), 1.0f); + float l = std::sqrt(r * r + g * g); + + HudNormColor color = { + uint8_t(255.0f * (r / l)), + uint8_t(255.0f * (g / l)), + uint8_t(0), uint8_t(255) }; + + float hVal = std::log2(std::max((us - minUs) / targetUs + 1.0f, 1.0f)) + / std::log2((maxUs - minUs) / targetUs); + + points[i].value = std::max(hVal, 1.0f / 40.0f); + points[i].color = color; + } + + renderer.drawGraph(position, + HudPos { float(NumDataPoints), 40.0f }, + points.size(), points.data()); + + position.y += 58.0f; + + renderer.drawText(12.0f, + { position.x, position.y }, + { 1.0f, 0.25f, 0.25f, 1.0f }, + "min:"); + + renderer.drawText(12.0f, + { position.x + 45.0f, position.y }, + { 1.0f, 1.0f, 1.0f, 1.0f }, + str::format(minMs / 10, ".", minMs % 10)); + + renderer.drawText(12.0f, + { position.x + 150.0f, position.y }, + { 1.0f, 0.25f, 0.25f, 1.0f }, + "max:"); + + renderer.drawText(12.0f, + { position.x + 195.0f, position.y }, + { 1.0f, 1.0f, 1.0f, 1.0f }, + str::format(maxMs / 10, ".", maxMs % 10)); + + position.y += 4.0f; + return position; + } + + + HudSubmissionStatsItem::HudSubmissionStatsItem(const Rc& device) + : m_device(device) { + + } + + + HudSubmissionStatsItem::~HudSubmissionStatsItem() { + + } + + + void HudSubmissionStatsItem::update(dxvk::high_resolution_clock::time_point time) { + DxvkStatCounters counters = m_device->getStatCounters(); + + uint64_t currSubmitCount = counters.getCtr(DxvkStatCounter::QueueSubmitCount); + uint64_t currSyncCount = counters.getCtr(DxvkStatCounter::GpuSyncCount); + uint64_t currSyncTicks = counters.getCtr(DxvkStatCounter::GpuSyncTicks); + + m_maxSubmitCount = std::max(m_maxSubmitCount, currSubmitCount - m_prevSubmitCount); + m_maxSyncCount = std::max(m_maxSyncCount, currSyncCount - m_prevSyncCount); + m_maxSyncTicks = std::max(m_maxSyncTicks, currSyncTicks - m_prevSyncTicks); + + m_prevSubmitCount = currSubmitCount; + m_prevSyncCount = currSyncCount; + m_prevSyncTicks = currSyncTicks; + + auto elapsed = std::chrono::duration_cast(time - m_lastUpdate); + + if (elapsed.count() >= UpdateInterval) { + m_submitString = str::format(m_maxSubmitCount); + + uint64_t syncTicks = m_maxSyncTicks / 100; + + m_syncString = m_maxSyncCount + ? str::format(m_maxSyncCount, " (", (syncTicks / 10), ".", (syncTicks % 10), " ms)") + : str::format(m_maxSyncCount); + + m_maxSubmitCount = 0; + m_maxSyncCount = 0; + m_maxSyncTicks = 0; + + m_lastUpdate = time; + } + } + + + HudPos HudSubmissionStatsItem::render( + HudRenderer& renderer, + HudPos position) { + position.y += 16.0f; + + renderer.drawText(16.0f, + { position.x, position.y }, + { 1.0f, 0.5f, 0.25f, 1.0f }, + "Queue submissions:"); + + renderer.drawText(16.0f, + { position.x + 228.0f, position.y }, + { 1.0f, 1.0f, 1.0f, 1.0f }, + m_submitString); + + position.y += 20.0f; + renderer.drawText(16.0f, + { position.x, position.y }, + { 1.0f, 0.5f, 0.25f, 1.0f }, + "Queue syncs:"); + + renderer.drawText(16.0f, + { position.x + 228.0f, position.y }, + { 1.0f, 1.0f, 1.0f, 1.0f }, + m_syncString); + + position.y += 8.0f; + return position; + } + + + HudDrawCallStatsItem::HudDrawCallStatsItem(const Rc& device) + : m_device(device) { + + } + + + HudDrawCallStatsItem::~HudDrawCallStatsItem() { + + } + + + void HudDrawCallStatsItem::update(dxvk::high_resolution_clock::time_point time) { + auto elapsed = std::chrono::duration_cast(time - m_lastUpdate); + + DxvkStatCounters counters = m_device->getStatCounters(); + auto diffCounters = counters.diff(m_prevCounters); + + if (elapsed.count() >= UpdateInterval) { + m_gpCount = diffCounters.getCtr(DxvkStatCounter::CmdDrawCalls); + m_cpCount = diffCounters.getCtr(DxvkStatCounter::CmdDispatchCalls); + m_rpCount = diffCounters.getCtr(DxvkStatCounter::CmdRenderPassCount); + m_pbCount = diffCounters.getCtr(DxvkStatCounter::CmdBarrierCount); + + m_lastUpdate = time; + } + + m_prevCounters = counters; + } + + + HudPos HudDrawCallStatsItem::render( + HudRenderer& renderer, + HudPos position) { + position.y += 16.0f; + renderer.drawText(16.0f, + { position.x, position.y }, + { 0.25f, 0.5f, 1.0f, 1.0f }, + "Draw calls:"); + + renderer.drawText(16.0f, + { position.x + 192.0f, position.y }, + { 1.0f, 1.0f, 1.0f, 1.0f }, + str::format(m_gpCount)); + + position.y += 20.0f; + renderer.drawText(16.0f, + { position.x, position.y }, + { 0.25f, 0.5f, 1.0f, 1.0f }, + "Dispatch calls:"); + + renderer.drawText(16.0f, + { position.x + 192.0f, position.y }, + { 1.0f, 1.0f, 1.0f, 1.0f }, + str::format(m_cpCount)); + + position.y += 20.0f; + renderer.drawText(16.0f, + { position.x, position.y }, + { 0.25f, 0.5f, 1.0f, 1.0f }, + "Render passes:"); + + renderer.drawText(16.0f, + { position.x + 192.0f, position.y }, + { 1.0f, 1.0f, 1.0f, 1.0f }, + str::format(m_rpCount)); + + position.y += 20.0f; + renderer.drawText(16.0f, + { position.x, position.y }, + { 0.25f, 0.5f, 1.0f, 1.0f }, + "Barriers:"); + + renderer.drawText(16.0f, + { position.x + 192.0f, position.y }, + { 1.0f, 1.0f, 1.0f, 1.0f }, + str::format(m_pbCount)); + + position.y += 8.0f; + return position; + } + + + HudPipelineStatsItem::HudPipelineStatsItem(const Rc& device) + : m_device(device) { + + } + + + HudPipelineStatsItem::~HudPipelineStatsItem() { + + } + + + void HudPipelineStatsItem::update(dxvk::high_resolution_clock::time_point time) { + DxvkStatCounters counters = m_device->getStatCounters(); + + m_graphicsPipelines = counters.getCtr(DxvkStatCounter::PipeCountGraphics); + m_computePipelines = counters.getCtr(DxvkStatCounter::PipeCountCompute); + } + + + HudPos HudPipelineStatsItem::render( + HudRenderer& renderer, + HudPos position) { + position.y += 16.0f; + renderer.drawText(16.0f, + { position.x, position.y }, + { 1.0f, 0.25f, 1.0f, 1.0f }, + "Graphics pipelines:"); + + renderer.drawText(16.0f, + { position.x + 240.0f, position.y }, + { 1.0f, 1.0f, 1.0f, 1.0f }, + str::format(m_graphicsPipelines)); + + position.y += 20.0f; + renderer.drawText(16.0f, + { position.x, position.y }, + { 1.0f, 0.25f, 1.0f, 1.0f }, + "Compute pipelines:"); + + renderer.drawText(16.0f, + { position.x + 240.0f, position.y }, + { 1.0f, 1.0f, 1.0f, 1.0f }, + str::format(m_computePipelines)); + + position.y += 8.0f; + return position; + } + + + HudMemoryStatsItem::HudMemoryStatsItem(const Rc& device) + : m_device(device), m_memory(device->adapter()->memoryProperties()) { + + } + + + HudMemoryStatsItem::~HudMemoryStatsItem() { + + } + + + void HudMemoryStatsItem::update(dxvk::high_resolution_clock::time_point time) { + for (uint32_t i = 0; i < m_memory.memoryHeapCount; i++) + m_heaps[i] = m_device->getMemoryStats(i); + } + + + HudPos HudMemoryStatsItem::render( + HudRenderer& renderer, + HudPos position) { + for (uint32_t i = 0; i < m_memory.memoryHeapCount; i++) { + bool isDeviceLocal = m_memory.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT; + + uint64_t memUsedMib = m_heaps[i].memoryUsed >> 20; + uint64_t memAllocatedMib = m_heaps[i].memoryAllocated >> 20; + uint64_t percentage = (100 * m_heaps[i].memoryAllocated) / m_memory.memoryHeaps[i].size; + + std::string label = str::format(isDeviceLocal ? "Vidmem" : "Sysmem", " heap ", i, ": "); + std::string text = str::format(std::setfill(' '), std::setw(5), memAllocatedMib, " MB (", percentage, "%) ", + std::setw(5 + (percentage < 10 ? 1 : 0) + (percentage < 100 ? 1 : 0)), memUsedMib, " MB used"); + + position.y += 16.0f; + renderer.drawText(16.0f, + { position.x, position.y }, + { 1.0f, 1.0f, 0.25f, 1.0f }, + label); + + renderer.drawText(16.0f, + { position.x + 168.0f, position.y }, + { 1.0f, 1.0f, 1.0f, 1.0f }, + text); + position.y += 4.0f; + } + + position.y += 4.0f; + return position; + } + + + HudCsThreadItem::HudCsThreadItem(const Rc& device) + : m_device(device) { + + } + + + HudCsThreadItem::~HudCsThreadItem() { + + } + + + void HudCsThreadItem::update(dxvk::high_resolution_clock::time_point time) { + uint64_t ticks = std::chrono::duration_cast(time - m_lastUpdate).count(); + + // Capture the maximum here since it's more useful to + // identify stutters than using any sort of average + DxvkStatCounters counters = m_device->getStatCounters(); + uint64_t currCsSyncCount = counters.getCtr(DxvkStatCounter::CsSyncCount); + uint64_t currCsSyncTicks = counters.getCtr(DxvkStatCounter::CsSyncTicks); + + m_maxCsSyncCount = std::max(m_maxCsSyncCount, currCsSyncCount - m_prevCsSyncCount); + m_maxCsSyncTicks = std::max(m_maxCsSyncTicks, currCsSyncTicks - m_prevCsSyncTicks); + + m_prevCsSyncCount = currCsSyncCount; + m_prevCsSyncTicks = currCsSyncTicks; + + m_updateCount++; + + if (ticks >= UpdateInterval) { + uint64_t currCsChunks = counters.getCtr(DxvkStatCounter::CsChunkCount); + uint64_t diffCsChunks = (currCsChunks - m_prevCsChunks) / m_updateCount; + m_prevCsChunks = currCsChunks; + + uint64_t syncTicks = m_maxCsSyncTicks / 100; + + m_csChunkString = str::format(diffCsChunks); + m_csSyncString = m_maxCsSyncCount + ? str::format(m_maxCsSyncCount, " (", (syncTicks / 10), ".", (syncTicks % 10), " ms)") + : str::format(m_maxCsSyncCount); + + m_maxCsSyncCount = 0; + m_maxCsSyncTicks = 0; + + m_updateCount = 0; + m_lastUpdate = time; + } + } + + + HudPos HudCsThreadItem::render( + HudRenderer& renderer, + HudPos position) { + position.y += 16.0f; + renderer.drawText(16.0f, + { position.x, position.y }, + { 0.25f, 1.0f, 0.25f, 1.0f }, + "CS chunks:"); + + renderer.drawText(16.0f, + { position.x + 132.0f, position.y }, + { 1.0f, 1.0f, 1.0f, 1.0f }, + m_csChunkString); + + position.y += 20.0f; + renderer.drawText(16.0f, + { position.x, position.y }, + { 0.25f, 1.0f, 0.25f, 1.0f }, + "CS syncs:"); + + renderer.drawText(16.0f, + { position.x + 132.0f, position.y }, + { 1.0f, 1.0f, 1.0f, 1.0f }, + m_csSyncString); + + position.y += 8.0f; + return position; + } + + + HudGpuLoadItem::HudGpuLoadItem(const Rc& device) + : m_device(device) { + + } + + + HudGpuLoadItem::~HudGpuLoadItem() { + + } + + + void HudGpuLoadItem::update(dxvk::high_resolution_clock::time_point time) { + uint64_t ticks = std::chrono::duration_cast(time - m_lastUpdate).count(); + + if (ticks >= UpdateInterval) { + DxvkStatCounters counters = m_device->getStatCounters(); + uint64_t currGpuIdleTicks = counters.getCtr(DxvkStatCounter::GpuIdleTicks); + + m_diffGpuIdleTicks = currGpuIdleTicks - m_prevGpuIdleTicks; + m_prevGpuIdleTicks = currGpuIdleTicks; + + uint64_t busyTicks = ticks > m_diffGpuIdleTicks + ? uint64_t(ticks - m_diffGpuIdleTicks) + : uint64_t(0); + + m_gpuLoadString = str::format((100 * busyTicks) / ticks, "%"); + m_lastUpdate = time; + } + } + + + HudPos HudGpuLoadItem::render( + HudRenderer& renderer, + HudPos position) { + position.y += 16.0f; + + renderer.drawText(16.0f, + { position.x, position.y }, + { 0.25f, 0.5f, 0.25f, 1.0f }, + "GPU:"); + + renderer.drawText(16.0f, + { position.x + 60.0f, position.y }, + { 1.0f, 1.0f, 1.0f, 1.0f }, + m_gpuLoadString); + + position.y += 8.0f; + return position; + } + + + HudCompilerActivityItem::HudCompilerActivityItem(const Rc& device) + : m_device(device) { + + } + + + HudCompilerActivityItem::~HudCompilerActivityItem() { + + } + + + void HudCompilerActivityItem::update(dxvk::high_resolution_clock::time_point time) { + DxvkStatCounters counters = m_device->getStatCounters(); + bool doShow = counters.getCtr(DxvkStatCounter::PipeCompilerBusy); + + if (!doShow) { + auto elapsed = std::chrono::duration_cast(time - m_timeShown); + doShow = elapsed.count() <= MinShowDuration; + } + + if (doShow && !m_show) + m_timeShown = time; + + m_show = doShow; + } + + + HudPos HudCompilerActivityItem::render( + HudRenderer& renderer, + HudPos position) { + if (m_show) { + renderer.drawText(16.0f, + { position.x, renderer.surfaceSize().height / renderer.scale() - 20.0f }, + { 1.0f, 1.0f, 1.0f, 1.0f }, + "Compiling shaders..."); + } + + return position; + } + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/hud/dxvk_hud_item.h b/utils/dxvk-1.10.3/src/dxvk/hud/dxvk_hud_item.h new file mode 100644 index 00000000000..275461c6df0 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/hud/dxvk_hud_item.h @@ -0,0 +1,464 @@ +#pragma once + +#include +#include +#include +#include + +#include "../../util/util_time.h" + +#include "dxvk_hud_renderer.h" + +namespace dxvk::hud { + + /** + * \brief HUD item + * + * A single named item in the HUD that + * can be enabled by the user. + */ + class HudItem : public RcObject { + + public: + + virtual ~HudItem(); + + /** + * \brief Updates the HUD item + * \param [in] time Current time + */ + virtual void update( + dxvk::high_resolution_clock::time_point time); + + /** + * \brief Renders the HUD + * + * \param [in] renderer HUD renderer + * \param [in] position Base offset + * \returns Base offset for next item + */ + virtual HudPos render( + HudRenderer& renderer, + HudPos position) = 0; + + }; + + + /** + * \brief HUD item set + * + * Manages HUD items. + */ + class HudItemSet { + + public: + + HudItemSet(const Rc& device); + + ~HudItemSet(); + + /** + * \brief Updates the HUD + * Updates all enabled HUD items. + */ + void update(); + + /** + * \brief Renders the HUD + * + * \param [in] renderer HUD renderer + * \returns Base offset for next item + */ + void render( + HudRenderer& renderer); + + /** + * \brief Creates a HUD item if enabled + * + * \tparam T The HUD item type + * \param [in] name HUD item name + * \param [in] at Position at which to insert the item + * \param [in] args Constructor arguments + */ + template + void add(const char* name, int32_t at, Args... args) { + bool enable = m_enableFull; + + if (!enable) { + auto entry = m_enabled.find(name); + enable = entry != m_enabled.end(); + } + + if (at < 0 || at > int32_t(m_items.size())) + at = m_items.size(); + + if (enable) { + m_items.insert(m_items.begin() + at, + new T(std::forward(args)...)); + } + } + + template + T getOption(const char *option, T fallback) { + auto entry = m_options.find(option); + if (entry == m_options.end()) + return fallback; + + T value = fallback; + parseOption(entry->second, value); + return value; + } + + private: + + bool m_enableFull = false; + std::unordered_set m_enabled; + std::unordered_map m_options; + std::vector> m_items; + + static void parseOption(const std::string& str, float& value); + + }; + + + /** + * \brief HUD item to display DXVK version + */ + class HudVersionItem : public HudItem { + + public: + + HudPos render( + HudRenderer& renderer, + HudPos position); + + }; + + + /** + * \brief HUD item to display the client API + */ + class HudClientApiItem : public HudItem { + + public: + + HudClientApiItem(std::string api); + + ~HudClientApiItem(); + + HudPos render( + HudRenderer& renderer, + HudPos position); + + private: + + std::string m_api; + + }; + + + /** + * \brief HUD item to display device info + */ + class HudDeviceInfoItem : public HudItem { + + public: + + HudDeviceInfoItem(const Rc& device); + + ~HudDeviceInfoItem(); + + HudPos render( + HudRenderer& renderer, + HudPos position); + + private: + + std::string m_deviceName; + std::string m_driverVer; + std::string m_vulkanVer; + + }; + + + /** + * \brief HUD item to display the frame rate + */ + class HudFpsItem : public HudItem { + constexpr static int64_t UpdateInterval = 500'000; + public: + + HudFpsItem(); + + ~HudFpsItem(); + + void update(dxvk::high_resolution_clock::time_point time); + + HudPos render( + HudRenderer& renderer, + HudPos position); + + private: + + uint32_t m_frameCount = 0; + dxvk::high_resolution_clock::time_point m_lastUpdate + = dxvk::high_resolution_clock::now(); + + std::string m_frameRate; + + }; + + + /** + * \brief HUD item to display the frame rate + */ + class HudFrameTimeItem : public HudItem { + constexpr static size_t NumDataPoints = 304; + public: + + HudFrameTimeItem(); + + ~HudFrameTimeItem(); + + void update(dxvk::high_resolution_clock::time_point time); + + HudPos render( + HudRenderer& renderer, + HudPos position); + + private: + + dxvk::high_resolution_clock::time_point m_lastUpdate + = dxvk::high_resolution_clock::now(); + + std::array m_dataPoints = {}; + uint32_t m_dataPointId = 0; + + }; + + + /** + * \brief HUD item to display queue statistics + */ + class HudSubmissionStatsItem : public HudItem { + constexpr static int64_t UpdateInterval = 500'000; + public: + + HudSubmissionStatsItem(const Rc& device); + + ~HudSubmissionStatsItem(); + + void update(dxvk::high_resolution_clock::time_point time); + + HudPos render( + HudRenderer& renderer, + HudPos position); + + private: + + Rc m_device; + + uint64_t m_prevSubmitCount = 0; + uint64_t m_prevSyncCount = 0; + uint64_t m_prevSyncTicks = 0; + + uint64_t m_maxSubmitCount = 0; + uint64_t m_maxSyncCount = 0; + uint64_t m_maxSyncTicks = 0; + + std::string m_submitString; + std::string m_syncString; + + dxvk::high_resolution_clock::time_point m_lastUpdate + = dxvk::high_resolution_clock::now(); + + }; + + + /** + * \brief HUD item to display draw call counts + */ + class HudDrawCallStatsItem : public HudItem { + constexpr static int64_t UpdateInterval = 500'000; + public: + + HudDrawCallStatsItem(const Rc& device); + + ~HudDrawCallStatsItem(); + + void update(dxvk::high_resolution_clock::time_point time); + + HudPos render( + HudRenderer& renderer, + HudPos position); + + private: + + Rc m_device; + + DxvkStatCounters m_prevCounters; + + uint64_t m_gpCount = 0; + uint64_t m_cpCount = 0; + uint64_t m_rpCount = 0; + uint64_t m_pbCount = 0; + + dxvk::high_resolution_clock::time_point m_lastUpdate + = dxvk::high_resolution_clock::now(); + + }; + + + /** + * \brief HUD item to display pipeline counts + */ + class HudPipelineStatsItem : public HudItem { + + public: + + HudPipelineStatsItem(const Rc& device); + + ~HudPipelineStatsItem(); + + void update(dxvk::high_resolution_clock::time_point time); + + HudPos render( + HudRenderer& renderer, + HudPos position); + + private: + + Rc m_device; + + uint64_t m_graphicsPipelines = 0; + uint64_t m_computePipelines = 0; + + }; + + + /** + * \brief HUD item to display memory usage + */ + class HudMemoryStatsItem : public HudItem { + + public: + + HudMemoryStatsItem(const Rc& device); + + ~HudMemoryStatsItem(); + + void update(dxvk::high_resolution_clock::time_point time); + + HudPos render( + HudRenderer& renderer, + HudPos position); + + private: + + Rc m_device; + VkPhysicalDeviceMemoryProperties m_memory; + DxvkMemoryStats m_heaps[VK_MAX_MEMORY_HEAPS]; + + }; + + + /** + * \brief HUD item to display CS thread statistics + */ + class HudCsThreadItem : public HudItem { + constexpr static int64_t UpdateInterval = 500'000; + public: + + HudCsThreadItem(const Rc& device); + + ~HudCsThreadItem(); + + void update(dxvk::high_resolution_clock::time_point time); + + HudPos render( + HudRenderer& renderer, + HudPos position); + + private: + + Rc m_device; + + uint64_t m_prevCsSyncCount = 0; + uint64_t m_prevCsSyncTicks = 0; + uint64_t m_prevCsChunks = 0; + + uint64_t m_maxCsSyncCount = 0; + uint64_t m_maxCsSyncTicks = 0; + + uint64_t m_updateCount = 0; + + std::string m_csSyncString; + std::string m_csChunkString; + + dxvk::high_resolution_clock::time_point m_lastUpdate + = dxvk::high_resolution_clock::now(); + + }; + + + /** + * \brief HUD item to display GPU load + */ + class HudGpuLoadItem : public HudItem { + constexpr static int64_t UpdateInterval = 500'000; + public: + + HudGpuLoadItem(const Rc& device); + + ~HudGpuLoadItem(); + + void update(dxvk::high_resolution_clock::time_point time); + + HudPos render( + HudRenderer& renderer, + HudPos position); + + private: + + Rc m_device; + + uint64_t m_prevGpuIdleTicks = 0; + uint64_t m_diffGpuIdleTicks = 0; + + std::string m_gpuLoadString; + + dxvk::high_resolution_clock::time_point m_lastUpdate + = dxvk::high_resolution_clock::now(); + + }; + + + /** + * \brief HUD item to display pipeline compiler activity + */ + class HudCompilerActivityItem : public HudItem { + constexpr static int64_t MinShowDuration = 1500; + public: + + HudCompilerActivityItem(const Rc& device); + + ~HudCompilerActivityItem(); + + void update(dxvk::high_resolution_clock::time_point time); + + HudPos render( + HudRenderer& renderer, + HudPos position); + + private: + + Rc m_device; + + bool m_show = false; + + dxvk::high_resolution_clock::time_point m_timeShown + = dxvk::high_resolution_clock::now(); + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/hud/dxvk_hud_renderer.cpp b/utils/dxvk-1.10.3/src/dxvk/hud/dxvk_hud_renderer.cpp new file mode 100644 index 00000000000..8635fd75af1 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/hud/dxvk_hud_renderer.cpp @@ -0,0 +1,347 @@ +#include "dxvk_hud_renderer.h" + +#include +#include + +#include +#include + +namespace dxvk::hud { + + HudRenderer::HudRenderer(const Rc& device) + : m_mode (Mode::RenderNone), + m_scale (1.0f), + m_surfaceSize { 0, 0 }, + m_device (device), + m_textShaders (createTextShaders()), + m_graphShaders (createGraphShaders()), + m_dataBuffer (createDataBuffer()), + m_dataView (createDataView()), + m_dataOffset (0ull), + m_fontBuffer (createFontBuffer()), + m_fontImage (createFontImage()), + m_fontView (createFontView()), + m_fontSampler (createFontSampler()) { + + } + + + HudRenderer::~HudRenderer() { + + } + + + void HudRenderer::beginFrame(const Rc& context, VkExtent2D surfaceSize, float scale) { + if (!m_initialized) + this->initFontTexture(context); + + m_mode = Mode::RenderNone; + m_scale = scale; + m_surfaceSize = surfaceSize; + m_context = context; + } + + + void HudRenderer::drawText( + float size, + HudPos pos, + HudColor color, + const std::string& text) { + if (text.empty()) + return; + + beginTextRendering(); + + // Copy string into string buffer, but extend it to cover a full cache + // line to avoid potential CPU performance issues with the upload. + std::string textCopy = text; + textCopy.resize(align(text.size(), CACHE_LINE_SIZE), ' '); + + VkDeviceSize offset = allocDataBuffer(textCopy.size()); + std::memcpy(m_dataBuffer->mapPtr(offset), textCopy.data(), textCopy.size()); + + // Fill in push constants for the next draw + HudTextPushConstants pushData; + pushData.color = color; + pushData.pos = pos; + pushData.offset = offset; + pushData.size = size; + pushData.scale.x = m_scale / std::max(float(m_surfaceSize.width), 1.0f); + pushData.scale.y = m_scale / std::max(float(m_surfaceSize.height), 1.0f); + + m_context->pushConstants(0, sizeof(pushData), &pushData); + + // Draw with orignal vertex count + m_context->draw(6 * text.size(), 1, 0, 0); + } + + + void HudRenderer::drawGraph( + HudPos pos, + HudPos size, + size_t pointCount, + const HudGraphPoint* pointData) { + beginGraphRendering(); + + VkDeviceSize dataSize = pointCount * sizeof(*pointData); + VkDeviceSize offset = allocDataBuffer(dataSize); + std::memcpy(m_dataBuffer->mapPtr(offset), pointData, dataSize); + + HudGraphPushConstants pushData; + pushData.offset = offset / sizeof(*pointData); + pushData.count = pointCount; + pushData.pos = pos; + pushData.size = size; + pushData.scale.x = m_scale / std::max(float(m_surfaceSize.width), 1.0f); + pushData.scale.y = m_scale / std::max(float(m_surfaceSize.height), 1.0f); + + m_context->pushConstants(0, sizeof(pushData), &pushData); + m_context->draw(4, 1, 0, 0); + } + + + void HudRenderer::beginTextRendering() { + if (m_mode != Mode::RenderText) { + m_mode = Mode::RenderText; + + m_context->bindShader(VK_SHADER_STAGE_VERTEX_BIT, m_textShaders.vert); + m_context->bindShader(VK_SHADER_STAGE_FRAGMENT_BIT, m_textShaders.frag); + + m_context->bindResourceBuffer (0, DxvkBufferSlice(m_fontBuffer)); + m_context->bindResourceView (1, nullptr, m_dataView); + m_context->bindResourceSampler(2, m_fontSampler); + m_context->bindResourceView (2, m_fontView, nullptr); + + static const DxvkInputAssemblyState iaState = { + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, + VK_FALSE, 0 }; + + m_context->setInputAssemblyState(iaState); + m_context->setInputLayout(0, nullptr, 0, nullptr); + } + } + + + void HudRenderer::beginGraphRendering() { + if (m_mode != Mode::RenderGraph) { + m_mode = Mode::RenderGraph; + + m_context->bindShader(VK_SHADER_STAGE_VERTEX_BIT, m_graphShaders.vert); + m_context->bindShader(VK_SHADER_STAGE_FRAGMENT_BIT, m_graphShaders.frag); + + m_context->bindResourceBuffer(0, DxvkBufferSlice(m_dataBuffer)); + + static const DxvkInputAssemblyState iaState = { + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, + VK_FALSE, 0 }; + + m_context->setInputAssemblyState(iaState); + m_context->setInputLayout(0, nullptr, 0, nullptr); + } + } + + + VkDeviceSize HudRenderer::allocDataBuffer(VkDeviceSize size) { + if (m_dataOffset + size > m_dataBuffer->info().size) { + m_context->invalidateBuffer(m_dataBuffer, m_dataBuffer->allocSlice()); + m_dataOffset = 0; + } + + VkDeviceSize offset = m_dataOffset; + m_dataOffset = align(offset + size, 64); + return offset; + } + + + HudRenderer::ShaderPair HudRenderer::createTextShaders() { + ShaderPair result; + + SpirvCodeBuffer vsCode(hud_text_vert); + SpirvCodeBuffer fsCode(hud_text_frag); + + const std::array vsResources = {{ + { 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_IMAGE_VIEW_TYPE_MAX_ENUM }, + { 1, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, VK_IMAGE_VIEW_TYPE_MAX_ENUM }, + }}; + + const std::array fsResources = {{ + { 2, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_IMAGE_VIEW_TYPE_2D }, + }}; + + DxvkShaderCreateInfo vsInfo; + vsInfo.stage = VK_SHADER_STAGE_VERTEX_BIT; + vsInfo.resourceSlotCount = vsResources.size(); + vsInfo.resourceSlots = vsResources.data(); + vsInfo.outputMask = 0x3; + vsInfo.pushConstSize = sizeof(HudTextPushConstants); + result.vert = new DxvkShader(vsInfo, std::move(vsCode)); + + DxvkShaderCreateInfo fsInfo; + fsInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT; + fsInfo.resourceSlotCount = fsResources.size(); + fsInfo.resourceSlots = fsResources.data(); + fsInfo.inputMask = 0x3; + fsInfo.outputMask = 0x1; + result.frag = new DxvkShader(fsInfo, std::move(fsCode)); + + return result; + } + + + HudRenderer::ShaderPair HudRenderer::createGraphShaders() { + ShaderPair result; + + SpirvCodeBuffer vsCode(hud_graph_vert); + SpirvCodeBuffer fsCode(hud_graph_frag); + + const std::array fsResources = {{ + { 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_IMAGE_VIEW_TYPE_MAX_ENUM }, + }}; + + DxvkShaderCreateInfo vsInfo; + vsInfo.stage = VK_SHADER_STAGE_VERTEX_BIT; + vsInfo.outputMask = 0x1; + vsInfo.pushConstSize = sizeof(HudGraphPushConstants); + result.vert = new DxvkShader(vsInfo, std::move(vsCode)); + + DxvkShaderCreateInfo fsInfo; + fsInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT; + fsInfo.resourceSlotCount = fsResources.size(); + fsInfo.resourceSlots = fsResources.data(); + fsInfo.inputMask = 0x1; + fsInfo.outputMask = 0x1; + fsInfo.pushConstSize = sizeof(HudGraphPushConstants); + result.frag = new DxvkShader(fsInfo, std::move(fsCode)); + + return result; + } + + + Rc HudRenderer::createDataBuffer() { + DxvkBufferCreateInfo info; + info.size = DataBufferSize; + info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT + | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT; + info.stages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT + | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + info.access = VK_ACCESS_SHADER_READ_BIT; + + return m_device->createBuffer(info, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | + VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + } + + + Rc HudRenderer::createDataView() { + DxvkBufferViewCreateInfo info; + info.format = VK_FORMAT_R8_UINT; + info.rangeOffset = 0; + info.rangeLength = m_dataBuffer->info().size; + + return m_device->createBufferView(m_dataBuffer, info); + } + + + Rc HudRenderer::createFontBuffer() { + DxvkBufferCreateInfo info; + info.size = sizeof(HudFontGpuData); + info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT + | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + info.stages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT + | VK_PIPELINE_STAGE_TRANSFER_BIT; + info.access = VK_ACCESS_SHADER_READ_BIT + | VK_ACCESS_TRANSFER_WRITE_BIT; + + return m_device->createBuffer(info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + } + + + Rc HudRenderer::createFontImage() { + DxvkImageCreateInfo info; + info.type = VK_IMAGE_TYPE_2D; + info.format = VK_FORMAT_R8_UNORM; + info.flags = 0; + info.sampleCount = VK_SAMPLE_COUNT_1_BIT; + info.extent = { g_hudFont.width, g_hudFont.height, 1 }; + info.numLayers = 1; + info.mipLevels = 1; + info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_SAMPLED_BIT; + info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT + | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + info.access = VK_ACCESS_TRANSFER_WRITE_BIT + | VK_ACCESS_SHADER_READ_BIT; + info.tiling = VK_IMAGE_TILING_OPTIMAL; + info.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + + return m_device->createImage(info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + } + + + Rc HudRenderer::createFontView() { + DxvkImageViewCreateInfo info; + info.type = VK_IMAGE_VIEW_TYPE_2D; + info.format = m_fontImage->info().format; + info.usage = VK_IMAGE_USAGE_SAMPLED_BIT; + info.aspect = VK_IMAGE_ASPECT_COLOR_BIT; + info.minLevel = 0; + info.numLevels = 1; + info.minLayer = 0; + info.numLayers = 1; + + return m_device->createImageView(m_fontImage, info); + } + + + Rc HudRenderer::createFontSampler() { + DxvkSamplerCreateInfo info; + info.magFilter = VK_FILTER_LINEAR; + info.minFilter = VK_FILTER_LINEAR; + info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; + info.mipmapLodBias = 0.0f; + info.mipmapLodMin = 0.0f; + info.mipmapLodMax = 0.0f; + info.useAnisotropy = VK_FALSE; + info.maxAnisotropy = 1.0f; + info.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + info.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + info.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + info.compareToDepth = VK_FALSE; + info.compareOp = VK_COMPARE_OP_NEVER; + info.borderColor = VkClearColorValue(); + info.usePixelCoord = VK_TRUE; + info.nonSeamless = VK_FALSE; + + return m_device->createSampler(info); + } + + + void HudRenderer::initFontTexture( + const Rc& context) { + HudFontGpuData gpuData = { }; + gpuData.size = float(g_hudFont.size); + gpuData.advance = float(g_hudFont.advance); + + for (uint32_t i = 0; i < g_hudFont.charCount; i++) { + auto src = &g_hudFont.glyphs[i]; + auto dst = &gpuData.glyphs[src->codePoint]; + + dst->x = src->x; + dst->y = src->y; + dst->w = src->w; + dst->h = src->h; + dst->originX = src->originX; + dst->originY = src->originY; + } + + context->uploadBuffer(m_fontBuffer, &gpuData); + + context->uploadImage(m_fontImage, + VkImageSubresourceLayers { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }, + g_hudFont.texture, g_hudFont.width, g_hudFont.width * g_hudFont.height); + + m_initialized = true; + } + +} diff --git a/utils/dxvk-1.10.3/src/dxvk/hud/dxvk_hud_renderer.h b/utils/dxvk-1.10.3/src/dxvk/hud/dxvk_hud_renderer.h new file mode 100644 index 00000000000..3986fba8130 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/hud/dxvk_hud_renderer.h @@ -0,0 +1,187 @@ +#pragma once + +#include "../dxvk_device.h" + +#include "dxvk_hud_font.h" + +namespace dxvk::hud { + + /** + * \brief HUD coordinates + * + * Coordinates relative to the top-left + * corner of the swap image, in pixels. + */ + struct HudPos { + float x; + float y; + }; + + /** + * \brief Color + * + * SRGB color with alpha channel. The text + * will use this color for the most part. + */ + struct HudColor { + float r; + float g; + float b; + float a; + }; + + /** + * \brief Normalized color + * + * SRGB color with alpha channel. + */ + struct HudNormColor { + uint8_t a; + uint8_t b; + uint8_t g; + uint8_t r; + }; + + /** + * \brief Graph point with color + */ + struct HudGraphPoint { + float value; + HudNormColor color; + }; + + /** + * \brief HUD push constant data + */ + struct HudTextPushConstants { + HudColor color; + HudPos pos; + uint32_t offset; + float size; + HudPos scale; + }; + + struct HudGraphPushConstants { + uint32_t offset; + uint32_t count; + HudPos pos; + HudPos size; + HudPos scale; + }; + + /** + * \brief Glyph data + */ + struct HudGlyphGpuData { + int16_t x; + int16_t y; + int16_t w; + int16_t h; + int16_t originX; + int16_t originY; + }; + + struct HudFontGpuData { + float size; + float advance; + uint32_t padding[2]; + HudGlyphGpuData glyphs[256]; + }; + + /** + * \brief Text renderer for the HUD + * + * Can be used by the presentation backend to + * display performance and driver information. + */ + class HudRenderer { + constexpr static VkDeviceSize DataBufferSize = 16384; + public: + + HudRenderer( + const Rc& device); + + ~HudRenderer(); + + void beginFrame( + const Rc& context, + VkExtent2D surfaceSize, + float scale); + + void drawText( + float size, + HudPos pos, + HudColor color, + const std::string& text); + + void drawGraph( + HudPos pos, + HudPos size, + size_t pointCount, + const HudGraphPoint* pointData); + + VkExtent2D surfaceSize() const { + return m_surfaceSize; + } + + float scale() const { + return m_scale; + } + + private: + + enum class Mode { + RenderNone, + RenderText, + RenderGraph, + }; + + struct ShaderPair { + Rc vert; + Rc frag; + }; + + Mode m_mode; + float m_scale; + VkExtent2D m_surfaceSize; + + Rc m_device; + Rc m_context; + + ShaderPair m_textShaders; + ShaderPair m_graphShaders; + + Rc m_dataBuffer; + Rc m_dataView; + VkDeviceSize m_dataOffset; + + Rc m_fontBuffer; + Rc m_fontImage; + Rc m_fontView; + Rc m_fontSampler; + + bool m_initialized = false; + + void beginTextRendering(); + + void beginGraphRendering(); + + VkDeviceSize allocDataBuffer(VkDeviceSize size); + + ShaderPair createTextShaders(); + ShaderPair createGraphShaders(); + + Rc createDataBuffer(); + Rc createDataView(); + + Rc createFontBuffer(); + Rc createFontImage(); + Rc createFontView(); + Rc createFontSampler(); + + void initFontTexture( + const Rc& context); + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/hud/shaders/hud_graph_frag.frag b/utils/dxvk-1.10.3/src/dxvk/hud/shaders/hud_graph_frag.frag new file mode 100644 index 00000000000..b45aa43efcd --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/hud/shaders/hud_graph_frag.frag @@ -0,0 +1,61 @@ +#version 450 + +layout(constant_id = 1225) const bool srgbSwapchain = false; + +layout(location = 0) in vec2 v_coord; +layout(location = 0) out vec4 o_color; + +struct line_point_t { + float value; + uint color; +}; + +layout(binding = 0, std430) +readonly buffer line_data_t { + line_point_t points[]; +}; + +layout(push_constant) +uniform push_data_t { + uint offset; + uint count; + vec2 pos; + vec2 size; + vec2 scale; +}; + +vec3 linearToSrgb(vec3 color) { + bvec3 isLo = lessThanEqual(color, vec3(0.0031308f)); + + vec3 loPart = color * 12.92f; + vec3 hiPart = pow(color, vec3(5.0f / 12.0f)) * 1.055f - 0.055f; + return mix(hiPart, loPart, isLo); +} + +void main() { + float cx = v_coord.x * float(count); + float fx = fract(cx); + + // We need to roll our own linear interpolation here + uint p0_idx = min(uint(floor(cx)), count - 1) + offset; + uint p1_idx = min(uint(ceil(cx)), count - 1) + offset; + + line_point_t p0 = points[p0_idx]; + line_point_t p1 = points[p1_idx]; + + float value = mix(p0.value, p1.value, fx); + float alpha = value + v_coord.y - 1.0f; + alpha = min(alpha / dFdy(v_coord.y), 1.0f); + + if (alpha <= 0.0f) + discard; + + o_color = mix( + unpackUnorm4x8(p0.color), + unpackUnorm4x8(p1.color), fx); + + if (!srgbSwapchain) + o_color.rgb = linearToSrgb(o_color.rgb); + + o_color *= alpha; +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/hud/shaders/hud_graph_vert.vert b/utils/dxvk-1.10.3/src/dxvk/hud/shaders/hud_graph_vert.vert new file mode 100644 index 00000000000..884dc3187f2 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/hud/shaders/hud_graph_vert.vert @@ -0,0 +1,23 @@ +#version 450 + +layout(location = 0) out vec2 o_coord; + +layout(push_constant) +uniform push_data_t { + uint offset; + uint count; + vec2 pos; + vec2 size; + vec2 scale; +}; + +void main() { + vec2 coord = vec2( + float(gl_VertexIndex & 1), + float(gl_VertexIndex >> 1)); + o_coord = coord; + + vec2 pixel_pos = pos + size * coord; + vec2 scaled_pos = 2.0f * scale * pixel_pos - 1.0f; + gl_Position = vec4(scaled_pos, 0.0f, 1.0f); +} diff --git a/utils/dxvk-1.10.3/src/dxvk/hud/shaders/hud_text_frag.frag b/utils/dxvk-1.10.3/src/dxvk/hud/shaders/hud_text_frag.frag new file mode 100644 index 00000000000..56a2823ceb9 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/hud/shaders/hud_text_frag.frag @@ -0,0 +1,39 @@ +#version 450 + +layout(constant_id = 1225) const bool srgbSwapchain = false; + +layout(binding = 2) uniform sampler2D s_font; + +layout(location = 0) in vec2 v_texcoord; +layout(location = 1) in vec4 v_color; + +layout(location = 0) out vec4 o_color; + +vec3 linearToSrgb(vec3 color) { + bvec3 isLo = lessThanEqual(color, vec3(0.0031308f)); + + vec3 loPart = color * 12.92f; + vec3 hiPart = pow(color, vec3(5.0f / 12.0f)) * 1.055f - 0.055f; + return mix(hiPart, loPart, isLo); +} + +float sampleAlpha(float alpha_bias, float dist_range) { + float value = textureLod(s_font, v_texcoord, 0).r + alpha_bias - 0.5f; + float dist = value * dot(vec2(dist_range, dist_range), 1.0f / fwidth(v_texcoord.xy)); + return clamp(dist + 0.5f, 0.0f, 1.0f); +} + +void main() { + float r_alpha_center = sampleAlpha(0.0f, 5.0f); + float r_alpha_shadow = sampleAlpha(0.3f, 5.0f); + + vec3 r_center = v_color.rgb; + vec3 r_shadow = vec3(0.0f, 0.0f, 0.0f); + + o_color.rgb = mix(r_shadow, r_center, r_alpha_center); + o_color.a = r_alpha_shadow * v_color.a; + o_color.rgb *= o_color.a; + + if (!srgbSwapchain) + o_color.rgb = linearToSrgb(o_color.rgb); +} diff --git a/utils/dxvk-1.10.3/src/dxvk/hud/shaders/hud_text_vert.vert b/utils/dxvk-1.10.3/src/dxvk/hud/shaders/hud_text_vert.vert new file mode 100644 index 00000000000..c0b0f17538b --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/hud/shaders/hud_text_vert.vert @@ -0,0 +1,75 @@ +#version 450 + +struct font_info_t { + float size; + float advance; + uvec2 padding; +}; + +struct glyph_info_t { + uint packed_xy; + uint packed_wh; + uint packed_origin; +}; + +layout(binding = 0, std430) +readonly buffer font_buffer_t { + font_info_t font_data; + glyph_info_t glyph_data[]; +}; + +layout(binding = 1) uniform usamplerBuffer text_buffer; + +layout(push_constant) +uniform push_data_t { + vec4 text_color; + vec2 text_pos; + uint text_offset; + float text_size; + vec2 hud_scale; +}; + +layout(location = 0) out vec2 o_texcoord; +layout(location = 1) out vec4 o_color; + +const uvec2 coord_mask = uvec2(0x2a, 0x1c); + +vec2 unpack_u16(uint v) { + // Inputs may be signed + int hi = int(v); + int lo = int(v << 16); + return vec2(float(lo >> 16), float(hi >> 16)); +} + +void main() { + o_color = text_color; + + // Compute character index and vertex index for the current + // character. We'll render two triangles per character. + uint chr_idx = gl_VertexIndex / 6; + uint vtx_idx = gl_VertexIndex - 6 * chr_idx; + + // Load glyph info based on vertex index + uint glyph_idx = texelFetch(text_buffer, int(text_offset + chr_idx)).x; + glyph_info_t glyph_info = glyph_data[glyph_idx]; + + // Compute texture coordinate from glyph data + vec2 coord = vec2((coord_mask >> vtx_idx) & 0x1); + + vec2 tex_xy = unpack_u16(glyph_info.packed_xy); + vec2 tex_wh = unpack_u16(glyph_info.packed_wh); + + o_texcoord = tex_xy + coord * tex_wh; + + // Compute vertex position. We can easily do this here since our + // font is a monospace font, otherwise we'd need to preprocess + // the strings to render in a compute shader. + float size_factor = text_size / font_data.size; + + vec2 local_pos = tex_wh * coord - unpack_u16(glyph_info.packed_origin) + + vec2(font_data.advance * float(chr_idx), 0.0f); + vec2 pixel_pos = text_pos + size_factor * local_pos; + vec2 scaled_pos = 2.0f * hud_scale * pixel_pos - 1.0f; + + gl_Position = vec4(scaled_pos, 0.0f, 1.0f); +} diff --git a/utils/dxvk-1.10.3/src/dxvk/meson.build b/utils/dxvk-1.10.3/src/dxvk/meson.build new file mode 100644 index 00000000000..e0e3e8f26db --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/meson.build @@ -0,0 +1,130 @@ +dxvk_shaders = files([ + 'shaders/dxvk_blit_frag_1d.frag', + 'shaders/dxvk_blit_frag_2d.frag', + 'shaders/dxvk_blit_frag_3d.frag', + + 'shaders/dxvk_clear_buffer_u.comp', + 'shaders/dxvk_clear_buffer_f.comp', + 'shaders/dxvk_clear_image1d_u.comp', + 'shaders/dxvk_clear_image1d_f.comp', + 'shaders/dxvk_clear_image1darr_u.comp', + 'shaders/dxvk_clear_image1darr_f.comp', + 'shaders/dxvk_clear_image2d_u.comp', + 'shaders/dxvk_clear_image2d_f.comp', + 'shaders/dxvk_clear_image2darr_u.comp', + 'shaders/dxvk_clear_image2darr_f.comp', + 'shaders/dxvk_clear_image3d_u.comp', + 'shaders/dxvk_clear_image3d_f.comp', + + 'shaders/dxvk_copy_buffer_image.comp', + 'shaders/dxvk_copy_color_1d.frag', + 'shaders/dxvk_copy_color_2d.frag', + 'shaders/dxvk_copy_color_ms.frag', + 'shaders/dxvk_copy_depth_1d.frag', + 'shaders/dxvk_copy_depth_2d.frag', + 'shaders/dxvk_copy_depth_ms.frag', + 'shaders/dxvk_copy_depth_stencil_1d.frag', + 'shaders/dxvk_copy_depth_stencil_2d.frag', + 'shaders/dxvk_copy_depth_stencil_ms.frag', + + 'shaders/dxvk_fullscreen_geom.geom', + 'shaders/dxvk_fullscreen_vert.vert', + 'shaders/dxvk_fullscreen_layer_vert.vert', + + 'shaders/dxvk_pack_d24s8.comp', + 'shaders/dxvk_pack_d32s8.comp', + + 'shaders/dxvk_present_frag.frag', + 'shaders/dxvk_present_frag_blit.frag', + 'shaders/dxvk_present_frag_ms.frag', + 'shaders/dxvk_present_frag_ms_amd.frag', + 'shaders/dxvk_present_vert.vert', + + 'shaders/dxvk_resolve_frag_d.frag', + 'shaders/dxvk_resolve_frag_ds.frag', + 'shaders/dxvk_resolve_frag_f.frag', + 'shaders/dxvk_resolve_frag_f_amd.frag', + 'shaders/dxvk_resolve_frag_i.frag', + 'shaders/dxvk_resolve_frag_u.frag', + + 'shaders/dxvk_unpack_d24s8_as_d32s8.comp', + 'shaders/dxvk_unpack_d24s8.comp', + 'shaders/dxvk_unpack_d32s8.comp', + + 'hud/shaders/hud_graph_frag.frag', + 'hud/shaders/hud_graph_vert.vert', + + 'hud/shaders/hud_text_frag.frag', + 'hud/shaders/hud_text_vert.vert', +]) + +dxvk_src = files([ + 'dxvk_adapter.cpp', + 'dxvk_barrier.cpp', + 'dxvk_buffer.cpp', + 'dxvk_cmdlist.cpp', + 'dxvk_compute.cpp', + 'dxvk_context.cpp', + 'dxvk_cs.cpp', + 'dxvk_data.cpp', + 'dxvk_descriptor.cpp', + 'dxvk_device.cpp', + 'dxvk_device_filter.cpp', + 'dxvk_extensions.cpp', + 'dxvk_fence.cpp', + 'dxvk_format.cpp', + 'dxvk_framebuffer.cpp', + 'dxvk_gpu_event.cpp', + 'dxvk_gpu_query.cpp', + 'dxvk_graphics.cpp', + 'dxvk_image.cpp', + 'dxvk_instance.cpp', + 'dxvk_lifetime.cpp', + 'dxvk_memory.cpp', + 'dxvk_meta_blit.cpp', + 'dxvk_meta_clear.cpp', + 'dxvk_meta_copy.cpp', + 'dxvk_meta_mipgen.cpp', + 'dxvk_meta_pack.cpp', + 'dxvk_meta_resolve.cpp', + 'dxvk_openvr.cpp', + 'dxvk_openxr.cpp', + 'dxvk_options.cpp', + 'dxvk_pipecache.cpp', + 'dxvk_pipelayout.cpp', + 'dxvk_pipemanager.cpp', + 'dxvk_queue.cpp', + 'dxvk_renderpass.cpp', + 'dxvk_resource.cpp', + 'dxvk_sampler.cpp', + 'dxvk_shader.cpp', + 'dxvk_shader_key.cpp', + 'dxvk_signal.cpp', + 'dxvk_spec_const.cpp', + 'dxvk_staging.cpp', + 'dxvk_state_cache.cpp', + 'dxvk_stats.cpp', + 'dxvk_swapchain_blitter.cpp', + 'dxvk_unbound.cpp', + 'dxvk_util.cpp', + + 'platform/dxvk_win32_exts.cpp', + + 'hud/dxvk_hud.cpp', + 'hud/dxvk_hud_font.cpp', + 'hud/dxvk_hud_item.cpp', + 'hud/dxvk_hud_renderer.cpp', +]) + +thread_dep = dependency('threads') + +dxvk_lib = static_library('dxvk', dxvk_src, glsl_generator.process(dxvk_shaders), dxvk_version, + link_with : [ util_lib, spirv_lib ], + dependencies : [ thread_dep, vkcommon_dep ] + dxvk_extradep, + include_directories : [ dxvk_include_path ], +) + +dxvk_dep = declare_dependency( + link_with : [ dxvk_lib ], + include_directories : [ dxvk_include_path ], +) diff --git a/utils/dxvk-1.10.3/src/dxvk/platform/dxvk_win32_exts.cpp b/utils/dxvk-1.10.3/src/dxvk/platform/dxvk_win32_exts.cpp new file mode 100644 index 00000000000..25c81cc5aff --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/platform/dxvk_win32_exts.cpp @@ -0,0 +1,36 @@ +#include "../dxvk_platform_exts.h" + +namespace dxvk { + + DxvkPlatformExts DxvkPlatformExts::s_instance; + + std::string_view DxvkPlatformExts::getName() { + return "Win32 WSI"; + } + + + DxvkNameSet DxvkPlatformExts::getInstanceExtensions() { + DxvkNameSet names; + names.add(VK_KHR_WIN32_SURFACE_EXTENSION_NAME); + + return names; + } + + + DxvkNameSet DxvkPlatformExts::getDeviceExtensions( + uint32_t adapterId) { + return DxvkNameSet(); + } + + + void DxvkPlatformExts::initInstanceExtensions() { + + } + + + void DxvkPlatformExts::initDeviceExtensions( + const DxvkInstance* instance) { + + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_blit_frag_1d.frag b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_blit_frag_1d.frag new file mode 100644 index 00000000000..2311c57c5eb --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_blit_frag_1d.frag @@ -0,0 +1,19 @@ +#version 450 + +layout(set = 0, binding = 0) +uniform sampler1DArray s_texture; + +layout(location = 0) in vec2 i_pos; +layout(location = 0) out vec4 o_color; + +layout(push_constant) +uniform push_block { + vec3 p_src_coord0; + vec3 p_src_coord1; + uint p_layer_count; +}; + +void main() { + float coord = mix(p_src_coord0.x, p_src_coord1.x, i_pos.x); + o_color = texture(s_texture, vec2(coord, gl_Layer)); +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_blit_frag_2d.frag b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_blit_frag_2d.frag new file mode 100644 index 00000000000..b177c5ee3d0 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_blit_frag_2d.frag @@ -0,0 +1,19 @@ +#version 450 + +layout(set = 0, binding = 0) +uniform sampler2DArray s_texture; + +layout(location = 0) in vec2 i_pos; +layout(location = 0) out vec4 o_color; + +layout(push_constant) +uniform push_block { + vec3 p_src_coord0; + vec3 p_src_coord1; + uint p_layer_count; +}; + +void main() { + vec2 coord = mix(p_src_coord0.xy, p_src_coord1.xy, i_pos); + o_color = texture(s_texture, vec3(coord, gl_Layer)); +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_blit_frag_3d.frag b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_blit_frag_3d.frag new file mode 100644 index 00000000000..856855c62a5 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_blit_frag_3d.frag @@ -0,0 +1,20 @@ +#version 450 + +layout(set = 0, binding = 0) +uniform sampler3D s_texture; + +layout(location = 0) in vec2 i_pos; +layout(location = 0) out vec4 o_color; + +layout(push_constant) +uniform push_block { + vec3 p_src_coord0; + vec3 p_src_coord1; + uint p_layer_count; +}; + +void main() { + vec3 coord = mix(p_src_coord0, p_src_coord1, + vec3(i_pos, (float(gl_Layer) + 0.5f) / float(p_layer_count))); + o_color = texture(s_texture, coord); +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_buffer_f.comp b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_buffer_f.comp new file mode 100644 index 00000000000..d682cb40b21 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_buffer_f.comp @@ -0,0 +1,26 @@ +#version 450 + +layout( + local_size_x = 128, + local_size_y = 1, + local_size_z = 1) in; + +layout(binding = 0) +writeonly uniform imageBuffer dst; + +layout(push_constant) +uniform u_info_t { + vec4 clear_value; + ivec4 dst_offset; + ivec4 dst_extent; +} u_info; + +void main() { + int thread_id = int(gl_GlobalInvocationID.x); + + if (thread_id < u_info.dst_extent.x) { + imageStore(dst, + u_info.dst_offset.x + thread_id, + u_info.clear_value); + } +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_buffer_u.comp b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_buffer_u.comp new file mode 100644 index 00000000000..97c1d0b0424 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_buffer_u.comp @@ -0,0 +1,26 @@ +#version 450 + +layout( + local_size_x = 128, + local_size_y = 1, + local_size_z = 1) in; + +layout(binding = 0) +writeonly uniform uimageBuffer dst; + +layout(push_constant) +uniform u_info_t { + uvec4 clear_value; + ivec4 dst_offset; + ivec4 dst_extent; +} u_info; + +void main() { + int thread_id = int(gl_GlobalInvocationID.x); + + if (thread_id < u_info.dst_extent.x) { + imageStore(dst, + u_info.dst_offset.x + thread_id, + u_info.clear_value); + } +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_image1d_f.comp b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_image1d_f.comp new file mode 100644 index 00000000000..4170dd23410 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_image1d_f.comp @@ -0,0 +1,26 @@ +#version 450 + +layout( + local_size_x = 64, + local_size_y = 1, + local_size_z = 1) in; + +layout(binding = 0) +writeonly uniform image1D dst; + +layout(push_constant) +uniform u_info_t { + vec4 clear_value; + ivec4 dst_offset; + ivec4 dst_extent; +} u_info; + +void main() { + ivec3 thread_id = ivec3(gl_GlobalInvocationID); + + if (thread_id.x < u_info.dst_extent.x) { + imageStore(dst, + u_info.dst_offset.x + thread_id.x, + u_info.clear_value); + } +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_image1d_u.comp b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_image1d_u.comp new file mode 100644 index 00000000000..43b62833fc9 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_image1d_u.comp @@ -0,0 +1,26 @@ +#version 450 + +layout( + local_size_x = 64, + local_size_y = 1, + local_size_z = 1) in; + +layout(binding = 0) +writeonly uniform uimage1D dst; + +layout(push_constant) +uniform u_info_t { + uvec4 clear_value; + ivec4 dst_offset; + ivec4 dst_extent; +} u_info; + +void main() { + ivec3 thread_id = ivec3(gl_GlobalInvocationID); + + if (thread_id.x < u_info.dst_extent.x) { + imageStore(dst, + u_info.dst_offset.x + thread_id.x, + u_info.clear_value); + } +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_image1darr_f.comp b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_image1darr_f.comp new file mode 100644 index 00000000000..ae5749a238e --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_image1darr_f.comp @@ -0,0 +1,26 @@ +#version 450 + +layout( + local_size_x = 64, + local_size_y = 1, + local_size_z = 1) in; + +layout(binding = 0) +writeonly uniform image1DArray dst; + +layout(push_constant) +uniform u_info_t { + vec4 clear_value; + ivec4 dst_offset; + ivec4 dst_extent; +} u_info; + +void main() { + ivec3 thread_id = ivec3(gl_GlobalInvocationID); + + if (thread_id.x < u_info.dst_extent.x) { + imageStore(dst, + ivec2(u_info.dst_offset.x + thread_id.x, thread_id.y), + u_info.clear_value); + } +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_image1darr_u.comp b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_image1darr_u.comp new file mode 100644 index 00000000000..24dcdf8712a --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_image1darr_u.comp @@ -0,0 +1,26 @@ +#version 450 + +layout( + local_size_x = 64, + local_size_y = 1, + local_size_z = 1) in; + +layout(binding = 0) +writeonly uniform uimage1DArray dst; + +layout(push_constant) +uniform u_info_t { + uvec4 clear_value; + ivec4 dst_offset; + ivec4 dst_extent; +} u_info; + +void main() { + ivec3 thread_id = ivec3(gl_GlobalInvocationID); + + if (thread_id.x < u_info.dst_extent.x) { + imageStore(dst, + ivec2(u_info.dst_offset.x + thread_id.x, thread_id.y), + u_info.clear_value); + } +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_image2d_f.comp b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_image2d_f.comp new file mode 100644 index 00000000000..5a5e63f7dd0 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_image2d_f.comp @@ -0,0 +1,26 @@ +#version 450 + +layout( + local_size_x = 8, + local_size_y = 8, + local_size_z = 1) in; + +layout(binding = 0) +writeonly uniform image2D dst; + +layout(push_constant) +uniform u_info_t { + vec4 clear_value; + ivec4 dst_offset; + ivec4 dst_extent; +} u_info; + +void main() { + ivec3 thread_id = ivec3(gl_GlobalInvocationID); + + if (all(lessThan(thread_id.xy, u_info.dst_extent.xy))) { + imageStore(dst, + u_info.dst_offset.xy + thread_id.xy, + u_info.clear_value); + } +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_image2d_u.comp b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_image2d_u.comp new file mode 100644 index 00000000000..32eecabcd41 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_image2d_u.comp @@ -0,0 +1,26 @@ +#version 450 + +layout( + local_size_x = 8, + local_size_y = 8, + local_size_z = 1) in; + +layout(binding = 0) +writeonly uniform uimage2D dst; + +layout(push_constant) +uniform u_info_t { + uvec4 clear_value; + ivec4 dst_offset; + ivec4 dst_extent; +} u_info; + +void main() { + ivec3 thread_id = ivec3(gl_GlobalInvocationID); + + if (all(lessThan(thread_id.xy, u_info.dst_extent.xy))) { + imageStore(dst, + u_info.dst_offset.xy + thread_id.xy, + u_info.clear_value); + } +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_image2darr_f.comp b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_image2darr_f.comp new file mode 100644 index 00000000000..4eec19ccec6 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_image2darr_f.comp @@ -0,0 +1,26 @@ +#version 450 + +layout( + local_size_x = 8, + local_size_y = 8, + local_size_z = 1) in; + +layout(binding = 0) +writeonly uniform image2DArray dst; + +layout(push_constant) +uniform u_info_t { + vec4 clear_value; + ivec4 dst_offset; + ivec4 dst_extent; +} u_info; + +void main() { + ivec3 thread_id = ivec3(gl_GlobalInvocationID); + + if (all(lessThan(thread_id.xy, u_info.dst_extent.xy))) { + imageStore(dst, + ivec3(u_info.dst_offset.xy + thread_id.xy, thread_id.z), + u_info.clear_value); + } +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_image2darr_u.comp b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_image2darr_u.comp new file mode 100644 index 00000000000..c8babb78d54 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_image2darr_u.comp @@ -0,0 +1,26 @@ +#version 450 + +layout( + local_size_x = 8, + local_size_y = 8, + local_size_z = 1) in; + +layout(binding = 0) +writeonly uniform uimage2DArray dst; + +layout(push_constant) +uniform u_info_t { + uvec4 clear_value; + ivec4 dst_offset; + ivec4 dst_extent; +} u_info; + +void main() { + ivec3 thread_id = ivec3(gl_GlobalInvocationID); + + if (all(lessThan(thread_id.xy, u_info.dst_extent.xy))) { + imageStore(dst, + ivec3(u_info.dst_offset.xy + thread_id.xy, thread_id.z), + u_info.clear_value); + } +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_image3d_f.comp b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_image3d_f.comp new file mode 100644 index 00000000000..2b38fb4f1cd --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_image3d_f.comp @@ -0,0 +1,26 @@ +#version 450 + +layout( + local_size_x = 4, + local_size_y = 4, + local_size_z = 4) in; + +layout(binding = 0) +writeonly uniform image3D dst; + +layout(push_constant) +uniform u_info_t { + vec4 clear_value; + ivec4 dst_offset; + ivec4 dst_extent; +} u_info; + +void main() { + ivec3 thread_id = ivec3(gl_GlobalInvocationID); + + if (all(lessThan(thread_id.xyz, u_info.dst_extent.xyz))) { + imageStore(dst, + u_info.dst_offset.xyz + thread_id.xyz, + u_info.clear_value); + } +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_image3d_u.comp b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_image3d_u.comp new file mode 100644 index 00000000000..06db19a9b67 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_clear_image3d_u.comp @@ -0,0 +1,26 @@ +#version 450 + +layout( + local_size_x = 4, + local_size_y = 4, + local_size_z = 4) in; + +layout(binding = 0) +writeonly uniform uimage3D dst; + +layout(push_constant) +uniform u_info_t { + uvec4 clear_value; + ivec4 dst_offset; + ivec4 dst_extent; +} u_info; + +void main() { + ivec3 thread_id = ivec3(gl_GlobalInvocationID); + + if (all(lessThan(thread_id.xyz, u_info.dst_extent.xyz))) { + imageStore(dst, + u_info.dst_offset.xyz + thread_id.xyz, + u_info.clear_value); + } +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_copy_buffer_image.comp b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_copy_buffer_image.comp new file mode 100644 index 00000000000..7407285e3fc --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_copy_buffer_image.comp @@ -0,0 +1,30 @@ +#version 450 + +layout( + local_size_x = 8, + local_size_y = 8, + local_size_z = 1) in; + +layout(binding = 0) writeonly uniform uimageBuffer u_dst; +layout(binding = 1) uniform usamplerBuffer u_src; + +layout(push_constant) +uniform u_info_t { + uvec3 dst_offset; + uvec3 src_offset; + uvec3 extent; + uvec2 dst_size; + uvec2 src_size; +} u_info; + +void main() { + if (all(lessThan(gl_GlobalInvocationID, u_info.extent))) { + uvec3 dst_coord = u_info.dst_offset + gl_GlobalInvocationID; + uvec3 src_coord = u_info.src_offset + gl_GlobalInvocationID; + + uint dst_index = dst_coord.x + u_info.dst_size.x * (dst_coord.y + u_info.dst_size.y * dst_coord.z); + uint src_index = src_coord.x + u_info.src_size.x * (src_coord.y + u_info.src_size.y * src_coord.z); + + imageStore(u_dst, int(dst_index), texelFetch(u_src, int(src_index))); + } +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_copy_color_1d.frag b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_copy_color_1d.frag new file mode 100644 index 00000000000..76e83dac338 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_copy_color_1d.frag @@ -0,0 +1,16 @@ +#version 450 + +layout(set = 0, binding = 0) +uniform sampler1DArray s_image; + +layout(location = 0) out vec4 o_color; + +layout(push_constant) +uniform u_info_t { + ivec2 offset; +} u_info; + +void main() { + o_color = texelFetch(s_image, + ivec2(gl_FragCoord.x + u_info.offset.x, gl_Layer), 0); +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_copy_color_2d.frag b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_copy_color_2d.frag new file mode 100644 index 00000000000..db76c248303 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_copy_color_2d.frag @@ -0,0 +1,16 @@ +#version 450 + +layout(set = 0, binding = 0) +uniform sampler2DArray s_image; + +layout(location = 0) out vec4 o_color; + +layout(push_constant) +uniform u_info_t { + ivec2 offset; +} u_info; + +void main() { + o_color = texelFetch(s_image, + ivec3(gl_FragCoord.xy + u_info.offset, gl_Layer), 0); +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_copy_color_ms.frag b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_copy_color_ms.frag new file mode 100644 index 00000000000..61b81241d64 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_copy_color_ms.frag @@ -0,0 +1,17 @@ +#version 450 + +layout(set = 0, binding = 0) +uniform sampler2DMSArray s_image; + +layout(location = 0) out vec4 o_color; + +layout(push_constant) +uniform u_info_t { + ivec2 offset; +} u_info; + +void main() { + o_color = texelFetch(s_image, + ivec3(gl_FragCoord.xy + u_info.offset, gl_Layer), + gl_SampleID); +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_copy_depth_1d.frag b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_copy_depth_1d.frag new file mode 100644 index 00000000000..7150db10d48 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_copy_depth_1d.frag @@ -0,0 +1,14 @@ +#version 450 + +layout(set = 0, binding = 0) +uniform sampler1DArray s_image; + +layout(push_constant) +uniform u_info_t { + ivec2 offset; +} u_info; + +void main() { + gl_FragDepth = texelFetch(s_image, + ivec2(gl_FragCoord.x + u_info.offset.x, gl_Layer), 0).r; +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_copy_depth_2d.frag b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_copy_depth_2d.frag new file mode 100644 index 00000000000..a5eaf4e93a8 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_copy_depth_2d.frag @@ -0,0 +1,14 @@ +#version 450 + +layout(set = 0, binding = 0) +uniform sampler2DArray s_image; + +layout(push_constant) +uniform u_info_t { + ivec2 offset; +} u_info; + +void main() { + gl_FragDepth = texelFetch(s_image, + ivec3(gl_FragCoord.xy + u_info.offset, gl_Layer), 0).r; +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_copy_depth_ms.frag b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_copy_depth_ms.frag new file mode 100644 index 00000000000..4264c0387c7 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_copy_depth_ms.frag @@ -0,0 +1,15 @@ +#version 450 + +layout(set = 0, binding = 0) +uniform sampler2DMSArray s_image; + +layout(push_constant) +uniform u_info_t { + ivec2 offset; +} u_info; + +void main() { + gl_FragDepth = texelFetch(s_image, + ivec3(gl_FragCoord.xy + u_info.offset, gl_Layer), + gl_SampleID).r; +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_copy_depth_stencil_1d.frag b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_copy_depth_stencil_1d.frag new file mode 100644 index 00000000000..e017145df89 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_copy_depth_stencil_1d.frag @@ -0,0 +1,20 @@ +#version 450 + +#extension GL_ARB_shader_stencil_export : enable + +layout(set = 0, binding = 0) +uniform sampler1DArray s_depth; + +layout(set = 0, binding = 1) +uniform usampler1DArray s_stencil; + +layout(push_constant) +uniform u_info_t { + ivec2 offset; +} u_info; + +void main() { + ivec2 coord = ivec2(gl_FragCoord.x + u_info.offset.x, gl_Layer); + gl_FragDepth = texelFetch(s_depth, coord, 0).r; + gl_FragStencilRefARB = int(texelFetch(s_stencil, coord, 0).r); +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_copy_depth_stencil_2d.frag b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_copy_depth_stencil_2d.frag new file mode 100644 index 00000000000..29e7d6b0b56 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_copy_depth_stencil_2d.frag @@ -0,0 +1,20 @@ +#version 450 + +#extension GL_ARB_shader_stencil_export : enable + +layout(set = 0, binding = 0) +uniform sampler2DArray s_depth; + +layout(set = 0, binding = 1) +uniform usampler2DArray s_stencil; + +layout(push_constant) +uniform u_info_t { + ivec2 offset; +} u_info; + +void main() { + ivec3 coord = ivec3(gl_FragCoord.xy + u_info.offset.xy, gl_Layer); + gl_FragDepth = texelFetch(s_depth, coord, 0).r; + gl_FragStencilRefARB = int(texelFetch(s_stencil, coord, 0).r); +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_copy_depth_stencil_ms.frag b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_copy_depth_stencil_ms.frag new file mode 100644 index 00000000000..dfb5f005826 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_copy_depth_stencil_ms.frag @@ -0,0 +1,20 @@ +#version 450 + +#extension GL_ARB_shader_stencil_export : enable + +layout(set = 0, binding = 0) +uniform sampler2DMSArray s_depth; + +layout(set = 0, binding = 1) +uniform usampler2DMSArray s_stencil; + +layout(push_constant) +uniform u_info_t { + ivec2 offset; +} u_info; + +void main() { + ivec3 coord = ivec3(gl_FragCoord.xy + u_info.offset.xy, gl_Layer); + gl_FragDepth = texelFetch(s_depth, coord, gl_SampleID).r; + gl_FragStencilRefARB = int(texelFetch(s_stencil, coord, gl_SampleID).r); +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_fullscreen_geom.geom b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_fullscreen_geom.geom new file mode 100644 index 00000000000..c9fae0ccf25 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_fullscreen_geom.geom @@ -0,0 +1,19 @@ +#version 450 + +layout(triangles) in; +layout(triangle_strip, max_vertices = 3) out; + +layout(location = 0) in int i_instance[3]; +layout(location = 1) in vec2 i_texcoord[3]; +layout(location = 0) out vec2 o_texcoord; + +void main() { + for (int i = 0; i < 3; i++) { + o_texcoord = i_texcoord[i]; + gl_Layer = i_instance[i]; + gl_Position = gl_in[i].gl_Position; + EmitVertex(); + } + + EndPrimitive(); +} diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_fullscreen_layer_vert.vert b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_fullscreen_layer_vert.vert new file mode 100644 index 00000000000..ee33749ba22 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_fullscreen_layer_vert.vert @@ -0,0 +1,15 @@ +#version 450 + +#extension GL_ARB_shader_viewport_layer_array : enable + +layout(location = 0) out vec2 o_texcoord; + +void main() { + vec2 coord = vec2( + float(gl_VertexIndex & 2), + float(gl_VertexIndex & 1) * 2.0f); + + o_texcoord = coord; + gl_Layer = gl_InstanceIndex; + gl_Position = vec4(-1.0f + 2.0f * coord, 0.0f, 1.0f); +} diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_fullscreen_vert.vert b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_fullscreen_vert.vert new file mode 100644 index 00000000000..cf1856d0f74 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_fullscreen_vert.vert @@ -0,0 +1,14 @@ +#version 450 + +layout(location = 0) out int o_instance; +layout(location = 1) out vec2 o_texcoord; + +void main() { + vec2 coord = vec2( + float(gl_VertexIndex & 2), + float(gl_VertexIndex & 1) * 2.0f); + + o_instance = gl_InstanceIndex; + o_texcoord = coord; + gl_Position = vec4(-1.0f + 2.0f * coord, 0.0f, 1.0f); +} diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_pack_d24s8.comp b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_pack_d24s8.comp new file mode 100644 index 00000000000..c32fae5813b --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_pack_d24s8.comp @@ -0,0 +1,41 @@ +#version 450 + +layout( + local_size_x = 8, + local_size_y = 8, + local_size_z = 1) in; + +layout(binding = 0, std430) +writeonly buffer s_buffer_t { + uint data[]; +} s_buffer; + +layout(binding = 1) uniform sampler2DArray u_depth; +layout(binding = 2) uniform usampler2DArray u_stencil; + +layout(push_constant) +uniform u_info_t { + uvec2 src_offset; + uvec2 src_extent; + uvec2 dst_offset; + uvec2 dst_extent; +} u_info; + +void main() { + if (all(lessThan(gl_GlobalInvocationID.xy, u_info.src_extent))) { + uvec3 src_coord = uvec3( + gl_GlobalInvocationID.xy + u_info.src_offset, + gl_GlobalInvocationID.z); + + uvec3 dst_coord = uvec3( + gl_GlobalInvocationID.xy + u_info.dst_offset, + gl_GlobalInvocationID.z); + + uint dst_index = dst_coord.x + u_info.dst_extent.x * (dst_coord.y + u_info.dst_extent.y * dst_coord.z); + + float depth = texelFetch(u_depth, ivec3(src_coord), 0).r; + uint stencil = texelFetch(u_stencil, ivec3(src_coord), 0).r; + + s_buffer.data[dst_index] = uint(mix(0.0f, float((1 << 24) - 1), depth)) | (stencil << 24); + } +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_pack_d32s8.comp b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_pack_d32s8.comp new file mode 100644 index 00000000000..a0332f02cd7 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_pack_d32s8.comp @@ -0,0 +1,44 @@ +#version 450 + +layout( + local_size_x = 8, + local_size_y = 8, + local_size_z = 1) in; + +struct d32s8_t { + float d32; + uint s8; +}; + +layout(binding = 0, std430) +writeonly buffer s_buffer_t { + d32s8_t data[]; +} s_buffer; + +layout(binding = 1) uniform sampler2DArray u_depth; +layout(binding = 2) uniform usampler2DArray u_stencil; + +layout(push_constant) +uniform u_info_t { + uvec2 src_offset; + uvec2 src_extent; + uvec2 dst_offset; + uvec2 dst_extent; +} u_info; + +void main() { + if (all(lessThan(gl_GlobalInvocationID.xy, u_info.src_extent))) { + uvec3 src_coord = uvec3( + gl_GlobalInvocationID.xy + u_info.src_offset, + gl_GlobalInvocationID.z); + + uvec3 dst_coord = uvec3( + gl_GlobalInvocationID.xy + u_info.dst_offset, + gl_GlobalInvocationID.z); + + uint dst_index = dst_coord.x + u_info.dst_extent.x * (dst_coord.y + u_info.dst_extent.y * dst_coord.z); + + s_buffer.data[dst_index].d32 = texelFetch(u_depth, ivec3(src_coord), 0).r; + s_buffer.data[dst_index].s8 = texelFetch(u_stencil, ivec3(src_coord), 0).r; + } +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_present_frag.frag b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_present_frag.frag new file mode 100644 index 00000000000..7498a40760d --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_present_frag.frag @@ -0,0 +1,27 @@ +#version 450 + +layout(constant_id = 1) const bool s_gamma_bound = true; + +layout(binding = 0) uniform sampler2D s_image; +layout(binding = 1) uniform sampler1D s_gamma; + +layout(location = 0) out vec4 o_color; + +layout(push_constant) +uniform present_info_t { + ivec2 src_offset; + ivec2 dst_offset; +}; + +void main() { + ivec2 coord = ivec2(gl_FragCoord.xy) + src_offset - dst_offset; + o_color = texelFetch(s_image, coord, 0); + + if (s_gamma_bound) { + o_color = vec4( + texture(s_gamma, o_color.r).r, + texture(s_gamma, o_color.g).g, + texture(s_gamma, o_color.b).b, + o_color.a); + } +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_present_frag_blit.frag b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_present_frag_blit.frag new file mode 100644 index 00000000000..c5b66069167 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_present_frag_blit.frag @@ -0,0 +1,28 @@ +#version 450 + +layout(constant_id = 1) const bool s_gamma_bound = true; + +layout(binding = 0) uniform sampler2D s_image; +layout(binding = 1) uniform sampler1D s_gamma; + +layout(location = 0) in vec2 i_coord; +layout(location = 0) out vec4 o_color; + +layout(push_constant) +uniform present_info_t { + ivec2 src_offset; + uvec2 src_extent; +}; + +void main() { + vec2 coord = vec2(src_offset) + vec2(src_extent) * i_coord; + o_color = textureLod(s_image, coord, 0.0f); + + if (s_gamma_bound) { + o_color = vec4( + texture(s_gamma, o_color.r).r, + texture(s_gamma, o_color.g).g, + texture(s_gamma, o_color.b).b, + o_color.a); + } +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_present_frag_ms.frag b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_present_frag_ms.frag new file mode 100644 index 00000000000..9dd751ecf85 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_present_frag_ms.frag @@ -0,0 +1,33 @@ +#version 450 + +layout(constant_id = 1) const bool s_gamma_bound = true; +layout(constant_id = 1225) const uint c_samples = 0; + +layout(binding = 0) uniform sampler2DMS s_image; +layout(binding = 1) uniform sampler1D s_gamma; + +layout(location = 0) out vec4 o_color; + +layout(push_constant) +uniform present_info_t { + ivec2 src_offset; + ivec2 dst_offset; +}; + +void main() { + ivec2 coord = ivec2(gl_FragCoord.xy) + src_offset - dst_offset; + o_color = texelFetch(s_image, coord, 0); + + for (uint i = 1; i < c_samples; i++) + o_color += texelFetch(s_image, coord, int(i)); + + o_color /= float(c_samples); + + if (s_gamma_bound) { + o_color = vec4( + texture(s_gamma, o_color.r).r, + texture(s_gamma, o_color.g).g, + texture(s_gamma, o_color.b).b, + o_color.a); + } +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_present_frag_ms_amd.frag b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_present_frag_ms_amd.frag new file mode 100644 index 00000000000..c234591f10c --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_present_frag_ms_amd.frag @@ -0,0 +1,52 @@ +#version 450 + +#extension GL_AMD_shader_fragment_mask: enable + +layout(constant_id = 1) const bool s_gamma_bound = true; +layout(constant_id = 1225) const uint c_samples = 0; + +layout(binding = 0) uniform sampler2DMS s_image; +layout(binding = 1) uniform sampler1D s_gamma; + +layout(location = 0) out vec4 o_color; + +layout(push_constant) +uniform present_info_t { + ivec2 src_offset; + ivec2 dst_offset; +}; + +void main() { + ivec2 coord = ivec2(gl_FragCoord.xy) + src_offset - dst_offset; + + // check dxvk_resolve_frag_f_amd.frag for documentation + uint fragMask = fragmentMaskFetchAMD(s_image, coord); + uint fragCount = 0u; + + for (int i = 0; i < 4 * c_samples; i += 4) { + uint fragIndex = bitfieldExtract(fragMask, i, 4); + fragCount += 1u << (fragIndex << 2); + } + + o_color = vec4(0.0f); + + while (fragCount != 0) { + int fragIndex = findLSB(fragCount) >> 2; + int fragShift = fragIndex << 2; + + o_color += fragmentFetchAMD(s_image, coord, fragIndex) + * float(bitfieldExtract(fragCount, fragShift, 4)); + + fragCount = bitfieldInsert(fragCount, 0, fragShift, 4); + } + + o_color /= float(c_samples); + + if (s_gamma_bound) { + o_color = vec4( + texture(s_gamma, o_color.r).r, + texture(s_gamma, o_color.g).g, + texture(s_gamma, o_color.b).b, + o_color.a); + } +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_present_vert.vert b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_present_vert.vert new file mode 100644 index 00000000000..753a16f8e19 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_present_vert.vert @@ -0,0 +1,12 @@ +#version 450 + +layout(location = 0) out vec2 o_coord; + +void main() { + vec2 coord = vec2( + float(gl_VertexIndex & 2), + float(gl_VertexIndex & 1) * 2.0f); + + o_coord = coord; + gl_Position = vec4(-1.0f + 2.0f * coord, 0.0f, 1.0f); +} diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_resolve_frag_d.frag b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_resolve_frag_d.frag new file mode 100644 index 00000000000..0b726c97eea --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_resolve_frag_d.frag @@ -0,0 +1,54 @@ +#version 450 + +#define VK_RESOLVE_MODE_NONE_KHR (0) +#define VK_RESOLVE_MODE_SAMPLE_ZERO_BIT_KHR (1 << 0) +#define VK_RESOLVE_MODE_AVERAGE_BIT_KHR (1 << 1) +#define VK_RESOLVE_MODE_MIN_BIT_KHR (1 << 2) +#define VK_RESOLVE_MODE_MAX_BIT_KHR (1 << 3) + +layout(constant_id = 0) const int c_samples = 1; +layout(constant_id = 1) const int c_mode_d = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT_KHR; + +layout(binding = 0) uniform sampler2DMSArray s_depth; + +layout(push_constant) +uniform u_info_t { + ivec2 offset; +} u_info; + +float resolve_depth(ivec3 coord) { + float depth = 0.0f; + + switch (c_mode_d) { + case VK_RESOLVE_MODE_SAMPLE_ZERO_BIT_KHR: + depth = texelFetch(s_depth, coord, 0).r; + break; + + case VK_RESOLVE_MODE_AVERAGE_BIT_KHR: + depth = texelFetch(s_depth, coord, 0).r; + for (int i = 1; i < c_samples; i++) + depth += texelFetch(s_depth, coord, i).r; + depth /= float(c_samples); + break; + + case VK_RESOLVE_MODE_MIN_BIT_KHR: + depth = texelFetch(s_depth, coord, 0).r; + for (int i = 1; i < c_samples; i++) + depth = min(depth, texelFetch(s_depth, coord, i).r); + break; + + case VK_RESOLVE_MODE_MAX_BIT_KHR: + depth = texelFetch(s_depth, coord, 0).r; + for (int i = 1; i < c_samples; i++) + depth = max(depth, texelFetch(s_depth, coord, i).r); + break; + } + + return depth; +} + +void main() { + ivec3 coord = ivec3(gl_FragCoord.xy + u_info.offset, gl_Layer); + + gl_FragDepth = resolve_depth(coord); +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_resolve_frag_ds.frag b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_resolve_frag_ds.frag new file mode 100644 index 00000000000..734fe0fbb65 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_resolve_frag_ds.frag @@ -0,0 +1,83 @@ +#version 450 + +#extension GL_ARB_shader_stencil_export : enable + +#define VK_RESOLVE_MODE_NONE_KHR (0) +#define VK_RESOLVE_MODE_SAMPLE_ZERO_BIT_KHR (1 << 0) +#define VK_RESOLVE_MODE_AVERAGE_BIT_KHR (1 << 1) +#define VK_RESOLVE_MODE_MIN_BIT_KHR (1 << 2) +#define VK_RESOLVE_MODE_MAX_BIT_KHR (1 << 3) + +layout(constant_id = 0) const int c_samples = 1; +layout(constant_id = 1) const int c_mode_d = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT_KHR; +layout(constant_id = 2) const int c_mode_s = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT_KHR; + +layout(binding = 0) uniform sampler2DMSArray s_depth; +layout(binding = 1) uniform usampler2DMSArray s_stencil; + +layout(push_constant) +uniform u_info_t { + ivec2 offset; +} u_info; + +float resolve_depth(ivec3 coord) { + float depth = 0.0f; + + switch (c_mode_d) { + case VK_RESOLVE_MODE_SAMPLE_ZERO_BIT_KHR: + depth = texelFetch(s_depth, coord, 0).r; + break; + + case VK_RESOLVE_MODE_AVERAGE_BIT_KHR: + depth = texelFetch(s_depth, coord, 0).r; + for (int i = 1; i < c_samples; i++) + depth += texelFetch(s_depth, coord, i).r; + depth /= float(c_samples); + break; + + case VK_RESOLVE_MODE_MIN_BIT_KHR: + depth = texelFetch(s_depth, coord, 0).r; + for (int i = 1; i < c_samples; i++) + depth = min(depth, texelFetch(s_depth, coord, i).r); + break; + + case VK_RESOLVE_MODE_MAX_BIT_KHR: + depth = texelFetch(s_depth, coord, 0).r; + for (int i = 1; i < c_samples; i++) + depth = max(depth, texelFetch(s_depth, coord, i).r); + break; + } + + return depth; +} + +int resolve_stencil(ivec3 coord) { + uint stencil = 0u; + + switch (c_mode_s) { + case VK_RESOLVE_MODE_SAMPLE_ZERO_BIT_KHR: + stencil = texelFetch(s_stencil, coord, 0).r; + break; + + case VK_RESOLVE_MODE_MIN_BIT_KHR: + stencil = texelFetch(s_stencil, coord, 0).r; + for (int i = 1; i < c_samples; i++) + stencil = min(stencil, texelFetch(s_stencil, coord, i).r); + break; + + case VK_RESOLVE_MODE_MAX_BIT_KHR: + stencil = texelFetch(s_stencil, coord, 0).r; + for (int i = 1; i < c_samples; i++) + stencil = max(stencil, texelFetch(s_stencil, coord, i).r); + break; + } + + return int(stencil); +} + +void main() { + ivec3 coord = ivec3(gl_FragCoord.xy + u_info.offset, gl_Layer); + + gl_FragDepth = resolve_depth(coord); + gl_FragStencilRefARB = resolve_stencil(coord); +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_resolve_frag_f.frag b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_resolve_frag_f.frag new file mode 100644 index 00000000000..645a2f9bf56 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_resolve_frag_f.frag @@ -0,0 +1,20 @@ +#version 450 + +layout(constant_id = 0) const int c_samples = 1; + +layout(binding = 0) uniform sampler2DMSArray s_image; + +layout(location = 0) out vec4 o_color; + +layout(push_constant) +uniform u_info_t { + ivec2 offset; +} u_info; + +void main() { + ivec3 coord = ivec3(gl_FragCoord.xy + u_info.offset, gl_Layer); + vec4 color = vec4(0.0f); + for (int i = 0; i < c_samples; i++) + color += texelFetch(s_image, coord, i); + o_color = color / float(c_samples); +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_resolve_frag_f_amd.frag b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_resolve_frag_f_amd.frag new file mode 100644 index 00000000000..a9cf9ee48be --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_resolve_frag_f_amd.frag @@ -0,0 +1,47 @@ +#version 450 + +#extension GL_AMD_shader_fragment_mask: enable + +layout(constant_id = 0) const int c_samples = 1; + +layout(set = 0, binding = 0) +uniform sampler2DMSArray s_image; + +layout(location = 0) out vec4 o_color; + +layout(push_constant) +uniform u_info_t { + ivec2 offset; +} u_info; + +void main() { + ivec3 coord = ivec3(gl_FragCoord.xy + u_info.offset, gl_Layer); + + // get a four-bit fragment index for each sample + uint fragMask = fragmentMaskFetchAMD(s_image, coord); + + // count number of occurences of each fragment + // index in one four-bit counter for each sample + uint fragCount = 0u; + + for (int i = 0; i < 4 * c_samples; i += 4) { + uint fragIndex = bitfieldExtract(fragMask, i, 4); + fragCount += 1u << (fragIndex << 2); + } + + // perform necessary texture lookups to compute + // final fragment color + o_color = vec4(0.0f); + + while (fragCount != 0) { + int fragIndex = findLSB(fragCount) >> 2; + int fragShift = fragIndex << 2; + + o_color += fragmentFetchAMD(s_image, coord, fragIndex) + * float(bitfieldExtract(fragCount, fragShift, 4)); + + fragCount = bitfieldInsert(fragCount, 0, fragShift, 4); + } + + o_color /= float(c_samples); +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_resolve_frag_i.frag b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_resolve_frag_i.frag new file mode 100644 index 00000000000..021980d64a4 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_resolve_frag_i.frag @@ -0,0 +1,15 @@ +#version 450 + +layout(binding = 0) uniform isampler2DMSArray s_image; + +layout(location = 0) out ivec4 o_color; + +layout(push_constant) +uniform u_info_t { + ivec2 offset; +} u_info; + +void main() { + ivec3 coord = ivec3(gl_FragCoord.xy + u_info.offset, gl_Layer); + o_color = texelFetch(s_image, coord, 0); +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_resolve_frag_u.frag b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_resolve_frag_u.frag new file mode 100644 index 00000000000..3d3cfdf3643 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_resolve_frag_u.frag @@ -0,0 +1,15 @@ +#version 450 + +layout(binding = 0) uniform usampler2DMSArray s_image; + +layout(location = 0) out uvec4 o_color; + +layout(push_constant) +uniform u_info_t { + ivec2 offset; +} u_info; + +void main() { + ivec3 coord = ivec3(gl_FragCoord.xy + u_info.offset, gl_Layer); + o_color = texelFetch(s_image, coord, 0); +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_unpack_d24s8.comp b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_unpack_d24s8.comp new file mode 100644 index 00000000000..6b7a85575f8 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_unpack_d24s8.comp @@ -0,0 +1,41 @@ +#version 450 + +layout( + local_size_x = 64, + local_size_y = 1, + local_size_z = 1) in; + +layout(binding = 0, r32ui) writeonly uniform uimageBuffer u_depth; +layout(binding = 1, r8ui) writeonly uniform uimageBuffer u_stencil; + +layout(binding = 2) +readonly buffer s_buffer_t { + uint data[]; +} s_buffer; + +layout(push_constant) +uniform u_info_t { + uvec2 src_offset; + uvec2 src_extent; + uvec2 dst_offset; + uvec2 dst_extent; +} u_info; + +void main() { + if (all(lessThan(gl_GlobalInvocationID.xy, u_info.dst_extent))) { + uvec3 src_coord = uvec3( + gl_GlobalInvocationID.xy + u_info.src_offset, + gl_GlobalInvocationID.z); + + uvec3 dst_coord = uvec3( + gl_GlobalInvocationID.xy + u_info.dst_offset, + gl_GlobalInvocationID.z); + + uint src_index = src_coord.x + u_info.src_extent.x * (src_coord.y + u_info.src_extent.y * src_coord.z); + uint dst_index = dst_coord.x + u_info.dst_extent.x * (dst_coord.y + u_info.dst_extent.y * dst_coord.z); + + uint src_data = s_buffer.data[src_index]; + imageStore(u_depth, int(dst_index), uvec4(src_data & 0xFFFFFF)); + imageStore(u_stencil, int(dst_index), uvec4(src_data >> 24)); + } +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_unpack_d24s8_as_d32s8.comp b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_unpack_d24s8_as_d32s8.comp new file mode 100644 index 00000000000..4c87fbba09a --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_unpack_d24s8_as_d32s8.comp @@ -0,0 +1,41 @@ +#version 450 + +layout( + local_size_x = 64, + local_size_y = 1, + local_size_z = 1) in; + +layout(binding = 0, r32f) writeonly uniform imageBuffer u_depth; +layout(binding = 1, r8ui) writeonly uniform uimageBuffer u_stencil; + +layout(binding = 2) +readonly buffer s_buffer_t { + uint data[]; +} s_buffer; + +layout(push_constant) +uniform u_info_t { + uvec2 src_offset; + uvec2 src_extent; + uvec2 dst_offset; + uvec2 dst_extent; +} u_info; + +void main() { + if (all(lessThan(gl_GlobalInvocationID.xy, u_info.dst_extent))) { + uvec3 src_coord = uvec3( + gl_GlobalInvocationID.xy + u_info.src_offset, + gl_GlobalInvocationID.z); + + uvec3 dst_coord = uvec3( + gl_GlobalInvocationID.xy + u_info.dst_offset, + gl_GlobalInvocationID.z); + + uint src_index = src_coord.x + u_info.src_extent.x * (src_coord.y + u_info.src_extent.y * src_coord.z); + uint dst_index = dst_coord.x + u_info.dst_extent.x * (dst_coord.y + u_info.dst_extent.y * dst_coord.z); + + uint src_data = s_buffer.data[src_index]; + imageStore(u_depth, int(dst_index), vec4(float(src_data & 0xFFFFFF) / float(0xFFFFFF))); + imageStore(u_stencil, int(dst_index), uvec4(src_data >> 24)); + } +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_unpack_d32s8.comp b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_unpack_d32s8.comp new file mode 100644 index 00000000000..dd114746899 --- /dev/null +++ b/utils/dxvk-1.10.3/src/dxvk/shaders/dxvk_unpack_d32s8.comp @@ -0,0 +1,46 @@ +#version 450 + +layout( + local_size_x = 64, + local_size_y = 1, + local_size_z = 1) in; + +struct d32s8_t { + float d32; + uint s8; +}; + +layout(binding = 0, r32f) writeonly uniform imageBuffer u_depth; +layout(binding = 1, r8ui) writeonly uniform uimageBuffer u_stencil; + +layout(binding = 2) +readonly buffer s_buffer_t { + d32s8_t data[]; +} s_buffer; + +layout(push_constant) +uniform u_info_t { + uvec2 src_offset; + uvec2 src_extent; + uvec2 dst_offset; + uvec2 dst_extent; +} u_info; + +void main() { + if (all(lessThan(gl_GlobalInvocationID.xy, u_info.dst_extent))) { + uvec3 src_coord = uvec3( + gl_GlobalInvocationID.xy + u_info.src_offset, + gl_GlobalInvocationID.z); + + uvec3 dst_coord = uvec3( + gl_GlobalInvocationID.xy + u_info.dst_offset, + gl_GlobalInvocationID.z); + + uint src_index = src_coord.x + u_info.src_extent.x * (src_coord.y + u_info.src_extent.y * src_coord.z); + uint dst_index = dst_coord.x + u_info.dst_extent.x * (dst_coord.y + u_info.dst_extent.y * dst_coord.z); + + d32s8_t src_data = s_buffer.data[src_index]; + imageStore(u_depth, int(dst_index), vec4(src_data.d32)); + imageStore(u_stencil, int(dst_index), uvec4(src_data.s8)); + } +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/meson.build b/utils/dxvk-1.10.3/src/meson.build new file mode 100644 index 00000000000..c5d2753a5c9 --- /dev/null +++ b/utils/dxvk-1.10.3/src/meson.build @@ -0,0 +1,36 @@ +subdir('util') +subdir('spirv') +subdir('vulkan') +subdir('dxvk') + +if get_option('enable_dxgi') + if not get_option('enable_d3d11') + error('D3D11 is required for DXGI.') + endif + subdir('dxgi') +endif + +if get_option('enable_d3d10') or get_option('enable_d3d11') or get_option('enable_tests') + subdir('dxbc') +endif + +if get_option('enable_d3d11') + subdir('d3d11') +endif + +if get_option('enable_d3d10') + if not get_option('enable_d3d11') + error('D3D11 is required for D3D10.') + endif + subdir('d3d10') +endif + +if get_option('enable_d3d9') + subdir('dxso') + subdir('d3d9') +endif + +# Nothing selected +if not get_option('enable_d3d9') and not get_option('enable_d3d10') and not get_option('enable_d3d11') and not get_option('enable_tests') + warning('Nothing selected to be built. Are you missing a frontend or tests?') +endif diff --git a/utils/dxvk-1.10.3/src/spirv/meson.build b/utils/dxvk-1.10.3/src/spirv/meson.build new file mode 100644 index 00000000000..1000138c40e --- /dev/null +++ b/utils/dxvk-1.10.3/src/spirv/meson.build @@ -0,0 +1,9 @@ +spirv_src = files([ + 'spirv_code_buffer.cpp', + 'spirv_compression.cpp', + 'spirv_module.cpp', +]) + +spirv_lib = static_library('spirv', spirv_src, + include_directories : [ dxvk_include_path ], +) diff --git a/utils/dxvk-1.10.3/src/spirv/spirv_code_buffer.cpp b/utils/dxvk-1.10.3/src/spirv/spirv_code_buffer.cpp new file mode 100644 index 00000000000..74d8dd970c6 --- /dev/null +++ b/utils/dxvk-1.10.3/src/spirv/spirv_code_buffer.cpp @@ -0,0 +1,154 @@ +#include +#include + +#include "spirv_code_buffer.h" + +namespace dxvk { + + SpirvCodeBuffer:: SpirvCodeBuffer() { } + SpirvCodeBuffer::~SpirvCodeBuffer() { } + + + SpirvCodeBuffer::SpirvCodeBuffer(uint32_t size) + : m_ptr(size) { + m_code.resize(size); + } + + + SpirvCodeBuffer::SpirvCodeBuffer(uint32_t size, const uint32_t* data) + : m_ptr(size) { + m_code.resize(size); + std::memcpy(m_code.data(), data, size * sizeof(uint32_t)); + } + + + SpirvCodeBuffer::SpirvCodeBuffer(std::istream& stream) { + stream.ignore(std::numeric_limits::max()); + std::streamsize length = stream.gcount(); + stream.clear(); + stream.seekg(0, std::ios_base::beg); + + std::vector buffer(length); + stream.read(buffer.data(), length); + buffer.resize(stream.gcount()); + + m_code.resize(buffer.size() / sizeof(uint32_t)); + std::memcpy(reinterpret_cast(m_code.data()), + buffer.data(), m_code.size() * sizeof(uint32_t)); + + m_ptr = m_code.size(); + } + + + uint32_t SpirvCodeBuffer::allocId() { + constexpr size_t BoundIdsOffset = 3; + + if (m_code.size() <= BoundIdsOffset) + return 0; + + return m_code[BoundIdsOffset]++; + } + + + void SpirvCodeBuffer::append(const SpirvCodeBuffer& other) { + if (other.size() != 0) { + const size_t size = m_code.size(); + m_code.resize(size + other.m_code.size()); + + uint32_t* dst = this->m_code.data(); + const uint32_t* src = other.m_code.data(); + + std::memcpy(dst + size, src, other.size()); + m_ptr += other.m_code.size(); + } + } + + + void SpirvCodeBuffer::putWord(uint32_t word) { + m_code.insert(m_code.begin() + m_ptr, word); + m_ptr += 1; + } + + + void SpirvCodeBuffer::putIns(spv::Op opCode, uint16_t wordCount) { + this->putWord( + (static_cast(opCode) << 0) + | (static_cast(wordCount) << 16)); + } + + + void SpirvCodeBuffer::putInt32(uint32_t word) { + this->putWord(word); + } + + + void SpirvCodeBuffer::putInt64(uint64_t value) { + this->putWord(value >> 0); + this->putWord(value >> 32); + } + + + void SpirvCodeBuffer::putFloat32(float value) { + uint32_t tmp; + static_assert(sizeof(tmp) == sizeof(value)); + std::memcpy(&tmp, &value, sizeof(value)); + this->putInt32(tmp); + } + + + void SpirvCodeBuffer::putFloat64(double value) { + uint64_t tmp; + static_assert(sizeof(tmp) == sizeof(value)); + std::memcpy(&tmp, &value, sizeof(value)); + this->putInt64(tmp); + } + + + void SpirvCodeBuffer::putStr(const char* str) { + uint32_t word = 0; + uint32_t nbit = 0; + + for (uint32_t i = 0; str[i] != '\0'; str++) { + word |= (static_cast(str[i]) & 0xFF) << nbit; + + if ((nbit += 8) == 32) { + this->putWord(word); + word = 0; + nbit = 0; + } + } + + // Commit current word + this->putWord(word); + } + + + void SpirvCodeBuffer::putHeader(uint32_t version, uint32_t boundIds) { + this->putWord(spv::MagicNumber); + this->putWord(version); + this->putWord(0); // Generator + this->putWord(boundIds); + this->putWord(0); // Schema + } + + + void SpirvCodeBuffer::erase(size_t size) { + m_code.erase( + m_code.begin() + m_ptr, + m_code.begin() + m_ptr + size); + } + + + uint32_t SpirvCodeBuffer::strLen(const char* str) { + // Null-termination plus padding + return (std::strlen(str) + 4) / 4; + } + + + void SpirvCodeBuffer::store(std::ostream& stream) const { + stream.write( + reinterpret_cast(m_code.data()), + sizeof(uint32_t) * m_code.size()); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/spirv/spirv_code_buffer.h b/utils/dxvk-1.10.3/src/spirv/spirv_code_buffer.h new file mode 100644 index 00000000000..a0ed2272769 --- /dev/null +++ b/utils/dxvk-1.10.3/src/spirv/spirv_code_buffer.h @@ -0,0 +1,225 @@ +#pragma once + +#include + +#include +#include +#include + +#include "spirv_instruction.h" + +namespace dxvk { + + /** + * \brief SPIR-V code buffer + * + * Helper class for generating SPIR-V shaders. + * Stores arbitrary SPIR-V instructions in a + * format that can be read by Vulkan drivers. + */ + class SpirvCodeBuffer { + + public: + + SpirvCodeBuffer(); + explicit SpirvCodeBuffer(uint32_t size); + SpirvCodeBuffer(uint32_t size, const uint32_t* data); + SpirvCodeBuffer(std::istream& stream); + + template + SpirvCodeBuffer(const uint32_t (&data)[N]) + : SpirvCodeBuffer(N, data) { } + + ~SpirvCodeBuffer(); + + /** + * \brief Code data + * \returns Code data + */ + const uint32_t* data() const { return m_code.data(); } + uint32_t* data() { return m_code.data(); } + + /** + * \brief Code size, in dwords + * \returns Code size, in dwords + */ + uint32_t dwords() const { + return m_code.size(); + } + + /** + * \brief Code size, in bytes + * \returns Code size, in bytes + */ + size_t size() const { + return m_code.size() * sizeof(uint32_t); + } + + /** + * \brief Begin instruction iterator + * + * Points to the first instruction in the instruction + * block. The header, if any, will be skipped over. + * \returns Instruction iterator + */ + SpirvInstructionIterator begin() { + return SpirvInstructionIterator( + m_code.data(), 0, m_code.size()); + } + + /** + * \brief End instruction iterator + * + * Points to the end of the instruction block. + * \returns Instruction iterator + */ + SpirvInstructionIterator end() { + return SpirvInstructionIterator(nullptr, 0, 0); + } + + /** + * \brief Allocates a new ID + * + * Returns a new valid ID and increments the + * maximum ID count stored in the header. + * \returns The new SPIR-V ID + */ + uint32_t allocId(); + + /** + * \brief Merges two code buffers + * + * This is useful to generate declarations or + * the SPIR-V header at the same time as the + * code when doing so in advance is impossible. + * \param [in] other Code buffer to append + */ + void append(const SpirvCodeBuffer& other); + + /** + * \brief Appends an 32-bit word to the buffer + * \param [in] word The word to append + */ + void putWord(uint32_t word); + + /** + * \brief Appends an instruction word to the buffer + * + * Adds a single word containing both the word count + * and the op code number for a single instruction. + * \param [in] opCode Operand code + * \param [in] wordCount Number of words + */ + void putIns(spv::Op opCode, uint16_t wordCount); + + /** + * \brief Appends a 32-bit integer to the buffer + * \param [in] value The number to add + */ + void putInt32(uint32_t word); + + /** + * \brief Appends a 64-bit integer to the buffer + * + * A 64-bit integer will take up two 32-bit words. + * \param [in] value 64-bit value to add + */ + void putInt64(uint64_t value); + + /** + * \brief Appends a 32-bit float to the buffer + * \param [in] value The number to add + */ + void putFloat32(float value); + + /** + * \brief Appends a 64-bit float to the buffer + * \param [in] value The number to add + */ + void putFloat64(double value); + + /** + * \brief Appends a literal string to the buffer + * \param [in] str String to append to the buffer + */ + void putStr(const char* str); + + /** + * \brief Adds the header to the buffer + * + * \param [in] version SPIR-V version + * \param [in] boundIds Number of bound IDs + */ + void putHeader(uint32_t version, uint32_t boundIds); + + /** + * \brief Erases given number of dwords + * + * Removes data from the code buffer, starting + * at the current insertion offset. + * \param [in] size Number of words to remove + */ + void erase(size_t size); + + /** + * \brief Computes length of a literal string + * + * \param [in] str The string to check + * \returns Number of words consumed by a string + */ + uint32_t strLen(const char* str); + + /** + * \brief Stores the SPIR-V module to a stream + * + * The ability to save modules to a file + * exists mostly for debugging purposes. + * \param [in] stream Output stream + */ + void store(std::ostream& stream) const; + + /** + * \brief Retrieves current insertion pointer + * + * Sometimes it may be necessay to insert code into the + * middle of the stream rather than appending it. This + * retrieves the current function pointer. Note that the + * pointer will become invalid if any code is inserted + * before the current pointer location. + * \returns Current instruction pointr + */ + size_t getInsertionPtr() const { + return m_ptr; + } + + /** + * \brief Sets insertion pointer to a specific value + * + * Sets the insertion pointer to a value that was + * previously retrieved by \ref getInsertionPtr. + * \returns Current instruction pointr + */ + void beginInsertion(size_t ptr) { + m_ptr = ptr; + } + + /** + * \brief Sets insertion pointer to the end + * + * After this call, new instructions will be + * appended to the stream. In other words, + * this will restore default behaviour. + * \returns Previous instruction pointer + */ + size_t endInsertion() { + return std::exchange(m_ptr, m_code.size()); + } + + private: + + std::vector m_code; + size_t m_ptr = 0; + + }; + +} diff --git a/utils/dxvk-1.10.3/src/spirv/spirv_compression.cpp b/utils/dxvk-1.10.3/src/spirv/spirv_compression.cpp new file mode 100644 index 00000000000..105162025a9 --- /dev/null +++ b/utils/dxvk-1.10.3/src/spirv/spirv_compression.cpp @@ -0,0 +1,123 @@ +#include "spirv_compression.h" + +namespace dxvk { + + SpirvCompressedBuffer::SpirvCompressedBuffer() + : m_size(0) { + + } + + + SpirvCompressedBuffer::SpirvCompressedBuffer(SpirvCodeBuffer& code) + : m_size(code.dwords()) { + // The compression (detailed below) achieves roughly 55% of the + // original size on average and is very consistent, so an initial + // estimate of roughly 58% will be accurate most of the time. + const uint32_t* data = code.data(); + m_code.reserve((m_size * 75) / 128); + + std::array block; + uint32_t blockMask = 0; + uint32_t blockOffset = 0; + + // The algorithm used is a simple variable-to-fixed compression that + // encodes up to two consecutive SPIR-V tokens into one DWORD using + // a small number of different encodings. While not achieving great + // compression ratios, the main goal is to allow decompression code + // to be fast, with short dependency chains. + // Compressed tokens are stored in blocks of 16 DWORDs, each preceeded + // by a single DWORD which stores the layout for each DWORD, two bits + // each. The supported layouts, are as follows: + // 0x0: 1x 32-bit; 0x1: 1x 20-bit + 1x 12-bit + // 0x2: 2x 16-bit; 0x3: 1x 12-bit + 1x 20-bit + // These layouts are chosen to allow reasonably efficient encoding of + // opcode tokens, which usually fit into 20 bits, followed by type IDs, + // which tend to be low as well since most types are defined early. + for (size_t i = 0; i < m_size; ) { + if (likely(i + 1 < m_size)) { + uint32_t a = data[i]; + uint32_t b = data[i + 1]; + uint32_t schema; + uint32_t encode; + + if (std::max(a, b) < (1u << 16)) { + schema = 0x2; + encode = a | (b << 16); + } else if (a < (1u << 20) && b < (1u << 12)) { + schema = 0x1; + encode = a | (b << 20); + } else if (a < (1u << 12) && b < (1u << 20)) { + schema = 0x3; + encode = a | (b << 12); + } else { + schema = 0x0; + encode = a; + } + + block[blockOffset] = encode; + blockMask |= schema << (blockOffset << 1); + blockOffset += 1; + + i += schema ? 2 : 1; + } else { + block[blockOffset] = data[i++]; + blockOffset += 1; + } + + if (unlikely(blockOffset == 16) || unlikely(i == m_size)) { + m_code.insert(m_code.end(), blockMask); + m_code.insert(m_code.end(), block.begin(), block.begin() + blockOffset); + + blockMask = 0; + blockOffset = 0; + } + } + + // Only shrink the array if we have lots of overhead for some reason. + // This should only happen on shaders where our initial estimate was + // too small. In general, we want to avoid reallocation here. + if (m_code.capacity() > (m_code.size() * 10) / 9) + m_code.shrink_to_fit(); + } + + + SpirvCompressedBuffer::~SpirvCompressedBuffer() { + + } + + + SpirvCodeBuffer SpirvCompressedBuffer::decompress() const { + SpirvCodeBuffer code(m_size); + uint32_t* data = code.data(); + + uint32_t srcOffset = 0; + uint32_t dstOffset = 0; + + constexpr uint32_t shiftAmounts = 0x0c101420; + + while (dstOffset < m_size) { + uint32_t blockMask = m_code[srcOffset]; + + for (uint32_t i = 0; i < 16 && dstOffset < m_size; i++) { + // Use 64-bit integers for some of the operands so we can + // shift by 32 bits and not handle it as a special cases + uint32_t schema = (blockMask >> (i << 1)) & 0x3; + uint32_t shift = (shiftAmounts >> (schema << 3)) & 0xff; + uint64_t mask = ~(~0ull << shift); + uint64_t encode = m_code[srcOffset + i + 1]; + + data[dstOffset] = encode & mask; + + if (likely(schema)) + data[dstOffset + 1] = encode >> shift; + + dstOffset += schema ? 2 : 1; + } + + srcOffset += 17; + } + + return code; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/spirv/spirv_compression.h b/utils/dxvk-1.10.3/src/spirv/spirv_compression.h new file mode 100644 index 00000000000..e48f39881c5 --- /dev/null +++ b/utils/dxvk-1.10.3/src/spirv/spirv_compression.h @@ -0,0 +1,38 @@ +#pragma once + +#include + +#include "spirv_code_buffer.h" + +namespace dxvk { + + /** + * \brief Compressed SPIR-V code buffer + * + * Implements a fast in-memory compression + * to keep memory footprint low. + */ + class SpirvCompressedBuffer { + + public: + + SpirvCompressedBuffer(); + + SpirvCompressedBuffer(SpirvCodeBuffer& code); + + ~SpirvCompressedBuffer(); + + SpirvCodeBuffer decompress() const; + + private: + + size_t m_size; + std::vector m_code; + + void encodeDword(uint32_t dw); + + uint32_t decodeDword(size_t& offset) const; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/spirv/spirv_include.h b/utils/dxvk-1.10.3/src/spirv/spirv_include.h new file mode 100644 index 00000000000..fca941816d0 --- /dev/null +++ b/utils/dxvk-1.10.3/src/spirv/spirv_include.h @@ -0,0 +1,12 @@ +#pragma once + +#include "../util/log/log.h" +#include "../util/log/log_debug.h" + +#include "../util/util_error.h" +#include "../util/util_flags.h" +#include "../util/util_likely.h" +#include "../util/util_string.h" + +#include "../util/rc/util_rc.h" +#include "../util/rc/util_rc_ptr.h" diff --git a/utils/dxvk-1.10.3/src/spirv/spirv_instruction.h b/utils/dxvk-1.10.3/src/spirv/spirv_instruction.h new file mode 100644 index 00000000000..ada816e723f --- /dev/null +++ b/utils/dxvk-1.10.3/src/spirv/spirv_instruction.h @@ -0,0 +1,161 @@ +#pragma once + +#include +#include + +#include "spirv_include.h" + +namespace dxvk { + + /** + * \brief SPIR-V instruction + * + * Helps parsing a single instruction, providing + * access to the op code, instruction length and + * instruction arguments. + */ + class SpirvInstruction { + + public: + + SpirvInstruction() { } + SpirvInstruction(uint32_t* code, uint32_t offset, uint32_t length) + : m_code(code), m_offset(offset), m_length(length) { } + + /** + * \brief SPIR-V Op code + * \returns The op code + */ + spv::Op opCode() const { + return static_cast( + this->arg(0) & spv::OpCodeMask); + } + + /** + * \brief Instruction length + * \returns Number of DWORDs + */ + uint32_t length() const { + return this->arg(0) >> spv::WordCountShift; + } + + /** + * \brief Instruction offset + * \returns Offset in DWORDs + */ + uint32_t offset() const { + return m_offset; + } + + /** + * \brief Argument value + * + * Retrieves an argument DWORD. Note that some instructions + * take 64-bit arguments which require more than one DWORD. + * Arguments start at index 1. Calling this method with an + * argument ID of 0 will return the opcode token. + * \param [in] idx Argument index, starting at 1 + * \returns The argument value + */ + uint32_t arg(uint32_t idx) const { + const uint32_t index = m_offset + idx; + return index < m_length ? m_code[index] : 0; + } + + /** + * \brief Argument string + * + * Retrieves a pointer to a UTF-8-encoded string. + * \param [in] idx Argument index, starting at 1 + * \returns Pointer to the literal string + */ + const char* chr(uint32_t idx) const { + const uint32_t index = m_offset + idx; + return index < m_length ? reinterpret_cast(&m_code[index]) : nullptr; + } + + /** + * \brief Changes the value of an argument + * + * \param [in] idx Argument index, starting at 1 + * \param [in] word New argument word + */ + void setArg(uint32_t idx, uint32_t word) const { + if (m_offset + idx < m_length) + m_code[m_offset + idx] = word; + } + + private: + + uint32_t* m_code = nullptr; + uint32_t m_offset = 0; + uint32_t m_length = 0; + + }; + + + /** + * \brief SPIR-V instruction iterator + * + * Convenient iterator that can be used + * to process raw SPIR-V shader code. + */ + class SpirvInstructionIterator { + + public: + + SpirvInstructionIterator() { } + SpirvInstructionIterator(uint32_t* code, uint32_t offset, uint32_t length) + : m_code (length != 0 ? code : nullptr), + m_offset(length != 0 ? offset : 0), + m_length(length) { + if ((length >= 5) && (offset == 0) && (m_code[0] == spv::MagicNumber)) + this->advance(5); + } + + SpirvInstructionIterator& operator ++ () { + this->advance(SpirvInstruction(m_code, m_offset, m_length).length()); + return *this; + } + + SpirvInstructionIterator operator ++ (int) { + SpirvInstructionIterator result = *this; + this->advance(SpirvInstruction(m_code, m_offset, m_length).length()); + return result; + } + + SpirvInstruction operator * () const { + return SpirvInstruction(m_code, m_offset, m_length); + } + + bool operator == (const SpirvInstructionIterator& other) const { + return this->m_code == other.m_code + && this->m_offset == other.m_offset + && this->m_length == other.m_length; + } + + bool operator != (const SpirvInstructionIterator& other) const { + return this->m_code != other.m_code + || this->m_offset != other.m_offset + || this->m_length != other.m_length; + } + + private: + + uint32_t* m_code = nullptr; + uint32_t m_offset = 0; + uint32_t m_length = 0; + + void advance(uint32_t n) { + if (m_offset + n < m_length) { + m_offset += n; + } else { + m_code = nullptr; + m_offset = 0; + m_length = 0; + } + } + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/spirv/spirv_module.cpp b/utils/dxvk-1.10.3/src/spirv/spirv_module.cpp new file mode 100644 index 00000000000..7811bae9aea --- /dev/null +++ b/utils/dxvk-1.10.3/src/spirv/spirv_module.cpp @@ -0,0 +1,3741 @@ +#include + +#include "spirv_module.h" + +namespace dxvk { + + SpirvModule::SpirvModule(uint32_t version) + : m_version(version) { + this->instImportGlsl450(); + } + + + SpirvModule::~SpirvModule() { + + } + + + SpirvCodeBuffer SpirvModule::compile() const { + SpirvCodeBuffer result; + result.putHeader(m_version, m_id); + result.append(m_capabilities); + result.append(m_extensions); + result.append(m_instExt); + result.append(m_memoryModel); + result.append(m_entryPoints); + result.append(m_execModeInfo); + result.append(m_debugNames); + result.append(m_annotations); + result.append(m_typeConstDefs); + result.append(m_variables); + result.append(m_code); + return result; + } + + + uint32_t SpirvModule::allocateId() { + return m_id++; + } + + + bool SpirvModule::hasCapability( + spv::Capability capability) { + for (auto ins : m_capabilities) { + if (ins.opCode() == spv::OpCapability && ins.arg(1) == capability) + return true; + } + + return false; + } + + void SpirvModule::enableCapability( + spv::Capability capability) { + // Scan the generated instructions to check + // whether we already enabled the capability. + if (!hasCapability(capability)) { + m_capabilities.putIns (spv::OpCapability, 2); + m_capabilities.putWord(capability); + } + } + + + void SpirvModule::enableExtension( + const char* extensionName) { + m_extensions.putIns (spv::OpExtension, 1 + m_extensions.strLen(extensionName)); + m_extensions.putStr (extensionName); + } + + + void SpirvModule::addEntryPoint( + uint32_t entryPointId, + spv::ExecutionModel executionModel, + const char* name, + uint32_t interfaceCount, + const uint32_t* interfaceIds) { + m_entryPoints.putIns (spv::OpEntryPoint, 3 + m_entryPoints.strLen(name) + interfaceCount); + m_entryPoints.putWord (executionModel); + m_entryPoints.putWord (entryPointId); + m_entryPoints.putStr (name); + + for (uint32_t i = 0; i < interfaceCount; i++) + m_entryPoints.putWord(interfaceIds[i]); + } + + + void SpirvModule::setMemoryModel( + spv::AddressingModel addressModel, + spv::MemoryModel memoryModel) { + m_memoryModel.putIns (spv::OpMemoryModel, 3); + m_memoryModel.putWord (addressModel); + m_memoryModel.putWord (memoryModel); + } + + + void SpirvModule::setExecutionMode( + uint32_t entryPointId, + spv::ExecutionMode executionMode) { + m_execModeInfo.putIns (spv::OpExecutionMode, 3); + m_execModeInfo.putWord(entryPointId); + m_execModeInfo.putWord(executionMode); + } + + + void SpirvModule::setExecutionMode( + uint32_t entryPointId, + spv::ExecutionMode executionMode, + uint32_t argCount, + const uint32_t* args) { + m_execModeInfo.putIns (spv::OpExecutionMode, 3 + argCount); + m_execModeInfo.putWord(entryPointId); + m_execModeInfo.putWord(executionMode); + + for (uint32_t i = 0; i < argCount; i++) + m_execModeInfo.putWord(args[i]); + } + + + void SpirvModule::setInvocations( + uint32_t entryPointId, + uint32_t invocations) { + m_execModeInfo.putIns (spv::OpExecutionMode, 4); + m_execModeInfo.putWord (entryPointId); + m_execModeInfo.putWord (spv::ExecutionModeInvocations); + m_execModeInfo.putInt32(invocations); + } + + + void SpirvModule::setLocalSize( + uint32_t entryPointId, + uint32_t x, + uint32_t y, + uint32_t z) { + m_execModeInfo.putIns (spv::OpExecutionMode, 6); + m_execModeInfo.putWord (entryPointId); + m_execModeInfo.putWord (spv::ExecutionModeLocalSize); + m_execModeInfo.putInt32(x); + m_execModeInfo.putInt32(y); + m_execModeInfo.putInt32(z); + } + + + void SpirvModule::setOutputVertices( + uint32_t entryPointId, + uint32_t vertexCount) { + m_execModeInfo.putIns (spv::OpExecutionMode, 4); + m_execModeInfo.putWord(entryPointId); + m_execModeInfo.putWord(spv::ExecutionModeOutputVertices); + m_execModeInfo.putWord(vertexCount); + } + + + uint32_t SpirvModule::addDebugString( + const char* string) { + uint32_t resultId = this->allocateId(); + + m_debugNames.putIns (spv::OpString, + 2 + m_debugNames.strLen(string)); + m_debugNames.putWord(resultId); + m_debugNames.putStr (string); + return resultId; + } + + + void SpirvModule::setDebugSource( + spv::SourceLanguage language, + uint32_t version, + uint32_t file, + const char* source) { + uint32_t strLen = source != nullptr + ? m_debugNames.strLen(source) : 0; + + m_debugNames.putIns (spv::OpSource, 4 + strLen); + m_debugNames.putWord(language); + m_debugNames.putWord(version); + m_debugNames.putWord(file); + + if (source != nullptr) + m_debugNames.putStr(source); + } + + void SpirvModule::setDebugName( + uint32_t expressionId, + const char* debugName) { + m_debugNames.putIns (spv::OpName, 2 + m_debugNames.strLen(debugName)); + m_debugNames.putWord(expressionId); + m_debugNames.putStr (debugName); + } + + + void SpirvModule::setDebugMemberName( + uint32_t structId, + uint32_t memberId, + const char* debugName) { + m_debugNames.putIns (spv::OpMemberName, 3 + m_debugNames.strLen(debugName)); + m_debugNames.putWord(structId); + m_debugNames.putWord(memberId); + m_debugNames.putStr (debugName); + } + + + uint32_t SpirvModule::constBool( + bool v) { + return this->defConst(v + ? spv::OpConstantTrue + : spv::OpConstantFalse, + this->defBoolType(), + 0, nullptr); + } + + + uint32_t SpirvModule::consti32( + int32_t v) { + std::array data; + std::memcpy(data.data(), &v, sizeof(v)); + + return this->defConst( + spv::OpConstant, + this->defIntType(32, 1), + data.size(), + data.data()); + } + + + uint32_t SpirvModule::consti64( + int64_t v) { + std::array data; + std::memcpy(data.data(), &v, sizeof(v)); + + return this->defConst( + spv::OpConstant, + this->defIntType(64, 1), + data.size(), + data.data()); + } + + + uint32_t SpirvModule::constu32( + uint32_t v) { + std::array data; + std::memcpy(data.data(), &v, sizeof(v)); + + return this->defConst( + spv::OpConstant, + this->defIntType(32, 0), + data.size(), + data.data()); + } + + + uint32_t SpirvModule::constu64( + uint64_t v) { + std::array data; + std::memcpy(data.data(), &v, sizeof(v)); + + return this->defConst( + spv::OpConstant, + this->defIntType(64, 0), + data.size(), + data.data()); + } + + + uint32_t SpirvModule::constf32( + float v) { + std::array data; + std::memcpy(data.data(), &v, sizeof(v)); + + return this->defConst( + spv::OpConstant, + this->defFloatType(32), + data.size(), + data.data()); + } + + + uint32_t SpirvModule::constf64( + double v) { + std::array data; + std::memcpy(data.data(), &v, sizeof(v)); + + return this->defConst( + spv::OpConstant, + this->defFloatType(64), + data.size(), + data.data()); + } + + + uint32_t SpirvModule::constvec4i32( + int32_t x, + int32_t y, + int32_t z, + int32_t w) { + std::array args = {{ + this->consti32(x), this->consti32(y), + this->consti32(z), this->consti32(w), + }}; + + uint32_t scalarTypeId = this->defIntType(32, 1); + uint32_t vectorTypeId = this->defVectorType(scalarTypeId, 4); + + return this->constComposite(vectorTypeId, args.size(), args.data()); + } + + + uint32_t SpirvModule::constvec4b32( + bool x, + bool y, + bool z, + bool w) { + std::array args = {{ + this->constBool(x), this->constBool(y), + this->constBool(z), this->constBool(w), + }}; + + uint32_t scalarTypeId = this->defBoolType(); + uint32_t vectorTypeId = this->defVectorType(scalarTypeId, 4); + + return this->constComposite(vectorTypeId, args.size(), args.data()); + } + + + uint32_t SpirvModule::constvec4u32( + uint32_t x, + uint32_t y, + uint32_t z, + uint32_t w) { + std::array args = {{ + this->constu32(x), this->constu32(y), + this->constu32(z), this->constu32(w), + }}; + + uint32_t scalarTypeId = this->defIntType(32, 0); + uint32_t vectorTypeId = this->defVectorType(scalarTypeId, 4); + + return this->constComposite(vectorTypeId, args.size(), args.data()); + } + + + uint32_t SpirvModule::constvec2f32( + float x, + float y) { + std::array args = {{ + this->constf32(x), this->constf32(y), + }}; + + uint32_t scalarTypeId = this->defFloatType(32); + uint32_t vectorTypeId = this->defVectorType(scalarTypeId, 2); + + return this->constComposite(vectorTypeId, args.size(), args.data()); + } + + + uint32_t SpirvModule::constvec3f32( + float x, + float y, + float z) { + std::array args = {{ + this->constf32(x), this->constf32(y), + this->constf32(z), + }}; + + uint32_t scalarTypeId = this->defFloatType(32); + uint32_t vectorTypeId = this->defVectorType(scalarTypeId, 3); + + return this->constComposite(vectorTypeId, args.size(), args.data()); + } + + + uint32_t SpirvModule::constvec4f32( + float x, + float y, + float z, + float w) { + std::array args = {{ + this->constf32(x), this->constf32(y), + this->constf32(z), this->constf32(w), + }}; + + uint32_t scalarTypeId = this->defFloatType(32); + uint32_t vectorTypeId = this->defVectorType(scalarTypeId, 4); + + return this->constComposite(vectorTypeId, args.size(), args.data()); + } + + + uint32_t SpirvModule::constfReplicant( + float replicant, + uint32_t count) { + uint32_t value = this->constf32(replicant); + + std::array args = { value, value, value, value }; + + // Can't make a scalar composite. + if (count == 1) + return args[0]; + + uint32_t scalarTypeId = this->defFloatType(32); + uint32_t vectorTypeId = this->defVectorType(scalarTypeId, count); + + return this->constComposite(vectorTypeId, count, args.data()); + } + + + uint32_t SpirvModule::constbReplicant( + bool replicant, + uint32_t count) { + uint32_t value = this->constBool(replicant); + + std::array args = { value, value, value, value }; + + // Can't make a scalar composite. + if (count == 1) + return args[0]; + + uint32_t scalarTypeId = this->defBoolType(); + uint32_t vectorTypeId = this->defVectorType(scalarTypeId, count); + + return this->constComposite(vectorTypeId, count, args.data()); + } + + + uint32_t SpirvModule::constiReplicant( + int32_t replicant, + uint32_t count) { + uint32_t value = this->consti32(replicant); + + std::array args = { value, value, value, value }; + + // Can't make a scalar composite. + if (count == 1) + return args[0]; + + uint32_t scalarTypeId = this->defIntType(32, 1); + uint32_t vectorTypeId = this->defVectorType(scalarTypeId, count); + + return this->constComposite(vectorTypeId, count, args.data()); + } + + + uint32_t SpirvModule::constuReplicant( + int32_t replicant, + uint32_t count) { + uint32_t value = this->constu32(replicant); + + std::array args = { value, value, value, value }; + + // Can't make a scalar composite. + if (count == 1) + return args[0]; + + uint32_t scalarTypeId = this->defIntType(32, 0); + uint32_t vectorTypeId = this->defVectorType(scalarTypeId, count); + + return this->constComposite(vectorTypeId, count, args.data()); + } + + + uint32_t SpirvModule::constComposite( + uint32_t typeId, + uint32_t constCount, + const uint32_t* constIds) { + return this->defConst( + spv::OpConstantComposite, + typeId, constCount, constIds); + } + + + uint32_t SpirvModule::constUndef( + uint32_t typeId) { + return this->defConst(spv::OpUndef, + typeId, 0, nullptr); + } + + + uint32_t SpirvModule::lateConst32( + uint32_t typeId) { + uint32_t resultId = this->allocateId(); + m_lateConsts.insert(resultId); + + m_typeConstDefs.putIns (spv::OpConstant, 4); + m_typeConstDefs.putWord(typeId); + m_typeConstDefs.putWord(resultId); + m_typeConstDefs.putWord(0); + return resultId; + } + + + void SpirvModule::setLateConst( + uint32_t constId, + const uint32_t* argIds) { + for (auto ins : m_typeConstDefs) { + if (ins.opCode() != spv::OpConstant + && ins.opCode() != spv::OpConstantComposite) + continue; + + if (ins.arg(2) != constId) + continue; + + for (uint32_t i = 3; i < ins.length(); i++) + ins.setArg(i, argIds[i - 3]); + + return; + } + } + + + uint32_t SpirvModule::specConstBool( + bool v) { + uint32_t typeId = this->defBoolType(); + uint32_t resultId = this->allocateId(); + + const spv::Op op = v + ? spv::OpSpecConstantTrue + : spv::OpSpecConstantFalse; + + m_typeConstDefs.putIns (op, 3); + m_typeConstDefs.putWord (typeId); + m_typeConstDefs.putWord (resultId); + return resultId; + } + + + uint32_t SpirvModule::specConst32( + uint32_t typeId, + uint32_t value) { + uint32_t resultId = this->allocateId(); + + m_typeConstDefs.putIns (spv::OpSpecConstant, 4); + m_typeConstDefs.putWord (typeId); + m_typeConstDefs.putWord (resultId); + m_typeConstDefs.putWord (value); + return resultId; + } + + + void SpirvModule::decorate( + uint32_t object, + spv::Decoration decoration) { + m_annotations.putIns (spv::OpDecorate, 3); + m_annotations.putWord (object); + m_annotations.putWord (decoration); + } + + + void SpirvModule::decorateArrayStride( + uint32_t object, + uint32_t stride) { + m_annotations.putIns (spv::OpDecorate, 4); + m_annotations.putWord (object); + m_annotations.putWord (spv::DecorationArrayStride); + m_annotations.putInt32(stride); + } + + + void SpirvModule::decorateBinding( + uint32_t object, + uint32_t binding) { + m_annotations.putIns (spv::OpDecorate, 4); + m_annotations.putWord (object); + m_annotations.putWord (spv::DecorationBinding); + m_annotations.putInt32(binding); + } + + + void SpirvModule::decorateBlock(uint32_t object) { + m_annotations.putIns (spv::OpDecorate, 3); + m_annotations.putWord (object); + m_annotations.putWord (spv::DecorationBlock); + } + + + void SpirvModule::decorateBuiltIn( + uint32_t object, + spv::BuiltIn builtIn) { + m_annotations.putIns (spv::OpDecorate, 4); + m_annotations.putWord (object); + m_annotations.putWord (spv::DecorationBuiltIn); + m_annotations.putWord (builtIn); + } + + + void SpirvModule::decorateComponent( + uint32_t object, + uint32_t location) { + m_annotations.putIns (spv::OpDecorate, 4); + m_annotations.putWord (object); + m_annotations.putWord (spv::DecorationComponent); + m_annotations.putInt32(location); + } + + + void SpirvModule::decorateDescriptorSet( + uint32_t object, + uint32_t set) { + m_annotations.putIns (spv::OpDecorate, 4); + m_annotations.putWord (object); + m_annotations.putWord (spv::DecorationDescriptorSet); + m_annotations.putInt32(set); + } + + + void SpirvModule::decorateIndex( + uint32_t object, + uint32_t index) { + m_annotations.putIns (spv::OpDecorate, 4); + m_annotations.putWord (object); + m_annotations.putWord (spv::DecorationIndex); + m_annotations.putInt32(index); + } + + + void SpirvModule::decorateLocation( + uint32_t object, + uint32_t location) { + m_annotations.putIns (spv::OpDecorate, 4); + m_annotations.putWord (object); + m_annotations.putWord (spv::DecorationLocation); + m_annotations.putInt32(location); + } + + + void SpirvModule::decorateSpecId( + uint32_t object, + uint32_t specId) { + m_annotations.putIns (spv::OpDecorate, 4); + m_annotations.putWord (object); + m_annotations.putWord (spv::DecorationSpecId); + m_annotations.putInt32(specId); + } + + + void SpirvModule::decorateXfb( + uint32_t object, + uint32_t streamId, + uint32_t bufferId, + uint32_t offset, + uint32_t stride) { + m_annotations.putIns (spv::OpDecorate, 4); + m_annotations.putWord (object); + m_annotations.putWord (spv::DecorationStream); + m_annotations.putInt32(streamId); + + m_annotations.putIns (spv::OpDecorate, 4); + m_annotations.putWord (object); + m_annotations.putWord (spv::DecorationXfbBuffer); + m_annotations.putInt32(bufferId); + + m_annotations.putIns (spv::OpDecorate, 4); + m_annotations.putWord (object); + m_annotations.putWord (spv::DecorationXfbStride); + m_annotations.putInt32(stride); + + m_annotations.putIns (spv::OpDecorate, 4); + m_annotations.putWord (object); + m_annotations.putWord (spv::DecorationOffset); + m_annotations.putInt32(offset); + } + + + void SpirvModule::memberDecorateBuiltIn( + uint32_t structId, + uint32_t memberId, + spv::BuiltIn builtIn) { + m_annotations.putIns (spv::OpMemberDecorate, 5); + m_annotations.putWord (structId); + m_annotations.putWord (memberId); + m_annotations.putWord (spv::DecorationBuiltIn); + m_annotations.putWord (builtIn); + } + + + void SpirvModule::memberDecorate( + uint32_t structId, + uint32_t memberId, + spv::Decoration decoration) { + m_annotations.putIns (spv::OpMemberDecorate, 4); + m_annotations.putWord (structId); + m_annotations.putWord (memberId); + m_annotations.putWord (decoration); + } + + + void SpirvModule::memberDecorateMatrixStride( + uint32_t structId, + uint32_t memberId, + uint32_t stride) { + m_annotations.putIns (spv::OpMemberDecorate, 5); + m_annotations.putWord (structId); + m_annotations.putWord (memberId); + m_annotations.putWord (spv::DecorationMatrixStride); + m_annotations.putWord (stride); + } + + + void SpirvModule::memberDecorateOffset( + uint32_t structId, + uint32_t memberId, + uint32_t offset) { + m_annotations.putIns (spv::OpMemberDecorate, 5); + m_annotations.putWord (structId); + m_annotations.putWord (memberId); + m_annotations.putWord (spv::DecorationOffset); + m_annotations.putWord (offset); + } + + + uint32_t SpirvModule::defVoidType() { + return this->defType(spv::OpTypeVoid, 0, nullptr); + } + + + uint32_t SpirvModule::defBoolType() { + return this->defType(spv::OpTypeBool, 0, nullptr); + } + + + uint32_t SpirvModule::defIntType( + uint32_t width, + uint32_t isSigned) { + std::array args = {{ width, isSigned }}; + return this->defType(spv::OpTypeInt, + args.size(), args.data()); + } + + + uint32_t SpirvModule::defFloatType( + uint32_t width) { + std::array args = {{ width }}; + return this->defType(spv::OpTypeFloat, + args.size(), args.data()); + } + + + uint32_t SpirvModule::defVectorType( + uint32_t elementType, + uint32_t elementCount) { + std::array args = + {{ elementType, elementCount }}; + + return this->defType(spv::OpTypeVector, + args.size(), args.data()); + } + + + uint32_t SpirvModule::defMatrixType( + uint32_t columnType, + uint32_t columnCount) { + std::array args = + {{ columnType, columnCount }}; + + return this->defType(spv::OpTypeMatrix, + args.size(), args.data()); + } + + + uint32_t SpirvModule::defArrayType( + uint32_t typeId, + uint32_t length) { + std::array args = {{ typeId, length }}; + + return this->defType(spv::OpTypeArray, + args.size(), args.data()); + } + + + uint32_t SpirvModule::defArrayTypeUnique( + uint32_t typeId, + uint32_t length) { + uint32_t resultId = this->allocateId(); + + m_typeConstDefs.putIns (spv::OpTypeArray, 4); + m_typeConstDefs.putWord(resultId); + m_typeConstDefs.putWord(typeId); + m_typeConstDefs.putWord(length); + return resultId; + } + + + uint32_t SpirvModule::defRuntimeArrayType( + uint32_t typeId) { + std::array args = { typeId }; + + return this->defType(spv::OpTypeRuntimeArray, + args.size(), args.data()); + } + + + uint32_t SpirvModule::defRuntimeArrayTypeUnique( + uint32_t typeId) { + uint32_t resultId = this->allocateId(); + + m_typeConstDefs.putIns (spv::OpTypeRuntimeArray, 3); + m_typeConstDefs.putWord(resultId); + m_typeConstDefs.putWord(typeId); + return resultId; + } + + + uint32_t SpirvModule::defFunctionType( + uint32_t returnType, + uint32_t argCount, + const uint32_t* argTypes) { + std::vector args; + args.push_back(returnType); + + for (uint32_t i = 0; i < argCount; i++) + args.push_back(argTypes[i]); + + return this->defType(spv::OpTypeFunction, + args.size(), args.data()); + } + + + uint32_t SpirvModule::defStructType( + uint32_t memberCount, + const uint32_t* memberTypes) { + return this->defType(spv::OpTypeStruct, + memberCount, memberTypes); + } + + + uint32_t SpirvModule::defStructTypeUnique( + uint32_t memberCount, + const uint32_t* memberTypes) { + uint32_t resultId = this->allocateId(); + + m_typeConstDefs.putIns (spv::OpTypeStruct, 2 + memberCount); + m_typeConstDefs.putWord(resultId); + + for (uint32_t i = 0; i < memberCount; i++) + m_typeConstDefs.putWord(memberTypes[i]); + return resultId; + } + + + uint32_t SpirvModule::defPointerType( + uint32_t variableType, + spv::StorageClass storageClass) { + std::array args = {{ + static_cast(storageClass), + variableType, + }}; + + return this->defType(spv::OpTypePointer, + args.size(), args.data()); + } + + + uint32_t SpirvModule::defSamplerType() { + return this->defType(spv::OpTypeSampler, 0, nullptr); + } + + + uint32_t SpirvModule::defImageType( + uint32_t sampledType, + spv::Dim dimensionality, + uint32_t depth, + uint32_t arrayed, + uint32_t multisample, + uint32_t sampled, + spv::ImageFormat format) { + std::array args = {{ + sampledType, + static_cast(dimensionality), + depth, arrayed, + multisample, + sampled, + static_cast(format) + }}; + + return this->defType(spv::OpTypeImage, + args.size(), args.data()); + } + + + uint32_t SpirvModule::defSampledImageType( + uint32_t imageType) { + return this->defType(spv::OpTypeSampledImage, 1, &imageType); + } + + + uint32_t SpirvModule::newVar( + uint32_t pointerType, + spv::StorageClass storageClass) { + uint32_t resultId = this->allocateId(); + + auto& code = storageClass != spv::StorageClassFunction + ? m_variables : m_code; + + code.putIns (spv::OpVariable, 4); + code.putWord (pointerType); + code.putWord (resultId); + code.putWord (storageClass); + return resultId; + } + + + uint32_t SpirvModule::newVarInit( + uint32_t pointerType, + spv::StorageClass storageClass, + uint32_t initialValue) { + uint32_t resultId = this->allocateId(); + + auto& code = storageClass != spv::StorageClassFunction + ? m_variables : m_code; + + code.putIns (spv::OpVariable, 5); + code.putWord (pointerType); + code.putWord (resultId); + code.putWord (storageClass); + code.putWord (initialValue); + return resultId; + } + + + void SpirvModule::functionBegin( + uint32_t returnType, + uint32_t functionId, + uint32_t functionType, + spv::FunctionControlMask functionControl) { + m_code.putIns (spv::OpFunction, 5); + m_code.putWord(returnType); + m_code.putWord(functionId); + m_code.putWord(functionControl); + m_code.putWord(functionType); + } + + + uint32_t SpirvModule::functionParameter( + uint32_t parameterType) { + uint32_t parameterId = this->allocateId(); + + m_code.putIns (spv::OpFunctionParameter, 3); + m_code.putWord(parameterType); + m_code.putWord(parameterId); + return parameterId; + } + + + void SpirvModule::functionEnd() { + m_code.putIns (spv::OpFunctionEnd, 1); + } + + + uint32_t SpirvModule::opAccessChain( + uint32_t resultType, + uint32_t composite, + uint32_t indexCount, + const uint32_t* indexArray) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpAccessChain, 4 + indexCount); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(composite); + + for (uint32_t i = 0; i < indexCount; i++) + m_code.putInt32(indexArray[i]); + return resultId; + } + + + uint32_t SpirvModule::opArrayLength( + uint32_t resultType, + uint32_t structure, + uint32_t memberId) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpArrayLength, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(structure); + m_code.putWord(memberId); + return resultId; + } + + + uint32_t SpirvModule::opAny( + uint32_t resultType, + uint32_t vector) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpAny, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector); + return resultId; + } + + + uint32_t SpirvModule::opAll( + uint32_t resultType, + uint32_t vector) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpAll, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector); + return resultId; + } + + + uint32_t SpirvModule::opAtomicLoad( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpAtomicLoad, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(pointer); + m_code.putWord(scope); + m_code.putWord(semantics); + return resultId; + } + + + void SpirvModule::opAtomicStore( + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value) { + m_code.putIns (spv::OpAtomicStore, 5); + m_code.putWord(pointer); + m_code.putWord(scope); + m_code.putWord(semantics); + m_code.putWord(value); + } + + + uint32_t SpirvModule::opAtomicExchange( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpAtomicExchange, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(pointer); + m_code.putWord(scope); + m_code.putWord(semantics); + m_code.putWord(value); + return resultId; + } + + + uint32_t SpirvModule::opAtomicCompareExchange( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t equal, + uint32_t unequal, + uint32_t value, + uint32_t comparator) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpAtomicCompareExchange, 9); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(pointer); + m_code.putWord(scope); + m_code.putWord(equal); + m_code.putWord(unequal); + m_code.putWord(value); + m_code.putWord(comparator); + return resultId; + } + + + uint32_t SpirvModule::opAtomicIIncrement( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpAtomicIIncrement, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(pointer); + m_code.putWord(scope); + m_code.putWord(semantics); + return resultId; + } + + + uint32_t SpirvModule::opAtomicIDecrement( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpAtomicIDecrement, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(pointer); + m_code.putWord(scope); + m_code.putWord(semantics); + return resultId; + } + + + uint32_t SpirvModule::opAtomicIAdd( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpAtomicIAdd, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(pointer); + m_code.putWord(scope); + m_code.putWord(semantics); + m_code.putWord(value); + return resultId; + } + + + uint32_t SpirvModule::opAtomicISub( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpAtomicISub, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(pointer); + m_code.putWord(scope); + m_code.putWord(semantics); + m_code.putWord(value); + return resultId; + } + + + uint32_t SpirvModule::opAtomicSMin( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpAtomicSMin, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(pointer); + m_code.putWord(scope); + m_code.putWord(semantics); + m_code.putWord(value); + return resultId; + } + + + uint32_t SpirvModule::opAtomicSMax( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpAtomicSMax, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(pointer); + m_code.putWord(scope); + m_code.putWord(semantics); + m_code.putWord(value); + return resultId; + } + + + uint32_t SpirvModule::opAtomicUMin( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpAtomicUMin, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(pointer); + m_code.putWord(scope); + m_code.putWord(semantics); + m_code.putWord(value); + return resultId; + } + + + uint32_t SpirvModule::opAtomicUMax( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpAtomicUMax, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(pointer); + m_code.putWord(scope); + m_code.putWord(semantics); + m_code.putWord(value); + return resultId; + } + + + uint32_t SpirvModule::opAtomicAnd( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpAtomicAnd, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(pointer); + m_code.putWord(scope); + m_code.putWord(semantics); + m_code.putWord(value); + return resultId; + } + + + uint32_t SpirvModule::opAtomicOr( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpAtomicOr, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(pointer); + m_code.putWord(scope); + m_code.putWord(semantics); + m_code.putWord(value); + return resultId; + } + + + uint32_t SpirvModule::opAtomicXor( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpAtomicXor, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(pointer); + m_code.putWord(scope); + m_code.putWord(semantics); + m_code.putWord(value); + return resultId; + } + + + uint32_t SpirvModule::opBitcast( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpBitcast, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opBitCount( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpBitCount, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opBitReverse( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpBitReverse, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opFindILsb( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450FindILsb); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opFindUMsb( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450FindUMsb); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opFindSMsb( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450FindSMsb); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opBitFieldInsert( + uint32_t resultType, + uint32_t base, + uint32_t insert, + uint32_t offset, + uint32_t count) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpBitFieldInsert, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(base); + m_code.putWord(insert); + m_code.putWord(offset); + m_code.putWord(count); + return resultId; + } + + + uint32_t SpirvModule::opBitFieldSExtract( + uint32_t resultType, + uint32_t base, + uint32_t offset, + uint32_t count) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpBitFieldSExtract, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(base); + m_code.putWord(offset); + m_code.putWord(count); + return resultId; + } + + + uint32_t SpirvModule::opBitFieldUExtract( + uint32_t resultType, + uint32_t base, + uint32_t offset, + uint32_t count) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpBitFieldUExtract, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(base); + m_code.putWord(offset); + m_code.putWord(count); + return resultId; + } + + + uint32_t SpirvModule::opBitwiseAnd( + uint32_t resultType, + uint32_t operand1, + uint32_t operand2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpBitwiseAnd, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand1); + m_code.putWord(operand2); + return resultId; + } + + + uint32_t SpirvModule::opBitwiseOr( + uint32_t resultType, + uint32_t operand1, + uint32_t operand2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpBitwiseOr, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand1); + m_code.putWord(operand2); + return resultId; + } + + + uint32_t SpirvModule::opBitwiseXor( + uint32_t resultType, + uint32_t operand1, + uint32_t operand2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpBitwiseXor, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand1); + m_code.putWord(operand2); + return resultId; + } + + + uint32_t SpirvModule::opNot( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpNot, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opShiftLeftLogical( + uint32_t resultType, + uint32_t base, + uint32_t shift) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpShiftLeftLogical, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(base); + m_code.putWord(shift); + return resultId; + } + + + uint32_t SpirvModule::opShiftRightArithmetic( + uint32_t resultType, + uint32_t base, + uint32_t shift) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpShiftRightArithmetic, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(base); + m_code.putWord(shift); + return resultId; + } + + + uint32_t SpirvModule::opShiftRightLogical( + uint32_t resultType, + uint32_t base, + uint32_t shift) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpShiftRightLogical, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(base); + m_code.putWord(shift); + return resultId; + } + + + uint32_t SpirvModule::opConvertFtoS( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpConvertFToS, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opConvertFtoU( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpConvertFToU, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opConvertStoF( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpConvertSToF, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opConvertUtoF( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpConvertUToF, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opCompositeConstruct( + uint32_t resultType, + uint32_t valueCount, + const uint32_t* valueArray) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpCompositeConstruct, 3 + valueCount); + m_code.putWord(resultType); + m_code.putWord(resultId); + + for (uint32_t i = 0; i < valueCount; i++) + m_code.putWord(valueArray[i]); + return resultId; + } + + + uint32_t SpirvModule::opCompositeExtract( + uint32_t resultType, + uint32_t composite, + uint32_t indexCount, + const uint32_t* indexArray) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpCompositeExtract, 4 + indexCount); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(composite); + + for (uint32_t i = 0; i < indexCount; i++) + m_code.putInt32(indexArray[i]); + return resultId; + } + + + uint32_t SpirvModule::opCompositeInsert( + uint32_t resultType, + uint32_t object, + uint32_t composite, + uint32_t indexCount, + const uint32_t* indexArray) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpCompositeInsert, 5 + indexCount); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(object); + m_code.putWord(composite); + + for (uint32_t i = 0; i < indexCount; i++) + m_code.putInt32(indexArray[i]); + return resultId; + } + + + uint32_t SpirvModule::opDpdx( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpDPdx, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opDpdy( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpDPdy, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opDpdxCoarse( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpDPdxCoarse, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opDpdyCoarse( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpDPdyCoarse, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opDpdxFine( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpDPdxFine, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opDpdyFine( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpDPdyFine, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opVectorExtractDynamic( + uint32_t resultType, + uint32_t vector, + uint32_t index) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpVectorExtractDynamic, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector); + m_code.putWord(index); + return resultId; + } + + + uint32_t SpirvModule::opVectorShuffle( + uint32_t resultType, + uint32_t vectorLeft, + uint32_t vectorRight, + uint32_t indexCount, + const uint32_t* indexArray) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpVectorShuffle, 5 + indexCount); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vectorLeft); + m_code.putWord(vectorRight); + + for (uint32_t i = 0; i < indexCount; i++) + m_code.putInt32(indexArray[i]); + return resultId; + } + + + uint32_t SpirvModule::opSNegate( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpSNegate, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opFNegate( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpFNegate, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opSAbs( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450SAbs); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opFAbs( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450FAbs); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opFSign( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450FSign); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opFMix( + uint32_t resultType, + uint32_t x, + uint32_t y, + uint32_t a) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 8); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450FMix); + m_code.putWord(x); + m_code.putWord(y); + m_code.putWord(a); + return resultId; + } + + + uint32_t SpirvModule::opCross( + uint32_t resultType, + uint32_t x, + uint32_t y) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Cross); + m_code.putWord(x); + m_code.putWord(y); + return resultId; + } + + + uint32_t SpirvModule::opIAdd( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpIAdd, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opISub( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpISub, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opFAdd( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpFAdd, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opFSub( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpFSub, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opSDiv( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpSDiv, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opUDiv( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpUDiv, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opSRem( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpSRem, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opUMod( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpUMod, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opFDiv( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpFDiv, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opIMul( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpIMul, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opFMul( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpFMul, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opVectorTimesScalar( + uint32_t resultType, + uint32_t vector, + uint32_t scalar) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpVectorTimesScalar, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector); + m_code.putWord(scalar); + return resultId; + } + + + uint32_t SpirvModule::opMatrixTimesMatrix( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpMatrixTimesMatrix, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opMatrixTimesVector( + uint32_t resultType, + uint32_t matrix, + uint32_t vector) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpMatrixTimesVector, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(matrix); + m_code.putWord(vector); + return resultId; + } + + + uint32_t SpirvModule::opVectorTimesMatrix( + uint32_t resultType, + uint32_t vector, + uint32_t matrix) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpVectorTimesMatrix, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector); + m_code.putWord(matrix); + return resultId; + } + + + uint32_t SpirvModule::opTranspose( + uint32_t resultType, + uint32_t matrix) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpTranspose, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(matrix); + return resultId; + } + + + uint32_t SpirvModule::opInverse( + uint32_t resultType, + uint32_t matrix) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450MatrixInverse); + m_code.putWord(matrix); + return resultId; + } + + + uint32_t SpirvModule::opFFma( + uint32_t resultType, + uint32_t a, + uint32_t b, + uint32_t c) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 8); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Fma); + m_code.putWord(a); + m_code.putWord(b); + m_code.putWord(c); + return resultId; + } + + + uint32_t SpirvModule::opFMax( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450FMax); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opFMin( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450FMin); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opNMax( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450NMax); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opNMin( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450NMin); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opSMax( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450SMax); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opSMin( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450SMin); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opUMax( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450UMax); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opUMin( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450UMin); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opFClamp( + uint32_t resultType, + uint32_t x, + uint32_t minVal, + uint32_t maxVal) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 8); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450FClamp); + m_code.putWord(x); + m_code.putWord(minVal); + m_code.putWord(maxVal); + return resultId; + } + + + uint32_t SpirvModule::opNClamp( + uint32_t resultType, + uint32_t x, + uint32_t minVal, + uint32_t maxVal) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 8); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450NClamp); + m_code.putWord(x); + m_code.putWord(minVal); + m_code.putWord(maxVal); + return resultId; + } + + + uint32_t SpirvModule::opIEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpIEqual, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector1); + m_code.putWord(vector2); + return resultId; + } + + + uint32_t SpirvModule::opINotEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpINotEqual, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector1); + m_code.putWord(vector2); + return resultId; + } + + + uint32_t SpirvModule::opSLessThan( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpSLessThan, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector1); + m_code.putWord(vector2); + return resultId; + } + + + uint32_t SpirvModule::opSLessThanEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpSLessThanEqual, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector1); + m_code.putWord(vector2); + return resultId; + } + + + uint32_t SpirvModule::opSGreaterThan( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpSGreaterThan, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector1); + m_code.putWord(vector2); + return resultId; + } + + + uint32_t SpirvModule::opSGreaterThanEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpSGreaterThanEqual, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector1); + m_code.putWord(vector2); + return resultId; + } + + + uint32_t SpirvModule::opULessThan( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpULessThan, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector1); + m_code.putWord(vector2); + return resultId; + } + + + uint32_t SpirvModule::opULessThanEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpULessThanEqual, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector1); + m_code.putWord(vector2); + return resultId; + } + + + uint32_t SpirvModule::opUGreaterThan( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpUGreaterThan, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector1); + m_code.putWord(vector2); + return resultId; + } + + + uint32_t SpirvModule::opUGreaterThanEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpUGreaterThanEqual, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector1); + m_code.putWord(vector2); + return resultId; + } + + + uint32_t SpirvModule::opFOrdEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpFOrdEqual, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector1); + m_code.putWord(vector2); + return resultId; + } + + + uint32_t SpirvModule::opFOrdNotEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpFOrdNotEqual, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector1); + m_code.putWord(vector2); + return resultId; + } + + + uint32_t SpirvModule::opFOrdLessThan( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpFOrdLessThan, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector1); + m_code.putWord(vector2); + return resultId; + } + + + uint32_t SpirvModule::opFOrdLessThanEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpFOrdLessThanEqual, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector1); + m_code.putWord(vector2); + return resultId; + } + + + uint32_t SpirvModule::opFOrdGreaterThan( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpFOrdGreaterThan, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector1); + m_code.putWord(vector2); + return resultId; + } + + + uint32_t SpirvModule::opFOrdGreaterThanEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpFOrdGreaterThanEqual, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector1); + m_code.putWord(vector2); + return resultId; + } + + + uint32_t SpirvModule::opLogicalEqual( + uint32_t resultType, + uint32_t operand1, + uint32_t operand2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpLogicalEqual, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand1); + m_code.putWord(operand2); + return resultId; + } + + + uint32_t SpirvModule::opLogicalNotEqual( + uint32_t resultType, + uint32_t operand1, + uint32_t operand2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpLogicalNotEqual, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand1); + m_code.putWord(operand2); + return resultId; + } + + + uint32_t SpirvModule::opLogicalAnd( + uint32_t resultType, + uint32_t operand1, + uint32_t operand2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpLogicalAnd, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand1); + m_code.putWord(operand2); + return resultId; + } + + + uint32_t SpirvModule::opLogicalOr( + uint32_t resultType, + uint32_t operand1, + uint32_t operand2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpLogicalOr, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand1); + m_code.putWord(operand2); + return resultId; + } + + + uint32_t SpirvModule::opLogicalNot( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpLogicalNot, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opDot( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpDot, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector1); + m_code.putWord(vector2); + return resultId; + } + + + uint32_t SpirvModule::opSin( + uint32_t resultType, + uint32_t vector) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Sin); + m_code.putWord(vector); + return resultId; + } + + + uint32_t SpirvModule::opCos( + uint32_t resultType, + uint32_t vector) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Cos); + m_code.putWord(vector); + return resultId; + } + + + uint32_t SpirvModule::opSqrt( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Sqrt); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opInverseSqrt( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450InverseSqrt); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opNormalize( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Normalize); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opReflect( + uint32_t resultType, + uint32_t incident, + uint32_t normal) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Reflect); + m_code.putWord(incident); + m_code.putWord(normal); + return resultId; + } + + + uint32_t SpirvModule::opLength( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Length); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opExp2( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Exp2); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opExp( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Exp); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opLog2( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Log2); + m_code.putWord(operand); + return resultId; + } + + uint32_t SpirvModule::opPow( + uint32_t resultType, + uint32_t base, + uint32_t exponent) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpExtInst, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Pow); + m_code.putWord(base); + m_code.putWord(exponent); + return resultId; + } + + uint32_t SpirvModule::opFract( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Fract); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opCeil( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Ceil); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opFloor( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Floor); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opRound( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Round); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opRoundEven( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450RoundEven); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opTrunc( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Trunc); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opFConvert( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpFConvert, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opPackHalf2x16( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450PackHalf2x16); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opUnpackHalf2x16( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450UnpackHalf2x16); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opSelect( + uint32_t resultType, + uint32_t condition, + uint32_t operand1, + uint32_t operand2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpSelect, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(condition); + m_code.putWord(operand1); + m_code.putWord(operand2); + return resultId; + } + + + uint32_t SpirvModule::opIsNan( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpIsNan, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opIsInf( + uint32_t resultType, + uint32_t operand) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpIsInf, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(operand); + return resultId; + } + + + uint32_t SpirvModule::opFunctionCall( + uint32_t resultType, + uint32_t functionId, + uint32_t argCount, + const uint32_t* argIds) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpFunctionCall, 4 + argCount); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(functionId); + + for (uint32_t i = 0; i < argCount; i++) + m_code.putWord(argIds[i]); + return resultId; + } + + + void SpirvModule::opLabel(uint32_t labelId) { + m_code.putIns (spv::OpLabel, 2); + m_code.putWord(labelId); + } + + + uint32_t SpirvModule::opLoad( + uint32_t typeId, + uint32_t pointerId) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpLoad, 4); + m_code.putWord(typeId); + m_code.putWord(resultId); + m_code.putWord(pointerId); + return resultId; + } + + + void SpirvModule::opStore( + uint32_t pointerId, + uint32_t valueId) { + m_code.putIns (spv::OpStore, 3); + m_code.putWord(pointerId); + m_code.putWord(valueId); + } + + + uint32_t SpirvModule::opInterpolateAtCentroid( + uint32_t resultType, + uint32_t interpolant) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450InterpolateAtCentroid); + m_code.putWord(interpolant); + return resultId; + } + + + uint32_t SpirvModule::opInterpolateAtSample( + uint32_t resultType, + uint32_t interpolant, + uint32_t sample) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450InterpolateAtSample); + m_code.putWord(interpolant); + m_code.putWord(sample); + return resultId; + } + + + uint32_t SpirvModule::opInterpolateAtOffset( + uint32_t resultType, + uint32_t interpolant, + uint32_t offset) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450InterpolateAtOffset); + m_code.putWord(interpolant); + m_code.putWord(offset); + return resultId; + } + + + uint32_t SpirvModule::opImage( + uint32_t resultType, + uint32_t sampledImage) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpImage, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(sampledImage); + return resultId; + } + + + uint32_t SpirvModule::opImageRead( + uint32_t resultType, + uint32_t image, + uint32_t coordinates, + const SpirvImageOperands& operands) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpImageRead, + 5 + getImageOperandWordCount(operands)); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(image); + m_code.putWord(coordinates); + + putImageOperands(operands); + return resultId; + } + + + void SpirvModule::opImageWrite( + uint32_t image, + uint32_t coordinates, + uint32_t texel, + const SpirvImageOperands& operands) { + m_code.putIns (spv::OpImageWrite, + 4 + getImageOperandWordCount(operands)); + m_code.putWord(image); + m_code.putWord(coordinates); + m_code.putWord(texel); + + putImageOperands(operands); + } + + + uint32_t SpirvModule::opSampledImage( + uint32_t resultType, + uint32_t image, + uint32_t sampler) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpSampledImage, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(image); + m_code.putWord(sampler); + return resultId; + } + + + uint32_t SpirvModule::opImageTexelPointer( + uint32_t resultType, + uint32_t image, + uint32_t coordinates, + uint32_t sample) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpImageTexelPointer, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(image); + m_code.putWord(coordinates); + m_code.putWord(sample); + return resultId; + } + + + uint32_t SpirvModule::opImageQuerySizeLod( + uint32_t resultType, + uint32_t image, + uint32_t lod) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpImageQuerySizeLod, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(image); + m_code.putWord(lod); + return resultId; + } + + + uint32_t SpirvModule::opImageQuerySize( + uint32_t resultType, + uint32_t image) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpImageQuerySize, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(image); + return resultId; + } + + + uint32_t SpirvModule::opImageQueryLevels( + uint32_t resultType, + uint32_t image) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpImageQueryLevels, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(image); + return resultId; + } + + + uint32_t SpirvModule::opImageQueryLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpImageQueryLod, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(sampledImage); + m_code.putWord(coordinates); + return resultId; + } + + + uint32_t SpirvModule::opImageQuerySamples( + uint32_t resultType, + uint32_t image) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpImageQuerySamples, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(image); + return resultId; + } + + + uint32_t SpirvModule::opImageFetch( + uint32_t resultType, + uint32_t image, + uint32_t coordinates, + const SpirvImageOperands& operands) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpImageFetch, + 5 + getImageOperandWordCount(operands)); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(image); + m_code.putWord(coordinates); + + putImageOperands(operands); + return resultId; + } + + + uint32_t SpirvModule::opImageGather( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + uint32_t component, + const SpirvImageOperands& operands) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpImageGather, + 6 + getImageOperandWordCount(operands)); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(sampledImage); + m_code.putWord(coordinates); + m_code.putWord(component); + + putImageOperands(operands); + return resultId; + } + + + uint32_t SpirvModule::opImageDrefGather( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + uint32_t reference, + const SpirvImageOperands& operands) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpImageDrefGather, + 6 + getImageOperandWordCount(operands)); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(sampledImage); + m_code.putWord(coordinates); + m_code.putWord(reference); + + putImageOperands(operands); + return resultId; + } + + + uint32_t SpirvModule::opImageSampleImplicitLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + const SpirvImageOperands& operands) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpImageSampleImplicitLod, + 5 + getImageOperandWordCount(operands)); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(sampledImage); + m_code.putWord(coordinates); + + putImageOperands(operands); + return resultId; + } + + + uint32_t SpirvModule::opImageSampleExplicitLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + const SpirvImageOperands& operands) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpImageSampleExplicitLod, + 5 + getImageOperandWordCount(operands)); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(sampledImage); + m_code.putWord(coordinates); + + putImageOperands(operands); + return resultId; + } + + + uint32_t SpirvModule::opImageSampleProjImplicitLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + const SpirvImageOperands& operands) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpImageSampleProjImplicitLod, + 5 + getImageOperandWordCount(operands)); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(sampledImage); + m_code.putWord(coordinates); + + putImageOperands(operands); + return resultId; + } + + + uint32_t SpirvModule::opImageSampleProjExplicitLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + const SpirvImageOperands& operands) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpImageSampleProjExplicitLod, + 5 + getImageOperandWordCount(operands)); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(sampledImage); + m_code.putWord(coordinates); + + putImageOperands(operands); + return resultId; + } + + + uint32_t SpirvModule::opImageSampleDrefImplicitLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + uint32_t reference, + const SpirvImageOperands& operands) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpImageSampleDrefImplicitLod, + 6 + getImageOperandWordCount(operands)); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(sampledImage); + m_code.putWord(coordinates); + m_code.putWord(reference); + + putImageOperands(operands); + return resultId; + } + + + uint32_t SpirvModule::opImageSampleDrefExplicitLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + uint32_t reference, + const SpirvImageOperands& operands) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpImageSampleDrefExplicitLod, + 6 + getImageOperandWordCount(operands)); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(sampledImage); + m_code.putWord(coordinates); + m_code.putWord(reference); + + putImageOperands(operands); + return resultId; + } + + + uint32_t SpirvModule::opImageSampleProjDrefImplicitLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + uint32_t reference, + const SpirvImageOperands& operands) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpImageSampleProjDrefImplicitLod, + 6 + getImageOperandWordCount(operands)); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(sampledImage); + m_code.putWord(coordinates); + m_code.putWord(reference); + + putImageOperands(operands); + return resultId; + } + + + uint32_t SpirvModule::opImageSampleProjDrefExplicitLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + uint32_t reference, + const SpirvImageOperands& operands) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpImageSampleProjDrefExplicitLod, + 6 + getImageOperandWordCount(operands)); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(sampledImage); + m_code.putWord(coordinates); + m_code.putWord(reference); + + putImageOperands(operands); + return resultId; + } + + + uint32_t SpirvModule::opGroupNonUniformBallot( + uint32_t resultType, + uint32_t execution, + uint32_t predicate) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpGroupNonUniformBallot, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(execution); + m_code.putWord(predicate); + return resultId; + } + + + uint32_t SpirvModule::opGroupNonUniformBallotBitCount( + uint32_t resultType, + uint32_t execution, + uint32_t operation, + uint32_t ballot) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpGroupNonUniformBallotBitCount, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(execution); + m_code.putWord(operation); + m_code.putWord(ballot); + return resultId; + } + + + uint32_t SpirvModule::opGroupNonUniformElect( + uint32_t resultType, + uint32_t execution) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpGroupNonUniformElect, 4); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(execution); + return resultId; + } + + + uint32_t SpirvModule::opGroupNonUniformBroadcastFirst( + uint32_t resultType, + uint32_t execution, + uint32_t value) { + uint32_t resultId = this->allocateId(); + + m_code.putIns(spv::OpGroupNonUniformBroadcastFirst, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(execution); + m_code.putWord(value); + return resultId; + } + + + void SpirvModule::opControlBarrier( + uint32_t execution, + uint32_t memory, + uint32_t semantics) { + m_code.putIns (spv::OpControlBarrier, 4); + m_code.putWord(execution); + m_code.putWord(memory); + m_code.putWord(semantics); + } + + + void SpirvModule::opMemoryBarrier( + uint32_t memory, + uint32_t semantics) { + m_code.putIns (spv::OpMemoryBarrier, 3); + m_code.putWord(memory); + m_code.putWord(semantics); + } + + + void SpirvModule::opLoopMerge( + uint32_t mergeBlock, + uint32_t continueTarget, + uint32_t loopControl) { + m_code.putIns (spv::OpLoopMerge, 4); + m_code.putWord(mergeBlock); + m_code.putWord(continueTarget); + m_code.putWord(loopControl); + } + + + void SpirvModule::opSelectionMerge( + uint32_t mergeBlock, + uint32_t selectionControl) { + m_code.putIns (spv::OpSelectionMerge, 3); + m_code.putWord(mergeBlock); + m_code.putWord(selectionControl); + } + + + void SpirvModule::opBranch( + uint32_t label) { + m_code.putIns (spv::OpBranch, 2); + m_code.putWord(label); + } + + + void SpirvModule::opBranchConditional( + uint32_t condition, + uint32_t trueLabel, + uint32_t falseLabel) { + m_code.putIns (spv::OpBranchConditional, 4); + m_code.putWord(condition); + m_code.putWord(trueLabel); + m_code.putWord(falseLabel); + } + + + void SpirvModule::opSwitch( + uint32_t selector, + uint32_t jumpDefault, + uint32_t caseCount, + const SpirvSwitchCaseLabel* caseLabels) { + m_code.putIns (spv::OpSwitch, 3 + 2 * caseCount); + m_code.putWord(selector); + m_code.putWord(jumpDefault); + + for (uint32_t i = 0; i < caseCount; i++) { + m_code.putWord(caseLabels[i].literal); + m_code.putWord(caseLabels[i].labelId); + } + } + + + uint32_t SpirvModule::opPhi( + uint32_t resultType, + uint32_t sourceCount, + const SpirvPhiLabel* sourceLabels) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpPhi, 3 + 2 * sourceCount); + m_code.putWord(resultType); + m_code.putWord(resultId); + + for (uint32_t i = 0; i < sourceCount; i++) { + m_code.putWord(sourceLabels[i].varId); + m_code.putWord(sourceLabels[i].labelId); + } + + return resultId; + } + + + void SpirvModule::opReturn() { + m_code.putIns (spv::OpReturn, 1); + } + + + void SpirvModule::opKill() { + m_code.putIns (spv::OpKill, 1); + } + + + void SpirvModule::opDemoteToHelperInvocation() { + m_code.putIns (spv::OpDemoteToHelperInvocationEXT, 1); + } + + + void SpirvModule::opEmitVertex( + uint32_t streamId) { + if (streamId == 0) { + m_code.putIns (spv::OpEmitVertex, 1); + } else { + m_code.putIns (spv::OpEmitStreamVertex, 2); + m_code.putWord(streamId); + } + } + + + void SpirvModule::opEndPrimitive( + uint32_t streamId) { + if (streamId == 0) { + m_code.putIns (spv::OpEndPrimitive, 1); + } else { + m_code.putIns (spv::OpEndStreamPrimitive, 2); + m_code.putWord(streamId); + } + } + + + uint32_t SpirvModule::defType( + spv::Op op, + uint32_t argCount, + const uint32_t* argIds) { + // Since the type info is stored in the code buffer, + // we can use the code buffer to look up type IDs as + // well. Result IDs are always stored as argument 1. + for (auto ins : m_typeConstDefs) { + bool match = ins.opCode() == op + && ins.length() == 2 + argCount; + + for (uint32_t i = 0; i < argCount && match; i++) + match &= ins.arg(2 + i) == argIds[i]; + + if (match) + return ins.arg(1); + } + + // Type not yet declared, create a new one. + uint32_t resultId = this->allocateId(); + m_typeConstDefs.putIns (op, 2 + argCount); + m_typeConstDefs.putWord(resultId); + + for (uint32_t i = 0; i < argCount; i++) + m_typeConstDefs.putWord(argIds[i]); + return resultId; + } + + + uint32_t SpirvModule::defConst( + spv::Op op, + uint32_t typeId, + uint32_t argCount, + const uint32_t* argIds) { + // Avoid declaring constants multiple times + for (auto ins : m_typeConstDefs) { + bool match = ins.opCode() == op + && ins.length() == 3 + argCount + && ins.arg(1) == typeId; + + for (uint32_t i = 0; i < argCount && match; i++) + match &= ins.arg(3 + i) == argIds[i]; + + if (!match) + continue; + + uint32_t id = ins.arg(2); + + if (m_lateConsts.find(id) == m_lateConsts.end()) + return id; + } + + // Constant not yet declared, make a new one + uint32_t resultId = this->allocateId(); + m_typeConstDefs.putIns (op, 3 + argCount); + m_typeConstDefs.putWord(typeId); + m_typeConstDefs.putWord(resultId); + + for (uint32_t i = 0; i < argCount; i++) + m_typeConstDefs.putWord(argIds[i]); + return resultId; + } + + + void SpirvModule::instImportGlsl450() { + m_instExtGlsl450 = this->allocateId(); + const char* name = "GLSL.std.450"; + + m_instExt.putIns (spv::OpExtInstImport, 2 + m_instExt.strLen(name)); + m_instExt.putWord(m_instExtGlsl450); + m_instExt.putStr (name); + } + + + uint32_t SpirvModule::getImageOperandWordCount(const SpirvImageOperands& op) const { + // Each flag may add one or more operands + const uint32_t result + = ((op.flags & spv::ImageOperandsBiasMask) ? 1 : 0) + + ((op.flags & spv::ImageOperandsLodMask) ? 1 : 0) + + ((op.flags & spv::ImageOperandsConstOffsetMask) ? 1 : 0) + + ((op.flags & spv::ImageOperandsGradMask) ? 2 : 0) + + ((op.flags & spv::ImageOperandsOffsetMask) ? 1 : 0) + + ((op.flags & spv::ImageOperandsConstOffsetsMask)? 1 : 0) + + ((op.flags & spv::ImageOperandsSampleMask) ? 1 : 0) + + ((op.flags & spv::ImageOperandsMinLodMask) ? 1 : 0); + + // Add a DWORD for the operand mask if it is non-zero + return result != 0 ? result + 1 : 0; + } + + + void SpirvModule::putImageOperands(const SpirvImageOperands& op) { + if (op.flags != 0) { + m_code.putWord(op.flags); + + if (op.flags & spv::ImageOperandsBiasMask) + m_code.putWord(op.sLodBias); + + if (op.flags & spv::ImageOperandsLodMask) + m_code.putWord(op.sLod); + + if (op.flags & spv::ImageOperandsConstOffsetMask) + m_code.putWord(op.sConstOffset); + + if (op.flags & spv::ImageOperandsGradMask) { + m_code.putWord(op.sGradX); + m_code.putWord(op.sGradY); + } + + if (op.flags & spv::ImageOperandsOffsetMask) + m_code.putWord(op.gOffset); + + if (op.flags & spv::ImageOperandsConstOffsetsMask) + m_code.putWord(op.gConstOffsets); + + if (op.flags & spv::ImageOperandsSampleMask) + m_code.putWord(op.sSampleId); + + if (op.flags & spv::ImageOperandsMinLodMask) + m_code.putWord(op.sMinLod); + } + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/spirv/spirv_module.h b/utils/dxvk-1.10.3/src/spirv/spirv_module.h new file mode 100644 index 00000000000..7ce5b8f153f --- /dev/null +++ b/utils/dxvk-1.10.3/src/spirv/spirv_module.h @@ -0,0 +1,1280 @@ +#pragma once + +#include + +#include "spirv_code_buffer.h" + +namespace dxvk { + + struct SpirvPhiLabel { + uint32_t varId = 0; + uint32_t labelId = 0; + }; + + struct SpirvSwitchCaseLabel { + uint32_t literal = 0; + uint32_t labelId = 0; + }; + + struct SpirvImageOperands { + uint32_t flags = 0; + uint32_t sLodBias = 0; + uint32_t sLod = 0; + uint32_t sConstOffset = 0; + uint32_t sGradX = 0; + uint32_t sGradY = 0; + uint32_t gOffset = 0; + uint32_t gConstOffsets = 0; + uint32_t sSampleId = 0; + uint32_t sMinLod = 0; + }; + + constexpr uint32_t spvVersion(uint32_t major, uint32_t minor) { + return (major << 16) | (minor << 8); + } + + /** + * \brief SPIR-V module + * + * This class generates a code buffer containing a full + * SPIR-V shader module. Ensures that the module layout + * is valid, as defined in the SPIR-V 1.0 specification, + * section 2.4 "Logical Layout of a Module". + */ + class SpirvModule { + + public: + + explicit SpirvModule(uint32_t version); + + ~SpirvModule(); + + SpirvCodeBuffer compile() const; + + size_t getInsertionPtr() { + return m_code.getInsertionPtr(); + } + + void beginInsertion(size_t ptr) { + m_code.beginInsertion(ptr); + } + + void endInsertion() { + m_code.endInsertion(); + } + + uint32_t allocateId(); + + bool hasCapability( + spv::Capability capability); + + void enableCapability( + spv::Capability capability); + + void enableExtension( + const char* extensionName); + + void addEntryPoint( + uint32_t entryPointId, + spv::ExecutionModel executionModel, + const char* name, + uint32_t interfaceCount, + const uint32_t* interfaceIds); + + void setMemoryModel( + spv::AddressingModel addressModel, + spv::MemoryModel memoryModel); + + void setExecutionMode( + uint32_t entryPointId, + spv::ExecutionMode executionMode); + + void setExecutionMode( + uint32_t entryPointId, + spv::ExecutionMode executionMode, + uint32_t argCount, + const uint32_t* args); + + void setInvocations( + uint32_t entryPointId, + uint32_t invocations); + + void setLocalSize( + uint32_t entryPointId, + uint32_t x, + uint32_t y, + uint32_t z); + + void setOutputVertices( + uint32_t entryPointId, + uint32_t vertexCount); + + uint32_t addDebugString( + const char* string); + + void setDebugSource( + spv::SourceLanguage language, + uint32_t version, + uint32_t file, + const char* source); + + void setDebugName( + uint32_t expressionId, + const char* debugName); + + void setDebugMemberName( + uint32_t structId, + uint32_t memberId, + const char* debugName); + + uint32_t constBool( + bool v); + + uint32_t consti32( + int32_t v); + + uint32_t consti64( + int64_t v); + + uint32_t constu32( + uint32_t v); + + uint32_t constu64( + uint64_t v); + + uint32_t constf32( + float v); + + uint32_t constf64( + double v); + + uint32_t constvec4i32( + int32_t x, + int32_t y, + int32_t z, + int32_t w); + + uint32_t constvec4b32( + bool x, + bool y, + bool z, + bool w); + + uint32_t constvec4u32( + uint32_t x, + uint32_t y, + uint32_t z, + uint32_t w); + + uint32_t constvec2f32( + float x, + float y); + + uint32_t constvec3f32( + float x, + float y, + float z); + + uint32_t constvec4f32( + float x, + float y, + float z, + float w); + + uint32_t constfReplicant( + float replicant, + uint32_t count); + + uint32_t constbReplicant( + bool replicant, + uint32_t count); + + uint32_t constiReplicant( + int32_t replicant, + uint32_t count); + + uint32_t constuReplicant( + int32_t replicant, + uint32_t count); + + uint32_t constComposite( + uint32_t typeId, + uint32_t constCount, + const uint32_t* constIds); + + uint32_t constUndef( + uint32_t typeId); + + uint32_t lateConst32( + uint32_t typeId); + + void setLateConst( + uint32_t constId, + const uint32_t* argIds); + + uint32_t specConstBool( + bool v); + + uint32_t specConst32( + uint32_t typeId, + uint32_t value); + + void decorate( + uint32_t object, + spv::Decoration decoration); + + void decorateArrayStride( + uint32_t object, + uint32_t stride); + + void decorateBinding( + uint32_t object, + uint32_t binding); + + void decorateBlock( + uint32_t object); + + void decorateBuiltIn( + uint32_t object, + spv::BuiltIn builtIn); + + void decorateComponent( + uint32_t object, + uint32_t location); + + void decorateDescriptorSet( + uint32_t object, + uint32_t set); + + void decorateIndex( + uint32_t object, + uint32_t index); + + void decorateLocation( + uint32_t object, + uint32_t location); + + void decorateSpecId( + uint32_t object, + uint32_t specId); + + void decorateXfb( + uint32_t object, + uint32_t streamId, + uint32_t bufferId, + uint32_t offset, + uint32_t stride); + + void memberDecorateBuiltIn( + uint32_t structId, + uint32_t memberId, + spv::BuiltIn builtIn); + + void memberDecorate( + uint32_t structId, + uint32_t memberId, + spv::Decoration decoration); + + void memberDecorateMatrixStride( + uint32_t structId, + uint32_t memberId, + uint32_t stride); + + void memberDecorateOffset( + uint32_t structId, + uint32_t memberId, + uint32_t offset); + + uint32_t defVoidType(); + + uint32_t defBoolType(); + + uint32_t defIntType( + uint32_t width, + uint32_t isSigned); + + uint32_t defFloatType( + uint32_t width); + + uint32_t defVectorType( + uint32_t elementType, + uint32_t elementCount); + + uint32_t defMatrixType( + uint32_t columnType, + uint32_t columnCount); + + uint32_t defArrayType( + uint32_t typeId, + uint32_t length); + + uint32_t defArrayTypeUnique( + uint32_t typeId, + uint32_t length); + + uint32_t defRuntimeArrayType( + uint32_t typeId); + + uint32_t defRuntimeArrayTypeUnique( + uint32_t typeId); + + uint32_t defFunctionType( + uint32_t returnType, + uint32_t argCount, + const uint32_t* argTypes); + + uint32_t defStructType( + uint32_t memberCount, + const uint32_t* memberTypes); + + uint32_t defStructTypeUnique( + uint32_t memberCount, + const uint32_t* memberTypes); + + uint32_t defPointerType( + uint32_t variableType, + spv::StorageClass storageClass); + + uint32_t defSamplerType(); + + uint32_t defImageType( + uint32_t sampledType, + spv::Dim dimensionality, + uint32_t depth, + uint32_t arrayed, + uint32_t multisample, + uint32_t sampled, + spv::ImageFormat format); + + uint32_t defSampledImageType( + uint32_t imageType); + + uint32_t newVar( + uint32_t pointerType, + spv::StorageClass storageClass); + + uint32_t newVarInit( + uint32_t pointerType, + spv::StorageClass storageClass, + uint32_t initialValue); + + void functionBegin( + uint32_t returnType, + uint32_t functionId, + uint32_t functionType, + spv::FunctionControlMask functionControl); + + uint32_t functionParameter( + uint32_t parameterType); + + void functionEnd(); + + uint32_t opAccessChain( + uint32_t resultType, + uint32_t composite, + uint32_t indexCount, + const uint32_t* indexArray); + + uint32_t opArrayLength( + uint32_t resultType, + uint32_t structure, + uint32_t memberId); + + uint32_t opAny( + uint32_t resultType, + uint32_t vector); + + uint32_t opAll( + uint32_t resultType, + uint32_t vector); + + uint32_t opAtomicLoad( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics); + + void opAtomicStore( + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value); + + uint32_t opAtomicExchange( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value); + + uint32_t opAtomicCompareExchange( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t equal, + uint32_t unequal, + uint32_t value, + uint32_t comparator); + + uint32_t opAtomicIIncrement( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics); + + uint32_t opAtomicIDecrement( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics); + + uint32_t opAtomicIAdd( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value); + + uint32_t opAtomicISub( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value); + + uint32_t opAtomicSMin( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value); + + uint32_t opAtomicSMax( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value); + + uint32_t opAtomicUMin( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value); + + uint32_t opAtomicUMax( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value); + + uint32_t opAtomicAnd( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value); + + uint32_t opAtomicOr( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value); + + uint32_t opAtomicXor( + uint32_t resultType, + uint32_t pointer, + uint32_t scope, + uint32_t semantics, + uint32_t value); + + uint32_t opBitcast( + uint32_t resultType, + uint32_t operand); + + uint32_t opBitCount( + uint32_t resultType, + uint32_t operand); + + uint32_t opBitReverse( + uint32_t resultType, + uint32_t operand); + + uint32_t opFindILsb( + uint32_t resultType, + uint32_t operand); + + uint32_t opFindUMsb( + uint32_t resultType, + uint32_t operand); + + uint32_t opFindSMsb( + uint32_t resultType, + uint32_t operand); + + uint32_t opBitFieldInsert( + uint32_t resultType, + uint32_t base, + uint32_t insert, + uint32_t offset, + uint32_t count); + + uint32_t opBitFieldSExtract( + uint32_t resultType, + uint32_t base, + uint32_t offset, + uint32_t count); + + uint32_t opBitFieldUExtract( + uint32_t resultType, + uint32_t base, + uint32_t offset, + uint32_t count); + + uint32_t opBitwiseAnd( + uint32_t resultType, + uint32_t operand1, + uint32_t operand2); + + uint32_t opBitwiseOr( + uint32_t resultType, + uint32_t operand1, + uint32_t operand2); + + uint32_t opBitwiseXor( + uint32_t resultType, + uint32_t operand1, + uint32_t operand2); + + uint32_t opNot( + uint32_t resultType, + uint32_t operand); + + uint32_t opShiftLeftLogical( + uint32_t resultType, + uint32_t base, + uint32_t shift); + + uint32_t opShiftRightArithmetic( + uint32_t resultType, + uint32_t base, + uint32_t shift); + + uint32_t opShiftRightLogical( + uint32_t resultType, + uint32_t base, + uint32_t shift); + + uint32_t opConvertFtoS( + uint32_t resultType, + uint32_t operand); + + uint32_t opConvertFtoU( + uint32_t resultType, + uint32_t operand); + + uint32_t opConvertStoF( + uint32_t resultType, + uint32_t operand); + + uint32_t opConvertUtoF( + uint32_t resultType, + uint32_t operand); + + uint32_t opCompositeConstruct( + uint32_t resultType, + uint32_t valueCount, + const uint32_t* valueArray); + + uint32_t opCompositeExtract( + uint32_t resultType, + uint32_t composite, + uint32_t indexCount, + const uint32_t* indexArray); + + uint32_t opCompositeInsert( + uint32_t resultType, + uint32_t object, + uint32_t composite, + uint32_t indexCount, + const uint32_t* indexArray); + + uint32_t opDpdx( + uint32_t resultType, + uint32_t operand); + + uint32_t opDpdy( + uint32_t resultType, + uint32_t operand); + + uint32_t opDpdxCoarse( + uint32_t resultType, + uint32_t operand); + + uint32_t opDpdyCoarse( + uint32_t resultType, + uint32_t operand); + + uint32_t opDpdxFine( + uint32_t resultType, + uint32_t operand); + + uint32_t opDpdyFine( + uint32_t resultType, + uint32_t operand); + + uint32_t opVectorExtractDynamic( + uint32_t resultType, + uint32_t vector, + uint32_t index); + + uint32_t opVectorShuffle( + uint32_t resultType, + uint32_t vectorLeft, + uint32_t vectorRight, + uint32_t indexCount, + const uint32_t* indexArray); + + uint32_t opSNegate( + uint32_t resultType, + uint32_t operand); + + uint32_t opFNegate( + uint32_t resultType, + uint32_t operand); + + uint32_t opSAbs( + uint32_t resultType, + uint32_t operand); + + uint32_t opFAbs( + uint32_t resultType, + uint32_t operand); + + uint32_t opFSign( + uint32_t resultType, + uint32_t operand); + + uint32_t opFMix( + uint32_t resultType, + uint32_t x, + uint32_t y, + uint32_t a); + + uint32_t opCross( + uint32_t resultType, + uint32_t x, + uint32_t y); + + uint32_t opIAdd( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opISub( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opFAdd( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opFSub( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opSDiv( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opUDiv( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opSRem( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opUMod( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opFDiv( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opIMul( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opFMul( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opVectorTimesScalar( + uint32_t resultType, + uint32_t vector, + uint32_t scalar); + + uint32_t opMatrixTimesMatrix( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opMatrixTimesVector( + uint32_t resultType, + uint32_t matrix, + uint32_t vector); + + uint32_t opVectorTimesMatrix( + uint32_t resultType, + uint32_t vector, + uint32_t matrix); + + uint32_t opTranspose( + uint32_t resultType, + uint32_t matrix); + + uint32_t opInverse( + uint32_t resultType, + uint32_t matrix); + + uint32_t opFFma( + uint32_t resultType, + uint32_t a, + uint32_t b, + uint32_t c); + + uint32_t opFMax( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opFMin( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opNMax( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opNMin( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opSMax( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opSMin( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opUMax( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opUMin( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opFClamp( + uint32_t resultType, + uint32_t x, + uint32_t minVal, + uint32_t maxVal); + + uint32_t opNClamp( + uint32_t resultType, + uint32_t x, + uint32_t minVal, + uint32_t maxVal); + + uint32_t opIEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2); + + uint32_t opINotEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2); + + uint32_t opSLessThan( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2); + + uint32_t opSLessThanEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2); + + uint32_t opSGreaterThan( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2); + + uint32_t opSGreaterThanEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2); + + uint32_t opULessThan( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2); + + uint32_t opULessThanEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2); + + uint32_t opUGreaterThan( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2); + + uint32_t opUGreaterThanEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2); + + uint32_t opFOrdEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2); + + uint32_t opFOrdNotEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2); + + uint32_t opFOrdLessThan( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2); + + uint32_t opFOrdLessThanEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2); + + uint32_t opFOrdGreaterThan( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2); + + uint32_t opFOrdGreaterThanEqual( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2); + + uint32_t opLogicalEqual( + uint32_t resultType, + uint32_t operand1, + uint32_t operand2); + + uint32_t opLogicalNotEqual( + uint32_t resultType, + uint32_t operand1, + uint32_t operand2); + + uint32_t opLogicalAnd( + uint32_t resultType, + uint32_t operand1, + uint32_t operand2); + + uint32_t opLogicalOr( + uint32_t resultType, + uint32_t operand1, + uint32_t operand2); + + uint32_t opLogicalNot( + uint32_t resultType, + uint32_t operand); + + uint32_t opDot( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2); + + uint32_t opSin( + uint32_t resultType, + uint32_t vector); + + uint32_t opCos( + uint32_t resultType, + uint32_t vector); + + uint32_t opSqrt( + uint32_t resultType, + uint32_t operand); + + uint32_t opInverseSqrt( + uint32_t resultType, + uint32_t operand); + + uint32_t opNormalize( + uint32_t resultType, + uint32_t operand); + + uint32_t opReflect( + uint32_t resultType, + uint32_t incident, + uint32_t normal); + + uint32_t opLength( + uint32_t resultType, + uint32_t operand); + + uint32_t opExp2( + uint32_t resultType, + uint32_t operand); + + uint32_t opExp( + uint32_t resultType, + uint32_t operand); + + uint32_t opLog2( + uint32_t resultType, + uint32_t operand); + + uint32_t opPow( + uint32_t resultType, + uint32_t base, + uint32_t exponent); + + uint32_t opFract( + uint32_t resultType, + uint32_t operand); + + uint32_t opCeil( + uint32_t resultType, + uint32_t operand); + + uint32_t opFloor( + uint32_t resultType, + uint32_t operand); + + uint32_t opRound( + uint32_t resultType, + uint32_t operand); + + uint32_t opRoundEven( + uint32_t resultType, + uint32_t operand); + + uint32_t opTrunc( + uint32_t resultType, + uint32_t operand); + + uint32_t opFConvert( + uint32_t resultType, + uint32_t operand); + + uint32_t opPackHalf2x16( + uint32_t resultType, + uint32_t operand); + + uint32_t opUnpackHalf2x16( + uint32_t resultType, + uint32_t operand); + + uint32_t opSelect( + uint32_t resultType, + uint32_t condition, + uint32_t operand1, + uint32_t operand2); + + uint32_t opIsNan( + uint32_t resultType, + uint32_t operand); + + uint32_t opIsInf( + uint32_t resultType, + uint32_t operand); + + uint32_t opFunctionCall( + uint32_t resultType, + uint32_t functionId, + uint32_t argCount, + const uint32_t* argIds); + + void opLabel( + uint32_t labelId); + + uint32_t opLoad( + uint32_t typeId, + uint32_t pointerId); + + void opStore( + uint32_t pointerId, + uint32_t valueId); + + uint32_t opInterpolateAtCentroid( + uint32_t resultType, + uint32_t interpolant); + + uint32_t opInterpolateAtSample( + uint32_t resultType, + uint32_t interpolant, + uint32_t sample); + + uint32_t opInterpolateAtOffset( + uint32_t resultType, + uint32_t interpolant, + uint32_t offset); + + uint32_t opImage( + uint32_t resultType, + uint32_t sampledImage); + + uint32_t opImageRead( + uint32_t resultType, + uint32_t image, + uint32_t coordinates, + const SpirvImageOperands& operands); + + void opImageWrite( + uint32_t image, + uint32_t coordinates, + uint32_t texel, + const SpirvImageOperands& operands); + + uint32_t opImageTexelPointer( + uint32_t resultType, + uint32_t image, + uint32_t coordinates, + uint32_t sample); + + uint32_t opSampledImage( + uint32_t resultType, + uint32_t image, + uint32_t sampler); + + uint32_t opImageQuerySizeLod( + uint32_t resultType, + uint32_t image, + uint32_t lod); + + uint32_t opImageQuerySize( + uint32_t resultType, + uint32_t image); + + uint32_t opImageQueryLevels( + uint32_t resultType, + uint32_t image); + + uint32_t opImageQueryLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates); + + uint32_t opImageQuerySamples( + uint32_t resultType, + uint32_t image); + + uint32_t opImageFetch( + uint32_t resultType, + uint32_t image, + uint32_t coordinates, + const SpirvImageOperands& operands); + + uint32_t opImageGather( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + uint32_t component, + const SpirvImageOperands& operands); + + uint32_t opImageDrefGather( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + uint32_t reference, + const SpirvImageOperands& operands); + + uint32_t opImageSampleImplicitLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + const SpirvImageOperands& operands); + + uint32_t opImageSampleExplicitLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + const SpirvImageOperands& operands); + + uint32_t opImageSampleProjImplicitLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + const SpirvImageOperands& operands); + + uint32_t opImageSampleProjExplicitLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + const SpirvImageOperands& operands); + + uint32_t opImageSampleDrefImplicitLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + uint32_t reference, + const SpirvImageOperands& operands); + + uint32_t opImageSampleDrefExplicitLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + uint32_t reference, + const SpirvImageOperands& operands); + + uint32_t opImageSampleProjDrefImplicitLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + uint32_t reference, + const SpirvImageOperands& operands); + + uint32_t opImageSampleProjDrefExplicitLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + uint32_t reference, + const SpirvImageOperands& operands); + + uint32_t opGroupNonUniformBallot( + uint32_t resultType, + uint32_t execution, + uint32_t predicate); + + uint32_t opGroupNonUniformBallotBitCount( + uint32_t resultType, + uint32_t execution, + uint32_t operation, + uint32_t ballot); + + uint32_t opGroupNonUniformElect( + uint32_t resultType, + uint32_t execution); + + uint32_t opGroupNonUniformBroadcastFirst( + uint32_t resultType, + uint32_t execution, + uint32_t value); + + void opControlBarrier( + uint32_t execution, + uint32_t memory, + uint32_t semantics); + + void opMemoryBarrier( + uint32_t memory, + uint32_t semantics); + + void opLoopMerge( + uint32_t mergeBlock, + uint32_t continueTarget, + uint32_t loopControl); + + void opSelectionMerge( + uint32_t mergeBlock, + uint32_t selectionControl); + + void opBranch( + uint32_t label); + + void opBranchConditional( + uint32_t condition, + uint32_t trueLabel, + uint32_t falseLabel); + + void opSwitch( + uint32_t selector, + uint32_t jumpDefault, + uint32_t caseCount, + const SpirvSwitchCaseLabel* caseLabels); + + uint32_t opPhi( + uint32_t resultType, + uint32_t sourceCount, + const SpirvPhiLabel* sourceLabels); + + void opReturn(); + + void opKill(); + + void opDemoteToHelperInvocation(); + + void opEmitVertex( + uint32_t streamId); + + void opEndPrimitive( + uint32_t streamId); + + private: + + uint32_t m_version; + uint32_t m_id = 1; + uint32_t m_instExtGlsl450 = 0; + + SpirvCodeBuffer m_capabilities; + SpirvCodeBuffer m_extensions; + SpirvCodeBuffer m_instExt; + SpirvCodeBuffer m_memoryModel; + SpirvCodeBuffer m_entryPoints; + SpirvCodeBuffer m_execModeInfo; + SpirvCodeBuffer m_debugNames; + SpirvCodeBuffer m_annotations; + SpirvCodeBuffer m_typeConstDefs; + SpirvCodeBuffer m_variables; + SpirvCodeBuffer m_code; + + std::unordered_set m_lateConsts; + + uint32_t defType( + spv::Op op, + uint32_t argCount, + const uint32_t* argIds); + + uint32_t defConst( + spv::Op op, + uint32_t typeId, + uint32_t argCount, + const uint32_t* argIds); + + void instImportGlsl450(); + + uint32_t getImageOperandWordCount( + const SpirvImageOperands& op) const; + + void putImageOperands( + const SpirvImageOperands& op); + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/util/com/com_guid.cpp b/utils/dxvk-1.10.3/src/util/com/com_guid.cpp new file mode 100644 index 00000000000..329d1848891 --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/com/com_guid.cpp @@ -0,0 +1,28 @@ +#include "com_guid.h" + +#include "../../d3d11/d3d11_interfaces.h" + +#include "../../dxgi/dxgi_interfaces.h" + +std::ostream& operator << (std::ostream& os, REFIID guid) { + os << std::hex << std::setfill('0') + << std::setw(8) << guid.Data1 << '-'; + + os << std::hex << std::setfill('0') + << std::setw(4) << guid.Data2 << '-'; + + os << std::hex << std::setfill('0') + << std::setw(4) << guid.Data3 << '-'; + + os << std::hex << std::setfill('0') + << std::setw(2) << static_cast(guid.Data4[0]) + << std::setw(2) << static_cast(guid.Data4[1]) + << '-' + << std::setw(2) << static_cast(guid.Data4[2]) + << std::setw(2) << static_cast(guid.Data4[3]) + << std::setw(2) << static_cast(guid.Data4[4]) + << std::setw(2) << static_cast(guid.Data4[5]) + << std::setw(2) << static_cast(guid.Data4[6]) + << std::setw(2) << static_cast(guid.Data4[7]); + return os; +} diff --git a/utils/dxvk-1.10.3/src/util/com/com_guid.h b/utils/dxvk-1.10.3/src/util/com/com_guid.h new file mode 100644 index 00000000000..9a69fc9320f --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/com/com_guid.h @@ -0,0 +1,8 @@ +#pragma once + +#include +#include + +#include "com_include.h" + +std::ostream& operator << (std::ostream& os, REFIID guid); diff --git a/utils/dxvk-1.10.3/src/util/com/com_include.h b/utils/dxvk-1.10.3/src/util/com/com_include.h new file mode 100644 index 00000000000..3c119309866 --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/com/com_include.h @@ -0,0 +1,17 @@ +#pragma once + +// GCC complains about the COM interfaces +// not having virtual destructors +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wnon-virtual-dtor" +#endif // __GNUC__ + +#define WIN32_LEAN_AND_MEAN +#include +#include + +// GCC: -std options disable certain keywords +// https://gcc.gnu.org/onlinedocs/gcc/Alternate-Keywords.html +#if defined(__WINE__) && !defined(typeof) +#define typeof __typeof +#endif diff --git a/utils/dxvk-1.10.3/src/util/com/com_object.h b/utils/dxvk-1.10.3/src/util/com/com_object.h new file mode 100644 index 00000000000..75188d5c133 --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/com/com_object.h @@ -0,0 +1,119 @@ +#pragma once + +#include + +#include "com_include.h" + +#include "../util_likely.h" + +namespace dxvk { + + template + class NoWrapper : public T { + + public: + + virtual ~NoWrapper() { } + + }; + + /** + * \brief Reference-counted COM object + * + * This can serve as a templated base class for most + * COM objects. It implements AddRef and Release from + * \c IUnknown, and provides methods to increment and + * decrement private references which are not visible + * to the application. + * + * Having two reference counters is sadly necessary + * in order to not break games which steal internal + * references if the refefence count of an object is + + greater than they expect. DXVK sometimes requires + * holding on to objects which the application wants + * to delete. + */ + template + class ComObject : public Base { + + public: + + virtual ~ComObject() { } + + ULONG STDMETHODCALLTYPE AddRef() { + uint32_t refCount = m_refCount++; + if (unlikely(!refCount)) + AddRefPrivate(); + return refCount + 1; + } + + ULONG STDMETHODCALLTYPE Release() { + uint32_t refCount = --m_refCount; + if (unlikely(!refCount)) + ReleasePrivate(); + return refCount; + } + + + void AddRefPrivate() { + ++m_refPrivate; + } + + + void ReleasePrivate() { + uint32_t refPrivate = --m_refPrivate; + if (unlikely(!refPrivate)) { + m_refPrivate += 0x80000000; + delete this; + } + } + + ULONG GetPrivateRefCount() { + return m_refPrivate.load(); + } + + protected: + + std::atomic m_refCount = { 0ul }; + std::atomic m_refPrivate = { 0ul }; + + }; + + /** + * \brief Clamped, reference-counted COM object + * + * This version of ComObject ensures that the reference + * count does not wrap around if a release happens at zero. + * eg. [m_refCount = 0] + * Release() + * [m_refCount = 0] + * This is a notable quirk of D3D9's COM implementation + * and is relied upon by some games. + */ + template + class ComObjectClamp : public ComObject { + + public: + + ULONG STDMETHODCALLTYPE Release() { + ULONG refCount = this->m_refCount; + if (likely(refCount != 0ul)) { + this->m_refCount--; + refCount--; + + if (refCount == 0ul) + this->ReleasePrivate(); + } + + return refCount; + } + + }; + + template + inline void InitReturnPtr(T** ptr) { + if (ptr != nullptr) + *ptr = nullptr; + } + +} diff --git a/utils/dxvk-1.10.3/src/util/com/com_pointer.h b/utils/dxvk-1.10.3/src/util/com/com_pointer.h new file mode 100644 index 00000000000..c81fae2484d --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/com/com_pointer.h @@ -0,0 +1,146 @@ +#pragma once + +#include "com_include.h" + +namespace dxvk { + + /** + * \brief Increment public ref count + * + * If the pointer is not \c nullptr, this + * calls \c AddRef for the given object. + * \returns Pointer to the object + */ + template + T* ref(T* object) { + if (object != nullptr) + object->AddRef(); + return object; + } + + + /** + * \brief Ref count methods for public references + */ + template + struct ComRef_ { + static void incRef(T* ptr) { ptr->AddRef(); } + static void decRef(T* ptr) { ptr->Release(); } + }; + + + /** + * \brief Ref count methods for private references + */ + template + struct ComRef_ { + static void incRef(T* ptr) { ptr->AddRefPrivate(); } + static void decRef(T* ptr) { ptr->ReleasePrivate(); } + }; + + + /** + * \brief COM pointer + * + * Implements automatic reference + * counting for COM objects. + */ + template + class Com { + using ComRef = ComRef_; + public: + + Com() { } + Com(std::nullptr_t) { } + Com(T* object) + : m_ptr(object) { + this->incRef(); + } + + Com(const Com& other) + : m_ptr(other.m_ptr) { + this->incRef(); + } + + Com(Com&& other) + : m_ptr(other.m_ptr) { + other.m_ptr = nullptr; + } + + Com& operator = (T* object) { + this->decRef(); + m_ptr = object; + this->incRef(); + return *this; + } + + Com& operator = (const Com& other) { + other.incRef(); + this->decRef(); + m_ptr = other.m_ptr; + return *this; + } + + Com& operator = (Com&& other) { + this->decRef(); + this->m_ptr = other.m_ptr; + other.m_ptr = nullptr; + return *this; + } + + Com& operator = (std::nullptr_t) { + this->decRef(); + m_ptr = nullptr; + return *this; + } + + ~Com() { + this->decRef(); + } + + T* operator -> () const { + return m_ptr; + } + + T** operator & () { return &m_ptr; } + T* const* operator & () const { return &m_ptr; } + + template + bool operator == (const Com& other) const { return m_ptr == other.m_ptr; } + template + bool operator != (const Com& other) const { return m_ptr != other.m_ptr; } + + bool operator == (const T* other) const { return m_ptr == other; } + bool operator != (const T* other) const { return m_ptr != other; } + + bool operator == (std::nullptr_t) const { return m_ptr == nullptr; } + bool operator != (std::nullptr_t) const { return m_ptr != nullptr; } + + T* ref() const { + return dxvk::ref(m_ptr); + } + + T* ptr() const { + return m_ptr; + } + + Com pubRef() const { return m_ptr; } + Com prvRef() const { return m_ptr; } + + private: + + T* m_ptr = nullptr; + + void incRef() const { + if (m_ptr != nullptr) + ComRef::incRef(m_ptr); + } + + void decRef() const { + if (m_ptr != nullptr) + ComRef::decRef(m_ptr); + } + + }; + +} diff --git a/utils/dxvk-1.10.3/src/util/com/com_private_data.cpp b/utils/dxvk-1.10.3/src/util/com/com_private_data.cpp new file mode 100644 index 00000000000..d27a4103f1f --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/com/com_private_data.cpp @@ -0,0 +1,171 @@ +#include +#include +#include + +#include "com_private_data.h" + +namespace dxvk { + + ComPrivateDataEntry::ComPrivateDataEntry() { } + ComPrivateDataEntry::ComPrivateDataEntry( + REFGUID guid, + UINT size, + const void* data) + : m_guid(guid), + m_type(ComPrivateDataType::Data), + m_size(size), + m_data(std::malloc(size)) { + std::memcpy(m_data, data, size); + } + + + ComPrivateDataEntry::ComPrivateDataEntry( + REFGUID guid, + const IUnknown* iface) + : m_guid (guid), + m_type(ComPrivateDataType::Iface), + m_iface (const_cast(iface)) { + if (m_iface) + m_iface->AddRef(); + } + + + ComPrivateDataEntry::~ComPrivateDataEntry() { + this->destroy(); + } + + + ComPrivateDataEntry::ComPrivateDataEntry(ComPrivateDataEntry&& other) + : m_guid (other.m_guid), + m_type (other.m_type), + m_size (other.m_size), + m_data (other.m_data), + m_iface (other.m_iface) { + other.m_guid = __uuidof(IUnknown); + other.m_type = ComPrivateDataType::None; + other.m_size = 0; + other.m_data = nullptr; + other.m_iface = nullptr; + } + + + ComPrivateDataEntry& ComPrivateDataEntry::operator = (ComPrivateDataEntry&& other) { + this->destroy(); + this->m_guid = other.m_guid; + this->m_type = other.m_type; + this->m_size = other.m_size; + this->m_data = other.m_data; + this->m_iface = other.m_iface; + + other.m_guid = __uuidof(IUnknown); + other.m_type = ComPrivateDataType::None; + other.m_size = 0; + other.m_data = nullptr; + other.m_iface = nullptr; + return *this; + } + + + HRESULT ComPrivateDataEntry::get(UINT& size, void* data) const { + UINT minSize = 0; + + if (m_type == ComPrivateDataType::Iface) minSize = sizeof(IUnknown*); + if (m_type == ComPrivateDataType::Data) minSize = m_size; + + if (!data) { + size = minSize; + return S_OK; + } + + HRESULT result = size < minSize + ? DXGI_ERROR_MORE_DATA + : S_OK; + + if (size >= minSize) { + if (m_type == ComPrivateDataType::Iface) { + if (m_iface) + m_iface->AddRef(); + std::memcpy(data, &m_iface, minSize); + } else { + std::memcpy(data, m_data, minSize); + } + } + + size = minSize; + return result; + } + + + void ComPrivateDataEntry::destroy() { + if (m_data) + std::free(m_data); + if (m_iface) + m_iface->Release(); + } + + + HRESULT ComPrivateData::setData( + REFGUID guid, + UINT size, + const void* data) { + if (!data) { + for (auto it = m_entries.begin(); it != m_entries.end(); ++it) { + if (it->hasGuid(guid)) { + m_entries.erase(it); + return S_OK; + } + } + return S_FALSE; + } + this->insertEntry(ComPrivateDataEntry(guid, size, data)); + return S_OK; + } + + + HRESULT ComPrivateData::setInterface( + REFGUID guid, + const IUnknown* iface) { + this->insertEntry(ComPrivateDataEntry(guid, iface)); + return S_OK; + } + + + HRESULT ComPrivateData::getData( + REFGUID guid, + UINT* size, + void* data) { + if (!size) + return E_INVALIDARG; + + auto entry = this->findEntry(guid); + + if (!entry) { + *size = 0; + return DXGI_ERROR_NOT_FOUND; + } + + return entry->get(*size, data); + } + + + ComPrivateDataEntry* ComPrivateData::findEntry(REFGUID guid) { + for (ComPrivateDataEntry& e : m_entries) { + if (e.hasGuid(guid)) + return &e; + } + + return nullptr; + } + + + void ComPrivateData::insertEntry(ComPrivateDataEntry&& entry) { + ComPrivateDataEntry srcEntry = std::move(entry); + ComPrivateDataEntry* dstEntry = this->findEntry(srcEntry.guid()); + + if (dstEntry) + *dstEntry = std::move(srcEntry); + else + m_entries.push_back(std::move(srcEntry)); + } + +} diff --git a/utils/dxvk-1.10.3/src/util/com/com_private_data.h b/utils/dxvk-1.10.3/src/util/com/com_private_data.h new file mode 100644 index 00000000000..0673f8e2d25 --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/com/com_private_data.h @@ -0,0 +1,115 @@ +#pragma once + +#include + +#include "com_include.h" + +namespace dxvk { + + /** + * \brief COM private data entry type + */ + enum ComPrivateDataType { + None, + Data, + Iface, + }; + + /** + * \brief Data entry for private storage + * Stores a single private storage item. + */ + class ComPrivateDataEntry { + + public: + + ComPrivateDataEntry(); + ComPrivateDataEntry( + REFGUID guid, + UINT size, + const void* data); + ComPrivateDataEntry( + REFGUID guid, + const IUnknown* iface); + ~ComPrivateDataEntry(); + + ComPrivateDataEntry (ComPrivateDataEntry&& other); + ComPrivateDataEntry& operator = (ComPrivateDataEntry&& other); + + /** + * \brief The entry's GUID + * \returns The GUID + */ + REFGUID guid() const { + return m_guid; + } + + /** + * \brief Checks whether the GUID matches another one + * + * GUIDs are used to identify private data entries. + * \param [in] guid The GUID to compare to + * \returns \c true if this entry holds the same GUID + */ + bool hasGuid(REFGUID guid) const { + return m_guid == guid; + } + + /** + * \brief Retrieves stored data + * + * \param [in,out] size Destination buffer size + * \param [in] data Appliaction-provided buffer + * \returns \c S_OK on success, or \c DXGI_ERROR_MORE_DATA + * if the destination buffer is too small + */ + HRESULT get(UINT& size, void* data) const; + + private: + + GUID m_guid = __uuidof(IUnknown); + ComPrivateDataType m_type = ComPrivateDataType::None; + UINT m_size = 0; + void* m_data = nullptr; + IUnknown* m_iface = nullptr; + + void destroy(); + + }; + + + /** + * \brief Private storage for DXGI objects + * + * Provides storage for application-defined + * byte arrays or COM interfaces that can be + * retrieved using GUIDs. + */ + class ComPrivateData { + + public: + + HRESULT setData( + REFGUID guid, + UINT size, + const void* data); + + HRESULT setInterface( + REFGUID guid, + const IUnknown* iface); + + HRESULT getData( + REFGUID guid, + UINT* size, + void* data); + + private: + + std::vector m_entries; + + ComPrivateDataEntry* findEntry(REFGUID guid); + void insertEntry(ComPrivateDataEntry&& entry); + + }; + +} diff --git a/utils/dxvk-1.10.3/src/util/config/config.cpp b/utils/dxvk-1.10.3/src/util/config/config.cpp new file mode 100644 index 00000000000..860debfe06a --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/config/config.cpp @@ -0,0 +1,882 @@ +#include +#include +#include +#include +#include +#include + +#include "config.h" + +#include "../log/log.h" + +#include "../util_env.h" + +namespace dxvk { + + const static std::vector> g_appDefaults = {{ + /* Assassin's Creed Syndicate: amdags issues */ + { R"(\\ACS\.exe$)", {{ + { "dxgi.customVendorId", "10de" }, + }} }, + /* Dissidia Final Fantasy NT Free Edition */ + { R"(\\dffnt\.exe$)", {{ + { "dxgi.deferSurfaceCreation", "True" }, + }} }, + /* Elite Dangerous: Compiles weird shaders * + * when running on AMD hardware */ + { R"(\\EliteDangerous64\.exe$)", {{ + { "dxgi.customVendorId", "10de" }, + }} }, + /* The Vanishing of Ethan Carter Redux */ + { R"(\\EthanCarter-Win64-Shipping\.exe$)", {{ + { "dxgi.customVendorId", "10de" }, + }} }, + /* The Evil Within: Submits command lists * + * multiple times */ + { R"(\\EvilWithin(Demo)?\.exe$)", {{ + { "d3d11.dcSingleUseMode", "False" }, + { "d3d11.cachedDynamicResources", "vi" }, + }} }, + /* Far Cry 3: Assumes clear(0.5) on an UNORM * + * format to result in 128 on AMD and 127 on * + * Nvidia. We assume that the Vulkan drivers * + * match the clear behaviour of D3D11. */ + { R"(\\(farcry3|fc3_blooddragon)_d3d11\.exe$)", {{ + { "dxgi.nvapiHack", "False" }, + }} }, + /* Far Cry 4: Same as Far Cry 3 */ + { R"(\\FarCry4\.exe$)", {{ + { "dxgi.nvapiHack", "False" }, + }} }, + /* Frostpunk: Renders one frame with D3D9 * + * after creating the DXGI swap chain */ + { R"(\\Frostpunk\.exe$)", {{ + { "dxgi.deferSurfaceCreation", "True" }, + { "d3d11.cachedDynamicResources", "c" }, + }} }, + /* Nioh: See Frostpunk, apparently? */ + { R"(\\nioh\.exe$)", {{ + { "dxgi.deferSurfaceCreation", "True" }, + }} }, + /* Quantum Break: Mever initializes shared * + * memory in one of its compute shaders. * + * Also loves using MAP_WRITE on the same * + * set of resources multiple times per frame. */ + { R"(\\QuantumBreak\.exe$)", {{ + { "d3d11.zeroInitWorkgroupMemory", "True" }, + { "d3d11.maxImplicitDiscardSize", "-1" }, + }} }, + /* Anno 2205: Random crashes with state cache */ + { R"(\\anno2205\.exe$)", {{ + { "dxvk.enableStateCache", "False" }, + }} }, + /* Anno 1800: Poor performance without this */ + { R"(\\Anno1800\.exe$)", {{ + { "d3d11.cachedDynamicResources", "c" }, + }} }, + /* Fifa '19+: Binds typed buffer SRV to shader * + * that expects raw/structured buffer SRV */ + { R"(\\FIFA(19|[2-9][0-9])(_demo)?\.exe$)", {{ + { "dxvk.useRawSsbo", "True" }, + }} }, + /* Resident Evil 2/3: Ignore WaW hazards */ + { R"(\\re(2|3|3demo)\.exe$)", {{ + { "d3d11.relaxedBarriers", "True" }, + }} }, + /* Devil May Cry 5 */ + { R"(\\DevilMayCry5\.exe$)", {{ + { "d3d11.relaxedBarriers", "True" }, + }} }, + /* Call of Duty WW2 */ + { R"(\\s2_sp64_ship\.exe$)", {{ + { "dxgi.nvapiHack", "False" }, + }} }, + /* Need for Speed 2015 */ + { R"(\\NFS16\.exe$)", {{ + { "dxgi.nvapiHack", "False" }, + }} }, + /* Mass Effect Andromeda */ + { R"(\\MassEffectAndromeda\.exe$)", {{ + { "dxgi.nvapiHack", "False" }, + }} }, + /* Mirror`s Edge Catalyst: Crashes on AMD */ + { R"(\\MirrorsEdgeCatalyst(Trial)?\.exe$)", {{ + { "dxgi.customVendorId", "10de" }, + }} }, + /* Star Wars Battlefront (2015) */ + { R"(\\starwarsbattlefront(trial)?\.exe$)", {{ + { "dxgi.nvapiHack", "False" }, + }} }, + /* Dark Souls Remastered */ + { R"(\\DarkSoulsRemastered\.exe$)", {{ + { "d3d11.constantBufferRangeCheck", "True" }, + }} }, + /* Grim Dawn */ + { R"(\\Grim Dawn\.exe$)", {{ + { "d3d11.constantBufferRangeCheck", "True" }, + }} }, + /* NieR:Automata */ + { R"(\\NieRAutomata\.exe$)", {{ + { "d3d11.constantBufferRangeCheck", "True" }, + }} }, + /* NieR Replicant */ + { R"(\\NieR Replicant ver\.1\.22474487139\.exe)", {{ + { "dxgi.syncInterval", "1" }, + { "dxgi.maxFrameRate", "60" }, + { "d3d11.cachedDynamicResources", "vi" }, + }} }, + /* SteamVR performance test */ + { R"(\\vr\.exe$)", {{ + { "d3d11.dcSingleUseMode", "False" }, + }} }, + /* Hitman 2 and 3 - requires AGS library */ + { R"(\\HITMAN(2|3)\.exe$)", {{ + { "dxgi.customVendorId", "10de" }, + }} }, + /* Modern Warfare Remastered */ + { R"(\\h1_[ms]p64_ship\.exe$)", {{ + { "dxgi.customVendorId", "10de" }, + }} }, + /* Titan Quest */ + { R"(\\TQ\.exe$)", {{ + { "d3d11.constantBufferRangeCheck", "True" }, + }} }, + /* Saints Row IV */ + { R"(\\SaintsRowIV\.exe$)", {{ + { "d3d11.constantBufferRangeCheck", "True" }, + }} }, + /* Saints Row: The Third */ + { R"(\\SaintsRowTheThird_DX11\.exe$)", {{ + { "d3d11.constantBufferRangeCheck", "True" }, + }} }, + /* Crysis 3 - slower if it notices AMD card * + * Apitrace mode helps massively in cpu bound * + * game parts */ + { R"(\\Crysis3\.exe$)", {{ + { "dxgi.customVendorId", "10de" }, + { "d3d11.cachedDynamicResources", "a" }, + }} }, + /* Crysis 3 Remastered * + * Apitrace mode helps massively in cpu bound * + * game parts */ + { R"(\\Crysis3Remastered\.exe$)", {{ + { "d3d11.cachedDynamicResources", "a" }, + }} }, + /* Atelier series - games try to render video * + * with a D3D9 swap chain over the DXGI swap * + * chain, which breaks D3D11 presentation */ + { R"(\\Atelier_(Ayesha|Escha_and_Logy|Shallie)(_EN)?\.exe$)", {{ + { "d3d9.deferSurfaceCreation", "True" }, + }} }, + /* Atelier Firis */ + { R"(\\A18\.exe$)", {{ + { "d3d9.deferSurfaceCreation", "True" }, + }} }, + /* Atelier Rorona/Totori/Meruru */ + { R"(\\A(11R|12V|13V)_x64_Release(_en)?\.exe$)", {{ + { "d3d9.deferSurfaceCreation", "True" }, + }} }, + /* Just how many of these games are there? */ + { R"(\\Atelier_(Lulua|Lydie_and_Suelle|Ryza(_2)?|Sophie_2)\.exe$)", {{ + { "d3d9.deferSurfaceCreation", "True" }, + }} }, + /* ... */ + { R"(\\Atelier_(Lydie_and_Suelle|Firis|Sophie)_DX\.exe$)", {{ + { "d3d9.deferSurfaceCreation", "True" }, + }} }, + /* Fairy Tail */ + { R"(\\FAIRY_TAIL\.exe$)", {{ + { "d3d9.deferSurfaceCreation", "True" }, + }} }, + /* Nights of Azure */ + { R"(\\CNN\.exe$)", {{ + { "d3d9.deferSurfaceCreation", "True" }, + }} }, + /* Star Wars Battlefront II: amdags issues */ + { R"(\\starwarsbattlefrontii\.exe$)", {{ + { "dxgi.customVendorId", "10de" }, + }} }, + /* F1 games - do not synchronize TGSM access * + * in a compute shader, causing artifacts */ + { R"(\\F1_20(1[89]|[2-9][0-9])\.exe$)", {{ + { "d3d11.forceTgsmBarriers", "True" }, + }} }, + /* Blue Reflection */ + { R"(\\BLUE_REFLECTION\.exe$)", {{ + { "d3d11.constantBufferRangeCheck", "True" }, + }} }, + /* Secret World Legends */ + { R"(\\SecretWorldLegendsDX11\.exe$)", {{ + { "d3d11.constantBufferRangeCheck", "True" }, + }} }, + /* Darksiders Warmastered - apparently reads * + * from write-only mapped buffers */ + { R"(\\darksiders1\.exe$)", {{ + { "d3d11.cachedDynamicResources", "a" }, + }} }, + /* Monster Hunter World */ + { R"(\\MonsterHunterWorld\.exe$)", {{ + { "d3d11.cachedDynamicResources", "a" }, + }} }, + /* Kingdome Come: Deliverance */ + { R"(\\KingdomCome\.exe$)", {{ + { "d3d11.cachedDynamicResources", "a" }, + }} }, + /* Homefront: The Revolution */ + { R"(\\Homefront2_Release\.exe$)", {{ + { "d3d11.cachedDynamicResources", "a" }, + }} }, + /* Sniper Ghost Warrior Contracts */ + { R"(\\SGWContracts\.exe$)", {{ + { "d3d11.cachedDynamicResources", "a" }, + }} }, + /* Armored Warfare */ + { R"(\\armoredwarfare\.exe$)", {{ + { "d3d11.cachedDynamicResources", "c" }, + }} }, + /* Shadow of the Tomb Raider - invariant * + * position breaks character rendering on NV */ + { R"(\\SOTTR\.exe$)", {{ + { "d3d11.invariantPosition", "False" }, + { "d3d11.floatControls", "False" }, + }} }, + /* Nioh 2 */ + { R"(\\nioh2\.exe$)", {{ + { "dxgi.deferSurfaceCreation", "True" }, + }} }, + /* DIRT 5 - uses amd_ags_x64.dll when it * + * detects an AMD GPU */ + { R"(\\DIRT5\.exe$)", {{ + { "dxgi.customVendorId", "10de" }, + }} }, + /* Crazy Machines 3 - crashes on long device * + * descriptions */ + { R"(\\cm3\.exe$)", {{ + { "dxgi.customDeviceDesc", "DXVK Adapter" }, + }} }, + /* World of Final Fantasy: Broken and useless * + * use of 4x MSAA throughout the renderer */ + { R"(\\WOFF\.exe$)", {{ + { "d3d11.disableMsaa", "True" }, + }} }, + /* Final Fantasy XIV - Stuttering on NV */ + { R"(\\ffxiv_dx11\.exe$)", {{ + { "dxvk.shrinkNvidiaHvvHeap", "True" }, + { "d3d11.cachedDynamicResources", "vi" }, + }} }, + /* God of War - relies on NVAPI/AMDAGS for * + * barrier stuff, needs nvapi for DLSS */ + { R"(\\GoW\.exe$)", {{ + { "d3d11.ignoreGraphicsBarriers", "True" }, + { "d3d11.relaxedBarriers", "True" }, + { "dxgi.nvapiHack", "False" }, + { "dxgi.maxFrameLatency", "1" }, + }} }, + /* AoE 2 DE - runs poorly for some users */ + { R"(\\AoE2DE_s\.exe$)", {{ + { "d3d11.cachedDynamicResources", "a" }, + }} }, + /* Total War: Warhammer III */ + { R"(\\Warhammer3\.exe$)", {{ + { "d3d11.maxDynamicImageBufferSize", "4096" }, + }} }, + /* Assassin's Creed 3 and 4 */ + { R"(\\ac(3|4bf)[sm]p\.exe$)", {{ + { "d3d11.cachedDynamicResources", "a" }, + }} }, + /* Stranger of Paradise - FF Origin */ + { R"(\\SOPFFO\.exe$)", {{ + { "d3d9.deferSurfaceCreation", "True" }, + /* Small Radios Big Televisions */ + }} }, + { R"(\\SRBT\.exe$)", {{ + { "d3d9.deferSurfaceCreation", "True" }, + }} }, + /* A Way Out: fix for stuttering and low fps */ + { R"(\\AWayOut(_friend)?\.exe$)", {{ + { "dxgi.maxFrameLatency", "1" }, + }} }, + /* Garden Warfare 2 + Won't start on amd Id without atiadlxx */ + { R"(\\GW2.Main_Win64_Retail\.exe$)", {{ + { "dxgi.customVendorId", "10de" }, + }} }, + /* DayZ */ + { R"(\\DayZ_x64\.exe$)", {{ + { "d3d11.cachedDynamicResources", "cr" }, + }} }, + /* Stray - writes to the same UAV every draw, * + * presumably for culling, which doesn't play * + * nicely with D3D11 without vendor libraries */ + { R"(\\Stray-Win64-Shipping\.exe$)", {{ + { "d3d11.ignoreGraphicsBarriers", "True" }, + }} }, + + /**********************************************/ + /* D3D9 GAMES */ + /**********************************************/ + + /* A Hat in Time */ + { R"(\\HatinTimeGame\.exe$)", {{ + { "d3d9.strictPow", "False" }, + { "d3d9.lenientClear", "True" }, + }} }, + /* Anarchy Online */ + { R"(\\anarchyonline\.exe$)", {{ + { "d3d9.memoryTrackTest", "True" }, + }} }, + /* Borderlands 2 and The Pre Sequel! */ + { R"(\\Borderlands(2|PreSequel)\.exe$)", {{ + { "d3d9.lenientClear", "True" }, + { "d3d9.supportDFFormats", "False" }, + }} }, + /* Borderlands */ + { R"(\\Borderlands\.exe$)", {{ + { "d3d9.lenientClear", "True" }, + }} }, + /* Gothic 3 */ + { R"(\\Gothic(3|3Final| III Forsaken Gods)\.exe$)", {{ + { "d3d9.supportDFFormats", "False" }, + }} }, + /* Sonic Adventure 2 */ + { R"(\\Sonic Adventure 2\\(launcher|sonic2app)\.exe$)", {{ + { "d3d9.floatEmulation", "Strict" }, + }} }, + /* The Sims 2, + Body Shop, + The Sims Life Stories, + The Sims Pet Stories, + and The Sims Castaway Stories */ + { R"(\\(Sims2.*|TS2BodyShop|SimsLS|SimsPS|SimsCS)\.exe$)", {{ + { "d3d9.customVendorId", "10de" }, + { "d3d9.customDeviceId", "0091" }, + { "d3d9.customDeviceDesc", "GeForce 7800 GTX" }, + { "d3d9.disableA8RT", "True" }, + { "d3d9.supportX4R4G4B4", "False" }, + { "d3d9.maxAvailableMemory", "2048" }, + { "d3d9.memoryTrackTest", "True" }, + }} }, + /* Dead Space uses the a NULL render target instead + of a 1x1 one if DF24 is NOT supported + Mouse and physics issues above 60 FPS + Built-in Vsync Locks the game to 30 FPS */ + { R"(\\Dead Space\.exe$)", {{ + { "d3d9.supportDFFormats", "False" }, + { "d3d9.maxFrameRate", "60" }, + { "d3d9.presentInterval", "1" }, + }} }, + /* Halo CE/HaloPC */ + { R"(\\halo(ce)?\.exe$)", {{ + // Game enables minor decal layering fixes + // specifically when it detects AMD. + // Avoids chip being detected as unsupported + // when on intel. Avoids possible path towards + // invalid texture addressing methods. + { "d3d9.customVendorId", "1002" }, + // Avoids card not recognized error. + // Keeps game's rendering methods consistent + // for optimal compatibility. + { "d3d9.customDeviceId", "4172" }, + // The game uses incorrect sampler types in + // the shaders for glass rendering which + // breaks it on native + us if we don't + // spec-constantly chose the sampler type + // automagically. + { "d3d9.forceSamplerTypeSpecConstants", "True" }, + }} }, + /* Counter Strike: Global Offensive + Needs NVAPI to avoid a forced AO + Smoke + exploit so we must force AMD vendor ID. */ + { R"(\\csgo\.exe$)", {{ + { "d3d9.customVendorId", "1002" }, + }} }, + /* Vampire - The Masquerade Bloodlines */ + { R"(\\vampire\.exe$)", {{ + { "d3d9.deferSurfaceCreation", "True" }, + { "d3d9.memoryTrackTest", "True" }, + { "d3d9.maxAvailableMemory", "1024" }, + }} }, + /* Senran Kagura Shinovi Versus */ + { R"(\\SKShinoviVersus\.exe$)", {{ + { "d3d9.forceAspectRatio", "16:9" }, + }} }, + /* Metal Slug X */ + { R"(\\mslugx\.exe$)", {{ + { "d3d9.supportD32", "False" }, + }} }, + /* Skyrim (NVAPI) */ + { R"(\\TESV\.exe$)", {{ + { "d3d9.customVendorId", "1002" }, + }} }, + /* RTHDRIBL Demo + Uses DONOTWAIT after GetRenderTargetData + then goes into an infinite loop if it gets + D3DERR_WASSTILLDRAWING. + This is a better solution than penalizing + other apps that use this properly. */ + { R"(\\rthdribl\.exe$)", {{ + { "d3d9.allowDoNotWait", "False" }, + }} }, + /* Hyperdimension Neptunia U: Action Unleashed */ + { R"(\\Neptunia\.exe$)", {{ + { "d3d9.forceAspectRatio", "16:9" }, + }} }, + /* D&D - The Temple Of Elemental Evil */ + { R"(\\ToEE\.exe$)", {{ + { "d3d9.allowDiscard", "False" }, + }} }, + /* ZUSI 3 - Aerosoft Edition */ + { R"(\\ZusiSim\.exe$)", {{ + { "d3d9.noExplicitFrontBuffer", "True" }, + }} }, + /* GTA IV (NVAPI) */ + /* Also thinks we're always on Intel * + * and will report/use bad amounts of VRAM. */ + { R"(\\GTAIV\.exe$)", {{ + { "d3d9.customVendorId", "1002" }, + { "dxgi.emulateUMA", "True" }, + }} }, + /* Battlefield 2 (bad z-pass) */ + { R"(\\BF2\.exe$)", {{ + { "d3d9.longMad", "True" }, + }} }, + /* SpellForce 2 Series */ + { R"(\\SpellForce2.*\.exe$)", {{ + { "d3d9.forceSamplerTypeSpecConstants", "True" }, + }} }, + /* Everquest 2 */ + { R"(\\EverQuest2.*\.exe$)", {{ + { "d3d9.alphaTestWiggleRoom", "True" }, + }} }, + /* Tomb Raider: Legend */ + { R"(\\trl\.exe$)", {{ + { "d3d9.apitraceMode", "True" }, + }} }, + /* Everquest */ + { R"(\\eqgame\.exe$)", {{ + { "d3d9.apitraceMode", "True" }, + }} }, + /* Dark Messiah of Might & Magic */ + { R"(\\mm\.exe$)", {{ + { "d3d9.deferSurfaceCreation", "True" }, + { "d3d9.memoryTrackTest", "True" }, + }} }, + /* Mafia 2 */ + { R"(\\mafia2\.exe$)", {{ + { "d3d9.customVendorId", "10de" }, + { "d3d9.customDeviceId", "0402" }, + }} }, + /* Warhammer: Online */ + { R"(\\WAR(-64)?\.exe$)", {{ + { "d3d9.customVendorId", "1002" }, + }} }, + /* Dragon Nest */ + { R"(\\DragonNest_x64\.exe$)", {{ + { "d3d9.memoryTrackTest ", "True" }, + }} }, + /* Dal Segno */ + { R"(\\DST\.exe$)", {{ + { "d3d9.deferSurfaceCreation", "True" }, + }} }, + /* Kohan II */ + { R"(\\k2\.exe$)", {{ + { "d3d9.memoryTrackTest", "True" }, + }} }, + /* Ninja Gaiden Sigma 1/2 */ + { R"(\\NINJA GAIDEN SIGMA(2)?\.exe$)", {{ + { "d3d9.deferSurfaceCreation", "True" }, + }} }, + /* Demon Stone breaks at frame rates > 60fps */ + { R"(\\Demonstone\.exe$)", {{ + { "d3d9.maxFrameRate", "60" }, + }} }, + /* Far Cry 1 has worse water rendering when it detects AMD GPUs */ + { R"(\\FarCry\.exe$)", {{ + { "d3d9.customVendorId", "10de" }, + }} }, + /* Earth Defense Force 5 */ + { R"(\\EDF5\.exe$)", {{ + { "dxgi.tearFree", "False" }, + { "dxgi.syncInterval", "1" }, + }} }, + /* Sine Mora EX */ + { R"(\\SineMoraEX\.exe$)", {{ + { "d3d9.maxFrameRate", "60" }, + }} }, + /* Fantasy Grounds */ + { R"(\\FantasyGrounds\.exe$)", {{ + { "d3d9.noExplicitFrontBuffer", "True" }, + }} }, + /* Red Orchestra 2 */ + { R"(\\ROGame\.exe$)", {{ + { "d3d9.floatEmulation", "Strict" }, + }} }, + /* Dark Souls II */ + { R"(\\DarkSoulsII\.exe$)", {{ + { "d3d9.floatEmulation", "Strict" }, + }} }, + /* Dogfight 1942 */ + { R"(\\Dogfight1942\.exe$)", {{ + { "d3d9.floatEmulation", "Strict" }, + }} }, + /* Bayonetta */ + { R"(\\Bayonetta\.exe$)", {{ + { "d3d9.floatEmulation", "Strict" }, + }} }, + /* Rayman Origins */ + { R"(\\Rayman Origins\.exe$)", {{ + { "d3d9.floatEmulation", "Strict" }, + }} }, + /* Guilty Gear Xrd -Relevator- */ + { R"(\\GuiltyGearXrd\.exe$)", {{ + { "d3d9.floatEmulation", "Strict" }, + }} }, + /* Richard Burns Rally */ + { R"(\\RichardBurnsRally_SSE\.exe$)", {{ + { "d3d9.floatEmulation", "Strict" }, + }} }, + /* BlazBlue Centralfiction */ + { R"(\\BBCF\.exe$)", {{ + { "d3d9.floatEmulation", "Strict" }, + }} }, + /* Resident Evil games */ + { R"(\\(rerev|rerev2|re0hd|bhd|re5dx9|BH6)\.exe$)", {{ + { "d3d9.allowDirectBufferMapping", "False" }, + }} }, + /* Limbo */ + { R"(\\limbo\.exe$)", {{ + { "d3d9.maxFrameRate", "60" }, + }} }, + /* Warhammer: Return of Reckoning Launcher + Forcing SM1 fixes a black window otherwise caused by + the lack of support for partial presentation */ + { R"(\\RoRLauncher\.exe$)", {{ + { "d3d9.shaderModel", "1" }, + }} }, + /* Halo CE SPV3 launcher + Same issue as Warhammer: RoR above */ + { R"(\\spv3\.exe$)", {{ + { "d3d9.shaderModel", "1" }, + }} }, + /* Star Wars The Force Unleashed 2 * + * Black particles because it tries to bind * + * a 2D texture for a shader that * + * declares a 3d texture. */ + { R"(\\SWTFU2\.exe$)", {{ + { "d3d9.forceSamplerTypeSpecConstants", "True" }, + }} }, + /* Scrapland (Remastered) */ + { R"(\\Scrap\.exe$)", {{ + { "d3d9.deferSurfaceCreation", "True" }, + }} }, + /* Majesty 2 (Collection) * + * Crashes on UMA without a memory limit, * + * since the game(s) will allocate all * + * available VRAM on startup. */ + { R"(\\Majesty2\.exe$)", {{ + { "d3d9.memoryTrackTest", "True" }, + { "d3d9.maxAvailableMemory", "2048" }, + }} }, + /* Myst V End of Ages + Game has white textures on amd radv. + Expects Nvidia, Intel or ATI VendorId. + "Radeon" in gpu description also works */ + { R"(\\eoa\.exe$)", {{ + { "d3d9.customVendorId", "10de" }, + }} }, + /* Beyond Good And Evil * + * Fixes missing sun and light shafts */ + { R"(\\BGE\.exe$)", {{ + { "d3d9.allowDoNotWait", "False" }, + }} }, + /* Supreme Commander & Forged Alliance Forever */ + { R"(\\(SupremeCommander|ForgedAlliance)\.exe$)", {{ + { "d3d9.floatEmulation", "Strict" }, + }} }, + /* Star Wars The Old Republic */ + { R"(\\swtor\.exe$)", {{ + { "d3d9.forceSamplerTypeSpecConstants", "True" }, + }} }, + /* Bionic Commando + Physics break at high fps */ + { R"(\\bionic_commando\.exe$)", {{ + { "d3d9.maxFrameRate", "60" }, + }} }, + /* Port Royale 3 * + * Fixes infinite loading screens */ + { R"(\\PortRoyale3\.exe$)", {{ + { "d3d9.allowDoNotWait", "False" }, + }} }, + /* Need For Speed 3 modern patch */ + { R"(\\nfs3\.exe$)", {{ + { "d3d9.enableDialogMode", "True" }, + }} }, + /* Ninja Blade * + * Transparent main character on Nvidia */ + { R"(\\NinjaBlade\.exe$)", {{ + { "d3d9.alphaTestWiggleRoom", "True" }, + }} }, + /* YS Origin * + * Helps very bad frametimes in some areas */ + { R"(\\yso_win\.exe$)", {{ + { "d3d9.maxFrameLatency", "1" }, + }} }, + }}; + + + static bool isWhitespace(char ch) { + return ch == ' ' || ch == '\x9' || ch == '\r'; + } + + + static bool isValidKeyChar(char ch) { + return (ch >= '0' && ch <= '9') + || (ch >= 'A' && ch <= 'Z') + || (ch >= 'a' && ch <= 'z') + || (ch == '.' || ch == '_'); + } + + + static size_t skipWhitespace(const std::string& line, size_t n) { + while (n < line.size() && isWhitespace(line[n])) + n += 1; + return n; + } + + + struct ConfigContext { + bool active; + }; + + + static void parseUserConfigLine(Config& config, ConfigContext& ctx, const std::string& line) { + std::stringstream key; + std::stringstream value; + + // Extract the key + size_t n = skipWhitespace(line, 0); + + if (n < line.size() && line[n] == '[') { + n += 1; + + size_t e = line.size() - 1; + while (e > n && line[e] != ']') + e -= 1; + + while (n < e) + key << line[n++]; + + ctx.active = key.str() == env::getExeName(); + } else { + while (n < line.size() && isValidKeyChar(line[n])) + key << line[n++]; + + // Check whether the next char is a '=' + n = skipWhitespace(line, n); + if (n >= line.size() || line[n] != '=') + return; + + // Extract the value + bool insideString = false; + n = skipWhitespace(line, n + 1); + + while (n < line.size()) { + if (!insideString && isWhitespace(line[n])) + break; + + if (line[n] == '"') { + insideString = !insideString; + n++; + } else + value << line[n++]; + } + + if (ctx.active) + config.setOption(key.str(), value.str()); + } + } + + + Config::Config() { } + Config::~Config() { } + + + Config::Config(OptionMap&& options) + : m_options(std::move(options)) { } + + + void Config::merge(const Config& other) { + for (auto& pair : other.m_options) + m_options.insert(pair); + } + + + void Config::setOption(const std::string& key, const std::string& value) { + m_options.insert_or_assign(key, value); + } + + + std::string Config::getOptionValue(const char* option) const { + auto iter = m_options.find(option); + + return iter != m_options.end() + ? iter->second : std::string(); + } + + + bool Config::parseOptionValue( + const std::string& value, + std::string& result) { + result = value; + return true; + } + + + bool Config::parseOptionValue( + const std::string& value, + bool& result) { + static const std::array, 2> s_lookup = {{ + { "true", true }, + { "false", false }, + }}; + + return parseStringOption(value, + s_lookup.begin(), s_lookup.end(), result); + } + + + bool Config::parseOptionValue( + const std::string& value, + int32_t& result) { + if (value.size() == 0) + return false; + + // Parse sign, don't allow '+' + int32_t sign = 1; + size_t start = 0; + + if (value[0] == '-') { + sign = -1; + start = 1; + } + + // Parse absolute number + int32_t intval = 0; + + for (size_t i = start; i < value.size(); i++) { + if (value[i] < '0' || value[i] > '9') + return false; + + intval *= 10; + intval += value[i] - '0'; + } + + // Apply sign and return + result = sign * intval; + return true; + } + + + bool Config::parseOptionValue( + const std::string& value, + Tristate& result) { + static const std::array, 3> s_lookup = {{ + { "true", Tristate::True }, + { "false", Tristate::False }, + { "auto", Tristate::Auto }, + }}; + + return parseStringOption(value, + s_lookup.begin(), s_lookup.end(), result); + } + + + template + bool Config::parseStringOption( + std::string str, + I begin, + I end, + V& value) { + str = Config::toLower(str); + + for (auto i = begin; i != end; i++) { + if (str == i->first) { + value = i->second; + return true; + } + } + + return false; + } + + + Config Config::getAppConfig(const std::string& appName) { + auto appConfig = std::find_if(g_appDefaults.begin(), g_appDefaults.end(), + [&appName] (const std::pair& pair) { + std::regex expr(pair.first, std::regex::extended | std::regex::icase); + return std::regex_search(appName, expr); + }); + + if (appConfig != g_appDefaults.end()) { + // Inform the user that we loaded a default config + Logger::info(str::format("Found built-in config:")); + + for (auto& pair : appConfig->second.m_options) + Logger::info(str::format(" ", pair.first, " = ", pair.second)); + + return appConfig->second; + } + + return Config(); + } + + + Config Config::getUserConfig() { + Config config; + + // Load either $DXVK_CONFIG_FILE or $PWD/dxvk.conf + std::string filePath = env::getEnvVar("DXVK_CONFIG_FILE"); + + if (filePath == "") + filePath = "dxvk.conf"; + + // Open the file if it exists + std::ifstream stream(str::tows(filePath.c_str()).c_str()); + + if (!stream) + return config; + + // Inform the user that we loaded a file, might + // help when debugging configuration issues + Logger::info(str::format("Found config file: ", filePath)); + + // Initialize parser context + ConfigContext ctx; + ctx.active = true; + + // Parse the file line by line + std::string line; + + while (std::getline(stream, line)) + parseUserConfigLine(config, ctx, line); + + return config; + } + + + void Config::logOptions() const { + if (!m_options.empty()) { + Logger::info("Effective configuration:"); + + for (auto& pair : m_options) + Logger::info(str::format(" ", pair.first, " = ", pair.second)); + } + } + + std::string Config::toLower(std::string str) { + std::transform(str.begin(), str.end(), str.begin(), + [] (unsigned char c) { return (c >= 'A' && c <= 'Z') ? (c + 'a' - 'A') : c; }); + return str; + } + +} diff --git a/utils/dxvk-1.10.3/src/util/config/config.h b/utils/dxvk-1.10.3/src/util/config/config.h new file mode 100644 index 00000000000..f947272caa3 --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/config/config.h @@ -0,0 +1,154 @@ +#pragma once + +#include +#include + +namespace dxvk { + + /** + * \brief Tri-state + * + * Used to conditionally override + * booleans if desired. + */ + enum class Tristate : int32_t { + Auto = -1, + False = 0, + True = 1, + }; + + /** + * \brief Config option set + * + * Stores configuration options + * as a set of key-value pairs. + */ + class Config { + using OptionMap = std::unordered_map; + public: + + Config(); + Config(OptionMap&& options); + ~Config(); + + /** + * \brief Merges two configuration sets + * + * Options specified in this config object will + * not be overridden if they are specified in + * the second config object. + * \param [in] other Config set to merge. + */ + void merge(const Config& other); + + /** + * \brief Sets an option + * + * \param [in] key Option name + * \param [in] value Option value + */ + void setOption( + const std::string& key, + const std::string& value); + + /** + * \brief Parses an option value + * + * Retrieves the option value as a string, and then + * tries to convert that string to the given type. + * If parsing the string fails because it is either + * invalid or if the option is not defined, this + * method will return a fallback value. + * + * Currently, this supports the types \c bool, + * \c int32_t, and \c std::string. + * \tparam T Return value type + * \param [in] option Option name + * \param [in] fallback Fallback value + * \returns Parsed option value + * \returns The parsed option value + */ + template + T getOption(const char* option, T fallback = T()) const { + const std::string& value = getOptionValue(option); + + T result = fallback; + parseOptionValue(value, result); + return result; + } + + /** + * \brief Logs option values + * + * Prints the effective configuration + * to the log for debugging purposes. + */ + void logOptions() const; + + /** + * \brief Retrieves default options for an app + * + * \param [in] appName Name of the application + * \returns Default options for the application + */ + static Config getAppConfig(const std::string& appName); + + /** + * \brief Retrieves user configuration + * + * Reads options from the configuration file, + * if it can be found, or an empty option set. + * \returns User-defined configuration options + */ + static Config getUserConfig(); + + static std::string toLower(std::string str); + + private: + + OptionMap m_options; + + std::string getOptionValue( + const char* option) const; + + static bool parseOptionValue( + const std::string& value, + std::string& result); + + static bool parseOptionValue( + const std::string& value, + bool& result); + + static bool parseOptionValue( + const std::string& value, + int32_t& result); + + static bool parseOptionValue( + const std::string& value, + Tristate& result); + + template + static bool parseStringOption( + std::string str, + I begin, + I end, + V& value); + + }; + + + /** + * \brief Applies tristate option + * + * Overrides the given value if \c state is + * \c True or \c False, and leaves it intact + * otherwise. + * \param [out] option The value to override + * \param [in] state Tristate to apply + */ + inline void applyTristate(bool& option, Tristate state) { + option &= state != Tristate::False; + option |= state == Tristate::True; + } + +} diff --git a/utils/dxvk-1.10.3/src/util/meson.build b/utils/dxvk-1.10.3/src/util/meson.build new file mode 100644 index 00000000000..34da01eeb1a --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/meson.build @@ -0,0 +1,33 @@ +util_src = files([ + 'util_env.cpp', + 'util_string.cpp', + 'util_fps_limiter.cpp', + 'util_gdi.cpp', + 'util_luid.cpp', + 'util_matrix.cpp', + 'util_monitor.cpp', + 'util_shared_res.cpp', + + 'thread.cpp', + + 'com/com_guid.cpp', + 'com/com_private_data.cpp', + + 'config/config.cpp', + + 'log/log.cpp', + 'log/log_debug.cpp', + + 'sha1/sha1.c', + 'sha1/sha1_util.cpp', + + 'sync/sync_recursive.cpp', +]) + +util_lib = static_library('util', util_src, + include_directories : [ dxvk_include_path ], +) + +util_dep = declare_dependency( + link_with : [ util_lib ], +) diff --git a/utils/dxvk-1.10.3/src/util/rc/util_rc.h b/utils/dxvk-1.10.3/src/util/rc/util_rc.h new file mode 100644 index 00000000000..c33d0c61425 --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/rc/util_rc.h @@ -0,0 +1,36 @@ +#pragma once + +#include + +namespace dxvk { + + /** + * \brief Reference-counted object + */ + class RcObject { + + public: + + /** + * \brief Increments reference count + * \returns New reference count + */ + uint32_t incRef() { + return ++m_refCount; + } + + /** + * \brief Decrements reference count + * \returns New reference count + */ + uint32_t decRef() { + return --m_refCount; + } + + private: + + std::atomic m_refCount = { 0u }; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/util/rc/util_rc_ptr.h b/utils/dxvk-1.10.3/src/util/rc/util_rc_ptr.h new file mode 100644 index 00000000000..23c5c43d518 --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/rc/util_rc_ptr.h @@ -0,0 +1,124 @@ +#pragma once + +#include +#include + +namespace dxvk { + + /** + * \brief Pointer for reference-counted objects + * + * This only requires the given type to implement \c incRef + * and \c decRef methods that adjust the reference count. + * \tparam T Object type + */ + template + class Rc { + template + friend class Rc; + public: + + Rc() { } + Rc(std::nullptr_t) { } + + Rc(T* object) + : m_object(object) { + this->incRef(); + } + + Rc(const Rc& other) + : m_object(other.m_object) { + this->incRef(); + } + + template + Rc(const Rc& other) + : m_object(other.m_object) { + this->incRef(); + } + + Rc(Rc&& other) + : m_object(other.m_object) { + other.m_object = nullptr; + } + + template + Rc(Rc&& other) + : m_object(other.m_object) { + other.m_object = nullptr; + } + + Rc& operator = (std::nullptr_t) { + this->decRef(); + m_object = nullptr; + return *this; + } + + Rc& operator = (const Rc& other) { + other.incRef(); + this->decRef(); + m_object = other.m_object; + return *this; + } + + template + Rc& operator = (const Rc& other) { + other.incRef(); + this->decRef(); + m_object = other.m_object; + return *this; + } + + Rc& operator = (Rc&& other) { + this->decRef(); + this->m_object = other.m_object; + other.m_object = nullptr; + return *this; + } + + template + Rc& operator = (Rc&& other) { + this->decRef(); + this->m_object = other.m_object; + other.m_object = nullptr; + return *this; + } + + ~Rc() { + this->decRef(); + } + + T& operator * () const { return *m_object; } + T* operator -> () const { return m_object; } + T* ptr() const { return m_object; } + + bool operator == (const Rc& other) const { return m_object == other.m_object; } + bool operator != (const Rc& other) const { return m_object != other.m_object; } + + bool operator == (std::nullptr_t) const { return m_object == nullptr; } + bool operator != (std::nullptr_t) const { return m_object != nullptr; } + + private: + + T* m_object = nullptr; + + void incRef() const { + if (m_object != nullptr) + m_object->incRef(); + } + + void decRef() const { + if (m_object != nullptr) { + if (m_object->decRef() == 0) + delete m_object; + } + } + + }; + +} + +template +std::ostream& operator << (std::ostream& os, const dxvk::Rc& rc) { + return os << rc.ptr(); +} diff --git a/utils/dxvk-1.10.3/src/util/sha1/sha1.c b/utils/dxvk-1.10.3/src/util/sha1/sha1.c new file mode 100644 index 00000000000..2782dd5a9e1 --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/sha1/sha1.c @@ -0,0 +1,170 @@ +/* $OpenBSD: sha1.c,v 1.26 2015/09/11 09:18:27 guenther Exp $ */ + +/* + * SHA-1 in C + * By Steve Reid + * 100% Public Domain + * + * Test Vectors (from FIPS PUB 180-1) + * "abc" + * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D + * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 + * A million repetitions of "a" + * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F + */ + +#include +#include +#include "sha1.h" + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +/* + * blk0() and blk() perform the initial expand. + * I got the idea of expanding during the round function from SSLeay + */ +# define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ + |(rol(block->l[i],8)&0x00FF00FF)) + +#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ + ^block->l[(i+2)&15]^block->l[i&15],1)) + +/* + * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1 + */ +#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); +#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); +#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); + +typedef union { + uint8_t c[64]; + uint32_t l[16]; +} CHAR64LONG16; + +/* + * Hash a single 512-bit block. This is the core of the algorithm. + */ +void +SHA1Transform(uint32_t state[5], const uint8_t* buffer) +{ + uint32_t a, b, c, d, e; + uint8_t workspace[SHA1_BLOCK_LENGTH]; + CHAR64LONG16 *block = (CHAR64LONG16 *)workspace; + + (void)memcpy(block, buffer, SHA1_BLOCK_LENGTH); + + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); + R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); + + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + + /* Wipe variables */ + a = b = c = d = e = 0; +} + + +/* + * SHA1Init - Initialize new context + */ +void +SHA1Init(SHA1_CTX *context) +{ + + /* SHA1 initialization constants */ + context->count = 0; + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; +} + + +/* + * Run your data through this. + */ +void +SHA1Update(SHA1_CTX *context, const uint8_t *data, size_t len) +{ + size_t i, j; + + j = (size_t)((context->count >> 3) & 63); + context->count += (len << 3); + if ((j + len) > 63) { + (void)memcpy(&context->buffer[j], data, (i = 64-j)); + SHA1Transform(context->state, context->buffer); + for ( ; i + 63 < len; i += 64) + SHA1Transform(context->state, (uint8_t *)&data[i]); + j = 0; + } else { + i = 0; + } + (void)memcpy(&context->buffer[j], &data[i], len - i); +} + + +/* + * Add padding and return the message digest. + */ +void +SHA1Pad(SHA1_CTX *context) +{ + uint8_t finalcount[8]; + uint32_t i; + + for (i = 0; i < 8; i++) { + finalcount[i] = (uint8_t)((context->count >> + ((7 - (i & 7)) * 8)) & 255); /* Endian independent */ + } + SHA1Update(context, (uint8_t *)"\200", 1); + while ((context->count & 504) != 448) + SHA1Update(context, (uint8_t *)"\0", 1); + SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ +} + +void +SHA1Final(uint8_t digest[SHA1_DIGEST_LENGTH], SHA1_CTX *context) +{ + uint32_t i; + + SHA1Pad(context); + for (i = 0; i < SHA1_DIGEST_LENGTH; i++) { + digest[i] = (uint8_t) + ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); + } + memset(context, 0, sizeof(*context)); +} diff --git a/utils/dxvk-1.10.3/src/util/sha1/sha1.h b/utils/dxvk-1.10.3/src/util/sha1/sha1.h new file mode 100644 index 00000000000..06867b395cc --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/sha1/sha1.h @@ -0,0 +1,53 @@ +/* $OpenBSD: sha1.h,v 1.24 2012/12/05 23:19:57 deraadt Exp $ */ + +/* + * SHA-1 in C + * By Steve Reid + * 100% Public Domain + */ + +#ifndef _SHA1_H +#define _SHA1_H + +#include +#include + +#define SHA1_BLOCK_LENGTH 64 +#define SHA1_DIGEST_LENGTH 20 +#define SHA1_DIGEST_STRING_LENGTH (SHA1_DIGEST_LENGTH * 2 + 1) + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _SHA1_CTX { + uint32_t state[5]; + uint64_t count; + uint8_t buffer[SHA1_BLOCK_LENGTH]; +} SHA1_CTX; + +void SHA1Init(SHA1_CTX *); +void SHA1Pad(SHA1_CTX *); +void SHA1Transform(uint32_t [5], const uint8_t*); +void SHA1Update(SHA1_CTX *, const uint8_t *, size_t); +void SHA1Final(uint8_t [SHA1_DIGEST_LENGTH], SHA1_CTX *); + +#define HTONDIGEST(x) do { \ + x[0] = htonl(x[0]); \ + x[1] = htonl(x[1]); \ + x[2] = htonl(x[2]); \ + x[3] = htonl(x[3]); \ + x[4] = htonl(x[4]); } while (0) + +#define NTOHDIGEST(x) do { \ + x[0] = ntohl(x[0]); \ + x[1] = ntohl(x[1]); \ + x[2] = ntohl(x[2]); \ + x[3] = ntohl(x[3]); \ + x[4] = ntohl(x[4]); } while (0) + +#ifdef __cplusplus +} +#endif + +#endif /* _SHA1_H */ diff --git a/utils/dxvk-1.10.3/src/util/sha1/sha1_util.cpp b/utils/dxvk-1.10.3/src/util/sha1/sha1_util.cpp new file mode 100644 index 00000000000..eefc927573a --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/sha1/sha1_util.cpp @@ -0,0 +1,48 @@ +#include "sha1.h" +#include "sha1_util.h" + +namespace dxvk { + + std::string Sha1Hash::toString() const { + static const char nibbles[] + = { '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + + std::string result; + result.resize(2 * m_digest.size()); + + for (uint32_t i = 0; i < m_digest.size(); i++) { + result.at(2 * i + 0) = nibbles[(m_digest[i] >> 4) & 0xF]; + result.at(2 * i + 1) = nibbles[(m_digest[i] >> 0) & 0xF]; + } + + return result; + } + + + Sha1Hash Sha1Hash::compute( + const void* data, + size_t size) { + Sha1Data chunk = { data, size }; + return compute(1, &chunk); + } + + + Sha1Hash Sha1Hash::compute( + size_t numChunks, + const Sha1Data* chunks) { + Sha1Digest digest; + + SHA1_CTX ctx; + SHA1Init(&ctx); + + for (size_t i = 0; i < numChunks; i++) { + auto ptr = reinterpret_cast(chunks[i].data); + SHA1Update(&ctx, ptr, chunks[i].size); + } + + SHA1Final(digest.data(), &ctx); + return Sha1Hash(digest); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/util/sha1/sha1_util.h b/utils/dxvk-1.10.3/src/util/sha1/sha1_util.h new file mode 100644 index 00000000000..9d83ab8c17e --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/sha1/sha1_util.h @@ -0,0 +1,63 @@ +#pragma once + +#include +#include +#include + +namespace dxvk { + + using Sha1Digest = std::array; + + struct Sha1Data { + const void* data; + size_t size; + }; + + class Sha1Hash { + + public: + + Sha1Hash() { } + Sha1Hash(const Sha1Digest& digest) + : m_digest(digest) { } + + std::string toString() const; + + uint32_t dword(uint32_t id) const { + return uint32_t(m_digest[4 * id + 0]) << 0 + | uint32_t(m_digest[4 * id + 1]) << 8 + | uint32_t(m_digest[4 * id + 2]) << 16 + | uint32_t(m_digest[4 * id + 3]) << 24; + } + + bool operator == (const Sha1Hash& other) const { + return !std::memcmp( + this->m_digest.data(), + other.m_digest.data(), + other.m_digest.size()); + } + + bool operator != (const Sha1Hash& other) const { + return !this->operator == (other); + } + + static Sha1Hash compute( + const void* data, + size_t size); + + static Sha1Hash compute( + size_t numChunks, + const Sha1Data* chunks); + + template + static Sha1Hash compute(const T& data) { + return compute(&data, sizeof(T)); + } + + private: + + Sha1Digest m_digest; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/util/sync/sync_list.h b/utils/dxvk-1.10.3/src/util/sync/sync_list.h new file mode 100644 index 00000000000..9fb50d85207 --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/sync/sync_list.h @@ -0,0 +1,130 @@ +#pragma once + +#include + +namespace dxvk::sync { + + /** + * \brief Lock-free single-linked list + */ + template + class List { + + struct Entry { + Entry(T&& data_) + : data(std::move(data_)), next(nullptr) { } + Entry(const T& data_) + : data(data_), next(nullptr) { } + template + Entry(Args... args) + : data(std::forward(args)...), next(nullptr) { } + + T data; + Entry* next; + }; + + public: + + class Iterator { + + public: + + using iterator_category = std::forward_iterator_tag; + using difference_type = std::ptrdiff_t; + using value_type = T; + using pointer = T*; + using reference = T&; + + Iterator() + : m_entry(nullptr) { } + + Iterator(Entry* e) + : m_entry(e) { } + + reference operator * () const { + return m_entry->data; + } + + pointer operator -> () const { + return &m_entry->data; + } + + Iterator& operator ++ () { + m_entry = m_entry->next; + return *this; + } + + Iterator operator ++ (int) { + Iterator tmp(m_entry); + m_entry = m_entry->next; + return tmp; + } + + bool operator == (const Iterator& other) const { return m_entry == other.m_entry; } + bool operator != (const Iterator& other) const { return m_entry != other.m_entry; } + + private: + + Entry* m_entry; + + }; + + using iterator = Iterator; + + List() + : m_head(nullptr) { } + List(List&& other) + : m_head(other.m_head.exchange(nullptr)) { } + + List& operator = (List&& other) { + freeList(m_head.exchange(other.m_head.exchange(nullptr))); + return *this; + } + + ~List() { + freeList(m_head.load()); + } + + auto begin() const { return Iterator(m_head); } + auto end() const { return Iterator(nullptr); } + + Iterator insert(const T& data) { + return insertEntry(new Entry(data)); + } + + Iterator insert(T&& data) { + return insertEntry(new Entry(std::move(data))); + } + + template + Iterator emplace(Args... args) { + return insertEntry(new Entry(std::forward(args)...)); + } + + private: + + std::atomic m_head; + + Iterator insertEntry(Entry* e) { + Entry* next = m_head.load(std::memory_order_acquire); + + do { + e->next = next; + } while (!m_head.compare_exchange_weak(next, e, + std::memory_order_release, + std::memory_order_acquire)); + + return Iterator(e); + } + + void freeList(Entry* e) { + while (e) { + Entry* next = e->next;; + delete e; + e = next; + } + } + + }; + +} diff --git a/utils/dxvk-1.10.3/src/util/sync/sync_recursive.cpp b/utils/dxvk-1.10.3/src/util/sync/sync_recursive.cpp new file mode 100644 index 00000000000..85af6137d21 --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/sync/sync_recursive.cpp @@ -0,0 +1,36 @@ +#include "sync_recursive.h" +#include "sync_spinlock.h" + +namespace dxvk::sync { + + void RecursiveSpinlock::lock() { + spin(2000, [this] { return try_lock(); }); + } + + + void RecursiveSpinlock::unlock() { + if (likely(m_counter == 0)) + m_owner.store(0, std::memory_order_release); + else + m_counter -= 1; + } + + + bool RecursiveSpinlock::try_lock() { + uint32_t threadId = dxvk::this_thread::get_id(); + uint32_t expected = 0; + + bool status = m_owner.compare_exchange_weak( + expected, threadId, std::memory_order_acquire); + + if (status) + return true; + + if (expected != threadId) + return false; + + m_counter += 1; + return true; + } + +} diff --git a/utils/dxvk-1.10.3/src/util/sync/sync_recursive.h b/utils/dxvk-1.10.3/src/util/sync/sync_recursive.h new file mode 100644 index 00000000000..1bb64db16ac --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/sync/sync_recursive.h @@ -0,0 +1,32 @@ +#pragma once + +#include + +#include "../com/com_include.h" + +namespace dxvk::sync { + + /** + * \brief Recursive spinlock + * + * Implements a spinlock that can be acquired + * by the same thread multiple times. + */ + class RecursiveSpinlock { + + public: + + void lock(); + + void unlock(); + + bool try_lock(); + + private: + + std::atomic m_owner = { 0u }; + uint32_t m_counter = { 0u }; + + }; + +} diff --git a/utils/dxvk-1.10.3/src/util/sync/sync_signal.h b/utils/dxvk-1.10.3/src/util/sync/sync_signal.h new file mode 100644 index 00000000000..cdbcae821b0 --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/sync/sync_signal.h @@ -0,0 +1,160 @@ +#pragma once + +#include +#include +#include + +#include "../rc/util_rc.h" + +#include "../thread.h" + +namespace dxvk::sync { + + /** + * \brief Signal + * + * Interface for a CPU-side fence. Can be signaled + * to a given value, and any thread waiting for a + * lower value will be woken up. + */ + class Signal : public RcObject { + + public: + + virtual ~Signal() { } + + /** + * \brief Last signaled value + * \returns Last signaled value + */ + virtual uint64_t value() const = 0; + + /** + * \brief Notifies signal + * + * Wakes up all threads currently waiting for + * a value lower than \c value. Note that + * \c value must monotonically increase. + * \param [in] value Value to signal to + */ + virtual void signal(uint64_t value) = 0; + + /** + * \brief Waits for signal + * + * Blocks the calling thread until another + * thread signals it with a value equal to + * or greater than \c value. + * \param [in] value The value to wait for + */ + virtual void wait(uint64_t value) = 0; + + }; + + + /** + * \brief Fence + * + * Simple CPU-side fence. + */ + class Fence final : public Signal { + + public: + + Fence() + : m_value(0ull) { } + + explicit Fence(uint64_t value) + : m_value(value) { } + + uint64_t value() const { + return m_value.load(std::memory_order_acquire); + } + + void signal(uint64_t value) { + std::unique_lock lock(m_mutex); + m_value.store(value, std::memory_order_release); + m_cond.notify_all(); + } + + void wait(uint64_t value) { + std::unique_lock lock(m_mutex); + m_cond.wait(lock, [this, value] { + return value <= m_value.load(std::memory_order_acquire); + }); + } + + private: + + std::atomic m_value; + dxvk::mutex m_mutex; + dxvk::condition_variable m_cond; + + }; + + + /** + * \brief Callback signal + * + * CPU-side fence with the ability to call a + * function when signaled to a given value. + */ + class CallbackFence final : public Signal { + + public: + + CallbackFence() + : m_value(0ull) { } + + explicit CallbackFence(uint64_t value) + : m_value(value) { } + + uint64_t value() const { + return m_value.load(std::memory_order_acquire); + } + + void signal(uint64_t value) { + std::unique_lock lock(m_mutex); + m_value.store(value, std::memory_order_release); + m_cond.notify_all(); + + for (auto i = m_callbacks.begin(); i != m_callbacks.end(); ) { + if (value >= i->first) { + i->second(); + i = m_callbacks.erase(i); + } else { + i++; + } + } + } + + void wait(uint64_t value) { + std::unique_lock lock(m_mutex); + m_cond.wait(lock, [this, value] { + return value <= m_value.load(std::memory_order_acquire); + }); + } + + template + void setCallback(uint64_t value, Fn&& proc) { + std::unique_lock lock(m_mutex); + + if (value > this->value()) + m_callbacks.emplace_back(std::piecewise_construct, + std::make_tuple(value), + std::make_tuple(proc)); + else + proc(); + } + + private: + + std::atomic m_value; + dxvk::mutex m_mutex; + dxvk::condition_variable m_cond; + + std::list>> m_callbacks; + + }; + +} diff --git a/utils/dxvk-1.10.3/src/util/sync/sync_spinlock.h b/utils/dxvk-1.10.3/src/util/sync/sync_spinlock.h new file mode 100644 index 00000000000..27157929f92 --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/sync/sync_spinlock.h @@ -0,0 +1,69 @@ +#pragma once + +#include + +#include "../thread.h" + +#include "../util_bit.h" +#include "../util_likely.h" + +namespace dxvk::sync { + + /** + * \brief Generic spin function + * + * Blocks calling thread until a condition becomes + * \c true, calling \c yield every few iterations. + * \param [in] spinCount Number of probes between each yield + * \param [in] fn Condition to test + */ + template + void spin(uint32_t spinCount, const Fn& fn) { + while (unlikely(!fn())) { + for (uint32_t i = 1; i < spinCount; i++) { + _mm_pause(); + if (fn()) + return; + } + + dxvk::this_thread::yield(); + } + } + + /** + * \brief Spin lock + * + * A low-overhead spin lock which can be used to + * protect data structures for a short duration + * in case the structure is not likely contested. + */ + class Spinlock { + + public: + + Spinlock() { } + ~Spinlock() { } + + Spinlock (const Spinlock&) = delete; + Spinlock& operator = (const Spinlock&) = delete; + + void lock() { + spin(200, [this] { return try_lock(); }); + } + + void unlock() { + m_lock.store(0, std::memory_order_release); + } + + bool try_lock() { + return likely(!m_lock.load()) + && likely(!m_lock.exchange(1, std::memory_order_acquire)); + } + + private: + + std::atomic m_lock = { 0 }; + + }; + +} diff --git a/utils/dxvk-1.10.3/src/util/sync/sync_ticketlock.h b/utils/dxvk-1.10.3/src/util/sync/sync_ticketlock.h new file mode 100644 index 00000000000..1c47f839fe5 --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/sync/sync_ticketlock.h @@ -0,0 +1,40 @@ +#pragma once + +#include + +#include "../thread.h" + +namespace dxvk::sync { + + /** + * \brief Ticket spinlock + * + * A fair spinlock implementation that should + * be preferred over \ref Spinlock when one of + * the threads accessing the lock is likely to + * starve another. + */ + class TicketLock { + + public: + + void lock() { + uint32_t ticket = m_counter.fetch_add(1); + + while (m_serving.load(std::memory_order_acquire) != ticket) + continue; + } + + void unlock() { + uint32_t serveNext = m_serving.load() + 1; + m_serving.store(serveNext, std::memory_order_release); + } + + private: + + std::atomic m_counter = { 0 }; + std::atomic m_serving = { 0 }; + + }; + +} diff --git a/utils/dxvk-1.10.3/src/util/thread.cpp b/utils/dxvk-1.10.3/src/util/thread.cpp new file mode 100644 index 00000000000..eed45d34b04 --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/thread.cpp @@ -0,0 +1,27 @@ +#include "thread.h" +#include "util_likely.h" + +#include + +#ifndef _WIN32 + +namespace dxvk::this_thread { + + static std::atomic g_threadCtr = { 0u }; + static thread_local uint32_t g_threadId = 0u; + + // This implementation returns thread ids unique to the current instance. + // ie. if you use this across multiple .so's then you might get conflicting ids. + // + // This isn't an issue for us, as it is only used by the spinlock implementation, + // but may be for you if you use this elsewhere. + uint32_t get_id() { + if (unlikely(!g_threadId)) + g_threadId = ++g_threadCtr; + + return g_threadId; + } + +} + +#endif diff --git a/utils/dxvk-1.10.3/src/util/thread.h b/utils/dxvk-1.10.3/src/util/thread.h new file mode 100644 index 00000000000..bc58d229e20 --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/thread.h @@ -0,0 +1,347 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include "util_error.h" + +#include "./com/com_include.h" + +#include "./rc/util_rc.h" +#include "./rc/util_rc_ptr.h" + +namespace dxvk { + +#ifdef _WIN32 + /** + * \brief Thread priority + */ + enum class ThreadPriority : int32_t { + Lowest = THREAD_PRIORITY_LOWEST, + Low = THREAD_PRIORITY_BELOW_NORMAL, + Normal = THREAD_PRIORITY_NORMAL, + High = THREAD_PRIORITY_ABOVE_NORMAL, + Highest = THREAD_PRIORITY_HIGHEST, + }; + + /** + * \brief Thread helper class + * + * This is needed mostly for winelib builds. Wine needs to setup each thread that + * calls Windows APIs. It means that in winelib builds, we can't let standard C++ + * library create threads and need to use Wine for that instead. We use a thin wrapper + * around Windows thread functions so that the rest of code just has to use + * dxvk::thread class instead of std::thread. + */ + class ThreadFn : public RcObject { + using Proc = std::function; + public: + + ThreadFn(Proc&& proc) + : m_proc(std::move(proc)) { + // Reference for the thread function + this->incRef(); + + m_handle = ::CreateThread(nullptr, 0x100000, + ThreadFn::threadProc, this, STACK_SIZE_PARAM_IS_A_RESERVATION, + nullptr); + + if (m_handle == nullptr) + throw DxvkError("Failed to create thread"); + } + + ~ThreadFn() { + if (this->joinable()) + std::terminate(); + } + + void detach() { + ::CloseHandle(m_handle); + m_handle = nullptr; + } + + void join() { + if(::WaitForSingleObjectEx(m_handle, INFINITE, FALSE) == WAIT_FAILED) + throw DxvkError("Failed to join thread"); + this->detach(); + } + + bool joinable() const { + return m_handle != nullptr; + } + + void set_priority(ThreadPriority priority) { + ::SetThreadPriority(m_handle, int32_t(priority)); + } + + private: + + Proc m_proc; + HANDLE m_handle; + + static DWORD WINAPI threadProc(void *arg) { + auto thread = reinterpret_cast(arg); + thread->m_proc(); + thread->decRef(); + return 0; + } + + }; + + + /** + * \brief RAII thread wrapper + * + * Wrapper for \c ThreadFn that can be used + * as a drop-in replacement for \c std::thread. + */ + class thread { + + public: + + thread() { } + + explicit thread(std::function&& func) + : m_thread(new ThreadFn(std::move(func))) { } + + thread(thread&& other) + : m_thread(std::move(other.m_thread)) { } + + thread& operator = (thread&& other) { + m_thread = std::move(other.m_thread); + return *this; + } + + void detach() { + m_thread->detach(); + } + + void join() { + m_thread->join(); + } + + bool joinable() const { + return m_thread != nullptr + && m_thread->joinable(); + } + + void set_priority(ThreadPriority priority) { + m_thread->set_priority(priority); + } + + static uint32_t hardware_concurrency() { + SYSTEM_INFO info = { }; + ::GetSystemInfo(&info); + return info.dwNumberOfProcessors; + } + + private: + + Rc m_thread; + + }; + + + namespace this_thread { + inline void yield() { + SwitchToThread(); + } + + inline uint32_t get_id() { + return uint32_t(GetCurrentThreadId()); + } + } + + + /** + * \brief SRW-based mutex implementation + * + * Drop-in replacement for \c std::mutex that uses Win32 + * SRW locks, which are implemented with \c futex in wine. + */ + class mutex { + + public: + + using native_handle_type = PSRWLOCK; + + mutex() { } + + mutex(const mutex&) = delete; + mutex& operator = (const mutex&) = delete; + + void lock() { + AcquireSRWLockExclusive(&m_lock); + } + + void unlock() { + ReleaseSRWLockExclusive(&m_lock); + } + + bool try_lock() { + return TryAcquireSRWLockExclusive(&m_lock); + } + + native_handle_type native_handle() { + return &m_lock; + } + + private: + + SRWLOCK m_lock = SRWLOCK_INIT; + + }; + + + /** + * \brief Recursive mutex implementation + * + * Drop-in replacement for \c std::recursive_mutex that + * uses Win32 critical sections. + */ + class recursive_mutex { + + public: + + using native_handle_type = PCRITICAL_SECTION; + + recursive_mutex() { + InitializeCriticalSection(&m_lock); + } + + ~recursive_mutex() { + DeleteCriticalSection(&m_lock); + } + + recursive_mutex(const recursive_mutex&) = delete; + recursive_mutex& operator = (const recursive_mutex&) = delete; + + void lock() { + EnterCriticalSection(&m_lock); + } + + void unlock() { + LeaveCriticalSection(&m_lock); + } + + bool try_lock() { + return TryEnterCriticalSection(&m_lock); + } + + native_handle_type native_handle() { + return &m_lock; + } + + private: + + CRITICAL_SECTION m_lock; + + }; + + + /** + * \brief SRW-based condition variable implementation + * + * Drop-in replacement for \c std::condition_variable that + * uses Win32 condition variables on SRW locks. + */ + class condition_variable { + + public: + + using native_handle_type = PCONDITION_VARIABLE; + + condition_variable() { + InitializeConditionVariable(&m_cond); + } + + condition_variable(condition_variable&) = delete; + + condition_variable& operator = (condition_variable&) = delete; + + void notify_one() { + WakeConditionVariable(&m_cond); + } + + void notify_all() { + WakeAllConditionVariable(&m_cond); + } + + void wait(std::unique_lock& lock) { + auto srw = lock.mutex()->native_handle(); + SleepConditionVariableSRW(&m_cond, srw, INFINITE, 0); + } + + template + void wait(std::unique_lock& lock, Predicate pred) { + while (!pred()) + wait(lock); + } + + template + std::cv_status wait_until(std::unique_lock& lock, const std::chrono::time_point& time) { + auto now = Clock::now(); + + return (now < time) + ? wait_for(lock, now - time) + : std::cv_status::timeout; + } + + template + bool wait_until(std::unique_lock& lock, const std::chrono::time_point& time, Predicate pred) { + if (pred()) + return true; + + auto now = Clock::now(); + return now < time && wait_for(lock, now - time, pred); + } + + template + std::cv_status wait_for(std::unique_lock& lock, const std::chrono::duration& timeout) { + auto ms = std::chrono::duration_cast(timeout); + auto srw = lock.mutex()->native_handle(); + + return SleepConditionVariableSRW(&m_cond, srw, ms.count(), 0) + ? std::cv_status::no_timeout + : std::cv_status::timeout; + } + + template + bool wait_for(std::unique_lock& lock, const std::chrono::duration& timeout, Predicate pred) { + bool result = pred(); + + if (!result && wait_for(lock, timeout) == std::cv_status::no_timeout) + result = pred(); + + return result; + } + + native_handle_type native_handle() { + return &m_cond; + } + + private: + + CONDITION_VARIABLE m_cond; + + }; + +#else + using mutex = std::mutex; + using thread = std::thread; + using recursive_mutex = std::recursive_mutex; + using condition_variable = std::condition_variable; + + namespace this_thread { + inline void yield() { + std::this_thread::yield(); + } + + uint32_t get_id(); + } +#endif + +} diff --git a/utils/dxvk-1.10.3/src/util/util_bit.h b/utils/dxvk-1.10.3/src/util/util_bit.h new file mode 100644 index 00000000000..7682ace86ad --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/util_bit.h @@ -0,0 +1,353 @@ +#pragma once + +#ifndef _MSC_VER +#if defined(__WINE__) && defined(__clang__) +#pragma push_macro("_WIN32") +#undef _WIN32 +#endif +#include +#if defined(__WINE__) && defined(__clang__) +#pragma pop_macro("_WIN32") +#endif +#else +#include +#endif + +#include "util_likely.h" +#include "util_math.h" + +#include +#include +#include + +namespace dxvk::bit { + + template + T cast(const J& src) { + static_assert(sizeof(T) == sizeof(J)); + static_assert(std::is_trivially_copyable::value && std::is_trivial::value); + + T dst; + std::memcpy(&dst, &src, sizeof(T)); + return dst; + } + + template + T extract(T value, uint32_t fst, uint32_t lst) { + return (value >> fst) & ~(~T(0) << (lst - fst + 1)); + } + + inline uint32_t popcntStep(uint32_t n, uint32_t mask, uint32_t shift) { + return (n & mask) + ((n & ~mask) >> shift); + } + + inline uint32_t popcnt(uint32_t n) { + n = popcntStep(n, 0x55555555, 1); + n = popcntStep(n, 0x33333333, 2); + n = popcntStep(n, 0x0F0F0F0F, 4); + n = popcntStep(n, 0x00FF00FF, 8); + n = popcntStep(n, 0x0000FFFF, 16); + return n; + } + + inline uint32_t tzcnt(uint32_t n) { + #if defined(_MSC_VER) && !defined(__clang__) + return _tzcnt_u32(n); + #elif defined(__BMI__) + return __tzcnt_u32(n); + #elif defined(__GNUC__) || defined(__clang__) + uint32_t res; + uint32_t tmp; + asm ( + "mov $32, %1;" + "bsf %2, %0;" + "cmovz %1, %0;" + : "=&r" (res), "=&r" (tmp) + : "r" (n)); + return res; + #else + uint32_t r = 31; + n &= -n; + r -= (n & 0x0000FFFF) ? 16 : 0; + r -= (n & 0x00FF00FF) ? 8 : 0; + r -= (n & 0x0F0F0F0F) ? 4 : 0; + r -= (n & 0x33333333) ? 2 : 0; + r -= (n & 0x55555555) ? 1 : 0; + return n != 0 ? r : 32; + #endif + } + + inline uint32_t bsf(uint32_t n) { + #if defined(_MSC_VER) && !defined(__clang__) + unsigned long index; + _BitScanForward(&index, n); + return uint32_t(index); + #elif defined(__GNUC__) || defined(__clang__) + return __builtin_ctz(n); + #else + uint32_t r = 31; + n &= -n; + r -= (n & 0x0000FFFF) ? 16 : 0; + r -= (n & 0x00FF00FF) ? 8 : 0; + r -= (n & 0x0F0F0F0F) ? 4 : 0; + r -= (n & 0x33333333) ? 2 : 0; + r -= (n & 0x55555555) ? 1 : 0; + return r; + #endif + } + + inline uint32_t lzcnt(uint32_t n) { + #if (defined(_MSC_VER) && !defined(__clang__)) || defined(__LZCNT__) + return _lzcnt_u32(n); + #elif defined(__GNUC__) || defined(__clang__) + return n != 0 ? __builtin_clz(n) : 32; + #else + uint32_t r = 0; + + if (n == 0) return 32; + + if (n <= 0x0000FFFF) { r += 16; n <<= 16; } + if (n <= 0x00FFFFFF) { r += 8; n <<= 8; } + if (n <= 0x0FFFFFFF) { r += 4; n <<= 4; } + if (n <= 0x3FFFFFFF) { r += 2; n <<= 2; } + if (n <= 0x7FFFFFFF) { r += 1; n <<= 1; } + + return r; + #endif + } + + template + uint32_t pack(T& dst, uint32_t& shift, T src, uint32_t count) { + constexpr uint32_t Bits = 8 * sizeof(T); + if (likely(shift < Bits)) + dst |= src << shift; + shift += count; + return shift > Bits ? shift - Bits : 0; + } + + template + uint32_t unpack(T& dst, T src, uint32_t& shift, uint32_t count) { + constexpr uint32_t Bits = 8 * sizeof(T); + if (likely(shift < Bits)) + dst = (src >> shift) & ((T(1) << count) - 1); + shift += count; + return shift > Bits ? shift - Bits : 0; + } + + /** + * \brief Compares two aligned structs bit by bit + * + * \param [in] a First struct + * \param [in] b Second struct + * \returns \c true if the structs are equal + */ + template + bool bcmpeq(const T* a, const T* b) { + static_assert(alignof(T) >= 16); + #if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER) + auto ai = reinterpret_cast(a); + auto bi = reinterpret_cast(b); + + size_t i = 0; + + #if defined(__clang__) + #pragma nounroll + #elif defined(__GNUC__) + #pragma GCC unroll 0 + #endif + + for ( ; i < 2 * (sizeof(T) / 32); i += 2) { + __m128i eq0 = _mm_cmpeq_epi8( + _mm_load_si128(ai + i), + _mm_load_si128(bi + i)); + __m128i eq1 = _mm_cmpeq_epi8( + _mm_load_si128(ai + i + 1), + _mm_load_si128(bi + i + 1)); + __m128i eq = _mm_and_si128(eq0, eq1); + + int mask = _mm_movemask_epi8(eq); + if (mask != 0xFFFF) + return false; + } + + for ( ; i < sizeof(T) / 16; i++) { + __m128i eq = _mm_cmpeq_epi8( + _mm_load_si128(ai + i), + _mm_load_si128(bi + i)); + + int mask = _mm_movemask_epi8(eq); + if (mask != 0xFFFF) + return false; + } + + return true; + #else + return !std::memcmp(a, b, sizeof(T)); + #endif + } + + template + class bitset { + static constexpr size_t Dwords = align(Bits, 32) / 32; + public: + + constexpr bitset() + : m_dwords() { + + } + + constexpr bool get(uint32_t idx) const { + uint32_t dword = 0; + uint32_t bit = idx; + + // Compiler doesn't remove this otherwise. + if constexpr (Dwords > 1) { + dword = idx / 32; + bit = idx % 32; + } + + return m_dwords[dword] & (1u << bit); + } + + constexpr void set(uint32_t idx, bool value) { + uint32_t dword = 0; + uint32_t bit = idx; + + // Compiler doesn't remove this otherwise. + if constexpr (Dwords > 1) { + dword = idx / 32; + bit = idx % 32; + } + + if (value) + m_dwords[dword] |= 1u << bit; + else + m_dwords[dword] &= ~(1u << bit); + } + + constexpr bool exchange(uint32_t idx, bool value) { + bool oldValue = get(idx); + set(idx, value); + return oldValue; + } + + constexpr void flip(uint32_t idx) { + uint32_t dword = 0; + uint32_t bit = idx; + + // Compiler doesn't remove this otherwise. + if constexpr (Dwords > 1) { + dword = idx / 32; + bit = idx % 32; + } + + m_dwords[dword] ^= 1u << bit; + } + + constexpr void setAll() { + if constexpr (Bits % 32 == 0) { + for (size_t i = 0; i < Dwords; i++) + m_dwords[i] = std::numeric_limits::max(); + } + else { + for (size_t i = 0; i < Dwords - 1; i++) + m_dwords[i] = std::numeric_limits::max(); + + m_dwords[Dwords - 1] = (1u << (Bits % 32)) - 1; + } + } + + constexpr void clearAll() { + for (size_t i = 0; i < Dwords; i++) + m_dwords[i] = 0; + } + + constexpr bool any() const { + for (size_t i = 0; i < Dwords; i++) { + if (m_dwords[i] != 0) + return true; + } + + return false; + } + + constexpr uint32_t& dword(uint32_t idx) { + return m_dwords[idx]; + } + + constexpr size_t bitCount() { + return Bits; + } + + constexpr size_t dwordCount() { + return Dwords; + } + + constexpr bool operator [] (uint32_t idx) const { + return get(idx); + } + + private: + + uint32_t m_dwords[Dwords]; + + }; + + class BitMask { + + public: + + class iterator { + public: + using iterator_category = std::input_iterator_tag; + using value_type = uint32_t; + using difference_type = uint32_t; + using pointer = const uint32_t*; + using reference = uint32_t; + + explicit iterator(uint32_t flags) + : m_mask(flags) { } + + iterator& operator ++ () { + m_mask &= m_mask - 1; + return *this; + } + + iterator operator ++ (int) { + iterator retval = *this; + m_mask &= m_mask - 1; + return retval; + } + + uint32_t operator * () const { + return bsf(m_mask); + } + + bool operator == (iterator other) const { return m_mask == other.m_mask; } + bool operator != (iterator other) const { return m_mask != other.m_mask; } + + private: + + uint32_t m_mask; + + }; + + BitMask() { } + + BitMask(uint32_t n) + : m_mask(n) { } + + iterator begin() { + return iterator(m_mask); + } + + iterator end() { + return iterator(0); + } + + private: + + uint32_t m_mask; + + }; +} diff --git a/utils/dxvk-1.10.3/src/util/util_enum.h b/utils/dxvk-1.10.3/src/util/util_enum.h new file mode 100644 index 00000000000..85b9b21b9f9 --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/util_enum.h @@ -0,0 +1,7 @@ +#pragma once + +#define ENUM_NAME(name) \ + case name: return os << #name + +#define ENUM_DEFAULT(name) \ + default: return os << static_cast(e) diff --git a/utils/dxvk-1.10.3/src/util/util_env.cpp b/utils/dxvk-1.10.3/src/util/util_env.cpp new file mode 100644 index 00000000000..61f6326e141 --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/util_env.cpp @@ -0,0 +1,122 @@ +#include +#include +#include +#include + +#ifdef __linux__ +#include +#include +#endif + +#include "util_env.h" + +#include "./com/com_include.h" + +namespace dxvk::env { + + std::string getEnvVar(const char* name) { +#ifdef _WIN32 + std::vector result; + result.resize(MAX_PATH + 1); + + DWORD len = ::GetEnvironmentVariableW(str::tows(name).c_str(), result.data(), MAX_PATH); + result.resize(len); + + return str::fromws(result.data()); +#else + const char* result = std::getenv(name); + return result ? result : ""; +#endif + } + + + size_t matchFileExtension(const std::string& name, const char* ext) { + auto pos = name.find_last_of('.'); + + if (pos == std::string::npos) + return pos; + + bool matches = std::accumulate(name.begin() + pos + 1, name.end(), true, + [&ext] (bool current, char a) { + if (a >= 'A' && a <= 'Z') + a += 'a' - 'A'; + return current && *ext && a == *(ext++); + }); + + return matches ? pos : std::string::npos; + } + + + std::string getExeName() { + std::string fullPath = getExePath(); + auto n = fullPath.find_last_of(env::PlatformDirSlash); + + return (n != std::string::npos) + ? fullPath.substr(n + 1) + : fullPath; + } + + + std::string getExeBaseName() { + auto exeName = getExeName(); +#ifdef _WIN32 + auto extp = matchFileExtension(exeName, "exe"); + + if (extp != std::string::npos) + exeName.erase(extp); +#endif + + return exeName; + } + + + std::string getExePath() { +#if defined(_WIN32) + std::vector exePath; + exePath.resize(MAX_PATH + 1); + + DWORD len = ::GetModuleFileNameW(NULL, exePath.data(), MAX_PATH); + exePath.resize(len); + + return str::fromws(exePath.data()); +#elif defined(__linux__) + std::array exePath = {}; + + size_t count = readlink("/proc/self/exe", exePath.data(), exePath.size()); + + return std::string(exePath.begin(), exePath.begin() + count); +#endif + } + + + void setThreadName(const std::string& name) { +#ifdef _WIN32 + using SetThreadDescriptionProc = HRESULT (WINAPI *) (HANDLE, PCWSTR); + + static auto proc = reinterpret_cast( + ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), "SetThreadDescription")); + + if (proc != nullptr) { + auto wideName = std::vector(name.length() + 1); + str::tows(name.c_str(), wideName.data(), wideName.size()); + (*proc)(::GetCurrentThread(), wideName.data()); + } +#else + std::array posixName = {}; + dxvk::str::strlcpy(posixName.data(), name.c_str(), 16); + ::pthread_setname_np(pthread_self(), posixName.data()); +#endif + } + + + bool createDirectory(const std::string& path) { +#ifdef _WIN32 + WCHAR widePath[MAX_PATH]; + str::tows(path.c_str(), widePath); + return !!CreateDirectoryW(widePath, nullptr); +#else + return std::filesystem::create_directories(path); +#endif + } + +} diff --git a/utils/dxvk-1.10.3/src/util/util_env.h b/utils/dxvk-1.10.3/src/util/util_env.h new file mode 100644 index 00000000000..80efcbc9829 --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/util_env.h @@ -0,0 +1,79 @@ +#pragma once + +#include "util_string.h" + +namespace dxvk::env { + +#ifdef _WIN32 + constexpr char PlatformDirSlash = '\\'; +#else + constexpr char PlatformDirSlash = '/'; +#endif + + /** + * \brief Checks whether the host platform is 32-bit + */ + constexpr bool is32BitHostPlatform() { + return sizeof(void*) == 4; + } + + /** + * \brief Gets environment variable + * + * If the variable is not defined, this will return + * an empty string. Note that environment variables + * may be defined with an empty value. + * \param [in] name Name of the variable + * \returns Value of the variable + */ + std::string getEnvVar(const char* name); + + /** + * \brief Checks whether a file name has a given extension + * + * \param [in] name File name + * \param [in] ext Extension to match, in lowercase letters + * \returns Position of the extension within the file name, or + * \c std::string::npos if the file has a different extension + */ + size_t matchFileExtension(const std::string& name, const char* ext); + + /** + * \brief Gets the executable name + * + * Returns the base name (not the full path) of the + * program executable, including the file extension. + * This function should be used to identify programs. + * \returns Executable name + */ + std::string getExeName(); + + /** + * \brief Gets the executable name without extension + * + * Same as \ref getExeName but without the file extension. + * \returns Executable name + */ + std::string getExeBaseName(); + + /** + * \brief Gets full path to executable + * \returns Path to executable + */ + std::string getExePath(); + + /** + * \brief Sets name of the calling thread + * \param [in] name Thread name + */ + void setThreadName(const std::string& name); + + /** + * \brief Creates a directory + * + * \param [in] path Path to directory + * \returns \c true on success + */ + bool createDirectory(const std::string& path); + +} diff --git a/utils/dxvk-1.10.3/src/util/util_error.h b/utils/dxvk-1.10.3/src/util/util_error.h new file mode 100644 index 00000000000..2cfd45ffd0c --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/util_error.h @@ -0,0 +1,31 @@ +#pragma once + +#include + +namespace dxvk { + + /** + * \brief DXVK error + * + * A generic exception class that stores a + * message. Exceptions should be logged. + */ + class DxvkError { + + public: + + DxvkError() { } + DxvkError(std::string&& message) + : m_message(std::move(message)) { } + + const std::string& message() const { + return m_message; + } + + private: + + std::string m_message; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/util/util_flags.h b/utils/dxvk-1.10.3/src/util/util_flags.h new file mode 100644 index 00000000000..f67b4a2efac --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/util_flags.h @@ -0,0 +1,110 @@ +#pragma once + +#include + +#include "util_bit.h" + +namespace dxvk { + + template + class Flags { + + public: + + using IntType = std::underlying_type_t; + + Flags() { } + + Flags(IntType t) + : m_bits(t) { } + + template + Flags(T f, Tx... fx) { + this->set(f, fx...); + } + + template + void set(Tx... fx) { + m_bits |= bits(fx...); + } + + void set(Flags flags) { + m_bits |= flags.m_bits; + } + + template + void clr(Tx... fx) { + m_bits &= ~bits(fx...); + } + + void clr(Flags flags) { + m_bits &= ~flags.m_bits; + } + + template + bool any(Tx... fx) const { + return (m_bits & bits(fx...)) != 0; + } + + template + bool all(Tx... fx) const { + const IntType mask = bits(fx...); + return (m_bits & mask) == mask; + } + + bool test(T f) const { + return this->any(f); + } + + bool isClear() const { + return m_bits == 0; + } + + void clrAll() { + m_bits = 0; + } + + IntType raw() const { + return m_bits; + } + + Flags operator & (const Flags& other) const { + return Flags(m_bits & other.m_bits); + } + + Flags operator | (const Flags& other) const { + return Flags(m_bits | other.m_bits); + } + + Flags operator ^ (const Flags& other) const { + return Flags(m_bits ^ other.m_bits); + } + + bool operator == (const Flags& other) const { + return m_bits == other.m_bits; + } + + bool operator != (const Flags& other) const { + return m_bits != other.m_bits; + } + + private: + + IntType m_bits = 0; + + static IntType bit(T f) { + return IntType(1) << static_cast(f); + } + + template + static IntType bits(T f, Tx... fx) { + return bit(f) | bits(fx...); + } + + static IntType bits() { + return 0; + } + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/util/util_fps_limiter.cpp b/utils/dxvk-1.10.3/src/util/util_fps_limiter.cpp new file mode 100644 index 00000000000..7716500b453 --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/util_fps_limiter.cpp @@ -0,0 +1,172 @@ +#include + +#include "thread.h" +#include "util_env.h" +#include "util_fps_limiter.h" +#include "util_string.h" + +#include "./log/log.h" + +namespace dxvk { + + FpsLimiter::FpsLimiter() { + std::string env = env::getEnvVar("DXVK_FRAME_RATE"); + + if (!env.empty()) { + try { + setTargetFrameRate(std::stod(env)); + m_envOverride = true; + } catch (const std::invalid_argument&) { + // no-op + } + } + } + + + FpsLimiter::~FpsLimiter() { + + } + + + void FpsLimiter::setTargetFrameRate(double frameRate) { + std::lock_guard lock(m_mutex); + + if (!m_envOverride) { + m_targetInterval = frameRate > 0.0 + ? NtTimerDuration(int64_t(double(NtTimerDuration::period::den) / frameRate)) + : NtTimerDuration::zero(); + + if (isEnabled() && !m_initialized) + initialize(); + } + } + + + void FpsLimiter::setDisplayRefreshRate(double refreshRate) { + std::lock_guard lock(m_mutex); + + m_refreshInterval = refreshRate > 0.0 + ? NtTimerDuration(int64_t(double(NtTimerDuration::period::den) / refreshRate)) + : NtTimerDuration::zero(); + } + + + void FpsLimiter::delay(bool vsyncEnabled) { + std::lock_guard lock(m_mutex); + + if (!isEnabled()) + return; + + // If the swap chain is known to have vsync enabled and the + // refresh rate is similar to the target frame rate, disable + // the limiter so it does not screw up frame times + if (vsyncEnabled && !m_envOverride + && m_refreshInterval * 100 > m_targetInterval * 97) + return; + + auto t0 = m_lastFrame; + auto t1 = dxvk::high_resolution_clock::now(); + + auto frameTime = std::chrono::duration_cast(t1 - t0); + + if (frameTime * 100 > m_targetInterval * 103 - m_deviation * 100) { + // If we have a slow frame, reset the deviation since we + // do not want to compensate for low performance later on + m_deviation = NtTimerDuration::zero(); + } else { + // Don't call sleep if the amount of time to sleep is shorter + // than the time the function calls are likely going to take + NtTimerDuration sleepDuration = m_targetInterval - m_deviation - frameTime; + t1 = sleep(t1, sleepDuration); + + // Compensate for any sleep inaccuracies in the next frame, and + // limit cumulative deviation in order to avoid stutter in case we + // have a number of slow frames immediately followed by a fast one. + frameTime = std::chrono::duration_cast(t1 - t0); + m_deviation += frameTime - m_targetInterval; + m_deviation = std::min(m_deviation, m_targetInterval / 16); + } + + m_lastFrame = t1; + } + + + FpsLimiter::TimePoint FpsLimiter::sleep(TimePoint t0, NtTimerDuration duration) { + if (duration <= NtTimerDuration::zero()) + return t0; + + // On wine, we can rely on NtDelayExecution waiting for more or + // less exactly the desired amount of time, and we want to avoid + // spamming QueryPerformanceCounter for performance reasons. + // On Windows, we busy-wait for the last couple of milliseconds + // since sleeping is highly inaccurate and inconsistent. + NtTimerDuration sleepThreshold = m_sleepThreshold; + + if (m_sleepGranularity != NtTimerDuration::zero()) + sleepThreshold += duration / 6; + + NtTimerDuration remaining = duration; + TimePoint t1 = t0; + + while (remaining > sleepThreshold) { + NtTimerDuration sleepDuration = remaining - sleepThreshold; + + if (NtDelayExecution) { + LARGE_INTEGER ticks; + ticks.QuadPart = -sleepDuration.count(); + + NtDelayExecution(FALSE, &ticks); + } else { + std::this_thread::sleep_for(sleepDuration); + } + + t1 = dxvk::high_resolution_clock::now(); + remaining -= std::chrono::duration_cast(t1 - t0); + t0 = t1; + } + + // Busy-wait until we have slept long enough + while (remaining > NtTimerDuration::zero()) { + t1 = dxvk::high_resolution_clock::now(); + remaining -= std::chrono::duration_cast(t1 - t0); + t0 = t1; + } + + return t1; + } + + + void FpsLimiter::initialize() { + HMODULE ntdll = ::GetModuleHandleW(L"ntdll.dll"); + + if (ntdll) { + NtDelayExecution = reinterpret_cast( + ::GetProcAddress(ntdll, "NtDelayExecution")); + auto NtQueryTimerResolution = reinterpret_cast( + ::GetProcAddress(ntdll, "NtQueryTimerResolution")); + auto NtSetTimerResolution = reinterpret_cast( + ::GetProcAddress(ntdll, "NtSetTimerResolution")); + + ULONG min, max, cur; + + // Wine's implementation of these functions is a stub as of 6.10, which is fine + // since it uses select() in NtDelayExecution. This is only relevant for Windows. + if (NtQueryTimerResolution && !NtQueryTimerResolution(&min, &max, &cur)) { + m_sleepGranularity = NtTimerDuration(cur); + + if (NtSetTimerResolution && !NtSetTimerResolution(max, TRUE, &cur)) { + Logger::info(str::format("Setting timer interval to ", (double(max) / 10.0), " us")); + m_sleepGranularity = NtTimerDuration(max); + } + } + } else { + // Assume 1ms sleep granularity by default + m_sleepGranularity = NtTimerDuration(10000); + } + + m_sleepThreshold = 4 * m_sleepGranularity; + m_lastFrame = dxvk::high_resolution_clock::now(); + m_initialized = true; + } + +} diff --git a/utils/dxvk-1.10.3/src/util/util_fps_limiter.h b/utils/dxvk-1.10.3/src/util/util_fps_limiter.h new file mode 100644 index 00000000000..9601dc96f78 --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/util_fps_limiter.h @@ -0,0 +1,89 @@ +#pragma once + +#include "thread.h" +#include "util_time.h" + +namespace dxvk { + + /** + * \brief Frame rate limiter + * + * Provides functionality to stall an application + * thread in order to maintain a given frame rate. + */ + class FpsLimiter { + + public: + + /** + * \brief Creates frame rate limiter + */ + FpsLimiter(); + + ~FpsLimiter(); + + /** + * \brief Sets target frame rate + * \param [in] frameRate Target frame rate + */ + void setTargetFrameRate(double frameRate); + + /** + * \brief Sets display refresh rate + * + * This information is used to decide whether or not + * the limiter should be active in the first place in + * case vertical synchronization is enabled. + * \param [in] refreshRate Current refresh rate + */ + void setDisplayRefreshRate(double refreshRate); + + /** + * \brief Stalls calling thread as necessary + * + * Blocks the calling thread if the limiter is enabled + * and the time since the last call to \ref delay is + * shorter than the target interval. + * \param [in] vsyncEnabled \c true if vsync is enabled + */ + void delay(bool vsyncEnabled); + + /** + * \brief Checks whether the frame rate limiter is enabled + * \returns \c true if the target frame rate is non-zero. + */ + bool isEnabled() const { + return m_targetInterval != NtTimerDuration::zero(); + } + + private: + + using TimePoint = dxvk::high_resolution_clock::time_point; + + using NtTimerDuration = std::chrono::duration>; + using NtQueryTimerResolutionProc = UINT (WINAPI *) (ULONG*, ULONG*, ULONG*); + using NtSetTimerResolutionProc = UINT (WINAPI *) (ULONG, BOOL, ULONG*); + using NtDelayExecutionProc = UINT (WINAPI *) (BOOL, LARGE_INTEGER*); + + dxvk::mutex m_mutex; + + NtTimerDuration m_targetInterval = NtTimerDuration::zero(); + NtTimerDuration m_refreshInterval = NtTimerDuration::zero(); + NtTimerDuration m_deviation = NtTimerDuration::zero(); + TimePoint m_lastFrame; + + bool m_initialized = false; + bool m_envOverride = false; + + NtTimerDuration m_sleepGranularity = NtTimerDuration::zero(); + NtTimerDuration m_sleepThreshold = NtTimerDuration::zero(); + + NtDelayExecutionProc NtDelayExecution = nullptr; + + TimePoint sleep(TimePoint t0, NtTimerDuration duration); + + void initialize(); + + }; + +} diff --git a/utils/dxvk-1.10.3/src/util/util_gdi.cpp b/utils/dxvk-1.10.3/src/util/util_gdi.cpp new file mode 100644 index 00000000000..901dd05ca9d --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/util_gdi.cpp @@ -0,0 +1,33 @@ +#include "util_gdi.h" +#include "log/log.h" + +namespace dxvk { + + HMODULE GetGDIModule() { + static HMODULE module = LoadLibraryA("gdi32.dll"); + return module; + } + + NTSTATUS D3DKMTCreateDCFromMemory(D3DKMT_CREATEDCFROMMEMORY* Arg1) { + static auto func = (D3DKMTCreateDCFromMemoryType) + GetProcAddress(GetGDIModule(), "D3DKMTCreateDCFromMemory"); + + if (func != nullptr) + return func(Arg1); + + Logger::warn("D3DKMTCreateDCFromMemory: Unable to query proc address."); + return -1; + } + + NTSTATUS D3DKMTDestroyDCFromMemory(D3DKMT_DESTROYDCFROMMEMORY* Arg1) { + static auto func = (D3DKMTDestroyDCFromMemoryType) + GetProcAddress(GetGDIModule(), "D3DKMTDestroyDCFromMemory"); + + if (func != nullptr) + return func(Arg1); + + Logger::warn("D3DKMTDestroyDCFromMemory: Unable to query proc address."); + return -1; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/util/util_gdi.h b/utils/dxvk-1.10.3/src/util/util_gdi.h new file mode 100644 index 00000000000..58724b155e7 --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/util_gdi.h @@ -0,0 +1,32 @@ +#pragma once + +#include + +namespace dxvk { + using NTSTATUS = LONG; + + // Slightly modified definitions... + struct D3DKMT_CREATEDCFROMMEMORY { + void* pMemory; + D3DFORMAT Format; + UINT Width; + UINT Height; + UINT Pitch; + HDC hDeviceDc; + PALETTEENTRY* pColorTable; + HDC hDc; + HANDLE hBitmap; + }; + + struct D3DKMT_DESTROYDCFROMMEMORY { + HDC hDC = nullptr; + HANDLE hBitmap = nullptr; + }; + + using D3DKMTCreateDCFromMemoryType = NTSTATUS(STDMETHODCALLTYPE*) (D3DKMT_CREATEDCFROMMEMORY*); + NTSTATUS D3DKMTCreateDCFromMemory (D3DKMT_CREATEDCFROMMEMORY* Arg1); + + using D3DKMTDestroyDCFromMemoryType = NTSTATUS(STDMETHODCALLTYPE*) (D3DKMT_DESTROYDCFROMMEMORY*); + NTSTATUS D3DKMTDestroyDCFromMemory(D3DKMT_DESTROYDCFROMMEMORY* Arg1); + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/util/util_lazy.h b/utils/dxvk-1.10.3/src/util/util_lazy.h new file mode 100644 index 00000000000..f17febb8315 --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/util_lazy.h @@ -0,0 +1,40 @@ +#pragma once + +#include + +namespace dxvk { + + /** + * \brief Lazy-initialized object + * + * Creates an object on demand with + * the given constructor arguments. + */ + template + class Lazy { + + public: + + template + T& get(Args... args) { + if (m_object) + return *m_object; + + std::lock_guard lock(m_mutex); + + if (!m_object) { + m_object = std::make_unique( + std::forward(args)...); + } + + return *m_object; + } + + private: + + dxvk::mutex m_mutex; + std::unique_ptr m_object; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/util/util_likely.h b/utils/dxvk-1.10.3/src/util/util_likely.h new file mode 100644 index 00000000000..7eba9818c52 --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/util_likely.h @@ -0,0 +1,9 @@ +#pragma once + +#ifdef __GNUC__ +#define likely(x) __builtin_expect((x),1) +#define unlikely(x) __builtin_expect((x),0) +#else +#define likely(x) (x) +#define unlikely(x) (x) +#endif diff --git a/utils/dxvk-1.10.3/src/util/util_luid.cpp b/utils/dxvk-1.10.3/src/util/util_luid.cpp new file mode 100644 index 00000000000..96a2a09a62f --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/util_luid.cpp @@ -0,0 +1,34 @@ +#include "util_luid.h" +#include "util_string.h" + +#include "./log/log.h" + +#include +#include + +namespace dxvk { + + LUID GetAdapterLUID(UINT Adapter) { + static dxvk::mutex s_mutex; + static std::vector s_luids; + + std::lock_guard lock(s_mutex); + uint32_t newLuidCount = Adapter + 1; + + while (s_luids.size() < newLuidCount) { + LUID luid = { 0, 0 }; + + if (!::AllocateLocallyUniqueId(&luid)) + Logger::err("Failed to allocate LUID"); + + + Logger::info(str::format("Adapter LUID ", s_luids.size(), ": ", + std::hex, luid.HighPart, ":", luid.LowPart, std::dec)); + + s_luids.push_back(luid); + } + + return s_luids[Adapter]; + } + +} diff --git a/utils/dxvk-1.10.3/src/util/util_luid.h b/utils/dxvk-1.10.3/src/util/util_luid.h new file mode 100644 index 00000000000..718040e3689 --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/util_luid.h @@ -0,0 +1,15 @@ +#include "./com/com_include.h" + +namespace dxvk { + + /** + * \brief Retrieves an adapter LUID + * + * Note that this only works reliably within the + * module that this function was compiled into. + * \param [in] Adapter The adapter index + * \returns LUID An LUID for that adapter + */ + LUID GetAdapterLUID(UINT Adapter); + +} diff --git a/utils/dxvk-1.10.3/src/util/util_math.h b/utils/dxvk-1.10.3/src/util/util_math.h new file mode 100644 index 00000000000..5457ef07128 --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/util_math.h @@ -0,0 +1,39 @@ +#pragma once + +#include + +namespace dxvk { + + constexpr size_t CACHE_LINE_SIZE = 64; + + template + constexpr T clamp(T n, T lo, T hi) { + if (n < lo) return lo; + if (n > hi) return hi; + return n; + } + + template + constexpr T align(T what, U to) { + return (what + to - 1) & ~(to - 1); + } + + template + constexpr T alignDown(T what, U to) { + return (what / to) * to; + } + + // Equivalent of std::clamp for use with floating point numbers + // Handles (-){INFINITY,NAN} cases. + // Will return min in cases of NAN, etc. + inline float fclamp(float value, float min, float max) { + return std::fmin( + std::fmax(value, min), max); + } + + template + inline T divCeil(T dividend, T divisor) { + return (dividend + divisor - 1) / divisor; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/util/util_matrix.cpp b/utils/dxvk-1.10.3/src/util/util_matrix.cpp new file mode 100644 index 00000000000..2c5e93140d8 --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/util_matrix.cpp @@ -0,0 +1,232 @@ +#include "util_matrix.h" + +namespace dxvk { + + Vector4& Matrix4::operator[](size_t index) { return data[index]; } + const Vector4& Matrix4::operator[](size_t index) const { return data[index]; } + + bool Matrix4::operator==(const Matrix4& m2) const { + const Matrix4& m1 = *this; + for (uint32_t i = 0; i < 4; i++) { + if (m1[i] != m2[i]) + return false; + } + return true; + } + + bool Matrix4::operator!=(const Matrix4& m2) const { return !operator==(m2); } + + Matrix4 Matrix4::operator+(const Matrix4& other) const { + Matrix4 mat; + for (uint32_t i = 0; i < 4; i++) + mat[i] = data[i] + other.data[i]; + return mat; + } + + Matrix4 Matrix4::operator-(const Matrix4& other) const { + Matrix4 mat; + for (uint32_t i = 0; i < 4; i++) + mat[i] = data[i] - other.data[i]; + return mat; + } + + Matrix4 Matrix4::operator*(const Matrix4& m2) const { + const Matrix4& m1 = *this; + + const Vector4 srcA0 = { m1[0] }; + const Vector4 srcA1 = { m1[1] }; + const Vector4 srcA2 = { m1[2] }; + const Vector4 srcA3 = { m1[3] }; + + const Vector4 srcB0 = { m2[0] }; + const Vector4 srcB1 = { m2[1] }; + const Vector4 srcB2 = { m2[2] }; + const Vector4 srcB3 = { m2[3] }; + + Matrix4 result; + result[0] = srcA0 * srcB0[0] + srcA1 * srcB0[1] + srcA2 * srcB0[2] + srcA3 * srcB0[3]; + result[1] = srcA0 * srcB1[0] + srcA1 * srcB1[1] + srcA2 * srcB1[2] + srcA3 * srcB1[3]; + result[2] = srcA0 * srcB2[0] + srcA1 * srcB2[1] + srcA2 * srcB2[2] + srcA3 * srcB2[3]; + result[3] = srcA0 * srcB3[0] + srcA1 * srcB3[1] + srcA2 * srcB3[2] + srcA3 * srcB3[3]; + return result; + } + + Vector4 Matrix4::operator*(const Vector4& v) const { + const Matrix4& m = *this; + + const Vector4 mul0 = { m[0] * v[0] }; + const Vector4 mul1 = { m[1] * v[1] }; + const Vector4 mul2 = { m[2] * v[2] }; + const Vector4 mul3 = { m[3] * v[3] }; + + const Vector4 add0 = { mul0 + mul1 }; + const Vector4 add1 = { mul2 + mul3 }; + + return add0 + add1; + } + + Matrix4 Matrix4::operator*(float scalar) const { + Matrix4 mat; + for (uint32_t i = 0; i < 4; i++) + mat[i] = data[i] * scalar; + return mat; + } + + Matrix4 Matrix4::operator/(float scalar) const { + Matrix4 mat; + for (uint32_t i = 0; i < 4; i++) + mat[i] = data[i] / scalar; + return mat; + } + + Matrix4& Matrix4::operator+=(const Matrix4& other) { + for (uint32_t i = 0; i < 4; i++) + data[i] += other.data[i]; + return *this; + } + + Matrix4& Matrix4::operator-=(const Matrix4& other) { + for (uint32_t i = 0; i < 4; i++) + data[i] -= other.data[i]; + return *this; + } + + Matrix4& Matrix4::operator*=(const Matrix4& other) { + return (*this = (*this) * other); + } + + Matrix4 transpose(const Matrix4& m) { + Matrix4 result; + + for (uint32_t i = 0; i < 4; i++) { + for (uint32_t j = 0; j < 4; j++) + result[i][j] = m.data[j][i]; + } + return result; + } + + float determinant(const Matrix4& m) { + float coef00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + float coef02 = m[1][2] * m[3][3] - m[3][2] * m[1][3]; + float coef03 = m[1][2] * m[2][3] - m[2][2] * m[1][3]; + + float coef04 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + float coef06 = m[1][1] * m[3][3] - m[3][1] * m[1][3]; + float coef07 = m[1][1] * m[2][3] - m[2][1] * m[1][3]; + + float coef08 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + float coef10 = m[1][1] * m[3][2] - m[3][1] * m[1][2]; + float coef11 = m[1][1] * m[2][2] - m[2][1] * m[1][2]; + + float coef12 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + float coef14 = m[1][0] * m[3][3] - m[3][0] * m[1][3]; + float coef15 = m[1][0] * m[2][3] - m[2][0] * m[1][3]; + + float coef16 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + float coef18 = m[1][0] * m[3][2] - m[3][0] * m[1][2]; + float coef19 = m[1][0] * m[2][2] - m[2][0] * m[1][2]; + + float coef20 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + float coef22 = m[1][0] * m[3][1] - m[3][0] * m[1][1]; + float coef23 = m[1][0] * m[2][1] - m[2][0] * m[1][1]; + + Vector4 fac0 = { coef00, coef00, coef02, coef03 }; + Vector4 fac1 = { coef04, coef04, coef06, coef07 }; + Vector4 fac2 = { coef08, coef08, coef10, coef11 }; + Vector4 fac3 = { coef12, coef12, coef14, coef15 }; + Vector4 fac4 = { coef16, coef16, coef18, coef19 }; + Vector4 fac5 = { coef20, coef20, coef22, coef23 }; + + Vector4 vec0 = { m[1][0], m[0][0], m[0][0], m[0][0] }; + Vector4 vec1 = { m[1][1], m[0][1], m[0][1], m[0][1] }; + Vector4 vec2 = { m[1][2], m[0][2], m[0][2], m[0][2] }; + Vector4 vec3 = { m[1][3], m[0][3], m[0][3], m[0][3] }; + + Vector4 inv0 = { vec1 * fac0 - vec2 * fac1 + vec3 * fac2 }; + Vector4 inv1 = { vec0 * fac0 - vec2 * fac3 + vec3 * fac4 }; + Vector4 inv2 = { vec0 * fac1 - vec1 * fac3 + vec3 * fac5 }; + Vector4 inv3 = { vec0 * fac2 - vec1 * fac4 + vec2 * fac5 }; + + Vector4 signA = { +1, -1, +1, -1 }; + Vector4 signB = { -1, +1, -1, +1 }; + Matrix4 inverse = { inv0 * signA, inv1 * signB, inv2 * signA, inv3 * signB }; + + Vector4 row0 = { inverse[0][0], inverse[1][0], inverse[2][0], inverse[3][0] }; + + Vector4 dot0 = { m[0] * row0 }; + + return (dot0.x + dot0.y) + (dot0.z + dot0.w); + } + + Matrix4 inverse(const Matrix4& m) + { + float coef00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + float coef02 = m[1][2] * m[3][3] - m[3][2] * m[1][3]; + float coef03 = m[1][2] * m[2][3] - m[2][2] * m[1][3]; + float coef04 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + float coef06 = m[1][1] * m[3][3] - m[3][1] * m[1][3]; + float coef07 = m[1][1] * m[2][3] - m[2][1] * m[1][3]; + float coef08 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + float coef10 = m[1][1] * m[3][2] - m[3][1] * m[1][2]; + float coef11 = m[1][1] * m[2][2] - m[2][1] * m[1][2]; + float coef12 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + float coef14 = m[1][0] * m[3][3] - m[3][0] * m[1][3]; + float coef15 = m[1][0] * m[2][3] - m[2][0] * m[1][3]; + float coef16 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + float coef18 = m[1][0] * m[3][2] - m[3][0] * m[1][2]; + float coef19 = m[1][0] * m[2][2] - m[2][0] * m[1][2]; + float coef20 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + float coef22 = m[1][0] * m[3][1] - m[3][0] * m[1][1]; + float coef23 = m[1][0] * m[2][1] - m[2][0] * m[1][1]; + + Vector4 fac0 = { coef00, coef00, coef02, coef03 }; + Vector4 fac1 = { coef04, coef04, coef06, coef07 }; + Vector4 fac2 = { coef08, coef08, coef10, coef11 }; + Vector4 fac3 = { coef12, coef12, coef14, coef15 }; + Vector4 fac4 = { coef16, coef16, coef18, coef19 }; + Vector4 fac5 = { coef20, coef20, coef22, coef23 }; + + Vector4 vec0 = { m[1][0], m[0][0], m[0][0], m[0][0] }; + Vector4 vec1 = { m[1][1], m[0][1], m[0][1], m[0][1] }; + Vector4 vec2 = { m[1][2], m[0][2], m[0][2], m[0][2] }; + Vector4 vec3 = { m[1][3], m[0][3], m[0][3], m[0][3] }; + + Vector4 inv0 = { vec1 * fac0 - vec2 * fac1 + vec3 * fac2 }; + Vector4 inv1 = { vec0 * fac0 - vec2 * fac3 + vec3 * fac4 }; + Vector4 inv2 = { vec0 * fac1 - vec1 * fac3 + vec3 * fac5 }; + Vector4 inv3 = { vec0 * fac2 - vec1 * fac4 + vec2 * fac5 }; + + Vector4 signA = { +1, -1, +1, -1 }; + Vector4 signB = { -1, +1, -1, +1 }; + Matrix4 inverse = { inv0 * signA, inv1 * signB, inv2 * signA, inv3 * signB }; + + Vector4 row0 = { inverse[0][0], inverse[1][0], inverse[2][0], inverse[3][0] }; + + Vector4 dot0 = { m[0] * row0 }; + float dot1 = (dot0.x + dot0.y) + (dot0.z + dot0.w); + + return inverse * (1.0f / dot1); + } + + Matrix4 hadamardProduct(const Matrix4& a, const Matrix4& b) { + Matrix4 result; + + for (uint32_t i = 0; i < 4; i++) + result[i] = a[i] * b[i]; + + return result; + } + + std::ostream& operator<<(std::ostream& os, const Matrix4& m) { + os << "Matrix4("; + for (uint32_t i = 0; i < 4; i++) { + os << "\n\t" << m[i]; + if (i < 3) + os << ", "; + } + os << "\n)"; + + return os; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/util/util_matrix.h b/utils/dxvk-1.10.3/src/util/util_matrix.h new file mode 100644 index 00000000000..98f260f8821 --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/util_matrix.h @@ -0,0 +1,85 @@ +#pragma once + +#include "util_vector.h" + +namespace dxvk { + + class Matrix4 { + + public: + + // Identity + inline Matrix4() { + data[0] = { 1, 0, 0, 0 }; + data[1] = { 0, 1, 0, 0 }; + data[2] = { 0, 0, 1, 0 }; + data[3] = { 0, 0, 0, 1 }; + } + + // Produces a scalar matrix, x * Identity + inline explicit Matrix4(float x) { + data[0] = { x, 0, 0, 0 }; + data[1] = { 0, x, 0, 0 }; + data[2] = { 0, 0, x, 0 }; + data[3] = { 0, 0, 0, x }; + } + + inline Matrix4( + const Vector4& v0, + const Vector4& v1, + const Vector4& v2, + const Vector4& v3) { + data[0] = v0; + data[1] = v1; + data[2] = v2; + data[3] = v3; + } + + inline Matrix4(const float matrix[4][4]) { + data[0] = Vector4(matrix[0]); + data[1] = Vector4(matrix[1]); + data[2] = Vector4(matrix[2]); + data[3] = Vector4(matrix[3]); + } + + Matrix4(const Matrix4& other) = default; + + Vector4& operator[](size_t index); + const Vector4& operator[](size_t index) const; + + bool operator==(const Matrix4& m2) const; + bool operator!=(const Matrix4& m2) const; + + Matrix4 operator+(const Matrix4& other) const; + Matrix4 operator-(const Matrix4& other) const; + + Matrix4 operator*(const Matrix4& m2) const; + Vector4 operator*(const Vector4& v) const; + Matrix4 operator*(float scalar) const; + + Matrix4 operator/(float scalar) const; + + Matrix4& operator+=(const Matrix4& other); + Matrix4& operator-=(const Matrix4& other); + + Matrix4& operator*=(const Matrix4& other); + + Vector4 data[4]; + + }; + + static_assert(sizeof(Matrix4) == sizeof(Vector4) * 4); + + inline Matrix4 operator*(float scalar, const Matrix4& m) { return m * scalar; } + + Matrix4 transpose(const Matrix4& m); + + float determinant(const Matrix4& m); + + Matrix4 inverse(const Matrix4& m); + + Matrix4 hadamardProduct(const Matrix4& a, const Matrix4& b); + + std::ostream& operator<<(std::ostream& os, const Matrix4& m); + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/util/util_misc.h b/utils/dxvk-1.10.3/src/util/util_misc.h new file mode 100644 index 00000000000..6fb41f15535 --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/util_misc.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +namespace dxvk { + + inline void DecodeD3DCOLOR(D3DCOLOR color, float* rgba) { + // Encoded in D3DCOLOR as argb + rgba[3] = (float)((color & 0xff000000) >> 24) / 255.0f; + rgba[0] = (float)((color & 0x00ff0000) >> 16) / 255.0f; + rgba[1] = (float)((color & 0x0000ff00) >> 8) / 255.0f; + rgba[2] = (float)((color & 0x000000ff)) / 255.0f; + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/util/util_monitor.cpp b/utils/dxvk-1.10.3/src/util/util_monitor.cpp new file mode 100644 index 00000000000..69f60d1652f --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/util_monitor.cpp @@ -0,0 +1,162 @@ +#include "util_monitor.h" +#include "util_string.h" + +#include "./log/log.h" + +namespace dxvk { + + HMONITOR GetDefaultMonitor() { + return ::MonitorFromPoint({ 0, 0 }, MONITOR_DEFAULTTOPRIMARY); + } + + + BOOL SetMonitorDisplayMode( + HMONITOR hMonitor, + DEVMODEW* pMode) { + ::MONITORINFOEXW monInfo; + monInfo.cbSize = sizeof(monInfo); + + if (!::GetMonitorInfoW(hMonitor, reinterpret_cast(&monInfo))) { + Logger::err("Failed to query monitor info"); + return E_FAIL; + } + + Logger::info(str::format("Setting display mode: ", + pMode->dmPelsWidth, "x", pMode->dmPelsHeight, "@", + pMode->dmDisplayFrequency)); + + DEVMODEW curMode = { }; + curMode.dmSize = sizeof(curMode); + + if (GetMonitorDisplayMode(hMonitor, ENUM_CURRENT_SETTINGS, &curMode)) { + bool eq = curMode.dmPelsWidth == pMode->dmPelsWidth + && curMode.dmPelsHeight == pMode->dmPelsHeight + && curMode.dmBitsPerPel == pMode->dmBitsPerPel; + + if (pMode->dmFields & DM_DISPLAYFREQUENCY) + eq &= curMode.dmDisplayFrequency == pMode->dmDisplayFrequency; + + if (eq) + return true; + } + + LONG status = ::ChangeDisplaySettingsExW(monInfo.szDevice, + pMode, nullptr, CDS_FULLSCREEN, nullptr); + + if (status != DISP_CHANGE_SUCCESSFUL) { + pMode->dmFields &= ~DM_DISPLAYFREQUENCY; + + status = ::ChangeDisplaySettingsExW(monInfo.szDevice, + pMode, nullptr, CDS_FULLSCREEN, nullptr); + } + + return status == DISP_CHANGE_SUCCESSFUL; + } + + + BOOL GetMonitorDisplayMode( + HMONITOR hMonitor, + DWORD modeNum, + DEVMODEW* pMode) { + ::MONITORINFOEXW monInfo; + monInfo.cbSize = sizeof(monInfo); + + if (!::GetMonitorInfoW(hMonitor, reinterpret_cast(&monInfo))) { + Logger::err("Failed to query monitor info"); + return false; + } + + return ::EnumDisplaySettingsW(monInfo.szDevice, modeNum, pMode); + } + + + BOOL CALLBACK RestoreMonitorDisplayModeCallback( + HMONITOR hMonitor, + HDC hDC, + LPRECT pRect, + LPARAM pUserdata) { + auto success = reinterpret_cast(pUserdata); + + DEVMODEW devMode = { }; + devMode.dmSize = sizeof(devMode); + + if (!GetMonitorDisplayMode(hMonitor, ENUM_REGISTRY_SETTINGS, &devMode)) { + *success = false; + return false; + } + + Logger::info(str::format("Restoring display mode: ", + devMode.dmPelsWidth, "x", devMode.dmPelsHeight, "@", + devMode.dmDisplayFrequency)); + + if (!SetMonitorDisplayMode(hMonitor, &devMode)) { + *success = false; + return false; + } + + return true; + } + + + BOOL RestoreMonitorDisplayMode() { + bool success = true; + bool result = ::EnumDisplayMonitors(nullptr, nullptr, + &RestoreMonitorDisplayModeCallback, + reinterpret_cast(&success)); + + return result && success; + } + + + void GetWindowClientSize( + HWND hWnd, + UINT* pWidth, + UINT* pHeight) { + RECT rect = { }; + ::GetClientRect(hWnd, &rect); + + if (pWidth) + *pWidth = rect.right - rect.left; + + if (pHeight) + *pHeight = rect.bottom - rect.top; + } + + + void GetMonitorClientSize( + HMONITOR hMonitor, + UINT* pWidth, + UINT* pHeight) { + ::MONITORINFOEXW monInfo; + monInfo.cbSize = sizeof(monInfo); + + if (!::GetMonitorInfoW(hMonitor, reinterpret_cast(&monInfo))) { + Logger::err("Failed to query monitor info"); + return; + } + + auto rect = monInfo.rcMonitor; + + if (pWidth) + *pWidth = rect.right - rect.left; + + if (pHeight) + *pHeight = rect.bottom - rect.top; + } + + + void GetMonitorRect( + HMONITOR hMonitor, + RECT* pRect) { + ::MONITORINFOEXW monInfo; + monInfo.cbSize = sizeof(monInfo); + + if (!::GetMonitorInfoW(hMonitor, reinterpret_cast(&monInfo))) { + Logger::err("Failed to query monitor info"); + return; + } + + *pRect = monInfo.rcMonitor; + } + +} diff --git a/utils/dxvk-1.10.3/src/util/util_monitor.h b/utils/dxvk-1.10.3/src/util/util_monitor.h new file mode 100644 index 00000000000..41c6ebee89f --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/util_monitor.h @@ -0,0 +1,78 @@ +#pragma once + +#include "./com/com_include.h" + +namespace dxvk { + + /** + * \brief Retrieves primary monitor + * \returns The primary monitor + */ + HMONITOR GetDefaultMonitor(); + + /** + * \brief Sets monitor display mode + * + * Note that \c pMode may be altered by this function. + * \param [in] hMonitor The monitor to change + * \param [in] pMode The desired display mode + * \returns \c true on success + */ + BOOL SetMonitorDisplayMode( + HMONITOR hMonitor, + DEVMODEW* pMode); + + /** + * \brief Enumerates monitor display modes + * + * \param [in] hMonitor The monitor to query + * \param [in] modeNum Mode number or enum + * \param [in] pMode The display mode + * \returns \c true on success + */ + BOOL GetMonitorDisplayMode( + HMONITOR hMonitor, + DWORD modeNum, + DEVMODEW* pMode); + + /** + * \brief Change display modes to registry settings + * \returns \c true on success + */ + BOOL RestoreMonitorDisplayMode(); + + /** + * \brief Queries window client size + * + * \param [in] hWnd Window to query + * \param [out] pWidth Client width + * \param [out] pHeight Client height + */ + void GetWindowClientSize( + HWND hWnd, + UINT* pWidth, + UINT* pHeight); + + /** + * \brief Queries monitor size + * + * \param [in] hMonitor Monitor to query + * \param [out] pWidth Client width + * \param [out] pHeight Client height + */ + void GetMonitorClientSize( + HMONITOR hMonitor, + UINT* pWidth, + UINT* pHeight); + + /** + * \brief Queries monitor rect + * + * \param [in] hMonitor Monitor to query + * \param [out] pRect The rect to return + */ + void GetMonitorRect( + HMONITOR hMonitor, + RECT* pRect); + +} diff --git a/utils/dxvk-1.10.3/src/util/util_ratio.h b/utils/dxvk-1.10.3/src/util/util_ratio.h new file mode 100644 index 00000000000..0257ad99ad5 --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/util_ratio.h @@ -0,0 +1,88 @@ +#include +#include +#include +#include +#include + +namespace dxvk { + + /** + * \brief Simplest ratio helper + */ + template + class Ratio { + + public: + + Ratio(T num, T denom) { + set(num, denom); + } + + Ratio(std::string_view view) { + set(0, 0); + + size_t colon = view.find(":"); + + if (colon == std::string_view::npos) + return; + + std::string_view numStr = view.substr(0, colon); + std::string_view denomStr = view.substr(colon + 1); + + T num = 0, denom = 0; + std::from_chars(numStr.data(), numStr.data() + numStr.size(), num); + std::from_chars(denomStr.data(), denomStr.data() + denomStr.size(), denom); + + set(num, denom); + } + + inline T num() const { return m_num; } + inline T denom() const { return m_denom; } + + inline bool undefined() const { return m_denom == 0; } + + inline void set(T num, T denom) { + const T gcd = std::gcd(num, denom); + + if (gcd == 0) { + m_num = 0; + m_denom = 0; + + return; + } + + m_num = num / gcd; + m_denom = denom / gcd; + } + + inline bool operator == (const Ratio& other) const { + return num() == other.num() && denom() == other.denom(); + } + + inline bool operator != (const Ratio& other) const { + return !(*this == other); + } + + inline bool operator >= (const Ratio& other) const { + return num() * other.denom() >= other.num() * denom(); + } + + inline bool operator > (const Ratio& other) const { + return num() * other.denom() > other.num() * denom(); + } + + inline bool operator < (const Ratio& other) const { + return !(*this >= other); + } + + inline bool operator <= (const Ratio& other) const { + return !(*this > other); + } + + private: + + T m_num, m_denom; + + }; + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/util/util_shared_res.cpp b/utils/dxvk-1.10.3/src/util/util_shared_res.cpp new file mode 100644 index 00000000000..d6ff1423cdd --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/util_shared_res.cpp @@ -0,0 +1,46 @@ +#include "util_shared_res.h" + +#include "winioctl.h" + +namespace dxvk { + + #define IOCTL_SHARED_GPU_RESOURCE_OPEN CTL_CODE(FILE_DEVICE_VIDEO, 1, METHOD_BUFFERED, FILE_WRITE_ACCESS) + + HANDLE openKmtHandle(HANDLE kmt_handle) { + HANDLE handle = ::CreateFileA("\\\\.\\SharedGpuResource", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (handle == INVALID_HANDLE_VALUE) + return handle; + + struct + { + unsigned int kmt_handle; + WCHAR name[1]; + } shared_resource_open = {0}; + shared_resource_open.kmt_handle = reinterpret_cast(kmt_handle); + + bool succeed = ::DeviceIoControl(handle, IOCTL_SHARED_GPU_RESOURCE_OPEN, &shared_resource_open, sizeof(shared_resource_open), NULL, 0, NULL, NULL); + if (!succeed) { + ::CloseHandle(handle); + return INVALID_HANDLE_VALUE; + } + return handle; + } + + #define IOCTL_SHARED_GPU_RESOURCE_SET_METADATA CTL_CODE(FILE_DEVICE_VIDEO, 4, METHOD_BUFFERED, FILE_WRITE_ACCESS) + + bool setSharedMetadata(HANDLE handle, void *buf, uint32_t bufSize) { + DWORD retSize; + return ::DeviceIoControl(handle, IOCTL_SHARED_GPU_RESOURCE_SET_METADATA, buf, bufSize, NULL, 0, &retSize, NULL); + } + + #define IOCTL_SHARED_GPU_RESOURCE_GET_METADATA CTL_CODE(FILE_DEVICE_VIDEO, 5, METHOD_BUFFERED, FILE_READ_ACCESS) + + bool getSharedMetadata(HANDLE handle, void *buf, uint32_t bufSize, uint32_t *metadataSize) { + DWORD retSize; + bool ret = ::DeviceIoControl(handle, IOCTL_SHARED_GPU_RESOURCE_GET_METADATA, NULL, 0, buf, bufSize, &retSize, NULL); + if (metadataSize) + *metadataSize = retSize; + return ret; + } + +} diff --git a/utils/dxvk-1.10.3/src/util/util_shared_res.h b/utils/dxvk-1.10.3/src/util/util_shared_res.h new file mode 100644 index 00000000000..aba742c4ea7 --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/util_shared_res.h @@ -0,0 +1,30 @@ +#pragma once + +#include + +#include "./com/com_include.h" + +#include + +namespace dxvk { + + HANDLE openKmtHandle(HANDLE kmt_handle); + + bool setSharedMetadata(HANDLE handle, void *buf, uint32_t bufSize); + bool getSharedMetadata(HANDLE handle, void *buf, uint32_t bufSize, uint32_t *metadataSize); + + struct DxvkSharedTextureMetadata { + UINT Width; + UINT Height; + UINT MipLevels; + UINT ArraySize; + DXGI_FORMAT Format; + DXGI_SAMPLE_DESC SampleDesc; + D3D11_USAGE Usage; + UINT BindFlags; + UINT CPUAccessFlags; + UINT MiscFlags; + D3D11_TEXTURE_LAYOUT TextureLayout; + }; + +} diff --git a/utils/dxvk-1.10.3/src/util/util_small_vector.h b/utils/dxvk-1.10.3/src/util/util_small_vector.h new file mode 100644 index 00000000000..c313ca4b152 --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/util_small_vector.h @@ -0,0 +1,133 @@ +#pragma once + +#include + +namespace dxvk { + + template + class small_vector { + using storage = std::aligned_storage_t; + public: + + small_vector() { } + + small_vector (const small_vector&) = delete; + small_vector& operator = (const small_vector&) = delete; + + ~small_vector() { + for (size_t i = 0; i < m_size; i++) + ptr(i)->~T(); + + if (m_capacity > N) + delete[] u.m_ptr; + } + + size_t size() const { + return m_size; + } + + void reserve(size_t n) { + n = pick_capacity(n); + + if (n <= m_capacity) + return; + + storage* data = new storage[n]; + + for (size_t i = 0; i < m_size; i++) { + new (&data[i]) T(std::move(*ptr(i))); + ptr(i)->~T(); + } + + if (m_capacity > N) + delete[] u.m_ptr; + + m_capacity = n; + u.m_ptr = data; + } + + const T* data() const { return ptr(0); } + T* data() { return ptr(0); } + + void resize(size_t n) { + reserve(n); + + for (size_t i = n; i < m_size; i++) + ptr(i)->~T(); + + for (size_t i = m_size; i < n; i++) + new (ptr(i)) T(); + } + + void push_back(const T& object) { + reserve(m_size + 1); + new (ptr(m_size++)) T(object); + } + + void push_back(T&& object) { + reserve(m_size + 1); + new (ptr(m_size++)) T(std::move(object)); + } + + template + void emplace_back(Args... args) { + reserve(m_size + 1); + new (ptr(m_size++)) T(std::forward(args)...); + } + + void erase(size_t idx) { + ptr(idx)->~T(); + + for (size_t i = idx; i < m_size - 1; i++) { + new (ptr(i)) T(std::move(*ptr(i + 1))); + ptr(i + 1)->~T(); + } + } + + void pop_back() { + ptr(--m_size)->~T(); + } + + T& operator [] (size_t idx) { return *ptr(idx); } + const T& operator [] (size_t idx) const { return *ptr(idx); } + + T& front() { return *ptr(0); } + const T& front() const { return *ptr(0); } + + T& back() { return *ptr(m_size - 1); } + const T& back() const { return *ptr(m_size - 1); } + + private: + + size_t m_capacity = N; + size_t m_size = 0; + + union { + storage* m_ptr; + storage m_data[sizeof(T) * N]; + } u; + + size_t pick_capacity(size_t n) { + size_t capacity = m_capacity; + + while (capacity < n) + capacity *= 2; + + return capacity; + } + + T* ptr(size_t idx) { + return m_capacity == N + ? reinterpret_cast(&u.m_data[idx]) + : reinterpret_cast(&u.m_ptr[idx]); + } + + const T* ptr(size_t idx) const { + return m_capacity == N + ? reinterpret_cast(&u.m_data[idx]) + : reinterpret_cast(&u.m_ptr[idx]); + } + + }; + +} diff --git a/utils/dxvk-1.10.3/src/util/util_string.cpp b/utils/dxvk-1.10.3/src/util/util_string.cpp new file mode 100644 index 00000000000..2151c1e4085 --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/util_string.cpp @@ -0,0 +1,43 @@ +#include "util_string.h" + +namespace dxvk::str { + std::string fromws(const WCHAR *ws) { + size_t len = ::WideCharToMultiByte(CP_UTF8, + 0, ws, -1, nullptr, 0, nullptr, nullptr); + + if (len <= 1) + return ""; + + len -= 1; + + std::string result; + result.resize(len); + ::WideCharToMultiByte(CP_UTF8, 0, ws, -1, + &result.at(0), len, nullptr, nullptr); + return result; + } + + + void tows(const char* mbs, WCHAR* wcs, size_t wcsLen) { + ::MultiByteToWideChar( + CP_UTF8, 0, mbs, -1, + wcs, wcsLen); + } + + std::wstring tows(const char* mbs) { + size_t len = ::MultiByteToWideChar(CP_UTF8, + 0, mbs, -1, nullptr, 0); + + if (len <= 1) + return L""; + + len -= 1; + + std::wstring result; + result.resize(len); + ::MultiByteToWideChar(CP_UTF8, 0, mbs, -1, + &result.at(0), len); + return result; + } + +} diff --git a/utils/dxvk-1.10.3/src/util/util_string.h b/utils/dxvk-1.10.3/src/util/util_string.h new file mode 100644 index 00000000000..ae6740343e7 --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/util_string.h @@ -0,0 +1,50 @@ +#pragma once + +#include +#include +#include +#include + +#include "./com/com_include.h" + +namespace dxvk::str { + + std::string fromws(const WCHAR *ws); + + void tows(const char* mbs, WCHAR* wcs, size_t wcsLen); + + template + void tows(const char* mbs, WCHAR (&wcs)[N]) { + return tows(mbs, wcs, N); + } + + std::wstring tows(const char* mbs); + + inline void format1(std::stringstream&) { } + + template + void format1(std::stringstream& str, const WCHAR *arg, const Tx&... args) { + str << fromws(arg); + format1(str, args...); + } + + template + void format1(std::stringstream& str, const T& arg, const Tx&... args) { + str << arg; + format1(str, args...); + } + + template + std::string format(const Args&... args) { + std::stringstream stream; + format1(stream, args...); + return stream.str(); + } + + inline void strlcpy(char* dst, const char* src, size_t count) { + std::strncpy(dst, src, count); + if (count > 0) + dst[count - 1] = '\0'; + } + +} diff --git a/utils/dxvk-1.10.3/src/util/util_time.h b/utils/dxvk-1.10.3/src/util/util_time.h new file mode 100644 index 00000000000..cbadfa5d027 --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/util_time.h @@ -0,0 +1,50 @@ +#pragma once + +#include +#include + +#if defined(_WIN32) && !defined(__WINE__) +#include +#endif + +namespace dxvk { + +#if defined(_WIN32) && !defined(__WINE__) + struct high_resolution_clock { + static constexpr bool is_steady = true; + + using rep = int64_t; + using period = std::nano; + using duration = std::chrono::nanoseconds; + using time_point = std::chrono::time_point; + + static inline time_point now() noexcept { + // Keep the frequency static, this doesn't change at all. + static const int64_t freq = getFrequency(); + const int64_t counter = getCounter(); + + const int64_t whole = (counter / freq) * period::den; + const int64_t part = (counter % freq) * period::den / freq; + + return time_point(duration(whole + part)); + } + + static inline int64_t getFrequency() { + LARGE_INTEGER freq; + QueryPerformanceFrequency(&freq); + + return freq.QuadPart; + } + + static inline int64_t getCounter() { + LARGE_INTEGER count; + QueryPerformanceCounter(&count); + + return count.QuadPart; + } + }; +#else + using high_resolution_clock = std::chrono::high_resolution_clock; +#endif + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/util/util_vector.h b/utils/dxvk-1.10.3/src/util/util_vector.h new file mode 100644 index 00000000000..77cdf2942b0 --- /dev/null +++ b/utils/dxvk-1.10.3/src/util/util_vector.h @@ -0,0 +1,161 @@ +#pragma once + +#include + +#include "util_bit.h" +#include "util_math.h" + +namespace dxvk { + + template + struct Vector4Base { + Vector4Base() + : x{ }, y{ }, z{ }, w{ } { } + + Vector4Base(T splat) + : x(splat), y(splat), z(splat), w(splat) { } + + Vector4Base(T x, T y, T z, T w) + : x(x), y(y), z(z), w(w) { } + + Vector4Base(const T xyzw[4]) + : x(xyzw[0]), y(xyzw[1]), z(xyzw[2]), w(xyzw[3]) { } + + Vector4Base(const Vector4Base& other) = default; + + inline T& operator[](size_t index) { return data[index]; } + inline const T& operator[](size_t index) const { return data[index]; } + + bool operator==(const Vector4Base& other) const { + for (uint32_t i = 0; i < 4; i++) { + if (data[i] != other.data[i]) + return false; + } + + return true; + } + + bool operator!=(const Vector4Base& other) const { + return !operator==(other); + } + + Vector4Base operator-() const { return {-x, -y, -z, -w}; } + + Vector4Base operator+(const Vector4Base& other) const { + return {x + other.x, y + other.y, z + other.z, w + other.w}; + } + + Vector4Base operator-(const Vector4Base& other) const { + return {x - other.x, y - other.y, z - other.z, w - other.w}; + } + + Vector4Base operator*(T scalar) const { + return {scalar * x, scalar * y, scalar * z, scalar * w}; + } + + Vector4Base operator*(const Vector4Base& other) const { + Vector4Base result; + for (uint32_t i = 0; i < 4; i++) + result[i] = data[i] * other.data[i]; + return result; + } + + Vector4Base operator/(const Vector4Base& other) const { + Vector4Base result; + for (uint32_t i = 0; i < 4; i++) + result[i] = data[i] / other.data[i]; + return result; + } + + Vector4Base operator/(T scalar) const { + return {x / scalar, y / scalar, z / scalar, w / scalar}; + } + + Vector4Base& operator+=(const Vector4Base& other) { + x += other.x; + y += other.y; + z += other.z; + w += other.w; + + return *this; + } + + Vector4Base& operator-=(const Vector4Base& other) { + x -= other.x; + y -= other.y; + z -= other.z; + w -= other.w; + + return *this; + } + + Vector4Base& operator*=(T scalar) { + x *= scalar; + y *= scalar; + z *= scalar; + w *= scalar; + + return *this; + } + + Vector4Base& operator/=(T scalar) { + x /= scalar; + y /= scalar; + z /= scalar; + w /= scalar; + + return *this; + } + + union { + T data[4]; + struct { + T x, y, z, w; + }; + struct { + T r, g, b, a; + }; + }; + + }; + + template + inline Vector4Base operator*(T scalar, const Vector4Base& vector) { + return vector * scalar; + } + + template + float dot(const Vector4Base& a, const Vector4Base& b) { + return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; + } + + template + T lengthSqr(const Vector4Base& a) { return dot(a, a); } + + template + float length(const Vector4Base& a) { return std::sqrt(float(lengthSqr(a))); } + + template + Vector4Base normalize(const Vector4Base& a) { return a * T(1.0f / length(a)); } + + template + std::ostream& operator<<(std::ostream& os, const Vector4Base& v) { + return os << "Vector4(" << v[0] << ", " << v[1] << ", " << v[2] << ", " << v[3] << ")"; + } + + using Vector4 = Vector4Base; + using Vector4i = Vector4Base; + + static_assert(sizeof(Vector4) == sizeof(float) * 4); + static_assert(sizeof(Vector4i) == sizeof(int) * 4); + + inline Vector4 replaceNaN(Vector4 a) { + Vector4 result; + __m128 value = _mm_load_ps(a.data); + __m128 mask = _mm_cmpeq_ps(value, value); + value = _mm_and_ps(value, mask); + _mm_store_ps(result.data, value); + return result; + } + +} diff --git a/utils/dxvk-1.10.3/src/vulkan/meson.build b/utils/dxvk-1.10.3/src/vulkan/meson.build new file mode 100644 index 00000000000..91350ea10cf --- /dev/null +++ b/utils/dxvk-1.10.3/src/vulkan/meson.build @@ -0,0 +1,17 @@ +vkcommon_src = files([ + 'vulkan_loader.cpp', + 'vulkan_names.cpp', + 'vulkan_presenter.cpp', +]) + +thread_dep = dependency('threads') + +vkcommon_lib = static_library('vkcommon', vkcommon_src, + dependencies : [ thread_dep, lib_vulkan ], + include_directories : [ dxvk_include_path ], +) + +vkcommon_dep = declare_dependency( + link_with : [ vkcommon_lib ], + include_directories : [ dxvk_include_path ], +) diff --git a/utils/dxvk-1.10.3/src/vulkan/vulkan_loader.cpp b/utils/dxvk-1.10.3/src/vulkan/vulkan_loader.cpp new file mode 100644 index 00000000000..faa5155f99e --- /dev/null +++ b/utils/dxvk-1.10.3/src/vulkan/vulkan_loader.cpp @@ -0,0 +1,51 @@ +#include "vulkan_loader.h" + +namespace dxvk::vk { + + static const PFN_vkGetInstanceProcAddr GetInstanceProcAddr = vkGetInstanceProcAddr; + + PFN_vkVoidFunction LibraryLoader::sym(const char* name) const { + return dxvk::vk::GetInstanceProcAddr(nullptr, name); + } + + + InstanceLoader::InstanceLoader(bool owned, VkInstance instance) + : m_instance(instance), m_owned(owned) { } + + + PFN_vkVoidFunction InstanceLoader::sym(const char* name) const { + return dxvk::vk::GetInstanceProcAddr(m_instance, name); + } + + + DeviceLoader::DeviceLoader(bool owned, VkInstance instance, VkDevice device) + : m_getDeviceProcAddr(reinterpret_cast( + dxvk::vk::GetInstanceProcAddr(instance, "vkGetDeviceProcAddr"))), + m_device(device), m_owned(owned) { } + + + PFN_vkVoidFunction DeviceLoader::sym(const char* name) const { + return m_getDeviceProcAddr(m_device, name); + } + + + LibraryFn::LibraryFn() { } + LibraryFn::~LibraryFn() { } + + + InstanceFn::InstanceFn(bool owned, VkInstance instance) + : InstanceLoader(owned, instance) { } + InstanceFn::~InstanceFn() { + if (m_owned) + this->vkDestroyInstance(m_instance, nullptr); + } + + + DeviceFn::DeviceFn(bool owned, VkInstance instance, VkDevice device) + : DeviceLoader(owned, instance, device) { } + DeviceFn::~DeviceFn() { + if (m_owned) + this->vkDestroyDevice(m_device, nullptr); + } + +} \ No newline at end of file diff --git a/utils/dxvk-1.10.3/src/vulkan/vulkan_loader.h b/utils/dxvk-1.10.3/src/vulkan/vulkan_loader.h new file mode 100644 index 00000000000..9d9a4d6ecaa --- /dev/null +++ b/utils/dxvk-1.10.3/src/vulkan/vulkan_loader.h @@ -0,0 +1,386 @@ +#pragma once + +#include "../util/rc/util_rc.h" +#include "../util/rc/util_rc_ptr.h" + +#define VK_USE_PLATFORM_WIN32_KHR 1 +#include + +#define VULKAN_FN(name) \ + ::PFN_ ## name name = reinterpret_cast<::PFN_ ## name>(sym(#name)) + +namespace dxvk::vk { + + /** + * \brief Vulkan library loader + * + * Provides methods to load Vulkan functions that + * can be called before creating a instance. + */ + struct LibraryLoader : public RcObject { + PFN_vkVoidFunction sym(const char* name) const; + }; + + + /** + * \brief Vulkan instance loader + * + * Loads Vulkan functions that can be + * called for a specific instance. + */ + struct InstanceLoader : public RcObject { + InstanceLoader(bool owned, VkInstance instance); + PFN_vkVoidFunction sym(const char* name) const; + VkInstance instance() const { return m_instance; } + protected: + const VkInstance m_instance; + const bool m_owned; + }; + + + /** + * \brief Vulkan device loader + * + * Loads Vulkan functions for a + * specific device. + */ + struct DeviceLoader : public RcObject { + DeviceLoader(bool owned, VkInstance instance, VkDevice device); + PFN_vkVoidFunction sym(const char* name) const; + VkDevice device() const { return m_device; } + protected: + const PFN_vkGetDeviceProcAddr m_getDeviceProcAddr; + const VkDevice m_device; + const bool m_owned; + }; + + + /** + * \brief Vulkan library functions + * + * Vulkan functions that are called before + * creating an actual Vulkan instance. + */ + struct LibraryFn : LibraryLoader { + LibraryFn(); + ~LibraryFn(); + + VULKAN_FN(vkCreateInstance); + VULKAN_FN(vkEnumerateInstanceLayerProperties); + VULKAN_FN(vkEnumerateInstanceExtensionProperties); + }; + + + /** + * \brief Vulkan instance functions + * + * Vulkan functions for a given instance that + * are independent of any Vulkan devices. + */ + struct InstanceFn : InstanceLoader { + InstanceFn(bool owned, VkInstance instance); + ~InstanceFn(); + + VULKAN_FN(vkCreateDevice); + VULKAN_FN(vkDestroyInstance); + VULKAN_FN(vkEnumerateDeviceExtensionProperties); + VULKAN_FN(vkEnumeratePhysicalDevices); + VULKAN_FN(vkGetPhysicalDeviceExternalSemaphoreProperties); + VULKAN_FN(vkGetPhysicalDeviceFeatures); + VULKAN_FN(vkGetPhysicalDeviceFeatures2); + VULKAN_FN(vkGetPhysicalDeviceFormatProperties); + VULKAN_FN(vkGetPhysicalDeviceFormatProperties2); + VULKAN_FN(vkGetPhysicalDeviceProperties2); + VULKAN_FN(vkGetPhysicalDeviceImageFormatProperties); + VULKAN_FN(vkGetPhysicalDeviceImageFormatProperties2); + VULKAN_FN(vkGetPhysicalDeviceMemoryProperties); + VULKAN_FN(vkGetPhysicalDeviceMemoryProperties2); + VULKAN_FN(vkGetPhysicalDeviceProperties); + VULKAN_FN(vkGetPhysicalDeviceQueueFamilyProperties); + VULKAN_FN(vkGetPhysicalDeviceQueueFamilyProperties2); + VULKAN_FN(vkGetPhysicalDeviceSparseImageFormatProperties); + VULKAN_FN(vkGetPhysicalDeviceSparseImageFormatProperties2); + + #ifdef VK_KHR_get_surface_capabilities2 + VULKAN_FN(vkGetPhysicalDeviceSurfaceCapabilities2KHR); + VULKAN_FN(vkGetPhysicalDeviceSurfaceFormats2KHR); + #endif + + #ifdef VK_KHR_surface + #ifdef VK_USE_PLATFORM_XCB_KHR + VULKAN_FN(vkCreateXcbSurfaceKHR); + VULKAN_FN(vkGetPhysicalDeviceXcbPresentationSupportKHR); + #endif + + #ifdef VK_USE_PLATFORM_XLIB_KHR + VULKAN_FN(vkCreateXlibSurfaceKHR); + VULKAN_FN(vkGetPhysicalDeviceXlibPresentationSupportKHR); + #endif + + #ifdef VK_USE_PLATFORM_WAYLAND_KHR + VULKAN_FN(vkCreateWaylandSurfaceKHR); + VULKAN_FN(vkGetPhysicalDeviceWaylandPresentationSupportKHR); + #endif + + #ifdef VK_USE_PLATFORM_WIN32_KHR + VULKAN_FN(vkCreateWin32SurfaceKHR); + VULKAN_FN(vkGetPhysicalDeviceWin32PresentationSupportKHR); + #endif + + VULKAN_FN(vkDestroySurfaceKHR); + + VULKAN_FN(vkGetPhysicalDeviceSurfaceSupportKHR); + VULKAN_FN(vkGetPhysicalDeviceSurfaceCapabilitiesKHR); + VULKAN_FN(vkGetPhysicalDeviceSurfaceFormatsKHR); + VULKAN_FN(vkGetPhysicalDeviceSurfacePresentModesKHR); + #endif + + #ifdef VK_EXT_debug_report + VULKAN_FN(vkCreateDebugReportCallbackEXT); + VULKAN_FN(vkDestroyDebugReportCallbackEXT); + VULKAN_FN(vkDebugReportMessageEXT); + #endif + + #ifdef VK_EXT_debug_utils + VULKAN_FN(vkCmdBeginDebugUtilsLabelEXT); + VULKAN_FN(vkCmdEndDebugUtilsLabelEXT); + VULKAN_FN(vkCmdInsertDebugUtilsLabelEXT); + #endif + + #ifdef VK_EXT_full_screen_exclusive + VULKAN_FN(vkGetPhysicalDeviceSurfacePresentModes2EXT); + #endif + }; + + + /** + * \brief Vulkan device functions + * + * Vulkan functions for a specific Vulkan device. + * This ensures that no slow dispatch code is executed. + */ + struct DeviceFn : DeviceLoader { + DeviceFn(bool owned, VkInstance instance, VkDevice device); + ~DeviceFn(); + + VULKAN_FN(vkDestroyDevice); + VULKAN_FN(vkGetDeviceQueue); + VULKAN_FN(vkQueueSubmit); + VULKAN_FN(vkQueueWaitIdle); + VULKAN_FN(vkDeviceWaitIdle); + VULKAN_FN(vkAllocateMemory); + VULKAN_FN(vkFreeMemory); + VULKAN_FN(vkMapMemory); + VULKAN_FN(vkUnmapMemory); + VULKAN_FN(vkFlushMappedMemoryRanges); + VULKAN_FN(vkInvalidateMappedMemoryRanges); + VULKAN_FN(vkGetDeviceMemoryCommitment); + VULKAN_FN(vkBindBufferMemory); + VULKAN_FN(vkBindImageMemory); + VULKAN_FN(vkGetBufferMemoryRequirements); + VULKAN_FN(vkGetBufferMemoryRequirements2); + VULKAN_FN(vkGetImageMemoryRequirements); + VULKAN_FN(vkGetImageMemoryRequirements2); + VULKAN_FN(vkGetImageSparseMemoryRequirements); + VULKAN_FN(vkGetImageSparseMemoryRequirements2); + VULKAN_FN(vkQueueBindSparse); + VULKAN_FN(vkCreateFence); + VULKAN_FN(vkDestroyFence); + VULKAN_FN(vkResetFences); + VULKAN_FN(vkGetFenceStatus); + VULKAN_FN(vkWaitForFences); + VULKAN_FN(vkCreateSemaphore); + VULKAN_FN(vkDestroySemaphore); + VULKAN_FN(vkCreateEvent); + VULKAN_FN(vkDestroyEvent); + VULKAN_FN(vkGetEventStatus); + VULKAN_FN(vkSetEvent); + VULKAN_FN(vkResetEvent); + VULKAN_FN(vkCreateQueryPool); + VULKAN_FN(vkDestroyQueryPool); + VULKAN_FN(vkGetQueryPoolResults); + VULKAN_FN(vkCreateBuffer); + VULKAN_FN(vkDestroyBuffer); + VULKAN_FN(vkCreateBufferView); + VULKAN_FN(vkDestroyBufferView); + VULKAN_FN(vkCreateImage); + VULKAN_FN(vkDestroyImage); + VULKAN_FN(vkGetImageSubresourceLayout); + VULKAN_FN(vkCreateImageView); + VULKAN_FN(vkDestroyImageView); + VULKAN_FN(vkCreateShaderModule); + VULKAN_FN(vkDestroyShaderModule); + VULKAN_FN(vkCreatePipelineCache); + VULKAN_FN(vkDestroyPipelineCache); + VULKAN_FN(vkGetPipelineCacheData); + VULKAN_FN(vkMergePipelineCaches); + VULKAN_FN(vkCreateGraphicsPipelines); + VULKAN_FN(vkCreateComputePipelines); + VULKAN_FN(vkDestroyPipeline); + VULKAN_FN(vkCreatePipelineLayout); + VULKAN_FN(vkDestroyPipelineLayout); + VULKAN_FN(vkCreateSampler); + VULKAN_FN(vkDestroySampler); + VULKAN_FN(vkCreateDescriptorSetLayout); + VULKAN_FN(vkDestroyDescriptorSetLayout); + VULKAN_FN(vkCreateDescriptorPool); + VULKAN_FN(vkDestroyDescriptorPool); + VULKAN_FN(vkResetDescriptorPool); + VULKAN_FN(vkAllocateDescriptorSets); + VULKAN_FN(vkFreeDescriptorSets); + VULKAN_FN(vkUpdateDescriptorSets); + VULKAN_FN(vkCreateFramebuffer); + VULKAN_FN(vkDestroyFramebuffer); + VULKAN_FN(vkCreateRenderPass); + VULKAN_FN(vkDestroyRenderPass); + VULKAN_FN(vkGetRenderAreaGranularity); + VULKAN_FN(vkCreateCommandPool); + VULKAN_FN(vkDestroyCommandPool); + VULKAN_FN(vkResetCommandPool); + VULKAN_FN(vkAllocateCommandBuffers); + VULKAN_FN(vkFreeCommandBuffers); + VULKAN_FN(vkBeginCommandBuffer); + VULKAN_FN(vkEndCommandBuffer); + VULKAN_FN(vkResetCommandBuffer); + VULKAN_FN(vkCreateDescriptorUpdateTemplate); + VULKAN_FN(vkDestroyDescriptorUpdateTemplate); + VULKAN_FN(vkUpdateDescriptorSetWithTemplate); + VULKAN_FN(vkCmdBindPipeline); + VULKAN_FN(vkCmdSetViewport); + VULKAN_FN(vkCmdSetScissor); + VULKAN_FN(vkCmdSetLineWidth); + VULKAN_FN(vkCmdSetDepthBias); + VULKAN_FN(vkCmdSetBlendConstants); + VULKAN_FN(vkCmdSetDepthBounds); + VULKAN_FN(vkCmdSetStencilCompareMask); + VULKAN_FN(vkCmdSetStencilWriteMask); + VULKAN_FN(vkCmdSetStencilReference); + VULKAN_FN(vkCmdBindDescriptorSets); + VULKAN_FN(vkCmdBindIndexBuffer); + VULKAN_FN(vkCmdBindVertexBuffers); + VULKAN_FN(vkCmdDraw); + VULKAN_FN(vkCmdDrawIndexed); + VULKAN_FN(vkCmdDrawIndirect); + VULKAN_FN(vkCmdDrawIndexedIndirect); + VULKAN_FN(vkCmdDispatch); + VULKAN_FN(vkCmdDispatchIndirect); + VULKAN_FN(vkCmdCopyBuffer); + VULKAN_FN(vkCmdCopyImage); + VULKAN_FN(vkCmdBlitImage); + VULKAN_FN(vkCmdCopyBufferToImage); + VULKAN_FN(vkCmdCopyImageToBuffer); + VULKAN_FN(vkCmdUpdateBuffer); + VULKAN_FN(vkCmdFillBuffer); + VULKAN_FN(vkCmdClearColorImage); + VULKAN_FN(vkCmdClearDepthStencilImage); + VULKAN_FN(vkCmdClearAttachments); + VULKAN_FN(vkCmdResolveImage); + VULKAN_FN(vkCmdSetEvent); + VULKAN_FN(vkCmdResetEvent); + VULKAN_FN(vkCmdWaitEvents); + VULKAN_FN(vkCmdPipelineBarrier); + VULKAN_FN(vkCmdBeginQuery); + VULKAN_FN(vkCmdEndQuery); + VULKAN_FN(vkCmdResetQueryPool); + VULKAN_FN(vkCmdWriteTimestamp); + VULKAN_FN(vkCmdCopyQueryPoolResults); + VULKAN_FN(vkCmdPushConstants); + VULKAN_FN(vkCmdBeginRenderPass); + VULKAN_FN(vkCmdNextSubpass); + VULKAN_FN(vkCmdEndRenderPass); + VULKAN_FN(vkCmdExecuteCommands); + + #ifdef VK_KHR_create_renderpass2 + VULKAN_FN(vkCreateRenderPass2KHR); + VULKAN_FN(vkCmdBeginRenderPass2KHR); + VULKAN_FN(vkCmdNextSubpass2KHR); + VULKAN_FN(vkCmdEndRenderPass2KHR); + #endif + + #ifdef VK_KHR_draw_indirect_count + VULKAN_FN(vkCmdDrawIndirectCountKHR); + VULKAN_FN(vkCmdDrawIndexedIndirectCountKHR); + #endif + + #ifdef VK_KHR_swapchain + VULKAN_FN(vkCreateSwapchainKHR); + VULKAN_FN(vkDestroySwapchainKHR); + VULKAN_FN(vkGetSwapchainImagesKHR); + VULKAN_FN(vkAcquireNextImageKHR); + VULKAN_FN(vkQueuePresentKHR); + #endif + + #ifdef VK_KHR_timeline_semaphore + VULKAN_FN(vkGetSemaphoreCounterValueKHR); + VULKAN_FN(vkSignalSemaphoreKHR); + VULKAN_FN(vkWaitSemaphoresKHR); + #endif + + #ifdef VK_EXT_conditional_rendering + VULKAN_FN(vkCmdBeginConditionalRenderingEXT); + VULKAN_FN(vkCmdEndConditionalRenderingEXT); + #endif + + #ifdef VK_EXT_extended_dynamic_state + VULKAN_FN(vkCmdBindVertexBuffers2EXT); + VULKAN_FN(vkCmdSetCullModeEXT); + VULKAN_FN(vkCmdSetDepthBoundsTestEnableEXT); + VULKAN_FN(vkCmdSetDepthCompareOpEXT); + VULKAN_FN(vkCmdSetDepthTestEnableEXT); + VULKAN_FN(vkCmdSetDepthWriteEnableEXT); + VULKAN_FN(vkCmdSetFrontFaceEXT); + VULKAN_FN(vkCmdSetPrimitiveTopologyEXT); + VULKAN_FN(vkCmdSetScissorWithCountEXT); + VULKAN_FN(vkCmdSetStencilOpEXT); + VULKAN_FN(vkCmdSetStencilTestEnableEXT); + VULKAN_FN(vkCmdSetViewportWithCountEXT); + #endif + + #ifdef VK_EXT_full_screen_exclusive + VULKAN_FN(vkAcquireFullScreenExclusiveModeEXT); + VULKAN_FN(vkReleaseFullScreenExclusiveModeEXT); + VULKAN_FN(vkGetDeviceGroupSurfacePresentModes2EXT); + #endif + + #ifdef VK_EXT_host_query_reset + VULKAN_FN(vkResetQueryPoolEXT); + #endif + + #ifdef VK_EXT_transform_feedback + VULKAN_FN(vkCmdBindTransformFeedbackBuffersEXT); + VULKAN_FN(vkCmdBeginTransformFeedbackEXT); + VULKAN_FN(vkCmdEndTransformFeedbackEXT); + VULKAN_FN(vkCmdDrawIndirectByteCountEXT); + VULKAN_FN(vkCmdBeginQueryIndexedEXT); + VULKAN_FN(vkCmdEndQueryIndexedEXT); + #endif + + #ifdef VK_NVX_image_view_handle + VULKAN_FN(vkGetImageViewHandleNVX); + VULKAN_FN(vkGetImageViewAddressNVX); + #endif + + #ifdef VK_NVX_binary_import + VULKAN_FN(vkCreateCuModuleNVX); + VULKAN_FN(vkCreateCuFunctionNVX); + VULKAN_FN(vkDestroyCuModuleNVX); + VULKAN_FN(vkDestroyCuFunctionNVX); + VULKAN_FN(vkCmdCuLaunchKernelNVX); + #endif + + #ifdef VK_KHR_buffer_device_address + VULKAN_FN(vkGetBufferDeviceAddressKHR); + #endif + + #ifdef VK_KHR_external_memory_win32 + VULKAN_FN(vkGetMemoryWin32HandleKHR); + VULKAN_FN(vkGetMemoryWin32HandlePropertiesKHR); + #endif + + #ifdef VK_KHR_external_semaphore_win32 + VULKAN_FN(vkGetSemaphoreWin32HandleKHR); + VULKAN_FN(vkImportSemaphoreWin32HandleKHR); + #endif + }; + +} diff --git a/utils/dxvk-1.10.3/src/vulkan/vulkan_names.cpp b/utils/dxvk-1.10.3/src/vulkan/vulkan_names.cpp new file mode 100644 index 00000000000..1dd6d7cf651 --- /dev/null +++ b/utils/dxvk-1.10.3/src/vulkan/vulkan_names.cpp @@ -0,0 +1,333 @@ +#include "vulkan_names.h" + +std::ostream& operator << (std::ostream& os, VkPipelineCacheHeaderVersion e) { + switch (e) { + ENUM_NAME(VK_PIPELINE_CACHE_HEADER_VERSION_ONE); + ENUM_DEFAULT(e); + } + return os; +} + + +std::ostream& operator << (std::ostream& os, VkResult e) { + switch (e) { + ENUM_NAME(VK_SUCCESS); + ENUM_NAME(VK_NOT_READY); + ENUM_NAME(VK_TIMEOUT); + ENUM_NAME(VK_EVENT_SET); + ENUM_NAME(VK_EVENT_RESET); + ENUM_NAME(VK_INCOMPLETE); + ENUM_NAME(VK_ERROR_OUT_OF_HOST_MEMORY); + ENUM_NAME(VK_ERROR_OUT_OF_DEVICE_MEMORY); + ENUM_NAME(VK_ERROR_INITIALIZATION_FAILED); + ENUM_NAME(VK_ERROR_DEVICE_LOST); + ENUM_NAME(VK_ERROR_MEMORY_MAP_FAILED); + ENUM_NAME(VK_ERROR_LAYER_NOT_PRESENT); + ENUM_NAME(VK_ERROR_EXTENSION_NOT_PRESENT); + ENUM_NAME(VK_ERROR_FEATURE_NOT_PRESENT); + ENUM_NAME(VK_ERROR_INCOMPATIBLE_DRIVER); + ENUM_NAME(VK_ERROR_TOO_MANY_OBJECTS); + ENUM_NAME(VK_ERROR_FORMAT_NOT_SUPPORTED); + ENUM_NAME(VK_ERROR_FRAGMENTED_POOL); + ENUM_NAME(VK_ERROR_SURFACE_LOST_KHR); + ENUM_NAME(VK_ERROR_NATIVE_WINDOW_IN_USE_KHR); + ENUM_NAME(VK_SUBOPTIMAL_KHR); + ENUM_NAME(VK_ERROR_OUT_OF_DATE_KHR); + ENUM_NAME(VK_ERROR_INCOMPATIBLE_DISPLAY_KHR); + ENUM_NAME(VK_ERROR_VALIDATION_FAILED_EXT); + ENUM_NAME(VK_ERROR_INVALID_SHADER_NV); + ENUM_NAME(VK_ERROR_OUT_OF_POOL_MEMORY_KHR); + ENUM_NAME(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR); + ENUM_DEFAULT(e); + } + return os; +} + + +std::ostream& operator << (std::ostream& os, VkFormat e) { + switch (e) { + ENUM_NAME(VK_FORMAT_UNDEFINED); + ENUM_NAME(VK_FORMAT_R4G4_UNORM_PACK8); + ENUM_NAME(VK_FORMAT_R4G4B4A4_UNORM_PACK16); + ENUM_NAME(VK_FORMAT_B4G4R4A4_UNORM_PACK16); + ENUM_NAME(VK_FORMAT_R5G6B5_UNORM_PACK16); + ENUM_NAME(VK_FORMAT_B5G6R5_UNORM_PACK16); + ENUM_NAME(VK_FORMAT_R5G5B5A1_UNORM_PACK16); + ENUM_NAME(VK_FORMAT_B5G5R5A1_UNORM_PACK16); + ENUM_NAME(VK_FORMAT_A1R5G5B5_UNORM_PACK16); + ENUM_NAME(VK_FORMAT_R8_UNORM); + ENUM_NAME(VK_FORMAT_R8_SNORM); + ENUM_NAME(VK_FORMAT_R8_USCALED); + ENUM_NAME(VK_FORMAT_R8_SSCALED); + ENUM_NAME(VK_FORMAT_R8_UINT); + ENUM_NAME(VK_FORMAT_R8_SINT); + ENUM_NAME(VK_FORMAT_R8_SRGB); + ENUM_NAME(VK_FORMAT_R8G8_UNORM); + ENUM_NAME(VK_FORMAT_R8G8_SNORM); + ENUM_NAME(VK_FORMAT_R8G8_USCALED); + ENUM_NAME(VK_FORMAT_R8G8_SSCALED); + ENUM_NAME(VK_FORMAT_R8G8_UINT); + ENUM_NAME(VK_FORMAT_R8G8_SINT); + ENUM_NAME(VK_FORMAT_R8G8_SRGB); + ENUM_NAME(VK_FORMAT_R8G8B8_UNORM); + ENUM_NAME(VK_FORMAT_R8G8B8_SNORM); + ENUM_NAME(VK_FORMAT_R8G8B8_USCALED); + ENUM_NAME(VK_FORMAT_R8G8B8_SSCALED); + ENUM_NAME(VK_FORMAT_R8G8B8_UINT); + ENUM_NAME(VK_FORMAT_R8G8B8_SINT); + ENUM_NAME(VK_FORMAT_R8G8B8_SRGB); + ENUM_NAME(VK_FORMAT_B8G8R8_UNORM); + ENUM_NAME(VK_FORMAT_B8G8R8_SNORM); + ENUM_NAME(VK_FORMAT_B8G8R8_USCALED); + ENUM_NAME(VK_FORMAT_B8G8R8_SSCALED); + ENUM_NAME(VK_FORMAT_B8G8R8_UINT); + ENUM_NAME(VK_FORMAT_B8G8R8_SINT); + ENUM_NAME(VK_FORMAT_B8G8R8_SRGB); + ENUM_NAME(VK_FORMAT_R8G8B8A8_UNORM); + ENUM_NAME(VK_FORMAT_R8G8B8A8_SNORM); + ENUM_NAME(VK_FORMAT_R8G8B8A8_USCALED); + ENUM_NAME(VK_FORMAT_R8G8B8A8_SSCALED); + ENUM_NAME(VK_FORMAT_R8G8B8A8_UINT); + ENUM_NAME(VK_FORMAT_R8G8B8A8_SINT); + ENUM_NAME(VK_FORMAT_R8G8B8A8_SRGB); + ENUM_NAME(VK_FORMAT_B8G8R8A8_UNORM); + ENUM_NAME(VK_FORMAT_B8G8R8A8_SNORM); + ENUM_NAME(VK_FORMAT_B8G8R8A8_USCALED); + ENUM_NAME(VK_FORMAT_B8G8R8A8_SSCALED); + ENUM_NAME(VK_FORMAT_B8G8R8A8_UINT); + ENUM_NAME(VK_FORMAT_B8G8R8A8_SINT); + ENUM_NAME(VK_FORMAT_B8G8R8A8_SRGB); + ENUM_NAME(VK_FORMAT_A8B8G8R8_UNORM_PACK32); + ENUM_NAME(VK_FORMAT_A8B8G8R8_SNORM_PACK32); + ENUM_NAME(VK_FORMAT_A8B8G8R8_USCALED_PACK32); + ENUM_NAME(VK_FORMAT_A8B8G8R8_SSCALED_PACK32); + ENUM_NAME(VK_FORMAT_A8B8G8R8_UINT_PACK32); + ENUM_NAME(VK_FORMAT_A8B8G8R8_SINT_PACK32); + ENUM_NAME(VK_FORMAT_A8B8G8R8_SRGB_PACK32); + ENUM_NAME(VK_FORMAT_A2R10G10B10_UNORM_PACK32); + ENUM_NAME(VK_FORMAT_A2R10G10B10_SNORM_PACK32); + ENUM_NAME(VK_FORMAT_A2R10G10B10_USCALED_PACK32); + ENUM_NAME(VK_FORMAT_A2R10G10B10_SSCALED_PACK32); + ENUM_NAME(VK_FORMAT_A2R10G10B10_UINT_PACK32); + ENUM_NAME(VK_FORMAT_A2R10G10B10_SINT_PACK32); + ENUM_NAME(VK_FORMAT_A2B10G10R10_UNORM_PACK32); + ENUM_NAME(VK_FORMAT_A2B10G10R10_SNORM_PACK32); + ENUM_NAME(VK_FORMAT_A2B10G10R10_USCALED_PACK32); + ENUM_NAME(VK_FORMAT_A2B10G10R10_SSCALED_PACK32); + ENUM_NAME(VK_FORMAT_A2B10G10R10_UINT_PACK32); + ENUM_NAME(VK_FORMAT_A2B10G10R10_SINT_PACK32); + ENUM_NAME(VK_FORMAT_R16_UNORM); + ENUM_NAME(VK_FORMAT_R16_SNORM); + ENUM_NAME(VK_FORMAT_R16_USCALED); + ENUM_NAME(VK_FORMAT_R16_SSCALED); + ENUM_NAME(VK_FORMAT_R16_UINT); + ENUM_NAME(VK_FORMAT_R16_SINT); + ENUM_NAME(VK_FORMAT_R16_SFLOAT); + ENUM_NAME(VK_FORMAT_R16G16_UNORM); + ENUM_NAME(VK_FORMAT_R16G16_SNORM); + ENUM_NAME(VK_FORMAT_R16G16_USCALED); + ENUM_NAME(VK_FORMAT_R16G16_SSCALED); + ENUM_NAME(VK_FORMAT_R16G16_UINT); + ENUM_NAME(VK_FORMAT_R16G16_SINT); + ENUM_NAME(VK_FORMAT_R16G16_SFLOAT); + ENUM_NAME(VK_FORMAT_R16G16B16_UNORM); + ENUM_NAME(VK_FORMAT_R16G16B16_SNORM); + ENUM_NAME(VK_FORMAT_R16G16B16_USCALED); + ENUM_NAME(VK_FORMAT_R16G16B16_SSCALED); + ENUM_NAME(VK_FORMAT_R16G16B16_UINT); + ENUM_NAME(VK_FORMAT_R16G16B16_SINT); + ENUM_NAME(VK_FORMAT_R16G16B16_SFLOAT); + ENUM_NAME(VK_FORMAT_R16G16B16A16_UNORM); + ENUM_NAME(VK_FORMAT_R16G16B16A16_SNORM); + ENUM_NAME(VK_FORMAT_R16G16B16A16_USCALED); + ENUM_NAME(VK_FORMAT_R16G16B16A16_SSCALED); + ENUM_NAME(VK_FORMAT_R16G16B16A16_UINT); + ENUM_NAME(VK_FORMAT_R16G16B16A16_SINT); + ENUM_NAME(VK_FORMAT_R16G16B16A16_SFLOAT); + ENUM_NAME(VK_FORMAT_R32_UINT); + ENUM_NAME(VK_FORMAT_R32_SINT); + ENUM_NAME(VK_FORMAT_R32_SFLOAT); + ENUM_NAME(VK_FORMAT_R32G32_UINT); + ENUM_NAME(VK_FORMAT_R32G32_SINT); + ENUM_NAME(VK_FORMAT_R32G32_SFLOAT); + ENUM_NAME(VK_FORMAT_R32G32B32_UINT); + ENUM_NAME(VK_FORMAT_R32G32B32_SINT); + ENUM_NAME(VK_FORMAT_R32G32B32_SFLOAT); + ENUM_NAME(VK_FORMAT_R32G32B32A32_UINT); + ENUM_NAME(VK_FORMAT_R32G32B32A32_SINT); + ENUM_NAME(VK_FORMAT_R32G32B32A32_SFLOAT); + ENUM_NAME(VK_FORMAT_R64_UINT); + ENUM_NAME(VK_FORMAT_R64_SINT); + ENUM_NAME(VK_FORMAT_R64_SFLOAT); + ENUM_NAME(VK_FORMAT_R64G64_UINT); + ENUM_NAME(VK_FORMAT_R64G64_SINT); + ENUM_NAME(VK_FORMAT_R64G64_SFLOAT); + ENUM_NAME(VK_FORMAT_R64G64B64_UINT); + ENUM_NAME(VK_FORMAT_R64G64B64_SINT); + ENUM_NAME(VK_FORMAT_R64G64B64_SFLOAT); + ENUM_NAME(VK_FORMAT_R64G64B64A64_UINT); + ENUM_NAME(VK_FORMAT_R64G64B64A64_SINT); + ENUM_NAME(VK_FORMAT_R64G64B64A64_SFLOAT); + ENUM_NAME(VK_FORMAT_B10G11R11_UFLOAT_PACK32); + ENUM_NAME(VK_FORMAT_E5B9G9R9_UFLOAT_PACK32); + ENUM_NAME(VK_FORMAT_D16_UNORM); + ENUM_NAME(VK_FORMAT_X8_D24_UNORM_PACK32); + ENUM_NAME(VK_FORMAT_D32_SFLOAT); + ENUM_NAME(VK_FORMAT_S8_UINT); + ENUM_NAME(VK_FORMAT_D16_UNORM_S8_UINT); + ENUM_NAME(VK_FORMAT_D24_UNORM_S8_UINT); + ENUM_NAME(VK_FORMAT_D32_SFLOAT_S8_UINT); + ENUM_NAME(VK_FORMAT_BC1_RGB_UNORM_BLOCK); + ENUM_NAME(VK_FORMAT_BC1_RGB_SRGB_BLOCK); + ENUM_NAME(VK_FORMAT_BC1_RGBA_UNORM_BLOCK); + ENUM_NAME(VK_FORMAT_BC1_RGBA_SRGB_BLOCK); + ENUM_NAME(VK_FORMAT_BC2_UNORM_BLOCK); + ENUM_NAME(VK_FORMAT_BC2_SRGB_BLOCK); + ENUM_NAME(VK_FORMAT_BC3_UNORM_BLOCK); + ENUM_NAME(VK_FORMAT_BC3_SRGB_BLOCK); + ENUM_NAME(VK_FORMAT_BC4_UNORM_BLOCK); + ENUM_NAME(VK_FORMAT_BC4_SNORM_BLOCK); + ENUM_NAME(VK_FORMAT_BC5_UNORM_BLOCK); + ENUM_NAME(VK_FORMAT_BC5_SNORM_BLOCK); + ENUM_NAME(VK_FORMAT_BC6H_UFLOAT_BLOCK); + ENUM_NAME(VK_FORMAT_BC6H_SFLOAT_BLOCK); + ENUM_NAME(VK_FORMAT_BC7_UNORM_BLOCK); + ENUM_NAME(VK_FORMAT_BC7_SRGB_BLOCK); + ENUM_NAME(VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK); + ENUM_NAME(VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK); + ENUM_NAME(VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK); + ENUM_NAME(VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK); + ENUM_NAME(VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK); + ENUM_NAME(VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK); + ENUM_NAME(VK_FORMAT_EAC_R11_UNORM_BLOCK); + ENUM_NAME(VK_FORMAT_EAC_R11_SNORM_BLOCK); + ENUM_NAME(VK_FORMAT_EAC_R11G11_UNORM_BLOCK); + ENUM_NAME(VK_FORMAT_EAC_R11G11_SNORM_BLOCK); + ENUM_NAME(VK_FORMAT_ASTC_4x4_UNORM_BLOCK); + ENUM_NAME(VK_FORMAT_ASTC_4x4_SRGB_BLOCK); + ENUM_NAME(VK_FORMAT_ASTC_5x4_UNORM_BLOCK); + ENUM_NAME(VK_FORMAT_ASTC_5x4_SRGB_BLOCK); + ENUM_NAME(VK_FORMAT_ASTC_5x5_UNORM_BLOCK); + ENUM_NAME(VK_FORMAT_ASTC_5x5_SRGB_BLOCK); + ENUM_NAME(VK_FORMAT_ASTC_6x5_UNORM_BLOCK); + ENUM_NAME(VK_FORMAT_ASTC_6x5_SRGB_BLOCK); + ENUM_NAME(VK_FORMAT_ASTC_6x6_UNORM_BLOCK); + ENUM_NAME(VK_FORMAT_ASTC_6x6_SRGB_BLOCK); + ENUM_NAME(VK_FORMAT_ASTC_8x5_UNORM_BLOCK); + ENUM_NAME(VK_FORMAT_ASTC_8x5_SRGB_BLOCK); + ENUM_NAME(VK_FORMAT_ASTC_8x6_UNORM_BLOCK); + ENUM_NAME(VK_FORMAT_ASTC_8x6_SRGB_BLOCK); + ENUM_NAME(VK_FORMAT_ASTC_8x8_UNORM_BLOCK); + ENUM_NAME(VK_FORMAT_ASTC_8x8_SRGB_BLOCK); + ENUM_NAME(VK_FORMAT_ASTC_10x5_UNORM_BLOCK); + ENUM_NAME(VK_FORMAT_ASTC_10x5_SRGB_BLOCK); + ENUM_NAME(VK_FORMAT_ASTC_10x6_UNORM_BLOCK); + ENUM_NAME(VK_FORMAT_ASTC_10x6_SRGB_BLOCK); + ENUM_NAME(VK_FORMAT_ASTC_10x8_UNORM_BLOCK); + ENUM_NAME(VK_FORMAT_ASTC_10x8_SRGB_BLOCK); + ENUM_NAME(VK_FORMAT_ASTC_10x10_UNORM_BLOCK); + ENUM_NAME(VK_FORMAT_ASTC_10x10_SRGB_BLOCK); + ENUM_NAME(VK_FORMAT_ASTC_12x10_UNORM_BLOCK); + ENUM_NAME(VK_FORMAT_ASTC_12x10_SRGB_BLOCK); + ENUM_NAME(VK_FORMAT_ASTC_12x12_UNORM_BLOCK); + ENUM_NAME(VK_FORMAT_ASTC_12x12_SRGB_BLOCK); + ENUM_DEFAULT(e); + } + return os; +} + + +std::ostream& operator << (std::ostream& os, VkImageType e) { + switch (e) { + ENUM_NAME(VK_IMAGE_TYPE_1D); + ENUM_NAME(VK_IMAGE_TYPE_2D); + ENUM_NAME(VK_IMAGE_TYPE_3D); + ENUM_DEFAULT(e); + } + return os; +} + + +std::ostream& operator << (std::ostream& os, VkImageTiling e) { + switch (e) { + ENUM_NAME(VK_IMAGE_TILING_OPTIMAL); + ENUM_NAME(VK_IMAGE_TILING_LINEAR); + ENUM_DEFAULT(e); + } + return os; +} + + +std::ostream& operator << (std::ostream& os, VkImageLayout e) { + switch (e) { + ENUM_NAME(VK_IMAGE_LAYOUT_UNDEFINED); + ENUM_NAME(VK_IMAGE_LAYOUT_GENERAL); + ENUM_NAME(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + ENUM_NAME(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + ENUM_NAME(VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL); + ENUM_NAME(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + ENUM_NAME(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + ENUM_NAME(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + ENUM_NAME(VK_IMAGE_LAYOUT_PREINITIALIZED); + ENUM_NAME(VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); + ENUM_NAME(VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR); + ENUM_DEFAULT(e); + } + return os; +} + + +std::ostream& operator << (std::ostream& os, VkImageViewType e) { + switch (e) { + ENUM_NAME(VK_IMAGE_VIEW_TYPE_1D); + ENUM_NAME(VK_IMAGE_VIEW_TYPE_2D); + ENUM_NAME(VK_IMAGE_VIEW_TYPE_3D); + ENUM_NAME(VK_IMAGE_VIEW_TYPE_CUBE); + ENUM_NAME(VK_IMAGE_VIEW_TYPE_1D_ARRAY); + ENUM_NAME(VK_IMAGE_VIEW_TYPE_2D_ARRAY); + ENUM_NAME(VK_IMAGE_VIEW_TYPE_CUBE_ARRAY); + ENUM_DEFAULT(e); + } + return os; +} + + +std::ostream& operator << (std::ostream& os, VkPresentModeKHR e) { + switch (e) { + ENUM_NAME(VK_PRESENT_MODE_IMMEDIATE_KHR); + ENUM_NAME(VK_PRESENT_MODE_MAILBOX_KHR); + ENUM_NAME(VK_PRESENT_MODE_FIFO_KHR); + ENUM_NAME(VK_PRESENT_MODE_FIFO_RELAXED_KHR); + ENUM_DEFAULT(e); + } + return os; +} + + +std::ostream& operator << (std::ostream& os, VkColorSpaceKHR e) { + switch (e) { + ENUM_NAME(VK_COLOR_SPACE_SRGB_NONLINEAR_KHR); + ENUM_DEFAULT(e); + } + return os; +} + + +std::ostream& operator << (std::ostream& os, VkOffset2D e) { + return os << "(" << e.x << "," << e.y << ")"; +} + + +std::ostream& operator << (std::ostream& os, VkOffset3D e) { + return os << "(" << e.x << "," << e.y << "," << e.z << ")"; +} + + +std::ostream& operator << (std::ostream& os, VkExtent2D e) { + return os << "(" << e.width << "," << e.height << ")"; +} + + +std::ostream& operator << (std::ostream& os, VkExtent3D e) { + return os << "(" << e.width << "," << e.height << "," << e.depth << ")"; +} diff --git a/utils/dxvk-1.10.3/src/vulkan/vulkan_names.h b/utils/dxvk-1.10.3/src/vulkan/vulkan_names.h new file mode 100644 index 00000000000..6752a12c449 --- /dev/null +++ b/utils/dxvk-1.10.3/src/vulkan/vulkan_names.h @@ -0,0 +1,21 @@ +#pragma once + +#include + +#include "../util/util_enum.h" + +#include "vulkan_loader.h" + +std::ostream& operator << (std::ostream& os, VkPipelineCacheHeaderVersion e); +std::ostream& operator << (std::ostream& os, VkResult e); +std::ostream& operator << (std::ostream& os, VkFormat e); +std::ostream& operator << (std::ostream& os, VkImageType e); +std::ostream& operator << (std::ostream& os, VkImageTiling e); +std::ostream& operator << (std::ostream& os, VkImageLayout e); +std::ostream& operator << (std::ostream& os, VkImageViewType e); +std::ostream& operator << (std::ostream& os, VkPresentModeKHR e); +std::ostream& operator << (std::ostream& os, VkColorSpaceKHR e); +std::ostream& operator << (std::ostream& os, VkOffset2D e); +std::ostream& operator << (std::ostream& os, VkOffset3D e); +std::ostream& operator << (std::ostream& os, VkExtent2D e); +std::ostream& operator << (std::ostream& os, VkExtent3D e); diff --git a/utils/dxvk-1.10.3/src/vulkan/vulkan_presenter.cpp b/utils/dxvk-1.10.3/src/vulkan/vulkan_presenter.cpp new file mode 100644 index 00000000000..b02869e3670 --- /dev/null +++ b/utils/dxvk-1.10.3/src/vulkan/vulkan_presenter.cpp @@ -0,0 +1,501 @@ +#include "vulkan_presenter.h" + +#include "../dxvk/dxvk_format.h" + +namespace dxvk::vk { + + Presenter::Presenter( + HWND window, + const Rc& vki, + const Rc& vkd, + PresenterDevice device, + const PresenterDesc& desc) + : m_vki(vki), m_vkd(vkd), m_device(device), m_window(window) { + // As of Wine 5.9, winevulkan provides this extension, but does + // not filter the pNext chain for VkSwapchainCreateInfoKHR properly + // before passing it to the Linux sude, which breaks RenderDoc. + if (m_device.features.fullScreenExclusive && ::GetModuleHandle("winevulkan.dll")) { + Logger::warn("winevulkan detected, disabling exclusive fullscreen support"); + m_device.features.fullScreenExclusive = false; + } + + if (createSurface() != VK_SUCCESS) + throw DxvkError("Failed to create surface"); + + if (recreateSwapChain(desc) != VK_SUCCESS) + throw DxvkError("Failed to create swap chain"); + } + + + Presenter::~Presenter() { + destroySwapchain(); + destroySurface(); + } + + + PresenterInfo Presenter::info() const { + return m_info; + } + + + PresenterImage Presenter::getImage(uint32_t index) const { + return m_images.at(index); + } + + + VkResult Presenter::acquireNextImage(PresenterSync& sync, uint32_t& index) { + sync = m_semaphores.at(m_frameIndex); + + // Don't acquire more than one image at a time + if (m_acquireStatus == VK_NOT_READY) { + m_acquireStatus = m_vkd->vkAcquireNextImageKHR(m_vkd->device(), + m_swapchain, std::numeric_limits::max(), + sync.acquire, VK_NULL_HANDLE, &m_imageIndex); + } + + if (m_acquireStatus != VK_SUCCESS && m_acquireStatus != VK_SUBOPTIMAL_KHR) + return m_acquireStatus; + + index = m_imageIndex; + return m_acquireStatus; + } + + + VkResult Presenter::presentImage() { + PresenterSync sync = m_semaphores.at(m_frameIndex); + + VkPresentInfoKHR info; + info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + info.pNext = nullptr; + info.waitSemaphoreCount = 1; + info.pWaitSemaphores = &sync.present; + info.swapchainCount = 1; + info.pSwapchains = &m_swapchain; + info.pImageIndices = &m_imageIndex; + info.pResults = nullptr; + + VkResult status = m_vkd->vkQueuePresentKHR(m_device.queue, &info); + + if (status != VK_SUCCESS && status != VK_SUBOPTIMAL_KHR) + return status; + + // Try to acquire next image already, in order to hide + // potential delays from the application thread. + m_frameIndex += 1; + m_frameIndex %= m_semaphores.size(); + + sync = m_semaphores.at(m_frameIndex); + + m_acquireStatus = m_vkd->vkAcquireNextImageKHR(m_vkd->device(), + m_swapchain, std::numeric_limits::max(), + sync.acquire, VK_NULL_HANDLE, &m_imageIndex); + + bool vsync = m_info.presentMode == VK_PRESENT_MODE_FIFO_KHR + || m_info.presentMode == VK_PRESENT_MODE_FIFO_RELAXED_KHR; + + m_fpsLimiter.delay(vsync); + return status; + } + + + VkResult Presenter::recreateSwapChain(const PresenterDesc& desc) { + if (m_swapchain) + destroySwapchain(); + + // Query surface capabilities. Some properties might + // have changed, including the size limits and supported + // present modes, so we'll just query everything again. + VkSurfaceCapabilitiesKHR caps; + std::vector formats; + std::vector modes; + + VkResult status; + + if ((status = m_vki->vkGetPhysicalDeviceSurfaceCapabilitiesKHR( + m_device.adapter, m_surface, &caps)) != VK_SUCCESS) { + if (status == VK_ERROR_SURFACE_LOST_KHR) { + // Recreate the surface and try again. + if (m_surface) + destroySurface(); + if ((status = createSurface()) != VK_SUCCESS) + return status; + status = m_vki->vkGetPhysicalDeviceSurfaceCapabilitiesKHR( + m_device.adapter, m_surface, &caps); + } + if (status != VK_SUCCESS) + return status; + } + + if ((status = getSupportedFormats(formats, desc)) != VK_SUCCESS) + return status; + + if ((status = getSupportedPresentModes(modes, desc)) != VK_SUCCESS) + return status; + + // Select actual swap chain properties and create swap chain + m_info.format = pickFormat(formats.size(), formats.data(), desc.numFormats, desc.formats); + m_info.presentMode = pickPresentMode(modes.size(), modes.data(), desc.numPresentModes, desc.presentModes); + m_info.imageExtent = pickImageExtent(caps, desc.imageExtent); + m_info.imageCount = pickImageCount(caps, m_info.presentMode, desc.imageCount); + + if (!m_info.imageExtent.width || !m_info.imageExtent.height) { + m_info.imageCount = 0; + m_info.format = { VK_FORMAT_UNDEFINED, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }; + return VK_SUCCESS; + } + + VkSurfaceFullScreenExclusiveInfoEXT fullScreenInfo; + fullScreenInfo.sType = VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT; + fullScreenInfo.pNext = nullptr; + fullScreenInfo.fullScreenExclusive = desc.fullScreenExclusive; + + VkSwapchainCreateInfoKHR swapInfo; + swapInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; + swapInfo.pNext = nullptr; + swapInfo.flags = 0; + swapInfo.surface = m_surface; + swapInfo.minImageCount = m_info.imageCount; + swapInfo.imageFormat = m_info.format.format; + swapInfo.imageColorSpace = m_info.format.colorSpace; + swapInfo.imageExtent = m_info.imageExtent; + swapInfo.imageArrayLayers = 1; + swapInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + swapInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + swapInfo.queueFamilyIndexCount = 0; + swapInfo.pQueueFamilyIndices = nullptr; + swapInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; + swapInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + swapInfo.presentMode = m_info.presentMode; + swapInfo.clipped = VK_TRUE; + swapInfo.oldSwapchain = VK_NULL_HANDLE; + + if (m_device.features.fullScreenExclusive) + swapInfo.pNext = &fullScreenInfo; + + Logger::info(str::format( + "Presenter: Actual swap chain properties:" + "\n Format: ", m_info.format.format, + "\n Present mode: ", m_info.presentMode, + "\n Buffer size: ", m_info.imageExtent.width, "x", m_info.imageExtent.height, + "\n Image count: ", m_info.imageCount, + "\n Exclusive FS: ", desc.fullScreenExclusive)); + + if ((status = m_vkd->vkCreateSwapchainKHR(m_vkd->device(), + &swapInfo, nullptr, &m_swapchain)) != VK_SUCCESS) + return status; + + // Acquire images and create views + std::vector images; + + if ((status = getSwapImages(images)) != VK_SUCCESS) + return status; + + // Update actual image count + m_info.imageCount = images.size(); + m_images.resize(m_info.imageCount); + + for (uint32_t i = 0; i < m_info.imageCount; i++) { + m_images[i].image = images[i]; + + VkImageViewCreateInfo viewInfo; + viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + viewInfo.pNext = nullptr; + viewInfo.flags = 0; + viewInfo.image = images[i]; + viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; + viewInfo.format = m_info.format.format; + viewInfo.components = VkComponentMapping { + VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, + VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY }; + viewInfo.subresourceRange = { + VK_IMAGE_ASPECT_COLOR_BIT, + 0, 1, 0, 1 }; + + if ((status = m_vkd->vkCreateImageView(m_vkd->device(), + &viewInfo, nullptr, &m_images[i].view)) != VK_SUCCESS) + return status; + } + + // Create one set of semaphores per swap image + m_semaphores.resize(m_info.imageCount); + + for (uint32_t i = 0; i < m_semaphores.size(); i++) { + VkSemaphoreCreateInfo semInfo; + semInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + semInfo.pNext = nullptr; + semInfo.flags = 0; + + if ((status = m_vkd->vkCreateSemaphore(m_vkd->device(), + &semInfo, nullptr, &m_semaphores[i].acquire)) != VK_SUCCESS) + return status; + + if ((status = m_vkd->vkCreateSemaphore(m_vkd->device(), + &semInfo, nullptr, &m_semaphores[i].present)) != VK_SUCCESS) + return status; + } + + // Invalidate indices + m_imageIndex = 0; + m_frameIndex = 0; + m_acquireStatus = VK_NOT_READY; + return VK_SUCCESS; + } + + + void Presenter::setFrameRateLimit(double frameRate) { + m_fpsLimiter.setTargetFrameRate(frameRate); + } + + + void Presenter::setFrameRateLimiterRefreshRate(double refreshRate) { + m_fpsLimiter.setDisplayRefreshRate(refreshRate); + } + + + VkResult Presenter::getSupportedFormats(std::vector& formats, const PresenterDesc& desc) { + uint32_t numFormats = 0; + + VkSurfaceFullScreenExclusiveInfoEXT fullScreenInfo; + fullScreenInfo.sType = VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT; + fullScreenInfo.pNext = nullptr; + fullScreenInfo.fullScreenExclusive = desc.fullScreenExclusive; + + VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo; + surfaceInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR; + surfaceInfo.pNext = &fullScreenInfo; + surfaceInfo.surface = m_surface; + + VkResult status; + + if (m_device.features.fullScreenExclusive) { + status = m_vki->vkGetPhysicalDeviceSurfaceFormats2KHR( + m_device.adapter, &surfaceInfo, &numFormats, nullptr); + } else { + status = m_vki->vkGetPhysicalDeviceSurfaceFormatsKHR( + m_device.adapter, m_surface, &numFormats, nullptr); + } + + if (status != VK_SUCCESS) + return status; + + formats.resize(numFormats); + + if (m_device.features.fullScreenExclusive) { + std::vector tmpFormats(numFormats, + { VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR, nullptr, VkSurfaceFormatKHR() }); + + status = m_vki->vkGetPhysicalDeviceSurfaceFormats2KHR( + m_device.adapter, &surfaceInfo, &numFormats, tmpFormats.data()); + + for (uint32_t i = 0; i < numFormats; i++) + formats[i] = tmpFormats[i].surfaceFormat; + } else { + status = m_vki->vkGetPhysicalDeviceSurfaceFormatsKHR( + m_device.adapter, m_surface, &numFormats, formats.data()); + } + + return status; + } + + + VkResult Presenter::getSupportedPresentModes(std::vector& modes, const PresenterDesc& desc) { + uint32_t numModes = 0; + + VkSurfaceFullScreenExclusiveInfoEXT fullScreenInfo; + fullScreenInfo.sType = VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT; + fullScreenInfo.pNext = nullptr; + fullScreenInfo.fullScreenExclusive = desc.fullScreenExclusive; + + VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo; + surfaceInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR; + surfaceInfo.pNext = &fullScreenInfo; + surfaceInfo.surface = m_surface; + + VkResult status; + + if (m_device.features.fullScreenExclusive) { + status = m_vki->vkGetPhysicalDeviceSurfacePresentModes2EXT( + m_device.adapter, &surfaceInfo, &numModes, nullptr); + } else { + status = m_vki->vkGetPhysicalDeviceSurfacePresentModesKHR( + m_device.adapter, m_surface, &numModes, nullptr); + } + + if (status != VK_SUCCESS) + return status; + + modes.resize(numModes); + + if (m_device.features.fullScreenExclusive) { + status = m_vki->vkGetPhysicalDeviceSurfacePresentModes2EXT( + m_device.adapter, &surfaceInfo, &numModes, modes.data()); + } else { + status = m_vki->vkGetPhysicalDeviceSurfacePresentModesKHR( + m_device.adapter, m_surface, &numModes, modes.data()); + } + + return status; + } + + + VkResult Presenter::getSwapImages(std::vector& images) { + uint32_t imageCount = 0; + + VkResult status = m_vkd->vkGetSwapchainImagesKHR( + m_vkd->device(), m_swapchain, &imageCount, nullptr); + + if (status != VK_SUCCESS) + return status; + + images.resize(imageCount); + + return m_vkd->vkGetSwapchainImagesKHR( + m_vkd->device(), m_swapchain, &imageCount, images.data()); + } + + + VkSurfaceFormatKHR Presenter::pickFormat( + uint32_t numSupported, + const VkSurfaceFormatKHR* pSupported, + uint32_t numDesired, + const VkSurfaceFormatKHR* pDesired) { + if (numDesired > 0) { + // If the implementation allows us to freely choose + // the format, we'll just use the preferred format. + if (numSupported == 1 && pSupported[0].format == VK_FORMAT_UNDEFINED) + return pDesired[0]; + + // If the preferred format is explicitly listed in + // the array of supported surface formats, use it + for (uint32_t i = 0; i < numDesired; i++) { + for (uint32_t j = 0; j < numSupported; j++) { + if (pSupported[j].format == pDesired[i].format + && pSupported[j].colorSpace == pDesired[i].colorSpace) + return pSupported[j]; + } + } + + // If that didn't work, we'll fall back to a format + // which has similar properties to the preferred one + DxvkFormatFlags prefFlags = imageFormatInfo(pDesired[0].format)->flags; + + for (uint32_t j = 0; j < numSupported; j++) { + auto currFlags = imageFormatInfo(pSupported[j].format)->flags; + + if ((currFlags & DxvkFormatFlag::ColorSpaceSrgb) + == (prefFlags & DxvkFormatFlag::ColorSpaceSrgb)) + return pSupported[j]; + } + } + + // Otherwise, fall back to the first supported format + return pSupported[0]; + } + + + VkPresentModeKHR Presenter::pickPresentMode( + uint32_t numSupported, + const VkPresentModeKHR* pSupported, + uint32_t numDesired, + const VkPresentModeKHR* pDesired) { + // Just pick the first desired and supported mode + for (uint32_t i = 0; i < numDesired; i++) { + for (uint32_t j = 0; j < numSupported; j++) { + if (pSupported[j] == pDesired[i]) + return pSupported[j]; + } + } + + // Guaranteed to be available + return VK_PRESENT_MODE_FIFO_KHR; + } + + + VkExtent2D Presenter::pickImageExtent( + const VkSurfaceCapabilitiesKHR& caps, + VkExtent2D desired) { + if (caps.currentExtent.width != std::numeric_limits::max()) + return caps.currentExtent; + + VkExtent2D actual; + actual.width = clamp(desired.width, caps.minImageExtent.width, caps.maxImageExtent.width); + actual.height = clamp(desired.height, caps.minImageExtent.height, caps.maxImageExtent.height); + return actual; + } + + + uint32_t Presenter::pickImageCount( + const VkSurfaceCapabilitiesKHR& caps, + VkPresentModeKHR presentMode, + uint32_t desired) { + uint32_t count = caps.minImageCount; + + if (presentMode != VK_PRESENT_MODE_IMMEDIATE_KHR) + count = caps.minImageCount + 1; + + if (count < desired) + count = desired; + + if (count > caps.maxImageCount && caps.maxImageCount != 0) + count = caps.maxImageCount; + + return count; + } + + + VkResult Presenter::createSurface() { + HINSTANCE instance = reinterpret_cast( + GetWindowLongPtr(m_window, GWLP_HINSTANCE)); + + VkWin32SurfaceCreateInfoKHR info; + info.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; + info.pNext = nullptr; + info.flags = 0; + info.hinstance = instance; + info.hwnd = m_window; + + VkResult status = m_vki->vkCreateWin32SurfaceKHR( + m_vki->instance(), &info, nullptr, &m_surface); + + if (status != VK_SUCCESS) + return status; + + VkBool32 supportStatus = VK_FALSE; + + if ((status = m_vki->vkGetPhysicalDeviceSurfaceSupportKHR(m_device.adapter, + m_device.queueFamily, m_surface, &supportStatus)) != VK_SUCCESS) + return status; + + if (!supportStatus) { + m_vki->vkDestroySurfaceKHR(m_vki->instance(), m_surface, nullptr); + return VK_ERROR_OUT_OF_HOST_MEMORY; // just abuse this + } + + return VK_SUCCESS; + } + + + void Presenter::destroySwapchain() { + for (const auto& img : m_images) + m_vkd->vkDestroyImageView(m_vkd->device(), img.view, nullptr); + + for (const auto& sem : m_semaphores) { + m_vkd->vkDestroySemaphore(m_vkd->device(), sem.acquire, nullptr); + m_vkd->vkDestroySemaphore(m_vkd->device(), sem.present, nullptr); + } + + m_vkd->vkDestroySwapchainKHR(m_vkd->device(), m_swapchain, nullptr); + + m_images.clear(); + m_semaphores.clear(); + + m_swapchain = VK_NULL_HANDLE; + } + + + void Presenter::destroySurface() { + m_vki->vkDestroySurfaceKHR(m_vki->instance(), m_surface, nullptr); + } + +} diff --git a/utils/dxvk-1.10.3/src/vulkan/vulkan_presenter.h b/utils/dxvk-1.10.3/src/vulkan/vulkan_presenter.h new file mode 100644 index 00000000000..40562f6e684 --- /dev/null +++ b/utils/dxvk-1.10.3/src/vulkan/vulkan_presenter.h @@ -0,0 +1,248 @@ +#pragma once + +#include + +#include "../util/log/log.h" + +#include "../util/util_error.h" +#include "../util/util_fps_limiter.h" +#include "../util/util_math.h" +#include "../util/util_string.h" + +#include "vulkan_loader.h" + +namespace dxvk::vk { + + /** + * \brief Presenter description + * + * Contains the desired properties of + * the swap chain. This is passed as + * an input during swap chain creation. + */ + struct PresenterDesc { + VkExtent2D imageExtent; + uint32_t imageCount; + uint32_t numFormats; + VkSurfaceFormatKHR formats[4]; + uint32_t numPresentModes; + VkPresentModeKHR presentModes[4]; + VkFullScreenExclusiveEXT fullScreenExclusive; + }; + + /** + * \brief Presenter properties + * + * Contains the actual properties + * of the underlying swap chain. + */ + struct PresenterInfo { + VkSurfaceFormatKHR format; + VkPresentModeKHR presentMode; + VkExtent2D imageExtent; + uint32_t imageCount; + }; + + /** + * \brief Presenter features + */ + struct PresenterFeatures { + bool fullScreenExclusive : 1; + }; + + /** + * \brief Adapter and queue + */ + struct PresenterDevice { + uint32_t queueFamily = 0; + VkQueue queue = VK_NULL_HANDLE; + VkPhysicalDevice adapter = VK_NULL_HANDLE; + PresenterFeatures features = { }; + }; + + /** + * \brief Swap image and view + */ + struct PresenterImage { + VkImage image = VK_NULL_HANDLE; + VkImageView view = VK_NULL_HANDLE; + }; + + /** + * \brief Presenter semaphores + * + * Pair of semaphores used for acquire and present + * operations, including the command buffers used + * in between. Also stores a fence to signal on + * image acquisition. + */ + struct PresenterSync { + VkSemaphore acquire; + VkSemaphore present; + }; + + /** + * \brief Vulkan presenter + * + * Provides abstractions for some of the + * more complicated aspects of Vulkan's + * window system integration. + */ + class Presenter : public RcObject { + + public: + + Presenter( + HWND window, + const Rc& vki, + const Rc& vkd, + PresenterDevice device, + const PresenterDesc& desc); + + ~Presenter(); + + /** + * \brief Actual presenter info + * \returns Swap chain properties + */ + PresenterInfo info() const; + + /** + * \brief Retrieves image by index + * + * Can be used to create per-image objects. + * \param [in] index Image index + * \returns Image handle + */ + PresenterImage getImage( + uint32_t index) const; + + /** + * \brief Acquires next image + * + * Potentially blocks the calling thread. + * If this returns an error, the swap chain + * must be recreated and a new image must + * be acquired before proceeding. + * \param [out] sync Synchronization semaphores + * \param [out] index Acquired image index + * \returns Status of the operation + */ + VkResult acquireNextImage( + PresenterSync& sync, + uint32_t& index); + + /** + * \brief Presents current image + * + * Presents the current image. If this returns + * an error, the swap chain must be recreated, + * but do not present before acquiring an image. + * \returns Status of the operation + */ + VkResult presentImage(); + + /** + * \brief Changes presenter properties + * + * Recreates the swap chain immediately. Note that + * no swap chain resources must be in use by the + * GPU at the time this is called. + * \param [in] desc Swap chain description + */ + VkResult recreateSwapChain( + const PresenterDesc& desc); + + /** + * \brief Changes maximum frame rate + * + * \param [in] frameRate Target frame rate. Set + * to 0 in order to disable the limiter. + */ + void setFrameRateLimit(double frameRate); + + /** + * \brief Notifies frame rate limiter about the display refresh rate + * + * Used to dynamically disable the frame rate limiter in case + * vertical synchronization is used and the target frame rate + * roughly equals the display's refresh rate. + * \param [in] refresnRate Current refresh rate + */ + void setFrameRateLimiterRefreshRate(double refreshRate); + + /** + * \brief Checks whether a Vulkan swap chain exists + * + * On Windows, there are situations where we cannot create + * a swap chain as the surface size can reach zero, and no + * presentation can be performed. + * \returns \c true if the presenter has a swap chain. + */ + bool hasSwapChain() const { + return m_swapchain; + } + + private: + + Rc m_vki; + Rc m_vkd; + + PresenterDevice m_device; + PresenterInfo m_info; + + HWND m_window = nullptr; + VkSurfaceKHR m_surface = VK_NULL_HANDLE; + VkSwapchainKHR m_swapchain = VK_NULL_HANDLE; + + std::vector m_images; + std::vector m_semaphores; + + uint32_t m_imageIndex = 0; + uint32_t m_frameIndex = 0; + + VkResult m_acquireStatus = VK_NOT_READY; + + FpsLimiter m_fpsLimiter; + + VkResult getSupportedFormats( + std::vector& formats, + const PresenterDesc& desc); + + VkResult getSupportedPresentModes( + std::vector& modes, + const PresenterDesc& desc); + + VkResult getSwapImages( + std::vector& images); + + VkSurfaceFormatKHR pickFormat( + uint32_t numSupported, + const VkSurfaceFormatKHR* pSupported, + uint32_t numDesired, + const VkSurfaceFormatKHR* pDesired); + + VkPresentModeKHR pickPresentMode( + uint32_t numSupported, + const VkPresentModeKHR* pSupported, + uint32_t numDesired, + const VkPresentModeKHR* pDesired); + + VkExtent2D pickImageExtent( + const VkSurfaceCapabilitiesKHR& caps, + VkExtent2D desired); + + uint32_t pickImageCount( + const VkSurfaceCapabilitiesKHR& caps, + VkPresentModeKHR presentMode, + uint32_t desired); + + VkResult createSurface(); + + void destroySwapchain(); + + void destroySurface(); + + }; + +} diff --git a/utils/dxvk-1.10.3/src/vulkan/vulkan_util.h b/utils/dxvk-1.10.3/src/vulkan/vulkan_util.h new file mode 100644 index 00000000000..38e0217cc6a --- /dev/null +++ b/utils/dxvk-1.10.3/src/vulkan/vulkan_util.h @@ -0,0 +1,247 @@ +#pragma once + +#include + +#include "vulkan_loader.h" + +namespace dxvk::vk { + + inline VkImageSubresourceRange makeSubresourceRange( + const VkImageSubresourceLayers& layers) { + VkImageSubresourceRange range; + range.aspectMask = layers.aspectMask; + range.baseMipLevel = layers.mipLevel; + range.levelCount = 1; + range.baseArrayLayer = layers.baseArrayLayer; + range.layerCount = layers.layerCount; + return range; + } + + inline VkImageSubresourceRange makeSubresourceRange( + const VkImageSubresource& subres) { + VkImageSubresourceRange range; + range.aspectMask = subres.aspectMask; + range.baseMipLevel = subres.mipLevel; + range.levelCount = 1; + range.baseArrayLayer = subres.arrayLayer; + range.layerCount = 1; + return range; + } + + inline VkImageSubresourceLayers makeSubresourceLayers( + const VkImageSubresource& subres) { + VkImageSubresourceLayers layers; + layers.aspectMask = subres.aspectMask; + layers.mipLevel = subres.mipLevel; + layers.baseArrayLayer = subres.arrayLayer; + layers.layerCount = 1; + return layers; + } + + inline VkImageSubresourceLayers pickSubresourceLayers( + const VkImageSubresourceRange& range, + uint32_t level) { + VkImageSubresourceLayers layers; + layers.aspectMask = range.aspectMask; + layers.mipLevel = range.baseMipLevel + level; + layers.baseArrayLayer = range.baseArrayLayer; + layers.layerCount = range.layerCount; + return layers; + } + + inline VkImageSubresource pickSubresource( + const VkImageSubresourceLayers& range, + uint32_t layer) { + VkImageSubresource subres; + subres.aspectMask = range.aspectMask; + subres.mipLevel = range.mipLevel; + subres.arrayLayer = range.baseArrayLayer + layer; + return subres; + } + + inline VkImageSubresource pickSubresource( + const VkImageSubresourceRange& range, + uint32_t level, + uint32_t layer) { + VkImageSubresource subres; + subres.aspectMask = range.aspectMask; + subres.mipLevel = range.baseMipLevel + level; + subres.arrayLayer = range.baseArrayLayer + layer; + return subres; + } + + inline bool checkSubresourceRangeOverlap( + const VkImageSubresourceRange& a, + const VkImageSubresourceRange& b) { + return a.baseMipLevel < b.baseMipLevel + b.levelCount + && a.baseMipLevel + a.levelCount > b.baseMipLevel + && a.baseArrayLayer < b.baseArrayLayer + b.layerCount + && a.baseArrayLayer + a.layerCount > b.baseArrayLayer; + } + + inline bool checkSubresourceRangeSuperset( + const VkImageSubresourceRange& a, + const VkImageSubresourceRange& b) { + return a.baseMipLevel <= b.baseMipLevel + && a.baseMipLevel + a.levelCount >= b.baseMipLevel + b.levelCount + && a.baseArrayLayer <= b.baseArrayLayer + && a.baseArrayLayer + a.layerCount >= b.baseArrayLayer + b.layerCount; + } + + inline VkImageAspectFlags getWritableAspectsForLayout(VkImageLayout layout) { + switch (layout) { + case VK_IMAGE_LAYOUT_GENERAL: + return VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; + case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: + return VK_IMAGE_ASPECT_COLOR_BIT; + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: + return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; + case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL: + return VK_IMAGE_ASPECT_DEPTH_BIT; + case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL: + return VK_IMAGE_ASPECT_STENCIL_BIT; + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: + case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: + return 0; + default: + Logger::err(str::format("Unhandled image layout ", layout)); + return 0; + } + } + + inline uint32_t getPlaneCount(VkImageAspectFlags aspects) { + // Use a 16-bit integer as a lookup table. This works because + // plane aspects use consecutive bits in the image aspect enum. + const uint32_t shift = (aspects / VK_IMAGE_ASPECT_PLANE_0_BIT) * 2; + const uint32_t counts = 0xffa5; + return (counts >> shift) & 0x3; + } + + inline uint32_t getPlaneIndex(VkImageAspectFlags aspect) { + // Works for up to PLANE_2_BIT due to enum poperties + return aspect / VK_IMAGE_ASPECT_PLANE_1_BIT; + } + + inline VkImageAspectFlagBits getPlaneAspect(uint32_t plane) { + return VkImageAspectFlagBits(VK_IMAGE_ASPECT_PLANE_0_BIT << plane); + } + + inline VkImageAspectFlags getNextAspect(VkImageAspectFlags& mask) { + if (likely(mask & (VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))) { + // Depth-stencil isn't considered multi-planar + return std::exchange(mask, VkImageAspectFlags(0)); + } else { + VkImageAspectFlags result = mask & -mask; + mask &= ~result; + return result; + } + } + + template + struct ChainStruct { + VkStructureType sType; + T* pNext; + }; + + template + void removeStructFromPNextChain(T** ppNext, VkStructureType sType) { + while (*ppNext) { + auto pStruct = reinterpret_cast*>(*ppNext); + + if (pStruct->sType == sType) { + *ppNext = pStruct->pNext; + return; + } + + ppNext = &pStruct->pNext; + } + } + +} + + +inline bool operator == ( + const VkImageSubresourceRange& a, + const VkImageSubresourceRange& b) { + return a.aspectMask == b.aspectMask + && a.baseMipLevel == b.baseMipLevel + && a.levelCount == b.levelCount + && a.baseArrayLayer == b.baseArrayLayer + && a.layerCount == b.layerCount; +} + + +inline bool operator != ( + const VkImageSubresourceRange& a, + const VkImageSubresourceRange& b) { + return !operator == (a, b); +} + + +inline bool operator == ( + const VkImageSubresourceLayers& a, + const VkImageSubresourceLayers& b) { + return a.aspectMask == b.aspectMask + && a.mipLevel == b.mipLevel + && a.baseArrayLayer == b.baseArrayLayer + && a.layerCount == b.layerCount; +} + + +inline bool operator != ( + const VkImageSubresourceLayers& a, + const VkImageSubresourceLayers& b) { + return !operator == (a, b); +} + + +inline bool operator == (VkExtent3D a, VkExtent3D b) { + return a.width == b.width + && a.height == b.height + && a.depth == b.depth; +} + + +inline bool operator != (VkExtent3D a, VkExtent3D b) { + return a.width != b.width + || a.height != b.height + || a.depth != b.depth; +} + + +inline bool operator == (VkExtent2D a, VkExtent2D b) { + return a.width == b.width + && a.height == b.height; +} + + +inline bool operator != (VkExtent2D a, VkExtent2D b) { + return a.width != b.width + || a.height != b.height; +} + + +inline bool operator == (VkOffset3D a, VkOffset3D b) { + return a.x == b.x + && a.y == b.y + && a.z == b.z; +} + + +inline bool operator != (VkOffset3D a, VkOffset3D b) { + return a.x != b.x + || a.y != b.y + || a.z != b.z; +} + + +inline bool operator == (VkOffset2D a, VkOffset2D b) { + return a.x == b.x + && a.y == b.y; +} + + +inline bool operator != (VkOffset2D a, VkOffset2D b) { + return a.x != b.x + || a.y != b.y; +} diff --git a/utils/dxvk-1.10.3/tests/d3d11/meson.build b/utils/dxvk-1.10.3/tests/d3d11/meson.build new file mode 100644 index 00000000000..31eba4ee39e --- /dev/null +++ b/utils/dxvk-1.10.3/tests/d3d11/meson.build @@ -0,0 +1,10 @@ +test_d3d11_deps = [ util_dep, lib_dxgi, lib_d3d11, lib_d3dcompiler_47 ] + +executable('d3d11-compute'+exe_ext, files('test_d3d11_compute.cpp'), dependencies : test_d3d11_deps, install : true, gui_app : true) +executable('d3d11-formats'+exe_ext, files('test_d3d11_formats.cpp'), dependencies : test_d3d11_deps, install : true, gui_app : true) +executable('d3d11-map-read'+exe_ext, files('test_d3d11_map_read.cpp'), dependencies : test_d3d11_deps, install : true, gui_app : true) +executable('d3d11-streamout'+exe_ext, files('test_d3d11_streamout.cpp'), dependencies : test_d3d11_deps, install : true, gui_app : true) +executable('d3d11-triangle'+exe_ext, files('test_d3d11_triangle.cpp'), dependencies : test_d3d11_deps, install : true, gui_app : true) +executable('d3d11-video'+exe_ext, files('test_d3d11_video.cpp'), dependencies : test_d3d11_deps, install : true, gui_app : true) + +install_data('video_image.raw', install_dir : get_option('bindir')) \ No newline at end of file diff --git a/utils/dxvk-1.10.3/tests/d3d11/test_d3d11_compute.cpp b/utils/dxvk-1.10.3/tests/d3d11/test_d3d11_compute.cpp new file mode 100644 index 00000000000..8782658192c --- /dev/null +++ b/utils/dxvk-1.10.3/tests/d3d11/test_d3d11_compute.cpp @@ -0,0 +1,172 @@ +#include + +#include +#include + +#include +#include + +#include "../test_utils.h" + +using namespace dxvk; + +const std::string g_computeShaderCode = + "StructuredBuffer buf_in : register(t0);\n" + "RWStructuredBuffer buf_out : register(u0);\n" + "groupshared uint tmp[64];\n" + "[numthreads(64,1,1)]\n" + "void main(uint localId : SV_GroupIndex, uint3 globalId : SV_DispatchThreadID) {\n" + " tmp[localId] = buf_in[2 * globalId.x + 0]\n" + " + buf_in[2 * globalId.x + 1];\n" + " GroupMemoryBarrierWithGroupSync();\n" + " uint activeGroups = 32;\n" + " while (activeGroups != 0) {\n" + " if (localId < activeGroups)\n" + " tmp[localId] += tmp[localId + activeGroups];\n" + " GroupMemoryBarrierWithGroupSync();\n" + " activeGroups >>= 1;\n" + " }\n" + " if (localId == 0)\n" + " buf_out[0] = tmp[0];\n" + "}\n"; + +int WINAPI WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) { + Com device; + Com context; + Com computeShader; + + Com srcBuffer; + Com dstBuffer; + Com readBuffer; + + Com srcView; + Com dstView; + + if (FAILED(D3D11CreateDevice( + nullptr, D3D_DRIVER_TYPE_HARDWARE, + nullptr, 0, nullptr, 0, D3D11_SDK_VERSION, + &device, nullptr, &context))) { + std::cerr << "Failed to create D3D11 device" << std::endl; + return 1; + } + + Com computeShaderBlob; + + if (FAILED(D3DCompile( + g_computeShaderCode.data(), + g_computeShaderCode.size(), + "Compute shader", + nullptr, nullptr, + "main", "cs_5_0", 0, 0, + &computeShaderBlob, + nullptr))) { + std::cerr << "Failed to compile compute shader" << std::endl; + return 1; + } + + if (FAILED(device->CreateComputeShader( + computeShaderBlob->GetBufferPointer(), + computeShaderBlob->GetBufferSize(), + nullptr, &computeShader))) { + std::cerr << "Failed to create compute shader" << std::endl; + return 1; + } + + std::array srcData; + for (uint32_t i = 0; i < srcData.size(); i++) + srcData[i] = i + 1; + + D3D11_BUFFER_DESC srcBufferDesc; + srcBufferDesc.ByteWidth = sizeof(uint32_t) * srcData.size(); + srcBufferDesc.Usage = D3D11_USAGE_IMMUTABLE; + srcBufferDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + srcBufferDesc.CPUAccessFlags = 0; + srcBufferDesc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; + srcBufferDesc.StructureByteStride = sizeof(uint32_t); + + D3D11_SUBRESOURCE_DATA srcDataInfo; + srcDataInfo.pSysMem = srcData.data(); + srcDataInfo.SysMemPitch = 0; + srcDataInfo.SysMemSlicePitch = 0; + + if (FAILED(device->CreateBuffer(&srcBufferDesc, &srcDataInfo, &srcBuffer))) { + std::cerr << "Failed to create source buffer" << std::endl; + return 1; + } + + D3D11_BUFFER_DESC dstBufferDesc; + dstBufferDesc.ByteWidth = sizeof(uint32_t); + dstBufferDesc.Usage = D3D11_USAGE_DEFAULT; + dstBufferDesc.BindFlags = D3D11_BIND_UNORDERED_ACCESS; + dstBufferDesc.CPUAccessFlags = 0; + dstBufferDesc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; + dstBufferDesc.StructureByteStride = sizeof(uint32_t); + + if (FAILED(device->CreateBuffer(&dstBufferDesc, &srcDataInfo, &dstBuffer))) { + std::cerr << "Failed to create destination buffer" << std::endl; + return 1; + } + + D3D11_BUFFER_DESC readBufferDesc; + readBufferDesc.ByteWidth = sizeof(uint32_t); + readBufferDesc.Usage = D3D11_USAGE_STAGING; + readBufferDesc.BindFlags = 0; + readBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + readBufferDesc.MiscFlags = 0; + readBufferDesc.StructureByteStride = 0; + + if (FAILED(device->CreateBuffer(&readBufferDesc, nullptr, &readBuffer))) { + std::cerr << "Failed to create readback buffer" << std::endl; + return 1; + } + + D3D11_SHADER_RESOURCE_VIEW_DESC srcViewDesc; + srcViewDesc.Format = DXGI_FORMAT_UNKNOWN; + srcViewDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX; + srcViewDesc.BufferEx.FirstElement = 0; + srcViewDesc.BufferEx.NumElements = srcData.size(); + srcViewDesc.BufferEx.Flags = 0; + + if (FAILED(device->CreateShaderResourceView(srcBuffer.ptr(), &srcViewDesc, &srcView))) { + std::cerr << "Failed to create shader resource view" << std::endl; + return 1; + } + + D3D11_UNORDERED_ACCESS_VIEW_DESC dstViewDesc; + dstViewDesc.Format = DXGI_FORMAT_UNKNOWN; + dstViewDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; + dstViewDesc.Buffer.FirstElement = 0; + dstViewDesc.Buffer.NumElements = 1; + dstViewDesc.Buffer.Flags = 0; + + if (FAILED(device->CreateUnorderedAccessView(dstBuffer.ptr(), &dstViewDesc, &dstView))) { + std::cerr << "Failed to create unordered access view" << std::endl; + return 1; + } + + // Compute sum of the source buffer values + context->CSSetShader(computeShader.ptr(), nullptr, 0); + context->CSSetShaderResources(0, 1, &srcView); + context->CSSetUnorderedAccessViews(0, 1, &dstView, nullptr); + context->Dispatch(1, 1, 1); + + // Write data to the readback buffer and query the result + context->CopyResource(readBuffer.ptr(), dstBuffer.ptr()); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + if (FAILED(context->Map(readBuffer.ptr(), 0, D3D11_MAP_READ, 0, &mappedResource))) { + std::cerr << "Failed to map readback buffer" << std::endl; + return 1; + } + + uint32_t result = 0; + std::memcpy(&result, mappedResource.pData, sizeof(result)); + context->Unmap(readBuffer.ptr(), 0); + + std::cout << "Sum of the numbers 1 to " << srcData.size() << " = " << result << std::endl; + context->ClearState(); + return 0; +} diff --git a/utils/dxvk-1.10.3/tests/d3d11/test_d3d11_formats.cpp b/utils/dxvk-1.10.3/tests/d3d11/test_d3d11_formats.cpp new file mode 100644 index 00000000000..daac8365dda --- /dev/null +++ b/utils/dxvk-1.10.3/tests/d3d11/test_d3d11_formats.cpp @@ -0,0 +1,273 @@ +#include + +#include +#include + +#include +#include + +#include "../test_utils.h" + +#undef ENUM_NAME +#define ENUM_NAME(e) case e: return #e; + +using namespace dxvk; + +std::string GetFormatName(DXGI_FORMAT Format) { + switch (Format) { + ENUM_NAME(DXGI_FORMAT_UNKNOWN); + ENUM_NAME(DXGI_FORMAT_R32G32B32A32_TYPELESS); + ENUM_NAME(DXGI_FORMAT_R32G32B32A32_FLOAT); + ENUM_NAME(DXGI_FORMAT_R32G32B32A32_UINT); + ENUM_NAME(DXGI_FORMAT_R32G32B32A32_SINT); + ENUM_NAME(DXGI_FORMAT_R32G32B32_TYPELESS); + ENUM_NAME(DXGI_FORMAT_R32G32B32_FLOAT); + ENUM_NAME(DXGI_FORMAT_R32G32B32_UINT); + ENUM_NAME(DXGI_FORMAT_R32G32B32_SINT); + ENUM_NAME(DXGI_FORMAT_R16G16B16A16_TYPELESS); + ENUM_NAME(DXGI_FORMAT_R16G16B16A16_FLOAT); + ENUM_NAME(DXGI_FORMAT_R16G16B16A16_UNORM); + ENUM_NAME(DXGI_FORMAT_R16G16B16A16_UINT); + ENUM_NAME(DXGI_FORMAT_R16G16B16A16_SNORM); + ENUM_NAME(DXGI_FORMAT_R16G16B16A16_SINT); + ENUM_NAME(DXGI_FORMAT_R32G32_TYPELESS); + ENUM_NAME(DXGI_FORMAT_R32G32_FLOAT); + ENUM_NAME(DXGI_FORMAT_R32G32_UINT); + ENUM_NAME(DXGI_FORMAT_R32G32_SINT); + ENUM_NAME(DXGI_FORMAT_R32G8X24_TYPELESS); + ENUM_NAME(DXGI_FORMAT_D32_FLOAT_S8X24_UINT); + ENUM_NAME(DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS); + ENUM_NAME(DXGI_FORMAT_X32_TYPELESS_G8X24_UINT); + ENUM_NAME(DXGI_FORMAT_R10G10B10A2_TYPELESS); + ENUM_NAME(DXGI_FORMAT_R10G10B10A2_UNORM); + ENUM_NAME(DXGI_FORMAT_R10G10B10A2_UINT); + ENUM_NAME(DXGI_FORMAT_R11G11B10_FLOAT); + ENUM_NAME(DXGI_FORMAT_R8G8B8A8_TYPELESS); + ENUM_NAME(DXGI_FORMAT_R8G8B8A8_UNORM); + ENUM_NAME(DXGI_FORMAT_R8G8B8A8_UNORM_SRGB); + ENUM_NAME(DXGI_FORMAT_R8G8B8A8_UINT); + ENUM_NAME(DXGI_FORMAT_R8G8B8A8_SNORM); + ENUM_NAME(DXGI_FORMAT_R8G8B8A8_SINT); + ENUM_NAME(DXGI_FORMAT_R16G16_TYPELESS); + ENUM_NAME(DXGI_FORMAT_R16G16_FLOAT); + ENUM_NAME(DXGI_FORMAT_R16G16_UNORM); + ENUM_NAME(DXGI_FORMAT_R16G16_UINT); + ENUM_NAME(DXGI_FORMAT_R16G16_SNORM); + ENUM_NAME(DXGI_FORMAT_R16G16_SINT); + ENUM_NAME(DXGI_FORMAT_R32_TYPELESS); + ENUM_NAME(DXGI_FORMAT_D32_FLOAT); + ENUM_NAME(DXGI_FORMAT_R32_FLOAT); + ENUM_NAME(DXGI_FORMAT_R32_UINT); + ENUM_NAME(DXGI_FORMAT_R32_SINT); + ENUM_NAME(DXGI_FORMAT_R24G8_TYPELESS); + ENUM_NAME(DXGI_FORMAT_D24_UNORM_S8_UINT); + ENUM_NAME(DXGI_FORMAT_R24_UNORM_X8_TYPELESS); + ENUM_NAME(DXGI_FORMAT_X24_TYPELESS_G8_UINT); + ENUM_NAME(DXGI_FORMAT_R8G8_TYPELESS); + ENUM_NAME(DXGI_FORMAT_R8G8_UNORM); + ENUM_NAME(DXGI_FORMAT_R8G8_UINT); + ENUM_NAME(DXGI_FORMAT_R8G8_SNORM); + ENUM_NAME(DXGI_FORMAT_R8G8_SINT); + ENUM_NAME(DXGI_FORMAT_R16_TYPELESS); + ENUM_NAME(DXGI_FORMAT_R16_FLOAT); + ENUM_NAME(DXGI_FORMAT_D16_UNORM); + ENUM_NAME(DXGI_FORMAT_R16_UNORM); + ENUM_NAME(DXGI_FORMAT_R16_UINT); + ENUM_NAME(DXGI_FORMAT_R16_SNORM); + ENUM_NAME(DXGI_FORMAT_R16_SINT); + ENUM_NAME(DXGI_FORMAT_R8_TYPELESS); + ENUM_NAME(DXGI_FORMAT_R8_UNORM); + ENUM_NAME(DXGI_FORMAT_R8_UINT); + ENUM_NAME(DXGI_FORMAT_R8_SNORM); + ENUM_NAME(DXGI_FORMAT_R8_SINT); + ENUM_NAME(DXGI_FORMAT_A8_UNORM); + ENUM_NAME(DXGI_FORMAT_R1_UNORM); + ENUM_NAME(DXGI_FORMAT_R9G9B9E5_SHAREDEXP); + ENUM_NAME(DXGI_FORMAT_R8G8_B8G8_UNORM); + ENUM_NAME(DXGI_FORMAT_G8R8_G8B8_UNORM); + ENUM_NAME(DXGI_FORMAT_BC1_TYPELESS); + ENUM_NAME(DXGI_FORMAT_BC1_UNORM); + ENUM_NAME(DXGI_FORMAT_BC1_UNORM_SRGB); + ENUM_NAME(DXGI_FORMAT_BC2_TYPELESS); + ENUM_NAME(DXGI_FORMAT_BC2_UNORM); + ENUM_NAME(DXGI_FORMAT_BC2_UNORM_SRGB); + ENUM_NAME(DXGI_FORMAT_BC3_TYPELESS); + ENUM_NAME(DXGI_FORMAT_BC3_UNORM); + ENUM_NAME(DXGI_FORMAT_BC3_UNORM_SRGB); + ENUM_NAME(DXGI_FORMAT_BC4_TYPELESS); + ENUM_NAME(DXGI_FORMAT_BC4_UNORM); + ENUM_NAME(DXGI_FORMAT_BC4_SNORM); + ENUM_NAME(DXGI_FORMAT_BC5_TYPELESS); + ENUM_NAME(DXGI_FORMAT_BC5_UNORM); + ENUM_NAME(DXGI_FORMAT_BC5_SNORM); + ENUM_NAME(DXGI_FORMAT_B5G6R5_UNORM); + ENUM_NAME(DXGI_FORMAT_B5G5R5A1_UNORM); + ENUM_NAME(DXGI_FORMAT_B8G8R8A8_UNORM); + ENUM_NAME(DXGI_FORMAT_B8G8R8X8_UNORM); + ENUM_NAME(DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM); + ENUM_NAME(DXGI_FORMAT_B8G8R8A8_TYPELESS); + ENUM_NAME(DXGI_FORMAT_B8G8R8A8_UNORM_SRGB); + ENUM_NAME(DXGI_FORMAT_B8G8R8X8_TYPELESS); + ENUM_NAME(DXGI_FORMAT_B8G8R8X8_UNORM_SRGB); + ENUM_NAME(DXGI_FORMAT_BC6H_TYPELESS); + ENUM_NAME(DXGI_FORMAT_BC6H_UF16); + ENUM_NAME(DXGI_FORMAT_BC6H_SF16); + ENUM_NAME(DXGI_FORMAT_BC7_TYPELESS); + ENUM_NAME(DXGI_FORMAT_BC7_UNORM); + ENUM_NAME(DXGI_FORMAT_BC7_UNORM_SRGB); + default: return std::to_string(Format); + } +} + + +std::string GetFormatFlagName(D3D11_FORMAT_SUPPORT Flag) { + switch (Flag) { + ENUM_NAME(D3D11_FORMAT_SUPPORT_BUFFER); + ENUM_NAME(D3D11_FORMAT_SUPPORT_IA_VERTEX_BUFFER); + ENUM_NAME(D3D11_FORMAT_SUPPORT_IA_INDEX_BUFFER); + ENUM_NAME(D3D11_FORMAT_SUPPORT_SO_BUFFER); + ENUM_NAME(D3D11_FORMAT_SUPPORT_TEXTURE1D); + ENUM_NAME(D3D11_FORMAT_SUPPORT_TEXTURE2D); + ENUM_NAME(D3D11_FORMAT_SUPPORT_TEXTURE3D); + ENUM_NAME(D3D11_FORMAT_SUPPORT_TEXTURECUBE); + ENUM_NAME(D3D11_FORMAT_SUPPORT_SHADER_LOAD); + ENUM_NAME(D3D11_FORMAT_SUPPORT_SHADER_SAMPLE); + ENUM_NAME(D3D11_FORMAT_SUPPORT_SHADER_SAMPLE_COMPARISON); + ENUM_NAME(D3D11_FORMAT_SUPPORT_SHADER_SAMPLE_MONO_TEXT); + ENUM_NAME(D3D11_FORMAT_SUPPORT_MIP); + ENUM_NAME(D3D11_FORMAT_SUPPORT_MIP_AUTOGEN); + ENUM_NAME(D3D11_FORMAT_SUPPORT_RENDER_TARGET); + ENUM_NAME(D3D11_FORMAT_SUPPORT_BLENDABLE); + ENUM_NAME(D3D11_FORMAT_SUPPORT_DEPTH_STENCIL); + ENUM_NAME(D3D11_FORMAT_SUPPORT_CPU_LOCKABLE); + ENUM_NAME(D3D11_FORMAT_SUPPORT_MULTISAMPLE_RESOLVE); + ENUM_NAME(D3D11_FORMAT_SUPPORT_DISPLAY); + ENUM_NAME(D3D11_FORMAT_SUPPORT_CAST_WITHIN_BIT_LAYOUT); + ENUM_NAME(D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET); + ENUM_NAME(D3D11_FORMAT_SUPPORT_MULTISAMPLE_LOAD); + ENUM_NAME(D3D11_FORMAT_SUPPORT_SHADER_GATHER); + ENUM_NAME(D3D11_FORMAT_SUPPORT_BACK_BUFFER_CAST); + ENUM_NAME(D3D11_FORMAT_SUPPORT_TYPED_UNORDERED_ACCESS_VIEW); + ENUM_NAME(D3D11_FORMAT_SUPPORT_SHADER_GATHER_COMPARISON); + ENUM_NAME(D3D11_FORMAT_SUPPORT_DECODER_OUTPUT); + ENUM_NAME(D3D11_FORMAT_SUPPORT_VIDEO_PROCESSOR_OUTPUT); + ENUM_NAME(D3D11_FORMAT_SUPPORT_VIDEO_PROCESSOR_INPUT); + ENUM_NAME(D3D11_FORMAT_SUPPORT_VIDEO_ENCODER); + default: return std::to_string(Flag); + } +} + + +int WINAPI WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) { + Com device; + + if (FAILED(D3D11CreateDevice( + nullptr, D3D_DRIVER_TYPE_HARDWARE, + nullptr, 0, nullptr, 0, D3D11_SDK_VERSION, + &device, nullptr, nullptr))) { + std::cerr << "Failed to create D3D11 device" << std::endl; + return 1; + } + + D3D11_FEATURE_DATA_THREADING featureThreading = { }; + D3D11_FEATURE_DATA_DOUBLES featureDoubles = { }; + D3D11_FEATURE_DATA_SHADER_MIN_PRECISION_SUPPORT featureMinPrecision = { }; + D3D11_FEATURE_DATA_D3D11_OPTIONS featureD3D11Options = { }; + D3D11_FEATURE_DATA_D3D11_OPTIONS1 featureD3D11Options1 = { }; + D3D11_FEATURE_DATA_D3D11_OPTIONS2 featureD3D11Options2 = { }; + D3D11_FEATURE_DATA_D3D11_OPTIONS3 featureD3D11Options3 = { }; + D3D11_FEATURE_DATA_D3D11_OPTIONS4 featureD3D11Options4 = { }; + + if (SUCCEEDED(device->CheckFeatureSupport(D3D11_FEATURE_THREADING, &featureThreading, sizeof(featureThreading)))) { + std::cout << "D3D11_FEATURE_THREADING:" << std::endl + << " DriverConcurrentCreates: " << featureThreading.DriverConcurrentCreates << std::endl + << " DriverCommandLists: " << featureThreading.DriverCommandLists << std::endl; + } + + if (SUCCEEDED(device->CheckFeatureSupport(D3D11_FEATURE_DOUBLES, &featureDoubles, sizeof(featureDoubles)))) { + std::cout << "D3D11_FEATURE_DOUBLES:" << std::endl + << " DoublePrecisionFloatShaderOps: " << featureDoubles.DoublePrecisionFloatShaderOps << std::endl; + } + + if (SUCCEEDED(device->CheckFeatureSupport(D3D11_FEATURE_SHADER_MIN_PRECISION_SUPPORT, &featureMinPrecision, sizeof(featureMinPrecision)))) { + std::cout << "D3D11_FEATURE_SHADER_MIN_PRECISION_SUPPORT:" << std::endl + << " PixelShaderMinPrecision: " << featureMinPrecision.PixelShaderMinPrecision << std::endl + << " AllOtherShaderStagesMinPrecision: " << featureMinPrecision.AllOtherShaderStagesMinPrecision << std::endl; + } + + if (SUCCEEDED(device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &featureD3D11Options, sizeof(featureD3D11Options)))) { + std::cout << "D3D11_FEATURE_D3D11_OPTIONS:" << std::endl + << " OutputMergerLogicOp: " << featureD3D11Options.OutputMergerLogicOp << std::endl + << " UAVOnlyRenderingForcedSampleCount: " << featureD3D11Options.UAVOnlyRenderingForcedSampleCount << std::endl + << " DiscardAPIsSeenByDriver: " << featureD3D11Options.DiscardAPIsSeenByDriver << std::endl + << " FlagsForUpdateAndCopySeenByDriver: " << featureD3D11Options.FlagsForUpdateAndCopySeenByDriver << std::endl + << " ClearView: " << featureD3D11Options.ClearView << std::endl + << " CopyWithOverlap: " << featureD3D11Options.CopyWithOverlap << std::endl + << " ConstantBufferPartialUpdate: " << featureD3D11Options.ConstantBufferPartialUpdate << std::endl + << " ConstantBufferOffsetting: " << featureD3D11Options.ConstantBufferOffsetting << std::endl + << " MapNoOverwriteOnDynamicConstantBuffer: " << featureD3D11Options.MapNoOverwriteOnDynamicConstantBuffer << std::endl + << " MapNoOverwriteOnDynamicBufferSRV: " << featureD3D11Options.MapNoOverwriteOnDynamicBufferSRV << std::endl + << " MultisampleRTVWithForcedSampleCountOne: " << featureD3D11Options.MultisampleRTVWithForcedSampleCountOne << std::endl + << " SAD4ShaderInstructions: " << featureD3D11Options.SAD4ShaderInstructions << std::endl + << " ExtendedDoublesShaderInstructions: " << featureD3D11Options.ExtendedDoublesShaderInstructions << std::endl + << " ExtendedResourceSharing: " << featureD3D11Options.ExtendedResourceSharing << std::endl; + } + + if (SUCCEEDED(device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS1, &featureD3D11Options1, sizeof(featureD3D11Options1)))) { + std::cout << "D3D11_FEATURE_D3D11_OPTIONS1:" << std::endl + << " TiledResourcesTier: " << featureD3D11Options1.TiledResourcesTier << std::endl + << " MinMaxFiltering: " << featureD3D11Options1.MinMaxFiltering << std::endl + << " ClearViewAlsoSupportsDepthOnlyFormats: " << featureD3D11Options1.ClearViewAlsoSupportsDepthOnlyFormats << std::endl + << " MapOnDefaultBuffers: " << featureD3D11Options1.MapOnDefaultBuffers << std::endl; + + } + + if (SUCCEEDED(device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS2, &featureD3D11Options2, sizeof(featureD3D11Options2)))) { + std::cout << "D3D11_FEATURE_D3D11_OPTIONS2:" << std::endl + << " PSSpecifiedStencilRefSupported: " << featureD3D11Options2.PSSpecifiedStencilRefSupported << std::endl + << " TypedUAVLoadAdditionalFormats: " << featureD3D11Options2.TypedUAVLoadAdditionalFormats << std::endl + << " ROVsSupported: " << featureD3D11Options2.ROVsSupported << std::endl + << " ConservativeRasterizationTier: " << featureD3D11Options2.ConservativeRasterizationTier << std::endl + << " MapOnDefaultTextures: " << featureD3D11Options2.MapOnDefaultTextures << std::endl + << " TiledResourcesTier: " << featureD3D11Options2.TiledResourcesTier << std::endl + << " StandardSwizzle: " << featureD3D11Options2.StandardSwizzle << std::endl + << " UnifiedMemoryArchitecture: " << featureD3D11Options2.UnifiedMemoryArchitecture << std::endl; + } + + if (SUCCEEDED(device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS3, &featureD3D11Options3, sizeof(featureD3D11Options3)))) { + std::cout << "D3D11_FEATURE_D3D11_OPTIONS3:" << std::endl + << " VPAndRTArrayIndexFromAnyShaderFeedingRasterizer: " << featureD3D11Options3.VPAndRTArrayIndexFromAnyShaderFeedingRasterizer << std::endl; + } + + if (SUCCEEDED(device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS4, &featureD3D11Options4, sizeof(featureD3D11Options4)))) { + std::cout << "D3D11_FEATURE_D3D11_OPTIONS4:" << std::endl + << " ExtendedNV12SharedTextureSupported: " << featureD3D11Options4.ExtendedNV12SharedTextureSupported << std::endl; + } + + for (UINT i = UINT(DXGI_FORMAT_UNKNOWN); + i <= UINT(DXGI_FORMAT_BC7_UNORM_SRGB); + i++) { + DXGI_FORMAT format = DXGI_FORMAT(i); + UINT flags = 0; + + std::cout << GetFormatName(format) << ": " << std::endl; + + if (SUCCEEDED(device->CheckFormatSupport(format, &flags))) { + for (uint32_t i = 0; i < 32; i++) { + if (flags & (1 << i)) { + std::cout << " " + << GetFormatFlagName(D3D11_FORMAT_SUPPORT(1 << i)) + << std::endl; + } + } + + } else { + std::cout << " Not supported" << std::endl; + } + } + + return 0; +} diff --git a/utils/dxvk-1.10.3/tests/d3d11/test_d3d11_map_read.cpp b/utils/dxvk-1.10.3/tests/d3d11/test_d3d11_map_read.cpp new file mode 100644 index 00000000000..8e73dc45ba5 --- /dev/null +++ b/utils/dxvk-1.10.3/tests/d3d11/test_d3d11_map_read.cpp @@ -0,0 +1,203 @@ +#include +#include + +#include +#include + +#include +#include + +#include "../test_utils.h" + +using namespace dxvk; + +const std::string g_vsCode = + "float4 main(float4 v_pos : VS_POSITION) : SV_POSITION {\n" + " return v_pos;\n" + "}\n"; + +Com g_d3d11Device; +Com g_d3d11Context; + +Com g_vertShader; +Com g_inputLayout; + +Com g_vertexBuffer; + +Com g_depthRender; +Com g_depthRead; +Com g_depthView; +Comg_depthState; + +struct Vertex { + float x, y, z, w; +}; + +int WINAPI WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) { + if (FAILED(D3D11CreateDevice( + nullptr, D3D_DRIVER_TYPE_HARDWARE, + nullptr, 0, nullptr, 0, D3D11_SDK_VERSION, + &g_d3d11Device, nullptr, &g_d3d11Context))) { + std::cerr << "Failed to create D3D11 device" << std::endl; + return 1; + } + + Com vsBlob; + Com gsBlob; + + if (FAILED(D3DCompile(g_vsCode.data(), g_vsCode.size(), + "Vertex shader", nullptr, nullptr, "main", "vs_4_0", + 0, 0, &vsBlob, nullptr))) { + std::cerr << "Failed to compile vertex shader" << std::endl; + return 1; + } + + if (FAILED(g_d3d11Device->CreateVertexShader( + vsBlob->GetBufferPointer(), + vsBlob->GetBufferSize(), + nullptr, &g_vertShader))) { + std::cerr << "Failed to create vertex shader" << std::endl; + return 1; + } + + std::array iaElements = {{ + { "VS_POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }}; + + if (FAILED(g_d3d11Device->CreateInputLayout( + iaElements.data(), + iaElements.size(), + vsBlob->GetBufferPointer(), + vsBlob->GetBufferSize(), + &g_inputLayout))) { + std::cerr << "Failed to create input layout" << std::endl; + return 1; + } + + std::array vertexData = {{ + { -1.0f, -1.0f, 0.00f, 1.0f }, + { -1.0f, 1.0f, 0.66f, 1.0f }, + { 1.0f, -1.0f, 0.33f, 1.0f }, + { 1.0f, 1.0f, 1.00f, 1.0f }, + }}; + + D3D11_BUFFER_DESC vertexDesc; + vertexDesc.ByteWidth = vertexData.size() * sizeof(Vertex); + vertexDesc.Usage = D3D11_USAGE_IMMUTABLE; + vertexDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + vertexDesc.CPUAccessFlags = 0; + vertexDesc.MiscFlags = 0; + vertexDesc.StructureByteStride = 0; + + D3D11_SUBRESOURCE_DATA vertexInfo; + vertexInfo.pSysMem = vertexData.data(); + vertexInfo.SysMemPitch = vertexDesc.ByteWidth; + vertexInfo.SysMemSlicePitch = vertexDesc.ByteWidth; + + if (FAILED(g_d3d11Device->CreateBuffer(&vertexDesc, &vertexInfo, &g_vertexBuffer))) { + std::cerr << "Failed to create vertex buffer" << std::endl; + return 1; + } + + D3D11_TEXTURE2D_DESC depthDesc; + depthDesc.Width = 16; + depthDesc.Height = 16; + depthDesc.MipLevels = 1; + depthDesc.ArraySize = 1; + depthDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; + // depthDesc.Format = DXGI_FORMAT_D32_FLOAT_S8X24_UINT; + depthDesc.SampleDesc = { 1, 0 }; + depthDesc.Usage = D3D11_USAGE_DEFAULT; + depthDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; + depthDesc.CPUAccessFlags = 0; + depthDesc.MiscFlags = 0; + + if (FAILED(g_d3d11Device->CreateTexture2D(&depthDesc, nullptr, &g_depthRender))) { + std::cerr << "Failed to create render buffer" << std::endl; + return 1; + } + + depthDesc.Usage = D3D11_USAGE_STAGING; + depthDesc.BindFlags = 0; + depthDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + + if (FAILED(g_d3d11Device->CreateTexture2D(&depthDesc, nullptr, &g_depthRead))) { + std::cerr << "Failed to create readback buffer" << std::endl; + return 1; + } + + if (FAILED(g_d3d11Device->CreateDepthStencilView(g_depthRender.ptr(), nullptr, &g_depthView))) { + std::cerr << "Failed to create depth-stencil view" << std::endl; + return 1; + } + + D3D11_DEPTH_STENCIL_DESC dsDesc; + dsDesc.DepthEnable = TRUE; + dsDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; + dsDesc.DepthFunc = D3D11_COMPARISON_ALWAYS; + dsDesc.StencilEnable = FALSE; + dsDesc.StencilReadMask = 0; + dsDesc.StencilWriteMask = 0; + dsDesc.FrontFace = { }; + dsDesc.BackFace = { }; + + if (FAILED(g_d3d11Device->CreateDepthStencilState(&dsDesc, &g_depthState))) { + std::cerr << "Failed to create depth-stencil state" << std::endl; + return 1; + } + + FLOAT omBlendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + + D3D11_VIEWPORT omViewport; + omViewport.TopLeftX = 0.0f; + omViewport.TopLeftY = 0.0f; + omViewport.Width = 16.0f; + omViewport.Height = 16.0f; + omViewport.MinDepth = 0.0f; + omViewport.MaxDepth = 1.0f; + + UINT vbOffset = 0; + UINT vbStride = sizeof(Vertex); + + g_d3d11Context->RSSetState(nullptr); + g_d3d11Context->RSSetViewports(1, &omViewport); + + g_d3d11Context->OMSetRenderTargets(0, nullptr, g_depthView.ptr()); + g_d3d11Context->OMSetBlendState(nullptr, omBlendFactor, 0xFFFFFFFF); + g_d3d11Context->OMSetDepthStencilState(g_depthState.ptr(), 0); + + g_d3d11Context->ClearDepthStencilView(g_depthView.ptr(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 0.5f, 0x80); + + g_d3d11Context->IASetInputLayout(g_inputLayout.ptr()); + g_d3d11Context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + g_d3d11Context->IASetVertexBuffers(0, 1, &g_vertexBuffer, &vbStride, &vbOffset); + + g_d3d11Context->VSSetShader(g_vertShader.ptr(), nullptr, 0); + g_d3d11Context->Draw(4, 0); + + g_d3d11Context->CopyResource(g_depthRead.ptr(), g_depthRender.ptr()); + + D3D11_MAPPED_SUBRESOURCE mapped; + + if (FAILED(g_d3d11Context->Map(g_depthRead.ptr(), 0, D3D11_MAP_READ, 0, &mapped))) { + std::cerr << "Failed to map image" << std::endl; + return 1; + } + + for (uint32_t y = 0; y < 16; y++) { + auto data = reinterpret_cast(mapped.pData) + + (y * mapped.RowPitch / 4); + + for (uint32_t x = 0; x < 16; x++) + std::cout << std::hex << std::setfill('0') << std::setw(8) << data[x] << " "; + + std::cout << std::endl; + } + + g_d3d11Context->Unmap(g_depthRead.ptr(), 0); + g_d3d11Context->ClearState(); + return 0; +} diff --git a/utils/dxvk-1.10.3/tests/d3d11/test_d3d11_streamout.cpp b/utils/dxvk-1.10.3/tests/d3d11/test_d3d11_streamout.cpp new file mode 100644 index 00000000000..3ff5f9ec389 --- /dev/null +++ b/utils/dxvk-1.10.3/tests/d3d11/test_d3d11_streamout.cpp @@ -0,0 +1,288 @@ +#include +#include + +#include +#include + +#include +#include + +#include "../test_utils.h" + +using namespace dxvk; + +const std::string g_vsCode = + "struct VS_IFACE {\n" + " float4 pos : VS_POSITION;\n" + "};\n" + "VS_IFACE main(VS_IFACE ia_in) {\n" + " return ia_in;\n" + "}\n"; + +const std::string g_gsCode = + "struct GS_IN {\n" + " float4 pos : VS_POSITION;\n" + "};\n" + "struct GS_OUT_NORMAL {\n" + " float3 nor : GS_NORMAL;\n" + " float len : GS_LENGTH;\n" + "};\n" + "[maxvertexcount(1)]\n" + "void main(triangle GS_IN vs_in[3], inout PointStream o_normals) {\n" + " float3 ds1 = vs_in[1].pos.xyz - vs_in[0].pos.xyz;\n" + " float3 ds2 = vs_in[2].pos.xyz - vs_in[0].pos.xyz;\n" + " float3 cv = cross(ds1, ds2);\n" + " float cl = length(cv);\n" + " GS_OUT_NORMAL normal;\n" + " normal.nor = cv / cl;\n" + " normal.len = cl;" + " o_normals.Append(normal);\n" + "}\n"; + +Com g_d3d11Device; +Com g_d3d11Context; + +Com g_vertShader; +Com g_geomShader; + +Com g_inputLayout; + +Com g_vertexBuffer; +Com g_normalBuffer; +Com g_readBuffer; + +Com g_soStream; +Com g_soOverflow; + +struct Vertex { + float x, y, z, w; +}; + +struct Normal { + float x, y, z, len; +}; + +int WINAPI WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) { + if (FAILED(D3D11CreateDevice( + nullptr, D3D_DRIVER_TYPE_HARDWARE, + nullptr, 0, nullptr, 0, D3D11_SDK_VERSION, + &g_d3d11Device, nullptr, &g_d3d11Context))) { + std::cerr << "Failed to create D3D11 device" << std::endl; + return 1; + } + + Com vsBlob; + Com gsBlob; + + if (FAILED(D3DCompile(g_vsCode.data(), g_vsCode.size(), + "Vertex shader", nullptr, nullptr, "main", "vs_4_0", + 0, 0, &vsBlob, nullptr))) { + std::cerr << "Failed to compile vertex shader" << std::endl; + return 1; + } + + if (FAILED(D3DCompile(g_gsCode.data(), g_gsCode.size(), + "Geometry shader", nullptr, nullptr, "main", "gs_4_0", + 0, 0, &gsBlob, nullptr))) { + std::cerr << "Failed to compile geometry shader" << std::endl; + return 1; + } + + if (FAILED(g_d3d11Device->CreateVertexShader( + vsBlob->GetBufferPointer(), + vsBlob->GetBufferSize(), + nullptr, &g_vertShader))) { + std::cerr << "Failed to create vertex shader" << std::endl; + return 1; + } + + std::array soDeclarations = {{ + { 0, "GS_NORMAL", 0, 0, 3, 0 }, + { 0, "GS_LENGTH", 0, 0, 1, 0 }, + }}; + + std::array soBufferStrides = {{ + sizeof(Normal), + }}; + + if (FAILED(g_d3d11Device->CreateGeometryShaderWithStreamOutput( + gsBlob->GetBufferPointer(), + gsBlob->GetBufferSize(), + soDeclarations.data(), + soDeclarations.size(), + soBufferStrides.data(), + soBufferStrides.size(), + D3D11_SO_NO_RASTERIZED_STREAM, + nullptr, &g_geomShader))) { + std::cerr << "Failed to create geometry shader" << std::endl; + return 1; + } + + std::array iaElements = {{ + { "VS_POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }}; + + if (FAILED(g_d3d11Device->CreateInputLayout( + iaElements.data(), + iaElements.size(), + vsBlob->GetBufferPointer(), + vsBlob->GetBufferSize(), + &g_inputLayout))) { + std::cerr << "Failed to create input layout" << std::endl; + return 1; + } + + std::array vertexData = {{ + { 0.0f, 0.0f, 0.0f, 1.0f }, + { 1.0f, 0.0f, 0.0f, 1.0f }, + { 0.0f, 1.0f, 0.0f, 1.0f }, + + { 0.5f,-1.0f,-0.2f, 1.0f }, + { 3.2f, 2.0f, 0.0f, 1.0f }, + {-1.0f,-1.0f, 0.4f, 1.0f }, + + { 0.7f,-0.5f,-0.8f, 1.0f }, + { 1.2f, 1.0f,-1.0f, 1.0f }, + {-0.1f, 1.0f,-2.7f, 1.0f }, + }}; + + D3D11_BUFFER_DESC vertexDesc; + vertexDesc.ByteWidth = vertexData.size() * sizeof(Vertex); + vertexDesc.Usage = D3D11_USAGE_IMMUTABLE; + vertexDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + vertexDesc.CPUAccessFlags = 0; + vertexDesc.MiscFlags = 0; + vertexDesc.StructureByteStride = 0; + + D3D11_SUBRESOURCE_DATA vertexInfo; + vertexInfo.pSysMem = vertexData.data(); + vertexInfo.SysMemPitch = vertexDesc.ByteWidth; + vertexInfo.SysMemSlicePitch = vertexDesc.ByteWidth; + + if (FAILED(g_d3d11Device->CreateBuffer(&vertexDesc, &vertexInfo, &g_vertexBuffer))) { + std::cerr << "Failed to create vertex buffer" << std::endl; + return 1; + } + + std::array normalData = { }; + + D3D11_BUFFER_DESC normalDesc; + normalDesc.ByteWidth = normalData.size() * sizeof(Normal); + normalDesc.Usage = D3D11_USAGE_DEFAULT; + normalDesc.BindFlags = D3D11_BIND_STREAM_OUTPUT; + normalDesc.CPUAccessFlags = 0; + normalDesc.MiscFlags = 0; + normalDesc.StructureByteStride = 0; + + D3D11_SUBRESOURCE_DATA normalInfo; + normalInfo.pSysMem = normalData.data(); + normalInfo.SysMemPitch = normalDesc.ByteWidth; + normalInfo.SysMemSlicePitch = normalDesc.ByteWidth; + + if (FAILED(g_d3d11Device->CreateBuffer(&normalDesc, &normalInfo, &g_normalBuffer))) { + std::cerr << "Failed to create normal buffer" << std::endl; + return 1; + } + + D3D11_BUFFER_DESC readDesc; + readDesc.ByteWidth = normalDesc.ByteWidth; + readDesc.Usage = D3D11_USAGE_STAGING; + readDesc.BindFlags = 0; + readDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + readDesc.MiscFlags = 0; + readDesc.StructureByteStride = 0; + + if (FAILED(g_d3d11Device->CreateBuffer(&readDesc, nullptr, &g_readBuffer))) { + std::cerr << "Failed to create readback buffer" << std::endl; + return 1; + } + + D3D11_QUERY_DESC soQueryDesc; + soQueryDesc.Query = D3D11_QUERY_SO_STATISTICS_STREAM0; + soQueryDesc.MiscFlags = 0; + + if (FAILED(g_d3d11Device->CreateQuery(&soQueryDesc, &g_soStream))) { + std::cerr << "Failed to create streamout query" << std::endl; + return 1; + } + + soQueryDesc.Query = D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM0; + if (FAILED(g_d3d11Device->CreateQuery(&soQueryDesc, &g_soOverflow))) { + std::cerr << "Failed to create streamout overflow query" << std::endl; + return 1; + } + + UINT soOffset = 0; + UINT vbOffset = 0; + UINT vbStride = sizeof(Vertex); + + FLOAT omBlendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + + D3D11_VIEWPORT omViewport; + omViewport.TopLeftX = 0.0f; + omViewport.TopLeftY = 0.0f; + omViewport.Width = 256.0f; + omViewport.Height = 256.0f; + omViewport.MinDepth = 0.0f; + omViewport.MaxDepth = 1.0f; + + g_d3d11Context->IASetInputLayout(g_inputLayout.ptr()); + g_d3d11Context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + g_d3d11Context->IASetVertexBuffers(0, 1, &g_vertexBuffer, &vbStride, &vbOffset); + + g_d3d11Context->RSSetState(nullptr); + g_d3d11Context->RSSetViewports(1, &omViewport); + + g_d3d11Context->OMSetRenderTargets(0, nullptr, nullptr); + g_d3d11Context->OMSetBlendState(nullptr, omBlendFactor, 0xFFFFFFFF); + g_d3d11Context->OMSetDepthStencilState(nullptr, 0); + + g_d3d11Context->SOSetTargets(1, &g_normalBuffer, &soOffset); + + g_d3d11Context->VSSetShader(g_vertShader.ptr(), nullptr, 0); + g_d3d11Context->GSSetShader(g_geomShader.ptr(), nullptr, 0); + + g_d3d11Context->Begin(g_soStream.ptr()); + g_d3d11Context->Begin(g_soOverflow.ptr()); + + g_d3d11Context->Draw(vertexData.size(), 0); + + g_d3d11Context->End(g_soOverflow.ptr()); + g_d3d11Context->End(g_soStream.ptr()); + + g_d3d11Context->CopyResource( + g_readBuffer.ptr(), + g_normalBuffer.ptr()); + + D3D11_QUERY_DATA_SO_STATISTICS soQueryData = { }; + BOOL soOverflowData = false; + + while (g_d3d11Context->GetData(g_soStream.ptr(), &soQueryData, sizeof(soQueryData), 0) != S_OK + || g_d3d11Context->GetData(g_soOverflow.ptr(), &soOverflowData, sizeof(soOverflowData), 0) != S_OK) + continue; + + std::cout << "Written: " << soQueryData.NumPrimitivesWritten << std::endl; + std::cout << "Needed: " << soQueryData.PrimitivesStorageNeeded << std::endl; + std::cout << "Overflow: " << (soOverflowData ? "Yes" : "No") << std::endl; + + D3D11_MAPPED_SUBRESOURCE mapInfo; + + if (FAILED(g_d3d11Context->Map(g_readBuffer.ptr(), 0, D3D11_MAP_READ, 0, &mapInfo))) { + std::cerr << "Failed to map readback buffer" << std::endl; + return 1; + } + + std::memcpy(normalData.data(), mapInfo.pData, normalDesc.ByteWidth); + g_d3d11Context->Unmap(g_readBuffer.ptr(), 0); + + for (uint32_t i = 0; i < normalData.size(); i++) { + std::cout << i << ": " << normalData[i].x << "," + << normalData[i].y << "," << normalData[i].z << "," + << normalData[i].len << std::endl; + } + + return 0; +} diff --git a/utils/dxvk-1.10.3/tests/d3d11/test_d3d11_triangle.cpp b/utils/dxvk-1.10.3/tests/d3d11/test_d3d11_triangle.cpp new file mode 100644 index 00000000000..5c2ea78f03a --- /dev/null +++ b/utils/dxvk-1.10.3/tests/d3d11/test_d3d11_triangle.cpp @@ -0,0 +1,606 @@ +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include "../test_utils.h" + +using namespace dxvk; + +struct Vertex { + float x, y; +}; + +struct VsConstants { + float x, y; + float w, h; +}; + +struct VsConstantsPad { + VsConstants data; + uint32_t pad[60]; +}; + +struct PsConstants { + float r, g, b, a; +}; + +struct DrawOptions { + bool mapDiscardOnce; + bool sortByTexture; + bool drawIndexed; +}; + +const std::string g_vertexShaderCode = + "cbuffer vs_cb : register(b0) {\n" + " float2 v_offset;\n" + " float2 v_scale;\n" + "};\n" + "float4 main(float4 v_pos : IN_POSITION) : SV_POSITION {\n" + " float2 coord = 2.0f * (v_pos * v_scale + v_offset) - 1.0f;\n" + " return float4(coord, 0.0f, 1.0f);\n" + "}\n"; + +const std::string g_pixelShaderCode = + "Texture2D tex0 : register(t0);" + "cbuffer ps_cb : register(b0) {\n" + " float4 color;\n" + "};\n" + "float4 main() : SV_TARGET {\n" + " return color * tex0.Load(int3(0, 0, 0));\n" + "}\n"; + +class TriangleApp { + +public: + + TriangleApp(HINSTANCE instance, HWND window) + : m_window(window) { + Com device; + + D3D_FEATURE_LEVEL fl = D3D_FEATURE_LEVEL_11_1; + + HRESULT status = D3D11CreateDevice( + nullptr, D3D_DRIVER_TYPE_HARDWARE, + nullptr, 0, &fl, 1, D3D11_SDK_VERSION, + &device, nullptr, nullptr); + + if (FAILED(status)) { + std::cerr << "Failed to create D3D11 device" << std::endl; + return; + } + + if (FAILED(device->QueryInterface(IID_PPV_ARGS(&m_device)))) { + std::cerr << "Failed to query ID3D11DeviceContext1" << std::endl; + return; + } + + Com dxgiDevice; + + if (FAILED(m_device->QueryInterface(IID_PPV_ARGS(&dxgiDevice)))) { + std::cerr << "Failed to query DXGI device" << std::endl; + return; + } + + if (FAILED(dxgiDevice->GetAdapter(&m_adapter))) { + std::cerr << "Failed to query DXGI adapter" << std::endl; + return; + } + + if (FAILED(m_adapter->GetParent(IID_PPV_ARGS(&m_factory)))) { + std::cerr << "Failed to query DXGI factory" << std::endl; + return; + } + + m_device->GetImmediateContext1(&m_context); + + DXGI_SWAP_CHAIN_DESC1 swapDesc; + swapDesc.Width = m_windowSizeW; + swapDesc.Height = m_windowSizeH; + swapDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + swapDesc.Stereo = FALSE; + swapDesc.SampleDesc = { 1, 0 }; + swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapDesc.BufferCount = 3; + swapDesc.Scaling = DXGI_SCALING_STRETCH; + swapDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; + swapDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; + swapDesc.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT + | DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; + + DXGI_SWAP_CHAIN_FULLSCREEN_DESC fsDesc; + fsDesc.RefreshRate = { 0, 0 }; + fsDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; + fsDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + fsDesc.Windowed = TRUE; + + Com swapChain; + if (FAILED(m_factory->CreateSwapChainForHwnd(m_device.ptr(), m_window, &swapDesc, &fsDesc, nullptr, &swapChain))) { + std::cerr << "Failed to create DXGI swap chain" << std::endl; + return; + } + + if (FAILED(swapChain->QueryInterface(IID_PPV_ARGS(&m_swapChain)))) { + std::cerr << "Failed to query DXGI swap chain interface" << std::endl; + return; + } + + m_factory->MakeWindowAssociation(m_window, 0); + + Com vertexShaderBlob; + Com pixelShaderBlob; + + if (FAILED(D3DCompile(g_vertexShaderCode.data(), g_vertexShaderCode.size(), + "Vertex shader", nullptr, nullptr, "main", "vs_5_0", 0, 0, &vertexShaderBlob, nullptr))) { + std::cerr << "Failed to compile vertex shader" << std::endl; + return; + } + + if (FAILED(D3DCompile(g_pixelShaderCode.data(), g_pixelShaderCode.size(), + "Pixel shader", nullptr, nullptr, "main", "ps_5_0", 0, 0, &pixelShaderBlob, nullptr))) { + std::cerr << "Failed to compile pixel shader" << std::endl; + return; + } + + if (FAILED(m_device->CreateVertexShader( + vertexShaderBlob->GetBufferPointer(), + vertexShaderBlob->GetBufferSize(), + nullptr, &m_vs))) { + std::cerr << "Failed to create vertex shader" << std::endl; + return; + } + + if (FAILED(m_device->CreatePixelShader( + pixelShaderBlob->GetBufferPointer(), + pixelShaderBlob->GetBufferSize(), + nullptr, &m_ps))) { + std::cerr << "Failed to create pixel shader" << std::endl; + return; + } + + std::array vertexFormatDesc = {{ + { "IN_POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }}; + + if (FAILED(m_device->CreateInputLayout( + vertexFormatDesc.data(), + vertexFormatDesc.size(), + vertexShaderBlob->GetBufferPointer(), + vertexShaderBlob->GetBufferSize(), + &m_vertexFormat))) { + std::cerr << "Failed to create input layout" << std::endl; + return; + } + + std::array vertexData = {{ + Vertex { -0.3f, 0.1f }, + Vertex { 0.5f, 0.9f }, + Vertex { 1.3f, 0.1f }, + Vertex { -0.3f, 0.9f }, + Vertex { 1.3f, 0.9f }, + Vertex { 0.5f, 0.1f }, + }}; + + D3D11_BUFFER_DESC vboDesc; + vboDesc.ByteWidth = sizeof(vertexData); + vboDesc.Usage = D3D11_USAGE_IMMUTABLE; + vboDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + vboDesc.CPUAccessFlags = 0; + vboDesc.MiscFlags = 0; + vboDesc.StructureByteStride = 0; + + D3D11_SUBRESOURCE_DATA vboData; + vboData.pSysMem = vertexData.data(); + vboData.SysMemPitch = vboDesc.ByteWidth; + vboData.SysMemSlicePitch = vboDesc.ByteWidth; + + if (FAILED(m_device->CreateBuffer(&vboDesc, &vboData, &m_vbo))) { + std::cerr << "Failed to create index buffer" << std::endl; + return; + } + + std::array indexData = {{ 0, 1, 2, 3, 4, 5 }}; + + D3D11_BUFFER_DESC iboDesc; + iboDesc.ByteWidth = sizeof(indexData); + iboDesc.Usage = D3D11_USAGE_IMMUTABLE; + iboDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; + iboDesc.CPUAccessFlags = 0; + iboDesc.MiscFlags = 0; + iboDesc.StructureByteStride = 0; + + D3D11_SUBRESOURCE_DATA iboData; + iboData.pSysMem = indexData.data(); + iboData.SysMemPitch = iboDesc.ByteWidth; + iboData.SysMemSlicePitch = iboDesc.ByteWidth; + + if (FAILED(m_device->CreateBuffer(&iboDesc, &iboData, &m_ibo))) { + std::cerr << "Failed to create index buffer" << std::endl; + return; + } + + D3D11_BUFFER_DESC cbDesc; + cbDesc.ByteWidth = sizeof(PsConstants); + cbDesc.Usage = D3D11_USAGE_DYNAMIC; + cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + cbDesc.MiscFlags = 0; + cbDesc.StructureByteStride = 0; + + if (FAILED(m_device->CreateBuffer(&cbDesc, nullptr, &m_cbPs))) { + std::cerr << "Failed to create constant buffer" << std::endl; + return; + } + + cbDesc.ByteWidth = sizeof(VsConstantsPad) * 128 * 8; + + if (FAILED(m_device->CreateBuffer(&cbDesc, nullptr, &m_cbVs))) { + std::cerr << "Failed to create constant buffer" << std::endl; + return; + } + + std::array colors = { 0xFFFFFFFF, 0xFFC0C0C0 }; + + D3D11_SUBRESOURCE_DATA texData; + texData.pSysMem = &colors[0]; + texData.SysMemPitch = sizeof(colors[0]); + texData.SysMemSlicePitch = sizeof(colors[0]); + + D3D11_TEXTURE2D_DESC texDesc; + texDesc.Width = 1; + texDesc.Height = 1; + texDesc.MipLevels = 1; + texDesc.ArraySize = 1; + texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + texDesc.SampleDesc = { 1, 0 }; + texDesc.Usage = D3D11_USAGE_IMMUTABLE; + texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + texDesc.CPUAccessFlags = 0; + texDesc.MiscFlags = 0; + + if (FAILED(m_device->CreateTexture2D(&texDesc, &texData, &m_tex0))) { + std::cerr << "Failed to create texture" << std::endl; + return; + } + + texData.pSysMem = &colors[1]; + + if (FAILED(m_device->CreateTexture2D(&texDesc, &texData, &m_tex1))) { + std::cerr << "Failed to create texture" << std::endl; + return; + } + + if (FAILED(m_device->CreateShaderResourceView(m_tex0.ptr(), nullptr, &m_srv0)) + || FAILED(m_device->CreateShaderResourceView(m_tex1.ptr(), nullptr, &m_srv1))) { + std::cerr << "Failed to create SRV" << std::endl; + return; + } + + m_initialized = true; + } + + + ~TriangleApp() { + m_context->ClearState(); + } + + + bool run() { + if (!m_initialized) + return false; + + if (m_occluded && (m_occluded = isOccluded())) + return true; + + if (!beginFrame()) + return true; + + std::array colors = {{ + PsConstants { 0.25f, 0.25f, 0.25f, 1.0f }, + PsConstants { 0.40f, 0.40f, 0.40f, 1.0f }, + }}; + + for (uint32_t i = 0; i < 8; i++) { + DrawOptions options; + options.sortByTexture = i & 1; + options.drawIndexed = i & 2; + options.mapDiscardOnce = i & 4; + drawLines(colors[i & 1], options, i); + } + + if (!endFrame()) + return false; + + updateFps(); + return true; + } + + + void drawLines(const PsConstants& psData, const DrawOptions& options, uint32_t baseY) { + D3D11_MAPPED_SUBRESOURCE sr; + + // Update color for the row + m_context->PSSetConstantBuffers(0, 1, &m_cbPs); + m_context->Map(m_cbPs.ptr(), 0, D3D11_MAP_WRITE_DISCARD, 0, &sr); + std::memcpy(sr.pData, &psData, sizeof(psData)); + m_context->Unmap(m_cbPs.ptr(), 0); + + baseY *= 8; + + if (options.mapDiscardOnce) { + uint32_t drawIndex = 0; + + // Discard and map the entire vertex constant buffer + // once, then bind sub-ranges while emitting draw calls + m_context->Map(m_cbVs.ptr(), 0, D3D11_MAP_WRITE_DISCARD, 0, &sr); + auto vsData = reinterpret_cast(sr.pData); + + for (uint32_t y = 0; y < 8; y++) { + for (uint32_t x = 0; x < 128; x++) + vsData[drawIndex++].data = getVsConstants(x, baseY + y); + } + + m_context->Unmap(m_cbVs.ptr(), 0); + } + + if (options.drawIndexed) + m_context->IASetIndexBuffer(m_ibo.ptr(), DXGI_FORMAT_R32_UINT, 0); + + uint32_t vsStride = sizeof(Vertex); + uint32_t vsOffset = 0; + m_context->IASetVertexBuffers(0, 1, &m_vbo, &vsStride, &vsOffset); + + uint32_t maxZ = options.sortByTexture ? 2 : 1; + + for (uint32_t z = 0; z < maxZ; z++) { + uint32_t drawIndex = z; + + if (options.sortByTexture) { + ID3D11ShaderResourceView* view = z ? m_srv1.ptr() : m_srv0.ptr(); + m_context->PSSetShaderResources(0, 1, &view); + } + + for (uint32_t y = 0; y < 8; y++) { + for (uint32_t x = z; x < 128; x += maxZ) { + uint32_t triIndex = (x ^ y) & 1; + + if (!options.mapDiscardOnce) { + D3D11_MAP mapMode = drawIndex ? D3D11_MAP_WRITE_NO_OVERWRITE : D3D11_MAP_WRITE_DISCARD; + m_context->Map(m_cbVs.ptr(), 0, mapMode, 0, &sr); + auto vsData = reinterpret_cast(sr.pData); + vsData[drawIndex].data = getVsConstants(x, baseY + y); + m_context->Unmap(m_cbVs.ptr(), 0); + } + + uint32_t constantOffset = 16 * drawIndex; + uint32_t constantCount = 16; + m_context->VSSetConstantBuffers1(0, 1, &m_cbVs, &constantOffset, &constantCount); + + if (!options.sortByTexture) { + ID3D11ShaderResourceView* view = triIndex ? m_srv1.ptr() : m_srv0.ptr(); + m_context->PSSetShaderResources(0, 1, &view); + } + + // Submit draw call + uint32_t baseIndex = 3 * triIndex; + + if (options.drawIndexed) + m_context->DrawIndexed(3, baseIndex, 0); + else + m_context->Draw(3, baseIndex); + + drawIndex += maxZ; + } + } + } + } + + + static VsConstants getVsConstants(uint32_t x, uint32_t y) { + VsConstants result; + result.x = float(x) / 128.0f; + result.y = float(y) / 64.0f; + result.w = 1.0f / 128.0f; + result.h = 1.0f / 64.0f; + return result; + } + + + bool beginFrame() { + // Make sure we can actually render to the window + RECT windowRect = { 0, 0, 1024, 600 }; + GetClientRect(m_window, &windowRect); + + uint32_t newWindowSizeW = uint32_t(windowRect.right - windowRect.left); + uint32_t newWindowSizeH = uint32_t(windowRect.bottom - windowRect.top); + + if (m_windowSizeW != newWindowSizeW || m_windowSizeH != newWindowSizeH) { + m_rtv = nullptr; + m_context->ClearState(); + + DXGI_SWAP_CHAIN_DESC1 desc; + m_swapChain->GetDesc1(&desc); + + if (FAILED(m_swapChain->ResizeBuffers(desc.BufferCount, + newWindowSizeW, newWindowSizeH, desc.Format, desc.Flags))) { + std::cerr << "Failed to resize back buffers" << std::endl; + return false; + } + + Com backBuffer; + if (FAILED(m_swapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer)))) { + std::cerr << "Failed to get swap chain back buffer" << std::endl; + return false; + } + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + rtvDesc.Texture2D = { 0u }; + + if (FAILED(m_device->CreateRenderTargetView(backBuffer.ptr(), &rtvDesc, &m_rtv))) { + std::cerr << "Failed to create render target view" << std::endl; + return false; + } + + m_windowSizeW = newWindowSizeW; + m_windowSizeH = newWindowSizeH; + } + + // Set up render state + FLOAT color[4] = { 0.5f, 0.5f, 0.5f, 1.0f }; + m_context->OMSetRenderTargets(1, &m_rtv, nullptr); + m_context->ClearRenderTargetView(m_rtv.ptr(), color); + + m_context->VSSetShader(m_vs.ptr(), nullptr, 0); + m_context->PSSetShader(m_ps.ptr(), nullptr, 0); + + m_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + m_context->IASetInputLayout(m_vertexFormat.ptr()); + + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0.0f; + viewport.TopLeftY = 0.0f; + viewport.Width = float(m_windowSizeW); + viewport.Height = float(m_windowSizeH); + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + m_context->RSSetViewports(1, &viewport); + return true; + } + + + bool endFrame() { + HRESULT hr = m_swapChain->Present(0, DXGI_PRESENT_TEST); + + if (hr == S_OK) + hr = m_swapChain->Present(0, 0); + + m_occluded = hr == DXGI_STATUS_OCCLUDED; + return true; + } + + void updateFps() { + if (!m_qpcFrequency.QuadPart) + QueryPerformanceFrequency(&m_qpcFrequency); + + if (!m_qpcLastUpdate.QuadPart) + QueryPerformanceCounter(&m_qpcLastUpdate); + + LARGE_INTEGER now; + QueryPerformanceCounter(&now); + + m_frameCount++; + + if (now.QuadPart - m_qpcLastUpdate.QuadPart < m_qpcFrequency.QuadPart) + return; + + double seconds = double(now.QuadPart - m_qpcLastUpdate.QuadPart) / double(m_qpcFrequency.QuadPart); + double fps = double(m_frameCount) / seconds; + + std::wstringstream str; + str << L"D3D11 triangle (" << fps << L" FPS)"; + + SetWindowTextW(m_window, str.str().c_str()); + + m_qpcLastUpdate = now; + m_frameCount = 0; + } + + bool isOccluded() { + return m_swapChain->Present(0, DXGI_PRESENT_TEST) == DXGI_STATUS_OCCLUDED; + } + +private: + + HWND m_window; + uint32_t m_windowSizeW = 1024; + uint32_t m_windowSizeH = 600; + bool m_initialized = false; + bool m_occluded = false; + + Com m_factory; + Com m_adapter; + Com m_device; + Com m_context; + Com m_swapChain; + + Com m_rtv; + Com m_ibo; + Com m_vbo; + Com m_vertexFormat; + + Com m_tex0; + Com m_tex1; + Com m_srv0; + Com m_srv1; + + Com m_cbPs; + Com m_cbVs; + + Com m_vs; + Com m_ps; + + LARGE_INTEGER m_qpcLastUpdate = { }; + LARGE_INTEGER m_qpcFrequency = { }; + + uint32_t m_frameCount = 0; + +}; + +LRESULT CALLBACK WindowProc(HWND hWnd, + UINT message, + WPARAM wParam, + LPARAM lParam); + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { + WNDCLASSEXW wc = { }; + wc.cbSize = sizeof(wc); + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = WindowProc; + wc.hInstance = hInstance; + wc.hCursor = LoadCursor(nullptr, IDC_ARROW); + wc.hbrBackground = HBRUSH(COLOR_WINDOW); + wc.lpszClassName = L"WindowClass"; + RegisterClassExW(&wc); + + HWND hWnd = CreateWindowExW(0, L"WindowClass", L"D3D11 triangle", + WS_OVERLAPPEDWINDOW, 300, 300, 1024, 600, + nullptr, nullptr, hInstance, nullptr); + ShowWindow(hWnd, nCmdShow); + + TriangleApp app(hInstance, hWnd); + + MSG msg; + + while (true) { + if (PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessageW(&msg); + + if (msg.message == WM_QUIT) + return msg.wParam; + } else { + if (!app.run()) + break; + } + } + + return msg.wParam; +} + +LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { + switch (message) { + case WM_CLOSE: + PostQuitMessage(0); + return 0; + } + + return DefWindowProcW(hWnd, message, wParam, lParam); +} diff --git a/utils/dxvk-1.10.3/tests/d3d11/test_d3d11_video.cpp b/utils/dxvk-1.10.3/tests/d3d11/test_d3d11_video.cpp new file mode 100644 index 00000000000..a974962a428 --- /dev/null +++ b/utils/dxvk-1.10.3/tests/d3d11/test_d3d11_video.cpp @@ -0,0 +1,459 @@ +#include + +#include +#include + +#include +#include +#include + +#include "../test_utils.h" + +using namespace dxvk; + +class VideoApp { + +public: + + VideoApp(HINSTANCE instance, HWND window) + : m_window(window) { + // Create base D3D11 device and swap chain + DXGI_SWAP_CHAIN_DESC swapchainDesc = { }; + swapchainDesc.BufferDesc.Width = m_windowSizeX; + swapchainDesc.BufferDesc.Height = m_windowSizeY; + swapchainDesc.BufferDesc.RefreshRate = { 0, 0 }; + swapchainDesc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + swapchainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; + swapchainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + swapchainDesc.BufferCount = 2; + swapchainDesc.SampleDesc = { 1, 0 }; + swapchainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapchainDesc.OutputWindow = m_window; + swapchainDesc.Windowed = true; + swapchainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + swapchainDesc.Flags = 0; + + HRESULT hr = D3D11CreateDeviceAndSwapChain(nullptr, + D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, nullptr, 0, + D3D11_SDK_VERSION, &swapchainDesc, &m_swapchain, + &m_device, nullptr, &m_context); + + if (FAILED(hr)) { + std::cerr << "Failed to initialize D3D11 device and swap chain" << std::endl; + return; + } + + if (FAILED(hr = m_device->QueryInterface(IID_PPV_ARGS(&m_vdevice)))) { + std::cerr << "Failed to query D3D11 video device" << std::endl; + return; + } + + if (FAILED(hr = m_context->QueryInterface(IID_PPV_ARGS(&m_vcontext)))) { + std::cerr << "Failed to query D3D11 video context" << std::endl; + return; + } + + if (FAILED(hr = m_swapchain->ResizeTarget(&swapchainDesc.BufferDesc))) { + std::cerr << "Failed to resize target" << std::endl; + return; + } + + if (FAILED(hr = m_swapchain->GetBuffer(0, IID_PPV_ARGS(&m_swapImage)))) { + std::cerr << "Failed to query swap chain image" << std::endl; + return; + } + + if (FAILED(hr = m_device->CreateRenderTargetView(m_swapImage.ptr(), nullptr, &m_swapImageView))) { + std::cerr << "Failed to create render target view" << std::endl; + return; + } + + // Create video processor instance + D3D11_VIDEO_PROCESSOR_CONTENT_DESC videoEnumDesc = { }; + videoEnumDesc.InputFrameFormat = D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE; + videoEnumDesc.InputFrameRate = { 60, 1 }; + videoEnumDesc.InputWidth = 128; + videoEnumDesc.InputHeight = 128; + videoEnumDesc.OutputFrameRate = { 60, 1 }; + videoEnumDesc.OutputWidth = 256; + videoEnumDesc.OutputHeight = 256; + videoEnumDesc.Usage = D3D11_VIDEO_USAGE_PLAYBACK_NORMAL; + + if (FAILED(hr = m_vdevice->CreateVideoProcessorEnumerator(&videoEnumDesc, &m_venum))) { + std::cerr << "Failed to create D3D11 video processor enumerator" << std::endl; + return; + } + + if (FAILED(hr = m_vdevice->CreateVideoProcessor(m_venum.ptr(), 0, &m_vprocessor))) { + std::cerr << "Failed to create D3D11 video processor" << std::endl; + return; + } + + // Video output image and view + D3D11_TEXTURE2D_DESC textureDesc = { }; + textureDesc.Width = 256; + textureDesc.Height = 256; + textureDesc.MipLevels = 1; + textureDesc.ArraySize = 1; + textureDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + textureDesc.SampleDesc = { 1, 0 }; + textureDesc.Usage = D3D11_USAGE_DEFAULT; + textureDesc.BindFlags = D3D11_BIND_RENDER_TARGET; + + if (FAILED(hr = m_device->CreateTexture2D(&textureDesc, nullptr, &m_videoOutput))) { + std::cerr << "Failed to create D3D11 video output image" << std::endl; + return; + } + + D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC outputDesc = { }; + outputDesc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2D; + outputDesc.Texture2D.MipSlice = 0; + + if (FAILED(hr = m_vdevice->CreateVideoProcessorOutputView(m_videoOutput.ptr(), m_venum.ptr(), &outputDesc, &m_videoOutputView))) { + std::cerr << "Failed to create D3D11 video output view" << std::endl; + return; + } + + if (FAILED(hr = m_device->CreateRenderTargetView(m_videoOutput.ptr(), nullptr, &m_videoOutputRtv))) { + std::cerr << "Failed to create video render target view" << std::endl; + return; + } + + // RGBA input image and view + textureDesc.Width = 128; + textureDesc.Height = 128; + textureDesc.BindFlags = 0; + + size_t pixelCount = textureDesc.Width * textureDesc.Height; + + size_t rowSizeRgba = textureDesc.Width * 4; + size_t rowSizeNv12 = textureDesc.Width; + size_t rowSizeYuy2 = textureDesc.Width * 2; + size_t imageSizeRgba = textureDesc.Height * rowSizeRgba; + size_t imageSizeNv12 = pixelCount + pixelCount / 2; + size_t imageSizeYuy2 = textureDesc.Height * rowSizeYuy2; + + std::vector srcData(pixelCount * 3); + std::vector imgDataRgba(imageSizeRgba); + std::vector imgDataNv12(imageSizeNv12); + std::vector imgDataYuy2(imageSizeYuy2); + std::ifstream ifile("video_image.raw", std::ios::binary); + + if (!ifile || !ifile.read(reinterpret_cast(srcData.data()), srcData.size())) { + std::cerr << "Failed to read image file" << std::endl; + return; + } + + for (size_t i = 0; i < pixelCount; i++) { + imgDataRgba[4 * i + 0] = srcData[3 * i + 0]; + imgDataRgba[4 * i + 1] = srcData[3 * i + 1]; + imgDataRgba[4 * i + 2] = srcData[3 * i + 2]; + imgDataRgba[4 * i + 3] = 0xFF; + + imgDataNv12[i] = y_coeff(&srcData[3 * i], 0.299000f, 0.587000f, 0.114000f); + + imgDataYuy2[2 * i + 0] = y_coeff(&srcData[3 * i], 0.299000f, 0.587000f, 0.114000f); + imgDataYuy2[2 * i + 1] = i % 2 + ? c_coeff(&srcData[3 * i], -0.168736f, -0.331264f, 0.500000f) + : c_coeff(&srcData[3 * i], 0.500000f, -0.418688f, -0.081312f); + } + + for (size_t y = 0; y < textureDesc.Height / 2; y++) { + for (size_t x = 0; x < textureDesc.Width / 2; x++) { + size_t p = textureDesc.Width * (2 * y) + 2 * x; + size_t i = pixelCount + textureDesc.Width * y + 2 * x; + imgDataNv12[i + 0] = c_coeff(&srcData[3 * p], 0.500000f, -0.418688f, -0.081312f); + imgDataNv12[i + 1] = c_coeff(&srcData[3 * p], -0.168736f, -0.331264f, 0.500000f); + } + } + + D3D11_SUBRESOURCE_DATA subresourceData = { }; + subresourceData.pSysMem = imgDataRgba.data(); + subresourceData.SysMemPitch = rowSizeRgba; + subresourceData.SysMemSlicePitch = rowSizeRgba * textureDesc.Height; + + if (FAILED(hr = m_device->CreateTexture2D(&textureDesc, &subresourceData, &m_videoInput))) { + std::cerr << "Failed to create D3D11 video input image" << std::endl; + return; + } + + D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC inputDesc = { }; + inputDesc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D; + inputDesc.Texture2D.MipSlice = 0; + + if (FAILED(hr = m_vdevice->CreateVideoProcessorInputView(m_videoInput.ptr(), m_venum.ptr(), &inputDesc, &m_videoInputView))) { + std::cerr << "Failed to create D3D11 video input view" << std::endl; + return; + } + + // NV12 input image and view + textureDesc.Format = DXGI_FORMAT_NV12; + textureDesc.BindFlags = 0; + + subresourceData.pSysMem = imgDataNv12.data(); + subresourceData.SysMemPitch = rowSizeNv12; + subresourceData.SysMemSlicePitch = rowSizeNv12 * textureDesc.Height; + + if (SUCCEEDED(hr = m_device->CreateTexture2D(&textureDesc, nullptr, &m_videoInputNv12))) { + if (FAILED(hr = m_vdevice->CreateVideoProcessorInputView(m_videoInputNv12.ptr(), m_venum.ptr(), &inputDesc, &m_videoInputViewNv12))) { + std::cerr << "Failed to create D3D11 video input view for NV12" << std::endl; + return; + } + } else { + std::cerr << "NV12 not supported" << std::endl; + } + + textureDesc.Usage = D3D11_USAGE_STAGING; + textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ; + + if (SUCCEEDED(hr = m_device->CreateTexture2D(&textureDesc, nullptr, &m_videoInputNv12Host))) { + D3D11_MAPPED_SUBRESOURCE mr = { }; + m_context->Map(m_videoInputNv12Host.ptr(), 0, D3D11_MAP_WRITE, D3D11_MAP_FLAG_DO_NOT_WAIT, &mr); + memcpy(mr.pData, imgDataNv12.data(), imgDataNv12.size()); + m_context->Unmap(m_videoInputNv12Host.ptr(), 0); + D3D11_BOX box = { 0, 0, 0, 128, 128, 1 }; + m_context->CopySubresourceRegion(m_videoInputNv12.ptr(), 0, 0, 0, 0, m_videoInputNv12Host.ptr(), 0, &box); + } + + // YUY2 input image and view + textureDesc.Format = DXGI_FORMAT_YUY2; + textureDesc.BindFlags = 0; + textureDesc.Usage = D3D11_USAGE_DEFAULT; + textureDesc.CPUAccessFlags = 0; + + subresourceData.pSysMem = imgDataYuy2.data(); + subresourceData.SysMemPitch = rowSizeYuy2; + subresourceData.SysMemSlicePitch = imageSizeYuy2; + + if (SUCCEEDED(hr = m_device->CreateTexture2D(&textureDesc, &subresourceData, &m_videoInputYuy2))) { + if (FAILED(hr = m_vdevice->CreateVideoProcessorInputView(m_videoInputYuy2.ptr(), m_venum.ptr(), &inputDesc, &m_videoInputViewYuy2))) { + std::cerr << "Failed to create D3D11 video input view for YUY2" << std::endl; + return; + } + } else { + std::cerr << "YUY2 not supported" << std::endl; + } + + m_initialized = true; + } + + + ~VideoApp() { + + } + + + void run() { + this->adjustBackBuffer(); + + float color[4] = { 0.5f, 0.5f, 0.5f, 1.0f }; + m_context->ClearRenderTargetView(m_swapImageView.ptr(), color); + + // Full range RGB output color space + D3D11_VIDEO_PROCESSOR_COLOR_SPACE csOut = { }; + csOut.Usage = 0; // Present + csOut.RGB_Range = 0; // Full range + csOut.Nominal_Range = 1; // Full range + + D3D11_VIDEO_PROCESSOR_COLOR_SPACE csIn = { }; + csIn.Usage = 0; // Present + csIn.RGB_Range = 0; // Full range + csIn.Nominal_Range = 1; // Full range + csIn.YCbCr_Matrix = 0; // BT.601 + + m_vcontext->VideoProcessorSetStreamAutoProcessingMode(m_vprocessor.ptr(), 0, false); + m_vcontext->VideoProcessorSetOutputColorSpace(m_vprocessor.ptr(), &csOut); + m_vcontext->VideoProcessorSetStreamColorSpace(m_vprocessor.ptr(), 0, &csIn); + blit(m_videoInputView.ptr(), 32, 32); + blit(m_videoInputViewNv12.ptr(), 32, 320); + blit(m_videoInputViewYuy2.ptr(), 32, 608); + + csIn.RGB_Range = 1; // Limited range + csIn.Nominal_Range = 0; // Limited range + m_vcontext->VideoProcessorSetStreamColorSpace(m_vprocessor.ptr(), 0, &csIn); + blit(m_videoInputView.ptr(), 320, 32); + blit(m_videoInputViewNv12.ptr(), 320, 320); + blit(m_videoInputViewYuy2.ptr(), 320, 608); + + // Limited range RGB output color space + csOut.RGB_Range = 1; + csOut.Nominal_Range = 0; + m_vcontext->VideoProcessorSetOutputColorSpace(m_vprocessor.ptr(), &csOut); + + csIn.RGB_Range = 0; // Full range + csIn.Nominal_Range = 1; // Full range + m_vcontext->VideoProcessorSetStreamColorSpace(m_vprocessor.ptr(), 0, &csIn); + blit(m_videoInputView.ptr(), 608, 32); + blit(m_videoInputViewNv12.ptr(), 608, 320); + blit(m_videoInputViewYuy2.ptr(), 608, 608); + + csIn.RGB_Range = 1; // Limited range + csIn.Nominal_Range = 0; // Limited range + m_vcontext->VideoProcessorSetStreamColorSpace(m_vprocessor.ptr(), 0, &csIn); + blit(m_videoInputView.ptr(), 896, 32); + blit(m_videoInputViewNv12.ptr(), 896, 320); + blit(m_videoInputViewYuy2.ptr(), 896, 608); + + m_swapchain->Present(1, 0); + } + + + void blit(ID3D11VideoProcessorInputView* pView, uint32_t x, uint32_t y) { + if (!pView) + return; + + D3D11_VIDEO_PROCESSOR_STREAM stream = { }; + stream.Enable = true; + stream.pInputSurface = pView; + + D3D11_BOX box; + box.left = 0; + box.top = 0; + box.front = 0; + box.right = 256; + box.bottom = 256; + box.back = 1; + + FLOAT red[4] = { 1.0f, 0.0f, 0.0f, 1.0f }; + m_context->ClearRenderTargetView(m_videoOutputRtv.ptr(), red); + m_vcontext->VideoProcessorBlt(m_vprocessor.ptr(), m_videoOutputView.ptr(), 0, 1, &stream); + m_context->CopySubresourceRegion(m_swapImage.ptr(), 0, x, y, 0, m_videoOutput.ptr(), 0, &box); + } + + + void adjustBackBuffer() { + RECT windowRect = { }; + GetClientRect(m_window, &windowRect); + + if (uint32_t(windowRect.right - windowRect.left) != m_windowSizeX + || uint32_t(windowRect.bottom - windowRect.top) != m_windowSizeY) { + m_windowSizeX = windowRect.right - windowRect.left; + m_windowSizeY = windowRect.bottom - windowRect.top; + + m_swapImage = nullptr; + m_swapImageView = nullptr; + + HRESULT hr = m_swapchain->ResizeBuffers(0, + m_windowSizeX, m_windowSizeY, DXGI_FORMAT_UNKNOWN, 0); + + if (FAILED(hr)) { + std::cerr << "Failed to resize swap chain buffer" << std::endl; + return; + } + + if (FAILED(hr = m_swapchain->GetBuffer(0, IID_PPV_ARGS(&m_swapImage)))) { + std::cerr << "Failed to query swap chain image" << std::endl; + return; + } + + if (FAILED(hr = m_device->CreateRenderTargetView(m_swapImage.ptr(), nullptr, &m_swapImageView))) { + std::cerr << "Failed to create render target view" << std::endl; + return; + } + } + } + + operator bool () const { + return m_initialized; + } + +private: + + HWND m_window; + uint32_t m_windowSizeX = 1280; + uint32_t m_windowSizeY = 720; + + Com m_swapchain; + Com m_device; + Com m_context; + Com m_vdevice; + Com m_vcontext; + Com m_venum; + Com m_vprocessor; + Com m_swapImage; + Com m_swapImageView; + Com m_videoOutput; + Com m_videoOutputView; + Com m_videoOutputRtv; + Com m_videoInput; + Com m_videoInputView; + Com m_videoInputNv12; + Com m_videoInputNv12Host; + Com m_videoInputYuy2; + Com m_videoInputViewNv12; + Com m_videoInputViewYuy2; + + bool m_initialized = false; + + static inline uint8_t y_coeff(const uint8_t* rgb, float r, float g, float b) { + float x = (rgb[0] * r + rgb[1] * g + rgb[2] * b) / 255.0f; + return 16 + uint8_t(std::roundf(219.0f * std::clamp(x, 0.0f, 1.0f))); + } + + static inline uint8_t c_coeff(const uint8_t* rgb, float r, float g, float b) { + float x = ((rgb[0] * r + rgb[1] * g + rgb[2] * b) / 255.0f) + 0.5f; + return uint8_t(std::roundf(255.0f * std::clamp(x, 0.0f, 1.0f))); + } + +}; + +LRESULT CALLBACK WindowProc(HWND hWnd, + UINT message, + WPARAM wParam, + LPARAM lParam); + +int WINAPI WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) { + HWND hWnd; + WNDCLASSEXW wc; + ZeroMemory(&wc, sizeof(WNDCLASSEX)); + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = WindowProc; + wc.hInstance = hInstance; + wc.hCursor = LoadCursor(nullptr, IDC_ARROW); + wc.hbrBackground = (HBRUSH)COLOR_WINDOW; + wc.lpszClassName = L"WindowClass1"; + RegisterClassExW(&wc); + + hWnd = CreateWindowExW(0, + L"WindowClass1", + L"Our First Windowed Program", + WS_OVERLAPPEDWINDOW, + 300, 300, + 1280, 720, + nullptr, + nullptr, + hInstance, + nullptr); + ShowWindow(hWnd, nCmdShow); + + MSG msg; + VideoApp app(hInstance, hWnd); + + while (app) { + if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + + if (msg.message == WM_QUIT) + return msg.wParam; + } else { + app.run(); + } + } + + return 0; +} + +LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { + switch (message) { + case WM_CLOSE: + PostQuitMessage(0); + return 0; + } + + return DefWindowProc(hWnd, message, wParam, lParam); +} diff --git a/utils/dxvk-1.10.3/tests/d3d11/video_image.raw b/utils/dxvk-1.10.3/tests/d3d11/video_image.raw new file mode 100644 index 00000000000..7d1b5f38e0e Binary files /dev/null and b/utils/dxvk-1.10.3/tests/d3d11/video_image.raw differ diff --git a/utils/dxvk-1.10.3/tests/d3d9/meson.build b/utils/dxvk-1.10.3/tests/d3d9/meson.build new file mode 100644 index 00000000000..f6af1d9c40d --- /dev/null +++ b/utils/dxvk-1.10.3/tests/d3d9/meson.build @@ -0,0 +1,9 @@ +test_d3d9_deps = [ util_dep, lib_d3d9, lib_d3dcompiler_47 ] + +executable('d3d9-clear'+exe_ext, files('test_d3d9_clear.cpp'), dependencies : test_d3d9_deps, install : true, gui_app : true) +executable('d3d9-buffer'+exe_ext, files('test_d3d9_buffer.cpp'), dependencies : test_d3d9_deps, install : true, gui_app : true) +executable('d3d9-triangle'+exe_ext, files('test_d3d9_triangle.cpp'), dependencies : test_d3d9_deps, install : true, gui_app : true) +executable('d3d9-l6v5u5'+exe_ext, files('test_d3d9_l6v5u5.cpp'), dependencies : test_d3d9_deps, install : true, gui_app : true) +executable('d3d9-nv12'+exe_ext, files('test_d3d9_nv12.cpp'), dependencies : test_d3d9_deps, install : true, gui_app : true) +executable('d3d9-bc-update-surface'+exe_ext, files('test_d3d9_bc_update_surface.cpp'), dependencies : test_d3d9_deps, install : true, gui_app : true) +executable('d3d9-up'+exe_ext, files('test_d3d9_up.cpp'), dependencies : test_d3d9_deps, install : true, gui_app : true) diff --git a/utils/dxvk-1.10.3/tests/d3d9/test_d3d9_bc_update_surface.cpp b/utils/dxvk-1.10.3/tests/d3d9/test_d3d9_bc_update_surface.cpp new file mode 100644 index 00000000000..6be3f29e805 --- /dev/null +++ b/utils/dxvk-1.10.3/tests/d3d9/test_d3d9_bc_update_surface.cpp @@ -0,0 +1,362 @@ +#include + +#include +#include + +#include "../test_utils.h" + +using namespace dxvk; + +struct Extent2D { + uint32_t w, h; +}; + +const std::string g_vertexShaderCode = R"( + +struct VS_INPUT { + float3 Position : POSITION; +}; + +struct VS_OUTPUT { + float4 Position : POSITION; + float2 Texcoord : TEXCOORD0; +}; + +VS_OUTPUT main( VS_INPUT IN ) { + VS_OUTPUT OUT; + OUT.Position = float4(IN.Position, 0.6f); + OUT.Texcoord = IN.Position.xy + float2(0.5, 0.5); + OUT.Texcoord.y = 1.0 - OUT.Texcoord.y; + + return OUT; +} + +)"; + +const std::string g_pixelShaderCode = R"( + +struct VS_OUTPUT { + float4 Position : POSITION; + float2 Texcoord : TEXCOORD0; +}; + +struct PS_OUTPUT { + float4 Colour : COLOR; +}; + +sampler g_frogTex : register( s0 ); + +PS_OUTPUT main( VS_OUTPUT IN ) { + PS_OUTPUT OUT; + + OUT.Colour = float4(1, 0, 0, 1); + + return OUT; +} + + +)"; + +Logger Logger::s_instance("triangle.log"); + +class TriangleApp { + +public: + + TriangleApp(HINSTANCE instance, HWND window) + : m_window(window) { + HRESULT status = Direct3DCreate9Ex(D3D_SDK_VERSION, &m_d3d); + + if (FAILED(status)) + throw DxvkError("Failed to create D3D9 interface"); + + UINT adapter = D3DADAPTER_DEFAULT; + + D3DADAPTER_IDENTIFIER9 adapterId; + m_d3d->GetAdapterIdentifier(adapter, 0, &adapterId); + + Logger::info(str::format("Using adapter: ", adapterId.Description)); + + D3DPRESENT_PARAMETERS params; + getPresentParams(params); + + status = m_d3d->CreateDeviceEx( + adapter, + D3DDEVTYPE_HAL, + m_window, + D3DCREATE_HARDWARE_VERTEXPROCESSING, + ¶ms, + nullptr, + &m_device); + + if (FAILED(status)) + throw DxvkError("Failed to create D3D9 device"); + + + // Vertex Shader + { + Com blob; + + status = D3DCompile( + g_vertexShaderCode.data(), + g_vertexShaderCode.length(), + nullptr, nullptr, nullptr, + "main", + "vs_2_0", + 0, 0, &blob, + nullptr); + + if (FAILED(status)) + throw DxvkError("Failed to compile vertex shader"); + + status = m_device->CreateVertexShader(reinterpret_cast(blob->GetBufferPointer()), &m_vs); + + if (FAILED(status)) + throw DxvkError("Failed to create vertex shader"); + } + + // Pixel Shader + { + Com blob; + + status = D3DCompile( + g_pixelShaderCode.data(), + g_pixelShaderCode.length(), + nullptr, nullptr, nullptr, + "main", + "ps_3_0", + 0, 0, &blob, + nullptr); + + if (FAILED(status)) + throw DxvkError("Failed to compile pixel shader"); + + status = m_device->CreatePixelShader(reinterpret_cast(blob->GetBufferPointer()), &m_ps); + + if (FAILED(status)) + throw DxvkError("Failed to create pixel shader"); + } + + m_device->SetVertexShader(m_vs.ptr()); + m_device->SetPixelShader(m_ps.ptr()); + + m_device->AddRef(); + + + std::array vertices = { + 0.0f, 0.5f, 0.0f, + 0.5f, -0.5f, 0.0f, + -0.5f, -0.5f, 0.0f, + }; + + const size_t vbSize = vertices.size() * sizeof(float); + + status = m_device->CreateVertexBuffer(vbSize, 0, 0, D3DPOOL_DEFAULT, &m_vb, nullptr); + if (FAILED(status)) + throw DxvkError("Failed to create vertex buffer"); + + void* data = nullptr; + status = m_vb->Lock(0, 0, &data, 0); + if (FAILED(status)) + throw DxvkError("Failed to lock vertex buffer"); + + std::memcpy(data, vertices.data(), vbSize); + + status = m_vb->Unlock(); + if (FAILED(status)) + throw DxvkError("Failed to unlock vertex buffer"); + + m_device->SetStreamSource(0, m_vb.ptr(), 0, 3 * sizeof(float)); + + std::array elements; + + elements[0].Method = 0; + elements[0].Offset = 0; + elements[0].Stream = 0; + elements[0].Type = D3DDECLTYPE_FLOAT3; + elements[0].Usage = D3DDECLUSAGE_POSITION; + elements[0].UsageIndex = 0; + + elements[1] = D3DDECL_END(); + + HRESULT result = m_device->CreateVertexDeclaration(elements.data(), &m_decl); + if (FAILED(result)) + throw DxvkError("Failed to create vertex decl"); + + m_device->SetVertexDeclaration(m_decl.ptr()); + + const uint32_t imageSize = 8; + + Com texDefault; + Com texDefaultSurf; + status = m_device->CreateTexture(imageSize, imageSize, 4, 0, D3DFMT_DXT1, D3DPOOL_DEFAULT, &texDefault, nullptr); + status = texDefault->GetSurfaceLevel(2, &texDefaultSurf); + + Com texSysmem; + Com texSysmemSurf; + status = m_device->CreateTexture(imageSize, imageSize, 4, 0, D3DFMT_DXT1, D3DPOOL_SYSTEMMEM, &texSysmem, nullptr); + status = texSysmem->GetSurfaceLevel(2, &texSysmemSurf); + + D3DLOCKED_RECT rect = {}; + status = texSysmemSurf->LockRect(&rect, nullptr, 0); + std::memset(rect.pBits, 0xF0, 2 * rect.Pitch); + status = texSysmemSurf->UnlockRect(); + + // 1 returns invalid call + // 2 succeeds + RECT sourceRect = { 0, 0, 2, 2 }; + POINT destPoint = { 0, 0 }; + status = m_device->UpdateSurface(texSysmemSurf.ptr(), &sourceRect, texDefaultSurf.ptr(), &destPoint); + } + + void run() { + this->adjustBackBuffer(); + + m_device->BeginScene(); + + m_device->Clear( + 0, + nullptr, + D3DCLEAR_TARGET, + D3DCOLOR_RGBA(44, 62, 80, 0), + 0, + 0); + + m_device->Clear( + 0, + nullptr, + D3DCLEAR_ZBUFFER, + 0, + 0.5f, + 0); + + m_device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1); + + m_device->EndScene(); + + m_device->PresentEx( + nullptr, + nullptr, + nullptr, + nullptr, + 0); + } + + void adjustBackBuffer() { + RECT windowRect = { 0, 0, 1024, 600 }; + GetClientRect(m_window, &windowRect); + + Extent2D newSize = { + static_cast(windowRect.right - windowRect.left), + static_cast(windowRect.bottom - windowRect.top), + }; + + if (m_windowSize.w != newSize.w + || m_windowSize.h != newSize.h) { + m_windowSize = newSize; + + D3DPRESENT_PARAMETERS params; + getPresentParams(params); + HRESULT status = m_device->ResetEx(¶ms, nullptr); + + if (FAILED(status)) + throw DxvkError("Device reset failed"); + } + } + + void getPresentParams(D3DPRESENT_PARAMETERS& params) { + params.AutoDepthStencilFormat = D3DFMT_UNKNOWN; + params.BackBufferCount = 1; + params.BackBufferFormat = D3DFMT_X8R8G8B8; + params.BackBufferWidth = m_windowSize.w; + params.BackBufferHeight = m_windowSize.h; + params.EnableAutoDepthStencil = 0; + params.Flags = 0; + params.FullScreen_RefreshRateInHz = 0; + params.hDeviceWindow = m_window; + params.MultiSampleQuality = 0; + params.MultiSampleType = D3DMULTISAMPLE_NONE; + params.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + params.SwapEffect = D3DSWAPEFFECT_DISCARD; + params.Windowed = TRUE; + } + +private: + + HWND m_window; + Extent2D m_windowSize = { 1024, 600 }; + + Com m_d3d; + Com m_device; + + Com m_vs; + Com m_ps; + Com m_vb; + Com m_decl; + +}; + +LRESULT CALLBACK WindowProc(HWND hWnd, + UINT message, + WPARAM wParam, + LPARAM lParam); + +int WINAPI WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) { + HWND hWnd; + WNDCLASSEXW wc; + ZeroMemory(&wc, sizeof(WNDCLASSEX)); + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = WindowProc; + wc.hInstance = hInstance; + wc.hCursor = LoadCursor(nullptr, IDC_ARROW); + wc.hbrBackground = (HBRUSH)COLOR_WINDOW; + wc.lpszClassName = L"WindowClass1"; + RegisterClassExW(&wc); + + hWnd = CreateWindowExW(0, + L"WindowClass1", + L"Our First Windowed Program", + WS_OVERLAPPEDWINDOW, + 300, 300, + 640, 480, + nullptr, + nullptr, + hInstance, + nullptr); + ShowWindow(hWnd, nCmdShow); + + MSG msg; + + try { + TriangleApp app(hInstance, hWnd); + + while (true) { + if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + + if (msg.message == WM_QUIT) + return msg.wParam; + } else { + app.run(); + } + } + } catch (const dxvk::DxvkError& e) { + std::cerr << e.message() << std::endl; + return msg.wParam; + } +} + +LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { + switch (message) { + case WM_CLOSE: + PostQuitMessage(0); + return 0; + } + + return DefWindowProc(hWnd, message, wParam, lParam); +} diff --git a/utils/dxvk-1.10.3/tests/d3d9/test_d3d9_buffer.cpp b/utils/dxvk-1.10.3/tests/d3d9/test_d3d9_buffer.cpp new file mode 100644 index 00000000000..f27c7b35035 --- /dev/null +++ b/utils/dxvk-1.10.3/tests/d3d9/test_d3d9_buffer.cpp @@ -0,0 +1,220 @@ +#include +#include + +#include "../test_utils.h" + +using namespace dxvk; + +struct Extent2D { + uint32_t w, h; +}; + +DWORD g_UsagePermuatations[] = { + 0, + D3DUSAGE_DYNAMIC, + D3DUSAGE_WRITEONLY, + D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, +}; + +DWORD g_MapFlagPermutations[] = { + 0, + D3DLOCK_DISCARD, + D3DLOCK_DONOTWAIT, + D3DLOCK_NOOVERWRITE +}; + +class BufferApp { + +public: + + BufferApp(HINSTANCE instance, HWND window) + : m_window(window) { + HRESULT status = Direct3DCreate9Ex(D3D_SDK_VERSION, &m_d3d); + + if (FAILED(status)) + throw DxvkError("Failed to create D3D9 interface"); + + D3DPRESENT_PARAMETERS params; + getPresentParams(params); + + status = m_d3d->CreateDeviceEx( + D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, + m_window, + D3DCREATE_HARDWARE_VERTEXPROCESSING, + ¶ms, + nullptr, + &m_device); + + if (FAILED(status)) + throw DxvkError("Failed to create D3D9 device"); + + uint8_t* data = new uint8_t[512]; + std::memset(data, 0xFC, 512); + + for (uint32_t i = 0; i < ARRAYSIZE(g_UsagePermuatations); i++) { + for (uint32_t j = 0; j < ARRAYSIZE(g_MapFlagPermutations); j++) { + testBuffer(data, g_UsagePermuatations[i], g_MapFlagPermutations[j]); + } + } + + delete[] data; + } + + void testBuffer(uint8_t* data, DWORD usage, DWORD mapFlags) { + Com buffer; + HRESULT status = m_device->CreateVertexBuffer(512, usage, 0, D3DPOOL_DEFAULT, &buffer, nullptr); + + if (FAILED(status)) + throw DxvkError("Failed to create buffer"); + + void* bufferMem = nullptr; + status = buffer->Lock(0, 0, &bufferMem, mapFlags); + + if (FAILED(status) || bufferMem == nullptr) + throw DxvkError("Failed to lock buffer"); + + std::memcpy(bufferMem, data, 512); + + status = buffer->Unlock(); + + if (FAILED(status)) + throw DxvkError("Failed to unlock buffer"); + } + + void run() { + this->adjustBackBuffer(); + + m_device->BeginScene(); + + m_device->Clear( + 0, + nullptr, + D3DCLEAR_TARGET, + D3DCOLOR_RGBA(255, 50, 139, 0), + 0.0f, + 0); + + m_device->EndScene(); + + m_device->PresentEx( + nullptr, + nullptr, + nullptr, + nullptr, + 0); + } + + void adjustBackBuffer() { + RECT windowRect = { 0, 0, 1024, 600 }; + GetClientRect(m_window, &windowRect); + + Extent2D newSize = { + static_cast(windowRect.right - windowRect.left), + static_cast(windowRect.bottom - windowRect.top), + }; + + if (m_windowSize.w != newSize.w + || m_windowSize.h != newSize.h) { + m_windowSize = newSize; + + D3DPRESENT_PARAMETERS params; + getPresentParams(params); + HRESULT status = m_device->ResetEx(¶ms, nullptr); + + if (FAILED(status)) + throw DxvkError("Device reset failed"); + } + } + + void getPresentParams(D3DPRESENT_PARAMETERS& params) { + params.AutoDepthStencilFormat = D3DFMT_UNKNOWN; + params.BackBufferCount = 1; + params.BackBufferFormat = D3DFMT_X8R8G8B8; + params.BackBufferWidth = m_windowSize.w; + params.BackBufferHeight = m_windowSize.h; + params.EnableAutoDepthStencil = FALSE; + params.Flags = 0; + params.FullScreen_RefreshRateInHz = 0; + params.hDeviceWindow = m_window; + params.MultiSampleQuality = 0; + params.MultiSampleType = D3DMULTISAMPLE_NONE; + params.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + params.SwapEffect = D3DSWAPEFFECT_DISCARD; + params.Windowed = TRUE; + } + +private: + + HWND m_window; + Extent2D m_windowSize = { 1024, 600 }; + + Com m_d3d; + Com m_device; + +}; + +LRESULT CALLBACK WindowProc(HWND hWnd, + UINT message, + WPARAM wParam, + LPARAM lParam); + +int WINAPI WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) { + HWND hWnd; + WNDCLASSEXW wc; + ZeroMemory(&wc, sizeof(WNDCLASSEX)); + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = WindowProc; + wc.hInstance = hInstance; + wc.hCursor = LoadCursor(nullptr, IDC_ARROW); + wc.hbrBackground = (HBRUSH)COLOR_WINDOW; + wc.lpszClassName = L"WindowClass1"; + RegisterClassExW(&wc); + + hWnd = CreateWindowExW(0, + L"WindowClass1", + L"Our First Windowed Program", + WS_OVERLAPPEDWINDOW, + 300, 300, + 640, 480, + nullptr, + nullptr, + hInstance, + nullptr); + ShowWindow(hWnd, nCmdShow); + + MSG msg; + + try { + BufferApp app(hInstance, hWnd); + + while (true) { + if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + + if (msg.message == WM_QUIT) + return msg.wParam; + } else { + app.run(); + } + } + } catch (const dxvk::DxvkError& e) { + std::cerr << e.message() << std::endl; + return msg.wParam; + } +} + +LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { + switch (message) { + case WM_CLOSE: + PostQuitMessage(0); + return 0; + } + + return DefWindowProc(hWnd, message, wParam, lParam); +} diff --git a/utils/dxvk-1.10.3/tests/d3d9/test_d3d9_clear.cpp b/utils/dxvk-1.10.3/tests/d3d9/test_d3d9_clear.cpp new file mode 100644 index 00000000000..9715333f1f2 --- /dev/null +++ b/utils/dxvk-1.10.3/tests/d3d9/test_d3d9_clear.cpp @@ -0,0 +1,173 @@ +#include + +#include "../test_utils.h" + +using namespace dxvk; + +struct Extent2D { + uint32_t w, h; +}; + +class ClearApp { + +public: + + ClearApp(HINSTANCE instance, HWND window) + : m_window(window) { + HRESULT status = Direct3DCreate9Ex(D3D_SDK_VERSION, &m_d3d); + + if (FAILED(status)) + throw DxvkError("Failed to create D3D9 interface"); + + D3DPRESENT_PARAMETERS params; + getPresentParams(params); + + status = m_d3d->CreateDeviceEx( + D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, + m_window, + D3DCREATE_HARDWARE_VERTEXPROCESSING, + ¶ms, + nullptr, + &m_device); + + if (FAILED(status)) + throw DxvkError("Failed to create D3D9 device"); + } + + void run() { + this->adjustBackBuffer(); + + m_device->BeginScene(); + + m_device->Clear( + 0, + nullptr, + D3DCLEAR_TARGET, + D3DCOLOR_RGBA(255, 0, 0, 0), + 0.0f, + 0); + + m_device->EndScene(); + + m_device->PresentEx( + nullptr, + nullptr, + nullptr, + nullptr, + 0); + } + + void adjustBackBuffer() { + RECT windowRect = { 0, 0, 1024, 600 }; + GetClientRect(m_window, &windowRect); + + Extent2D newSize = { + static_cast(windowRect.right - windowRect.left), + static_cast(windowRect.bottom - windowRect.top), + }; + + if (m_windowSize.w != newSize.w + || m_windowSize.h != newSize.h) { + m_windowSize = newSize; + + D3DPRESENT_PARAMETERS params; + getPresentParams(params); + HRESULT status = m_device->ResetEx(¶ms, nullptr); + + if (FAILED(status)) + throw DxvkError("Device reset failed"); + } + } + + void getPresentParams(D3DPRESENT_PARAMETERS& params) { + params.AutoDepthStencilFormat = D3DFMT_UNKNOWN; + params.BackBufferCount = 1; + params.BackBufferFormat = D3DFMT_X8R8G8B8; + params.BackBufferWidth = m_windowSize.w; + params.BackBufferHeight = m_windowSize.h; + params.EnableAutoDepthStencil = FALSE; + params.Flags = 0; + params.FullScreen_RefreshRateInHz = 0; + params.hDeviceWindow = m_window; + params.MultiSampleQuality = 0; + params.MultiSampleType = D3DMULTISAMPLE_NONE; + params.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + params.SwapEffect = D3DSWAPEFFECT_DISCARD; + params.Windowed = TRUE; + } + +private: + + HWND m_window; + Extent2D m_windowSize = { 1024, 600 }; + + Com m_d3d; + Com m_device; + +}; + +LRESULT CALLBACK WindowProc(HWND hWnd, + UINT message, + WPARAM wParam, + LPARAM lParam); + +int WINAPI WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) { + HWND hWnd; + WNDCLASSEXW wc; + ZeroMemory(&wc, sizeof(WNDCLASSEX)); + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = WindowProc; + wc.hInstance = hInstance; + wc.hCursor = LoadCursor(nullptr, IDC_ARROW); + wc.hbrBackground = (HBRUSH)COLOR_WINDOW; + wc.lpszClassName = L"WindowClass1"; + RegisterClassExW(&wc); + + hWnd = CreateWindowExW(0, + L"WindowClass1", + L"Our First Windowed Program", + WS_OVERLAPPEDWINDOW, + 300, 300, + 640, 480, + nullptr, + nullptr, + hInstance, + nullptr); + ShowWindow(hWnd, nCmdShow); + + MSG msg; + + try { + ClearApp app(hInstance, hWnd); + + while (true) { + if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + + if (msg.message == WM_QUIT) + return msg.wParam; + } else { + app.run(); + } + } + } catch (const dxvk::DxvkError& e) { + std::cerr << e.message() << std::endl; + return msg.wParam; + } +} + +LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { + switch (message) { + case WM_CLOSE: + PostQuitMessage(0); + return 0; + } + + return DefWindowProc(hWnd, message, wParam, lParam); +} diff --git a/utils/dxvk-1.10.3/tests/d3d9/test_d3d9_l6v5u5.cpp b/utils/dxvk-1.10.3/tests/d3d9/test_d3d9_l6v5u5.cpp new file mode 100644 index 00000000000..09465278c33 --- /dev/null +++ b/utils/dxvk-1.10.3/tests/d3d9/test_d3d9_l6v5u5.cpp @@ -0,0 +1,361 @@ +#include + +#include +#include + +#include "../test_utils.h" + +using namespace dxvk; + +struct Extent2D { + uint32_t w, h; +}; + +const std::string g_vertexShaderCode = R"( + +struct VS_INPUT { + float3 Position : POSITION; +}; + +struct VS_OUTPUT { + float4 Position : POSITION; +}; + +VS_OUTPUT main( VS_INPUT IN ) { + VS_OUTPUT OUT; + OUT.Position = float4(IN.Position, 1.0f); + + return OUT; +} + +)"; + +const std::string g_pixelShaderCode = R"( + +struct VS_OUTPUT { + float4 Position : POSITION; +}; + +struct PS_OUTPUT { + float4 Colour : COLOR; +}; + +sampler g_tex : register( s0 ); + +PS_OUTPUT main( VS_OUTPUT IN ) { + PS_OUTPUT OUT; + + float4 color = float4(tex2D(g_tex, float2(0.5, 0.5)).rgb, 1.0f); + color.r = -color.r; + color.g = -color.g; + OUT.Colour = color; + + + return OUT; +} + + +)"; + +class TriangleApp { + +public: + + TriangleApp(HINSTANCE instance, HWND window) + : m_window(window) { + HRESULT status = Direct3DCreate9Ex(D3D_SDK_VERSION, &m_d3d); + + if (FAILED(status)) + throw DxvkError("Failed to create D3D9 interface"); + + D3DPRESENT_PARAMETERS params; + getPresentParams(params); + + status = m_d3d->CreateDeviceEx( + D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, + m_window, + D3DCREATE_HARDWARE_VERTEXPROCESSING, + ¶ms, + nullptr, + &m_device); + + if (FAILED(status)) + throw DxvkError("Failed to create D3D9 device"); + + // Vertex Shader + { + Com blob; + + status = D3DCompile( + g_vertexShaderCode.data(), + g_vertexShaderCode.length(), + nullptr, nullptr, nullptr, + "main", + "vs_2_0", + 0, 0, &blob, + nullptr); + + if (FAILED(status)) + throw DxvkError("Failed to compile vertex shader"); + + status = m_device->CreateVertexShader(reinterpret_cast(blob->GetBufferPointer()), &m_vs); + + if (FAILED(status)) + throw DxvkError("Failed to create vertex shader"); + } + + // Pixel Shader + { + Com blob; + + status = D3DCompile( + g_pixelShaderCode.data(), + g_pixelShaderCode.length(), + nullptr, nullptr, nullptr, + "main", + "ps_2_0", + 0, 0, &blob, + nullptr); + + if (FAILED(status)) + throw DxvkError("Failed to compile pixel shader"); + + status = m_device->CreatePixelShader(reinterpret_cast(blob->GetBufferPointer()), &m_ps); + + if (FAILED(status)) + throw DxvkError("Failed to create pixel shader"); + } + + m_device->SetVertexShader(m_vs.ptr()); + m_device->SetPixelShader(m_ps.ptr()); + + std::array vertices = { + 0.0f, 0.5f, 0.0f, + 0.5f, -0.5f, 0.0f, + -0.5f, -0.5f, 0.0f, + }; + + const size_t vbSize = vertices.size() * sizeof(float); + + status = m_device->CreateVertexBuffer(vbSize, 0, 0, D3DPOOL_DEFAULT, &m_vb, nullptr); + if (FAILED(status)) + throw DxvkError("Failed to create vertex buffer"); + + void* data = nullptr; + status = m_vb->Lock(0, 0, &data, 0); + if (FAILED(status)) + throw DxvkError("Failed to lock vertex buffer"); + + std::memcpy(data, vertices.data(), vbSize); + + status = m_vb->Unlock(); + if (FAILED(status)) + throw DxvkError("Failed to unlock vertex buffer"); + + m_device->SetStreamSource(0, m_vb.ptr(), 0, 3 * sizeof(float)); + + std::array elements; + + elements[0].Method = 0; + elements[0].Offset = 0; + elements[0].Stream = 0; + elements[0].Type = D3DDECLTYPE_FLOAT3; + elements[0].Usage = D3DDECLUSAGE_POSITION; + elements[0].UsageIndex = 0; + + elements[1] = D3DDECL_END(); + + HRESULT result = m_device->CreateVertexDeclaration(elements.data(), &m_decl); + if (FAILED(result)) + throw DxvkError("Failed to create vertex decl"); + + m_device->SetVertexDeclaration(m_decl.ptr()); + + // The actual texture we want to test... + + Com texture; + status = m_device->CreateTexture(64, 64, 1, D3DUSAGE_DYNAMIC, D3DFMT_L6V5U5, D3DPOOL_DEFAULT, &texture, nullptr); + + D3DLOCKED_RECT rect; + status = texture->LockRect(0, &rect, nullptr, 0); + + uint16_t* texData = reinterpret_cast(rect.pBits); + for (uint32_t i = 0; i < (rect.Pitch * 64) / sizeof(uint16_t); i++) { + // -> U -1, V -1, L 1 + texData[i] = 0b1111111000010000; + // -> U 1, V 1, L 1 + //texData[i] = 0b1111110111101111; + } + + status = texture->UnlockRect(0); + + status = m_device->SetTexture(0, texture.ptr()); + + ///////////// + + /*Com texture2; + status = m_device->CreateTexture(64, 64, 1, 0, D3DFMT_A8B8G8R8, D3DPOOL_MANAGED, &texture2, nullptr); + status = texture2->LockRect(0, &rect, nullptr, 0); + + uint32_t* texData2 = reinterpret_cast(rect.pBits); + for (uint32_t i = 0; i < (rect.Pitch * 64) / sizeof(uint32_t); i++) { + texData2[i] = 0b00000000000000000000000011111111; + } + + status = texture2->UnlockRect(0); + + status = m_device->SetTexture(0, texture2.ptr());*/ + } + + void run() { + this->adjustBackBuffer(); + + m_device->BeginScene(); + + m_device->Clear( + 0, + nullptr, + D3DCLEAR_TARGET, + D3DCOLOR_RGBA(44, 62, 80, 0), + 0, + 0); + + m_device->Clear( + 0, + nullptr, + D3DCLEAR_ZBUFFER, + 0, + 0.5f, + 0); + + m_device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1); + + m_device->EndScene(); + + m_device->PresentEx( + nullptr, + nullptr, + nullptr, + nullptr, + 0); + } + + void adjustBackBuffer() { + RECT windowRect = { 0, 0, 1024, 600 }; + GetClientRect(m_window, &windowRect); + + Extent2D newSize = { + static_cast(windowRect.right - windowRect.left), + static_cast(windowRect.bottom - windowRect.top), + }; + + if (m_windowSize.w != newSize.w + || m_windowSize.h != newSize.h) { + m_windowSize = newSize; + + D3DPRESENT_PARAMETERS params; + getPresentParams(params); + HRESULT status = m_device->ResetEx(¶ms, nullptr); + + if (FAILED(status)) + throw DxvkError("Device reset failed"); + } + } + + void getPresentParams(D3DPRESENT_PARAMETERS& params) { + params.AutoDepthStencilFormat = D3DFMT_UNKNOWN; + params.BackBufferCount = 1; + params.BackBufferFormat = D3DFMT_X8R8G8B8; + params.BackBufferWidth = m_windowSize.w; + params.BackBufferHeight = m_windowSize.h; + params.EnableAutoDepthStencil = 0; + params.Flags = 0; + params.FullScreen_RefreshRateInHz = 0; + params.hDeviceWindow = m_window; + params.MultiSampleQuality = 0; + params.MultiSampleType = D3DMULTISAMPLE_NONE; + params.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + params.SwapEffect = D3DSWAPEFFECT_DISCARD; + params.Windowed = TRUE; + } + +private: + + HWND m_window; + Extent2D m_windowSize = { 1024, 600 }; + + Com m_d3d; + Com m_device; + + Com m_vs; + Com m_ps; + Com m_vb; + Com m_decl; + +}; + +LRESULT CALLBACK WindowProc(HWND hWnd, + UINT message, + WPARAM wParam, + LPARAM lParam); + +int WINAPI WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) { + HWND hWnd; + WNDCLASSEXW wc; + ZeroMemory(&wc, sizeof(WNDCLASSEX)); + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = WindowProc; + wc.hInstance = hInstance; + wc.hCursor = LoadCursor(nullptr, IDC_ARROW); + wc.hbrBackground = (HBRUSH)COLOR_WINDOW; + wc.lpszClassName = L"WindowClass1"; + RegisterClassExW(&wc); + + hWnd = CreateWindowExW(0, + L"WindowClass1", + L"Our First Windowed Program", + WS_OVERLAPPEDWINDOW, + 300, 300, + 640, 480, + nullptr, + nullptr, + hInstance, + nullptr); + ShowWindow(hWnd, nCmdShow); + + MSG msg; + + try { + TriangleApp app(hInstance, hWnd); + + while (true) { + if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + + if (msg.message == WM_QUIT) + return msg.wParam; + } else { + app.run(); + } + } + } catch (const dxvk::DxvkError& e) { + std::cerr << e.message() << std::endl; + return msg.wParam; + } +} + +LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { + switch (message) { + case WM_CLOSE: + PostQuitMessage(0); + return 0; + } + + return DefWindowProc(hWnd, message, wParam, lParam); +} diff --git a/utils/dxvk-1.10.3/tests/d3d9/test_d3d9_nv12.cpp b/utils/dxvk-1.10.3/tests/d3d9/test_d3d9_nv12.cpp new file mode 100644 index 00000000000..6d4f46175ed --- /dev/null +++ b/utils/dxvk-1.10.3/tests/d3d9/test_d3d9_nv12.cpp @@ -0,0 +1,370 @@ +#include + +#include +#include + +#include "../test_utils.h" +#include "test_d3d9_nv12.yuv.h" + +using namespace dxvk; + +struct Extent2D { + uint32_t w, h; +}; + +const std::string g_vertexShaderCode = R"( + +struct VS_INPUT { + float3 Position : POSITION; +}; + +struct VS_OUTPUT { + float4 Position : POSITION; + float2 Texcoord : TEXCOORD0; +}; + +VS_OUTPUT main( VS_INPUT IN ) { + VS_OUTPUT OUT; + OUT.Position = float4(IN.Position, 0.6f); + OUT.Texcoord = IN.Position.xy + float2(0.5, 0.5); + OUT.Texcoord.y = 1.0 - OUT.Texcoord.y; + + return OUT; +} + +)"; + +const std::string g_pixelShaderCode = R"( + +struct VS_OUTPUT { + float4 Position : POSITION; + float2 Texcoord : TEXCOORD0; +}; + +struct PS_OUTPUT { + float4 Colour : COLOR; +}; + +sampler g_frogTex : register( s0 ); + +PS_OUTPUT main( VS_OUTPUT IN ) { + PS_OUTPUT OUT; + + OUT.Colour = tex2D(g_frogTex, IN.Texcoord); + + return OUT; +} + + +)"; + +Logger Logger::s_instance("triangle.log"); + +class TriangleApp { + +public: + + TriangleApp(HINSTANCE instance, HWND window) + : m_window(window) { + HRESULT status = Direct3DCreate9Ex(D3D_SDK_VERSION, &m_d3d); + + if (FAILED(status)) + throw DxvkError("Failed to create D3D9 interface"); + + UINT adapter = D3DADAPTER_DEFAULT; + + D3DADAPTER_IDENTIFIER9 adapterId; + m_d3d->GetAdapterIdentifier(adapter, 0, &adapterId); + + Logger::info(str::format("Using adapter: ", adapterId.Description)); + + D3DPRESENT_PARAMETERS params; + getPresentParams(params); + + status = m_d3d->CreateDeviceEx( + adapter, + D3DDEVTYPE_HAL, + m_window, + D3DCREATE_HARDWARE_VERTEXPROCESSING, + ¶ms, + nullptr, + &m_device); + + if (FAILED(status)) + throw DxvkError("Failed to create D3D9 device"); + + + // Vertex Shader + { + Com blob; + + status = D3DCompile( + g_vertexShaderCode.data(), + g_vertexShaderCode.length(), + nullptr, nullptr, nullptr, + "main", + "vs_2_0", + 0, 0, &blob, + nullptr); + + if (FAILED(status)) + throw DxvkError("Failed to compile vertex shader"); + + status = m_device->CreateVertexShader(reinterpret_cast(blob->GetBufferPointer()), &m_vs); + + if (FAILED(status)) + throw DxvkError("Failed to create vertex shader"); + } + + // Pixel Shader + { + Com blob; + + status = D3DCompile( + g_pixelShaderCode.data(), + g_pixelShaderCode.length(), + nullptr, nullptr, nullptr, + "main", + "ps_2_0", + 0, 0, &blob, + nullptr); + + if (FAILED(status)) + throw DxvkError("Failed to compile pixel shader"); + + status = m_device->CreatePixelShader(reinterpret_cast(blob->GetBufferPointer()), &m_ps); + + if (FAILED(status)) + throw DxvkError("Failed to create pixel shader"); + } + + m_device->SetVertexShader(m_vs.ptr()); + m_device->SetPixelShader(m_ps.ptr()); + + m_device->AddRef(); + + + std::array vertices = { + 0.0f, 0.5f, 0.0f, + 0.5f, -0.5f, 0.0f, + -0.5f, -0.5f, 0.0f, + }; + + const size_t vbSize = vertices.size() * sizeof(float); + + status = m_device->CreateVertexBuffer(vbSize, 0, 0, D3DPOOL_DEFAULT, &m_vb, nullptr); + if (FAILED(status)) + throw DxvkError("Failed to create vertex buffer"); + + void* data = nullptr; + status = m_vb->Lock(0, 0, &data, 0); + if (FAILED(status)) + throw DxvkError("Failed to lock vertex buffer"); + + std::memcpy(data, vertices.data(), vbSize); + + status = m_vb->Unlock(); + if (FAILED(status)) + throw DxvkError("Failed to unlock vertex buffer"); + + m_device->SetStreamSource(0, m_vb.ptr(), 0, 3 * sizeof(float)); + + std::array elements; + + elements[0].Method = 0; + elements[0].Offset = 0; + elements[0].Stream = 0; + elements[0].Type = D3DDECLTYPE_FLOAT3; + elements[0].Usage = D3DDECLUSAGE_POSITION; + elements[0].UsageIndex = 0; + + elements[1] = D3DDECL_END(); + + HRESULT result = m_device->CreateVertexDeclaration(elements.data(), &m_decl); + if (FAILED(result)) + throw DxvkError("Failed to create vertex decl"); + + m_device->SetVertexDeclaration(m_decl.ptr()); + + const uint32_t imageSize = 320; + + Com texture; + Com texSurf; + status = m_device->CreateTexture(imageSize, imageSize, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, nullptr); + status = texture->GetSurfaceLevel(0, &texSurf); + + Com nv12Surf; + status = m_device->CreateOffscreenPlainSurface(imageSize, imageSize, (D3DFORMAT)MAKEFOURCC('N', 'V', '1', '2'), D3DPOOL_DEFAULT, &nv12Surf, nullptr); + D3DLOCKED_RECT rect; + nv12Surf->LockRect(&rect, nullptr, 0); + char* dst = (char*)rect.pBits; + char* src = (char*)test_d3d9_nv12_yuv; + for (uint32_t i = 0; i < imageSize; i++) + { + std::memcpy(dst, src, imageSize); + src += imageSize; + dst += rect.Pitch; + } + + for (uint32_t i = 0; i < imageSize / 2; i++) + { + std::memcpy(dst, src, imageSize); + src += imageSize; + dst += rect.Pitch; + } + nv12Surf->UnlockRect(); + status = m_device->StretchRect(nv12Surf.ptr(), nullptr, texSurf.ptr(), nullptr, D3DTEXF_LINEAR); + m_device->SetTexture(0, texture.ptr()); + } + + void run() { + this->adjustBackBuffer(); + + m_device->BeginScene(); + + m_device->Clear( + 0, + nullptr, + D3DCLEAR_TARGET, + D3DCOLOR_RGBA(44, 62, 80, 0), + 0, + 0); + + m_device->Clear( + 0, + nullptr, + D3DCLEAR_ZBUFFER, + 0, + 0.5f, + 0); + + m_device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1); + + m_device->EndScene(); + + m_device->PresentEx( + nullptr, + nullptr, + nullptr, + nullptr, + 0); + } + + void adjustBackBuffer() { + RECT windowRect = { 0, 0, 1024, 600 }; + GetClientRect(m_window, &windowRect); + + Extent2D newSize = { + static_cast(windowRect.right - windowRect.left), + static_cast(windowRect.bottom - windowRect.top), + }; + + if (m_windowSize.w != newSize.w + || m_windowSize.h != newSize.h) { + m_windowSize = newSize; + + D3DPRESENT_PARAMETERS params; + getPresentParams(params); + HRESULT status = m_device->ResetEx(¶ms, nullptr); + + if (FAILED(status)) + throw DxvkError("Device reset failed"); + } + } + + void getPresentParams(D3DPRESENT_PARAMETERS& params) { + params.AutoDepthStencilFormat = D3DFMT_UNKNOWN; + params.BackBufferCount = 1; + params.BackBufferFormat = D3DFMT_X8R8G8B8; + params.BackBufferWidth = m_windowSize.w; + params.BackBufferHeight = m_windowSize.h; + params.EnableAutoDepthStencil = 0; + params.Flags = 0; + params.FullScreen_RefreshRateInHz = 0; + params.hDeviceWindow = m_window; + params.MultiSampleQuality = 0; + params.MultiSampleType = D3DMULTISAMPLE_NONE; + params.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + params.SwapEffect = D3DSWAPEFFECT_DISCARD; + params.Windowed = TRUE; + } + +private: + + HWND m_window; + Extent2D m_windowSize = { 1024, 600 }; + + Com m_d3d; + Com m_device; + + Com m_vs; + Com m_ps; + Com m_vb; + Com m_decl; + +}; + +LRESULT CALLBACK WindowProc(HWND hWnd, + UINT message, + WPARAM wParam, + LPARAM lParam); + +int WINAPI WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) { + HWND hWnd; + WNDCLASSEXW wc; + ZeroMemory(&wc, sizeof(WNDCLASSEX)); + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = WindowProc; + wc.hInstance = hInstance; + wc.hCursor = LoadCursor(nullptr, IDC_ARROW); + wc.hbrBackground = (HBRUSH)COLOR_WINDOW; + wc.lpszClassName = L"WindowClass1"; + RegisterClassExW(&wc); + + hWnd = CreateWindowExW(0, + L"WindowClass1", + L"Our First Windowed Program", + WS_OVERLAPPEDWINDOW, + 300, 300, + 640, 480, + nullptr, + nullptr, + hInstance, + nullptr); + ShowWindow(hWnd, nCmdShow); + + MSG msg; + + try { + TriangleApp app(hInstance, hWnd); + + while (true) { + if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + + if (msg.message == WM_QUIT) + return msg.wParam; + } else { + app.run(); + } + } + } catch (const dxvk::DxvkError& e) { + std::cerr << e.message() << std::endl; + return msg.wParam; + } +} + +LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { + switch (message) { + case WM_CLOSE: + PostQuitMessage(0); + return 0; + } + + return DefWindowProc(hWnd, message, wParam, lParam); +} diff --git a/utils/dxvk-1.10.3/tests/d3d9/test_d3d9_nv12.yuv.h b/utils/dxvk-1.10.3/tests/d3d9/test_d3d9_nv12.yuv.h new file mode 100644 index 00000000000..80a6f96a067 --- /dev/null +++ b/utils/dxvk-1.10.3/tests/d3d9/test_d3d9_nv12.yuv.h @@ -0,0 +1,12803 @@ +unsigned char test_d3d9_nv12_yuv[] = { + 0x7a, 0x78, 0x77, 0x75, 0x73, 0x72, 0x72, 0x70, 0x6f, 0x6f, 0x6e, 0x6d, + 0x6d, 0x6d, 0x6c, 0x6c, 0x6a, 0x69, 0x6a, 0x6b, 0x6b, 0x6a, 0x69, 0x69, + 0x6a, 0x6a, 0x6a, 0x6a, 0x69, 0x69, 0x6a, 0x70, 0x76, 0x7a, 0x80, 0x87, + 0x89, 0x8a, 0x8a, 0x8c, 0x8d, 0x8a, 0x87, 0x86, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x86, 0x87, 0x87, 0x87, 0x87, 0x86, 0x85, 0x83, 0x82, 0x81, 0x81, + 0x7f, 0x7c, 0x7b, 0x7a, 0x7a, 0x79, 0x77, 0x76, 0x75, 0x74, 0x72, 0x72, + 0x74, 0x76, 0x76, 0x77, 0x79, 0x7a, 0x7c, 0x7d, 0x7e, 0x80, 0x82, 0x83, + 0x84, 0x84, 0x84, 0x83, 0x83, 0x82, 0x82, 0x82, 0x80, 0x7e, 0x7e, 0x7e, + 0x7d, 0x7b, 0x7a, 0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7e, 0x80, 0x82, 0x82, + 0x84, 0x83, 0x83, 0x82, 0x83, 0x82, 0x83, 0x83, 0x84, 0x84, 0x83, 0x83, + 0x83, 0x83, 0x82, 0x81, 0x82, 0x83, 0x83, 0x83, 0x83, 0x82, 0x81, 0x7f, + 0x7d, 0x7b, 0x7b, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7e, 0x81, + 0x82, 0x83, 0x84, 0x84, 0x85, 0x87, 0x86, 0x87, 0x89, 0x8a, 0x8a, 0x8a, + 0x8b, 0x8d, 0x8d, 0x8c, 0x8d, 0x8e, 0x8e, 0x8e, 0x90, 0x90, 0x90, 0x8f, + 0x90, 0x92, 0x93, 0x93, 0x93, 0x95, 0x96, 0x95, 0x95, 0x98, 0x99, 0x99, + 0x9a, 0x9b, 0x9a, 0x9d, 0x9e, 0x9e, 0x9e, 0x9d, 0x9e, 0xa1, 0xa2, 0xa2, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa3, 0xa1, 0x9f, 0x9d, 0x9c, 0x9c, 0x9a, + 0x97, 0x96, 0x95, 0x95, 0x95, 0x95, 0x94, 0x94, 0x93, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x92, 0x92, 0x92, 0x92, 0x90, 0x90, 0x91, 0x92, + 0x92, 0x92, 0x92, 0x91, 0x91, 0x94, 0x94, 0x93, 0x92, 0x92, 0x90, 0x8f, + 0x91, 0x91, 0x90, 0x8f, 0x90, 0x8f, 0x8d, 0x8a, 0x87, 0x85, 0x84, 0x84, + 0x83, 0x84, 0x88, 0x8a, 0x89, 0x88, 0x85, 0x7d, 0x71, 0x69, 0x65, 0x62, + 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x65, 0x64, 0x63, 0x62, 0x63, + 0x63, 0x62, 0x60, 0x5f, 0x5d, 0x5a, 0x59, 0x56, 0x52, 0x4f, 0x4d, 0x4c, + 0x47, 0x41, 0x3c, 0x39, 0x36, 0x30, 0x27, 0x1d, 0x17, 0x14, 0x12, 0x12, + 0x11, 0x10, 0x11, 0x11, 0x10, 0x10, 0x11, 0x12, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x11, 0x12, 0x13, 0x13, 0x13, 0x14, 0x79, 0x76, 0x75, 0x74, + 0x72, 0x71, 0x71, 0x71, 0x70, 0x6f, 0x6e, 0x6e, 0x6e, 0x6d, 0x6c, 0x6d, + 0x6d, 0x6c, 0x6c, 0x6b, 0x6a, 0x6a, 0x69, 0x69, 0x69, 0x6a, 0x69, 0x6a, + 0x6a, 0x6a, 0x6e, 0x76, 0x7a, 0x7d, 0x82, 0x87, 0x8a, 0x8c, 0x8d, 0x8e, + 0x8d, 0x8a, 0x89, 0x88, 0x86, 0x87, 0x86, 0x86, 0x86, 0x87, 0x88, 0x88, + 0x89, 0x88, 0x87, 0x85, 0x84, 0x83, 0x82, 0x81, 0x7e, 0x7c, 0x7b, 0x7a, + 0x79, 0x78, 0x76, 0x75, 0x75, 0x74, 0x73, 0x74, 0x76, 0x77, 0x79, 0x79, + 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81, 0x82, 0x84, 0x84, 0x84, 0x82, 0x82, + 0x81, 0x81, 0x80, 0x80, 0x7e, 0x7d, 0x7c, 0x7d, 0x7c, 0x7b, 0x7b, 0x7b, + 0x7c, 0x7c, 0x7c, 0x7d, 0x7e, 0x80, 0x82, 0x82, 0x84, 0x84, 0x83, 0x83, + 0x82, 0x82, 0x83, 0x83, 0x84, 0x84, 0x83, 0x83, 0x83, 0x83, 0x82, 0x81, + 0x82, 0x82, 0x82, 0x83, 0x83, 0x82, 0x81, 0x7f, 0x7d, 0x7d, 0x7c, 0x7c, + 0x7c, 0x7b, 0x7b, 0x7c, 0x7d, 0x7d, 0x7e, 0x81, 0x82, 0x83, 0x83, 0x84, + 0x85, 0x87, 0x86, 0x87, 0x88, 0x8a, 0x8a, 0x8a, 0x8b, 0x8d, 0x8d, 0x8c, + 0x8d, 0x8e, 0x8e, 0x8e, 0x90, 0x90, 0x91, 0x90, 0x90, 0x91, 0x92, 0x92, + 0x93, 0x95, 0x95, 0x95, 0x95, 0x97, 0x98, 0x98, 0x98, 0x99, 0x9c, 0x9c, + 0x9c, 0x9d, 0x9e, 0x9d, 0x9e, 0xa0, 0xa1, 0xa1, 0xa3, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa3, 0xa1, 0x9f, 0x9d, 0x9c, 0x9c, 0x9a, 0x97, 0x96, 0x95, 0x94, + 0x95, 0x94, 0x93, 0x93, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x92, 0x92, 0x92, 0x92, 0x90, 0x90, 0x91, 0x92, 0x92, 0x94, 0x93, 0x92, + 0x92, 0x91, 0x92, 0x91, 0x91, 0x90, 0x8e, 0x8e, 0x90, 0x90, 0x91, 0x91, + 0x8f, 0x8f, 0x8e, 0x8b, 0x88, 0x86, 0x86, 0x85, 0x84, 0x86, 0x89, 0x8a, + 0x89, 0x88, 0x84, 0x7c, 0x71, 0x69, 0x66, 0x64, 0x65, 0x65, 0x65, 0x64, + 0x65, 0x65, 0x65, 0x66, 0x65, 0x65, 0x64, 0x62, 0x63, 0x63, 0x62, 0x60, + 0x5c, 0x59, 0x58, 0x56, 0x52, 0x4e, 0x4d, 0x4c, 0x48, 0x43, 0x3e, 0x3b, + 0x37, 0x31, 0x29, 0x20, 0x18, 0x16, 0x13, 0x12, 0x11, 0x11, 0x11, 0x11, + 0x10, 0x11, 0x10, 0x11, 0x12, 0x13, 0x13, 0x13, 0x13, 0x13, 0x12, 0x13, + 0x12, 0x12, 0x12, 0x14, 0x79, 0x77, 0x76, 0x75, 0x73, 0x71, 0x72, 0x71, + 0x71, 0x6f, 0x6f, 0x6f, 0x6e, 0x6d, 0x6c, 0x6e, 0x6e, 0x6e, 0x6e, 0x6c, + 0x6b, 0x6b, 0x6a, 0x69, 0x6a, 0x6a, 0x6a, 0x69, 0x6a, 0x6b, 0x70, 0x79, + 0x7e, 0x81, 0x83, 0x86, 0x8a, 0x8e, 0x8f, 0x8f, 0x8e, 0x8a, 0x89, 0x89, + 0x87, 0x87, 0x87, 0x87, 0x88, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x88, 0x85, + 0x84, 0x83, 0x82, 0x80, 0x7e, 0x7b, 0x7a, 0x79, 0x77, 0x76, 0x75, 0x76, + 0x75, 0x74, 0x74, 0x75, 0x77, 0x78, 0x79, 0x79, 0x7b, 0x7d, 0x7e, 0x7f, + 0x80, 0x82, 0x82, 0x84, 0x84, 0x83, 0x82, 0x81, 0x81, 0x80, 0x80, 0x7f, + 0x7e, 0x7d, 0x7c, 0x7c, 0x7b, 0x7b, 0x7a, 0x7b, 0x7c, 0x7d, 0x7d, 0x7d, + 0x7e, 0x80, 0x81, 0x83, 0x83, 0x83, 0x83, 0x83, 0x82, 0x82, 0x83, 0x83, + 0x84, 0x84, 0x83, 0x83, 0x83, 0x84, 0x82, 0x82, 0x82, 0x83, 0x83, 0x83, + 0x83, 0x82, 0x81, 0x7f, 0x7e, 0x7d, 0x7e, 0x7d, 0x7c, 0x7c, 0x7c, 0x7c, + 0x7c, 0x7d, 0x7f, 0x82, 0x82, 0x83, 0x83, 0x84, 0x85, 0x87, 0x87, 0x87, + 0x89, 0x8b, 0x8b, 0x8b, 0x8c, 0x8c, 0x8c, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8f, 0x8f, 0x8f, 0x90, 0x8f, 0x91, 0x91, 0x93, 0x94, 0x94, 0x94, 0x94, + 0x95, 0x97, 0x97, 0x97, 0x98, 0x99, 0x9b, 0x9c, 0x9d, 0x9d, 0x9e, 0x9e, + 0x9f, 0xa1, 0xa1, 0xa2, 0xa3, 0xa4, 0xa4, 0xa4, 0xa4, 0xa3, 0xa1, 0x9f, + 0x9e, 0x9c, 0x9b, 0x99, 0x97, 0x96, 0x95, 0x94, 0x93, 0x93, 0x92, 0x92, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x92, 0x92, 0x92, 0x92, + 0x90, 0x90, 0x91, 0x92, 0x92, 0x93, 0x92, 0x92, 0x92, 0x91, 0x91, 0x90, + 0x8f, 0x90, 0x8e, 0x8d, 0x8f, 0x90, 0x91, 0x90, 0x91, 0x90, 0x8f, 0x8c, + 0x88, 0x87, 0x87, 0x86, 0x86, 0x87, 0x8b, 0x8c, 0x8a, 0x88, 0x83, 0x7a, + 0x71, 0x69, 0x66, 0x64, 0x66, 0x66, 0x67, 0x67, 0x67, 0x67, 0x66, 0x67, + 0x66, 0x65, 0x64, 0x62, 0x62, 0x62, 0x63, 0x60, 0x5c, 0x59, 0x58, 0x56, + 0x52, 0x4f, 0x4c, 0x4b, 0x47, 0x43, 0x3f, 0x3b, 0x37, 0x32, 0x2a, 0x20, + 0x18, 0x15, 0x13, 0x11, 0x11, 0x11, 0x12, 0x12, 0x11, 0x10, 0x11, 0x11, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x11, 0x12, 0x13, 0x13, 0x13, 0x13, + 0x7a, 0x77, 0x76, 0x76, 0x74, 0x71, 0x72, 0x72, 0x71, 0x6f, 0x6f, 0x6e, + 0x6d, 0x6c, 0x6c, 0x6e, 0x6e, 0x6e, 0x6e, 0x6d, 0x6b, 0x6b, 0x6a, 0x6a, + 0x6a, 0x6a, 0x6a, 0x69, 0x6a, 0x6c, 0x72, 0x7a, 0x7f, 0x81, 0x84, 0x87, + 0x8b, 0x8e, 0x8f, 0x8f, 0x8e, 0x8b, 0x8a, 0x8a, 0x88, 0x88, 0x87, 0x88, + 0x89, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x88, 0x85, 0x84, 0x83, 0x82, 0x80, + 0x7d, 0x7a, 0x7a, 0x79, 0x77, 0x76, 0x75, 0x75, 0x75, 0x74, 0x74, 0x76, + 0x77, 0x79, 0x79, 0x79, 0x7c, 0x7d, 0x7f, 0x80, 0x81, 0x83, 0x83, 0x84, + 0x84, 0x84, 0x82, 0x80, 0x80, 0x80, 0x7f, 0x7e, 0x7d, 0x7d, 0x7c, 0x7b, + 0x7a, 0x7b, 0x7a, 0x7b, 0x7c, 0x7d, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, + 0x83, 0x83, 0x83, 0x83, 0x82, 0x82, 0x83, 0x83, 0x84, 0x83, 0x82, 0x82, + 0x83, 0x84, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x82, 0x81, 0x7f, + 0x7e, 0x7d, 0x7d, 0x7d, 0x7c, 0x7b, 0x7c, 0x7c, 0x7c, 0x7e, 0x80, 0x82, + 0x82, 0x83, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x8a, 0x8b, 0x8b, 0x8c, + 0x8c, 0x8c, 0x8d, 0x8e, 0x8e, 0x8e, 0x8e, 0x8d, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x90, 0x91, 0x93, 0x94, 0x94, 0x93, 0x94, 0x95, 0x96, 0x96, 0x96, + 0x97, 0x99, 0x9a, 0x9c, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa0, 0xa0, 0xa1, + 0xa2, 0xa4, 0xa4, 0xa4, 0xa4, 0xa3, 0xa1, 0xa0, 0x9e, 0x9d, 0x9c, 0x99, + 0x96, 0x95, 0x95, 0x93, 0x93, 0x93, 0x92, 0x92, 0x93, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x92, 0x92, 0x92, 0x92, 0x90, 0x90, 0x90, 0x91, + 0x91, 0x93, 0x92, 0x92, 0x92, 0x91, 0x91, 0x90, 0x8f, 0x90, 0x8e, 0x8d, + 0x8f, 0x90, 0x91, 0x90, 0x91, 0x90, 0x90, 0x8d, 0x89, 0x87, 0x87, 0x87, + 0x86, 0x87, 0x8b, 0x8c, 0x8a, 0x88, 0x82, 0x79, 0x70, 0x69, 0x66, 0x65, + 0x66, 0x67, 0x68, 0x68, 0x68, 0x68, 0x67, 0x67, 0x67, 0x66, 0x65, 0x63, + 0x62, 0x62, 0x63, 0x61, 0x5d, 0x5a, 0x59, 0x56, 0x53, 0x4f, 0x4d, 0x4b, + 0x48, 0x44, 0x3f, 0x3b, 0x37, 0x33, 0x2b, 0x21, 0x18, 0x14, 0x12, 0x11, + 0x11, 0x12, 0x12, 0x12, 0x11, 0x10, 0x11, 0x11, 0x11, 0x11, 0x12, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x13, 0x13, 0x13, 0x14, 0x7a, 0x78, 0x77, 0x76, + 0x75, 0x72, 0x72, 0x73, 0x72, 0x6f, 0x6e, 0x6e, 0x6e, 0x6d, 0x6e, 0x6d, + 0x6e, 0x6e, 0x6e, 0x6e, 0x6d, 0x6b, 0x6b, 0x6b, 0x6b, 0x6a, 0x6b, 0x6a, + 0x6b, 0x6f, 0x75, 0x7c, 0x80, 0x82, 0x85, 0x88, 0x8d, 0x8f, 0x90, 0x8f, + 0x8f, 0x8d, 0x8c, 0x8b, 0x8a, 0x8a, 0x89, 0x8b, 0x8b, 0x8a, 0x8a, 0x89, + 0x8a, 0x8a, 0x89, 0x85, 0x83, 0x82, 0x81, 0x7e, 0x7b, 0x7a, 0x78, 0x78, + 0x76, 0x76, 0x76, 0x77, 0x76, 0x76, 0x76, 0x77, 0x79, 0x7a, 0x7a, 0x7a, + 0x7c, 0x7e, 0x80, 0x81, 0x83, 0x84, 0x84, 0x84, 0x84, 0x83, 0x82, 0x81, + 0x7f, 0x7e, 0x7e, 0x7c, 0x7c, 0x7b, 0x7a, 0x78, 0x78, 0x7a, 0x7a, 0x7b, + 0x7d, 0x7d, 0x7e, 0x7f, 0x7f, 0x7f, 0x80, 0x82, 0x82, 0x82, 0x83, 0x82, + 0x83, 0x82, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x84, 0x84, 0x83, + 0x83, 0x84, 0x84, 0x83, 0x83, 0x82, 0x81, 0x7f, 0x7d, 0x7c, 0x7c, 0x7c, + 0x7c, 0x7c, 0x7b, 0x7c, 0x7d, 0x7f, 0x81, 0x83, 0x83, 0x83, 0x84, 0x84, + 0x85, 0x86, 0x86, 0x87, 0x89, 0x8b, 0x8c, 0x8c, 0x8c, 0x8c, 0x8e, 0x8f, + 0x8e, 0x8d, 0x8d, 0x8c, 0x8d, 0x8e, 0x8f, 0x8e, 0x8e, 0x8f, 0x91, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x94, 0x95, 0x96, 0x96, 0x97, 0x98, 0x99, 0x9a, + 0x9b, 0x9c, 0x9e, 0x9e, 0x9f, 0x9f, 0x9f, 0xa1, 0xa1, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa2, 0xa0, 0x9e, 0x9e, 0x9c, 0x98, 0x96, 0x94, 0x93, 0x94, + 0x93, 0x92, 0x92, 0x92, 0x92, 0x93, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x92, 0x92, 0x92, 0x92, 0x91, 0x90, 0x90, 0x90, 0x91, 0x92, 0x93, 0x92, + 0x92, 0x91, 0x91, 0x90, 0x90, 0x90, 0x8e, 0x8d, 0x8f, 0x90, 0x90, 0x90, + 0x91, 0x91, 0x91, 0x8e, 0x8a, 0x88, 0x88, 0x88, 0x87, 0x88, 0x8b, 0x8c, + 0x8a, 0x88, 0x82, 0x79, 0x6f, 0x68, 0x66, 0x65, 0x67, 0x67, 0x69, 0x69, + 0x68, 0x69, 0x67, 0x67, 0x67, 0x67, 0x65, 0x65, 0x63, 0x63, 0x63, 0x62, + 0x5e, 0x5b, 0x59, 0x57, 0x54, 0x51, 0x4e, 0x4c, 0x49, 0x45, 0x40, 0x3a, + 0x37, 0x33, 0x2c, 0x22, 0x18, 0x14, 0x12, 0x11, 0x12, 0x12, 0x12, 0x11, + 0x11, 0x10, 0x10, 0x10, 0x10, 0x11, 0x13, 0x12, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x12, 0x12, 0x15, 0x7b, 0x79, 0x79, 0x78, 0x76, 0x74, 0x72, 0x72, + 0x72, 0x6f, 0x6e, 0x6e, 0x6e, 0x6d, 0x6e, 0x6c, 0x6d, 0x6e, 0x6e, 0x6d, + 0x6d, 0x6b, 0x6b, 0x6b, 0x6a, 0x69, 0x6a, 0x6b, 0x6d, 0x72, 0x79, 0x7f, + 0x82, 0x83, 0x86, 0x8b, 0x90, 0x90, 0x90, 0x8f, 0x8f, 0x8e, 0x8d, 0x8c, + 0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8c, 0x8c, 0x89, 0x8a, 0x8a, 0x88, 0x84, + 0x82, 0x81, 0x80, 0x7d, 0x7b, 0x79, 0x78, 0x77, 0x76, 0x76, 0x77, 0x76, + 0x77, 0x78, 0x78, 0x77, 0x79, 0x7a, 0x7b, 0x7b, 0x7d, 0x7f, 0x81, 0x83, + 0x84, 0x83, 0x83, 0x83, 0x82, 0x82, 0x80, 0x80, 0x7e, 0x7d, 0x7c, 0x7a, + 0x7a, 0x7a, 0x79, 0x77, 0x77, 0x79, 0x7a, 0x7c, 0x7d, 0x7d, 0x7e, 0x7f, + 0x7f, 0x80, 0x80, 0x82, 0x82, 0x82, 0x83, 0x82, 0x83, 0x82, 0x83, 0x83, + 0x83, 0x83, 0x82, 0x82, 0x83, 0x84, 0x84, 0x83, 0x83, 0x84, 0x84, 0x83, + 0x83, 0x82, 0x81, 0x7f, 0x7d, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, + 0x7d, 0x7e, 0x80, 0x82, 0x82, 0x83, 0x85, 0x84, 0x85, 0x86, 0x86, 0x87, + 0x89, 0x8b, 0x8c, 0x8c, 0x8b, 0x8c, 0x8e, 0x8f, 0x8e, 0x8d, 0x8d, 0x8d, + 0x8e, 0x8f, 0x8f, 0x8f, 0x8e, 0x8f, 0x8f, 0x91, 0x91, 0x92, 0x91, 0x92, + 0x93, 0x93, 0x95, 0x95, 0x95, 0x97, 0x97, 0x99, 0x9a, 0x9b, 0x9b, 0x9d, + 0x9d, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa1, 0xa1, 0xa2, 0xa3, 0xa2, 0xa0, + 0x9e, 0x9d, 0x9c, 0x98, 0x96, 0x94, 0x94, 0x94, 0x93, 0x93, 0x93, 0x93, + 0x91, 0x91, 0x94, 0x94, 0x94, 0x94, 0x93, 0x93, 0x92, 0x91, 0x92, 0x92, + 0x90, 0x90, 0x90, 0x90, 0x93, 0x93, 0x93, 0x92, 0x92, 0x91, 0x91, 0x90, + 0x90, 0x90, 0x8e, 0x8d, 0x8f, 0x8f, 0x90, 0x91, 0x91, 0x91, 0x90, 0x8e, + 0x8c, 0x8a, 0x8a, 0x89, 0x89, 0x8a, 0x8c, 0x8c, 0x8a, 0x88, 0x83, 0x7a, + 0x70, 0x68, 0x66, 0x66, 0x68, 0x69, 0x6a, 0x6a, 0x6a, 0x6a, 0x69, 0x68, + 0x68, 0x68, 0x66, 0x65, 0x64, 0x64, 0x64, 0x62, 0x5e, 0x5c, 0x5a, 0x57, + 0x54, 0x52, 0x4f, 0x4c, 0x49, 0x44, 0x41, 0x3b, 0x37, 0x31, 0x2c, 0x23, + 0x19, 0x14, 0x12, 0x11, 0x12, 0x12, 0x12, 0x11, 0x11, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x12, 0x12, 0x11, 0x11, 0x11, 0x10, 0x11, 0x12, 0x14, 0x15, + 0x7b, 0x79, 0x79, 0x78, 0x76, 0x74, 0x73, 0x72, 0x71, 0x70, 0x6f, 0x6f, + 0x6e, 0x6d, 0x6d, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e, 0x6c, 0x6c, 0x6d, 0x6c, + 0x6b, 0x6a, 0x6a, 0x6d, 0x71, 0x76, 0x7d, 0x81, 0x82, 0x83, 0x88, 0x8d, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x8e, 0x8e, 0x8d, 0x8c, 0x8c, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8c, 0x89, 0x88, 0x87, 0x86, 0x84, 0x82, 0x80, 0x7f, 0x7c, + 0x7a, 0x78, 0x77, 0x76, 0x76, 0x77, 0x77, 0x76, 0x76, 0x77, 0x79, 0x79, + 0x79, 0x7a, 0x7b, 0x7c, 0x7e, 0x7f, 0x81, 0x82, 0x82, 0x82, 0x81, 0x81, + 0x81, 0x81, 0x80, 0x7e, 0x7c, 0x7b, 0x7a, 0x79, 0x78, 0x77, 0x77, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7e, 0x80, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x83, 0x83, 0x83, 0x83, 0x82, 0x82, 0x83, 0x82, 0x82, + 0x82, 0x84, 0x84, 0x82, 0x81, 0x82, 0x83, 0x83, 0x83, 0x83, 0x81, 0x80, + 0x7e, 0x7d, 0x7c, 0x7c, 0x7d, 0x7d, 0x7c, 0x7c, 0x7d, 0x7e, 0x7f, 0x82, + 0x83, 0x84, 0x85, 0x85, 0x86, 0x88, 0x87, 0x87, 0x89, 0x8a, 0x8b, 0x8c, + 0x8d, 0x8e, 0x8e, 0x8e, 0x8e, 0x8d, 0x8d, 0x8f, 0x8f, 0x8f, 0x8f, 0x90, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x91, 0x90, 0x90, 0x91, 0x93, 0x93, 0x94, + 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9a, 0x9b, 0x9d, 0x9d, 0x9d, 0x9e, + 0xa0, 0xa0, 0xa2, 0xa2, 0xa2, 0xa2, 0xa1, 0xa0, 0x9f, 0x9e, 0x9c, 0x9a, + 0x97, 0x96, 0x95, 0x94, 0x92, 0x93, 0x93, 0x93, 0x92, 0x92, 0x92, 0x94, + 0x95, 0x95, 0x95, 0x94, 0x93, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x91, + 0x93, 0x94, 0x93, 0x93, 0x93, 0x91, 0x91, 0x90, 0x90, 0x91, 0x90, 0x8e, + 0x8e, 0x8f, 0x90, 0x8f, 0x90, 0x91, 0x90, 0x8e, 0x8d, 0x8c, 0x8c, 0x8c, + 0x8b, 0x8c, 0x8d, 0x8c, 0x8a, 0x88, 0x83, 0x79, 0x6f, 0x69, 0x68, 0x69, + 0x6b, 0x6b, 0x6b, 0x6b, 0x6a, 0x6b, 0x6a, 0x69, 0x6a, 0x6a, 0x68, 0x67, + 0x67, 0x66, 0x65, 0x62, 0x5f, 0x5d, 0x5b, 0x5a, 0x57, 0x52, 0x50, 0x4e, + 0x4a, 0x46, 0x41, 0x3c, 0x38, 0x33, 0x2c, 0x24, 0x1a, 0x16, 0x13, 0x12, + 0x11, 0x11, 0x10, 0x11, 0x11, 0x10, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, + 0x12, 0x11, 0x12, 0x11, 0x13, 0x13, 0x14, 0x14, 0x7c, 0x7a, 0x79, 0x78, + 0x76, 0x76, 0x75, 0x73, 0x72, 0x71, 0x70, 0x70, 0x6e, 0x6d, 0x6c, 0x6c, + 0x6d, 0x6e, 0x6e, 0x6d, 0x6d, 0x6c, 0x6d, 0x6e, 0x6d, 0x6b, 0x6c, 0x71, + 0x74, 0x7a, 0x80, 0x82, 0x83, 0x85, 0x8a, 0x8f, 0x91, 0x90, 0x90, 0x90, + 0x90, 0x8e, 0x8e, 0x8e, 0x8d, 0x8e, 0x8e, 0x8e, 0x8d, 0x8c, 0x8a, 0x89, + 0x87, 0x86, 0x85, 0x82, 0x81, 0x80, 0x7e, 0x7c, 0x79, 0x78, 0x77, 0x76, + 0x77, 0x78, 0x78, 0x76, 0x77, 0x78, 0x7a, 0x7b, 0x7b, 0x7b, 0x7c, 0x7c, + 0x7e, 0x7f, 0x81, 0x82, 0x82, 0x81, 0x80, 0x80, 0x81, 0x80, 0x7f, 0x7b, + 0x7b, 0x7a, 0x79, 0x78, 0x77, 0x76, 0x76, 0x76, 0x78, 0x7a, 0x7b, 0x7b, + 0x7c, 0x7c, 0x7c, 0x7c, 0x7e, 0x7f, 0x82, 0x83, 0x82, 0x82, 0x82, 0x83, + 0x83, 0x83, 0x83, 0x81, 0x81, 0x83, 0x84, 0x84, 0x83, 0x83, 0x83, 0x82, + 0x81, 0x82, 0x81, 0x82, 0x83, 0x82, 0x81, 0x7f, 0x7e, 0x7d, 0x7d, 0x7d, + 0x7d, 0x7e, 0x7d, 0x7d, 0x7e, 0x7f, 0x7f, 0x81, 0x83, 0x84, 0x85, 0x85, + 0x87, 0x88, 0x88, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8d, 0x8d, + 0x8d, 0x8c, 0x8d, 0x8f, 0x90, 0x90, 0x8f, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x8f, 0x90, 0x90, 0x90, 0x92, 0x92, 0x93, 0x94, 0x96, 0x96, 0x97, + 0x98, 0x99, 0x99, 0x9a, 0x9c, 0x9c, 0x9c, 0x9d, 0x9f, 0x9f, 0xa0, 0xa1, + 0xa1, 0xa1, 0xa0, 0x9f, 0x9f, 0x9f, 0x9d, 0x9b, 0x97, 0x96, 0x96, 0x94, + 0x92, 0x92, 0x92, 0x93, 0x93, 0x92, 0x92, 0x94, 0x95, 0x96, 0x96, 0x96, + 0x94, 0x94, 0x93, 0x92, 0x93, 0x93, 0x92, 0x91, 0x93, 0x94, 0x93, 0x92, + 0x92, 0x91, 0x91, 0x90, 0x90, 0x91, 0x91, 0x8e, 0x8e, 0x8e, 0x90, 0x90, + 0x91, 0x91, 0x90, 0x8f, 0x8d, 0x8c, 0x8e, 0x8e, 0x8d, 0x8e, 0x8e, 0x8c, + 0x8a, 0x87, 0x82, 0x79, 0x6f, 0x69, 0x68, 0x69, 0x6b, 0x6c, 0x6b, 0x6b, + 0x69, 0x69, 0x6a, 0x6a, 0x69, 0x69, 0x68, 0x68, 0x69, 0x67, 0x65, 0x63, + 0x60, 0x5e, 0x5d, 0x5c, 0x58, 0x53, 0x51, 0x4f, 0x4a, 0x46, 0x43, 0x3d, + 0x39, 0x34, 0x2c, 0x24, 0x1b, 0x16, 0x13, 0x11, 0x11, 0x10, 0x11, 0x11, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x13, 0x14, 0x13, 0x14, 0x7c, 0x7a, 0x79, 0x79, 0x77, 0x76, 0x75, 0x73, + 0x72, 0x71, 0x70, 0x70, 0x6f, 0x6d, 0x6c, 0x6c, 0x6c, 0x6e, 0x6e, 0x6e, + 0x6d, 0x6c, 0x6e, 0x6e, 0x6d, 0x6c, 0x6e, 0x72, 0x76, 0x7b, 0x82, 0x83, + 0x84, 0x87, 0x8c, 0x90, 0x91, 0x90, 0x90, 0x91, 0x91, 0x8f, 0x8f, 0x8f, + 0x8d, 0x8e, 0x8e, 0x8e, 0x8d, 0x8b, 0x8a, 0x88, 0x86, 0x86, 0x84, 0x82, + 0x80, 0x7f, 0x7e, 0x7b, 0x78, 0x77, 0x76, 0x77, 0x78, 0x78, 0x78, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, 0x7e, 0x7f, 0x81, 0x82, + 0x81, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x7d, 0x7a, 0x7a, 0x79, 0x78, 0x78, + 0x76, 0x75, 0x75, 0x75, 0x78, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, 0x7d, + 0x7e, 0x80, 0x82, 0x83, 0x82, 0x82, 0x82, 0x83, 0x83, 0x83, 0x82, 0x82, + 0x82, 0x83, 0x84, 0x84, 0x84, 0x83, 0x83, 0x83, 0x82, 0x82, 0x81, 0x82, + 0x83, 0x82, 0x81, 0x7f, 0x7e, 0x7d, 0x7e, 0x7e, 0x7d, 0x7e, 0x7e, 0x7d, + 0x7e, 0x7f, 0x7f, 0x81, 0x83, 0x84, 0x85, 0x85, 0x87, 0x88, 0x88, 0x88, + 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x90, + 0x90, 0x90, 0x8f, 0x90, 0x90, 0x90, 0x90, 0x8f, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x91, 0x90, 0x92, 0x93, 0x95, 0x96, 0x97, 0x97, 0x97, 0x98, 0x9a, + 0x9c, 0x9c, 0x9b, 0x9c, 0x9e, 0x9e, 0xa0, 0xa0, 0xa1, 0xa0, 0xa0, 0x9f, + 0x9f, 0x9f, 0x9d, 0x9b, 0x97, 0x96, 0x95, 0x94, 0x92, 0x92, 0x92, 0x93, + 0x93, 0x92, 0x92, 0x94, 0x95, 0x96, 0x96, 0x96, 0x95, 0x94, 0x94, 0x93, + 0x93, 0x93, 0x92, 0x91, 0x93, 0x94, 0x93, 0x93, 0x93, 0x91, 0x91, 0x90, + 0x90, 0x91, 0x90, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x91, 0x91, 0x91, 0x8f, + 0x8e, 0x8d, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8c, 0x89, 0x86, 0x81, 0x79, + 0x6f, 0x69, 0x68, 0x69, 0x6b, 0x6c, 0x6b, 0x6a, 0x69, 0x69, 0x6a, 0x6a, + 0x69, 0x69, 0x69, 0x69, 0x69, 0x68, 0x64, 0x63, 0x61, 0x5f, 0x5e, 0x5c, + 0x58, 0x54, 0x51, 0x4f, 0x4b, 0x46, 0x43, 0x3e, 0x3a, 0x35, 0x2d, 0x24, + 0x1b, 0x16, 0x13, 0x11, 0x10, 0x11, 0x11, 0x12, 0x10, 0x10, 0x10, 0x10, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x14, 0x14, 0x13, 0x14, + 0x7d, 0x7b, 0x79, 0x78, 0x78, 0x77, 0x75, 0x75, 0x73, 0x72, 0x71, 0x71, + 0x6f, 0x6e, 0x6d, 0x6d, 0x6d, 0x6e, 0x6f, 0x6e, 0x6d, 0x6e, 0x6d, 0x6d, + 0x6e, 0x6d, 0x6f, 0x75, 0x79, 0x7e, 0x82, 0x83, 0x86, 0x89, 0x8c, 0x90, + 0x91, 0x90, 0x90, 0x91, 0x91, 0x90, 0x90, 0x8f, 0x8f, 0x8f, 0x8f, 0x8e, + 0x8d, 0x8b, 0x89, 0x87, 0x86, 0x85, 0x84, 0x81, 0x7f, 0x7d, 0x7c, 0x7a, + 0x79, 0x76, 0x76, 0x76, 0x78, 0x79, 0x78, 0x78, 0x79, 0x7a, 0x7b, 0x7b, + 0x7b, 0x7d, 0x7d, 0x7d, 0x7e, 0x7f, 0x81, 0x82, 0x81, 0x7f, 0x7e, 0x7e, + 0x7e, 0x7d, 0x7b, 0x78, 0x78, 0x78, 0x77, 0x77, 0x75, 0x74, 0x74, 0x75, + 0x78, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7d, 0x7f, 0x7f, 0x80, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x83, 0x83, 0x83, 0x83, 0x82, 0x82, 0x84, 0x84, 0x84, + 0x84, 0x83, 0x83, 0x83, 0x83, 0x82, 0x81, 0x82, 0x83, 0x81, 0x81, 0x80, + 0x7f, 0x7e, 0x7e, 0x7f, 0x7e, 0x7d, 0x7e, 0x7e, 0x7e, 0x7f, 0x80, 0x82, + 0x84, 0x84, 0x85, 0x85, 0x87, 0x88, 0x89, 0x89, 0x8a, 0x8a, 0x8b, 0x8c, + 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8d, 0x8f, 0x90, 0x90, 0x90, 0x8f, 0x90, + 0x90, 0x90, 0x90, 0x8e, 0x8f, 0x90, 0x90, 0x8f, 0x8f, 0x90, 0x90, 0x92, + 0x92, 0x94, 0x96, 0x97, 0x96, 0x96, 0x98, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, + 0x9d, 0x9d, 0x9f, 0x9f, 0xa0, 0x9f, 0xa0, 0x9f, 0x9f, 0x9e, 0x9c, 0x99, + 0x97, 0x97, 0x96, 0x95, 0x93, 0x92, 0x93, 0x93, 0x93, 0x93, 0x93, 0x95, + 0x95, 0x95, 0x96, 0x96, 0x95, 0x95, 0x94, 0x93, 0x94, 0x93, 0x92, 0x91, + 0x92, 0x94, 0x94, 0x94, 0x94, 0x91, 0x91, 0x90, 0x8f, 0x90, 0x8f, 0x91, + 0x91, 0x91, 0x91, 0x90, 0x91, 0x91, 0x90, 0x90, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x90, 0x90, 0x8c, 0x89, 0x85, 0x80, 0x77, 0x6e, 0x68, 0x67, 0x68, + 0x6b, 0x6c, 0x6a, 0x69, 0x69, 0x69, 0x6a, 0x69, 0x69, 0x6a, 0x6a, 0x69, + 0x69, 0x68, 0x65, 0x64, 0x62, 0x61, 0x5f, 0x5e, 0x59, 0x55, 0x50, 0x4e, + 0x4b, 0x47, 0x43, 0x3f, 0x3b, 0x36, 0x2e, 0x25, 0x1c, 0x17, 0x12, 0x11, + 0x11, 0x11, 0x11, 0x12, 0x10, 0x11, 0x10, 0x11, 0x11, 0x11, 0x11, 0x13, + 0x13, 0x11, 0x12, 0x13, 0x12, 0x12, 0x13, 0x13, 0x7d, 0x7b, 0x7a, 0x79, + 0x77, 0x76, 0x74, 0x74, 0x73, 0x72, 0x71, 0x72, 0x70, 0x6f, 0x6e, 0x6e, + 0x6f, 0x6f, 0x6f, 0x6e, 0x6e, 0x6e, 0x6d, 0x6d, 0x6d, 0x6e, 0x73, 0x78, + 0x7c, 0x7f, 0x83, 0x85, 0x88, 0x8b, 0x8e, 0x8e, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x90, 0x91, 0x91, 0x90, 0x91, 0x8f, 0x8e, 0x8d, 0x8a, 0x89, 0x87, + 0x86, 0x85, 0x83, 0x80, 0x7e, 0x7c, 0x7b, 0x7a, 0x7a, 0x77, 0x76, 0x77, + 0x79, 0x7a, 0x79, 0x7a, 0x7b, 0x7b, 0x7a, 0x7a, 0x7b, 0x7d, 0x7d, 0x7d, + 0x7e, 0x7f, 0x81, 0x81, 0x80, 0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x79, 0x77, + 0x76, 0x77, 0x76, 0x74, 0x74, 0x74, 0x74, 0x76, 0x77, 0x7a, 0x7a, 0x7b, + 0x7d, 0x7d, 0x7e, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81, 0x82, 0x83, 0x82, + 0x83, 0x83, 0x83, 0x84, 0x84, 0x83, 0x82, 0x82, 0x82, 0x84, 0x84, 0x83, + 0x83, 0x83, 0x82, 0x83, 0x83, 0x82, 0x81, 0x80, 0x7f, 0x7f, 0x80, 0x80, + 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7f, 0x80, 0x82, 0x83, 0x84, 0x85, 0x85, + 0x87, 0x88, 0x89, 0x89, 0x8a, 0x8b, 0x8c, 0x8b, 0x8c, 0x8c, 0x8e, 0x8f, + 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x90, 0x8f, 0x90, 0x90, 0x90, 0x8f, 0x8e, + 0x8e, 0x8f, 0x8f, 0x8f, 0x8e, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x95, 0x96, + 0x96, 0x96, 0x98, 0x99, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9d, 0x9e, + 0x9e, 0x9f, 0xa0, 0x9f, 0x9f, 0x9e, 0x9d, 0x9a, 0x99, 0x98, 0x98, 0x96, + 0x93, 0x92, 0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x94, 0x95, 0x96, + 0x96, 0x96, 0x95, 0x93, 0x94, 0x94, 0x93, 0x92, 0x93, 0x94, 0x94, 0x94, + 0x94, 0x93, 0x92, 0x90, 0x8f, 0x8e, 0x8f, 0x91, 0x92, 0x92, 0x91, 0x90, + 0x90, 0x8f, 0x8f, 0x90, 0x8f, 0x90, 0x8f, 0x8f, 0x8f, 0x91, 0x90, 0x8c, + 0x89, 0x86, 0x80, 0x77, 0x6e, 0x69, 0x68, 0x6a, 0x6c, 0x6c, 0x6b, 0x6b, + 0x6d, 0x6d, 0x6b, 0x6a, 0x6a, 0x6a, 0x6b, 0x6a, 0x69, 0x68, 0x66, 0x65, + 0x62, 0x62, 0x61, 0x5e, 0x5a, 0x56, 0x51, 0x4f, 0x4b, 0x48, 0x43, 0x40, + 0x3d, 0x38, 0x31, 0x27, 0x1e, 0x18, 0x14, 0x11, 0x12, 0x11, 0x11, 0x12, + 0x12, 0x11, 0x11, 0x11, 0x12, 0x12, 0x11, 0x12, 0x13, 0x13, 0x12, 0x13, + 0x13, 0x13, 0x12, 0x14, 0x7e, 0x7b, 0x7b, 0x7a, 0x79, 0x77, 0x75, 0x75, + 0x75, 0x74, 0x72, 0x71, 0x71, 0x70, 0x6f, 0x6e, 0x6f, 0x6e, 0x6f, 0x70, + 0x6f, 0x6d, 0x6d, 0x6d, 0x6e, 0x6f, 0x76, 0x7c, 0x7f, 0x82, 0x84, 0x87, + 0x8b, 0x8d, 0x8f, 0x8f, 0x90, 0x91, 0x91, 0x91, 0x92, 0x92, 0x93, 0x93, + 0x92, 0x90, 0x8e, 0x8d, 0x8c, 0x8a, 0x88, 0x86, 0x85, 0x83, 0x82, 0x7f, + 0x7d, 0x7b, 0x7a, 0x7a, 0x7a, 0x78, 0x79, 0x7a, 0x7a, 0x7a, 0x7a, 0x7b, + 0x7d, 0x7d, 0x7c, 0x7c, 0x7c, 0x7d, 0x7e, 0x7d, 0x7e, 0x7f, 0x81, 0x81, + 0x80, 0x7d, 0x7c, 0x7b, 0x7a, 0x79, 0x78, 0x75, 0x74, 0x73, 0x73, 0x73, + 0x73, 0x74, 0x74, 0x76, 0x76, 0x78, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x80, + 0x80, 0x80, 0x81, 0x81, 0x81, 0x82, 0x82, 0x81, 0x82, 0x84, 0x84, 0x84, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x84, 0x84, 0x83, 0x83, 0x83, 0x82, 0x83, + 0x84, 0x84, 0x83, 0x82, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7e, 0x7f, 0x7e, + 0x7e, 0x7f, 0x81, 0x84, 0x84, 0x84, 0x85, 0x85, 0x87, 0x87, 0x88, 0x8a, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8c, 0x8c, 0x8e, 0x8f, 0x8f, 0x90, 0x90, 0x8f, + 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x90, 0x8e, 0x8c, 0x8d, 0x8d, 0x8c, + 0x8c, 0x8c, 0x8d, 0x8f, 0x8f, 0x91, 0x94, 0x95, 0x94, 0x95, 0x96, 0x98, + 0x98, 0x99, 0x9a, 0x99, 0x9a, 0x99, 0x9b, 0x9d, 0x9d, 0x9d, 0x9e, 0x9f, + 0x9f, 0x9e, 0x9d, 0x9c, 0x9a, 0x99, 0x99, 0x97, 0x94, 0x92, 0x92, 0x92, + 0x93, 0x93, 0x94, 0x94, 0x94, 0x94, 0x95, 0x96, 0x96, 0x96, 0x94, 0x93, + 0x94, 0x93, 0x93, 0x93, 0x92, 0x94, 0x94, 0x94, 0x94, 0x93, 0x93, 0x92, + 0x91, 0x8f, 0x90, 0x91, 0x91, 0x91, 0x90, 0x90, 0x90, 0x8f, 0x8f, 0x90, + 0x91, 0x90, 0x8f, 0x8f, 0x91, 0x93, 0x91, 0x8c, 0x87, 0x84, 0x7e, 0x75, + 0x6d, 0x6a, 0x6a, 0x6b, 0x6d, 0x6c, 0x6d, 0x6d, 0x6e, 0x6d, 0x6e, 0x6d, + 0x6d, 0x6c, 0x6b, 0x6b, 0x6b, 0x6a, 0x67, 0x65, 0x63, 0x62, 0x62, 0x5f, + 0x5a, 0x57, 0x53, 0x51, 0x4d, 0x49, 0x45, 0x41, 0x3f, 0x39, 0x32, 0x28, + 0x20, 0x1b, 0x15, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x11, 0x11, 0x11, + 0x12, 0x12, 0x11, 0x12, 0x13, 0x13, 0x11, 0x13, 0x13, 0x12, 0x13, 0x11, + 0x7f, 0x7c, 0x7b, 0x7b, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, + 0x70, 0x70, 0x6f, 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x6f, 0x6c, 0x6c, 0x6d, + 0x6e, 0x71, 0x78, 0x7d, 0x80, 0x83, 0x85, 0x89, 0x8d, 0x8f, 0x8f, 0x8f, + 0x8f, 0x90, 0x91, 0x92, 0x93, 0x93, 0x93, 0x93, 0x91, 0x8f, 0x8e, 0x8d, + 0x8b, 0x89, 0x87, 0x84, 0x83, 0x82, 0x80, 0x7e, 0x7b, 0x7b, 0x7a, 0x7a, + 0x7a, 0x79, 0x79, 0x79, 0x7a, 0x7b, 0x7b, 0x7b, 0x7d, 0x7d, 0x7d, 0x7d, + 0x7e, 0x7e, 0x7e, 0x7f, 0x7e, 0x80, 0x81, 0x80, 0x7f, 0x7c, 0x7b, 0x7b, + 0x7a, 0x79, 0x77, 0x74, 0x73, 0x72, 0x72, 0x71, 0x72, 0x73, 0x74, 0x76, + 0x76, 0x78, 0x7a, 0x7b, 0x7b, 0x7c, 0x7e, 0x80, 0x80, 0x80, 0x81, 0x80, + 0x82, 0x82, 0x82, 0x81, 0x83, 0x84, 0x84, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x82, 0x83, 0x84, 0x84, 0x84, 0x82, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x80, 0x82, 0x83, + 0x84, 0x84, 0x85, 0x85, 0x87, 0x88, 0x89, 0x8b, 0x8b, 0x8c, 0x8b, 0x8b, + 0x8c, 0x8d, 0x8d, 0x8e, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x8f, 0x8e, 0x8e, 0x8d, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x94, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x99, 0x99, + 0x98, 0x9a, 0x9a, 0x9b, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9c, 0x9c, + 0x9b, 0x9a, 0x99, 0x98, 0x95, 0x94, 0x93, 0x93, 0x92, 0x92, 0x94, 0x94, + 0x95, 0x94, 0x95, 0x95, 0x96, 0x96, 0x95, 0x94, 0x93, 0x94, 0x94, 0x94, + 0x93, 0x93, 0x93, 0x94, 0x95, 0x94, 0x93, 0x92, 0x91, 0x91, 0x90, 0x92, + 0x92, 0x92, 0x91, 0x91, 0x90, 0x8f, 0x8f, 0x8f, 0x91, 0x91, 0x91, 0x92, + 0x92, 0x94, 0x91, 0x8c, 0x87, 0x83, 0x7c, 0x75, 0x6d, 0x6b, 0x6b, 0x6c, + 0x6d, 0x6d, 0x6d, 0x6e, 0x6e, 0x6e, 0x6e, 0x6d, 0x6d, 0x6c, 0x6c, 0x6b, + 0x6b, 0x6a, 0x67, 0x66, 0x63, 0x62, 0x62, 0x5e, 0x5c, 0x57, 0x55, 0x53, + 0x50, 0x4b, 0x45, 0x42, 0x40, 0x3a, 0x32, 0x2a, 0x22, 0x1b, 0x14, 0x11, + 0x10, 0x11, 0x11, 0x11, 0x11, 0x10, 0x11, 0x11, 0x11, 0x12, 0x12, 0x11, + 0x11, 0x12, 0x11, 0x13, 0x13, 0x13, 0x12, 0x12, 0x7f, 0x7c, 0x7c, 0x7b, + 0x79, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70, 0x70, 0x70, 0x6f, + 0x70, 0x6f, 0x6f, 0x70, 0x6f, 0x6c, 0x6c, 0x6d, 0x6e, 0x73, 0x7a, 0x7f, + 0x81, 0x83, 0x86, 0x8b, 0x8e, 0x90, 0x90, 0x8f, 0x8f, 0x90, 0x91, 0x93, + 0x93, 0x93, 0x93, 0x92, 0x90, 0x8e, 0x8d, 0x8c, 0x8b, 0x88, 0x86, 0x84, + 0x82, 0x81, 0x7f, 0x7d, 0x7b, 0x7a, 0x7a, 0x7b, 0x7a, 0x7b, 0x7a, 0x7a, + 0x7a, 0x7b, 0x7b, 0x7b, 0x7c, 0x7d, 0x7d, 0x7d, 0x7d, 0x7e, 0x7f, 0x7f, + 0x7f, 0x80, 0x81, 0x80, 0x7f, 0x7b, 0x7a, 0x7a, 0x7a, 0x79, 0x76, 0x74, + 0x73, 0x72, 0x71, 0x70, 0x71, 0x73, 0x75, 0x76, 0x77, 0x78, 0x7a, 0x7a, + 0x7a, 0x7c, 0x7e, 0x80, 0x80, 0x80, 0x81, 0x81, 0x82, 0x82, 0x82, 0x81, + 0x82, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x82, 0x83, 0x84, 0x84, + 0x84, 0x84, 0x83, 0x83, 0x84, 0x84, 0x84, 0x82, 0x81, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x7f, 0x81, 0x82, 0x83, 0x84, 0x85, 0x85, 0x85, + 0x87, 0x89, 0x89, 0x8b, 0x8c, 0x8c, 0x8b, 0x8b, 0x8c, 0x8d, 0x8d, 0x8e, + 0x8e, 0x8f, 0x8f, 0x90, 0x8f, 0x8f, 0x8f, 0x90, 0x8f, 0x8e, 0x8d, 0x8d, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8b, 0x8b, 0x8d, 0x8f, 0x8f, 0x91, 0x91, 0x93, + 0x94, 0x94, 0x96, 0x97, 0x98, 0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x9a, + 0x9b, 0x9b, 0x9c, 0x9c, 0x9d, 0x9d, 0x9c, 0x9d, 0x9b, 0x9a, 0x9a, 0x98, + 0x96, 0x95, 0x93, 0x92, 0x91, 0x91, 0x93, 0x94, 0x94, 0x95, 0x95, 0x94, + 0x96, 0x96, 0x96, 0x95, 0x94, 0x94, 0x94, 0x94, 0x94, 0x93, 0x92, 0x93, + 0x94, 0x94, 0x93, 0x91, 0x91, 0x91, 0x91, 0x92, 0x93, 0x93, 0x92, 0x92, + 0x90, 0x8f, 0x8e, 0x8e, 0x91, 0x91, 0x92, 0x93, 0x93, 0x94, 0x91, 0x8c, + 0x87, 0x83, 0x7c, 0x75, 0x6d, 0x6b, 0x6b, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e, + 0x6e, 0x6e, 0x6f, 0x6d, 0x6d, 0x6d, 0x6d, 0x6b, 0x6b, 0x6a, 0x68, 0x67, + 0x64, 0x63, 0x62, 0x5f, 0x5c, 0x58, 0x56, 0x55, 0x51, 0x4c, 0x46, 0x42, + 0x40, 0x3a, 0x33, 0x2b, 0x21, 0x1c, 0x14, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x11, 0x11, 0x12, 0x11, 0x13, + 0x13, 0x13, 0x12, 0x13, 0x80, 0x7d, 0x7d, 0x7c, 0x7a, 0x78, 0x78, 0x77, + 0x76, 0x75, 0x73, 0x72, 0x71, 0x71, 0x72, 0x71, 0x71, 0x6f, 0x6e, 0x6f, + 0x6f, 0x6d, 0x6c, 0x6d, 0x6f, 0x75, 0x7c, 0x81, 0x83, 0x85, 0x88, 0x8d, + 0x90, 0x90, 0x8f, 0x8f, 0x8e, 0x8f, 0x90, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x91, 0x8e, 0x8c, 0x8b, 0x89, 0x87, 0x84, 0x83, 0x81, 0x80, 0x7e, 0x7d, + 0x7a, 0x79, 0x79, 0x79, 0x7b, 0x7c, 0x7b, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, + 0x7d, 0x7d, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x80, 0x7f, 0x80, 0x80, 0x7f, + 0x7e, 0x7c, 0x7b, 0x79, 0x79, 0x77, 0x75, 0x73, 0x71, 0x70, 0x6f, 0x70, + 0x72, 0x73, 0x75, 0x77, 0x77, 0x79, 0x79, 0x79, 0x7a, 0x7d, 0x7f, 0x80, + 0x80, 0x80, 0x82, 0x82, 0x81, 0x81, 0x81, 0x80, 0x81, 0x81, 0x82, 0x83, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x84, 0x83, 0x85, 0x85, 0x85, 0x85, 0x84, + 0x85, 0x84, 0x84, 0x83, 0x81, 0x81, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x80, + 0x81, 0x82, 0x83, 0x85, 0x85, 0x85, 0x86, 0x86, 0x88, 0x8a, 0x8a, 0x8c, + 0x8c, 0x8c, 0x8b, 0x8b, 0x8c, 0x8c, 0x8c, 0x8d, 0x8d, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x8d, 0x8d, 0x8d, 0x8d, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x8f, 0x91, 0x92, 0x94, 0x95, 0x96, + 0x97, 0x97, 0x97, 0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x9a, 0x9a, 0x9b, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9b, 0x9a, 0x9a, 0x99, 0x97, 0x96, 0x94, 0x93, + 0x92, 0x92, 0x92, 0x93, 0x94, 0x95, 0x95, 0x95, 0x96, 0x97, 0x95, 0x96, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x93, 0x92, 0x93, 0x94, 0x93, 0x93, 0x92, + 0x91, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x90, 0x8f, 0x8e, 0x8f, + 0x91, 0x92, 0x93, 0x93, 0x93, 0x93, 0x91, 0x8b, 0x86, 0x81, 0x7b, 0x74, + 0x6d, 0x6c, 0x6c, 0x6d, 0x6e, 0x6d, 0x6e, 0x6f, 0x6f, 0x6e, 0x6e, 0x6d, + 0x6d, 0x6c, 0x6c, 0x6b, 0x6b, 0x6a, 0x68, 0x68, 0x66, 0x65, 0x63, 0x60, + 0x5d, 0x59, 0x57, 0x55, 0x52, 0x4d, 0x46, 0x42, 0x40, 0x3a, 0x34, 0x2b, + 0x22, 0x1c, 0x15, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x11, 0x11, + 0x11, 0x12, 0x11, 0x13, 0x13, 0x11, 0x11, 0x12, 0x12, 0x12, 0x13, 0x11, + 0x81, 0x7e, 0x7d, 0x7c, 0x7b, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, + 0x72, 0x72, 0x73, 0x72, 0x72, 0x71, 0x70, 0x71, 0x70, 0x6f, 0x6e, 0x6f, + 0x70, 0x76, 0x7e, 0x83, 0x86, 0x87, 0x8a, 0x8d, 0x90, 0x90, 0x8f, 0x8f, + 0x8f, 0x8f, 0x90, 0x92, 0x94, 0x93, 0x92, 0x92, 0x91, 0x8e, 0x8c, 0x89, + 0x88, 0x86, 0x84, 0x81, 0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x7b, 0x7a, 0x7a, + 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, 0x7e, 0x7d, 0x7c, 0x7c, + 0x7e, 0x7f, 0x7f, 0x80, 0x80, 0x7f, 0x7e, 0x7d, 0x7c, 0x7c, 0x7a, 0x79, + 0x78, 0x76, 0x73, 0x71, 0x70, 0x6f, 0x6f, 0x70, 0x72, 0x74, 0x75, 0x77, + 0x77, 0x78, 0x78, 0x79, 0x79, 0x7c, 0x7e, 0x80, 0x80, 0x7f, 0x81, 0x81, + 0x80, 0x7f, 0x7f, 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x83, 0x83, + 0x84, 0x84, 0x84, 0x85, 0x86, 0x86, 0x86, 0x85, 0x84, 0x84, 0x83, 0x82, + 0x83, 0x82, 0x81, 0x81, 0x82, 0x81, 0x81, 0x82, 0x82, 0x83, 0x84, 0x85, + 0x85, 0x85, 0x86, 0x86, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8d, 0x8d, 0x8e, 0x8e, 0x8f, 0x8e, 0x8e, 0x8f, 0x8f, + 0x8f, 0x8e, 0x8d, 0x8d, 0x8c, 0x8b, 0x8a, 0x8a, 0x89, 0x8a, 0x8b, 0x8c, + 0x8c, 0x8d, 0x8e, 0x90, 0x92, 0x93, 0x93, 0x95, 0x96, 0x95, 0x95, 0x96, + 0x97, 0x96, 0x97, 0x98, 0x99, 0x99, 0x99, 0x9a, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9b, 0x99, 0x99, 0x99, 0x97, 0x96, 0x95, 0x94, 0x95, 0x94, 0x93, 0x93, + 0x94, 0x95, 0x95, 0x95, 0x96, 0x96, 0x95, 0x95, 0x96, 0x96, 0x96, 0x95, + 0x95, 0x94, 0x92, 0x93, 0x94, 0x94, 0x95, 0x94, 0x94, 0x94, 0x94, 0x93, + 0x93, 0x93, 0x93, 0x92, 0x90, 0x8f, 0x8e, 0x8e, 0x90, 0x92, 0x93, 0x93, + 0x94, 0x94, 0x8f, 0x89, 0x84, 0x80, 0x79, 0x72, 0x6d, 0x6c, 0x6d, 0x6e, + 0x6e, 0x6e, 0x6f, 0x70, 0x70, 0x6e, 0x6f, 0x6e, 0x6d, 0x6d, 0x6d, 0x6b, + 0x6c, 0x6c, 0x6b, 0x69, 0x67, 0x66, 0x64, 0x62, 0x5f, 0x5a, 0x58, 0x56, + 0x52, 0x4e, 0x49, 0x45, 0x41, 0x3b, 0x34, 0x2a, 0x21, 0x1b, 0x14, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x11, 0x11, 0x11, 0x12, 0x13, + 0x13, 0x13, 0x11, 0x12, 0x13, 0x13, 0x13, 0x11, 0x80, 0x7e, 0x7d, 0x7d, + 0x7c, 0x79, 0x7a, 0x79, 0x78, 0x74, 0x73, 0x73, 0x73, 0x73, 0x73, 0x71, + 0x71, 0x70, 0x70, 0x71, 0x71, 0x70, 0x6e, 0x6f, 0x71, 0x79, 0x81, 0x85, + 0x86, 0x87, 0x8a, 0x8e, 0x90, 0x90, 0x8f, 0x90, 0x90, 0x8f, 0x90, 0x91, + 0x92, 0x92, 0x92, 0x92, 0x91, 0x8e, 0x8c, 0x89, 0x87, 0x85, 0x81, 0x80, + 0x7d, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, 0x7c, 0x7d, 0x7d, 0x7d, + 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7b, 0x7c, 0x7d, 0x7f, 0x7f, 0x80, + 0x80, 0x7f, 0x7e, 0x7e, 0x7c, 0x7c, 0x7a, 0x78, 0x76, 0x74, 0x73, 0x70, + 0x6f, 0x6f, 0x6f, 0x70, 0x72, 0x75, 0x76, 0x77, 0x77, 0x77, 0x78, 0x7a, + 0x7b, 0x7b, 0x7c, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x80, 0x80, 0x81, 0x80, + 0x81, 0x80, 0x81, 0x82, 0x81, 0x82, 0x84, 0x86, 0x86, 0x86, 0x85, 0x86, + 0x87, 0x85, 0x85, 0x86, 0x86, 0x85, 0x84, 0x83, 0x83, 0x83, 0x84, 0x84, + 0x83, 0x82, 0x81, 0x82, 0x83, 0x84, 0x84, 0x85, 0x86, 0x86, 0x86, 0x86, + 0x88, 0x8a, 0x8b, 0x8c, 0x8c, 0x8d, 0x8d, 0x8d, 0x8c, 0x8c, 0x8c, 0x8d, + 0x8d, 0x8e, 0x8d, 0x8d, 0x8d, 0x8e, 0x8f, 0x8d, 0x8d, 0x8c, 0x8c, 0x8b, + 0x8b, 0x8a, 0x8a, 0x8a, 0x89, 0x89, 0x8a, 0x8b, 0x8c, 0x8c, 0x8e, 0x8f, + 0x90, 0x91, 0x93, 0x93, 0x93, 0x93, 0x94, 0x95, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x98, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9c, 0x9b, 0x9a, 0x9a, 0x99, + 0x98, 0x96, 0x95, 0x95, 0x95, 0x94, 0x93, 0x94, 0x94, 0x94, 0x95, 0x94, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x95, 0x94, 0x94, 0x95, 0x95, 0x94, 0x93, + 0x93, 0x93, 0x95, 0x95, 0x95, 0x95, 0x95, 0x93, 0x94, 0x94, 0x94, 0x92, + 0x91, 0x90, 0x90, 0x8f, 0x90, 0x90, 0x92, 0x94, 0x95, 0x93, 0x8f, 0x88, + 0x83, 0x7f, 0x79, 0x71, 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, + 0x6f, 0x6f, 0x6f, 0x6e, 0x6e, 0x6c, 0x6c, 0x6d, 0x6c, 0x6b, 0x6c, 0x6a, + 0x67, 0x66, 0x65, 0x63, 0x5f, 0x5b, 0x58, 0x55, 0x50, 0x4c, 0x49, 0x46, + 0x42, 0x3c, 0x35, 0x2b, 0x22, 0x1c, 0x15, 0x11, 0x11, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x13, 0x13, 0x13, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x11, 0x80, 0x7e, 0x7d, 0x7d, 0x7c, 0x79, 0x79, 0x79, + 0x78, 0x74, 0x73, 0x74, 0x73, 0x72, 0x72, 0x71, 0x71, 0x70, 0x70, 0x71, + 0x71, 0x6f, 0x6e, 0x6f, 0x73, 0x7b, 0x82, 0x86, 0x87, 0x88, 0x8b, 0x90, + 0x91, 0x90, 0x90, 0x90, 0x90, 0x8f, 0x8f, 0x91, 0x92, 0x91, 0x91, 0x91, + 0x90, 0x8c, 0x8b, 0x89, 0x86, 0x84, 0x81, 0x7f, 0x7d, 0x7c, 0x7c, 0x7d, + 0x7c, 0x7d, 0x7d, 0x7d, 0x7c, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7c, + 0x7c, 0x7c, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x80, 0x80, 0x7f, 0x7f, 0x7e, + 0x7d, 0x7c, 0x7a, 0x77, 0x76, 0x73, 0x72, 0x70, 0x6f, 0x6f, 0x70, 0x70, + 0x72, 0x75, 0x76, 0x77, 0x77, 0x77, 0x78, 0x7a, 0x7b, 0x7b, 0x7c, 0x7e, + 0x7e, 0x7f, 0x7e, 0x7e, 0x7f, 0x80, 0x80, 0x7f, 0x81, 0x80, 0x81, 0x82, + 0x81, 0x82, 0x84, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x87, + 0x85, 0x85, 0x84, 0x82, 0x83, 0x83, 0x84, 0x85, 0x84, 0x83, 0x82, 0x83, + 0x84, 0x85, 0x85, 0x86, 0x86, 0x87, 0x87, 0x87, 0x89, 0x8a, 0x8b, 0x8c, + 0x8c, 0x8d, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8d, 0x8e, 0x8f, 0x8d, 0x8d, + 0x8e, 0x8e, 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x8b, 0x8a, 0x8a, 0x89, + 0x88, 0x89, 0x8a, 0x8a, 0x8b, 0x8b, 0x8e, 0x8f, 0x8f, 0x90, 0x92, 0x93, + 0x92, 0x92, 0x93, 0x94, 0x95, 0x94, 0x95, 0x95, 0x95, 0x97, 0x97, 0x98, + 0x98, 0x99, 0x9a, 0x99, 0x9a, 0x9b, 0x9b, 0x9b, 0x9a, 0x98, 0x97, 0x96, + 0x97, 0x95, 0x95, 0x94, 0x94, 0x94, 0x96, 0x96, 0x95, 0x95, 0x96, 0x96, + 0x96, 0x95, 0x94, 0x94, 0x95, 0x95, 0x94, 0x94, 0x93, 0x93, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x93, 0x93, 0x94, 0x94, 0x92, 0x92, 0x91, 0x90, 0x8f, + 0x90, 0x90, 0x92, 0x93, 0x94, 0x92, 0x8e, 0x87, 0x81, 0x7e, 0x78, 0x70, + 0x6d, 0x6e, 0x6f, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x70, 0x6f, 0x6f, 0x6e, + 0x6d, 0x6c, 0x6c, 0x6d, 0x6c, 0x6b, 0x6c, 0x6b, 0x67, 0x66, 0x65, 0x63, + 0x60, 0x5c, 0x59, 0x57, 0x52, 0x4d, 0x4b, 0x47, 0x43, 0x3c, 0x36, 0x2b, + 0x23, 0x1d, 0x15, 0x11, 0x11, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x12, 0x13, 0x12, 0x11, 0x11, 0x12, 0x12, 0x13, 0x13, 0x13, 0x11, + 0x81, 0x7e, 0x7d, 0x7c, 0x7c, 0x79, 0x79, 0x79, 0x78, 0x75, 0x73, 0x74, + 0x73, 0x72, 0x72, 0x71, 0x71, 0x70, 0x70, 0x71, 0x71, 0x6f, 0x6f, 0x70, + 0x73, 0x7c, 0x83, 0x86, 0x87, 0x89, 0x8c, 0x90, 0x91, 0x91, 0x90, 0x90, + 0x8f, 0x8f, 0x90, 0x91, 0x91, 0x90, 0x91, 0x90, 0x8f, 0x8c, 0x8b, 0x88, + 0x86, 0x83, 0x80, 0x7e, 0x7d, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, + 0x7c, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7c, 0x7d, 0x7d, 0x7e, 0x7e, + 0x7e, 0x7e, 0x7f, 0x7f, 0x80, 0x7f, 0x7e, 0x7e, 0x7d, 0x7b, 0x79, 0x77, + 0x75, 0x73, 0x71, 0x6f, 0x6f, 0x70, 0x70, 0x70, 0x73, 0x75, 0x76, 0x77, + 0x77, 0x77, 0x78, 0x79, 0x7b, 0x7b, 0x7c, 0x7e, 0x7e, 0x7f, 0x7f, 0x7e, + 0x80, 0x80, 0x7f, 0x7f, 0x81, 0x80, 0x81, 0x82, 0x82, 0x82, 0x84, 0x86, + 0x86, 0x86, 0x85, 0x86, 0x86, 0x86, 0x86, 0x86, 0x85, 0x84, 0x83, 0x82, + 0x83, 0x84, 0x85, 0x85, 0x84, 0x84, 0x83, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x87, 0x87, 0x87, 0x88, 0x8a, 0x8a, 0x8b, 0x8c, 0x8c, 0x8d, 0x8d, 0x8d, + 0x8c, 0x8c, 0x8d, 0x8d, 0x8e, 0x8e, 0x8d, 0x8d, 0x8e, 0x8f, 0x8f, 0x8d, + 0x8d, 0x8d, 0x8c, 0x8b, 0x8b, 0x8a, 0x89, 0x88, 0x88, 0x89, 0x89, 0x8a, + 0x8a, 0x8a, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x92, 0x92, 0x92, 0x93, + 0x94, 0x93, 0x94, 0x94, 0x95, 0x96, 0x96, 0x97, 0x97, 0x99, 0x99, 0x99, + 0x9a, 0x9c, 0x9c, 0x9c, 0x9a, 0x99, 0x98, 0x97, 0x97, 0x96, 0x95, 0x94, + 0x93, 0x94, 0x96, 0x97, 0x95, 0x95, 0x96, 0x96, 0x96, 0x96, 0x95, 0x94, + 0x95, 0x95, 0x94, 0x94, 0x93, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x93, + 0x94, 0x94, 0x94, 0x93, 0x92, 0x90, 0x90, 0x8f, 0x90, 0x90, 0x92, 0x93, + 0x94, 0x91, 0x8d, 0x87, 0x81, 0x7d, 0x77, 0x70, 0x6d, 0x6e, 0x6f, 0x70, + 0x70, 0x6f, 0x71, 0x71, 0x71, 0x70, 0x6e, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, + 0x6d, 0x6c, 0x6c, 0x6b, 0x68, 0x66, 0x65, 0x63, 0x61, 0x5d, 0x59, 0x57, + 0x52, 0x4e, 0x4b, 0x47, 0x43, 0x3d, 0x36, 0x2b, 0x22, 0x1d, 0x15, 0x11, + 0x11, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x12, 0x12, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x12, 0x13, 0x13, 0x11, 0x81, 0x7e, 0x7d, 0x7c, + 0x7c, 0x7a, 0x7a, 0x7a, 0x78, 0x76, 0x74, 0x75, 0x74, 0x73, 0x73, 0x71, + 0x71, 0x70, 0x6f, 0x70, 0x6f, 0x70, 0x6f, 0x71, 0x74, 0x7d, 0x84, 0x88, + 0x89, 0x8a, 0x8d, 0x91, 0x92, 0x92, 0x91, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x91, 0x90, 0x90, 0x8f, 0x8d, 0x8c, 0x89, 0x87, 0x86, 0x83, 0x80, 0x7e, + 0x7c, 0x7b, 0x7c, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7c, 0x7d, 0x7d, 0x7d, + 0x7d, 0x7d, 0x7d, 0x7d, 0x7e, 0x7e, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x80, + 0x7f, 0x7e, 0x7d, 0x7d, 0x7b, 0x7a, 0x78, 0x76, 0x74, 0x72, 0x71, 0x70, + 0x70, 0x70, 0x71, 0x71, 0x73, 0x75, 0x77, 0x78, 0x79, 0x77, 0x78, 0x79, + 0x7b, 0x7b, 0x7c, 0x7c, 0x7d, 0x7e, 0x7f, 0x7e, 0x7e, 0x7e, 0x7e, 0x80, + 0x81, 0x80, 0x80, 0x80, 0x81, 0x83, 0x85, 0x86, 0x86, 0x85, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x85, 0x84, 0x84, 0x83, 0x84, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x84, 0x84, 0x85, 0x86, 0x86, 0x87, 0x88, 0x88, 0x88, 0x89, + 0x8b, 0x8a, 0x8b, 0x8c, 0x8c, 0x8d, 0x8d, 0x8d, 0x8c, 0x8d, 0x8d, 0x8e, + 0x8e, 0x8e, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8d, 0x8d, 0x8d, 0x8c, 0x8c, + 0x8c, 0x8a, 0x88, 0x88, 0x88, 0x89, 0x8a, 0x89, 0x89, 0x8a, 0x8d, 0x8f, + 0x8e, 0x8f, 0x90, 0x92, 0x92, 0x91, 0x91, 0x93, 0x93, 0x93, 0x94, 0x94, + 0x94, 0x95, 0x96, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9b, 0x9c, 0x9c, 0x9c, + 0x9b, 0x99, 0x98, 0x98, 0x97, 0x96, 0x95, 0x95, 0x94, 0x95, 0x97, 0x97, + 0x96, 0x96, 0x96, 0x97, 0x97, 0x97, 0x97, 0x95, 0x96, 0x96, 0x94, 0x93, + 0x93, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x94, 0x94, + 0x92, 0x91, 0x90, 0x90, 0x90, 0x90, 0x92, 0x93, 0x93, 0x90, 0x8b, 0x86, + 0x80, 0x7c, 0x76, 0x70, 0x6e, 0x6e, 0x70, 0x71, 0x71, 0x70, 0x71, 0x71, + 0x70, 0x70, 0x6f, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6d, 0x6d, 0x6c, 0x6a, + 0x69, 0x66, 0x65, 0x64, 0x61, 0x5c, 0x5a, 0x57, 0x53, 0x50, 0x4c, 0x48, + 0x44, 0x3e, 0x37, 0x2d, 0x23, 0x1d, 0x15, 0x11, 0x11, 0x11, 0x11, 0x10, + 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x10, 0x11, 0x11, + 0x12, 0x12, 0x12, 0x13, 0x81, 0x7f, 0x7e, 0x7e, 0x7d, 0x7b, 0x7a, 0x79, + 0x78, 0x78, 0x76, 0x76, 0x75, 0x75, 0x74, 0x73, 0x73, 0x72, 0x71, 0x6f, + 0x6f, 0x70, 0x70, 0x71, 0x76, 0x7e, 0x85, 0x89, 0x8b, 0x8d, 0x8f, 0x91, + 0x91, 0x91, 0x90, 0x8f, 0x90, 0x90, 0x90, 0x90, 0x90, 0x8f, 0x8f, 0x8e, + 0x8d, 0x8a, 0x88, 0x86, 0x84, 0x82, 0x7f, 0x7f, 0x7e, 0x7e, 0x7e, 0x7e, + 0x7f, 0x7f, 0x7f, 0x7e, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, + 0x7e, 0x7f, 0x80, 0x80, 0x7f, 0x80, 0x80, 0x80, 0x7f, 0x7e, 0x7d, 0x7c, + 0x7b, 0x79, 0x77, 0x75, 0x74, 0x72, 0x71, 0x71, 0x71, 0x71, 0x72, 0x72, + 0x73, 0x75, 0x76, 0x77, 0x79, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7b, 0x7b, + 0x7b, 0x7d, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x80, 0x80, 0x80, 0x7f, 0x7f, + 0x81, 0x84, 0x86, 0x86, 0x87, 0x86, 0x87, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x86, 0x86, 0x85, 0x86, 0x85, 0x86, 0x86, 0x86, 0x86, 0x87, 0x86, 0x85, + 0x86, 0x88, 0x88, 0x87, 0x89, 0x89, 0x88, 0x89, 0x8b, 0x8b, 0x8b, 0x8d, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8b, 0x8d, 0x8e, 0x8e, 0x8e, 0x8e, 0x8d, 0x8d, + 0x8e, 0x8e, 0x8d, 0x8e, 0x8e, 0x8d, 0x8d, 0x8c, 0x8b, 0x89, 0x87, 0x86, + 0x87, 0x88, 0x89, 0x88, 0x89, 0x8b, 0x8c, 0x8d, 0x8d, 0x8e, 0x8f, 0x91, + 0x91, 0x90, 0x90, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92, 0x93, 0x95, 0x95, + 0x96, 0x97, 0x98, 0x99, 0x9b, 0x9c, 0x9c, 0x9b, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x97, 0x97, 0x97, 0x97, 0x96, 0x97, 0x96, 0x97, 0x97, 0x97, 0x98, + 0x98, 0x98, 0x97, 0x96, 0x97, 0x97, 0x95, 0x94, 0x95, 0x95, 0x95, 0x95, + 0x96, 0x95, 0x95, 0x96, 0x96, 0x96, 0x95, 0x95, 0x93, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x92, 0x93, 0x93, 0x8e, 0x8a, 0x84, 0x7f, 0x7b, 0x76, 0x70, + 0x6e, 0x6f, 0x70, 0x71, 0x70, 0x71, 0x72, 0x72, 0x71, 0x71, 0x71, 0x70, + 0x70, 0x70, 0x6f, 0x6d, 0x6e, 0x6d, 0x6b, 0x6a, 0x6a, 0x68, 0x67, 0x66, + 0x62, 0x5e, 0x5b, 0x58, 0x55, 0x51, 0x4c, 0x48, 0x45, 0x3f, 0x37, 0x2d, + 0x23, 0x1c, 0x13, 0x11, 0x11, 0x11, 0x10, 0x11, 0x10, 0x10, 0x10, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x10, 0x10, 0x11, 0x11, 0x12, 0x13, 0x14, 0x14, + 0x82, 0x80, 0x80, 0x7f, 0x7e, 0x7b, 0x7a, 0x79, 0x78, 0x78, 0x77, 0x77, + 0x76, 0x76, 0x75, 0x74, 0x74, 0x73, 0x72, 0x71, 0x70, 0x6f, 0x70, 0x72, + 0x77, 0x7f, 0x86, 0x8a, 0x8c, 0x8d, 0x91, 0x91, 0x91, 0x91, 0x91, 0x8f, + 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x8f, 0x8e, 0x8d, 0x8c, 0x89, 0x87, 0x85, + 0x83, 0x81, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x7f, + 0x7d, 0x7e, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7e, 0x7e, 0x7f, 0x7f, 0x80, + 0x7f, 0x80, 0x80, 0x80, 0x7e, 0x7e, 0x7d, 0x7c, 0x7b, 0x79, 0x78, 0x76, + 0x74, 0x72, 0x71, 0x73, 0x72, 0x73, 0x73, 0x74, 0x75, 0x76, 0x76, 0x77, + 0x79, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7c, 0x7b, 0x7c, 0x7d, 0x7e, 0x7e, + 0x7e, 0x7e, 0x7e, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x81, 0x84, 0x86, 0x86, + 0x85, 0x86, 0x88, 0x89, 0x89, 0x89, 0x89, 0x89, 0x88, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x87, 0x88, 0x88, 0x88, 0x87, 0x87, 0x89, 0x8a, 0x89, + 0x8a, 0x8a, 0x89, 0x8b, 0x8c, 0x8d, 0x8d, 0x8e, 0x8e, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8e, 0x8e, 0x8e, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8d, 0x8d, 0x8b, 0x89, 0x89, 0x87, 0x86, 0x86, 0x88, 0x89, 0x89, + 0x89, 0x8a, 0x8b, 0x8c, 0x8c, 0x8d, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x91, + 0x91, 0x90, 0x91, 0x91, 0x91, 0x92, 0x95, 0x95, 0x96, 0x97, 0x98, 0x99, + 0x9b, 0x9c, 0x9c, 0x9c, 0x9a, 0x9b, 0x9b, 0x9b, 0x9a, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x97, 0x96, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x97, 0x96, + 0x96, 0x97, 0x96, 0x95, 0x96, 0x94, 0x95, 0x95, 0x95, 0x94, 0x94, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x94, 0x93, 0x92, 0x93, 0x92, 0x91, 0x92, 0x93, + 0x92, 0x8d, 0x89, 0x83, 0x7d, 0x7a, 0x75, 0x70, 0x6e, 0x6f, 0x70, 0x71, + 0x6f, 0x70, 0x72, 0x72, 0x73, 0x71, 0x72, 0x71, 0x71, 0x70, 0x6f, 0x6e, + 0x6e, 0x6d, 0x6c, 0x6a, 0x6a, 0x68, 0x67, 0x65, 0x63, 0x5f, 0x5b, 0x59, + 0x56, 0x52, 0x4e, 0x4a, 0x46, 0x40, 0x37, 0x2d, 0x23, 0x1c, 0x14, 0x11, + 0x12, 0x11, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x12, 0x11, + 0x11, 0x11, 0x10, 0x11, 0x12, 0x13, 0x14, 0x13, 0x82, 0x80, 0x80, 0x7f, + 0x7d, 0x7b, 0x7b, 0x7a, 0x79, 0x79, 0x78, 0x77, 0x76, 0x75, 0x76, 0x74, + 0x74, 0x73, 0x72, 0x71, 0x72, 0x71, 0x71, 0x73, 0x78, 0x81, 0x88, 0x8b, + 0x8c, 0x8e, 0x92, 0x93, 0x92, 0x91, 0x90, 0x90, 0x90, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8e, 0x8e, 0x8c, 0x89, 0x86, 0x84, 0x84, 0x82, 0x81, 0x7f, + 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7d, 0x7d, 0x7d, 0x7d, + 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7f, 0x80, 0x80, 0x81, 0x81, 0x80, 0x7f, + 0x7e, 0x7d, 0x7d, 0x7d, 0x7b, 0x79, 0x77, 0x77, 0x75, 0x74, 0x74, 0x75, + 0x74, 0x74, 0x74, 0x75, 0x76, 0x76, 0x78, 0x79, 0x7a, 0x7a, 0x7a, 0x7a, + 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, 0x7e, 0x7e, 0x7f, 0x7e, + 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x84, 0x86, 0x86, 0x86, 0x88, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x88, 0x86, 0x86, 0x87, 0x88, 0x87, 0x87, 0x88, + 0x8a, 0x8a, 0x8a, 0x88, 0x89, 0x8b, 0x8b, 0x8a, 0x8a, 0x8a, 0x8a, 0x8b, + 0x8c, 0x8c, 0x8c, 0x8d, 0x8e, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8e, 0x8d, + 0x8d, 0x8c, 0x8c, 0x8e, 0x8e, 0x8e, 0x8e, 0x8d, 0x8d, 0x8c, 0x8c, 0x8c, + 0x8a, 0x88, 0x87, 0x87, 0x86, 0x87, 0x89, 0x89, 0x89, 0x89, 0x89, 0x8b, + 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x90, 0x8f, 0x8f, 0x8f, 0x90, 0x90, + 0x91, 0x92, 0x94, 0x94, 0x96, 0x96, 0x97, 0x98, 0x9a, 0x9b, 0x9c, 0x9d, + 0x9c, 0x9d, 0x9c, 0x9c, 0x99, 0x99, 0x98, 0x97, 0x97, 0x97, 0x98, 0x99, + 0x99, 0x99, 0x98, 0x97, 0x97, 0x98, 0x98, 0x97, 0x97, 0x98, 0x97, 0x97, + 0x97, 0x95, 0x96, 0x95, 0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x95, 0x95, + 0x93, 0x92, 0x93, 0x93, 0x93, 0x92, 0x93, 0x93, 0x92, 0x8e, 0x8a, 0x82, + 0x7e, 0x79, 0x74, 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x70, 0x71, 0x71, 0x72, + 0x73, 0x72, 0x72, 0x72, 0x71, 0x70, 0x6f, 0x6f, 0x6e, 0x6d, 0x6e, 0x6c, + 0x6a, 0x68, 0x67, 0x66, 0x62, 0x60, 0x5c, 0x59, 0x56, 0x53, 0x4d, 0x48, + 0x46, 0x41, 0x39, 0x2e, 0x23, 0x1d, 0x15, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x10, 0x11, 0x11, 0x11, 0x11, 0x13, 0x12, 0x12, 0x12, 0x11, 0x11, + 0x12, 0x13, 0x13, 0x14, 0x82, 0x80, 0x80, 0x7f, 0x7d, 0x7b, 0x7b, 0x7a, + 0x79, 0x79, 0x78, 0x77, 0x76, 0x75, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, + 0x72, 0x71, 0x71, 0x73, 0x79, 0x82, 0x88, 0x8b, 0x8c, 0x8f, 0x92, 0x94, + 0x93, 0x91, 0x90, 0x91, 0x90, 0x8f, 0x8f, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8c, 0x88, 0x85, 0x84, 0x84, 0x82, 0x82, 0x80, 0x80, 0x80, 0x81, 0x81, + 0x80, 0x80, 0x80, 0x7f, 0x7d, 0x7c, 0x7c, 0x7d, 0x7e, 0x7e, 0x7e, 0x7e, + 0x7f, 0x7f, 0x80, 0x80, 0x81, 0x81, 0x81, 0x7f, 0x7e, 0x7c, 0x7c, 0x7d, + 0x7a, 0x78, 0x77, 0x76, 0x76, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x76, + 0x76, 0x77, 0x78, 0x7a, 0x7a, 0x7a, 0x7a, 0x7b, 0x7c, 0x7c, 0x7c, 0x7c, + 0x7c, 0x7d, 0x7c, 0x7c, 0x7e, 0x7f, 0x7f, 0x7e, 0x7e, 0x7f, 0x80, 0x81, + 0x83, 0x84, 0x85, 0x86, 0x86, 0x88, 0x89, 0x89, 0x88, 0x89, 0x89, 0x8a, + 0x88, 0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x88, 0x8a, 0x8a, 0x8a, 0x89, + 0x89, 0x8b, 0x8c, 0x8b, 0x8b, 0x8a, 0x8a, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8e, 0x8d, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8d, 0x8c, 0x8b, 0x8c, 0x8d, + 0x8e, 0x8e, 0x8e, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8b, 0x88, 0x87, 0x87, + 0x86, 0x86, 0x88, 0x89, 0x89, 0x89, 0x89, 0x8b, 0x8b, 0x8b, 0x8c, 0x8e, + 0x8f, 0x90, 0x90, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x91, 0x93, 0x94, + 0x96, 0x96, 0x97, 0x98, 0x9a, 0x9a, 0x9b, 0x9d, 0x9d, 0x9d, 0x9c, 0x9c, + 0x9a, 0x9a, 0x98, 0x97, 0x96, 0x97, 0x99, 0x99, 0x9a, 0x9a, 0x98, 0x98, + 0x97, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x97, 0x96, 0x97, 0x95, + 0x95, 0x95, 0x95, 0x96, 0x96, 0x96, 0x95, 0x96, 0x94, 0x93, 0x93, 0x93, + 0x93, 0x92, 0x93, 0x93, 0x92, 0x8e, 0x89, 0x82, 0x7d, 0x79, 0x73, 0x6e, + 0x6e, 0x6f, 0x70, 0x70, 0x70, 0x71, 0x71, 0x71, 0x73, 0x73, 0x73, 0x72, + 0x70, 0x70, 0x6f, 0x6f, 0x6d, 0x6d, 0x6e, 0x6d, 0x6a, 0x68, 0x67, 0x66, + 0x62, 0x60, 0x5c, 0x59, 0x56, 0x52, 0x4d, 0x49, 0x46, 0x42, 0x3a, 0x2e, + 0x24, 0x1e, 0x16, 0x11, 0x10, 0x11, 0x11, 0x11, 0x11, 0x10, 0x11, 0x11, + 0x10, 0x11, 0x12, 0x12, 0x12, 0x12, 0x12, 0x11, 0x12, 0x12, 0x12, 0x15, + 0x82, 0x80, 0x80, 0x7f, 0x7e, 0x7c, 0x7a, 0x79, 0x78, 0x79, 0x77, 0x77, + 0x76, 0x76, 0x77, 0x76, 0x74, 0x73, 0x73, 0x72, 0x72, 0x70, 0x71, 0x73, + 0x79, 0x82, 0x88, 0x8c, 0x8d, 0x8f, 0x92, 0x93, 0x93, 0x91, 0x90, 0x91, + 0x90, 0x8f, 0x8e, 0x8e, 0x8f, 0x8e, 0x8e, 0x8d, 0x8c, 0x88, 0x85, 0x84, + 0x83, 0x82, 0x82, 0x81, 0x82, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, + 0x7d, 0x7c, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x7e, 0x7f, 0x80, 0x80, 0x81, + 0x80, 0x81, 0x81, 0x7f, 0x7e, 0x7d, 0x7d, 0x7c, 0x7b, 0x78, 0x76, 0x76, + 0x76, 0x76, 0x76, 0x75, 0x75, 0x75, 0x76, 0x75, 0x75, 0x77, 0x78, 0x79, + 0x79, 0x7a, 0x7a, 0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, + 0x7e, 0x7f, 0x7f, 0x7f, 0x7e, 0x7f, 0x80, 0x81, 0x83, 0x84, 0x85, 0x87, + 0x86, 0x87, 0x89, 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x88, 0x87, 0x88, 0x89, + 0x89, 0x89, 0x89, 0x8a, 0x8b, 0x8b, 0x8b, 0x8a, 0x8b, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8b, 0x8b, 0x8d, 0x8d, 0x8c, 0x8c, 0x8c, 0x8e, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8e, 0x8e, 0x8d, 0x8d, 0x8b, 0x8c, 0x8d, 0x8e, 0x8e, 0x8e, 0x8d, + 0x8c, 0x8c, 0x8b, 0x8c, 0x8b, 0x88, 0x88, 0x87, 0x87, 0x86, 0x87, 0x88, + 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8b, 0x8d, 0x8e, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x92, 0x93, 0x95, 0x96, 0x98, 0x98, + 0x9a, 0x9a, 0x9b, 0x9d, 0x9d, 0x9c, 0x9c, 0x9b, 0x9b, 0x9b, 0x99, 0x98, + 0x97, 0x98, 0x9a, 0x9a, 0x9a, 0x9a, 0x99, 0x98, 0x97, 0x97, 0x97, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x96, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x95, + 0x95, 0x96, 0x96, 0x96, 0x95, 0x93, 0x92, 0x93, 0x93, 0x92, 0x92, 0x92, + 0x91, 0x8d, 0x88, 0x81, 0x7c, 0x78, 0x72, 0x6d, 0x6d, 0x6e, 0x6e, 0x6f, + 0x70, 0x71, 0x71, 0x71, 0x73, 0x74, 0x72, 0x71, 0x71, 0x71, 0x71, 0x70, + 0x6d, 0x6d, 0x6d, 0x6d, 0x6a, 0x68, 0x67, 0x66, 0x63, 0x60, 0x5c, 0x59, + 0x56, 0x52, 0x4d, 0x49, 0x46, 0x42, 0x3a, 0x2f, 0x24, 0x1e, 0x16, 0x11, + 0x10, 0x11, 0x11, 0x11, 0x11, 0x10, 0x11, 0x11, 0x10, 0x11, 0x12, 0x11, + 0x11, 0x11, 0x12, 0x11, 0x11, 0x11, 0x11, 0x14, 0x82, 0x80, 0x80, 0x80, + 0x7f, 0x7e, 0x7b, 0x79, 0x79, 0x7a, 0x79, 0x78, 0x77, 0x77, 0x77, 0x74, + 0x74, 0x74, 0x73, 0x72, 0x72, 0x71, 0x71, 0x73, 0x7a, 0x83, 0x8a, 0x8d, + 0x8e, 0x8f, 0x92, 0x93, 0x92, 0x91, 0x90, 0x90, 0x8f, 0x8f, 0x8e, 0x8e, + 0x8f, 0x8e, 0x8c, 0x8b, 0x8a, 0x89, 0x86, 0x85, 0x84, 0x83, 0x83, 0x82, + 0x82, 0x82, 0x81, 0x81, 0x80, 0x81, 0x81, 0x80, 0x7e, 0x7d, 0x7d, 0x7e, + 0x7f, 0x7f, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x82, 0x80, 0x81, 0x80, 0x7f, + 0x7f, 0x7d, 0x7c, 0x7c, 0x7a, 0x79, 0x77, 0x76, 0x76, 0x75, 0x75, 0x77, + 0x77, 0x77, 0x77, 0x76, 0x76, 0x78, 0x78, 0x7a, 0x7b, 0x7b, 0x7b, 0x7b, + 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x7e, + 0x7f, 0x80, 0x80, 0x82, 0x84, 0x85, 0x86, 0x87, 0x88, 0x88, 0x89, 0x89, + 0x89, 0x8a, 0x8b, 0x8b, 0x88, 0x87, 0x88, 0x8a, 0x89, 0x8a, 0x8b, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8c, 0x8c, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x8e, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8c, 0x8c, 0x8d, 0x8d, 0x8c, 0x8b, 0x8c, + 0x8a, 0x88, 0x87, 0x87, 0x87, 0x87, 0x86, 0x87, 0x88, 0x88, 0x8a, 0x8a, + 0x89, 0x89, 0x8a, 0x8c, 0x8c, 0x8d, 0x8e, 0x8f, 0x8f, 0x8e, 0x8e, 0x8f, + 0x8f, 0x8f, 0x91, 0x93, 0x95, 0x96, 0x97, 0x98, 0x9a, 0x9a, 0x9b, 0x9d, + 0x9e, 0x9d, 0x9b, 0x9b, 0x9b, 0x9c, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x99, + 0x9a, 0x9a, 0x99, 0x99, 0x98, 0x98, 0x98, 0x97, 0x98, 0x98, 0x97, 0x97, + 0x97, 0x97, 0x98, 0x98, 0x98, 0x98, 0x98, 0x96, 0x96, 0x97, 0x98, 0x97, + 0x95, 0x95, 0x95, 0x94, 0x93, 0x94, 0x93, 0x93, 0x91, 0x8c, 0x86, 0x7f, + 0x7a, 0x76, 0x71, 0x6d, 0x6e, 0x6d, 0x6e, 0x70, 0x71, 0x71, 0x72, 0x72, + 0x73, 0x73, 0x73, 0x71, 0x70, 0x71, 0x71, 0x71, 0x6f, 0x6e, 0x6e, 0x6d, + 0x6b, 0x67, 0x66, 0x66, 0x63, 0x61, 0x5e, 0x5b, 0x57, 0x53, 0x4e, 0x4a, + 0x47, 0x43, 0x3b, 0x2e, 0x23, 0x1d, 0x16, 0x11, 0x10, 0x11, 0x11, 0x10, + 0x11, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x11, 0x12, 0x11, + 0x11, 0x12, 0x13, 0x12, 0x83, 0x81, 0x81, 0x80, 0x7f, 0x7d, 0x7d, 0x7b, + 0x7a, 0x7a, 0x79, 0x79, 0x77, 0x76, 0x77, 0x75, 0x75, 0x73, 0x72, 0x71, + 0x72, 0x71, 0x70, 0x72, 0x79, 0x83, 0x8b, 0x8e, 0x8f, 0x90, 0x92, 0x93, + 0x91, 0x91, 0x90, 0x91, 0x90, 0x8f, 0x8e, 0x8d, 0x8d, 0x8c, 0x8c, 0x8c, + 0x8a, 0x89, 0x88, 0x86, 0x86, 0x85, 0x85, 0x83, 0x83, 0x83, 0x83, 0x82, + 0x80, 0x81, 0x80, 0x7f, 0x7f, 0x7e, 0x7d, 0x7e, 0x80, 0x80, 0x7f, 0x80, + 0x80, 0x81, 0x82, 0x82, 0x81, 0x80, 0x80, 0x81, 0x80, 0x7d, 0x7d, 0x7d, + 0x7b, 0x7a, 0x78, 0x77, 0x77, 0x76, 0x77, 0x78, 0x79, 0x79, 0x78, 0x78, + 0x78, 0x79, 0x79, 0x79, 0x7b, 0x7c, 0x7b, 0x7b, 0x7c, 0x7d, 0x7d, 0x7d, + 0x7d, 0x7c, 0x7d, 0x7e, 0x7e, 0x7e, 0x7d, 0x7d, 0x80, 0x82, 0x82, 0x83, + 0x85, 0x85, 0x87, 0x88, 0x87, 0x88, 0x88, 0x89, 0x89, 0x89, 0x8c, 0x8c, + 0x8a, 0x89, 0x88, 0x89, 0x8a, 0x8a, 0x8c, 0x8c, 0x8c, 0x8c, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8c, 0x8c, 0x8e, 0x8e, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8e, 0x8f, 0x90, 0x90, 0x90, 0x8f, 0x8c, 0x8c, 0x8d, 0x8e, 0x8d, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8d, 0x8d, 0x8c, 0x8c, 0x8c, 0x8a, 0x87, 0x88, 0x87, + 0x86, 0x86, 0x86, 0x87, 0x88, 0x88, 0x89, 0x89, 0x8a, 0x8a, 0x8b, 0x8b, + 0x8c, 0x8c, 0x8d, 0x8e, 0x8e, 0x8d, 0x8d, 0x8f, 0x8f, 0x90, 0x92, 0x94, + 0x95, 0x96, 0x97, 0x97, 0x99, 0x9b, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9c, 0x9c, 0x9c, 0x9b, 0x9b, 0x9b, 0x9a, 0x9a, 0x99, 0x99, 0x99, 0x99, + 0x98, 0x98, 0x98, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98, 0x98, 0x99, + 0x99, 0x99, 0x98, 0x96, 0x96, 0x97, 0x98, 0x98, 0x95, 0x96, 0x96, 0x95, + 0x93, 0x94, 0x93, 0x92, 0x8f, 0x8a, 0x85, 0x7e, 0x78, 0x74, 0x70, 0x6e, + 0x6e, 0x6e, 0x6d, 0x6e, 0x70, 0x70, 0x72, 0x73, 0x73, 0x74, 0x74, 0x72, + 0x71, 0x71, 0x71, 0x70, 0x6f, 0x6e, 0x6f, 0x6d, 0x6b, 0x68, 0x67, 0x65, + 0x62, 0x60, 0x5e, 0x5c, 0x58, 0x53, 0x4f, 0x4c, 0x49, 0x44, 0x3b, 0x2e, + 0x24, 0x1d, 0x17, 0x12, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x11, 0x12, 0x11, 0x11, 0x13, 0x12, + 0x83, 0x81, 0x80, 0x81, 0x7f, 0x7d, 0x7e, 0x7d, 0x7b, 0x7a, 0x79, 0x78, + 0x77, 0x76, 0x76, 0x77, 0x76, 0x74, 0x73, 0x72, 0x73, 0x71, 0x70, 0x72, + 0x79, 0x83, 0x8a, 0x8e, 0x8f, 0x90, 0x92, 0x93, 0x92, 0x91, 0x90, 0x91, + 0x90, 0x90, 0x8e, 0x8d, 0x8d, 0x8b, 0x8c, 0x8c, 0x8a, 0x89, 0x89, 0x87, + 0x87, 0x87, 0x86, 0x84, 0x84, 0x84, 0x84, 0x83, 0x80, 0x81, 0x80, 0x7f, + 0x7f, 0x7e, 0x7e, 0x7e, 0x80, 0x80, 0x7f, 0x80, 0x80, 0x81, 0x82, 0x82, + 0x81, 0x81, 0x81, 0x81, 0x80, 0x7f, 0x7f, 0x7e, 0x7d, 0x7c, 0x79, 0x78, + 0x79, 0x79, 0x7a, 0x79, 0x79, 0x79, 0x78, 0x7a, 0x79, 0x78, 0x78, 0x79, + 0x7b, 0x7c, 0x7b, 0x7c, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7e, 0x7e, + 0x7e, 0x7e, 0x7d, 0x7d, 0x80, 0x82, 0x82, 0x83, 0x85, 0x86, 0x87, 0x87, + 0x87, 0x87, 0x89, 0x89, 0x89, 0x89, 0x8c, 0x8d, 0x8b, 0x8b, 0x8a, 0x8b, + 0x8b, 0x8d, 0x8e, 0x8e, 0x8d, 0x8d, 0x8e, 0x8f, 0x8f, 0x8e, 0x8e, 0x8e, + 0x8d, 0x8e, 0x8f, 0x8f, 0x8e, 0x8e, 0x8e, 0x8d, 0x8e, 0x8f, 0x90, 0x90, + 0x8f, 0x8f, 0x8c, 0x8c, 0x8c, 0x8d, 0x8d, 0x8b, 0x8c, 0x8c, 0x8c, 0x8d, + 0x8d, 0x8d, 0x8c, 0x8c, 0x8a, 0x87, 0x87, 0x87, 0x86, 0x86, 0x86, 0x87, + 0x88, 0x87, 0x88, 0x88, 0x8a, 0x8a, 0x8b, 0x8a, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8d, 0x8c, 0x8d, 0x8e, 0x8f, 0x91, 0x92, 0x94, 0x95, 0x95, 0x95, 0x96, + 0x9a, 0x9b, 0x9c, 0x9d, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9c, 0x9b, + 0x9a, 0x9a, 0x9b, 0x9b, 0x9a, 0x9a, 0x99, 0x98, 0x98, 0x98, 0x98, 0x97, + 0x97, 0x97, 0x98, 0x99, 0x9a, 0x99, 0x99, 0x98, 0x98, 0x98, 0x98, 0x96, + 0x96, 0x97, 0x98, 0x98, 0x96, 0x96, 0x96, 0x94, 0x94, 0x94, 0x93, 0x91, + 0x8e, 0x8a, 0x84, 0x7d, 0x77, 0x74, 0x6f, 0x6c, 0x6d, 0x6d, 0x6c, 0x6d, + 0x70, 0x71, 0x73, 0x73, 0x72, 0x74, 0x74, 0x73, 0x72, 0x72, 0x70, 0x70, + 0x6f, 0x6e, 0x6e, 0x6c, 0x6c, 0x69, 0x69, 0x66, 0x62, 0x60, 0x5d, 0x5c, + 0x59, 0x55, 0x4f, 0x4b, 0x48, 0x44, 0x3b, 0x2f, 0x25, 0x1e, 0x17, 0x12, + 0x11, 0x11, 0x11, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x12, 0x12, 0x12, 0x11, 0x11, 0x11, 0x13, 0x83, 0x81, 0x81, 0x81, + 0x80, 0x7e, 0x7e, 0x7d, 0x7c, 0x7a, 0x79, 0x78, 0x77, 0x77, 0x77, 0x78, + 0x77, 0x74, 0x73, 0x73, 0x72, 0x71, 0x71, 0x73, 0x7a, 0x83, 0x8a, 0x8d, + 0x8e, 0x90, 0x92, 0x93, 0x92, 0x91, 0x90, 0x90, 0x90, 0x8f, 0x8e, 0x8d, + 0x8d, 0x8b, 0x8c, 0x8c, 0x8a, 0x89, 0x89, 0x88, 0x88, 0x88, 0x87, 0x84, + 0x84, 0x84, 0x85, 0x83, 0x80, 0x81, 0x81, 0x7f, 0x7f, 0x7e, 0x7e, 0x7e, + 0x80, 0x80, 0x80, 0x81, 0x81, 0x81, 0x82, 0x82, 0x81, 0x81, 0x81, 0x81, + 0x80, 0x7f, 0x7f, 0x7e, 0x7d, 0x7c, 0x7a, 0x7a, 0x7a, 0x7b, 0x7c, 0x7a, + 0x7a, 0x7a, 0x79, 0x7a, 0x79, 0x78, 0x77, 0x78, 0x7b, 0x7c, 0x7c, 0x7c, + 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7e, 0x7e, 0x7d, 0x7d, + 0x80, 0x82, 0x82, 0x83, 0x85, 0x86, 0x87, 0x87, 0x88, 0x88, 0x89, 0x89, + 0x89, 0x8a, 0x8c, 0x8d, 0x8c, 0x8b, 0x8b, 0x8b, 0x8c, 0x8e, 0x8e, 0x8e, + 0x8d, 0x8d, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8e, 0x8e, 0x8f, 0x90, 0x90, + 0x8e, 0x8f, 0x8f, 0x8d, 0x8e, 0x8f, 0x90, 0x90, 0x8e, 0x8e, 0x8c, 0x8b, + 0x8c, 0x8d, 0x8d, 0x8c, 0x8c, 0x8c, 0x8c, 0x8d, 0x8d, 0x8d, 0x8c, 0x8b, + 0x8a, 0x88, 0x88, 0x87, 0x86, 0x87, 0x87, 0x88, 0x88, 0x87, 0x88, 0x88, + 0x8a, 0x8a, 0x8b, 0x8a, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8d, 0x8f, + 0x8f, 0x91, 0x91, 0x93, 0x94, 0x95, 0x94, 0x96, 0x9a, 0x9b, 0x9c, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9c, 0x9b, 0x9a, 0x9a, 0x9c, 0x9c, + 0x9b, 0x9a, 0x98, 0x98, 0x99, 0x98, 0x98, 0x97, 0x97, 0x97, 0x99, 0x99, + 0x9a, 0x99, 0x9a, 0x99, 0x98, 0x99, 0x99, 0x97, 0x97, 0x98, 0x99, 0x98, + 0x97, 0x96, 0x95, 0x94, 0x95, 0x94, 0x92, 0x90, 0x8d, 0x89, 0x83, 0x7c, + 0x77, 0x73, 0x6f, 0x6c, 0x6d, 0x6d, 0x6d, 0x6d, 0x70, 0x71, 0x72, 0x73, + 0x73, 0x74, 0x74, 0x73, 0x73, 0x72, 0x71, 0x71, 0x6f, 0x6e, 0x6e, 0x6c, + 0x6c, 0x6a, 0x69, 0x67, 0x63, 0x60, 0x5d, 0x5c, 0x5a, 0x55, 0x4f, 0x4b, + 0x48, 0x44, 0x3c, 0x30, 0x26, 0x1f, 0x17, 0x13, 0x11, 0x11, 0x11, 0x10, + 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x11, + 0x11, 0x11, 0x11, 0x13, 0x83, 0x82, 0x81, 0x81, 0x81, 0x7e, 0x7e, 0x7d, + 0x7c, 0x7b, 0x7b, 0x79, 0x78, 0x78, 0x79, 0x78, 0x75, 0x75, 0x74, 0x73, + 0x71, 0x70, 0x71, 0x73, 0x79, 0x82, 0x8a, 0x8c, 0x8e, 0x8f, 0x92, 0x93, + 0x92, 0x91, 0x90, 0x8f, 0x8f, 0x8e, 0x8e, 0x8e, 0x8c, 0x8d, 0x8c, 0x8c, + 0x8c, 0x8a, 0x8a, 0x89, 0x89, 0x88, 0x86, 0x86, 0x84, 0x84, 0x84, 0x84, + 0x81, 0x81, 0x81, 0x80, 0x7e, 0x7f, 0x7e, 0x7f, 0x7f, 0x80, 0x81, 0x81, + 0x83, 0x83, 0x82, 0x82, 0x82, 0x82, 0x82, 0x81, 0x80, 0x80, 0x7f, 0x7f, + 0x7e, 0x7d, 0x7d, 0x7c, 0x7c, 0x7d, 0x7d, 0x7c, 0x7d, 0x7c, 0x7b, 0x79, + 0x79, 0x78, 0x78, 0x79, 0x7b, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, + 0x7d, 0x7d, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, 0x7d, 0x80, 0x82, 0x82, 0x83, + 0x84, 0x86, 0x87, 0x88, 0x88, 0x89, 0x8a, 0x8a, 0x89, 0x8b, 0x8c, 0x8d, + 0x8d, 0x8c, 0x8b, 0x8c, 0x8d, 0x8e, 0x8d, 0x8d, 0x8d, 0x8d, 0x8f, 0x8f, + 0x90, 0x90, 0x90, 0x8e, 0x8f, 0x8f, 0x90, 0x8f, 0x8f, 0x90, 0x90, 0x8e, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8d, 0x8e, 0x8c, 0x8c, 0x8d, 0x8e, 0x8e, 0x8d, + 0x8d, 0x8d, 0x8c, 0x8d, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x89, 0x88, 0x88, + 0x87, 0x88, 0x87, 0x88, 0x88, 0x88, 0x89, 0x8a, 0x8a, 0x8a, 0x8b, 0x8b, + 0x8c, 0x8b, 0x8c, 0x8c, 0x8c, 0x8c, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x91, + 0x93, 0x94, 0x94, 0x97, 0x9a, 0x9a, 0x9b, 0x9d, 0x9d, 0x9d, 0x9d, 0x9c, + 0x9c, 0x9c, 0x9d, 0x9c, 0x9c, 0x9c, 0x9c, 0x9d, 0x9c, 0x9b, 0x99, 0x99, + 0x9a, 0x99, 0x98, 0x97, 0x96, 0x99, 0x9a, 0x9a, 0x9b, 0x9a, 0x9a, 0x9a, + 0x9a, 0x9a, 0x99, 0x98, 0x99, 0x99, 0x99, 0x99, 0x97, 0x96, 0x95, 0x94, + 0x94, 0x93, 0x92, 0x90, 0x8c, 0x87, 0x81, 0x79, 0x74, 0x71, 0x6e, 0x6c, + 0x6c, 0x6d, 0x6e, 0x6e, 0x70, 0x71, 0x71, 0x72, 0x73, 0x72, 0x74, 0x74, + 0x74, 0x73, 0x73, 0x72, 0x6f, 0x6e, 0x6e, 0x6c, 0x6c, 0x6a, 0x69, 0x69, + 0x64, 0x60, 0x5e, 0x5c, 0x59, 0x55, 0x4f, 0x4a, 0x47, 0x43, 0x3b, 0x2f, + 0x27, 0x21, 0x17, 0x12, 0x12, 0x11, 0x11, 0x11, 0x10, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, + 0x83, 0x81, 0x80, 0x80, 0x80, 0x7e, 0x7e, 0x7d, 0x7d, 0x7c, 0x7b, 0x79, + 0x78, 0x79, 0x79, 0x77, 0x75, 0x75, 0x74, 0x73, 0x71, 0x70, 0x71, 0x74, + 0x79, 0x82, 0x88, 0x8c, 0x8d, 0x8e, 0x92, 0x93, 0x92, 0x91, 0x91, 0x8f, + 0x8f, 0x8d, 0x8d, 0x8d, 0x8c, 0x8c, 0x8c, 0x8b, 0x8c, 0x8a, 0x8a, 0x89, + 0x88, 0x88, 0x87, 0x87, 0x85, 0x84, 0x83, 0x83, 0x81, 0x80, 0x80, 0x80, + 0x7f, 0x7f, 0x7f, 0x7f, 0x81, 0x82, 0x83, 0x83, 0x83, 0x83, 0x83, 0x84, + 0x84, 0x84, 0x83, 0x82, 0x82, 0x81, 0x7f, 0x7f, 0x80, 0x7f, 0x7f, 0x7e, + 0x7f, 0x7f, 0x7f, 0x7d, 0x7e, 0x7d, 0x7c, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, + 0x7a, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7c, 0x7c, 0x7c, + 0x7d, 0x7d, 0x7d, 0x7d, 0x80, 0x81, 0x81, 0x83, 0x83, 0x86, 0x87, 0x88, + 0x89, 0x8b, 0x8c, 0x8a, 0x8b, 0x8d, 0x8e, 0x8e, 0x8e, 0x8c, 0x8c, 0x8c, + 0x8d, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x90, 0x8f, 0x90, 0x91, 0x91, 0x90, + 0x8f, 0x8f, 0x8f, 0x90, 0x8f, 0x8f, 0x90, 0x91, 0x90, 0x8f, 0x90, 0x8f, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8f, 0x8d, 0x8d, 0x8d, 0x8c, 0x8d, + 0x8d, 0x8c, 0x8b, 0x89, 0x89, 0x89, 0x89, 0x88, 0x88, 0x88, 0x87, 0x87, + 0x87, 0x87, 0x89, 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8b, 0x8b, 0x8c, 0x8d, + 0x8c, 0x8c, 0x8e, 0x8f, 0x8f, 0x90, 0x90, 0x91, 0x92, 0x93, 0x94, 0x97, + 0x99, 0x9a, 0x9b, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9c, 0x9c, 0x9d, 0x9d, + 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9a, 0x99, 0x9a, 0x99, 0x97, 0x96, + 0x97, 0x99, 0x99, 0x9a, 0x9a, 0x9b, 0x9a, 0x99, 0x9a, 0x9b, 0x9b, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x97, 0x96, 0x96, 0x97, 0x96, 0x94, 0x90, 0x8e, + 0x8b, 0x85, 0x7e, 0x77, 0x72, 0x6f, 0x6b, 0x6b, 0x6c, 0x6d, 0x6d, 0x6e, + 0x6e, 0x70, 0x70, 0x71, 0x72, 0x72, 0x74, 0x75, 0x74, 0x74, 0x74, 0x72, + 0x71, 0x70, 0x70, 0x6f, 0x6d, 0x6c, 0x6a, 0x69, 0x65, 0x62, 0x5e, 0x5c, + 0x59, 0x55, 0x4f, 0x4a, 0x47, 0x43, 0x3a, 0x2f, 0x27, 0x21, 0x17, 0x11, + 0x11, 0x11, 0x10, 0x11, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x13, 0x82, 0x82, 0x81, 0x80, + 0x80, 0x80, 0x7f, 0x7e, 0x7d, 0x7c, 0x7c, 0x7a, 0x7a, 0x7a, 0x79, 0x77, + 0x76, 0x74, 0x74, 0x73, 0x71, 0x70, 0x71, 0x74, 0x7b, 0x82, 0x88, 0x8c, + 0x8d, 0x8f, 0x92, 0x93, 0x92, 0x91, 0x90, 0x90, 0x8e, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8c, 0x8c, 0x8c, 0x8b, 0x8a, 0x89, 0x89, 0x89, 0x89, 0x88, + 0x88, 0x86, 0x84, 0x82, 0x81, 0x81, 0x81, 0x80, 0x81, 0x81, 0x80, 0x81, + 0x82, 0x82, 0x83, 0x84, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x83, + 0x82, 0x81, 0x81, 0x81, 0x82, 0x81, 0x81, 0x82, 0x81, 0x80, 0x80, 0x7f, + 0x7e, 0x7e, 0x7d, 0x7b, 0x7c, 0x7c, 0x7b, 0x7a, 0x7a, 0x7c, 0x7c, 0x7c, + 0x7d, 0x7d, 0x7c, 0x7c, 0x7d, 0x7c, 0x7d, 0x7c, 0x7d, 0x7d, 0x7d, 0x7f, + 0x80, 0x80, 0x81, 0x82, 0x84, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, + 0x8c, 0x8e, 0x8e, 0x8e, 0x8e, 0x8d, 0x8c, 0x8d, 0x8d, 0x8f, 0x90, 0x90, + 0x8f, 0x90, 0x91, 0x90, 0x91, 0x91, 0x91, 0x91, 0x90, 0x8f, 0x8f, 0x91, + 0x91, 0x90, 0x90, 0x91, 0x91, 0x90, 0x91, 0x90, 0x8f, 0x8f, 0x90, 0x90, + 0x90, 0x8f, 0x8e, 0x8d, 0x8e, 0x8e, 0x8e, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, + 0x8a, 0x89, 0x88, 0x88, 0x88, 0x87, 0x87, 0x87, 0x87, 0x87, 0x89, 0x89, + 0x87, 0x87, 0x88, 0x88, 0x8a, 0x8b, 0x8b, 0x8c, 0x8c, 0x8c, 0x8e, 0x8f, + 0x90, 0x8f, 0x91, 0x92, 0x92, 0x92, 0x93, 0x95, 0x98, 0x9a, 0x9b, 0x9c, + 0x9b, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9b, 0x9b, 0x9b, 0x9a, 0x98, 0x97, 0x97, 0x97, 0x99, 0x99, + 0x9a, 0x9b, 0x9b, 0x9a, 0x9b, 0x9c, 0x9c, 0x9a, 0x9a, 0x9a, 0x9b, 0x9a, + 0x97, 0x96, 0x97, 0x97, 0x96, 0x92, 0x8f, 0x8c, 0x88, 0x82, 0x7d, 0x76, + 0x70, 0x6c, 0x6a, 0x6a, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x70, + 0x72, 0x73, 0x75, 0x75, 0x75, 0x74, 0x74, 0x73, 0x72, 0x71, 0x71, 0x6f, + 0x6e, 0x6c, 0x6a, 0x67, 0x65, 0x62, 0x5e, 0x5b, 0x59, 0x55, 0x4f, 0x4a, + 0x47, 0x43, 0x3b, 0x2f, 0x26, 0x20, 0x18, 0x12, 0x11, 0x10, 0x10, 0x10, + 0x10, 0x11, 0x10, 0x11, 0x12, 0x12, 0x12, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x12, 0x12, 0x83, 0x83, 0x82, 0x82, 0x80, 0x80, 0x7f, 0x7e, + 0x7c, 0x7c, 0x7b, 0x7a, 0x7a, 0x7a, 0x79, 0x79, 0x77, 0x76, 0x75, 0x73, + 0x72, 0x71, 0x72, 0x74, 0x7a, 0x83, 0x89, 0x8d, 0x8e, 0x8f, 0x92, 0x93, + 0x92, 0x91, 0x90, 0x90, 0x8e, 0x8e, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8b, 0x8b, 0x8a, 0x8a, 0x8a, 0x89, 0x89, 0x89, 0x88, 0x85, 0x83, + 0x83, 0x82, 0x82, 0x82, 0x83, 0x82, 0x82, 0x82, 0x83, 0x83, 0x83, 0x85, + 0x85, 0x86, 0x87, 0x87, 0x86, 0x86, 0x86, 0x85, 0x83, 0x82, 0x82, 0x82, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x81, 0x80, 0x81, 0x7f, 0x7e, 0x7d, 0x7d, + 0x7d, 0x7c, 0x7b, 0x7b, 0x7b, 0x7c, 0x7d, 0x7d, 0x7d, 0x7d, 0x7c, 0x7c, + 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7e, 0x80, 0x80, 0x81, 0x81, 0x83, + 0x85, 0x87, 0x88, 0x89, 0x8a, 0x8c, 0x8c, 0x8c, 0x8d, 0x8d, 0x8f, 0x8f, + 0x8f, 0x8d, 0x8d, 0x8e, 0x8e, 0x8f, 0x90, 0x90, 0x90, 0x90, 0x91, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x90, 0x90, 0x91, 0x92, 0x91, 0x90, 0x91, + 0x90, 0x91, 0x92, 0x91, 0x90, 0x90, 0x91, 0x91, 0x91, 0x90, 0x8f, 0x8d, + 0x8e, 0x8f, 0x8e, 0x8d, 0x8e, 0x8c, 0x8b, 0x8b, 0x8b, 0x8a, 0x8a, 0x8a, + 0x89, 0x88, 0x89, 0x89, 0x89, 0x89, 0x88, 0x87, 0x87, 0x86, 0x87, 0x88, + 0x8a, 0x8a, 0x8b, 0x8c, 0x8b, 0x8d, 0x8e, 0x8f, 0x8f, 0x90, 0x92, 0x92, + 0x92, 0x92, 0x93, 0x96, 0x98, 0x9a, 0x9a, 0x9b, 0x9a, 0x9a, 0x9c, 0x9c, + 0x9d, 0x9c, 0x9d, 0x9e, 0x9e, 0x9d, 0x9c, 0x9c, 0x9d, 0x9d, 0x9c, 0x9c, + 0x9a, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a, 0x9a, 0x9c, 0x9c, + 0x9c, 0x9d, 0x9d, 0x9b, 0x9b, 0x9b, 0x9c, 0x9b, 0x98, 0x97, 0x98, 0x98, + 0x95, 0x90, 0x8d, 0x8a, 0x86, 0x80, 0x7b, 0x73, 0x6e, 0x6b, 0x68, 0x68, + 0x6a, 0x6b, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x72, 0x72, 0x74, 0x74, + 0x74, 0x74, 0x74, 0x74, 0x72, 0x71, 0x72, 0x70, 0x6e, 0x6c, 0x6a, 0x68, + 0x64, 0x62, 0x5e, 0x5b, 0x58, 0x55, 0x50, 0x4b, 0x48, 0x42, 0x3b, 0x30, + 0x26, 0x20, 0x19, 0x13, 0x12, 0x12, 0x12, 0x10, 0x11, 0x10, 0x10, 0x11, + 0x12, 0x12, 0x13, 0x12, 0x11, 0x11, 0x11, 0x13, 0x11, 0x11, 0x13, 0x13, + 0x82, 0x83, 0x82, 0x82, 0x80, 0x80, 0x7f, 0x7d, 0x7c, 0x7b, 0x7b, 0x7a, + 0x7a, 0x7a, 0x79, 0x79, 0x78, 0x76, 0x75, 0x73, 0x72, 0x71, 0x71, 0x74, + 0x7a, 0x83, 0x89, 0x8c, 0x8e, 0x8f, 0x92, 0x93, 0x92, 0x91, 0x90, 0x8f, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8d, 0x8e, 0x8e, 0x8d, 0x8d, 0x8c, 0x8c, 0x8b, + 0x8b, 0x8b, 0x8a, 0x8a, 0x89, 0x88, 0x86, 0x84, 0x83, 0x83, 0x83, 0x82, + 0x83, 0x83, 0x83, 0x83, 0x84, 0x83, 0x84, 0x86, 0x86, 0x87, 0x88, 0x88, + 0x87, 0x87, 0x87, 0x85, 0x83, 0x82, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x82, 0x81, 0x82, 0x80, 0x7f, 0x7e, 0x7d, 0x7d, 0x7c, 0x7b, 0x7b, + 0x7b, 0x7c, 0x7d, 0x7d, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7b, + 0x7d, 0x7d, 0x7e, 0x80, 0x80, 0x81, 0x82, 0x83, 0x85, 0x87, 0x89, 0x8a, + 0x8b, 0x8c, 0x8d, 0x8d, 0x8d, 0x8d, 0x8f, 0x8f, 0x8f, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8f, 0x90, 0x90, 0x91, 0x91, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x91, 0x91, 0x91, 0x91, 0x92, 0x91, 0x90, 0x90, 0x90, 0x91, 0x92, 0x91, + 0x90, 0x90, 0x91, 0x91, 0x90, 0x8f, 0x8f, 0x8d, 0x8e, 0x8f, 0x8f, 0x8e, + 0x8d, 0x8c, 0x8b, 0x8b, 0x8b, 0x8a, 0x8b, 0x8a, 0x8a, 0x88, 0x8a, 0x8a, + 0x8a, 0x8a, 0x87, 0x87, 0x87, 0x87, 0x88, 0x89, 0x8a, 0x8a, 0x8b, 0x8b, + 0x8b, 0x8c, 0x8d, 0x8f, 0x8f, 0x8f, 0x92, 0x92, 0x92, 0x92, 0x93, 0x96, + 0x98, 0x99, 0x9a, 0x9a, 0x99, 0x99, 0x9b, 0x9c, 0x9d, 0x9c, 0x9d, 0x9e, + 0x9e, 0x9d, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9c, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x9a, 0x9a, 0x9b, 0x9a, 0x9c, 0x9d, 0x9d, 0x9d, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9d, 0x9c, 0x99, 0x98, 0x98, 0x98, 0x94, 0x8f, 0x8c, 0x89, + 0x84, 0x7f, 0x79, 0x71, 0x6c, 0x69, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, + 0x6c, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x74, 0x74, 0x74, 0x73, 0x74, 0x74, + 0x72, 0x71, 0x72, 0x6f, 0x6e, 0x6c, 0x6a, 0x68, 0x64, 0x62, 0x5e, 0x5c, + 0x58, 0x55, 0x50, 0x4b, 0x48, 0x41, 0x3b, 0x30, 0x26, 0x20, 0x18, 0x13, + 0x12, 0x12, 0x12, 0x10, 0x11, 0x10, 0x10, 0x11, 0x12, 0x12, 0x13, 0x12, + 0x11, 0x11, 0x12, 0x13, 0x12, 0x12, 0x13, 0x14, 0x82, 0x82, 0x82, 0x81, + 0x80, 0x80, 0x7f, 0x7d, 0x7c, 0x7c, 0x7b, 0x7a, 0x7a, 0x7a, 0x79, 0x79, + 0x77, 0x77, 0x76, 0x73, 0x72, 0x71, 0x71, 0x73, 0x79, 0x82, 0x88, 0x8b, + 0x8c, 0x8e, 0x91, 0x92, 0x91, 0x91, 0x8f, 0x8f, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8d, 0x8e, 0x8e, 0x8d, 0x8e, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8b, 0x8b, + 0x8a, 0x89, 0x87, 0x85, 0x84, 0x84, 0x84, 0x83, 0x84, 0x84, 0x83, 0x84, + 0x85, 0x85, 0x86, 0x87, 0x87, 0x87, 0x88, 0x89, 0x87, 0x88, 0x88, 0x86, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x83, 0x83, 0x84, 0x84, 0x83, 0x83, 0x82, + 0x81, 0x80, 0x7f, 0x7d, 0x7d, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, + 0x7d, 0x7d, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7b, 0x7d, 0x7d, 0x7e, 0x80, + 0x81, 0x82, 0x83, 0x83, 0x85, 0x87, 0x89, 0x8a, 0x8b, 0x8c, 0x8e, 0x8e, + 0x8d, 0x8d, 0x8e, 0x8e, 0x8f, 0x90, 0x8f, 0x90, 0x8f, 0x8f, 0x90, 0x91, + 0x91, 0x92, 0x94, 0x94, 0x93, 0x93, 0x93, 0x93, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x90, 0x90, 0x91, 0x91, 0x92, 0x91, 0x90, 0x90, 0x91, 0x91, + 0x91, 0x90, 0x8f, 0x8d, 0x8e, 0x8e, 0x8f, 0x8d, 0x8d, 0x8c, 0x8b, 0x8b, + 0x8b, 0x8a, 0x8a, 0x8a, 0x89, 0x88, 0x8a, 0x8a, 0x8a, 0x8a, 0x88, 0x87, + 0x86, 0x87, 0x88, 0x89, 0x8a, 0x89, 0x8a, 0x8b, 0x8b, 0x8d, 0x8d, 0x8f, + 0x8f, 0x8f, 0x91, 0x92, 0x92, 0x92, 0x93, 0x96, 0x98, 0x98, 0x99, 0x9a, + 0x99, 0x9a, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9d, 0x9c, 0x9c, + 0x9c, 0x9d, 0x9d, 0x9c, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, + 0x9b, 0x9a, 0x9b, 0x9d, 0x9d, 0x9c, 0x9b, 0x9c, 0x9b, 0x9c, 0x9d, 0x9c, + 0x9a, 0x9a, 0x99, 0x96, 0x92, 0x8d, 0x89, 0x87, 0x82, 0x7b, 0x76, 0x6e, + 0x69, 0x67, 0x66, 0x66, 0x69, 0x69, 0x6a, 0x6b, 0x6b, 0x6d, 0x6e, 0x6f, + 0x70, 0x70, 0x73, 0x73, 0x73, 0x74, 0x74, 0x74, 0x72, 0x71, 0x71, 0x6f, + 0x6e, 0x6c, 0x6b, 0x69, 0x64, 0x61, 0x5e, 0x5c, 0x58, 0x55, 0x50, 0x4a, + 0x46, 0x42, 0x3a, 0x2f, 0x26, 0x20, 0x17, 0x13, 0x11, 0x11, 0x11, 0x10, + 0x11, 0x10, 0x10, 0x11, 0x11, 0x11, 0x12, 0x11, 0x11, 0x12, 0x12, 0x11, + 0x11, 0x11, 0x11, 0x14, 0x83, 0x83, 0x83, 0x82, 0x80, 0x7e, 0x7e, 0x7d, + 0x7c, 0x7d, 0x7d, 0x7b, 0x79, 0x79, 0x7a, 0x79, 0x78, 0x77, 0x76, 0x75, + 0x73, 0x72, 0x72, 0x73, 0x77, 0x80, 0x86, 0x89, 0x8a, 0x8c, 0x8f, 0x92, + 0x92, 0x91, 0x90, 0x8f, 0x8e, 0x8e, 0x8e, 0x8d, 0x8d, 0x8d, 0x8d, 0x8e, + 0x8e, 0x8d, 0x8e, 0x8e, 0x8f, 0x8e, 0x8c, 0x8c, 0x8c, 0x8b, 0x88, 0x87, + 0x86, 0x85, 0x84, 0x83, 0x84, 0x85, 0x86, 0x86, 0x85, 0x86, 0x88, 0x89, + 0x88, 0x88, 0x89, 0x8a, 0x89, 0x89, 0x89, 0x88, 0x87, 0x86, 0x86, 0x86, + 0x85, 0x86, 0x85, 0x86, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x7f, 0x7e, + 0x7e, 0x7e, 0x7e, 0x7c, 0x7c, 0x7e, 0x7e, 0x7e, 0x7d, 0x7d, 0x7b, 0x7b, + 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, 0x7f, 0x80, 0x81, 0x81, 0x82, 0x84, + 0x86, 0x87, 0x88, 0x89, 0x8b, 0x8c, 0x8f, 0x8f, 0x8f, 0x8f, 0x90, 0x8f, + 0x8f, 0x90, 0x90, 0x90, 0x90, 0x90, 0x91, 0x91, 0x93, 0x93, 0x94, 0x94, + 0x94, 0x93, 0x93, 0x93, 0x92, 0x92, 0x93, 0x93, 0x93, 0x92, 0x92, 0x92, + 0x93, 0x93, 0x92, 0x92, 0x91, 0x90, 0x90, 0x90, 0x8f, 0x8e, 0x8f, 0x8e, + 0x8e, 0x8e, 0x8f, 0x8d, 0x8d, 0x8c, 0x8c, 0x8c, 0x8c, 0x8a, 0x8a, 0x8a, + 0x8b, 0x89, 0x8a, 0x8a, 0x8a, 0x89, 0x89, 0x88, 0x87, 0x87, 0x88, 0x88, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8c, 0x8d, 0x8c, 0x8e, 0x8e, 0x8f, 0x91, 0x92, + 0x92, 0x93, 0x94, 0x95, 0x96, 0x96, 0x97, 0x98, 0x9b, 0x9c, 0x9b, 0x9c, + 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9d, 0x9d, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9c, 0x9c, 0x9b, 0x9b, 0x9a, 0x9b, 0x9b, 0x9b, 0x9a, 0x9c, 0x9b, 0x9b, + 0x9c, 0x9c, 0x9c, 0x9d, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9b, 0x9a, 0x96, + 0x91, 0x8b, 0x85, 0x82, 0x7d, 0x79, 0x72, 0x6b, 0x67, 0x66, 0x65, 0x66, + 0x68, 0x69, 0x69, 0x69, 0x6b, 0x6c, 0x6e, 0x6e, 0x6f, 0x70, 0x73, 0x74, + 0x74, 0x73, 0x73, 0x72, 0x72, 0x72, 0x71, 0x70, 0x6e, 0x6d, 0x6c, 0x69, + 0x64, 0x61, 0x5f, 0x5d, 0x58, 0x54, 0x4f, 0x4a, 0x46, 0x41, 0x38, 0x2f, + 0x26, 0x20, 0x19, 0x13, 0x11, 0x11, 0x10, 0x10, 0x11, 0x11, 0x10, 0x10, + 0x10, 0x11, 0x12, 0x11, 0x11, 0x12, 0x12, 0x11, 0x10, 0x11, 0x12, 0x13, + 0x84, 0x84, 0x83, 0x82, 0x80, 0x7e, 0x7e, 0x7d, 0x7d, 0x7e, 0x7d, 0x7b, + 0x79, 0x79, 0x79, 0x78, 0x79, 0x78, 0x77, 0x75, 0x73, 0x72, 0x72, 0x73, + 0x77, 0x7f, 0x85, 0x88, 0x8a, 0x8c, 0x8f, 0x92, 0x92, 0x91, 0x90, 0x8f, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8c, 0x8e, 0x8e, 0x8d, 0x8d, 0x8e, 0x8f, + 0x90, 0x8f, 0x8d, 0x8d, 0x8d, 0x8c, 0x8a, 0x88, 0x87, 0x86, 0x85, 0x86, + 0x85, 0x86, 0x87, 0x87, 0x87, 0x89, 0x8b, 0x8b, 0x8a, 0x8a, 0x8b, 0x8a, + 0x8a, 0x8b, 0x8a, 0x89, 0x89, 0x88, 0x88, 0x88, 0x88, 0x87, 0x87, 0x87, + 0x88, 0x87, 0x85, 0x83, 0x82, 0x81, 0x81, 0x7f, 0x7f, 0x80, 0x80, 0x7e, + 0x7d, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, + 0x7d, 0x7d, 0x80, 0x82, 0x82, 0x82, 0x83, 0x85, 0x87, 0x88, 0x8a, 0x8a, + 0x8b, 0x8d, 0x8d, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x8f, + 0x91, 0x92, 0x92, 0x93, 0x94, 0x94, 0x93, 0x94, 0x94, 0x93, 0x94, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x94, 0x93, 0x93, 0x92, 0x94, 0x94, 0x92, 0x91, + 0x91, 0x90, 0x90, 0x90, 0x8f, 0x8e, 0x8f, 0x8e, 0x8e, 0x8e, 0x8f, 0x8d, + 0x8d, 0x8d, 0x8c, 0x8d, 0x8c, 0x8a, 0x8a, 0x8a, 0x8a, 0x89, 0x89, 0x8a, + 0x8a, 0x89, 0x89, 0x87, 0x87, 0x88, 0x87, 0x87, 0x88, 0x89, 0x89, 0x89, + 0x8c, 0x8d, 0x8d, 0x8e, 0x8e, 0x8f, 0x91, 0x92, 0x92, 0x93, 0x94, 0x95, + 0x95, 0x96, 0x97, 0x98, 0x9b, 0x9d, 0x9c, 0x9c, 0x9d, 0x9c, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9c, 0x9b, 0x9a, + 0x9b, 0x9c, 0x9c, 0x9c, 0x9b, 0x9c, 0x9b, 0x9a, 0x9b, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9e, 0x9e, 0x9c, 0x9a, 0x98, 0x94, 0x8e, 0x87, 0x81, 0x7e, + 0x7a, 0x75, 0x6e, 0x69, 0x65, 0x65, 0x65, 0x65, 0x66, 0x68, 0x69, 0x68, + 0x6a, 0x6b, 0x6d, 0x6e, 0x6d, 0x6e, 0x71, 0x73, 0x73, 0x72, 0x72, 0x72, + 0x72, 0x72, 0x71, 0x71, 0x6e, 0x6d, 0x6c, 0x68, 0x65, 0x62, 0x60, 0x5d, + 0x58, 0x54, 0x4f, 0x4b, 0x48, 0x41, 0x37, 0x2e, 0x26, 0x21, 0x18, 0x12, + 0x11, 0x10, 0x10, 0x11, 0x11, 0x12, 0x11, 0x10, 0x10, 0x11, 0x11, 0x12, + 0x12, 0x12, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x83, 0x83, 0x83, 0x83, + 0x81, 0x7f, 0x7f, 0x7d, 0x7d, 0x7d, 0x7c, 0x7a, 0x7a, 0x79, 0x79, 0x78, + 0x79, 0x78, 0x77, 0x75, 0x73, 0x73, 0x72, 0x73, 0x77, 0x7e, 0x83, 0x86, + 0x88, 0x8b, 0x90, 0x93, 0x93, 0x92, 0x91, 0x8f, 0x8e, 0x8e, 0x8e, 0x8d, + 0x8e, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8f, 0x8f, 0x90, 0x8f, 0x8e, 0x8d, + 0x8d, 0x8d, 0x8b, 0x89, 0x88, 0x87, 0x87, 0x87, 0x86, 0x86, 0x88, 0x88, + 0x89, 0x8a, 0x8c, 0x8c, 0x8d, 0x8d, 0x8d, 0x8c, 0x8b, 0x8a, 0x8a, 0x8a, + 0x89, 0x89, 0x8a, 0x8a, 0x89, 0x88, 0x87, 0x87, 0x88, 0x87, 0x85, 0x83, + 0x83, 0x82, 0x81, 0x80, 0x80, 0x81, 0x81, 0x7f, 0x7e, 0x7d, 0x7e, 0x7e, + 0x7e, 0x7e, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7e, 0x7f, 0x7f, 0x81, 0x82, + 0x83, 0x84, 0x85, 0x86, 0x88, 0x8a, 0x8b, 0x8c, 0x8b, 0x8d, 0x8e, 0x8f, + 0x8f, 0x8f, 0x90, 0x90, 0x8f, 0x90, 0x90, 0x90, 0x91, 0x93, 0x93, 0x94, + 0x95, 0x95, 0x94, 0x95, 0x94, 0x94, 0x94, 0x94, 0x93, 0x92, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x92, 0x91, 0x91, 0x90, 0x91, + 0x91, 0x90, 0x90, 0x8f, 0x8f, 0x8f, 0x8f, 0x8e, 0x8e, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8b, 0x8b, 0x8b, 0x8b, 0x89, 0x8a, 0x89, 0x89, 0x88, 0x89, 0x88, + 0x88, 0x88, 0x88, 0x87, 0x88, 0x87, 0x88, 0x89, 0x8b, 0x8d, 0x8d, 0x8e, + 0x8f, 0x8f, 0x92, 0x92, 0x93, 0x93, 0x94, 0x95, 0x95, 0x96, 0x98, 0x99, + 0x9b, 0x9c, 0x9c, 0x9c, 0x9d, 0x9c, 0x9d, 0x9e, 0x9e, 0x9d, 0x9c, 0x9b, + 0x9c, 0x9c, 0x9b, 0x9c, 0x9c, 0x9b, 0x9b, 0x9a, 0x9c, 0x9d, 0x9d, 0x9d, + 0x9c, 0x9b, 0x9c, 0x9b, 0x9c, 0x9d, 0x9c, 0x9c, 0x9c, 0x9d, 0x9f, 0x9e, + 0x9c, 0x99, 0x97, 0x93, 0x8c, 0x84, 0x7f, 0x7b, 0x78, 0x73, 0x6c, 0x66, + 0x64, 0x64, 0x65, 0x65, 0x66, 0x67, 0x68, 0x68, 0x68, 0x6a, 0x6b, 0x6c, + 0x6c, 0x6d, 0x70, 0x71, 0x71, 0x71, 0x71, 0x73, 0x73, 0x73, 0x72, 0x71, + 0x6f, 0x6d, 0x6c, 0x69, 0x66, 0x62, 0x60, 0x5e, 0x59, 0x54, 0x4f, 0x4a, + 0x46, 0x3f, 0x38, 0x2e, 0x27, 0x22, 0x19, 0x12, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x10, 0x10, 0x10, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x11, + 0x10, 0x11, 0x11, 0x10, 0x83, 0x83, 0x82, 0x82, 0x81, 0x7f, 0x7f, 0x7e, + 0x7d, 0x7d, 0x7c, 0x7b, 0x7a, 0x7a, 0x79, 0x78, 0x79, 0x78, 0x77, 0x75, + 0x73, 0x72, 0x72, 0x73, 0x77, 0x7d, 0x83, 0x85, 0x87, 0x8b, 0x90, 0x92, + 0x93, 0x92, 0x90, 0x8f, 0x8f, 0x8e, 0x8e, 0x8e, 0x8e, 0x8d, 0x8d, 0x8d, + 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8e, 0x8e, 0x8e, 0x8c, 0x8a, + 0x89, 0x88, 0x88, 0x88, 0x87, 0x87, 0x88, 0x89, 0x8a, 0x8c, 0x8d, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8d, 0x8c, 0x8b, 0x8b, 0x8a, 0x8a, 0x89, 0x8a, 0x8b, + 0x89, 0x88, 0x88, 0x88, 0x88, 0x87, 0x85, 0x83, 0x83, 0x83, 0x82, 0x81, + 0x81, 0x81, 0x81, 0x7f, 0x7e, 0x7d, 0x7e, 0x7e, 0x7e, 0x7e, 0x7c, 0x7c, + 0x7c, 0x7d, 0x7e, 0x7f, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x85, 0x86, 0x86, + 0x88, 0x8a, 0x8b, 0x8c, 0x8c, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x90, 0x90, + 0x8f, 0x90, 0x90, 0x90, 0x92, 0x93, 0x93, 0x94, 0x95, 0x95, 0x94, 0x95, + 0x94, 0x94, 0x95, 0x95, 0x93, 0x92, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x92, 0x92, 0x91, 0x91, 0x91, 0x91, 0x91, 0x90, 0x90, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8e, 0x8e, 0x8d, 0x8d, 0x8d, 0x8d, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8a, 0x89, 0x89, 0x88, 0x88, 0x89, 0x88, 0x88, 0x88, 0x87, 0x86, + 0x87, 0x87, 0x88, 0x89, 0x8a, 0x8d, 0x8d, 0x8e, 0x8e, 0x8f, 0x92, 0x93, + 0x94, 0x94, 0x95, 0x95, 0x96, 0x96, 0x97, 0x99, 0x9b, 0x9c, 0x9c, 0x9c, + 0x9d, 0x9c, 0x9d, 0x9e, 0x9e, 0x9d, 0x9c, 0x9b, 0x9b, 0x9b, 0x9a, 0x9b, + 0x9b, 0x9a, 0x9b, 0x9b, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9c, 0x9d, 0x9c, + 0x9c, 0x9d, 0x9c, 0x9d, 0x9d, 0x9e, 0x9f, 0x9e, 0x9b, 0x98, 0x96, 0x91, + 0x8b, 0x82, 0x7c, 0x7a, 0x76, 0x71, 0x6a, 0x65, 0x63, 0x63, 0x64, 0x64, + 0x65, 0x66, 0x67, 0x67, 0x68, 0x69, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, + 0x71, 0x70, 0x70, 0x73, 0x73, 0x72, 0x72, 0x71, 0x6f, 0x6d, 0x6c, 0x69, + 0x67, 0x63, 0x60, 0x5e, 0x5a, 0x55, 0x4f, 0x4a, 0x46, 0x3f, 0x38, 0x2f, + 0x28, 0x22, 0x19, 0x12, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x10, + 0x10, 0x11, 0x11, 0x12, 0x12, 0x12, 0x11, 0x10, 0x11, 0x11, 0x11, 0x11, + 0x84, 0x84, 0x83, 0x82, 0x82, 0x80, 0x7f, 0x7f, 0x7e, 0x7d, 0x7c, 0x7c, + 0x7a, 0x7a, 0x79, 0x79, 0x79, 0x78, 0x76, 0x75, 0x74, 0x73, 0x71, 0x72, + 0x76, 0x7d, 0x81, 0x84, 0x86, 0x8a, 0x8e, 0x92, 0x93, 0x93, 0x91, 0x8f, + 0x8f, 0x8f, 0x8e, 0x8d, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x90, 0x8f, 0x8f, + 0x90, 0x90, 0x90, 0x90, 0x8f, 0x8f, 0x8d, 0x8b, 0x8a, 0x8a, 0x8a, 0x89, + 0x89, 0x88, 0x8a, 0x8a, 0x8b, 0x8d, 0x8e, 0x8f, 0x90, 0x90, 0x8e, 0x8e, + 0x8e, 0x8d, 0x8c, 0x8c, 0x8b, 0x8a, 0x8b, 0x8b, 0x8a, 0x8a, 0x8b, 0x8a, + 0x89, 0x87, 0x86, 0x84, 0x83, 0x83, 0x82, 0x82, 0x81, 0x81, 0x80, 0x7f, + 0x7e, 0x7f, 0x7e, 0x7e, 0x7c, 0x7d, 0x7c, 0x7c, 0x7c, 0x7e, 0x7f, 0x80, + 0x80, 0x80, 0x81, 0x82, 0x84, 0x85, 0x86, 0x86, 0x89, 0x8a, 0x8b, 0x8b, + 0x8b, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x92, + 0x93, 0x94, 0x94, 0x93, 0x94, 0x94, 0x95, 0x95, 0x95, 0x94, 0x95, 0x95, + 0x94, 0x94, 0x94, 0x92, 0x93, 0x92, 0x92, 0x93, 0x93, 0x93, 0x92, 0x92, + 0x91, 0x91, 0x92, 0x91, 0x91, 0x8f, 0x90, 0x8f, 0x90, 0x90, 0x90, 0x8f, + 0x8f, 0x8e, 0x8d, 0x8e, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8a, 0x89, 0x89, + 0x89, 0x89, 0x8a, 0x89, 0x88, 0x87, 0x86, 0x86, 0x87, 0x87, 0x87, 0x87, + 0x89, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x91, 0x94, 0x95, 0x95, 0x95, 0x96, + 0x96, 0x96, 0x96, 0x97, 0x9a, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9c, 0x9d, + 0x9e, 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9c, + 0x9d, 0x9d, 0x9d, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e, 0x9d, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9d, 0x9a, 0x96, 0x93, 0x8f, 0x87, 0x7e, 0x78, 0x76, + 0x73, 0x6e, 0x66, 0x63, 0x62, 0x62, 0x63, 0x65, 0x66, 0x65, 0x66, 0x67, + 0x67, 0x69, 0x6b, 0x6c, 0x6d, 0x6d, 0x6f, 0x70, 0x70, 0x71, 0x71, 0x72, + 0x72, 0x71, 0x71, 0x70, 0x6e, 0x6d, 0x6c, 0x69, 0x67, 0x62, 0x5f, 0x5d, + 0x5a, 0x54, 0x4e, 0x4a, 0x46, 0x3f, 0x38, 0x2f, 0x27, 0x21, 0x1a, 0x12, + 0x10, 0x10, 0x10, 0x11, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x12, + 0x12, 0x12, 0x10, 0x10, 0x11, 0x11, 0x11, 0x12, 0x84, 0x84, 0x83, 0x82, + 0x82, 0x7f, 0x7f, 0x7f, 0x7f, 0x7d, 0x7e, 0x7d, 0x7c, 0x7b, 0x7b, 0x79, + 0x79, 0x78, 0x77, 0x76, 0x75, 0x73, 0x71, 0x71, 0x74, 0x7b, 0x7e, 0x82, + 0x84, 0x88, 0x8c, 0x91, 0x93, 0x93, 0x91, 0x8f, 0x8f, 0x8f, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8f, 0x90, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x90, 0x8d, 0x8d, 0x8c, 0x8b, 0x8b, 0x8b, 0x8b, 0x8d, 0x8d, + 0x8d, 0x8f, 0x91, 0x90, 0x90, 0x90, 0x8f, 0x8f, 0x8f, 0x8e, 0x8d, 0x8d, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8d, 0x8b, 0x8b, 0x89, 0x87, 0x86, + 0x84, 0x84, 0x83, 0x83, 0x83, 0x82, 0x81, 0x80, 0x80, 0x7f, 0x7e, 0x7d, + 0x7c, 0x7d, 0x7e, 0x7d, 0x7d, 0x7d, 0x7f, 0x80, 0x7f, 0x80, 0x81, 0x84, + 0x86, 0x87, 0x87, 0x87, 0x88, 0x8a, 0x8c, 0x8c, 0x8d, 0x8f, 0x90, 0x90, + 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x90, 0x91, 0x93, 0x94, 0x95, 0x95, 0x95, + 0x95, 0x96, 0x94, 0x94, 0x94, 0x95, 0x94, 0x95, 0x94, 0x94, 0x94, 0x92, + 0x91, 0x91, 0x91, 0x91, 0x93, 0x92, 0x92, 0x91, 0x91, 0x91, 0x92, 0x91, + 0x91, 0x90, 0x90, 0x8f, 0x90, 0x90, 0x90, 0x90, 0x8f, 0x8e, 0x8d, 0x8d, + 0x8c, 0x8d, 0x8c, 0x8c, 0x8b, 0x8b, 0x89, 0x89, 0x89, 0x89, 0x8a, 0x89, + 0x88, 0x87, 0x86, 0x86, 0x87, 0x88, 0x87, 0x87, 0x89, 0x8c, 0x8c, 0x8d, + 0x8e, 0x8f, 0x91, 0x94, 0x95, 0x96, 0x95, 0x97, 0x97, 0x97, 0x96, 0x97, + 0x9a, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9c, 0x9d, 0x9e, 0x9d, 0x9c, 0x9b, + 0x9a, 0x99, 0x9a, 0x9b, 0x9a, 0x9a, 0x9a, 0x9d, 0x9e, 0x9d, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9d, 0x9f, 0x9f, 0x9e, 0x9d, 0x9b, + 0x97, 0x93, 0x90, 0x8a, 0x81, 0x7a, 0x76, 0x73, 0x6f, 0x67, 0x62, 0x61, + 0x61, 0x61, 0x62, 0x64, 0x65, 0x65, 0x66, 0x67, 0x67, 0x68, 0x6b, 0x6b, + 0x6c, 0x6c, 0x6e, 0x6e, 0x6f, 0x6f, 0x70, 0x71, 0x71, 0x71, 0x70, 0x70, + 0x6e, 0x6e, 0x6d, 0x6a, 0x67, 0x61, 0x5f, 0x5c, 0x58, 0x52, 0x4e, 0x49, + 0x45, 0x3f, 0x38, 0x2e, 0x27, 0x22, 0x1b, 0x13, 0x10, 0x11, 0x11, 0x12, + 0x11, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x12, 0x12, 0x12, 0x10, 0x10, + 0x11, 0x11, 0x12, 0x14, 0x83, 0x83, 0x83, 0x83, 0x81, 0x7f, 0x7f, 0x80, + 0x7f, 0x7e, 0x7e, 0x7d, 0x7d, 0x7d, 0x7c, 0x7b, 0x7a, 0x78, 0x78, 0x77, + 0x74, 0x71, 0x70, 0x71, 0x73, 0x78, 0x7c, 0x80, 0x83, 0x88, 0x8c, 0x90, + 0x93, 0x93, 0x93, 0x90, 0x8e, 0x8f, 0x8e, 0x8e, 0x8d, 0x8e, 0x8d, 0x8d, + 0x8e, 0x8f, 0x8f, 0x91, 0x92, 0x92, 0x93, 0x92, 0x92, 0x92, 0x91, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8e, 0x8e, 0x8e, 0x8f, 0x90, 0x91, 0x91, 0x93, 0x94, + 0x93, 0x92, 0x91, 0x90, 0x8e, 0x8e, 0x8e, 0x8f, 0x8d, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8d, 0x8c, 0x8b, 0x89, 0x87, 0x86, 0x86, 0x85, 0x85, 0x85, + 0x84, 0x82, 0x81, 0x80, 0x80, 0x80, 0x7f, 0x7e, 0x7d, 0x7d, 0x7e, 0x7e, + 0x7e, 0x7e, 0x7e, 0x7f, 0x81, 0x81, 0x82, 0x84, 0x86, 0x87, 0x87, 0x88, + 0x89, 0x8a, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x8f, 0x8f, 0x8f, 0x90, 0x91, + 0x91, 0x92, 0x92, 0x94, 0x95, 0x96, 0x95, 0x95, 0x95, 0x96, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x94, 0x94, 0x94, 0x93, 0x91, 0x92, 0x92, 0x92, + 0x92, 0x93, 0x92, 0x92, 0x90, 0x91, 0x91, 0x90, 0x90, 0x8f, 0x8f, 0x8f, + 0x90, 0x90, 0x90, 0x90, 0x8f, 0x8e, 0x8d, 0x8c, 0x8c, 0x8d, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8b, 0x8b, 0x8a, 0x89, 0x89, 0x89, 0x87, 0x87, 0x85, 0x85, + 0x87, 0x88, 0x88, 0x87, 0x88, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x91, 0x94, + 0x95, 0x96, 0x96, 0x97, 0x98, 0x98, 0x98, 0x98, 0x9a, 0x9c, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9c, 0x9d, 0x9e, 0x9d, 0x9b, 0x9a, 0x9b, 0x9a, 0x99, 0x9a, + 0x9a, 0x9b, 0x9c, 0x9d, 0x9c, 0x9e, 0x9e, 0x9e, 0x9d, 0x9f, 0x9e, 0x9e, + 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0x9d, 0x9c, 0x99, 0x95, 0x91, 0x8e, 0x86, + 0x7e, 0x77, 0x72, 0x6e, 0x69, 0x62, 0x60, 0x60, 0x61, 0x62, 0x63, 0x64, + 0x64, 0x65, 0x65, 0x67, 0x68, 0x69, 0x6b, 0x6b, 0x6c, 0x6c, 0x6d, 0x6d, + 0x6e, 0x6f, 0x6e, 0x6f, 0x70, 0x71, 0x71, 0x71, 0x6e, 0x6e, 0x6d, 0x69, + 0x67, 0x62, 0x5e, 0x5c, 0x58, 0x52, 0x4d, 0x4a, 0x46, 0x3f, 0x38, 0x2f, + 0x27, 0x22, 0x1a, 0x13, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, + 0x11, 0x11, 0x11, 0x12, 0x11, 0x10, 0x10, 0x12, 0x13, 0x13, 0x12, 0x13, + 0x82, 0x82, 0x83, 0x83, 0x81, 0x80, 0x7f, 0x80, 0x7f, 0x7e, 0x7f, 0x7e, + 0x7d, 0x7d, 0x7d, 0x7b, 0x79, 0x79, 0x79, 0x77, 0x74, 0x71, 0x70, 0x70, + 0x71, 0x75, 0x7c, 0x7f, 0x82, 0x86, 0x8b, 0x8e, 0x91, 0x92, 0x92, 0x91, + 0x8f, 0x8f, 0x8e, 0x8d, 0x8e, 0x8d, 0x8d, 0x8e, 0x8e, 0x8f, 0x90, 0x91, + 0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x92, 0x90, 0x90, 0x91, 0x91, 0x91, + 0x91, 0x90, 0x91, 0x91, 0x93, 0x93, 0x94, 0x95, 0x93, 0x93, 0x93, 0x92, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8d, 0x8c, + 0x8b, 0x89, 0x87, 0x87, 0x86, 0x85, 0x85, 0x85, 0x83, 0x82, 0x81, 0x81, + 0x81, 0x7f, 0x80, 0x7f, 0x7d, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x7e, 0x80, + 0x81, 0x82, 0x83, 0x84, 0x86, 0x87, 0x87, 0x88, 0x8a, 0x8a, 0x8c, 0x8d, + 0x8e, 0x8f, 0x90, 0x90, 0x90, 0x8f, 0x90, 0x90, 0x91, 0x92, 0x93, 0x95, + 0x96, 0x96, 0x95, 0x95, 0x95, 0x96, 0x97, 0x97, 0x97, 0x95, 0x94, 0x95, + 0x93, 0x93, 0x93, 0x93, 0x92, 0x92, 0x92, 0x93, 0x92, 0x92, 0x91, 0x91, + 0x90, 0x91, 0x91, 0x90, 0x90, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x90, 0x90, + 0x90, 0x8f, 0x8e, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8d, 0x8d, 0x8c, 0x8c, + 0x8b, 0x89, 0x89, 0x88, 0x87, 0x86, 0x85, 0x85, 0x87, 0x88, 0x87, 0x88, + 0x89, 0x8c, 0x8c, 0x8d, 0x8e, 0x8f, 0x91, 0x94, 0x96, 0x96, 0x96, 0x97, + 0x97, 0x98, 0x99, 0x98, 0x9a, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9c, 0x9d, + 0x9e, 0x9d, 0x9b, 0x99, 0x9a, 0x9a, 0x99, 0x99, 0x9a, 0x9b, 0x9d, 0x9d, + 0x9d, 0x9f, 0x9f, 0x9f, 0x9e, 0x9f, 0x9f, 0x9d, 0x9c, 0x9c, 0x9d, 0x9e, + 0x9d, 0x9c, 0x9b, 0x97, 0x91, 0x8d, 0x89, 0x82, 0x7a, 0x74, 0x6e, 0x6a, + 0x64, 0x5f, 0x5f, 0x60, 0x60, 0x61, 0x62, 0x63, 0x63, 0x64, 0x65, 0x65, + 0x67, 0x69, 0x6a, 0x6b, 0x6c, 0x6c, 0x6d, 0x6d, 0x6e, 0x6f, 0x6f, 0x6f, + 0x70, 0x71, 0x71, 0x70, 0x6e, 0x6e, 0x6d, 0x6a, 0x66, 0x62, 0x5e, 0x5c, + 0x59, 0x53, 0x4d, 0x49, 0x46, 0x40, 0x36, 0x2e, 0x26, 0x21, 0x1a, 0x14, + 0x11, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, + 0x11, 0x11, 0x11, 0x12, 0x13, 0x13, 0x12, 0x11, 0x82, 0x82, 0x83, 0x82, + 0x81, 0x80, 0x80, 0x80, 0x7f, 0x7e, 0x7e, 0x7d, 0x7d, 0x7d, 0x7d, 0x7b, + 0x79, 0x79, 0x78, 0x77, 0x74, 0x72, 0x70, 0x70, 0x6f, 0x74, 0x7a, 0x7f, + 0x82, 0x85, 0x8a, 0x8d, 0x91, 0x92, 0x92, 0x92, 0x90, 0x8f, 0x8f, 0x8d, + 0x8d, 0x8d, 0x8e, 0x8e, 0x8d, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x94, + 0x94, 0x94, 0x92, 0x92, 0x91, 0x92, 0x92, 0x92, 0x92, 0x91, 0x92, 0x92, + 0x94, 0x95, 0x95, 0x95, 0x94, 0x93, 0x94, 0x92, 0x90, 0x8f, 0x8f, 0x90, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8e, 0x8d, 0x8c, 0x8c, 0x89, 0x87, 0x86, + 0x86, 0x85, 0x85, 0x85, 0x83, 0x82, 0x82, 0x81, 0x81, 0x80, 0x80, 0x7f, + 0x7d, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x7e, 0x80, 0x82, 0x82, 0x82, 0x84, + 0x86, 0x87, 0x87, 0x88, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, + 0x91, 0x90, 0x90, 0x90, 0x91, 0x92, 0x93, 0x95, 0x96, 0x96, 0x95, 0x96, + 0x95, 0x96, 0x97, 0x98, 0x97, 0x94, 0x94, 0x94, 0x93, 0x92, 0x92, 0x93, + 0x92, 0x93, 0x93, 0x93, 0x93, 0x93, 0x92, 0x91, 0x91, 0x92, 0x91, 0x90, + 0x90, 0x8f, 0x8f, 0x8e, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x8f, 0x8e, 0x8d, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8d, 0x8d, 0x8c, 0x8c, 0x8b, 0x89, 0x89, 0x88, + 0x87, 0x86, 0x85, 0x85, 0x87, 0x87, 0x87, 0x88, 0x89, 0x8c, 0x8c, 0x8e, + 0x8e, 0x8f, 0x91, 0x94, 0x96, 0x96, 0x96, 0x96, 0x96, 0x98, 0x99, 0x98, + 0x99, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9c, 0x9d, 0x9e, 0x9d, 0x9b, 0x99, + 0x9a, 0x9a, 0x98, 0x98, 0x99, 0x9b, 0x9d, 0x9d, 0x9d, 0x9e, 0x9f, 0x9f, + 0x9e, 0xa0, 0x9f, 0x9d, 0x9c, 0x9c, 0x9e, 0x9e, 0x9c, 0x9b, 0x9a, 0x95, + 0x8f, 0x8a, 0x86, 0x7f, 0x78, 0x71, 0x6b, 0x67, 0x61, 0x5e, 0x5f, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x63, 0x64, 0x65, 0x65, 0x67, 0x6a, 0x69, 0x6a, + 0x6b, 0x6c, 0x6d, 0x6d, 0x6e, 0x6f, 0x70, 0x6f, 0x70, 0x71, 0x70, 0x70, + 0x6e, 0x6e, 0x6d, 0x6b, 0x66, 0x62, 0x5e, 0x5c, 0x59, 0x53, 0x4d, 0x49, + 0x46, 0x3f, 0x36, 0x2e, 0x25, 0x20, 0x19, 0x14, 0x11, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x11, 0x11, 0x11, 0x11, + 0x12, 0x12, 0x12, 0x11, 0x82, 0x82, 0x82, 0x82, 0x80, 0x80, 0x80, 0x80, + 0x7f, 0x7e, 0x7d, 0x7d, 0x7e, 0x7e, 0x7d, 0x7b, 0x78, 0x78, 0x77, 0x76, + 0x74, 0x72, 0x70, 0x6f, 0x6e, 0x72, 0x79, 0x7e, 0x81, 0x84, 0x88, 0x8c, + 0x90, 0x91, 0x92, 0x91, 0x8f, 0x8f, 0x8e, 0x8d, 0x8e, 0x8e, 0x8e, 0x8f, + 0x8e, 0x90, 0x90, 0x91, 0x92, 0x94, 0x95, 0x94, 0x95, 0x95, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x93, 0x94, 0x94, 0x94, 0x95, 0x96, 0x96, 0x96, + 0x95, 0x94, 0x94, 0x93, 0x91, 0x91, 0x91, 0x91, 0x90, 0x8f, 0x90, 0x90, + 0x8f, 0x8f, 0x8e, 0x8d, 0x8c, 0x8a, 0x87, 0x87, 0x86, 0x86, 0x86, 0x86, + 0x84, 0x83, 0x83, 0x82, 0x82, 0x81, 0x80, 0x7f, 0x7d, 0x7d, 0x7e, 0x7d, + 0x7d, 0x7d, 0x7f, 0x81, 0x81, 0x82, 0x83, 0x84, 0x86, 0x86, 0x87, 0x88, + 0x8a, 0x8b, 0x8c, 0x8d, 0x8d, 0x8e, 0x8f, 0x91, 0x91, 0x91, 0x91, 0x90, + 0x92, 0x93, 0x94, 0x94, 0x95, 0x96, 0x96, 0x96, 0x95, 0x96, 0x98, 0x98, + 0x97, 0x95, 0x94, 0x95, 0x94, 0x93, 0x93, 0x93, 0x91, 0x91, 0x92, 0x93, + 0x93, 0x93, 0x92, 0x92, 0x91, 0x92, 0x91, 0x90, 0x90, 0x8f, 0x90, 0x8f, + 0x8f, 0x8f, 0x90, 0x8f, 0x8f, 0x8e, 0x8e, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8c, 0x8d, 0x8b, 0x8c, 0x8b, 0x8a, 0x8a, 0x89, 0x88, 0x87, 0x85, 0x85, + 0x87, 0x86, 0x87, 0x89, 0x8a, 0x8b, 0x8c, 0x8e, 0x8e, 0x8f, 0x91, 0x94, + 0x94, 0x95, 0x95, 0x96, 0x96, 0x98, 0x99, 0x97, 0x98, 0x9b, 0x9b, 0x9b, + 0x9c, 0x9c, 0x9c, 0x9d, 0x9e, 0x9d, 0x9b, 0x9a, 0x9a, 0x9a, 0x99, 0x99, + 0x99, 0x9b, 0x9c, 0x9d, 0x9d, 0x9e, 0x9f, 0xa0, 0xa0, 0x9f, 0x9f, 0x9e, + 0x9d, 0x9c, 0x9e, 0x9e, 0x9b, 0x99, 0x97, 0x93, 0x8b, 0x86, 0x82, 0x7b, + 0x75, 0x6d, 0x66, 0x62, 0x5d, 0x5b, 0x5d, 0x5e, 0x5e, 0x60, 0x61, 0x61, + 0x63, 0x64, 0x66, 0x67, 0x68, 0x69, 0x69, 0x69, 0x6b, 0x6b, 0x6d, 0x6d, + 0x6e, 0x70, 0x70, 0x6f, 0x70, 0x70, 0x6f, 0x6f, 0x6e, 0x6e, 0x6d, 0x6a, + 0x66, 0x62, 0x5e, 0x5c, 0x59, 0x53, 0x4c, 0x48, 0x45, 0x3e, 0x35, 0x2e, + 0x26, 0x20, 0x19, 0x13, 0x11, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x12, 0x12, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x7f, 0x80, 0x81, 0x81, 0x81, 0x81, 0x81, 0x7f, 0x7f, 0x7f, 0x7e, 0x7e, + 0x7e, 0x7e, 0x7c, 0x7c, 0x79, 0x77, 0x77, 0x76, 0x73, 0x71, 0x6d, 0x6c, + 0x6c, 0x6f, 0x76, 0x7c, 0x7e, 0x82, 0x86, 0x8b, 0x8e, 0x8f, 0x91, 0x91, + 0x91, 0x90, 0x8f, 0x8e, 0x8f, 0x8e, 0x8e, 0x8e, 0x8e, 0x8f, 0x90, 0x92, + 0x93, 0x93, 0x95, 0x95, 0x96, 0x96, 0x95, 0x95, 0x95, 0x96, 0x96, 0x96, + 0x95, 0x97, 0x97, 0x97, 0x97, 0x97, 0x98, 0x97, 0x96, 0x96, 0x95, 0x94, + 0x93, 0x93, 0x92, 0x91, 0x92, 0x91, 0x90, 0x90, 0x91, 0x8f, 0x8f, 0x8e, + 0x8d, 0x8a, 0x89, 0x88, 0x87, 0x87, 0x87, 0x87, 0x84, 0x83, 0x83, 0x84, + 0x82, 0x81, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x7e, 0x7e, 0x7f, 0x81, + 0x81, 0x82, 0x84, 0x86, 0x87, 0x87, 0x88, 0x89, 0x8a, 0x8c, 0x8e, 0x8d, + 0x8d, 0x8e, 0x90, 0x90, 0x91, 0x91, 0x90, 0x91, 0x93, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x96, 0x96, 0x96, 0x97, 0x98, 0x98, 0x98, 0x98, 0x97, 0x95, + 0x94, 0x94, 0x94, 0x92, 0x91, 0x91, 0x92, 0x93, 0x94, 0x93, 0x92, 0x91, + 0x91, 0x91, 0x91, 0x90, 0x90, 0x90, 0x91, 0x90, 0x8f, 0x8f, 0x8f, 0x8d, + 0x8d, 0x8c, 0x8d, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8b, 0x8b, 0x8b, 0x8a, 0x88, 0x87, 0x86, 0x86, 0x86, 0x86, 0x87, 0x89, + 0x8a, 0x8c, 0x8c, 0x8d, 0x8f, 0x90, 0x93, 0x94, 0x94, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x98, 0x97, 0x98, 0x9a, 0x9a, 0x9a, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9b, 0x9b, 0x9a, 0x9b, 0x9b, 0x9b, 0x99, 0x99, 0x9b, 0x9c, 0x9e, + 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0x9f, 0x9e, 0x9d, 0x9c, 0x9b, + 0x98, 0x96, 0x93, 0x8e, 0x87, 0x82, 0x7e, 0x77, 0x6f, 0x66, 0x60, 0x5e, + 0x5b, 0x5b, 0x5b, 0x5d, 0x5e, 0x5f, 0x61, 0x62, 0x62, 0x64, 0x65, 0x67, + 0x67, 0x69, 0x69, 0x6a, 0x6c, 0x6d, 0x6c, 0x6d, 0x6d, 0x6f, 0x6f, 0x70, + 0x70, 0x70, 0x70, 0x6e, 0x6e, 0x6d, 0x6c, 0x68, 0x66, 0x62, 0x5e, 0x5c, + 0x58, 0x54, 0x4d, 0x48, 0x44, 0x3e, 0x36, 0x2f, 0x27, 0x21, 0x1a, 0x13, + 0x11, 0x11, 0x10, 0x11, 0x10, 0x11, 0x11, 0x11, 0x11, 0x12, 0x11, 0x13, + 0x13, 0x13, 0x12, 0x11, 0x11, 0x11, 0x11, 0x12, 0x7f, 0x80, 0x82, 0x82, + 0x82, 0x83, 0x82, 0x80, 0x80, 0x80, 0x7f, 0x7e, 0x7e, 0x7e, 0x7d, 0x7b, + 0x79, 0x78, 0x77, 0x76, 0x72, 0x6e, 0x6c, 0x6c, 0x6b, 0x6d, 0x74, 0x79, + 0x7c, 0x80, 0x85, 0x8a, 0x8c, 0x8e, 0x90, 0x91, 0x91, 0x90, 0x8f, 0x90, + 0x8f, 0x8f, 0x8f, 0x8e, 0x8e, 0x8f, 0x90, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x97, 0x97, 0x96, 0x96, 0x98, 0x99, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x99, 0x99, 0x99, 0x97, 0x97, 0x96, 0x95, 0x93, 0x94, 0x94, 0x94, + 0x94, 0x93, 0x92, 0x92, 0x92, 0x91, 0x8f, 0x8e, 0x8c, 0x8a, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x88, 0x85, 0x84, 0x84, 0x84, 0x82, 0x81, 0x80, 0x7f, + 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x81, 0x81, 0x82, 0x82, 0x82, 0x83, 0x87, + 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8d, 0x8e, 0x8e, 0x8d, 0x8e, 0x90, 0x91, + 0x92, 0x92, 0x92, 0x91, 0x92, 0x95, 0x95, 0x95, 0x96, 0x95, 0x96, 0x96, + 0x96, 0x96, 0x98, 0x98, 0x98, 0x99, 0x99, 0x96, 0x95, 0x94, 0x94, 0x92, + 0x91, 0x91, 0x92, 0x93, 0x94, 0x93, 0x92, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x92, 0x91, 0x8f, 0x8e, 0x8e, 0x8d, 0x8d, 0x8c, 0x8d, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8c, 0x8b, 0x8c, 0x8c, 0x8c, 0x8c, 0x8b, 0x8a, + 0x88, 0x87, 0x86, 0x86, 0x86, 0x86, 0x87, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, + 0x8f, 0x90, 0x92, 0x92, 0x94, 0x96, 0x97, 0x97, 0x97, 0x98, 0x98, 0x97, + 0x98, 0x9a, 0x9a, 0x9a, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9b, 0x9b, 0x9a, + 0x9b, 0x9b, 0x9b, 0x99, 0x99, 0x9a, 0x9c, 0x9d, 0x9f, 0xa0, 0xa1, 0xa1, + 0xa1, 0x9f, 0x9f, 0xa0, 0x9f, 0x9d, 0x9b, 0x98, 0x95, 0x92, 0x8e, 0x88, + 0x82, 0x7d, 0x79, 0x72, 0x6a, 0x61, 0x5c, 0x5a, 0x59, 0x59, 0x59, 0x5c, + 0x5f, 0x61, 0x61, 0x62, 0x62, 0x64, 0x65, 0x67, 0x67, 0x69, 0x69, 0x6a, + 0x6c, 0x6d, 0x6c, 0x6d, 0x6e, 0x6f, 0x6f, 0x70, 0x70, 0x70, 0x70, 0x6e, + 0x6e, 0x6e, 0x6c, 0x68, 0x66, 0x62, 0x5c, 0x5a, 0x57, 0x54, 0x4d, 0x48, + 0x45, 0x3f, 0x36, 0x2d, 0x27, 0x22, 0x1a, 0x13, 0x11, 0x11, 0x10, 0x11, + 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x13, 0x13, 0x13, 0x13, 0x12, 0x13, + 0x12, 0x12, 0x11, 0x13, 0x80, 0x80, 0x82, 0x83, 0x82, 0x83, 0x83, 0x82, + 0x82, 0x80, 0x80, 0x7f, 0x7e, 0x7e, 0x7d, 0x7b, 0x79, 0x79, 0x78, 0x75, + 0x70, 0x6c, 0x6b, 0x6b, 0x6a, 0x6c, 0x73, 0x77, 0x7a, 0x7e, 0x83, 0x89, + 0x8b, 0x8d, 0x8f, 0x90, 0x91, 0x91, 0x90, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8e, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x97, 0x97, 0x97, 0x98, 0x98, + 0x97, 0x99, 0x9a, 0x99, 0x9a, 0x9a, 0x9b, 0x9a, 0x9a, 0x99, 0x99, 0x99, + 0x99, 0x97, 0x96, 0x95, 0x94, 0x94, 0x94, 0x95, 0x94, 0x94, 0x93, 0x93, + 0x92, 0x92, 0x90, 0x8e, 0x8d, 0x8b, 0x8a, 0x89, 0x8a, 0x8a, 0x8a, 0x89, + 0x86, 0x86, 0x85, 0x85, 0x82, 0x80, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x81, 0x82, 0x83, 0x82, 0x83, 0x84, 0x87, 0x89, 0x8a, 0x8a, 0x8b, + 0x8a, 0x8c, 0x8e, 0x8e, 0x8e, 0x8e, 0x91, 0x92, 0x92, 0x93, 0x92, 0x92, + 0x93, 0x95, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x97, 0x97, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x97, 0x96, 0x96, 0x95, 0x93, 0x92, 0x92, 0x92, 0x93, + 0x93, 0x93, 0x92, 0x92, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x8f, 0x8f, 0x8f, 0x8e, 0x8e, 0x8e, 0x8e, 0x8f, 0x8e, 0x8d, 0x8d, 0x8e, + 0x8c, 0x8c, 0x8c, 0x8d, 0x8c, 0x8d, 0x8b, 0x89, 0x88, 0x88, 0x87, 0x87, + 0x87, 0x87, 0x88, 0x89, 0x8a, 0x8a, 0x8c, 0x8d, 0x8f, 0x8f, 0x91, 0x93, + 0x95, 0x96, 0x98, 0x99, 0x98, 0x99, 0x99, 0x98, 0x99, 0x9a, 0x9b, 0x9c, + 0x9d, 0x9d, 0x9c, 0x9d, 0x9d, 0x9b, 0x9b, 0x9a, 0x9a, 0x9b, 0x9b, 0x9a, + 0x9a, 0x9c, 0x9c, 0x9e, 0xa0, 0xa1, 0xa1, 0xa1, 0xa0, 0x9f, 0xa0, 0x9f, + 0x9f, 0x9d, 0x9a, 0x96, 0x92, 0x8f, 0x8b, 0x84, 0x7d, 0x78, 0x76, 0x6f, + 0x65, 0x5c, 0x59, 0x58, 0x58, 0x57, 0x59, 0x5c, 0x5f, 0x60, 0x61, 0x61, + 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6c, 0x6d, + 0x6d, 0x6e, 0x6e, 0x70, 0x70, 0x70, 0x70, 0x6f, 0x6e, 0x6e, 0x6c, 0x68, + 0x64, 0x61, 0x5c, 0x5a, 0x57, 0x54, 0x4d, 0x48, 0x44, 0x3e, 0x38, 0x2e, + 0x25, 0x21, 0x1b, 0x14, 0x11, 0x11, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, + 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x12, 0x12, 0x14, + 0x80, 0x81, 0x82, 0x83, 0x83, 0x84, 0x83, 0x83, 0x82, 0x80, 0x80, 0x7f, + 0x7f, 0x7e, 0x7d, 0x7b, 0x79, 0x78, 0x77, 0x74, 0x6f, 0x6c, 0x6b, 0x6a, + 0x6a, 0x6b, 0x72, 0x76, 0x79, 0x7c, 0x82, 0x88, 0x8b, 0x8c, 0x8e, 0x8f, + 0x91, 0x91, 0x91, 0x90, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x90, 0x92, 0x92, + 0x93, 0x95, 0x96, 0x97, 0x97, 0x97, 0x98, 0x98, 0x99, 0x9a, 0x9b, 0x9a, + 0x9b, 0x9b, 0x9b, 0x9c, 0x9b, 0x9a, 0x99, 0x99, 0x99, 0x98, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x94, 0x94, 0x93, 0x93, 0x93, 0x93, 0x91, 0x8e, + 0x8d, 0x8b, 0x8a, 0x89, 0x8a, 0x89, 0x89, 0x89, 0x87, 0x86, 0x86, 0x85, + 0x83, 0x80, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x82, 0x82, + 0x82, 0x83, 0x85, 0x87, 0x89, 0x8a, 0x8a, 0x8b, 0x8a, 0x8c, 0x8e, 0x8f, + 0x8f, 0x8f, 0x90, 0x92, 0x92, 0x93, 0x93, 0x93, 0x94, 0x95, 0x95, 0x96, + 0x96, 0x97, 0x96, 0x97, 0x97, 0x98, 0x99, 0x99, 0x99, 0x99, 0x98, 0x97, + 0x97, 0x96, 0x95, 0x94, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x92, 0x92, + 0x91, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x8f, 0x8f, 0x8f, 0x8e, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8a, 0x88, 0x88, 0x88, 0x87, 0x88, 0x87, 0x87, 0x88, 0x88, + 0x8a, 0x8a, 0x8c, 0x8e, 0x8f, 0x8f, 0x90, 0x93, 0x95, 0x96, 0x98, 0x99, + 0x98, 0x99, 0x99, 0x98, 0x99, 0x9a, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, 0x9d, + 0x9d, 0x9c, 0x9b, 0x9a, 0x9a, 0x9b, 0x9a, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, + 0xa0, 0xa1, 0xa1, 0xa1, 0xa0, 0x9f, 0xa0, 0x9f, 0x9e, 0x9c, 0x98, 0x94, + 0x90, 0x8d, 0x89, 0x81, 0x79, 0x75, 0x72, 0x6c, 0x62, 0x5a, 0x58, 0x58, + 0x58, 0x57, 0x59, 0x5c, 0x5f, 0x60, 0x60, 0x61, 0x64, 0x66, 0x67, 0x67, + 0x68, 0x69, 0x6a, 0x6a, 0x6b, 0x6d, 0x6c, 0x6d, 0x6e, 0x6e, 0x6e, 0x6f, + 0x70, 0x70, 0x70, 0x6f, 0x6e, 0x6e, 0x6c, 0x68, 0x63, 0x61, 0x5d, 0x5b, + 0x57, 0x53, 0x4c, 0x48, 0x45, 0x3f, 0x39, 0x2e, 0x25, 0x20, 0x1b, 0x14, + 0x11, 0x11, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x12, 0x11, + 0x11, 0x11, 0x13, 0x13, 0x12, 0x12, 0x13, 0x14, 0x81, 0x82, 0x82, 0x82, + 0x83, 0x84, 0x83, 0x83, 0x82, 0x81, 0x81, 0x7f, 0x7e, 0x7e, 0x7c, 0x7b, + 0x78, 0x77, 0x76, 0x74, 0x6f, 0x6c, 0x6a, 0x6a, 0x6a, 0x6a, 0x6f, 0x74, + 0x77, 0x7a, 0x81, 0x87, 0x8a, 0x8b, 0x8c, 0x8e, 0x91, 0x92, 0x91, 0x90, + 0x8f, 0x90, 0x8f, 0x90, 0x8f, 0x91, 0x92, 0x92, 0x93, 0x95, 0x95, 0x97, + 0x97, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, + 0x9c, 0x9b, 0x99, 0x9a, 0x99, 0x98, 0x96, 0x96, 0x96, 0x95, 0x95, 0x95, + 0x93, 0x94, 0x94, 0x93, 0x92, 0x92, 0x90, 0x8e, 0x8d, 0x8c, 0x8b, 0x89, + 0x89, 0x89, 0x88, 0x89, 0x87, 0x86, 0x86, 0x85, 0x82, 0x81, 0x7f, 0x7f, + 0x80, 0x80, 0x7f, 0x7f, 0x80, 0x80, 0x81, 0x81, 0x82, 0x83, 0x85, 0x87, + 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8c, 0x8e, 0x8f, 0x8f, 0x8f, 0x90, 0x91, + 0x92, 0x93, 0x94, 0x93, 0x95, 0x95, 0x96, 0x97, 0x97, 0x98, 0x97, 0x97, + 0x97, 0x98, 0x9a, 0x9a, 0x99, 0x98, 0x98, 0x97, 0x97, 0x96, 0x95, 0x94, + 0x93, 0x93, 0x93, 0x91, 0x91, 0x92, 0x91, 0x91, 0x90, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x90, 0x8f, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x90, + 0x8f, 0x8d, 0x8c, 0x8d, 0x8e, 0x8d, 0x8c, 0x8d, 0x8d, 0x8c, 0x8a, 0x87, + 0x88, 0x87, 0x87, 0x87, 0x86, 0x87, 0x87, 0x88, 0x8a, 0x8a, 0x8d, 0x8e, + 0x8e, 0x8f, 0x90, 0x92, 0x94, 0x96, 0x98, 0x99, 0x98, 0x99, 0x98, 0x98, + 0x98, 0x99, 0x9b, 0x9b, 0x9a, 0x9a, 0x9b, 0x9c, 0x9c, 0x9c, 0x9a, 0x99, + 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9d, 0x9e, 0x9e, 0xa0, 0xa0, 0xa1, 0xa2, + 0xa2, 0xa0, 0xa0, 0x9e, 0x9d, 0x9a, 0x94, 0x90, 0x8c, 0x89, 0x85, 0x7d, + 0x75, 0x71, 0x6e, 0x66, 0x5c, 0x58, 0x57, 0x57, 0x57, 0x57, 0x5a, 0x5b, + 0x5e, 0x5e, 0x5f, 0x60, 0x64, 0x65, 0x66, 0x67, 0x67, 0x69, 0x68, 0x69, + 0x6a, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6d, 0x6f, 0x6f, 0x6f, 0x6f, 0x70, + 0x6e, 0x6d, 0x6b, 0x67, 0x63, 0x61, 0x5d, 0x5b, 0x56, 0x51, 0x4b, 0x47, + 0x45, 0x40, 0x38, 0x2e, 0x25, 0x20, 0x1a, 0x14, 0x11, 0x11, 0x11, 0x10, + 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, + 0x12, 0x12, 0x13, 0x12, 0x84, 0x84, 0x83, 0x84, 0x84, 0x85, 0x84, 0x84, + 0x84, 0x83, 0x81, 0x7f, 0x7e, 0x7c, 0x7b, 0x79, 0x76, 0x75, 0x74, 0x72, + 0x70, 0x6d, 0x6b, 0x6a, 0x6a, 0x6a, 0x6c, 0x70, 0x74, 0x77, 0x7f, 0x84, + 0x87, 0x88, 0x8a, 0x8e, 0x91, 0x92, 0x92, 0x91, 0x8f, 0x8e, 0x8f, 0x8f, + 0x8f, 0x90, 0x90, 0x92, 0x93, 0x95, 0x96, 0x96, 0x96, 0x97, 0x97, 0x99, + 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0x9f, 0x9f, 0x9e, 0x9b, 0x9a, 0x9a, + 0x9a, 0x9a, 0x98, 0x97, 0x97, 0x97, 0x97, 0x95, 0x93, 0x93, 0x93, 0x93, + 0x92, 0x91, 0x8f, 0x8d, 0x8c, 0x8c, 0x8a, 0x8a, 0x8a, 0x8a, 0x89, 0x89, + 0x87, 0x85, 0x85, 0x84, 0x82, 0x81, 0x7f, 0x7f, 0x80, 0x7f, 0x7f, 0x80, + 0x80, 0x81, 0x82, 0x82, 0x82, 0x83, 0x85, 0x87, 0x89, 0x89, 0x89, 0x8a, + 0x8a, 0x8c, 0x8e, 0x8f, 0x8f, 0x8f, 0x90, 0x91, 0x92, 0x94, 0x94, 0x92, + 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x99, 0x98, 0x98, 0x98, 0x99, 0x9a, + 0x9a, 0x98, 0x97, 0x96, 0x97, 0x97, 0x95, 0x95, 0x93, 0x93, 0x93, 0x91, + 0x92, 0x92, 0x92, 0x91, 0x90, 0x90, 0x90, 0x8f, 0x8f, 0x8f, 0x8f, 0x90, + 0x90, 0x8f, 0x90, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8d, 0x8d, 0x8d, + 0x8e, 0x8d, 0x8d, 0x8d, 0x8d, 0x8c, 0x8a, 0x87, 0x88, 0x87, 0x87, 0x87, + 0x86, 0x86, 0x87, 0x88, 0x8a, 0x8a, 0x8c, 0x8e, 0x8f, 0x8f, 0x90, 0x93, + 0x94, 0x96, 0x98, 0x99, 0x98, 0x99, 0x99, 0x98, 0x98, 0x97, 0x99, 0x99, + 0x99, 0x99, 0x9a, 0x9b, 0x9b, 0x9c, 0x9a, 0x99, 0x9a, 0x9a, 0x9a, 0x99, + 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa2, 0xa2, 0xa2, 0xa1, 0x9e, 0x9b, + 0x9a, 0x97, 0x91, 0x8b, 0x87, 0x84, 0x7e, 0x77, 0x70, 0x6a, 0x66, 0x5f, + 0x58, 0x56, 0x56, 0x56, 0x57, 0x57, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x60, + 0x62, 0x64, 0x65, 0x66, 0x66, 0x68, 0x68, 0x69, 0x6b, 0x6d, 0x6c, 0x6d, + 0x6d, 0x6d, 0x6d, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6e, 0x6d, 0x6b, 0x68, + 0x65, 0x61, 0x5d, 0x5a, 0x55, 0x50, 0x4b, 0x47, 0x45, 0x40, 0x37, 0x2d, + 0x26, 0x20, 0x1a, 0x13, 0x12, 0x11, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, + 0x11, 0x11, 0x12, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x13, 0x13, + 0x84, 0x85, 0x86, 0x86, 0x85, 0x85, 0x85, 0x84, 0x83, 0x82, 0x80, 0x7e, + 0x7e, 0x7c, 0x79, 0x77, 0x75, 0x74, 0x73, 0x72, 0x70, 0x6e, 0x6d, 0x6c, + 0x6a, 0x68, 0x6a, 0x6d, 0x71, 0x75, 0x7b, 0x80, 0x83, 0x85, 0x88, 0x8c, + 0x8f, 0x92, 0x93, 0x93, 0x91, 0x91, 0x91, 0x90, 0x8f, 0x90, 0x91, 0x93, + 0x94, 0x94, 0x96, 0x96, 0x96, 0x97, 0x99, 0x9a, 0x9c, 0x9c, 0x9d, 0x9f, + 0x9f, 0xa0, 0xa0, 0xa0, 0x9e, 0x9b, 0x9b, 0x9c, 0x9b, 0x9a, 0x9a, 0x98, + 0x97, 0x97, 0x97, 0x96, 0x96, 0x94, 0x94, 0x94, 0x92, 0x91, 0x8f, 0x8e, + 0x8e, 0x8d, 0x8b, 0x8a, 0x8a, 0x8a, 0x89, 0x8a, 0x88, 0x87, 0x85, 0x84, + 0x82, 0x80, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x7f, 0x80, 0x81, 0x83, 0x83, + 0x84, 0x84, 0x84, 0x86, 0x89, 0x89, 0x89, 0x89, 0x8b, 0x8b, 0x8d, 0x8e, + 0x90, 0x90, 0x91, 0x92, 0x93, 0x93, 0x94, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x99, 0x9a, 0x99, 0x99, 0x9a, 0x9a, 0x9a, 0x99, 0x98, 0x98, + 0x97, 0x96, 0x97, 0x96, 0x93, 0x93, 0x93, 0x91, 0x92, 0x92, 0x92, 0x92, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x8f, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8e, 0x8c, 0x8d, + 0x8d, 0x8b, 0x8b, 0x89, 0x89, 0x88, 0x87, 0x87, 0x88, 0x88, 0x88, 0x87, + 0x88, 0x8a, 0x8b, 0x8d, 0x8e, 0x8f, 0x90, 0x93, 0x95, 0x96, 0x97, 0x97, + 0x98, 0x99, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x99, 0x9a, 0x99, 0x9a, + 0x9b, 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x99, 0x9a, 0x9b, 0x9b, 0x9c, 0x9e, + 0xa0, 0xa0, 0xa2, 0xa2, 0xa1, 0xa0, 0x9c, 0x99, 0x97, 0x93, 0x8e, 0x86, + 0x81, 0x7d, 0x78, 0x73, 0x6a, 0x64, 0x60, 0x5a, 0x55, 0x54, 0x55, 0x56, + 0x57, 0x57, 0x58, 0x5a, 0x5c, 0x5d, 0x5d, 0x5f, 0x62, 0x64, 0x65, 0x65, + 0x67, 0x67, 0x69, 0x6a, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e, 0x6f, 0x6f, 0x71, + 0x71, 0x71, 0x70, 0x6f, 0x6d, 0x6c, 0x6b, 0x67, 0x64, 0x5e, 0x5b, 0x58, + 0x56, 0x51, 0x4b, 0x47, 0x44, 0x3f, 0x38, 0x30, 0x26, 0x20, 0x1a, 0x14, + 0x12, 0x11, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, + 0x12, 0x12, 0x11, 0x12, 0x12, 0x13, 0x13, 0x12, 0x86, 0x86, 0x87, 0x87, + 0x86, 0x85, 0x85, 0x84, 0x83, 0x82, 0x80, 0x7d, 0x7c, 0x7b, 0x77, 0x76, + 0x75, 0x74, 0x74, 0x72, 0x70, 0x70, 0x6e, 0x6d, 0x6a, 0x68, 0x69, 0x6b, + 0x6d, 0x72, 0x78, 0x7d, 0x81, 0x83, 0x87, 0x8a, 0x8e, 0x92, 0x93, 0x93, + 0x93, 0x93, 0x92, 0x91, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x95, + 0x96, 0x97, 0x99, 0x9b, 0x9d, 0x9d, 0x9e, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1, + 0x9f, 0x9d, 0x9d, 0x9d, 0x9c, 0x9b, 0x9b, 0x99, 0x98, 0x99, 0x98, 0x96, + 0x96, 0x94, 0x94, 0x94, 0x93, 0x92, 0x90, 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, + 0x8b, 0x8a, 0x89, 0x8a, 0x89, 0x87, 0x86, 0x85, 0x82, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x80, 0x82, 0x83, 0x84, 0x84, 0x84, 0x86, + 0x89, 0x89, 0x8a, 0x8a, 0x8b, 0x8b, 0x8d, 0x8e, 0x90, 0x90, 0x91, 0x93, + 0x93, 0x94, 0x95, 0x94, 0x95, 0x95, 0x96, 0x97, 0x98, 0x9a, 0x9a, 0x9a, + 0x99, 0x9a, 0x9b, 0x9a, 0x9a, 0x99, 0x98, 0x98, 0x97, 0x97, 0x97, 0x97, + 0x93, 0x92, 0x92, 0x91, 0x91, 0x93, 0x93, 0x92, 0x91, 0x92, 0x92, 0x91, + 0x91, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91, 0x91, 0x8f, 0x8e, 0x8f, + 0x8f, 0x90, 0x90, 0x90, 0x90, 0x8e, 0x8d, 0x8e, 0x8e, 0x8c, 0x8a, 0x89, + 0x89, 0x89, 0x89, 0x87, 0x88, 0x88, 0x88, 0x87, 0x89, 0x89, 0x8b, 0x8d, + 0x8e, 0x8f, 0x91, 0x94, 0x96, 0x96, 0x97, 0x97, 0x98, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9b, 0x9a, 0x99, 0x99, + 0x9b, 0x9b, 0x99, 0x9a, 0x9b, 0x9b, 0x9c, 0x9f, 0xa0, 0xa0, 0xa1, 0xa2, + 0xa0, 0x9d, 0x9a, 0x97, 0x94, 0x8f, 0x89, 0x81, 0x7b, 0x78, 0x74, 0x6e, + 0x65, 0x60, 0x5c, 0x58, 0x55, 0x54, 0x55, 0x56, 0x57, 0x57, 0x57, 0x59, + 0x5c, 0x5d, 0x5d, 0x5f, 0x61, 0x64, 0x64, 0x64, 0x67, 0x68, 0x68, 0x69, + 0x6b, 0x6c, 0x6d, 0x6d, 0x6d, 0x6f, 0x70, 0x71, 0x71, 0x71, 0x70, 0x6f, + 0x6e, 0x6c, 0x6b, 0x68, 0x64, 0x5e, 0x5a, 0x58, 0x56, 0x52, 0x4b, 0x47, + 0x45, 0x40, 0x39, 0x31, 0x27, 0x21, 0x1b, 0x14, 0x12, 0x11, 0x10, 0x10, + 0x10, 0x11, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x11, 0x12, + 0x12, 0x12, 0x13, 0x13, 0x87, 0x87, 0x87, 0x87, 0x86, 0x86, 0x85, 0x84, + 0x83, 0x82, 0x80, 0x7d, 0x7c, 0x7a, 0x77, 0x75, 0x76, 0x75, 0x74, 0x72, + 0x70, 0x6f, 0x6e, 0x6d, 0x6b, 0x69, 0x68, 0x69, 0x6b, 0x6f, 0x76, 0x7c, + 0x80, 0x82, 0x86, 0x89, 0x8e, 0x91, 0x93, 0x93, 0x95, 0x95, 0x93, 0x92, + 0x91, 0x92, 0x92, 0x93, 0x93, 0x95, 0x96, 0x95, 0x96, 0x97, 0x99, 0x9b, + 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa1, 0xa1, 0xa0, 0x9e, 0x9e, 0x9e, + 0x9d, 0x9c, 0x9b, 0x99, 0x99, 0x99, 0x99, 0x97, 0x96, 0x94, 0x94, 0x94, + 0x93, 0x91, 0x8f, 0x8f, 0x8e, 0x8d, 0x8c, 0x8c, 0x8b, 0x8a, 0x8a, 0x8a, + 0x89, 0x87, 0x85, 0x84, 0x82, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, + 0x7f, 0x7f, 0x82, 0x83, 0x84, 0x84, 0x84, 0x86, 0x89, 0x89, 0x89, 0x8a, + 0x8b, 0x8b, 0x8d, 0x8e, 0x90, 0x90, 0x92, 0x93, 0x93, 0x94, 0x95, 0x95, + 0x95, 0x95, 0x96, 0x97, 0x98, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9a, + 0x9a, 0x99, 0x99, 0x99, 0x97, 0x97, 0x97, 0x96, 0x93, 0x92, 0x92, 0x92, + 0x92, 0x93, 0x93, 0x92, 0x91, 0x92, 0x92, 0x91, 0x91, 0x90, 0x90, 0x90, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x8f, 0x8e, 0x8f, 0x8f, 0x90, 0x90, 0x90, + 0x90, 0x8e, 0x8e, 0x8f, 0x8e, 0x8d, 0x8b, 0x89, 0x89, 0x89, 0x88, 0x87, + 0x88, 0x88, 0x88, 0x87, 0x89, 0x89, 0x8b, 0x8d, 0x8d, 0x8f, 0x91, 0x94, + 0x95, 0x96, 0x96, 0x97, 0x98, 0x99, 0x99, 0x99, 0x99, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x99, 0x9a, 0x9b, 0x9a, 0x99, 0x99, 0x9a, 0x9a, 0x9a, 0x9a, + 0x9b, 0x9b, 0x9c, 0x9f, 0xa0, 0xa1, 0xa1, 0xa1, 0xa0, 0x9d, 0x99, 0x95, + 0x92, 0x8d, 0x86, 0x7e, 0x79, 0x75, 0x72, 0x6b, 0x61, 0x5d, 0x5a, 0x57, + 0x54, 0x54, 0x56, 0x57, 0x58, 0x57, 0x58, 0x5a, 0x5c, 0x5d, 0x5d, 0x5f, + 0x61, 0x64, 0x64, 0x64, 0x67, 0x68, 0x67, 0x68, 0x6b, 0x6c, 0x6d, 0x6d, + 0x6d, 0x6f, 0x70, 0x71, 0x71, 0x71, 0x70, 0x6f, 0x6e, 0x6c, 0x6b, 0x68, + 0x64, 0x5e, 0x5b, 0x58, 0x56, 0x52, 0x4c, 0x47, 0x45, 0x41, 0x38, 0x31, + 0x28, 0x22, 0x1b, 0x14, 0x12, 0x11, 0x10, 0x10, 0x10, 0x11, 0x10, 0x11, + 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x11, 0x12, 0x11, 0x12, 0x13, 0x12, + 0x88, 0x88, 0x87, 0x86, 0x86, 0x87, 0x86, 0x84, 0x83, 0x82, 0x7f, 0x7c, + 0x7a, 0x79, 0x76, 0x75, 0x75, 0x75, 0x74, 0x72, 0x6f, 0x6e, 0x6f, 0x6f, + 0x6d, 0x69, 0x67, 0x68, 0x69, 0x6c, 0x74, 0x7a, 0x7e, 0x81, 0x83, 0x88, + 0x8d, 0x91, 0x93, 0x94, 0x97, 0x97, 0x95, 0x93, 0x92, 0x92, 0x93, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x95, 0x96, 0x98, 0x9b, 0x9d, 0x9e, 0x9f, 0xa1, + 0xa2, 0xa3, 0xa2, 0xa1, 0xa1, 0x9e, 0x9e, 0x9e, 0x9d, 0x9c, 0x9c, 0x9a, + 0x99, 0x9a, 0x99, 0x98, 0x96, 0x94, 0x94, 0x93, 0x91, 0x90, 0x8f, 0x90, + 0x8f, 0x8e, 0x8c, 0x8c, 0x8c, 0x8b, 0x8a, 0x8a, 0x89, 0x86, 0x85, 0x83, + 0x82, 0x81, 0x81, 0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x82, 0x83, + 0x84, 0x84, 0x84, 0x86, 0x87, 0x87, 0x88, 0x89, 0x8b, 0x8b, 0x8d, 0x8e, + 0x90, 0x91, 0x93, 0x94, 0x94, 0x94, 0x95, 0x94, 0x95, 0x96, 0x96, 0x97, + 0x99, 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9a, 0x9b, 0x9a, 0x9a, 0x99, 0x99, + 0x98, 0x97, 0x98, 0x97, 0x93, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x92, + 0x91, 0x92, 0x92, 0x91, 0x91, 0x8f, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x8f, 0x8f, 0x90, 0x90, 0x8e, 0x8f, 0x8f, 0x8f, 0x90, 0x8f, 0x90, + 0x8f, 0x8d, 0x8b, 0x89, 0x89, 0x88, 0x86, 0x86, 0x88, 0x88, 0x88, 0x87, + 0x89, 0x8a, 0x8b, 0x8d, 0x8e, 0x8f, 0x91, 0x93, 0x94, 0x95, 0x95, 0x97, + 0x99, 0x9a, 0x9a, 0x99, 0x98, 0x97, 0x97, 0x97, 0x98, 0x98, 0x9a, 0x9b, + 0x9b, 0x9a, 0x99, 0x98, 0x99, 0x99, 0x9a, 0x9b, 0x9b, 0x9b, 0x9c, 0x9e, + 0x9f, 0xa0, 0xa1, 0xa0, 0x9e, 0x9b, 0x97, 0x93, 0x90, 0x8a, 0x83, 0x7c, + 0x76, 0x73, 0x6f, 0x66, 0x5d, 0x5a, 0x58, 0x56, 0x54, 0x54, 0x56, 0x58, + 0x59, 0x58, 0x5a, 0x5b, 0x5c, 0x5d, 0x5d, 0x5f, 0x62, 0x63, 0x63, 0x63, + 0x66, 0x67, 0x67, 0x67, 0x6a, 0x6c, 0x6d, 0x6d, 0x6d, 0x6f, 0x70, 0x70, + 0x70, 0x70, 0x70, 0x6f, 0x6e, 0x6c, 0x6b, 0x68, 0x62, 0x5f, 0x5a, 0x58, + 0x56, 0x52, 0x4c, 0x48, 0x45, 0x41, 0x39, 0x30, 0x28, 0x22, 0x1b, 0x14, + 0x11, 0x11, 0x10, 0x11, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, + 0x12, 0x11, 0x12, 0x12, 0x11, 0x11, 0x12, 0x11, 0x8a, 0x8a, 0x89, 0x88, + 0x88, 0x87, 0x85, 0x83, 0x82, 0x7f, 0x7c, 0x7a, 0x78, 0x77, 0x76, 0x73, + 0x73, 0x73, 0x73, 0x72, 0x70, 0x6f, 0x6f, 0x6f, 0x6d, 0x69, 0x67, 0x66, + 0x68, 0x6a, 0x70, 0x77, 0x7a, 0x7d, 0x80, 0x86, 0x8c, 0x90, 0x93, 0x95, + 0x98, 0x98, 0x97, 0x95, 0x94, 0x94, 0x94, 0x94, 0x94, 0x93, 0x93, 0x93, + 0x94, 0x96, 0x98, 0x9b, 0x9d, 0x9e, 0x9f, 0xa1, 0xa2, 0xa4, 0xa3, 0xa3, + 0xa2, 0xa1, 0x9f, 0xa0, 0x9f, 0x9e, 0x9c, 0x9b, 0x9a, 0x99, 0x99, 0x98, + 0x96, 0x94, 0x93, 0x92, 0x91, 0x8f, 0x90, 0x90, 0x8e, 0x8d, 0x8d, 0x8d, + 0x8c, 0x8c, 0x8a, 0x8a, 0x87, 0x86, 0x86, 0x83, 0x82, 0x81, 0x81, 0x81, + 0x80, 0x80, 0x80, 0x7f, 0x80, 0x80, 0x82, 0x81, 0x83, 0x83, 0x83, 0x85, + 0x86, 0x86, 0x87, 0x89, 0x8b, 0x8b, 0x8d, 0x8e, 0x90, 0x92, 0x94, 0x94, + 0x95, 0x95, 0x95, 0x95, 0x96, 0x97, 0x97, 0x97, 0x99, 0x9b, 0x9a, 0x9a, + 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9a, 0x98, 0x99, 0x99, 0x98, 0x98, 0x97, + 0x97, 0x96, 0x94, 0x93, 0x93, 0x93, 0x93, 0x92, 0x91, 0x92, 0x92, 0x91, + 0x91, 0x8f, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91, 0x91, 0x90, 0x90, 0x90, + 0x90, 0x8f, 0x8f, 0x8f, 0x8f, 0x90, 0x8f, 0x90, 0x8f, 0x8d, 0x8d, 0x8b, + 0x8a, 0x89, 0x87, 0x86, 0x88, 0x88, 0x88, 0x87, 0x89, 0x8b, 0x8c, 0x8d, + 0x8e, 0x8e, 0x90, 0x92, 0x93, 0x94, 0x95, 0x96, 0x99, 0x99, 0x98, 0x97, + 0x97, 0x96, 0x95, 0x96, 0x97, 0x98, 0x99, 0x99, 0x99, 0x99, 0x98, 0x97, + 0x98, 0x99, 0x9a, 0x99, 0x9a, 0x9c, 0x9e, 0x9f, 0x9f, 0xa0, 0xa0, 0x9e, + 0x9c, 0x98, 0x93, 0x8f, 0x8b, 0x84, 0x7d, 0x77, 0x72, 0x6f, 0x69, 0x61, + 0x5a, 0x58, 0x58, 0x56, 0x54, 0x54, 0x56, 0x57, 0x59, 0x5b, 0x5b, 0x5b, + 0x5c, 0x5d, 0x5e, 0x60, 0x60, 0x62, 0x62, 0x62, 0x64, 0x64, 0x66, 0x67, + 0x69, 0x6a, 0x6d, 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x6f, 0x70, 0x6f, + 0x6e, 0x6c, 0x6b, 0x68, 0x62, 0x5f, 0x5a, 0x58, 0x56, 0x52, 0x4c, 0x47, + 0x44, 0x40, 0x38, 0x30, 0x29, 0x24, 0x1c, 0x14, 0x12, 0x11, 0x10, 0x10, + 0x11, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x11, 0x12, 0x12, + 0x11, 0x11, 0x12, 0x11, 0x8c, 0x8b, 0x8a, 0x88, 0x88, 0x86, 0x84, 0x81, + 0x80, 0x7d, 0x79, 0x78, 0x77, 0x76, 0x75, 0x72, 0x72, 0x72, 0x72, 0x71, + 0x6f, 0x6f, 0x6e, 0x6e, 0x6b, 0x68, 0x65, 0x65, 0x65, 0x67, 0x6c, 0x72, + 0x77, 0x7a, 0x7e, 0x84, 0x8b, 0x90, 0x92, 0x95, 0x99, 0x9a, 0x99, 0x98, + 0x96, 0x95, 0x95, 0x95, 0x95, 0x94, 0x93, 0x94, 0x95, 0x96, 0x98, 0x9b, + 0x9d, 0x9e, 0x9f, 0xa0, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa1, 0xa0, 0xa0, + 0xa0, 0x9f, 0x9d, 0x9c, 0x9b, 0x9b, 0x9a, 0x98, 0x95, 0x93, 0x94, 0x93, + 0x91, 0x8f, 0x90, 0x90, 0x8f, 0x8d, 0x8d, 0x8e, 0x8e, 0x8d, 0x8b, 0x8b, + 0x88, 0x86, 0x85, 0x83, 0x82, 0x81, 0x81, 0x80, 0x7f, 0x7f, 0x80, 0x80, + 0x80, 0x80, 0x82, 0x82, 0x83, 0x83, 0x83, 0x84, 0x86, 0x86, 0x86, 0x89, + 0x8a, 0x8b, 0x8d, 0x8e, 0x91, 0x92, 0x94, 0x94, 0x95, 0x95, 0x95, 0x95, + 0x96, 0x97, 0x97, 0x97, 0x99, 0x9b, 0x9a, 0x99, 0x9a, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9a, 0x9a, 0x9a, 0x99, 0x98, 0x98, 0x97, 0x97, 0x96, 0x95, 0x93, + 0x92, 0x92, 0x92, 0x92, 0x91, 0x91, 0x92, 0x91, 0x91, 0x8f, 0x90, 0x8f, + 0x90, 0x90, 0x8f, 0x90, 0x90, 0x8f, 0x90, 0x90, 0x90, 0x8e, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x90, 0x8f, 0x8e, 0x8e, 0x8c, 0x8b, 0x89, 0x87, 0x87, + 0x88, 0x87, 0x87, 0x87, 0x89, 0x8b, 0x8c, 0x8d, 0x8e, 0x8e, 0x90, 0x92, + 0x93, 0x93, 0x95, 0x96, 0x98, 0x99, 0x98, 0x98, 0x97, 0x96, 0x97, 0x97, + 0x96, 0x96, 0x98, 0x98, 0x98, 0x97, 0x97, 0x97, 0x99, 0x9a, 0x9a, 0x99, + 0x9a, 0x9c, 0x9d, 0x9d, 0xa0, 0x9f, 0x9d, 0x9b, 0x99, 0x94, 0x8d, 0x89, + 0x85, 0x7e, 0x77, 0x70, 0x6c, 0x68, 0x62, 0x5c, 0x59, 0x58, 0x58, 0x57, + 0x56, 0x56, 0x57, 0x58, 0x59, 0x5b, 0x5a, 0x5a, 0x5c, 0x5d, 0x5e, 0x5f, + 0x61, 0x62, 0x62, 0x63, 0x64, 0x64, 0x65, 0x67, 0x68, 0x69, 0x6c, 0x6d, + 0x6d, 0x6c, 0x6f, 0x70, 0x70, 0x70, 0x70, 0x6f, 0x6d, 0x6b, 0x6a, 0x68, + 0x62, 0x5f, 0x5a, 0x58, 0x56, 0x52, 0x4c, 0x47, 0x44, 0x3f, 0x38, 0x30, + 0x29, 0x24, 0x1c, 0x14, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x10, 0x11, + 0x11, 0x11, 0x11, 0x12, 0x13, 0x12, 0x12, 0x12, 0x11, 0x10, 0x11, 0x13, + 0x8e, 0x8c, 0x8b, 0x8a, 0x88, 0x86, 0x84, 0x82, 0x7f, 0x7c, 0x79, 0x77, + 0x76, 0x76, 0x75, 0x73, 0x72, 0x70, 0x70, 0x71, 0x6f, 0x6f, 0x6d, 0x6c, + 0x69, 0x68, 0x66, 0x63, 0x63, 0x64, 0x68, 0x6e, 0x74, 0x78, 0x7c, 0x81, + 0x89, 0x8e, 0x91, 0x94, 0x99, 0x9a, 0x9a, 0x99, 0x98, 0x96, 0x96, 0x95, + 0x95, 0x93, 0x93, 0x95, 0x95, 0x96, 0x98, 0x9b, 0x9d, 0x9e, 0x9f, 0xa0, + 0xa1, 0xa3, 0xa3, 0xa3, 0xa3, 0xa2, 0xa1, 0x9f, 0x9f, 0x9f, 0x9e, 0x9c, + 0x9c, 0x9b, 0x9b, 0x98, 0x96, 0x94, 0x94, 0x93, 0x90, 0x8f, 0x8e, 0x8f, + 0x8f, 0x8e, 0x8e, 0x8f, 0x8f, 0x8e, 0x8c, 0x8c, 0x89, 0x85, 0x83, 0x82, + 0x81, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x82, 0x82, + 0x82, 0x83, 0x84, 0x85, 0x87, 0x87, 0x87, 0x87, 0x8a, 0x8c, 0x8c, 0x8e, + 0x90, 0x92, 0x93, 0x93, 0x94, 0x96, 0x95, 0x96, 0x97, 0x98, 0x98, 0x98, + 0x99, 0x9b, 0x9b, 0x9b, 0x9b, 0x9a, 0x9b, 0x9b, 0x9c, 0x9b, 0x9a, 0x9a, + 0x99, 0x99, 0x99, 0x97, 0x97, 0x96, 0x95, 0x95, 0x93, 0x93, 0x93, 0x93, + 0x92, 0x92, 0x91, 0x90, 0x90, 0x91, 0x90, 0x90, 0x91, 0x91, 0x90, 0x91, + 0x90, 0x91, 0x91, 0x90, 0x90, 0x90, 0x90, 0x90, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8b, 0x89, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x88, 0x8a, 0x8a, 0x8c, 0x8d, 0x8e, 0x90, 0x91, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x95, 0x96, 0x96, 0x95, 0x95, 0x97, 0x97, + 0x96, 0x95, 0x96, 0x98, 0x99, 0x99, 0x9a, 0x9a, 0x9b, 0x9d, 0x9e, 0x9e, + 0x9f, 0x9e, 0x9b, 0x99, 0x96, 0x91, 0x8a, 0x85, 0x81, 0x7b, 0x74, 0x6d, + 0x67, 0x63, 0x5e, 0x5a, 0x58, 0x58, 0x57, 0x57, 0x56, 0x57, 0x57, 0x58, + 0x59, 0x5b, 0x5c, 0x5b, 0x5c, 0x5d, 0x5f, 0x60, 0x60, 0x61, 0x62, 0x64, + 0x65, 0x64, 0x65, 0x67, 0x68, 0x69, 0x6b, 0x6b, 0x6c, 0x6e, 0x6f, 0x70, + 0x70, 0x70, 0x70, 0x6f, 0x6d, 0x6b, 0x69, 0x66, 0x63, 0x5e, 0x5b, 0x5a, + 0x56, 0x52, 0x4d, 0x47, 0x44, 0x3f, 0x37, 0x30, 0x29, 0x24, 0x1d, 0x14, + 0x11, 0x10, 0x10, 0x10, 0x11, 0x10, 0x11, 0x11, 0x12, 0x11, 0x11, 0x12, + 0x13, 0x11, 0x11, 0x11, 0x11, 0x10, 0x11, 0x12, 0x8f, 0x8c, 0x8b, 0x8a, + 0x88, 0x85, 0x83, 0x81, 0x7f, 0x7c, 0x78, 0x77, 0x76, 0x75, 0x73, 0x73, + 0x71, 0x70, 0x6f, 0x70, 0x70, 0x70, 0x6d, 0x6b, 0x69, 0x68, 0x65, 0x62, + 0x62, 0x63, 0x66, 0x6c, 0x72, 0x76, 0x7b, 0x81, 0x88, 0x8d, 0x90, 0x93, + 0x99, 0x9a, 0x9a, 0x99, 0x98, 0x96, 0x96, 0x95, 0x94, 0x92, 0x93, 0x95, + 0x95, 0x95, 0x98, 0x9a, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa2, 0xa2, 0xa0, 0x9e, 0x9e, 0x9e, 0x9d, 0x9d, 0x9b, 0x9a, 0x98, + 0x96, 0x94, 0x94, 0x93, 0x91, 0x90, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x90, + 0x8f, 0x8e, 0x8d, 0x8c, 0x88, 0x84, 0x82, 0x82, 0x80, 0x7f, 0x80, 0x80, + 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x81, 0x82, 0x82, 0x82, 0x84, 0x85, + 0x87, 0x87, 0x87, 0x87, 0x8a, 0x8c, 0x8d, 0x8e, 0x90, 0x91, 0x93, 0x93, + 0x95, 0x95, 0x96, 0x96, 0x98, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9b, 0x9b, + 0x9b, 0x9a, 0x9b, 0x9c, 0x9c, 0x9c, 0x9a, 0x9a, 0x9a, 0x9a, 0x99, 0x97, + 0x97, 0x96, 0x96, 0x96, 0x94, 0x94, 0x94, 0x94, 0x93, 0x92, 0x90, 0x90, + 0x90, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x90, + 0x91, 0x90, 0x91, 0x90, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8e, 0x8e, 0x8c, + 0x8c, 0x8c, 0x8a, 0x88, 0x86, 0x87, 0x87, 0x87, 0x87, 0x89, 0x8a, 0x8b, + 0x8c, 0x8e, 0x90, 0x91, 0x92, 0x93, 0x95, 0x96, 0x96, 0x97, 0x96, 0x97, + 0x97, 0x95, 0x96, 0x96, 0x95, 0x95, 0x96, 0x96, 0x96, 0x95, 0x96, 0x98, + 0x98, 0x99, 0x9a, 0x9a, 0x9c, 0x9e, 0x9e, 0x9e, 0x9e, 0x9c, 0x9a, 0x98, + 0x94, 0x8f, 0x88, 0x83, 0x7f, 0x79, 0x71, 0x6a, 0x64, 0x60, 0x5c, 0x59, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58, 0x5a, 0x5b, 0x5c, 0x5b, + 0x5c, 0x5d, 0x5f, 0x60, 0x60, 0x61, 0x62, 0x64, 0x64, 0x64, 0x66, 0x67, + 0x68, 0x68, 0x6b, 0x6b, 0x6b, 0x6e, 0x6f, 0x70, 0x70, 0x70, 0x70, 0x6f, + 0x6c, 0x6a, 0x68, 0x66, 0x63, 0x5e, 0x5c, 0x5a, 0x56, 0x52, 0x4d, 0x47, + 0x43, 0x3f, 0x37, 0x30, 0x28, 0x23, 0x1d, 0x14, 0x11, 0x10, 0x10, 0x10, + 0x11, 0x10, 0x11, 0x11, 0x12, 0x11, 0x11, 0x12, 0x12, 0x11, 0x10, 0x11, + 0x11, 0x10, 0x11, 0x12, 0x90, 0x8d, 0x8b, 0x89, 0x87, 0x84, 0x82, 0x7f, + 0x7d, 0x7a, 0x76, 0x76, 0x75, 0x74, 0x72, 0x72, 0x70, 0x6e, 0x6e, 0x6f, + 0x6e, 0x6e, 0x6b, 0x69, 0x68, 0x68, 0x65, 0x63, 0x62, 0x61, 0x62, 0x68, + 0x6f, 0x73, 0x78, 0x7e, 0x85, 0x8b, 0x8e, 0x91, 0x97, 0x9a, 0x9a, 0x9a, + 0x99, 0x97, 0x97, 0x96, 0x95, 0x93, 0x93, 0x95, 0x95, 0x95, 0x96, 0x9a, + 0x9c, 0x9e, 0x9f, 0xa0, 0xa1, 0xa3, 0xa3, 0xa4, 0xa4, 0xa2, 0xa2, 0xa1, + 0xa0, 0x9f, 0x9f, 0x9d, 0x9d, 0x9b, 0x9a, 0x99, 0x96, 0x94, 0x94, 0x93, + 0x92, 0x8f, 0x8e, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x8f, 0x8f, 0x8d, 0x8b, + 0x87, 0x83, 0x82, 0x82, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7e, + 0x7f, 0x80, 0x80, 0x81, 0x82, 0x83, 0x84, 0x84, 0x85, 0x85, 0x85, 0x86, + 0x89, 0x8c, 0x8d, 0x8e, 0x90, 0x91, 0x93, 0x93, 0x95, 0x95, 0x96, 0x97, + 0x97, 0x99, 0x99, 0x99, 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9a, 0x9c, 0x9d, + 0x9c, 0x9c, 0x9a, 0x9a, 0x9a, 0x99, 0x99, 0x98, 0x98, 0x97, 0x97, 0x97, + 0x94, 0x94, 0x94, 0x94, 0x93, 0x91, 0x90, 0x90, 0x90, 0x90, 0x8f, 0x90, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x90, 0x91, 0x91, 0x91, 0x91, + 0x90, 0x91, 0x90, 0x90, 0x8f, 0x8e, 0x8e, 0x8d, 0x8b, 0x8a, 0x89, 0x89, + 0x87, 0x87, 0x87, 0x86, 0x87, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x90, 0x90, + 0x91, 0x92, 0x94, 0x96, 0x97, 0x97, 0x97, 0x97, 0x97, 0x96, 0x96, 0x95, + 0x94, 0x94, 0x96, 0x97, 0x97, 0x96, 0x96, 0x98, 0x97, 0x98, 0x99, 0x99, + 0x9b, 0x9d, 0x9d, 0x9d, 0x9c, 0x9a, 0x97, 0x95, 0x92, 0x8b, 0x84, 0x7e, + 0x7a, 0x74, 0x6d, 0x65, 0x60, 0x5d, 0x5a, 0x59, 0x57, 0x57, 0x57, 0x58, + 0x58, 0x58, 0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5f, 0x60, + 0x60, 0x61, 0x62, 0x63, 0x63, 0x65, 0x65, 0x66, 0x67, 0x67, 0x6a, 0x6b, + 0x6b, 0x6d, 0x6f, 0x70, 0x6f, 0x6f, 0x6f, 0x6f, 0x6c, 0x6a, 0x68, 0x66, + 0x63, 0x5e, 0x5c, 0x59, 0x56, 0x52, 0x4d, 0x47, 0x44, 0x3f, 0x36, 0x31, + 0x29, 0x24, 0x1c, 0x14, 0x11, 0x10, 0x10, 0x11, 0x11, 0x10, 0x10, 0x10, + 0x11, 0x10, 0x11, 0x11, 0x11, 0x11, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x91, 0x8e, 0x8b, 0x89, 0x87, 0x83, 0x80, 0x7d, 0x7b, 0x78, 0x76, 0x74, + 0x73, 0x72, 0x71, 0x70, 0x6f, 0x6d, 0x6d, 0x6e, 0x6d, 0x6b, 0x69, 0x68, + 0x66, 0x66, 0x64, 0x62, 0x61, 0x60, 0x61, 0x66, 0x6c, 0x70, 0x75, 0x7d, + 0x84, 0x89, 0x8c, 0x8f, 0x95, 0x98, 0x9a, 0x9a, 0x9b, 0x99, 0x97, 0x97, + 0x97, 0x95, 0x93, 0x94, 0x94, 0x94, 0x95, 0x99, 0x9b, 0x9e, 0x9f, 0x9f, + 0xa1, 0xa3, 0xa3, 0xa4, 0xa5, 0xa5, 0xa4, 0xa2, 0xa1, 0xa1, 0xa0, 0x9f, + 0x9d, 0x9a, 0x99, 0x98, 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x90, 0x8f, + 0x8f, 0x90, 0x90, 0x90, 0x8f, 0x8f, 0x8c, 0x89, 0x87, 0x85, 0x83, 0x82, + 0x81, 0x7f, 0x80, 0x80, 0x80, 0x7f, 0x7e, 0x7f, 0x80, 0x80, 0x80, 0x81, + 0x82, 0x83, 0x83, 0x83, 0x83, 0x84, 0x85, 0x87, 0x89, 0x8c, 0x8c, 0x8e, + 0x90, 0x91, 0x93, 0x93, 0x95, 0x95, 0x95, 0x96, 0x97, 0x98, 0x99, 0x99, + 0x9a, 0x9a, 0x9a, 0x9a, 0x99, 0x9a, 0x9d, 0x9d, 0x9d, 0x9c, 0x9d, 0x9c, + 0x9a, 0x99, 0x9a, 0x99, 0x99, 0x98, 0x98, 0x97, 0x95, 0x93, 0x93, 0x93, + 0x92, 0x92, 0x92, 0x92, 0x91, 0x90, 0x90, 0x90, 0x90, 0x8f, 0x8f, 0x91, + 0x90, 0x90, 0x91, 0x92, 0x93, 0x92, 0x92, 0x92, 0x92, 0x92, 0x91, 0x91, + 0x90, 0x8f, 0x8f, 0x8d, 0x8d, 0x8b, 0x8a, 0x8a, 0x88, 0x89, 0x88, 0x88, + 0x87, 0x89, 0x89, 0x8b, 0x8c, 0x8d, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x95, + 0x96, 0x97, 0x97, 0x97, 0x97, 0x96, 0x96, 0x95, 0x94, 0x94, 0x95, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x97, 0x99, 0x99, 0x9a, 0x9a, 0x9b, 0x9c, + 0x9b, 0x97, 0x94, 0x92, 0x8e, 0x86, 0x7e, 0x78, 0x73, 0x6d, 0x67, 0x5f, + 0x5b, 0x5a, 0x58, 0x59, 0x58, 0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, + 0x5b, 0x5a, 0x5b, 0x5b, 0x5c, 0x5d, 0x5f, 0x5f, 0x61, 0x61, 0x61, 0x62, + 0x62, 0x65, 0x66, 0x66, 0x66, 0x67, 0x69, 0x6b, 0x6b, 0x6c, 0x6d, 0x6f, + 0x6f, 0x6f, 0x6f, 0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x64, 0x5e, 0x5c, 0x59, + 0x55, 0x50, 0x4b, 0x47, 0x44, 0x40, 0x38, 0x31, 0x2c, 0x26, 0x1d, 0x15, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x12, + 0x12, 0x12, 0x12, 0x11, 0x12, 0x12, 0x13, 0x11, 0x90, 0x8d, 0x8b, 0x89, + 0x86, 0x82, 0x7f, 0x7c, 0x7a, 0x78, 0x76, 0x72, 0x70, 0x70, 0x70, 0x70, + 0x6e, 0x6d, 0x6c, 0x6c, 0x6b, 0x68, 0x67, 0x66, 0x66, 0x65, 0x64, 0x62, + 0x61, 0x61, 0x62, 0x64, 0x68, 0x6b, 0x72, 0x7a, 0x82, 0x87, 0x8a, 0x8f, + 0x93, 0x96, 0x98, 0x9a, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96, 0x93, 0x93, + 0x92, 0x93, 0x95, 0x97, 0x9b, 0x9e, 0x9f, 0xa0, 0xa1, 0xa4, 0xa4, 0xa5, + 0xa6, 0xa6, 0xa5, 0xa4, 0xa3, 0xa1, 0x9f, 0x9e, 0x9d, 0x9b, 0x99, 0x98, + 0x95, 0x94, 0x93, 0x92, 0x90, 0x90, 0x90, 0x8f, 0x8f, 0x8f, 0x90, 0x90, + 0x8f, 0x8e, 0x8c, 0x89, 0x87, 0x85, 0x83, 0x82, 0x81, 0x80, 0x80, 0x80, + 0x7e, 0x7e, 0x7e, 0x7f, 0x7f, 0x7f, 0x80, 0x81, 0x81, 0x81, 0x81, 0x83, + 0x83, 0x85, 0x86, 0x87, 0x88, 0x8b, 0x8b, 0x8c, 0x8e, 0x91, 0x93, 0x94, + 0x94, 0x95, 0x95, 0x96, 0x98, 0x98, 0x99, 0x99, 0x9b, 0x9b, 0x9a, 0x9a, + 0x9a, 0x9c, 0x9e, 0x9e, 0x9d, 0x9d, 0x9d, 0x9b, 0x9b, 0x9c, 0x9b, 0x9a, + 0x9a, 0x98, 0x98, 0x97, 0x95, 0x94, 0x93, 0x92, 0x93, 0x92, 0x93, 0x93, + 0x92, 0x91, 0x92, 0x92, 0x91, 0x90, 0x90, 0x91, 0x92, 0x91, 0x92, 0x93, + 0x93, 0x92, 0x92, 0x92, 0x92, 0x93, 0x92, 0x91, 0x91, 0x8f, 0x90, 0x8e, + 0x8d, 0x8d, 0x8c, 0x8a, 0x8a, 0x89, 0x89, 0x89, 0x8a, 0x8b, 0x8a, 0x8b, + 0x8c, 0x8d, 0x8f, 0x8f, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x96, 0x95, + 0x96, 0x94, 0x94, 0x95, 0x96, 0x95, 0x96, 0x95, 0x95, 0x95, 0x96, 0x96, + 0x97, 0x97, 0x97, 0x99, 0x9a, 0x9a, 0x9a, 0x9a, 0x99, 0x95, 0x91, 0x8e, + 0x89, 0x81, 0x78, 0x72, 0x6e, 0x68, 0x60, 0x5b, 0x5a, 0x59, 0x57, 0x57, + 0x58, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5b, 0x5c, 0x5f, + 0x60, 0x60, 0x60, 0x60, 0x61, 0x60, 0x5f, 0x60, 0x62, 0x64, 0x65, 0x65, + 0x65, 0x67, 0x68, 0x6a, 0x6a, 0x6b, 0x6c, 0x6e, 0x6d, 0x6e, 0x6f, 0x6f, + 0x6e, 0x6d, 0x6b, 0x68, 0x65, 0x61, 0x5c, 0x59, 0x56, 0x50, 0x4c, 0x49, + 0x46, 0x41, 0x3a, 0x32, 0x2c, 0x27, 0x1f, 0x16, 0x11, 0x11, 0x11, 0x11, + 0x12, 0x12, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x11, 0x12, 0x11, + 0x12, 0x12, 0x12, 0x13, 0x8f, 0x8c, 0x8a, 0x88, 0x85, 0x81, 0x7e, 0x7b, + 0x7a, 0x78, 0x75, 0x71, 0x70, 0x6f, 0x6f, 0x6f, 0x6e, 0x6b, 0x6a, 0x6a, + 0x69, 0x67, 0x65, 0x65, 0x64, 0x63, 0x62, 0x62, 0x62, 0x62, 0x62, 0x63, + 0x65, 0x68, 0x6f, 0x77, 0x7f, 0x85, 0x88, 0x8d, 0x92, 0x95, 0x98, 0x99, + 0x9b, 0x9b, 0x9b, 0x99, 0x98, 0x97, 0x94, 0x93, 0x92, 0x93, 0x94, 0x96, + 0x9a, 0x9d, 0x9e, 0x9f, 0xa1, 0xa3, 0xa4, 0xa5, 0xa6, 0xa5, 0xa6, 0xa4, + 0xa4, 0xa3, 0xa0, 0x9f, 0x9d, 0x9b, 0x99, 0x99, 0x96, 0x94, 0x93, 0x92, + 0x90, 0x91, 0x91, 0x90, 0x8f, 0x8f, 0x90, 0x90, 0x8f, 0x8f, 0x8c, 0x8a, + 0x87, 0x84, 0x83, 0x82, 0x80, 0x80, 0x80, 0x80, 0x7e, 0x7e, 0x7e, 0x7e, + 0x7e, 0x7f, 0x80, 0x82, 0x81, 0x80, 0x80, 0x82, 0x83, 0x84, 0x86, 0x86, + 0x87, 0x8a, 0x8b, 0x8c, 0x8e, 0x91, 0x93, 0x94, 0x95, 0x95, 0x96, 0x97, + 0x99, 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9d, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9b, 0x9c, 0x9c, 0x9c, 0x9a, 0x9b, 0x99, 0x99, 0x98, + 0x97, 0x95, 0x94, 0x93, 0x94, 0x93, 0x93, 0x93, 0x93, 0x92, 0x92, 0x92, + 0x92, 0x91, 0x91, 0x93, 0x93, 0x92, 0x92, 0x94, 0x94, 0x93, 0x93, 0x93, + 0x93, 0x94, 0x93, 0x92, 0x92, 0x91, 0x90, 0x8f, 0x8f, 0x8e, 0x8c, 0x8a, + 0x8b, 0x8a, 0x89, 0x8a, 0x8a, 0x8b, 0x8a, 0x8b, 0x8c, 0x8c, 0x8e, 0x8f, + 0x90, 0x92, 0x93, 0x95, 0x96, 0x96, 0x96, 0x95, 0x96, 0x94, 0x94, 0x95, + 0x95, 0x95, 0x96, 0x96, 0x96, 0x95, 0x96, 0x95, 0x96, 0x96, 0x96, 0x99, + 0x9b, 0x9b, 0x9a, 0x99, 0x97, 0x93, 0x8f, 0x8b, 0x84, 0x7b, 0x73, 0x6d, + 0x69, 0x62, 0x5c, 0x5a, 0x59, 0x58, 0x57, 0x57, 0x57, 0x58, 0x59, 0x59, + 0x5a, 0x5c, 0x5c, 0x5c, 0x5c, 0x5b, 0x5d, 0x60, 0x61, 0x61, 0x5f, 0x60, + 0x61, 0x60, 0x60, 0x61, 0x61, 0x63, 0x64, 0x64, 0x64, 0x65, 0x67, 0x68, + 0x68, 0x69, 0x6b, 0x6d, 0x6e, 0x6e, 0x6f, 0x6f, 0x6e, 0x6e, 0x6c, 0x69, + 0x67, 0x62, 0x5c, 0x59, 0x56, 0x52, 0x4d, 0x4a, 0x46, 0x41, 0x3b, 0x34, + 0x2b, 0x27, 0x1f, 0x16, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x11, 0x11, + 0x12, 0x12, 0x12, 0x11, 0x11, 0x12, 0x11, 0x12, 0x12, 0x12, 0x12, 0x13, + 0x90, 0x8c, 0x89, 0x87, 0x84, 0x80, 0x7c, 0x7a, 0x79, 0x77, 0x74, 0x70, + 0x6f, 0x6e, 0x6e, 0x6f, 0x6e, 0x6b, 0x6a, 0x69, 0x68, 0x66, 0x64, 0x64, + 0x63, 0x62, 0x62, 0x62, 0x62, 0x61, 0x62, 0x62, 0x64, 0x66, 0x6c, 0x75, + 0x7d, 0x83, 0x87, 0x8b, 0x90, 0x93, 0x96, 0x98, 0x9a, 0x9b, 0x9b, 0x9a, + 0x99, 0x97, 0x95, 0x94, 0x93, 0x93, 0x93, 0x95, 0x99, 0x9c, 0x9d, 0x9f, + 0xa1, 0xa2, 0xa4, 0xa5, 0xa7, 0xa6, 0xa6, 0xa5, 0xa4, 0xa3, 0xa1, 0x9f, + 0x9d, 0x9b, 0x99, 0x98, 0x96, 0x94, 0x93, 0x92, 0x90, 0x91, 0x90, 0x90, + 0x8f, 0x8f, 0x90, 0x8f, 0x8f, 0x8f, 0x8d, 0x8a, 0x87, 0x84, 0x83, 0x82, + 0x81, 0x80, 0x80, 0x7f, 0x7e, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f, 0x80, 0x81, + 0x80, 0x80, 0x80, 0x81, 0x82, 0x84, 0x84, 0x85, 0x86, 0x8a, 0x8c, 0x8c, + 0x8e, 0x91, 0x93, 0x94, 0x95, 0x96, 0x96, 0x97, 0x99, 0x9a, 0x9a, 0x9a, + 0x9a, 0x9c, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0x9d, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9b, 0x9b, 0x9a, 0x99, 0x99, 0x97, 0x96, 0x95, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x93, 0x93, 0x92, 0x92, 0x92, 0x92, 0x93, + 0x93, 0x93, 0x92, 0x93, 0x94, 0x94, 0x94, 0x94, 0x94, 0x95, 0x94, 0x93, + 0x93, 0x92, 0x91, 0x8f, 0x8f, 0x8f, 0x8d, 0x8b, 0x8b, 0x8a, 0x89, 0x89, + 0x8a, 0x8b, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x91, 0x92, 0x94, 0x95, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x95, 0x95, 0x95, 0x95, 0x95, 0x96, 0x96, + 0x96, 0x95, 0x95, 0x94, 0x95, 0x95, 0x96, 0x98, 0x9a, 0x9b, 0x9a, 0x98, + 0x95, 0x91, 0x8e, 0x89, 0x81, 0x79, 0x70, 0x6a, 0x66, 0x5f, 0x59, 0x58, + 0x58, 0x57, 0x56, 0x56, 0x57, 0x58, 0x59, 0x59, 0x5b, 0x5d, 0x5d, 0x5c, + 0x5c, 0x5b, 0x5d, 0x60, 0x61, 0x61, 0x5f, 0x60, 0x61, 0x61, 0x60, 0x61, + 0x61, 0x61, 0x63, 0x63, 0x63, 0x65, 0x67, 0x67, 0x68, 0x69, 0x6a, 0x6d, + 0x6e, 0x6f, 0x6f, 0x6f, 0x6e, 0x6d, 0x6c, 0x6a, 0x67, 0x62, 0x5c, 0x5a, + 0x56, 0x52, 0x4d, 0x49, 0x46, 0x41, 0x3b, 0x34, 0x2c, 0x26, 0x1f, 0x15, + 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x13, 0x12, 0x12, 0x12, 0x13, 0x90, 0x8b, 0x88, 0x85, + 0x82, 0x7e, 0x7a, 0x78, 0x78, 0x76, 0x73, 0x6e, 0x6d, 0x6d, 0x6e, 0x6e, + 0x6b, 0x6a, 0x69, 0x67, 0x66, 0x65, 0x64, 0x63, 0x61, 0x60, 0x62, 0x61, + 0x61, 0x61, 0x62, 0x62, 0x63, 0x64, 0x69, 0x72, 0x7b, 0x81, 0x84, 0x88, + 0x8e, 0x92, 0x94, 0x96, 0x99, 0x9b, 0x9c, 0x9b, 0x9a, 0x98, 0x96, 0x96, + 0x94, 0x93, 0x94, 0x95, 0x98, 0x9a, 0x9c, 0x9f, 0xa1, 0xa1, 0xa3, 0xa5, + 0xa7, 0xa7, 0xa6, 0xa6, 0xa5, 0xa4, 0xa2, 0xa0, 0x9e, 0x9c, 0x9a, 0x97, + 0x95, 0x93, 0x92, 0x92, 0x90, 0x90, 0x8f, 0x90, 0x90, 0x8f, 0x90, 0x8f, + 0x8f, 0x8f, 0x8d, 0x89, 0x87, 0x84, 0x83, 0x82, 0x81, 0x80, 0x80, 0x7f, + 0x7e, 0x7d, 0x7f, 0x80, 0x80, 0x7f, 0x7f, 0x80, 0x80, 0x7f, 0x7f, 0x81, + 0x83, 0x83, 0x83, 0x84, 0x86, 0x89, 0x8b, 0x8c, 0x8d, 0x90, 0x93, 0x94, + 0x94, 0x95, 0x95, 0x97, 0x99, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, + 0x9e, 0x9e, 0x9e, 0x9f, 0x9f, 0x9f, 0x9e, 0x9c, 0x9c, 0x9c, 0x9c, 0x9b, + 0x9b, 0x9a, 0x99, 0x99, 0x98, 0x97, 0x96, 0x95, 0x95, 0x95, 0x95, 0x94, + 0x94, 0x93, 0x93, 0x92, 0x91, 0x92, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, + 0x93, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x94, 0x94, 0x93, 0x92, 0x91, + 0x90, 0x90, 0x8f, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8b, 0x8d, 0x8e, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x96, 0x96, + 0x96, 0x95, 0x95, 0x95, 0x96, 0x96, 0x96, 0x95, 0x95, 0x94, 0x95, 0x94, + 0x95, 0x95, 0x96, 0x97, 0x99, 0x9a, 0x99, 0x97, 0x93, 0x8e, 0x8a, 0x86, + 0x7f, 0x75, 0x6c, 0x65, 0x61, 0x5b, 0x58, 0x56, 0x56, 0x56, 0x57, 0x57, + 0x57, 0x59, 0x5a, 0x5a, 0x5d, 0x5e, 0x5e, 0x5d, 0x5c, 0x5c, 0x5d, 0x60, + 0x61, 0x61, 0x60, 0x5f, 0x60, 0x60, 0x60, 0x62, 0x62, 0x61, 0x62, 0x63, + 0x63, 0x66, 0x65, 0x67, 0x68, 0x69, 0x6a, 0x6d, 0x6e, 0x6f, 0x6f, 0x70, + 0x6e, 0x6c, 0x6b, 0x6a, 0x67, 0x62, 0x5d, 0x5a, 0x57, 0x53, 0x4d, 0x49, + 0x46, 0x42, 0x3c, 0x34, 0x2d, 0x28, 0x20, 0x15, 0x11, 0x11, 0x11, 0x10, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x13, 0x13, 0x12, 0x13, 0x11, + 0x12, 0x12, 0x12, 0x14, 0x8f, 0x8a, 0x86, 0x84, 0x80, 0x7c, 0x79, 0x77, + 0x76, 0x74, 0x70, 0x6c, 0x6b, 0x6b, 0x6c, 0x6b, 0x69, 0x68, 0x67, 0x64, + 0x63, 0x63, 0x62, 0x61, 0x60, 0x60, 0x60, 0x5f, 0x5f, 0x5f, 0x60, 0x61, + 0x62, 0x63, 0x67, 0x6d, 0x77, 0x7d, 0x81, 0x85, 0x8b, 0x90, 0x92, 0x94, + 0x98, 0x9b, 0x9b, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x94, 0x93, 0x93, 0x94, + 0x96, 0x98, 0x9a, 0x9e, 0xa0, 0xa1, 0xa3, 0xa5, 0xa7, 0xa8, 0xa6, 0xa6, + 0xa5, 0xa4, 0xa3, 0xa1, 0x9e, 0x9b, 0x99, 0x97, 0x95, 0x93, 0x92, 0x92, + 0x90, 0x90, 0x8f, 0x90, 0x90, 0x91, 0x90, 0x8f, 0x8f, 0x8e, 0x8c, 0x88, + 0x87, 0x85, 0x83, 0x82, 0x82, 0x80, 0x7f, 0x7f, 0x7d, 0x7d, 0x7f, 0x80, + 0x80, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x83, 0x83, 0x83, 0x83, + 0x86, 0x87, 0x8a, 0x8c, 0x8f, 0x92, 0x93, 0x94, 0x95, 0x97, 0x97, 0x99, + 0x9a, 0x9b, 0x9c, 0x9c, 0x9d, 0x9d, 0x9c, 0x9c, 0x9d, 0x9f, 0x9f, 0x9f, + 0x9f, 0x9e, 0x9e, 0x9d, 0x9d, 0x9d, 0x9d, 0x9b, 0x9c, 0x9b, 0x9a, 0x9a, + 0x99, 0x98, 0x96, 0x95, 0x96, 0x95, 0x96, 0x95, 0x94, 0x93, 0x92, 0x93, + 0x93, 0x93, 0x93, 0x92, 0x93, 0x94, 0x95, 0x94, 0x94, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x95, 0x95, 0x94, 0x94, 0x92, 0x92, 0x91, 0x91, 0x8f, + 0x8d, 0x8c, 0x8b, 0x89, 0x8a, 0x89, 0x8a, 0x8c, 0x8c, 0x8d, 0x8f, 0x90, + 0x91, 0x92, 0x93, 0x94, 0x96, 0x96, 0x96, 0x96, 0x96, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x96, 0x95, 0x94, 0x94, 0x94, 0x95, 0x96, 0x97, 0x97, 0x96, + 0x98, 0x98, 0x97, 0x94, 0x90, 0x89, 0x85, 0x81, 0x7a, 0x6f, 0x66, 0x5f, + 0x5c, 0x59, 0x58, 0x56, 0x56, 0x57, 0x58, 0x58, 0x5a, 0x5b, 0x5b, 0x5b, + 0x5d, 0x5f, 0x5e, 0x5e, 0x5e, 0x5f, 0x60, 0x61, 0x61, 0x61, 0x61, 0x5f, + 0x60, 0x61, 0x61, 0x61, 0x61, 0x62, 0x63, 0x63, 0x63, 0x65, 0x65, 0x66, + 0x67, 0x69, 0x6b, 0x6e, 0x6f, 0x70, 0x70, 0x70, 0x6f, 0x6c, 0x6b, 0x6b, + 0x67, 0x63, 0x5f, 0x5d, 0x59, 0x53, 0x4f, 0x4b, 0x48, 0x43, 0x3d, 0x34, + 0x2f, 0x2b, 0x21, 0x16, 0x12, 0x11, 0x10, 0x11, 0x10, 0x12, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x14, 0x15, 0x13, 0x13, 0x11, 0x11, 0x11, 0x13, 0x14, + 0x8e, 0x8a, 0x86, 0x83, 0x7e, 0x7a, 0x77, 0x75, 0x73, 0x71, 0x6e, 0x6a, + 0x69, 0x69, 0x6a, 0x69, 0x67, 0x66, 0x65, 0x63, 0x62, 0x62, 0x62, 0x61, + 0x60, 0x5f, 0x5f, 0x5e, 0x5e, 0x5e, 0x5f, 0x60, 0x61, 0x63, 0x64, 0x69, + 0x72, 0x79, 0x7d, 0x81, 0x88, 0x8d, 0x91, 0x94, 0x97, 0x9a, 0x9b, 0x9b, + 0x9a, 0x9a, 0x99, 0x96, 0x95, 0x94, 0x94, 0x93, 0x95, 0x98, 0x9a, 0x9d, + 0xa0, 0xa2, 0xa4, 0xa6, 0xa7, 0xa8, 0xa7, 0xa8, 0xa7, 0xa6, 0xa4, 0xa2, + 0x9e, 0x9b, 0x99, 0x96, 0x95, 0x93, 0x92, 0x91, 0x91, 0x90, 0x8f, 0x90, + 0x90, 0x91, 0x90, 0x8f, 0x8f, 0x8e, 0x8c, 0x89, 0x86, 0x84, 0x83, 0x82, + 0x81, 0x7f, 0x7f, 0x7f, 0x7d, 0x7d, 0x7e, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, + 0x80, 0x7f, 0x80, 0x81, 0x82, 0x84, 0x84, 0x83, 0x85, 0x86, 0x88, 0x8a, + 0x8e, 0x91, 0x93, 0x94, 0x95, 0x97, 0x97, 0x98, 0x9a, 0x9b, 0x9c, 0x9d, + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9f, 0x9f, 0x9e, 0x9e, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9c, 0x9b, 0x9b, 0x9b, 0x99, 0x98, 0x96, 0x96, + 0x96, 0x95, 0x96, 0x95, 0x95, 0x93, 0x94, 0x95, 0x95, 0x95, 0x95, 0x94, + 0x95, 0x96, 0x96, 0x96, 0x97, 0x97, 0x96, 0x96, 0x97, 0x96, 0x96, 0x95, + 0x95, 0x95, 0x95, 0x94, 0x92, 0x92, 0x91, 0x8f, 0x8f, 0x8d, 0x8c, 0x8a, + 0x8a, 0x89, 0x89, 0x8b, 0x8c, 0x8d, 0x8f, 0x90, 0x91, 0x91, 0x92, 0x93, + 0x96, 0x96, 0x96, 0x95, 0x95, 0x95, 0x96, 0x96, 0x96, 0x96, 0x96, 0x95, + 0x95, 0x94, 0x95, 0x95, 0x96, 0x96, 0x95, 0x96, 0x97, 0x97, 0x96, 0x93, + 0x8d, 0x86, 0x81, 0x7d, 0x75, 0x6b, 0x61, 0x5b, 0x59, 0x57, 0x58, 0x59, + 0x58, 0x58, 0x59, 0x59, 0x5b, 0x5b, 0x5b, 0x5a, 0x5c, 0x5e, 0x5e, 0x5e, + 0x5e, 0x5f, 0x60, 0x60, 0x61, 0x61, 0x61, 0x5f, 0x60, 0x60, 0x5f, 0x60, + 0x61, 0x64, 0x65, 0x65, 0x64, 0x65, 0x66, 0x67, 0x68, 0x6a, 0x6b, 0x6e, + 0x6f, 0x70, 0x70, 0x71, 0x70, 0x6f, 0x6d, 0x6b, 0x68, 0x64, 0x60, 0x5d, + 0x5a, 0x54, 0x50, 0x4d, 0x49, 0x43, 0x3d, 0x34, 0x2f, 0x2b, 0x22, 0x17, + 0x12, 0x11, 0x10, 0x11, 0x10, 0x11, 0x11, 0x11, 0x11, 0x12, 0x11, 0x12, + 0x12, 0x11, 0x12, 0x11, 0x11, 0x11, 0x13, 0x13, 0x8c, 0x88, 0x85, 0x81, + 0x7b, 0x77, 0x74, 0x71, 0x6f, 0x6d, 0x6c, 0x69, 0x68, 0x67, 0x68, 0x67, + 0x65, 0x64, 0x64, 0x63, 0x61, 0x60, 0x60, 0x5f, 0x5f, 0x60, 0x5f, 0x5f, + 0x5f, 0x5f, 0x5f, 0x5f, 0x60, 0x62, 0x64, 0x67, 0x6e, 0x75, 0x78, 0x7d, + 0x85, 0x8a, 0x8e, 0x91, 0x95, 0x97, 0x9a, 0x9a, 0x9a, 0x99, 0x99, 0x96, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x96, 0x98, 0x9b, 0x9e, 0xa2, 0xa4, 0xa4, + 0xa5, 0xa6, 0xa7, 0xa8, 0xa7, 0xa6, 0xa5, 0xa2, 0x9f, 0x9b, 0x99, 0x98, + 0x95, 0x94, 0x91, 0x91, 0x91, 0x90, 0x8f, 0x91, 0x91, 0x90, 0x90, 0x90, + 0x8e, 0x8d, 0x8b, 0x88, 0x86, 0x86, 0x85, 0x83, 0x81, 0x7f, 0x7e, 0x7e, + 0x7d, 0x7e, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x7e, 0x7e, 0x7d, 0x7f, + 0x82, 0x83, 0x83, 0x82, 0x84, 0x87, 0x89, 0x8a, 0x8c, 0x8e, 0x92, 0x94, + 0x96, 0x97, 0x97, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0xa0, 0xa0, 0xa0, + 0x9f, 0x9e, 0xa0, 0x9f, 0x9e, 0x9f, 0x9f, 0x9f, 0x9e, 0x9e, 0x9e, 0x9d, + 0x9b, 0x9b, 0x9b, 0x9b, 0x9a, 0x99, 0x98, 0x98, 0x96, 0x96, 0x95, 0x95, + 0x95, 0x96, 0x96, 0x96, 0x96, 0x96, 0x95, 0x95, 0x95, 0x96, 0x97, 0x97, + 0x97, 0x95, 0x95, 0x96, 0x98, 0x97, 0x98, 0x96, 0x96, 0x97, 0x95, 0x95, + 0x94, 0x94, 0x92, 0x91, 0x90, 0x8f, 0x8e, 0x8c, 0x8a, 0x89, 0x89, 0x8b, + 0x8c, 0x8d, 0x8e, 0x8e, 0x8f, 0x90, 0x92, 0x93, 0x95, 0x95, 0x95, 0x95, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x95, 0x96, 0x96, 0x95, 0x95, 0x95, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x95, 0x93, 0x90, 0x89, 0x82, 0x7d, 0x79, + 0x72, 0x67, 0x5e, 0x58, 0x57, 0x56, 0x57, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, + 0x5b, 0x5c, 0x5c, 0x5c, 0x5c, 0x5e, 0x5f, 0x5f, 0x5f, 0x5e, 0x5f, 0x5f, + 0x60, 0x61, 0x61, 0x60, 0x61, 0x60, 0x60, 0x60, 0x61, 0x64, 0x65, 0x64, + 0x63, 0x64, 0x66, 0x68, 0x68, 0x6a, 0x6b, 0x6e, 0x6f, 0x70, 0x70, 0x71, + 0x71, 0x6f, 0x6e, 0x6a, 0x68, 0x64, 0x61, 0x5e, 0x5b, 0x57, 0x51, 0x4d, + 0x4a, 0x44, 0x3d, 0x35, 0x2f, 0x2b, 0x23, 0x18, 0x12, 0x11, 0x10, 0x11, + 0x11, 0x10, 0x10, 0x11, 0x11, 0x12, 0x11, 0x12, 0x12, 0x12, 0x12, 0x11, + 0x12, 0x12, 0x12, 0x14, 0x8b, 0x87, 0x82, 0x7f, 0x79, 0x75, 0x72, 0x6f, + 0x6e, 0x6b, 0x68, 0x68, 0x66, 0x66, 0x65, 0x64, 0x63, 0x62, 0x61, 0x61, + 0x60, 0x5d, 0x5e, 0x5f, 0x5e, 0x5f, 0x5e, 0x5e, 0x5f, 0x5e, 0x5f, 0x60, + 0x60, 0x61, 0x64, 0x68, 0x6c, 0x70, 0x73, 0x79, 0x81, 0x87, 0x8b, 0x8e, + 0x92, 0x96, 0x98, 0x99, 0x9a, 0x9a, 0x99, 0x98, 0x96, 0x96, 0x95, 0x95, + 0x95, 0x96, 0x97, 0x9a, 0x9d, 0xa1, 0xa3, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa6, 0xa6, 0xa4, 0xa1, 0x9e, 0x9c, 0x99, 0x97, 0x95, 0x94, 0x91, 0x91, + 0x91, 0x90, 0x90, 0x91, 0x91, 0x91, 0x90, 0x90, 0x8e, 0x8d, 0x8b, 0x88, + 0x86, 0x86, 0x85, 0x83, 0x81, 0x7f, 0x7e, 0x7d, 0x7d, 0x7d, 0x7f, 0x81, + 0x80, 0x7f, 0x7f, 0x7f, 0x7e, 0x7d, 0x7e, 0x80, 0x82, 0x82, 0x82, 0x81, + 0x83, 0x87, 0x89, 0x8a, 0x8d, 0x8f, 0x92, 0x94, 0x96, 0x97, 0x97, 0x99, + 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa1, 0xa1, 0xa0, 0x9f, 0x9f, 0xa0, 0x9f, + 0x9e, 0x9e, 0x9f, 0x9f, 0x9e, 0x9f, 0x9f, 0x9d, 0x9b, 0x9c, 0x9c, 0x9b, + 0x9a, 0x99, 0x98, 0x98, 0x97, 0x97, 0x96, 0x96, 0x96, 0x97, 0x97, 0x95, + 0x96, 0x96, 0x95, 0x95, 0x95, 0x96, 0x97, 0x97, 0x97, 0x96, 0x97, 0x98, + 0x98, 0x98, 0x99, 0x98, 0x97, 0x98, 0x96, 0x96, 0x95, 0x95, 0x94, 0x92, + 0x91, 0x90, 0x8e, 0x8c, 0x8c, 0x8b, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8e, + 0x8f, 0x90, 0x92, 0x92, 0x94, 0x95, 0x95, 0x95, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x96, 0x96, 0x96, 0x96, + 0x95, 0x93, 0x91, 0x8d, 0x85, 0x7e, 0x7a, 0x76, 0x6f, 0x64, 0x5c, 0x58, + 0x57, 0x58, 0x57, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c, 0x5c, + 0x5b, 0x5e, 0x5f, 0x5f, 0x5d, 0x5d, 0x5d, 0x5d, 0x5f, 0x60, 0x61, 0x60, + 0x61, 0x61, 0x61, 0x62, 0x62, 0x63, 0x64, 0x64, 0x62, 0x64, 0x66, 0x68, + 0x68, 0x6a, 0x6b, 0x6e, 0x6f, 0x70, 0x70, 0x71, 0x71, 0x70, 0x6f, 0x6b, + 0x68, 0x63, 0x61, 0x5f, 0x5c, 0x57, 0x51, 0x4e, 0x4b, 0x46, 0x3e, 0x36, + 0x31, 0x2c, 0x23, 0x1a, 0x13, 0x11, 0x10, 0x11, 0x11, 0x10, 0x10, 0x11, + 0x11, 0x12, 0x12, 0x11, 0x12, 0x13, 0x13, 0x11, 0x12, 0x12, 0x11, 0x13, + 0x8b, 0x85, 0x81, 0x7e, 0x78, 0x74, 0x71, 0x6e, 0x6c, 0x6a, 0x67, 0x66, + 0x65, 0x64, 0x64, 0x62, 0x61, 0x60, 0x60, 0x60, 0x5f, 0x5c, 0x5d, 0x5e, + 0x5d, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5f, 0x60, 0x61, 0x61, 0x63, 0x67, + 0x6b, 0x6e, 0x71, 0x76, 0x7e, 0x85, 0x89, 0x8c, 0x90, 0x95, 0x96, 0x98, + 0x99, 0x9a, 0x99, 0x98, 0x97, 0x96, 0x94, 0x95, 0x94, 0x95, 0x96, 0x99, + 0x9c, 0xa1, 0xa2, 0xa3, 0xa3, 0xa5, 0xa5, 0xa6, 0xa6, 0xa5, 0xa4, 0xa1, + 0x9e, 0x9b, 0x99, 0x97, 0x95, 0x94, 0x92, 0x91, 0x91, 0x90, 0x8f, 0x91, + 0x91, 0x91, 0x90, 0x90, 0x8e, 0x8c, 0x8b, 0x88, 0x86, 0x85, 0x85, 0x83, + 0x81, 0x80, 0x7e, 0x7e, 0x7d, 0x7e, 0x80, 0x81, 0x81, 0x7f, 0x80, 0x80, + 0x7e, 0x7e, 0x7e, 0x80, 0x81, 0x81, 0x81, 0x81, 0x83, 0x87, 0x89, 0x8a, + 0x8d, 0x8f, 0x92, 0x95, 0x95, 0x96, 0x97, 0x9a, 0x9c, 0x9d, 0x9d, 0x9f, + 0x9f, 0xa1, 0xa1, 0xa1, 0xa0, 0xa0, 0xa1, 0x9f, 0x9e, 0x9e, 0x9f, 0x9f, + 0x9e, 0x9e, 0x9e, 0x9d, 0x9c, 0x9c, 0x9c, 0x9b, 0x99, 0x9a, 0x99, 0x99, + 0x98, 0x97, 0x97, 0x96, 0x96, 0x97, 0x97, 0x95, 0x95, 0x95, 0x96, 0x95, + 0x96, 0x96, 0x96, 0x98, 0x97, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x99, + 0x98, 0x98, 0x97, 0x97, 0x95, 0x94, 0x94, 0x93, 0x92, 0x90, 0x8f, 0x8d, + 0x8c, 0x8c, 0x8b, 0x8b, 0x8c, 0x8d, 0x8e, 0x8e, 0x8f, 0x90, 0x91, 0x91, + 0x94, 0x96, 0x96, 0x95, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x96, 0x96, 0x96, 0x96, 0x94, 0x92, 0x90, 0x8b, + 0x83, 0x7c, 0x77, 0x74, 0x6d, 0x62, 0x5a, 0x57, 0x58, 0x58, 0x57, 0x5a, + 0x5b, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c, 0x5c, 0x5b, 0x5d, 0x5e, 0x5e, + 0x5d, 0x5d, 0x5c, 0x5d, 0x5f, 0x5f, 0x60, 0x60, 0x61, 0x61, 0x61, 0x62, + 0x63, 0x63, 0x64, 0x64, 0x63, 0x64, 0x67, 0x67, 0x68, 0x6a, 0x6a, 0x6d, + 0x6f, 0x70, 0x70, 0x71, 0x71, 0x70, 0x6f, 0x6c, 0x68, 0x63, 0x60, 0x5f, + 0x5c, 0x58, 0x52, 0x4f, 0x4b, 0x46, 0x3e, 0x36, 0x31, 0x2b, 0x23, 0x1a, + 0x14, 0x11, 0x10, 0x11, 0x11, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x12, 0x13, 0x13, 0x11, 0x12, 0x12, 0x11, 0x13, 0x8a, 0x83, 0x7e, 0x7b, + 0x77, 0x72, 0x6e, 0x6b, 0x69, 0x66, 0x64, 0x64, 0x63, 0x62, 0x60, 0x5f, + 0x5f, 0x5e, 0x5d, 0x5e, 0x5d, 0x5b, 0x5c, 0x5c, 0x5d, 0x5d, 0x5d, 0x5d, + 0x5d, 0x5e, 0x5f, 0x60, 0x60, 0x61, 0x63, 0x66, 0x68, 0x6c, 0x6e, 0x73, + 0x7b, 0x82, 0x87, 0x8b, 0x8f, 0x92, 0x95, 0x97, 0x99, 0x9a, 0x99, 0x99, + 0x96, 0x95, 0x94, 0x95, 0x95, 0x95, 0x95, 0x97, 0x9a, 0x9e, 0xa0, 0xa1, + 0xa3, 0xa5, 0xa6, 0xa6, 0xa5, 0xa5, 0xa4, 0xa2, 0x9e, 0x9a, 0x99, 0x96, + 0x95, 0x94, 0x92, 0x92, 0x90, 0x90, 0x8f, 0x90, 0x91, 0x91, 0x90, 0x8e, + 0x8d, 0x8c, 0x8b, 0x88, 0x85, 0x85, 0x84, 0x82, 0x7f, 0x7f, 0x7e, 0x7e, + 0x7d, 0x7f, 0x80, 0x81, 0x81, 0x80, 0x80, 0x80, 0x7f, 0x7e, 0x7e, 0x7e, + 0x80, 0x81, 0x81, 0x81, 0x83, 0x86, 0x88, 0x89, 0x8c, 0x8f, 0x93, 0x95, + 0x95, 0x95, 0x97, 0x9a, 0x9c, 0x9d, 0x9d, 0x9e, 0x9f, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa1, 0xa1, 0x9f, 0x9e, 0x9e, 0x9e, 0x9e, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9d, 0x9c, 0x9c, 0x9a, 0x99, 0x9b, 0x9a, 0x9a, 0x98, 0x97, 0x96, 0x96, + 0x96, 0x97, 0x97, 0x96, 0x96, 0x96, 0x96, 0x96, 0x97, 0x97, 0x96, 0x98, + 0x98, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x99, 0x9a, 0x9a, 0x99, 0x97, 0x97, + 0x96, 0x95, 0x95, 0x94, 0x92, 0x8f, 0x8e, 0x8e, 0x8c, 0x8b, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8e, 0x8f, 0x8f, 0x90, 0x91, 0x91, 0x94, 0x94, 0x95, 0x96, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x95, 0x96, 0x96, 0x96, 0x95, 0x95, + 0x95, 0x96, 0x96, 0x95, 0x93, 0x90, 0x8e, 0x89, 0x81, 0x7a, 0x75, 0x70, + 0x69, 0x60, 0x59, 0x57, 0x58, 0x58, 0x58, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, + 0x5b, 0x5b, 0x5c, 0x5c, 0x5b, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5d, + 0x5d, 0x5e, 0x5f, 0x5e, 0x60, 0x60, 0x61, 0x62, 0x63, 0x63, 0x63, 0x63, + 0x64, 0x65, 0x66, 0x66, 0x67, 0x68, 0x6a, 0x6c, 0x6e, 0x6e, 0x6f, 0x71, + 0x71, 0x70, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x5e, 0x5c, 0x56, 0x52, 0x4e, + 0x4b, 0x46, 0x3f, 0x37, 0x30, 0x2b, 0x23, 0x1a, 0x14, 0x11, 0x11, 0x10, + 0x11, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x12, 0x11, 0x11, 0x11, + 0x11, 0x12, 0x12, 0x13, 0x86, 0x7f, 0x7a, 0x78, 0x73, 0x6e, 0x6a, 0x67, + 0x66, 0x64, 0x62, 0x61, 0x61, 0x60, 0x5e, 0x5e, 0x5d, 0x5c, 0x5c, 0x5c, + 0x5b, 0x5b, 0x5b, 0x5c, 0x5d, 0x5e, 0x5e, 0x5d, 0x5d, 0x5e, 0x5e, 0x60, + 0x61, 0x60, 0x62, 0x66, 0x68, 0x69, 0x6b, 0x6f, 0x77, 0x7e, 0x83, 0x86, + 0x8b, 0x90, 0x93, 0x95, 0x97, 0x98, 0x98, 0x99, 0x97, 0x95, 0x94, 0x95, + 0x95, 0x95, 0x95, 0x97, 0x99, 0x9d, 0x9f, 0xa0, 0xa2, 0xa3, 0xa5, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa1, 0x9e, 0x9a, 0x99, 0x97, 0x97, 0x96, 0x94, 0x93, + 0x91, 0x90, 0x8f, 0x90, 0x90, 0x8f, 0x8f, 0x8c, 0x8b, 0x8b, 0x8a, 0x88, + 0x86, 0x85, 0x84, 0x82, 0x7f, 0x7f, 0x7e, 0x7e, 0x7e, 0x80, 0x81, 0x81, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7e, 0x7f, 0x80, 0x80, 0x80, + 0x82, 0x85, 0x87, 0x88, 0x8a, 0x8f, 0x92, 0x94, 0x95, 0x95, 0x97, 0x9a, + 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa2, 0xa2, 0xa2, 0xa2, 0xa3, 0xa2, 0xa0, + 0x9f, 0x9f, 0x9e, 0x9e, 0x9d, 0x9c, 0x9d, 0x9d, 0x9d, 0x9c, 0x9b, 0x9a, + 0x9b, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x98, 0x98, 0x97, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x97, 0x96, 0x95, 0x96, 0x98, 0x9a, 0x9a, 0x9a, + 0x99, 0x99, 0x9a, 0x9b, 0x9c, 0x9a, 0x98, 0x98, 0x97, 0x97, 0x96, 0x93, + 0x92, 0x90, 0x8f, 0x8f, 0x8e, 0x8c, 0x8d, 0x8d, 0x8d, 0x8d, 0x8f, 0x8f, + 0x8f, 0x90, 0x91, 0x91, 0x93, 0x94, 0x95, 0x97, 0x97, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x97, 0x96, 0x96, 0x96, 0x95, 0x95, 0x96, 0x96, 0x96, 0x94, + 0x91, 0x8e, 0x8c, 0x87, 0x7d, 0x75, 0x70, 0x6b, 0x65, 0x5d, 0x59, 0x57, + 0x58, 0x59, 0x59, 0x5a, 0x5b, 0x5b, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, + 0x5c, 0x5c, 0x5b, 0x5b, 0x5b, 0x5b, 0x5c, 0x5c, 0x5c, 0x5d, 0x5e, 0x5e, + 0x60, 0x61, 0x61, 0x61, 0x62, 0x63, 0x62, 0x63, 0x64, 0x65, 0x64, 0x65, + 0x66, 0x68, 0x6a, 0x6b, 0x6d, 0x6e, 0x6e, 0x70, 0x70, 0x6f, 0x6e, 0x6b, + 0x69, 0x65, 0x62, 0x61, 0x5d, 0x56, 0x52, 0x4f, 0x4c, 0x47, 0x40, 0x38, + 0x32, 0x2c, 0x24, 0x1a, 0x13, 0x11, 0x10, 0x11, 0x12, 0x10, 0x10, 0x10, + 0x10, 0x11, 0x11, 0x11, 0x12, 0x11, 0x12, 0x11, 0x11, 0x11, 0x12, 0x11, + 0x82, 0x7b, 0x76, 0x74, 0x71, 0x6b, 0x67, 0x64, 0x63, 0x61, 0x5e, 0x5d, + 0x5f, 0x5f, 0x5d, 0x5d, 0x5c, 0x5b, 0x5b, 0x5a, 0x5a, 0x5a, 0x5a, 0x5b, + 0x5d, 0x5f, 0x5f, 0x5d, 0x5d, 0x5d, 0x5d, 0x5f, 0x60, 0x61, 0x61, 0x64, + 0x67, 0x68, 0x69, 0x6c, 0x72, 0x79, 0x80, 0x83, 0x88, 0x8d, 0x91, 0x92, + 0x94, 0x96, 0x98, 0x98, 0x98, 0x97, 0x96, 0x95, 0x95, 0x95, 0x95, 0x96, + 0x98, 0x9b, 0x9e, 0x9f, 0xa0, 0xa3, 0xa4, 0xa4, 0xa3, 0xa3, 0xa2, 0xa0, + 0x9e, 0x9b, 0x9a, 0x9a, 0x98, 0x97, 0x94, 0x93, 0x92, 0x90, 0x8f, 0x90, + 0x8f, 0x8e, 0x8d, 0x8c, 0x8a, 0x8a, 0x89, 0x87, 0x86, 0x85, 0x84, 0x82, + 0x7f, 0x7f, 0x7e, 0x7e, 0x7e, 0x80, 0x81, 0x81, 0x80, 0x80, 0x81, 0x81, + 0x80, 0x80, 0x7f, 0x7e, 0x7e, 0x7f, 0x7f, 0x80, 0x82, 0x84, 0x85, 0x86, + 0x89, 0x8e, 0x91, 0x93, 0x94, 0x95, 0x97, 0x9a, 0x9d, 0x9e, 0x9f, 0xa1, + 0xa2, 0xa3, 0xa3, 0xa3, 0xa2, 0xa3, 0xa2, 0xa0, 0x9f, 0x9f, 0x9e, 0x9e, + 0x9d, 0x9d, 0x9d, 0x9c, 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x96, 0x95, + 0x94, 0x94, 0x94, 0x95, 0x95, 0x96, 0x95, 0x96, 0x97, 0x97, 0x96, 0x96, + 0x97, 0x96, 0x96, 0x96, 0x98, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9c, 0x9c, + 0x9c, 0x9b, 0x9b, 0x99, 0x98, 0x97, 0x96, 0x94, 0x92, 0x91, 0x90, 0x90, + 0x8f, 0x8e, 0x8c, 0x8d, 0x8d, 0x8d, 0x8f, 0x8f, 0x90, 0x90, 0x91, 0x91, + 0x93, 0x94, 0x95, 0x96, 0x95, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x95, + 0x95, 0x95, 0x97, 0x97, 0x96, 0x96, 0x95, 0x93, 0x90, 0x8c, 0x89, 0x83, + 0x79, 0x70, 0x6a, 0x66, 0x62, 0x5c, 0x58, 0x57, 0x57, 0x58, 0x59, 0x5a, + 0x5b, 0x5b, 0x5b, 0x59, 0x5a, 0x5b, 0x5b, 0x5a, 0x5c, 0x5b, 0x5c, 0x5c, + 0x5b, 0x5b, 0x5c, 0x5c, 0x5d, 0x5e, 0x5e, 0x5e, 0x61, 0x61, 0x61, 0x61, + 0x63, 0x63, 0x62, 0x63, 0x64, 0x65, 0x64, 0x65, 0x66, 0x67, 0x6a, 0x6b, + 0x6d, 0x6e, 0x6e, 0x70, 0x71, 0x70, 0x6f, 0x6c, 0x6a, 0x66, 0x63, 0x62, + 0x5e, 0x58, 0x53, 0x50, 0x4d, 0x48, 0x40, 0x39, 0x33, 0x2f, 0x26, 0x1a, + 0x13, 0x11, 0x10, 0x10, 0x11, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, + 0x12, 0x13, 0x13, 0x11, 0x12, 0x12, 0x13, 0x11, 0x81, 0x79, 0x74, 0x71, + 0x6d, 0x66, 0x63, 0x62, 0x61, 0x5f, 0x5c, 0x5c, 0x5d, 0x5d, 0x5c, 0x5a, + 0x5a, 0x59, 0x59, 0x5a, 0x5a, 0x59, 0x58, 0x59, 0x5c, 0x5f, 0x5f, 0x5e, + 0x5d, 0x5d, 0x5c, 0x5e, 0x60, 0x61, 0x62, 0x63, 0x67, 0x69, 0x6a, 0x6c, + 0x70, 0x76, 0x7c, 0x7f, 0x84, 0x8a, 0x8e, 0x90, 0x92, 0x94, 0x97, 0x98, + 0x98, 0x98, 0x96, 0x96, 0x95, 0x94, 0x94, 0x95, 0x97, 0x9b, 0x9d, 0x9e, + 0xa0, 0xa1, 0xa4, 0xa4, 0xa4, 0xa3, 0xa2, 0xa0, 0x9d, 0x9c, 0x9b, 0x9a, + 0x98, 0x97, 0x95, 0x94, 0x92, 0x91, 0x90, 0x8f, 0x8e, 0x8e, 0x8d, 0x8c, + 0x8a, 0x89, 0x87, 0x87, 0x85, 0x84, 0x83, 0x81, 0x80, 0x7f, 0x7e, 0x7e, + 0x7f, 0x7f, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80, 0x81, 0x81, 0x7f, 0x7f, + 0x7d, 0x7e, 0x7e, 0x7f, 0x81, 0x82, 0x84, 0x85, 0x88, 0x8c, 0x90, 0x92, + 0x93, 0x94, 0x98, 0x9c, 0x9e, 0x9e, 0x9f, 0xa1, 0xa2, 0xa2, 0xa2, 0xa3, + 0xa2, 0xa3, 0xa2, 0xa0, 0x9f, 0x9f, 0x9d, 0x9d, 0x9e, 0x9e, 0x9d, 0x9d, + 0x9c, 0x9b, 0x9a, 0x97, 0x95, 0x90, 0x8e, 0x8d, 0x8d, 0x8c, 0x8c, 0x8c, + 0x8d, 0x8f, 0x92, 0x94, 0x96, 0x97, 0x97, 0x98, 0x97, 0x96, 0x96, 0x98, + 0x99, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9a, + 0x98, 0x97, 0x95, 0x94, 0x93, 0x92, 0x92, 0x90, 0x8f, 0x8e, 0x8c, 0x8c, + 0x8c, 0x8e, 0x8e, 0x90, 0x90, 0x91, 0x91, 0x93, 0x94, 0x95, 0x95, 0x96, + 0x96, 0x98, 0x98, 0x98, 0x98, 0x98, 0x97, 0x95, 0x95, 0x95, 0x97, 0x98, + 0x97, 0x97, 0x95, 0x91, 0x8d, 0x89, 0x86, 0x81, 0x78, 0x6e, 0x67, 0x63, + 0x5f, 0x5a, 0x57, 0x56, 0x57, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, + 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5c, 0x5c, + 0x5d, 0x5d, 0x5e, 0x5e, 0x61, 0x61, 0x61, 0x61, 0x62, 0x62, 0x62, 0x63, + 0x65, 0x65, 0x64, 0x65, 0x66, 0x67, 0x69, 0x6c, 0x6e, 0x6e, 0x6e, 0x70, + 0x71, 0x70, 0x6f, 0x6c, 0x6a, 0x66, 0x63, 0x61, 0x5e, 0x59, 0x54, 0x50, + 0x4e, 0x48, 0x3f, 0x38, 0x33, 0x30, 0x27, 0x1b, 0x13, 0x11, 0x10, 0x10, + 0x11, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x13, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x13, 0x80, 0x77, 0x72, 0x6f, 0x6a, 0x62, 0x60, 0x60, + 0x5f, 0x5d, 0x5b, 0x5a, 0x5b, 0x5b, 0x5b, 0x5a, 0x59, 0x59, 0x59, 0x5a, + 0x5a, 0x58, 0x57, 0x58, 0x5b, 0x5e, 0x5e, 0x5e, 0x5d, 0x5d, 0x5d, 0x5f, + 0x5f, 0x60, 0x62, 0x64, 0x67, 0x68, 0x69, 0x6b, 0x6e, 0x74, 0x79, 0x7c, + 0x81, 0x87, 0x8c, 0x8e, 0x90, 0x92, 0x95, 0x97, 0x98, 0x97, 0x96, 0x96, + 0x95, 0x94, 0x94, 0x95, 0x97, 0x9a, 0x9b, 0x9c, 0x9e, 0xa0, 0xa2, 0xa3, + 0xa3, 0xa3, 0xa2, 0xa0, 0x9d, 0x9c, 0x9b, 0x9a, 0x98, 0x97, 0x95, 0x94, + 0x92, 0x91, 0x90, 0x8e, 0x8e, 0x8e, 0x8d, 0x8c, 0x8b, 0x89, 0x87, 0x86, + 0x85, 0x84, 0x82, 0x81, 0x80, 0x7f, 0x7e, 0x7e, 0x7f, 0x7f, 0x80, 0x81, + 0x81, 0x82, 0x81, 0x80, 0x81, 0x80, 0x7f, 0x7f, 0x7e, 0x7e, 0x7e, 0x7e, + 0x81, 0x82, 0x84, 0x85, 0x88, 0x8c, 0x8f, 0x92, 0x93, 0x94, 0x98, 0x9c, + 0x9e, 0x9f, 0x9f, 0xa1, 0xa2, 0xa1, 0xa2, 0xa3, 0xa2, 0xa3, 0xa2, 0xa0, + 0x9f, 0x9f, 0x9d, 0x9d, 0x9e, 0x9e, 0x9c, 0x9b, 0x98, 0x97, 0x96, 0x92, + 0x8e, 0x88, 0x85, 0x84, 0x83, 0x82, 0x82, 0x83, 0x84, 0x87, 0x8b, 0x90, + 0x93, 0x95, 0x97, 0x98, 0x98, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9d, 0x9c, 0x9b, 0x9c, 0x9c, 0x9c, 0x9a, 0x99, 0x97, 0x95, 0x94, + 0x94, 0x93, 0x92, 0x90, 0x90, 0x8e, 0x8c, 0x8c, 0x8c, 0x8e, 0x8e, 0x90, + 0x91, 0x90, 0x90, 0x93, 0x94, 0x95, 0x95, 0x96, 0x96, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x97, 0x95, 0x95, 0x95, 0x97, 0x98, 0x97, 0x96, 0x94, 0x90, + 0x8c, 0x87, 0x84, 0x7f, 0x76, 0x6c, 0x65, 0x61, 0x5d, 0x59, 0x56, 0x56, + 0x57, 0x59, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5c, 0x5c, 0x5c, 0x5b, + 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b, 0x5d, 0x5d, 0x5e, 0x5e, + 0x61, 0x61, 0x61, 0x61, 0x62, 0x61, 0x62, 0x63, 0x65, 0x65, 0x65, 0x66, + 0x67, 0x68, 0x69, 0x6c, 0x6e, 0x6e, 0x6e, 0x70, 0x71, 0x70, 0x6f, 0x6d, + 0x6b, 0x66, 0x62, 0x60, 0x5e, 0x59, 0x54, 0x51, 0x4e, 0x48, 0x40, 0x39, + 0x34, 0x30, 0x28, 0x1c, 0x13, 0x11, 0x11, 0x10, 0x11, 0x10, 0x10, 0x11, + 0x11, 0x11, 0x11, 0x12, 0x12, 0x13, 0x12, 0x12, 0x12, 0x12, 0x12, 0x14, + 0x7b, 0x74, 0x6e, 0x6b, 0x65, 0x5f, 0x5d, 0x5d, 0x5d, 0x5b, 0x59, 0x59, + 0x58, 0x58, 0x58, 0x57, 0x57, 0x57, 0x58, 0x59, 0x5a, 0x58, 0x58, 0x59, + 0x5c, 0x5e, 0x5e, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x60, 0x61, 0x64, 0x65, + 0x66, 0x67, 0x68, 0x6a, 0x6d, 0x70, 0x74, 0x77, 0x7e, 0x84, 0x89, 0x8b, + 0x8e, 0x91, 0x93, 0x95, 0x95, 0x96, 0x97, 0x97, 0x95, 0x94, 0x95, 0x95, + 0x96, 0x98, 0x9a, 0x9a, 0x9c, 0x9e, 0xa0, 0xa0, 0xa2, 0xa2, 0xa1, 0x9f, + 0x9d, 0x9c, 0x9b, 0x9a, 0x98, 0x97, 0x95, 0x94, 0x92, 0x91, 0x91, 0x8e, + 0x8e, 0x8d, 0x8d, 0x8c, 0x89, 0x89, 0x88, 0x87, 0x85, 0x84, 0x82, 0x81, + 0x80, 0x7f, 0x7e, 0x7e, 0x7f, 0x7f, 0x80, 0x81, 0x81, 0x82, 0x81, 0x80, + 0x81, 0x80, 0x7f, 0x7f, 0x7d, 0x7d, 0x7d, 0x7e, 0x80, 0x83, 0x84, 0x86, + 0x88, 0x8b, 0x8f, 0x92, 0x93, 0x94, 0x97, 0x9c, 0x9d, 0xa0, 0xa1, 0xa2, + 0xa2, 0xa2, 0xa3, 0xa3, 0xa2, 0xa2, 0xa1, 0x9f, 0x9f, 0x9f, 0x9e, 0x9c, + 0x9c, 0x9b, 0x98, 0x93, 0x8f, 0x8c, 0x89, 0x84, 0x80, 0x79, 0x74, 0x72, + 0x6f, 0x6f, 0x71, 0x71, 0x73, 0x75, 0x7b, 0x83, 0x88, 0x8c, 0x92, 0x96, + 0x98, 0x99, 0x99, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9d, 0x9c, 0x9c, + 0x9b, 0x9c, 0x9c, 0x9a, 0x99, 0x98, 0x97, 0x96, 0x95, 0x94, 0x93, 0x91, + 0x90, 0x8f, 0x8c, 0x8c, 0x8c, 0x8d, 0x8e, 0x90, 0x91, 0x90, 0x90, 0x93, + 0x94, 0x95, 0x95, 0x96, 0x96, 0x98, 0x98, 0x98, 0x98, 0x98, 0x97, 0x96, + 0x95, 0x95, 0x97, 0x98, 0x97, 0x95, 0x92, 0x8f, 0x8a, 0x85, 0x82, 0x7c, + 0x73, 0x68, 0x63, 0x5f, 0x5b, 0x58, 0x57, 0x57, 0x58, 0x59, 0x5a, 0x5a, + 0x5a, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5a, 0x5b, 0x5b, 0x5b, 0x5b, + 0x5a, 0x5b, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x5e, 0x60, 0x61, 0x61, 0x61, + 0x62, 0x61, 0x62, 0x63, 0x66, 0x67, 0x66, 0x67, 0x67, 0x6a, 0x6b, 0x6b, + 0x6d, 0x6e, 0x6e, 0x70, 0x71, 0x70, 0x6f, 0x6d, 0x6b, 0x66, 0x63, 0x61, + 0x5f, 0x5a, 0x55, 0x52, 0x4f, 0x48, 0x42, 0x3a, 0x35, 0x31, 0x28, 0x1c, + 0x13, 0x12, 0x11, 0x10, 0x11, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x12, 0x13, 0x11, 0x11, 0x12, 0x12, 0x12, 0x14, 0x75, 0x6d, 0x68, 0x64, + 0x61, 0x5d, 0x5b, 0x5c, 0x5b, 0x58, 0x57, 0x56, 0x56, 0x56, 0x56, 0x56, + 0x56, 0x57, 0x58, 0x58, 0x5a, 0x5a, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x61, 0x62, 0x63, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6c, 0x6d, 0x70, 0x73, 0x79, 0x81, 0x86, 0x89, 0x8b, 0x8e, 0x91, 0x93, + 0x94, 0x95, 0x95, 0x96, 0x95, 0x95, 0x95, 0x95, 0x95, 0x96, 0x97, 0x98, + 0x9a, 0x9c, 0x9e, 0xa0, 0x9f, 0x9f, 0x9e, 0x9e, 0x9d, 0x9c, 0x9c, 0x9b, + 0x9a, 0x97, 0x96, 0x95, 0x93, 0x91, 0x90, 0x8e, 0x8d, 0x8d, 0x8c, 0x8a, + 0x89, 0x88, 0x88, 0x87, 0x85, 0x83, 0x81, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x81, 0x81, 0x81, 0x82, 0x82, 0x83, 0x83, 0x82, 0x81, 0x81, 0x80, 0x7e, + 0x7c, 0x7c, 0x7d, 0x7d, 0x80, 0x83, 0x84, 0x85, 0x87, 0x8b, 0x90, 0x92, + 0x93, 0x95, 0x99, 0x9c, 0x9e, 0xa0, 0xa2, 0xa3, 0xa2, 0xa2, 0xa3, 0xa3, + 0xa3, 0xa2, 0xa1, 0xa0, 0xa0, 0x9f, 0x9d, 0x9a, 0x96, 0x93, 0x8c, 0x82, + 0x7a, 0x74, 0x71, 0x6c, 0x67, 0x62, 0x5f, 0x5d, 0x5b, 0x5c, 0x5e, 0x60, + 0x60, 0x63, 0x68, 0x6f, 0x76, 0x7a, 0x82, 0x8d, 0x96, 0x99, 0x9a, 0x9b, + 0x9b, 0x9a, 0x9a, 0x9b, 0x9b, 0x9d, 0x9c, 0x9c, 0x9c, 0x9c, 0x9b, 0x9a, + 0x9a, 0x99, 0x99, 0x98, 0x96, 0x95, 0x93, 0x93, 0x91, 0x90, 0x8d, 0x8c, + 0x8c, 0x8d, 0x8d, 0x8f, 0x90, 0x91, 0x92, 0x92, 0x94, 0x94, 0x95, 0x96, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x96, 0x96, 0x96, 0x97, 0x97, + 0x97, 0x95, 0x92, 0x8e, 0x88, 0x83, 0x7f, 0x79, 0x6f, 0x66, 0x60, 0x5d, + 0x5a, 0x58, 0x58, 0x59, 0x59, 0x59, 0x59, 0x5a, 0x5a, 0x59, 0x58, 0x58, + 0x59, 0x5a, 0x5b, 0x5a, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5a, 0x5a, 0x5b, + 0x5d, 0x5e, 0x5f, 0x5f, 0x60, 0x61, 0x61, 0x61, 0x62, 0x63, 0x64, 0x64, + 0x65, 0x68, 0x69, 0x68, 0x68, 0x6a, 0x6b, 0x6b, 0x6c, 0x6d, 0x6f, 0x70, + 0x70, 0x70, 0x6f, 0x6d, 0x6b, 0x67, 0x64, 0x62, 0x60, 0x5b, 0x56, 0x53, + 0x50, 0x4a, 0x43, 0x3c, 0x37, 0x33, 0x2a, 0x1d, 0x14, 0x12, 0x12, 0x12, + 0x12, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x13, 0x13, 0x13, 0x13, 0x12, + 0x12, 0x12, 0x12, 0x14, 0x6e, 0x65, 0x5f, 0x5c, 0x5a, 0x59, 0x58, 0x59, + 0x59, 0x56, 0x55, 0x55, 0x54, 0x54, 0x55, 0x55, 0x56, 0x57, 0x57, 0x58, + 0x5a, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x60, 0x60, 0x61, 0x61, + 0x62, 0x63, 0x63, 0x65, 0x67, 0x68, 0x69, 0x69, 0x6c, 0x6d, 0x6e, 0x70, + 0x76, 0x7c, 0x81, 0x85, 0x88, 0x8b, 0x8e, 0x91, 0x92, 0x92, 0x92, 0x94, + 0x94, 0x94, 0x95, 0x95, 0x94, 0x94, 0x96, 0x96, 0x98, 0x9b, 0x9c, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9d, 0x9d, 0x9b, 0x9a, 0x9b, 0x99, 0x98, 0x97, 0x96, + 0x94, 0x92, 0x90, 0x8f, 0x8e, 0x8d, 0x8c, 0x89, 0x88, 0x88, 0x88, 0x86, + 0x84, 0x82, 0x80, 0x7f, 0x7e, 0x7f, 0x7f, 0x80, 0x82, 0x82, 0x82, 0x83, + 0x84, 0x84, 0x84, 0x82, 0x81, 0x81, 0x80, 0x7d, 0x7c, 0x7c, 0x7c, 0x7d, + 0x80, 0x82, 0x83, 0x84, 0x87, 0x8b, 0x8f, 0x92, 0x93, 0x96, 0x9a, 0x9d, + 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa2, 0xa3, 0xa1, 0xa0, + 0x9f, 0x9c, 0x97, 0x90, 0x88, 0x82, 0x77, 0x69, 0x61, 0x5d, 0x5a, 0x58, + 0x58, 0x57, 0x57, 0x57, 0x58, 0x5b, 0x60, 0x62, 0x61, 0x60, 0x61, 0x64, + 0x68, 0x6b, 0x73, 0x7f, 0x8b, 0x91, 0x94, 0x97, 0x9b, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9b, 0x9d, 0x9c, 0x9d, 0x9c, 0x9b, 0x99, 0x99, 0x99, 0x99, 0x97, + 0x95, 0x94, 0x94, 0x93, 0x92, 0x92, 0x90, 0x8e, 0x8e, 0x8f, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x92, 0x94, 0x95, 0x94, 0x94, 0x96, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x97, 0x98, 0x98, 0x98, 0x96, 0x97, 0x96, 0x95, 0x91, 0x8c, + 0x86, 0x7f, 0x7b, 0x75, 0x6c, 0x64, 0x5d, 0x5b, 0x58, 0x56, 0x57, 0x59, + 0x59, 0x58, 0x58, 0x58, 0x58, 0x58, 0x57, 0x57, 0x58, 0x59, 0x5a, 0x5b, + 0x5a, 0x5a, 0x5b, 0x5a, 0x5a, 0x5b, 0x5a, 0x5b, 0x5d, 0x5e, 0x5f, 0x5e, + 0x5f, 0x5f, 0x5f, 0x60, 0x63, 0x64, 0x65, 0x65, 0x67, 0x68, 0x69, 0x69, + 0x69, 0x6a, 0x69, 0x6a, 0x6c, 0x6e, 0x6f, 0x71, 0x70, 0x70, 0x70, 0x6d, + 0x6b, 0x67, 0x64, 0x62, 0x5f, 0x5a, 0x57, 0x52, 0x4f, 0x4a, 0x44, 0x3f, + 0x38, 0x33, 0x2a, 0x1e, 0x14, 0x12, 0x11, 0x12, 0x10, 0x11, 0x10, 0x11, + 0x11, 0x11, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x12, 0x12, 0x12, 0x14, + 0x68, 0x61, 0x5b, 0x58, 0x57, 0x57, 0x56, 0x57, 0x56, 0x55, 0x55, 0x54, + 0x53, 0x54, 0x55, 0x56, 0x57, 0x57, 0x56, 0x58, 0x5a, 0x5a, 0x5c, 0x5c, + 0x5d, 0x5e, 0x5f, 0x60, 0x60, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, + 0x67, 0x69, 0x69, 0x6a, 0x6b, 0x6d, 0x6d, 0x6e, 0x72, 0x78, 0x7e, 0x83, + 0x86, 0x89, 0x8c, 0x8d, 0x8e, 0x8f, 0x91, 0x92, 0x93, 0x95, 0x95, 0x96, + 0x95, 0x94, 0x95, 0x95, 0x97, 0x98, 0x99, 0x9c, 0x9d, 0x9d, 0x9d, 0x9c, + 0x9c, 0x9b, 0x9b, 0x9b, 0x98, 0x96, 0x96, 0x96, 0x94, 0x91, 0x90, 0x8f, + 0x8e, 0x8d, 0x8b, 0x89, 0x89, 0x89, 0x88, 0x86, 0x83, 0x82, 0x80, 0x7f, + 0x7e, 0x7f, 0x7f, 0x80, 0x82, 0x82, 0x83, 0x84, 0x85, 0x85, 0x84, 0x82, + 0x81, 0x80, 0x80, 0x7d, 0x7c, 0x7c, 0x7c, 0x7c, 0x7e, 0x80, 0x82, 0x84, + 0x86, 0x8a, 0x8e, 0x91, 0x93, 0x96, 0x9a, 0x9d, 0x9f, 0xa0, 0xa1, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa2, 0x9f, 0x9c, 0x97, 0x8e, 0x81, + 0x77, 0x6f, 0x65, 0x5b, 0x56, 0x53, 0x52, 0x52, 0x53, 0x56, 0x58, 0x58, + 0x5a, 0x5e, 0x63, 0x66, 0x65, 0x64, 0x62, 0x64, 0x66, 0x68, 0x6b, 0x73, + 0x7b, 0x80, 0x83, 0x89, 0x92, 0x98, 0x9b, 0x9c, 0x9d, 0x9c, 0x9d, 0x9c, + 0x9b, 0x9a, 0x9b, 0x9a, 0x9b, 0x9a, 0x9a, 0x98, 0x95, 0x94, 0x94, 0x94, + 0x92, 0x93, 0x92, 0x8f, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x91, 0x92, 0x92, + 0x94, 0x94, 0x94, 0x94, 0x96, 0x97, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x96, 0x97, 0x96, 0x94, 0x90, 0x8a, 0x83, 0x7d, 0x78, 0x72, + 0x69, 0x62, 0x5c, 0x5a, 0x58, 0x57, 0x58, 0x59, 0x59, 0x59, 0x58, 0x57, + 0x57, 0x57, 0x58, 0x58, 0x58, 0x59, 0x59, 0x5a, 0x58, 0x58, 0x59, 0x59, + 0x59, 0x5b, 0x5b, 0x5b, 0x5c, 0x5d, 0x5e, 0x5e, 0x5e, 0x5e, 0x5f, 0x61, + 0x63, 0x64, 0x65, 0x67, 0x68, 0x69, 0x6a, 0x6a, 0x6b, 0x6b, 0x6a, 0x6a, + 0x6c, 0x6e, 0x6f, 0x71, 0x70, 0x70, 0x70, 0x6d, 0x6a, 0x67, 0x64, 0x62, + 0x5f, 0x5a, 0x57, 0x52, 0x4f, 0x4b, 0x45, 0x3e, 0x38, 0x33, 0x2a, 0x1e, + 0x14, 0x11, 0x10, 0x11, 0x10, 0x10, 0x12, 0x12, 0x11, 0x11, 0x13, 0x13, + 0x13, 0x13, 0x12, 0x13, 0x13, 0x13, 0x12, 0x13, 0x64, 0x5f, 0x59, 0x56, + 0x55, 0x55, 0x54, 0x55, 0x54, 0x54, 0x54, 0x53, 0x53, 0x53, 0x55, 0x55, + 0x57, 0x57, 0x56, 0x57, 0x5a, 0x5b, 0x5b, 0x5c, 0x5d, 0x5d, 0x5f, 0x60, + 0x60, 0x60, 0x61, 0x61, 0x63, 0x63, 0x64, 0x65, 0x67, 0x68, 0x69, 0x6a, + 0x6b, 0x6c, 0x6c, 0x6d, 0x6f, 0x75, 0x7c, 0x81, 0x84, 0x87, 0x8a, 0x8b, + 0x8d, 0x8e, 0x8f, 0x91, 0x92, 0x94, 0x95, 0x95, 0x95, 0x94, 0x94, 0x95, + 0x96, 0x98, 0x99, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9b, 0x9b, 0x9a, + 0x97, 0x95, 0x96, 0x95, 0x93, 0x91, 0x90, 0x8e, 0x8e, 0x8d, 0x8b, 0x89, + 0x89, 0x89, 0x87, 0x85, 0x82, 0x81, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, + 0x81, 0x82, 0x83, 0x85, 0x86, 0x86, 0x84, 0x82, 0x81, 0x81, 0x80, 0x7e, + 0x7c, 0x7c, 0x7c, 0x7c, 0x7e, 0x80, 0x82, 0x83, 0x86, 0x8a, 0x8d, 0x90, + 0x93, 0x95, 0x9a, 0x9c, 0x9f, 0xa0, 0xa1, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa1, 0x9e, 0x9a, 0x92, 0x85, 0x76, 0x6a, 0x64, 0x5c, 0x55, + 0x53, 0x50, 0x50, 0x51, 0x53, 0x57, 0x58, 0x5a, 0x5b, 0x5e, 0x63, 0x66, + 0x66, 0x65, 0x64, 0x66, 0x69, 0x69, 0x69, 0x6b, 0x6f, 0x71, 0x73, 0x7a, + 0x83, 0x8b, 0x92, 0x95, 0x98, 0x9b, 0x9d, 0x9c, 0x9c, 0x9a, 0x9b, 0x9a, + 0x9b, 0x9b, 0x9a, 0x98, 0x97, 0x95, 0x94, 0x94, 0x93, 0x93, 0x92, 0x8f, + 0x8f, 0x8f, 0x8f, 0x90, 0x91, 0x91, 0x92, 0x92, 0x94, 0x95, 0x95, 0x95, + 0x97, 0x97, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x97, 0x97, + 0x95, 0x93, 0x8f, 0x89, 0x82, 0x7c, 0x77, 0x70, 0x67, 0x5f, 0x5b, 0x59, + 0x58, 0x57, 0x58, 0x58, 0x58, 0x59, 0x58, 0x57, 0x56, 0x57, 0x57, 0x57, + 0x57, 0x59, 0x59, 0x59, 0x57, 0x58, 0x59, 0x59, 0x59, 0x5a, 0x5b, 0x5b, + 0x5c, 0x5c, 0x5d, 0x5e, 0x5e, 0x5f, 0x5f, 0x61, 0x64, 0x64, 0x66, 0x67, + 0x67, 0x69, 0x6a, 0x6b, 0x6b, 0x6b, 0x6a, 0x6a, 0x6c, 0x6e, 0x6f, 0x71, + 0x71, 0x70, 0x70, 0x6d, 0x6a, 0x67, 0x65, 0x63, 0x60, 0x5b, 0x57, 0x52, + 0x4f, 0x4c, 0x45, 0x3d, 0x38, 0x33, 0x2a, 0x1e, 0x15, 0x11, 0x10, 0x11, + 0x10, 0x11, 0x12, 0x12, 0x11, 0x11, 0x13, 0x13, 0x13, 0x13, 0x12, 0x13, + 0x13, 0x13, 0x12, 0x12, 0x5d, 0x5a, 0x57, 0x55, 0x54, 0x53, 0x52, 0x52, + 0x52, 0x52, 0x53, 0x53, 0x52, 0x52, 0x54, 0x56, 0x56, 0x56, 0x57, 0x57, + 0x59, 0x5b, 0x5b, 0x5b, 0x5c, 0x5e, 0x60, 0x60, 0x60, 0x61, 0x62, 0x62, + 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x6a, 0x6b, 0x6c, 0x6d, 0x6c, + 0x6c, 0x71, 0x78, 0x7e, 0x80, 0x82, 0x86, 0x88, 0x8b, 0x8c, 0x8d, 0x8e, + 0x90, 0x92, 0x93, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x97, 0x98, 0x9a, + 0x9a, 0x9a, 0x9b, 0x9a, 0x9a, 0x9b, 0x9a, 0x98, 0x96, 0x95, 0x94, 0x93, + 0x92, 0x92, 0x90, 0x8d, 0x8d, 0x8c, 0x8b, 0x8a, 0x88, 0x87, 0x86, 0x84, + 0x82, 0x81, 0x80, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x81, 0x82, 0x85, 0x86, + 0x86, 0x87, 0x86, 0x84, 0x83, 0x82, 0x7f, 0x7d, 0x7c, 0x7c, 0x7d, 0x7d, + 0x7f, 0x81, 0x82, 0x83, 0x85, 0x89, 0x8c, 0x8f, 0x91, 0x94, 0x99, 0x9b, + 0x9e, 0x9e, 0xa0, 0xa1, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa0, 0x9b, + 0x95, 0x87, 0x74, 0x65, 0x5e, 0x5b, 0x56, 0x53, 0x52, 0x50, 0x50, 0x52, + 0x56, 0x58, 0x5a, 0x5a, 0x5a, 0x5b, 0x60, 0x62, 0x63, 0x64, 0x63, 0x66, + 0x68, 0x68, 0x64, 0x60, 0x5e, 0x5d, 0x5d, 0x5f, 0x64, 0x6b, 0x75, 0x7b, + 0x86, 0x90, 0x98, 0x9b, 0x9c, 0x9b, 0x9b, 0x99, 0x96, 0x94, 0x93, 0x94, + 0x96, 0x97, 0x97, 0x94, 0x92, 0x93, 0x91, 0x8f, 0x8f, 0x8f, 0x8f, 0x91, + 0x92, 0x92, 0x93, 0x93, 0x95, 0x96, 0x96, 0x96, 0x97, 0x97, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x97, 0x97, 0x96, 0x93, 0x91, 0x8e, 0x87, + 0x7f, 0x78, 0x74, 0x6d, 0x64, 0x5d, 0x59, 0x57, 0x57, 0x56, 0x57, 0x57, + 0x57, 0x58, 0x57, 0x56, 0x57, 0x57, 0x57, 0x57, 0x56, 0x58, 0x58, 0x58, + 0x57, 0x59, 0x59, 0x59, 0x58, 0x58, 0x5a, 0x59, 0x5a, 0x5a, 0x5b, 0x5d, + 0x5f, 0x5f, 0x60, 0x61, 0x63, 0x65, 0x66, 0x66, 0x67, 0x68, 0x6b, 0x6c, + 0x6c, 0x6c, 0x6a, 0x6b, 0x6c, 0x6e, 0x6f, 0x71, 0x72, 0x71, 0x6f, 0x6d, + 0x6b, 0x68, 0x66, 0x64, 0x5f, 0x5b, 0x57, 0x52, 0x50, 0x4d, 0x46, 0x3e, + 0x3a, 0x35, 0x2c, 0x1f, 0x15, 0x12, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, + 0x11, 0x11, 0x11, 0x13, 0x14, 0x13, 0x13, 0x13, 0x12, 0x11, 0x11, 0x13, + 0x58, 0x57, 0x55, 0x54, 0x54, 0x53, 0x51, 0x51, 0x51, 0x51, 0x51, 0x52, + 0x52, 0x52, 0x53, 0x56, 0x56, 0x58, 0x58, 0x58, 0x59, 0x5b, 0x5b, 0x5b, + 0x5c, 0x5e, 0x5f, 0x61, 0x61, 0x61, 0x61, 0x63, 0x63, 0x64, 0x65, 0x66, + 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6c, 0x6b, 0x6b, 0x6b, 0x6e, 0x73, 0x78, + 0x7a, 0x7d, 0x80, 0x84, 0x87, 0x88, 0x89, 0x8b, 0x8e, 0x8f, 0x90, 0x91, + 0x92, 0x93, 0x92, 0x92, 0x94, 0x96, 0x96, 0x98, 0x98, 0x98, 0x99, 0x99, + 0x9a, 0x9a, 0x99, 0x97, 0x96, 0x94, 0x93, 0x92, 0x91, 0x91, 0x8f, 0x8d, + 0x8d, 0x8d, 0x8b, 0x8a, 0x88, 0x88, 0x86, 0x84, 0x82, 0x81, 0x81, 0x7f, + 0x80, 0x80, 0x81, 0x82, 0x82, 0x83, 0x85, 0x85, 0x85, 0x86, 0x86, 0x85, + 0x84, 0x82, 0x80, 0x7d, 0x7b, 0x7c, 0x7c, 0x7c, 0x7e, 0x81, 0x82, 0x82, + 0x85, 0x89, 0x8c, 0x8e, 0x90, 0x93, 0x97, 0x9b, 0x9e, 0x9f, 0xa1, 0xa1, + 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa2, 0x9d, 0x95, 0x8b, 0x77, 0x62, 0x5a, + 0x5a, 0x58, 0x54, 0x53, 0x52, 0x52, 0x53, 0x55, 0x59, 0x5b, 0x5c, 0x5c, + 0x5b, 0x5b, 0x5a, 0x59, 0x5a, 0x59, 0x59, 0x5b, 0x5c, 0x5a, 0x56, 0x54, + 0x54, 0x51, 0x50, 0x4f, 0x50, 0x51, 0x55, 0x5b, 0x64, 0x70, 0x7d, 0x8b, + 0x92, 0x97, 0x93, 0x89, 0x7f, 0x79, 0x71, 0x75, 0x84, 0x91, 0x95, 0x95, + 0x93, 0x92, 0x92, 0x91, 0x90, 0x90, 0x91, 0x90, 0x92, 0x92, 0x92, 0x93, + 0x95, 0x96, 0x96, 0x97, 0x96, 0x97, 0x97, 0x97, 0x97, 0x96, 0x98, 0x98, + 0x98, 0x97, 0x97, 0x95, 0x92, 0x90, 0x8d, 0x86, 0x7c, 0x76, 0x71, 0x69, + 0x61, 0x5b, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x59, 0x57, 0x55, + 0x56, 0x56, 0x55, 0x56, 0x55, 0x57, 0x57, 0x57, 0x56, 0x58, 0x59, 0x58, + 0x58, 0x58, 0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5d, 0x5f, 0x5f, 0x60, 0x63, + 0x65, 0x65, 0x67, 0x68, 0x69, 0x69, 0x6b, 0x6d, 0x6e, 0x6e, 0x6c, 0x6c, + 0x6e, 0x6f, 0x6f, 0x71, 0x72, 0x70, 0x6f, 0x6d, 0x6b, 0x67, 0x66, 0x65, + 0x61, 0x5c, 0x58, 0x53, 0x50, 0x4c, 0x47, 0x40, 0x3b, 0x36, 0x2f, 0x23, + 0x15, 0x11, 0x11, 0x11, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x13, + 0x14, 0x13, 0x13, 0x11, 0x12, 0x12, 0x11, 0x13, 0x57, 0x57, 0x54, 0x53, + 0x54, 0x53, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x53, 0x53, 0x55, + 0x56, 0x58, 0x58, 0x58, 0x59, 0x5b, 0x5b, 0x5c, 0x5d, 0x5e, 0x60, 0x62, + 0x61, 0x60, 0x61, 0x64, 0x64, 0x65, 0x66, 0x67, 0x66, 0x67, 0x69, 0x69, + 0x6a, 0x6b, 0x6a, 0x6a, 0x6a, 0x6b, 0x6d, 0x71, 0x74, 0x78, 0x7b, 0x80, + 0x83, 0x84, 0x86, 0x88, 0x8b, 0x8c, 0x8d, 0x8f, 0x90, 0x91, 0x91, 0x91, + 0x93, 0x95, 0x94, 0x95, 0x95, 0x96, 0x97, 0x98, 0x98, 0x98, 0x97, 0x96, + 0x94, 0x93, 0x93, 0x93, 0x91, 0x90, 0x8e, 0x8d, 0x8c, 0x8c, 0x8b, 0x89, + 0x88, 0x87, 0x86, 0x84, 0x83, 0x82, 0x81, 0x7e, 0x7f, 0x81, 0x82, 0x83, + 0x84, 0x85, 0x85, 0x86, 0x86, 0x87, 0x86, 0x85, 0x83, 0x82, 0x80, 0x7c, + 0x7b, 0x7c, 0x7c, 0x7b, 0x7d, 0x80, 0x81, 0x81, 0x83, 0x88, 0x8c, 0x8e, + 0x90, 0x93, 0x96, 0x9a, 0x9d, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa2, 0xa3, + 0xa3, 0xa3, 0x9b, 0x8f, 0x82, 0x6c, 0x5d, 0x5a, 0x5a, 0x58, 0x54, 0x54, + 0x55, 0x57, 0x58, 0x5b, 0x5c, 0x5c, 0x5c, 0x5d, 0x5c, 0x5a, 0x59, 0x58, + 0x57, 0x59, 0x60, 0x60, 0x5d, 0x5b, 0x59, 0x54, 0x52, 0x4e, 0x4d, 0x4d, + 0x4d, 0x4c, 0x4f, 0x52, 0x57, 0x5d, 0x67, 0x73, 0x7b, 0x7e, 0x79, 0x84, + 0x8a, 0x83, 0x6c, 0x5b, 0x62, 0x73, 0x81, 0x93, 0x94, 0x93, 0x93, 0x91, + 0x90, 0x90, 0x91, 0x91, 0x92, 0x93, 0x94, 0x94, 0x95, 0x95, 0x95, 0x95, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97, 0x95, + 0x92, 0x8f, 0x8b, 0x83, 0x7a, 0x73, 0x6e, 0x67, 0x5e, 0x58, 0x56, 0x56, + 0x56, 0x57, 0x57, 0x57, 0x57, 0x58, 0x57, 0x55, 0x56, 0x55, 0x54, 0x55, + 0x54, 0x55, 0x56, 0x56, 0x55, 0x56, 0x58, 0x58, 0x57, 0x58, 0x59, 0x5a, + 0x5a, 0x5b, 0x5b, 0x5d, 0x5f, 0x5f, 0x60, 0x63, 0x66, 0x67, 0x68, 0x69, + 0x69, 0x6a, 0x6c, 0x6e, 0x6e, 0x6e, 0x6d, 0x6d, 0x6e, 0x6f, 0x70, 0x72, + 0x71, 0x70, 0x6f, 0x6e, 0x6c, 0x68, 0x66, 0x65, 0x60, 0x5e, 0x59, 0x54, + 0x51, 0x4e, 0x48, 0x40, 0x3b, 0x37, 0x2f, 0x21, 0x15, 0x11, 0x11, 0x11, + 0x10, 0x11, 0x10, 0x10, 0x10, 0x11, 0x12, 0x12, 0x11, 0x12, 0x13, 0x11, + 0x11, 0x11, 0x11, 0x13, 0x56, 0x56, 0x55, 0x53, 0x53, 0x53, 0x53, 0x53, + 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x54, 0x55, 0x57, 0x58, 0x59, + 0x5a, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x62, 0x63, 0x63, 0x62, 0x63, 0x65, + 0x65, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68, 0x68, 0x6a, 0x6a, 0x6a, 0x6a, + 0x6b, 0x6b, 0x6b, 0x6d, 0x70, 0x74, 0x77, 0x7c, 0x7f, 0x81, 0x83, 0x85, + 0x88, 0x89, 0x8b, 0x8d, 0x8e, 0x90, 0x91, 0x92, 0x93, 0x93, 0x95, 0x95, + 0x94, 0x94, 0x95, 0x96, 0x96, 0x95, 0x95, 0x94, 0x94, 0x92, 0x93, 0x92, + 0x91, 0x8f, 0x8d, 0x8c, 0x8c, 0x8c, 0x8b, 0x89, 0x88, 0x87, 0x86, 0x83, + 0x81, 0x81, 0x80, 0x7e, 0x7e, 0x81, 0x83, 0x83, 0x84, 0x85, 0x86, 0x88, + 0x88, 0x89, 0x86, 0x84, 0x82, 0x81, 0x7f, 0x7d, 0x7b, 0x7b, 0x7b, 0x7a, + 0x7c, 0x7f, 0x81, 0x81, 0x83, 0x87, 0x8b, 0x8e, 0x91, 0x93, 0x95, 0x99, + 0x9c, 0x9e, 0x9f, 0xa1, 0xa2, 0xa2, 0xa2, 0xa2, 0xa3, 0xa2, 0x98, 0x8a, + 0x7d, 0x69, 0x5e, 0x5b, 0x59, 0x58, 0x55, 0x57, 0x59, 0x5b, 0x5c, 0x5d, + 0x5b, 0x5b, 0x5d, 0x5d, 0x5b, 0x58, 0x58, 0x5b, 0x63, 0x75, 0x83, 0x76, + 0x68, 0x65, 0x65, 0x5e, 0x5a, 0x53, 0x4f, 0x4d, 0x4b, 0x49, 0x4e, 0x51, + 0x56, 0x5c, 0x67, 0x6f, 0x6f, 0x68, 0x75, 0xa8, 0xb6, 0xac, 0x89, 0x5e, + 0x52, 0x58, 0x6a, 0x8f, 0x96, 0x93, 0x91, 0x90, 0x91, 0x90, 0x90, 0x92, + 0x94, 0x94, 0x95, 0x96, 0x97, 0x96, 0x95, 0x96, 0x97, 0x98, 0x98, 0x98, + 0x97, 0x96, 0x96, 0x96, 0x96, 0x97, 0x96, 0x93, 0x91, 0x8e, 0x89, 0x81, + 0x77, 0x70, 0x6c, 0x66, 0x5d, 0x56, 0x55, 0x55, 0x56, 0x56, 0x56, 0x56, + 0x56, 0x56, 0x57, 0x55, 0x56, 0x55, 0x54, 0x54, 0x55, 0x56, 0x56, 0x55, + 0x55, 0x57, 0x58, 0x58, 0x58, 0x58, 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5d, + 0x5e, 0x60, 0x61, 0x63, 0x65, 0x68, 0x69, 0x6a, 0x6a, 0x6a, 0x6c, 0x6e, + 0x6f, 0x6f, 0x6e, 0x6e, 0x6e, 0x6f, 0x71, 0x72, 0x71, 0x70, 0x70, 0x6e, + 0x6b, 0x69, 0x67, 0x65, 0x61, 0x5d, 0x58, 0x55, 0x52, 0x4e, 0x48, 0x42, + 0x3e, 0x3a, 0x31, 0x22, 0x16, 0x12, 0x11, 0x11, 0x11, 0x10, 0x10, 0x10, + 0x11, 0x12, 0x13, 0x12, 0x12, 0x13, 0x13, 0x13, 0x11, 0x11, 0x11, 0x13, + 0x56, 0x56, 0x55, 0x54, 0x53, 0x53, 0x54, 0x53, 0x53, 0x54, 0x54, 0x53, + 0x53, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5d, 0x5d, 0x5e, + 0x5f, 0x61, 0x63, 0x64, 0x64, 0x63, 0x64, 0x65, 0x65, 0x66, 0x66, 0x66, + 0x67, 0x67, 0x67, 0x68, 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6c, + 0x6d, 0x70, 0x74, 0x79, 0x7d, 0x7e, 0x81, 0x82, 0x86, 0x87, 0x88, 0x8b, + 0x8e, 0x8f, 0x91, 0x91, 0x92, 0x92, 0x94, 0x94, 0x93, 0x92, 0x93, 0x94, + 0x94, 0x93, 0x93, 0x93, 0x92, 0x91, 0x91, 0x91, 0x90, 0x8e, 0x8d, 0x8c, + 0x8c, 0x8c, 0x8a, 0x89, 0x88, 0x87, 0x86, 0x82, 0x81, 0x81, 0x80, 0x7e, + 0x7f, 0x81, 0x82, 0x83, 0x84, 0x85, 0x87, 0x89, 0x8a, 0x89, 0x86, 0x83, + 0x82, 0x81, 0x7f, 0x7d, 0x7b, 0x7b, 0x7b, 0x7a, 0x7c, 0x7e, 0x80, 0x81, + 0x83, 0x87, 0x8a, 0x8e, 0x90, 0x92, 0x96, 0x9a, 0x9c, 0x9d, 0x9f, 0xa1, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa1, 0x96, 0x87, 0x7a, 0x68, 0x5e, 0x5b, + 0x59, 0x57, 0x56, 0x59, 0x5c, 0x5c, 0x5d, 0x5d, 0x5b, 0x5b, 0x5d, 0x5d, + 0x5b, 0x5b, 0x63, 0x6b, 0x75, 0x8a, 0x97, 0x83, 0x74, 0x6f, 0x6a, 0x61, + 0x61, 0x56, 0x51, 0x4f, 0x4b, 0x4a, 0x4f, 0x53, 0x57, 0x5e, 0x69, 0x73, + 0x70, 0x66, 0x80, 0xbd, 0xca, 0xbd, 0x95, 0x61, 0x4d, 0x4c, 0x5d, 0x87, + 0x95, 0x93, 0x91, 0x90, 0x91, 0x90, 0x90, 0x92, 0x94, 0x95, 0x95, 0x96, + 0x97, 0x96, 0x95, 0x96, 0x97, 0x98, 0x98, 0x98, 0x97, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x93, 0x8f, 0x8c, 0x87, 0x7f, 0x75, 0x6e, 0x6a, 0x64, + 0x5b, 0x56, 0x55, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x55, + 0x55, 0x55, 0x54, 0x54, 0x55, 0x55, 0x55, 0x54, 0x54, 0x57, 0x58, 0x58, + 0x59, 0x58, 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5d, 0x5e, 0x60, 0x61, 0x63, + 0x64, 0x68, 0x69, 0x6a, 0x6b, 0x6b, 0x6c, 0x6e, 0x6f, 0x6f, 0x6e, 0x6e, + 0x6e, 0x6f, 0x72, 0x72, 0x72, 0x71, 0x70, 0x6e, 0x6b, 0x6a, 0x67, 0x65, + 0x61, 0x5d, 0x57, 0x54, 0x51, 0x4e, 0x49, 0x43, 0x3f, 0x3a, 0x31, 0x22, + 0x16, 0x12, 0x11, 0x11, 0x11, 0x10, 0x11, 0x11, 0x11, 0x12, 0x12, 0x11, + 0x12, 0x13, 0x13, 0x13, 0x11, 0x11, 0x11, 0x13, 0x56, 0x56, 0x56, 0x55, + 0x54, 0x54, 0x55, 0x54, 0x54, 0x55, 0x55, 0x54, 0x54, 0x54, 0x55, 0x56, + 0x57, 0x58, 0x5a, 0x5b, 0x5c, 0x5e, 0x5e, 0x5f, 0x60, 0x62, 0x63, 0x64, + 0x64, 0x64, 0x65, 0x64, 0x65, 0x66, 0x66, 0x66, 0x67, 0x68, 0x68, 0x69, + 0x69, 0x69, 0x69, 0x69, 0x6a, 0x6a, 0x69, 0x69, 0x6a, 0x6c, 0x70, 0x75, + 0x77, 0x7a, 0x7c, 0x7e, 0x82, 0x84, 0x86, 0x89, 0x8c, 0x8d, 0x8f, 0x90, + 0x91, 0x91, 0x92, 0x92, 0x90, 0x90, 0x91, 0x91, 0x91, 0x92, 0x91, 0x91, + 0x90, 0x8f, 0x8f, 0x8f, 0x8e, 0x8c, 0x8b, 0x8c, 0x8c, 0x8c, 0x8b, 0x8a, + 0x88, 0x87, 0x85, 0x82, 0x81, 0x80, 0x7f, 0x7f, 0x7f, 0x81, 0x82, 0x83, + 0x84, 0x85, 0x87, 0x8a, 0x8b, 0x8a, 0x87, 0x83, 0x82, 0x81, 0x7f, 0x7d, + 0x7b, 0x7b, 0x7a, 0x7a, 0x7c, 0x7d, 0x7f, 0x80, 0x83, 0x86, 0x89, 0x8d, + 0x8e, 0x91, 0x96, 0x9a, 0x9c, 0x9e, 0x9f, 0xa1, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa0, 0x93, 0x83, 0x77, 0x69, 0x5f, 0x5a, 0x57, 0x57, 0x59, 0x5c, + 0x5e, 0x5e, 0x5d, 0x5c, 0x5b, 0x5d, 0x5e, 0x5d, 0x5c, 0x65, 0x7d, 0x8b, + 0x92, 0x9a, 0x9b, 0x8b, 0x85, 0x7d, 0x6a, 0x61, 0x67, 0x58, 0x51, 0x51, + 0x4d, 0x4d, 0x53, 0x55, 0x59, 0x60, 0x6c, 0x7c, 0x7d, 0x79, 0x9d, 0xc7, + 0xc6, 0xb6, 0x92, 0x64, 0x4c, 0x46, 0x51, 0x74, 0x92, 0x94, 0x92, 0x91, + 0x92, 0x91, 0x91, 0x93, 0x94, 0x95, 0x95, 0x97, 0x97, 0x96, 0x95, 0x96, + 0x97, 0x98, 0x98, 0x98, 0x98, 0x97, 0x97, 0x97, 0x97, 0x97, 0x95, 0x91, + 0x8e, 0x8b, 0x85, 0x7c, 0x72, 0x6b, 0x67, 0x61, 0x5a, 0x55, 0x55, 0x55, + 0x56, 0x57, 0x57, 0x57, 0x56, 0x55, 0x55, 0x54, 0x55, 0x54, 0x53, 0x53, + 0x54, 0x55, 0x55, 0x53, 0x53, 0x56, 0x57, 0x57, 0x58, 0x58, 0x59, 0x5a, + 0x5a, 0x5b, 0x5b, 0x5d, 0x5e, 0x5f, 0x61, 0x63, 0x64, 0x67, 0x69, 0x6b, + 0x6c, 0x6c, 0x6d, 0x6e, 0x6f, 0x6e, 0x6e, 0x6f, 0x6e, 0x6f, 0x72, 0x72, + 0x72, 0x71, 0x70, 0x6e, 0x6b, 0x6a, 0x68, 0x66, 0x63, 0x5e, 0x57, 0x54, + 0x52, 0x4e, 0x49, 0x42, 0x3e, 0x39, 0x30, 0x22, 0x16, 0x12, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x13, 0x13, 0x13, + 0x11, 0x11, 0x11, 0x13, 0x56, 0x56, 0x56, 0x55, 0x54, 0x55, 0x56, 0x57, + 0x56, 0x57, 0x57, 0x55, 0x55, 0x57, 0x58, 0x57, 0x59, 0x5a, 0x5b, 0x5d, + 0x5f, 0x5e, 0x5e, 0x5f, 0x61, 0x63, 0x63, 0x64, 0x64, 0x64, 0x64, 0x64, + 0x65, 0x66, 0x66, 0x67, 0x66, 0x67, 0x67, 0x67, 0x68, 0x69, 0x69, 0x69, + 0x6a, 0x69, 0x66, 0x67, 0x67, 0x68, 0x6c, 0x6e, 0x72, 0x74, 0x76, 0x79, + 0x7e, 0x81, 0x82, 0x86, 0x88, 0x8b, 0x8d, 0x8e, 0x8e, 0x90, 0x90, 0x90, + 0x8f, 0x8f, 0x8f, 0x90, 0x8f, 0x90, 0x8f, 0x8e, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8a, 0x88, 0x88, 0x86, 0x83, + 0x81, 0x80, 0x80, 0x7f, 0x7f, 0x81, 0x82, 0x84, 0x83, 0x86, 0x88, 0x8a, + 0x8a, 0x8b, 0x89, 0x86, 0x84, 0x82, 0x80, 0x7e, 0x7b, 0x7a, 0x7a, 0x7a, + 0x7a, 0x7d, 0x7e, 0x7f, 0x82, 0x85, 0x8a, 0x8c, 0x8d, 0x91, 0x95, 0x99, + 0x9c, 0x9e, 0x9f, 0xa0, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0x9f, 0x8f, 0x7f, + 0x74, 0x68, 0x5f, 0x5a, 0x58, 0x59, 0x5d, 0x61, 0x61, 0x5e, 0x5d, 0x5b, + 0x5e, 0x5f, 0x5c, 0x5b, 0x5f, 0x6f, 0x7f, 0x84, 0x82, 0x7f, 0x83, 0x85, + 0x84, 0x7e, 0x73, 0x71, 0x6d, 0x5a, 0x52, 0x4f, 0x4d, 0x4e, 0x51, 0x53, + 0x58, 0x60, 0x6c, 0x83, 0x8f, 0x9d, 0xbb, 0xbb, 0x9e, 0x91, 0x88, 0x67, + 0x50, 0x48, 0x4d, 0x62, 0x83, 0x92, 0x92, 0x92, 0x92, 0x93, 0x92, 0x94, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x97, 0x97, 0x97, 0x97, 0x96, 0x93, 0x8e, 0x8a, 0x87, 0x81, 0x78, + 0x6f, 0x69, 0x65, 0x5f, 0x58, 0x55, 0x55, 0x54, 0x54, 0x56, 0x56, 0x56, + 0x56, 0x55, 0x55, 0x54, 0x52, 0x51, 0x50, 0x51, 0x53, 0x54, 0x54, 0x53, + 0x54, 0x54, 0x55, 0x56, 0x56, 0x58, 0x59, 0x5a, 0x5b, 0x5b, 0x5b, 0x5e, + 0x5f, 0x61, 0x62, 0x62, 0x64, 0x68, 0x69, 0x6a, 0x6b, 0x6e, 0x6f, 0x70, + 0x70, 0x6f, 0x70, 0x6f, 0x6f, 0x70, 0x72, 0x73, 0x71, 0x71, 0x71, 0x70, + 0x6d, 0x69, 0x67, 0x66, 0x63, 0x5e, 0x59, 0x55, 0x53, 0x4e, 0x49, 0x42, + 0x3d, 0x39, 0x31, 0x23, 0x16, 0x13, 0x12, 0x11, 0x11, 0x11, 0x12, 0x12, + 0x10, 0x11, 0x11, 0x11, 0x11, 0x12, 0x13, 0x13, 0x12, 0x11, 0x11, 0x13, + 0x57, 0x58, 0x57, 0x56, 0x55, 0x55, 0x57, 0x58, 0x58, 0x58, 0x58, 0x56, + 0x57, 0x58, 0x59, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5f, 0x5f, 0x61, 0x61, + 0x62, 0x63, 0x64, 0x64, 0x64, 0x64, 0x65, 0x66, 0x67, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x69, 0x69, 0x69, 0x6a, 0x68, 0x65, 0x65, + 0x65, 0x65, 0x67, 0x68, 0x6c, 0x6e, 0x6f, 0x73, 0x77, 0x7b, 0x7e, 0x81, + 0x85, 0x89, 0x8c, 0x8c, 0x8d, 0x8e, 0x8f, 0x8f, 0x8f, 0x8e, 0x8d, 0x8d, + 0x8c, 0x8d, 0x8d, 0x8b, 0x8b, 0x8a, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8c, + 0x8c, 0x8d, 0x8b, 0x88, 0x87, 0x87, 0x86, 0x83, 0x80, 0x80, 0x80, 0x7f, + 0x7f, 0x80, 0x83, 0x84, 0x84, 0x87, 0x89, 0x8b, 0x8b, 0x8a, 0x89, 0x86, + 0x84, 0x83, 0x80, 0x7e, 0x7b, 0x7a, 0x7a, 0x7a, 0x7b, 0x7d, 0x7e, 0x7f, + 0x82, 0x85, 0x89, 0x8b, 0x8c, 0x90, 0x95, 0x99, 0x9c, 0x9d, 0x9e, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0x9b, 0x8b, 0x7b, 0x72, 0x68, 0x5f, 0x5b, + 0x59, 0x5b, 0x60, 0x65, 0x65, 0x62, 0x5f, 0x5e, 0x61, 0x5f, 0x5d, 0x5d, + 0x63, 0x6b, 0x6c, 0x6a, 0x69, 0x69, 0x6e, 0x6e, 0x75, 0x7c, 0x85, 0x7f, + 0x7b, 0x67, 0x5a, 0x51, 0x4d, 0x4b, 0x4c, 0x4d, 0x50, 0x56, 0x64, 0x86, + 0xa0, 0xbe, 0xc5, 0xa6, 0x89, 0x83, 0x84, 0x61, 0x53, 0x56, 0x58, 0x58, + 0x63, 0x8c, 0x94, 0x92, 0x92, 0x93, 0x93, 0x94, 0x96, 0x96, 0x96, 0x97, + 0x96, 0x97, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x96, 0x96, 0x96, + 0x95, 0x93, 0x90, 0x8b, 0x86, 0x83, 0x7d, 0x74, 0x6c, 0x65, 0x61, 0x5b, + 0x56, 0x55, 0x55, 0x55, 0x55, 0x54, 0x55, 0x55, 0x55, 0x55, 0x53, 0x52, + 0x51, 0x50, 0x50, 0x51, 0x50, 0x52, 0x52, 0x52, 0x53, 0x53, 0x55, 0x56, + 0x57, 0x59, 0x59, 0x5a, 0x5b, 0x5a, 0x5b, 0x5e, 0x5f, 0x61, 0x62, 0x62, + 0x65, 0x68, 0x6a, 0x6c, 0x6d, 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x72, 0x72, + 0x72, 0x72, 0x71, 0x72, 0x71, 0x71, 0x71, 0x70, 0x6d, 0x69, 0x67, 0x65, + 0x62, 0x5f, 0x59, 0x56, 0x53, 0x4e, 0x4a, 0x43, 0x3d, 0x3a, 0x32, 0x24, + 0x17, 0x13, 0x12, 0x11, 0x11, 0x10, 0x10, 0x11, 0x11, 0x11, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x12, 0x11, 0x12, 0x14, 0x58, 0x59, 0x58, 0x57, + 0x56, 0x56, 0x57, 0x58, 0x58, 0x58, 0x57, 0x57, 0x58, 0x59, 0x5a, 0x5a, + 0x5c, 0x5d, 0x5d, 0x5d, 0x5f, 0x60, 0x62, 0x62, 0x62, 0x64, 0x64, 0x64, + 0x64, 0x64, 0x65, 0x67, 0x68, 0x68, 0x68, 0x69, 0x69, 0x69, 0x69, 0x68, + 0x68, 0x69, 0x69, 0x69, 0x6a, 0x68, 0x66, 0x64, 0x63, 0x64, 0x63, 0x64, + 0x67, 0x69, 0x6b, 0x6e, 0x73, 0x78, 0x7b, 0x7e, 0x82, 0x87, 0x8a, 0x8b, + 0x8c, 0x8d, 0x8e, 0x8e, 0x8e, 0x8d, 0x8c, 0x8c, 0x8c, 0x8d, 0x8c, 0x8a, + 0x89, 0x89, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8c, 0x8c, 0x8c, 0x8b, 0x88, + 0x87, 0x86, 0x84, 0x82, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x82, 0x83, + 0x85, 0x88, 0x8b, 0x8c, 0x8c, 0x8a, 0x88, 0x85, 0x84, 0x82, 0x80, 0x7e, + 0x7b, 0x7b, 0x7b, 0x7a, 0x7b, 0x7d, 0x7f, 0x80, 0x82, 0x84, 0x88, 0x8a, + 0x8b, 0x8f, 0x94, 0x99, 0x9c, 0x9c, 0x9d, 0x9f, 0x9f, 0xa0, 0x9f, 0xa0, + 0xa0, 0x98, 0x89, 0x78, 0x6f, 0x68, 0x60, 0x5b, 0x5a, 0x5c, 0x62, 0x68, + 0x68, 0x62, 0x61, 0x60, 0x5f, 0x5e, 0x60, 0x62, 0x65, 0x65, 0x65, 0x65, + 0x65, 0x64, 0x65, 0x63, 0x6b, 0x75, 0x82, 0x80, 0x7c, 0x70, 0x69, 0x61, + 0x54, 0x47, 0x46, 0x48, 0x4a, 0x52, 0x66, 0x84, 0x9f, 0xc4, 0xc5, 0x99, + 0x82, 0x78, 0x6c, 0x5b, 0x56, 0x5f, 0x59, 0x41, 0x43, 0x86, 0x95, 0x92, + 0x91, 0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x96, 0x96, 0x97, 0x98, 0x98, + 0x98, 0x96, 0x97, 0x97, 0x97, 0x97, 0x97, 0x96, 0x95, 0x93, 0x8f, 0x89, + 0x84, 0x80, 0x7a, 0x71, 0x69, 0x62, 0x5e, 0x59, 0x54, 0x54, 0x54, 0x54, + 0x54, 0x53, 0x54, 0x55, 0x54, 0x53, 0x51, 0x52, 0x51, 0x50, 0x51, 0x50, + 0x50, 0x51, 0x52, 0x51, 0x53, 0x54, 0x55, 0x56, 0x56, 0x58, 0x59, 0x5b, + 0x5c, 0x5b, 0x5c, 0x5e, 0x60, 0x62, 0x62, 0x63, 0x66, 0x68, 0x6a, 0x6c, + 0x6d, 0x6e, 0x70, 0x70, 0x71, 0x72, 0x73, 0x73, 0x73, 0x73, 0x72, 0x72, + 0x72, 0x71, 0x71, 0x6f, 0x6d, 0x69, 0x66, 0x65, 0x62, 0x5f, 0x5a, 0x57, + 0x54, 0x4e, 0x49, 0x44, 0x3e, 0x3a, 0x31, 0x23, 0x16, 0x12, 0x11, 0x10, + 0x11, 0x10, 0x10, 0x10, 0x11, 0x11, 0x12, 0x13, 0x13, 0x12, 0x13, 0x12, + 0x12, 0x12, 0x11, 0x13, 0x58, 0x59, 0x58, 0x57, 0x56, 0x56, 0x57, 0x58, + 0x58, 0x58, 0x57, 0x58, 0x59, 0x59, 0x5b, 0x5b, 0x5d, 0x5e, 0x5e, 0x5e, + 0x5f, 0x60, 0x62, 0x63, 0x62, 0x64, 0x64, 0x65, 0x65, 0x65, 0x66, 0x67, + 0x68, 0x68, 0x69, 0x69, 0x68, 0x69, 0x69, 0x69, 0x68, 0x68, 0x69, 0x69, + 0x68, 0x68, 0x66, 0x64, 0x63, 0x63, 0x61, 0x62, 0x64, 0x66, 0x68, 0x6b, + 0x70, 0x75, 0x78, 0x7c, 0x80, 0x85, 0x88, 0x8a, 0x8a, 0x8c, 0x8d, 0x8e, + 0x8d, 0x8c, 0x8c, 0x8b, 0x8b, 0x8b, 0x8b, 0x89, 0x89, 0x88, 0x8a, 0x8a, + 0x89, 0x8a, 0x8a, 0x8c, 0x8c, 0x8c, 0x8b, 0x88, 0x87, 0x86, 0x83, 0x82, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x82, 0x84, 0x86, 0x89, 0x8c, 0x8d, + 0x8c, 0x8b, 0x88, 0x85, 0x84, 0x82, 0x80, 0x7e, 0x7b, 0x7b, 0x7a, 0x79, + 0x7a, 0x7d, 0x7f, 0x80, 0x82, 0x84, 0x87, 0x89, 0x8b, 0x8e, 0x93, 0x98, + 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa0, 0xa0, 0xa0, 0x97, 0x87, 0x77, + 0x6f, 0x68, 0x60, 0x5b, 0x5a, 0x5d, 0x63, 0x6a, 0x69, 0x63, 0x60, 0x60, + 0x61, 0x67, 0x6f, 0x72, 0x6f, 0x65, 0x61, 0x60, 0x60, 0x5f, 0x5f, 0x61, + 0x6a, 0x72, 0x7c, 0x77, 0x75, 0x77, 0x76, 0x72, 0x64, 0x48, 0x43, 0x45, + 0x49, 0x50, 0x66, 0x85, 0xa0, 0xc3, 0xbf, 0x93, 0x7c, 0x6f, 0x5e, 0x58, + 0x56, 0x5f, 0x55, 0x31, 0x35, 0x82, 0x95, 0x92, 0x92, 0x94, 0x95, 0x95, + 0x96, 0x96, 0x97, 0x96, 0x96, 0x98, 0x98, 0x98, 0x98, 0x96, 0x96, 0x96, + 0x97, 0x97, 0x97, 0x96, 0x95, 0x93, 0x8e, 0x87, 0x82, 0x7e, 0x78, 0x6f, + 0x67, 0x61, 0x5c, 0x57, 0x54, 0x54, 0x54, 0x54, 0x53, 0x53, 0x53, 0x54, + 0x53, 0x52, 0x51, 0x52, 0x51, 0x51, 0x52, 0x51, 0x50, 0x51, 0x51, 0x52, + 0x54, 0x54, 0x56, 0x56, 0x56, 0x58, 0x59, 0x5b, 0x5c, 0x5c, 0x5c, 0x5e, + 0x60, 0x62, 0x62, 0x63, 0x65, 0x68, 0x6a, 0x6c, 0x6d, 0x6e, 0x70, 0x70, + 0x71, 0x73, 0x73, 0x73, 0x73, 0x73, 0x72, 0x73, 0x73, 0x72, 0x71, 0x70, + 0x6d, 0x69, 0x67, 0x65, 0x62, 0x5f, 0x5b, 0x57, 0x54, 0x4f, 0x49, 0x45, + 0x3f, 0x3a, 0x31, 0x23, 0x17, 0x12, 0x11, 0x10, 0x11, 0x10, 0x10, 0x10, + 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x12, 0x11, 0x12, 0x12, 0x11, 0x12, + 0x58, 0x58, 0x57, 0x56, 0x55, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x59, + 0x59, 0x5a, 0x5b, 0x5b, 0x5d, 0x5e, 0x5f, 0x5e, 0x5f, 0x60, 0x62, 0x62, + 0x64, 0x65, 0x64, 0x66, 0x66, 0x65, 0x66, 0x66, 0x67, 0x68, 0x69, 0x69, + 0x68, 0x69, 0x6a, 0x6a, 0x69, 0x67, 0x68, 0x68, 0x67, 0x68, 0x66, 0x64, + 0x63, 0x63, 0x60, 0x60, 0x61, 0x61, 0x63, 0x67, 0x6e, 0x72, 0x74, 0x78, + 0x7c, 0x82, 0x86, 0x87, 0x89, 0x8a, 0x8c, 0x8c, 0x8b, 0x8c, 0x8c, 0x8b, + 0x89, 0x89, 0x89, 0x89, 0x88, 0x88, 0x89, 0x89, 0x88, 0x89, 0x8a, 0x8b, + 0x8b, 0x8b, 0x8b, 0x89, 0x87, 0x85, 0x83, 0x81, 0x80, 0x80, 0x81, 0x80, + 0x80, 0x81, 0x83, 0x84, 0x87, 0x8a, 0x8c, 0x8d, 0x8c, 0x8b, 0x88, 0x86, + 0x84, 0x83, 0x81, 0x7d, 0x7c, 0x7b, 0x7a, 0x79, 0x79, 0x7c, 0x7e, 0x7f, + 0x81, 0x82, 0x86, 0x88, 0x8a, 0x8e, 0x92, 0x96, 0x99, 0x9a, 0x9a, 0x9c, + 0x9f, 0xa0, 0xa0, 0xa0, 0xa0, 0x96, 0x85, 0x75, 0x6d, 0x67, 0x60, 0x5b, + 0x5a, 0x5d, 0x65, 0x6d, 0x67, 0x60, 0x5f, 0x64, 0x70, 0x84, 0x97, 0x98, + 0x8a, 0x71, 0x60, 0x58, 0x55, 0x51, 0x54, 0x5d, 0x6a, 0x71, 0x71, 0x62, + 0x68, 0x81, 0x8b, 0x8c, 0x84, 0x53, 0x42, 0x42, 0x49, 0x4c, 0x5e, 0x86, + 0xa2, 0xbc, 0xaf, 0x8d, 0x71, 0x61, 0x55, 0x58, 0x51, 0x53, 0x47, 0x24, + 0x2d, 0x7c, 0x94, 0x94, 0x93, 0x94, 0x95, 0x96, 0x96, 0x96, 0x96, 0x95, + 0x95, 0x97, 0x98, 0x98, 0x97, 0x96, 0x95, 0x96, 0x97, 0x98, 0x97, 0x95, + 0x93, 0x91, 0x8b, 0x84, 0x7f, 0x7b, 0x74, 0x6c, 0x63, 0x5d, 0x59, 0x56, + 0x53, 0x53, 0x52, 0x53, 0x53, 0x52, 0x53, 0x53, 0x53, 0x52, 0x51, 0x51, + 0x50, 0x51, 0x51, 0x51, 0x50, 0x51, 0x51, 0x51, 0x52, 0x55, 0x56, 0x56, + 0x56, 0x58, 0x59, 0x5b, 0x5c, 0x5c, 0x5d, 0x5e, 0x60, 0x62, 0x62, 0x63, + 0x65, 0x67, 0x6a, 0x6c, 0x6d, 0x6f, 0x71, 0x70, 0x71, 0x72, 0x73, 0x73, + 0x73, 0x73, 0x72, 0x72, 0x73, 0x73, 0x72, 0x70, 0x6d, 0x69, 0x67, 0x66, + 0x63, 0x5f, 0x5b, 0x57, 0x54, 0x50, 0x4b, 0x44, 0x3f, 0x3b, 0x33, 0x25, + 0x17, 0x12, 0x10, 0x11, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x12, 0x12, 0x11, 0x12, 0x13, 0x11, 0x12, 0x58, 0x58, 0x57, 0x56, + 0x56, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x59, 0x5a, 0x5a, 0x5b, 0x5c, + 0x5e, 0x5f, 0x5f, 0x5e, 0x5e, 0x5f, 0x61, 0x62, 0x64, 0x65, 0x64, 0x66, + 0x66, 0x65, 0x66, 0x66, 0x67, 0x68, 0x69, 0x69, 0x68, 0x69, 0x69, 0x6a, + 0x69, 0x67, 0x68, 0x68, 0x67, 0x66, 0x64, 0x64, 0x63, 0x61, 0x5e, 0x5e, + 0x5e, 0x5e, 0x5f, 0x62, 0x68, 0x6b, 0x6d, 0x72, 0x77, 0x7c, 0x80, 0x83, + 0x85, 0x87, 0x89, 0x8a, 0x8a, 0x8a, 0x8b, 0x89, 0x88, 0x88, 0x88, 0x86, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x88, 0x89, 0x89, 0x89, 0x89, 0x8a, 0x89, + 0x86, 0x85, 0x83, 0x81, 0x80, 0x80, 0x81, 0x81, 0x81, 0x82, 0x84, 0x86, + 0x88, 0x8a, 0x8b, 0x8c, 0x8c, 0x8b, 0x88, 0x85, 0x83, 0x82, 0x80, 0x7d, + 0x7c, 0x7b, 0x7a, 0x79, 0x79, 0x7b, 0x7c, 0x7d, 0x7f, 0x81, 0x85, 0x87, + 0x89, 0x8d, 0x90, 0x92, 0x94, 0x95, 0x96, 0x97, 0x9a, 0x9e, 0xa0, 0xa0, + 0x9d, 0x93, 0x82, 0x72, 0x6b, 0x65, 0x5f, 0x5b, 0x5c, 0x5f, 0x66, 0x6e, + 0x65, 0x60, 0x65, 0x79, 0x96, 0xa8, 0xbc, 0xbc, 0xa3, 0x8b, 0x78, 0x6c, + 0x5f, 0x4c, 0x45, 0x50, 0x5c, 0x63, 0x67, 0x58, 0x67, 0x87, 0x97, 0x9e, + 0x94, 0x6a, 0x48, 0x41, 0x4b, 0x48, 0x57, 0x73, 0x88, 0x9c, 0x90, 0x86, + 0x68, 0x57, 0x50, 0x56, 0x46, 0x3c, 0x30, 0x1a, 0x29, 0x75, 0x93, 0x95, + 0x94, 0x94, 0x96, 0x96, 0x97, 0x97, 0x96, 0x95, 0x95, 0x97, 0x97, 0x96, + 0x97, 0x96, 0x95, 0x96, 0x97, 0x97, 0x95, 0x93, 0x91, 0x8d, 0x87, 0x80, + 0x7a, 0x75, 0x6f, 0x68, 0x5e, 0x59, 0x56, 0x52, 0x51, 0x52, 0x51, 0x51, + 0x52, 0x51, 0x51, 0x51, 0x51, 0x50, 0x50, 0x4f, 0x50, 0x50, 0x4f, 0x50, + 0x4f, 0x50, 0x51, 0x50, 0x52, 0x55, 0x56, 0x56, 0x56, 0x58, 0x59, 0x5b, + 0x5c, 0x5c, 0x5e, 0x5e, 0x5f, 0x61, 0x61, 0x62, 0x66, 0x67, 0x6a, 0x6c, + 0x6d, 0x6f, 0x71, 0x70, 0x71, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x72, + 0x73, 0x73, 0x72, 0x70, 0x6d, 0x69, 0x67, 0x66, 0x63, 0x5d, 0x5a, 0x57, + 0x54, 0x50, 0x4a, 0x42, 0x3c, 0x38, 0x32, 0x26, 0x17, 0x12, 0x10, 0x11, + 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x11, + 0x12, 0x12, 0x12, 0x11, 0x58, 0x58, 0x58, 0x57, 0x56, 0x56, 0x58, 0x58, + 0x57, 0x57, 0x58, 0x5a, 0x5a, 0x5a, 0x5c, 0x5d, 0x5d, 0x5f, 0x5f, 0x5f, + 0x5f, 0x5f, 0x61, 0x62, 0x63, 0x64, 0x65, 0x65, 0x65, 0x66, 0x67, 0x67, + 0x68, 0x69, 0x69, 0x69, 0x68, 0x68, 0x69, 0x69, 0x68, 0x66, 0x67, 0x67, + 0x67, 0x64, 0x63, 0x63, 0x62, 0x60, 0x5f, 0x5d, 0x5b, 0x5b, 0x5c, 0x5d, + 0x61, 0x65, 0x69, 0x6d, 0x72, 0x77, 0x7a, 0x7d, 0x81, 0x84, 0x86, 0x89, + 0x89, 0x8a, 0x8a, 0x89, 0x87, 0x88, 0x87, 0x86, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x87, 0x88, 0x88, 0x88, 0x89, 0x8a, 0x88, 0x86, 0x85, 0x83, 0x80, + 0x7f, 0x80, 0x80, 0x80, 0x81, 0x84, 0x86, 0x87, 0x89, 0x8b, 0x8c, 0x8d, + 0x8d, 0x8c, 0x89, 0x85, 0x83, 0x81, 0x7f, 0x7c, 0x7b, 0x7a, 0x7a, 0x79, + 0x7a, 0x79, 0x7c, 0x7d, 0x7e, 0x80, 0x83, 0x87, 0x89, 0x8a, 0x8c, 0x8c, + 0x8c, 0x8d, 0x8e, 0x90, 0x95, 0x9c, 0x9f, 0x9f, 0x9b, 0x90, 0x7f, 0x71, + 0x6a, 0x65, 0x5f, 0x5d, 0x5e, 0x61, 0x67, 0x6c, 0x65, 0x68, 0x77, 0x96, + 0xa0, 0xa2, 0xab, 0xa6, 0x8e, 0x81, 0x8d, 0x8b, 0x7c, 0x58, 0x3f, 0x42, + 0x4d, 0x53, 0x58, 0x5a, 0x6a, 0x81, 0x94, 0xa7, 0x92, 0x78, 0x51, 0x47, + 0x51, 0x4c, 0x55, 0x5b, 0x64, 0x77, 0x7d, 0x78, 0x5f, 0x53, 0x50, 0x4f, + 0x38, 0x29, 0x20, 0x17, 0x29, 0x75, 0x94, 0x94, 0x93, 0x94, 0x96, 0x97, + 0x97, 0x98, 0x98, 0x96, 0x96, 0x98, 0x98, 0x96, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x95, 0x93, 0x91, 0x8e, 0x89, 0x83, 0x7c, 0x76, 0x72, 0x6c, 0x64, + 0x5b, 0x56, 0x53, 0x51, 0x50, 0x50, 0x51, 0x51, 0x51, 0x51, 0x51, 0x50, + 0x50, 0x4f, 0x50, 0x4f, 0x50, 0x50, 0x4f, 0x4e, 0x4e, 0x50, 0x51, 0x52, + 0x53, 0x55, 0x56, 0x56, 0x56, 0x58, 0x58, 0x59, 0x5b, 0x5d, 0x5e, 0x5e, + 0x61, 0x62, 0x62, 0x63, 0x66, 0x67, 0x69, 0x6a, 0x6c, 0x6f, 0x71, 0x70, + 0x71, 0x73, 0x73, 0x72, 0x72, 0x72, 0x74, 0x75, 0x74, 0x71, 0x70, 0x6f, + 0x6d, 0x68, 0x66, 0x65, 0x61, 0x5e, 0x5b, 0x58, 0x55, 0x50, 0x4a, 0x42, + 0x3c, 0x37, 0x30, 0x25, 0x17, 0x12, 0x10, 0x10, 0x11, 0x10, 0x10, 0x10, + 0x11, 0x10, 0x11, 0x12, 0x13, 0x13, 0x13, 0x13, 0x12, 0x11, 0x12, 0x11, + 0x59, 0x58, 0x58, 0x57, 0x56, 0x56, 0x59, 0x59, 0x5a, 0x59, 0x59, 0x5b, + 0x5a, 0x5b, 0x5d, 0x5f, 0x5e, 0x5f, 0x60, 0x60, 0x5f, 0x61, 0x62, 0x63, + 0x64, 0x65, 0x65, 0x65, 0x66, 0x67, 0x68, 0x68, 0x69, 0x69, 0x6a, 0x69, + 0x69, 0x69, 0x69, 0x6a, 0x69, 0x67, 0x67, 0x67, 0x66, 0x64, 0x63, 0x62, + 0x61, 0x61, 0x5f, 0x5c, 0x5a, 0x5a, 0x59, 0x5a, 0x5e, 0x61, 0x65, 0x6a, + 0x6f, 0x73, 0x77, 0x79, 0x7d, 0x81, 0x84, 0x87, 0x88, 0x89, 0x89, 0x88, + 0x88, 0x88, 0x87, 0x86, 0x84, 0x85, 0x84, 0x84, 0x85, 0x86, 0x87, 0x87, + 0x87, 0x88, 0x89, 0x88, 0x86, 0x85, 0x83, 0x80, 0x7f, 0x80, 0x80, 0x81, + 0x82, 0x85, 0x86, 0x88, 0x8a, 0x8c, 0x8d, 0x8e, 0x8e, 0x8d, 0x8a, 0x85, + 0x82, 0x81, 0x7e, 0x7c, 0x7b, 0x79, 0x79, 0x7a, 0x7a, 0x79, 0x7b, 0x7d, + 0x7e, 0x80, 0x84, 0x86, 0x88, 0x88, 0x87, 0x86, 0x85, 0x86, 0x88, 0x8b, + 0x90, 0x98, 0x9d, 0x9e, 0x99, 0x8d, 0x7c, 0x6f, 0x68, 0x64, 0x5f, 0x5d, + 0x60, 0x63, 0x67, 0x69, 0x6a, 0x77, 0x86, 0x95, 0x90, 0xa3, 0xa9, 0xa5, + 0x9b, 0x94, 0x98, 0x94, 0x86, 0x65, 0x44, 0x3d, 0x45, 0x4a, 0x4f, 0x57, + 0x65, 0x75, 0x89, 0xa4, 0x8a, 0x66, 0x50, 0x4d, 0x55, 0x51, 0x51, 0x50, + 0x53, 0x5c, 0x65, 0x67, 0x5a, 0x53, 0x50, 0x47, 0x2c, 0x22, 0x1d, 0x18, + 0x2d, 0x78, 0x94, 0x95, 0x94, 0x94, 0x96, 0x97, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x99, 0x99, 0x98, 0x97, 0x97, 0x97, 0x97, 0x96, 0x94, 0x92, 0x8f, + 0x8c, 0x87, 0x80, 0x7a, 0x73, 0x6f, 0x69, 0x60, 0x58, 0x53, 0x51, 0x50, + 0x4f, 0x4f, 0x4f, 0x50, 0x51, 0x4f, 0x4f, 0x4e, 0x4d, 0x4e, 0x4e, 0x4e, + 0x4f, 0x4f, 0x4e, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x55, 0x56, 0x56, + 0x56, 0x58, 0x58, 0x59, 0x5b, 0x5c, 0x5e, 0x5e, 0x61, 0x62, 0x63, 0x63, + 0x66, 0x67, 0x69, 0x6a, 0x6c, 0x6f, 0x71, 0x70, 0x71, 0x73, 0x74, 0x72, + 0x72, 0x73, 0x75, 0x75, 0x74, 0x71, 0x70, 0x70, 0x6d, 0x68, 0x67, 0x64, + 0x61, 0x5d, 0x5b, 0x58, 0x55, 0x50, 0x4a, 0x43, 0x3d, 0x38, 0x2f, 0x24, + 0x18, 0x12, 0x10, 0x10, 0x12, 0x11, 0x10, 0x10, 0x10, 0x11, 0x11, 0x12, + 0x13, 0x13, 0x13, 0x13, 0x12, 0x12, 0x12, 0x11, 0x59, 0x59, 0x59, 0x58, + 0x57, 0x56, 0x5a, 0x5a, 0x5b, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, 0x5d, 0x5f, + 0x5e, 0x5e, 0x5f, 0x60, 0x60, 0x61, 0x63, 0x63, 0x65, 0x65, 0x65, 0x66, + 0x66, 0x68, 0x68, 0x68, 0x69, 0x6a, 0x6a, 0x69, 0x68, 0x69, 0x69, 0x6a, + 0x69, 0x68, 0x68, 0x67, 0x66, 0x64, 0x64, 0x62, 0x61, 0x61, 0x5f, 0x5d, + 0x5b, 0x5a, 0x58, 0x59, 0x5c, 0x5f, 0x62, 0x67, 0x6c, 0x71, 0x74, 0x76, + 0x7b, 0x80, 0x83, 0x86, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x87, 0x86, + 0x83, 0x84, 0x83, 0x84, 0x84, 0x85, 0x87, 0x86, 0x87, 0x87, 0x88, 0x88, + 0x86, 0x85, 0x83, 0x80, 0x7f, 0x80, 0x81, 0x81, 0x82, 0x85, 0x87, 0x88, + 0x8a, 0x8c, 0x8e, 0x8e, 0x8e, 0x8d, 0x8a, 0x85, 0x82, 0x81, 0x7e, 0x7c, + 0x7b, 0x79, 0x79, 0x7a, 0x7a, 0x79, 0x7b, 0x7d, 0x7e, 0x80, 0x83, 0x86, + 0x87, 0x86, 0x85, 0x82, 0x80, 0x80, 0x82, 0x85, 0x8c, 0x95, 0x9b, 0x9c, + 0x97, 0x8b, 0x7a, 0x6d, 0x67, 0x63, 0x5f, 0x5e, 0x61, 0x64, 0x67, 0x69, + 0x6f, 0x82, 0x8c, 0x8e, 0x8f, 0xa7, 0xab, 0xaa, 0xa7, 0x9f, 0x97, 0x8e, + 0x82, 0x66, 0x47, 0x3e, 0x44, 0x48, 0x4d, 0x58, 0x67, 0x71, 0x80, 0x97, + 0x85, 0x60, 0x52, 0x52, 0x5a, 0x58, 0x51, 0x4e, 0x4f, 0x52, 0x59, 0x5c, + 0x55, 0x51, 0x4e, 0x40, 0x26, 0x23, 0x24, 0x25, 0x38, 0x7d, 0x94, 0x95, + 0x95, 0x94, 0x96, 0x97, 0x98, 0x99, 0x99, 0x98, 0x98, 0x99, 0x99, 0x99, + 0x97, 0x97, 0x97, 0x97, 0x95, 0x94, 0x91, 0x8d, 0x8a, 0x85, 0x7e, 0x77, + 0x71, 0x6c, 0x66, 0x5d, 0x55, 0x51, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, + 0x50, 0x4f, 0x4e, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4e, 0x4f, 0x4e, 0x4e, + 0x4f, 0x50, 0x51, 0x52, 0x53, 0x55, 0x56, 0x56, 0x56, 0x58, 0x58, 0x5a, + 0x5b, 0x5c, 0x5e, 0x5e, 0x61, 0x62, 0x63, 0x63, 0x66, 0x67, 0x69, 0x6a, + 0x6c, 0x6f, 0x71, 0x70, 0x71, 0x74, 0x74, 0x73, 0x73, 0x74, 0x75, 0x75, + 0x74, 0x71, 0x70, 0x70, 0x6d, 0x69, 0x67, 0x64, 0x60, 0x5d, 0x5b, 0x58, + 0x55, 0x50, 0x4a, 0x43, 0x3e, 0x39, 0x2f, 0x24, 0x17, 0x12, 0x10, 0x10, + 0x12, 0x11, 0x10, 0x10, 0x10, 0x11, 0x11, 0x12, 0x12, 0x13, 0x12, 0x12, + 0x13, 0x13, 0x12, 0x11, 0x5c, 0x5c, 0x5b, 0x5a, 0x58, 0x58, 0x5b, 0x5c, + 0x5c, 0x5c, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x5e, 0x5f, 0x60, 0x61, + 0x60, 0x62, 0x64, 0x65, 0x65, 0x65, 0x66, 0x67, 0x67, 0x68, 0x68, 0x69, + 0x6a, 0x6a, 0x69, 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x69, 0x68, 0x68, 0x68, + 0x67, 0x64, 0x64, 0x62, 0x61, 0x61, 0x5f, 0x5d, 0x5b, 0x59, 0x57, 0x57, + 0x58, 0x5a, 0x5d, 0x63, 0x68, 0x6e, 0x71, 0x73, 0x76, 0x7c, 0x80, 0x84, + 0x86, 0x87, 0x87, 0x87, 0x88, 0x88, 0x88, 0x85, 0x83, 0x82, 0x82, 0x83, + 0x83, 0x85, 0x85, 0x85, 0x86, 0x86, 0x87, 0x87, 0x86, 0x85, 0x82, 0x81, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8d, 0x8e, 0x8f, + 0x8e, 0x8d, 0x89, 0x86, 0x83, 0x81, 0x7e, 0x7c, 0x7a, 0x79, 0x79, 0x7a, + 0x7a, 0x79, 0x7b, 0x7d, 0x7e, 0x7f, 0x82, 0x84, 0x84, 0x83, 0x80, 0x7c, + 0x78, 0x77, 0x78, 0x7b, 0x84, 0x90, 0x97, 0x99, 0x95, 0x88, 0x77, 0x6a, + 0x65, 0x64, 0x60, 0x60, 0x63, 0x66, 0x69, 0x6c, 0x79, 0x8d, 0x8f, 0x85, + 0x99, 0xa6, 0xa5, 0xa7, 0xaa, 0x9c, 0x8d, 0x83, 0x79, 0x63, 0x4a, 0x43, + 0x4a, 0x4e, 0x51, 0x5c, 0x71, 0x72, 0x74, 0x7b, 0x7f, 0x66, 0x59, 0x59, + 0x63, 0x62, 0x52, 0x4e, 0x4f, 0x50, 0x50, 0x51, 0x4d, 0x4b, 0x48, 0x33, + 0x22, 0x2a, 0x34, 0x40, 0x4f, 0x86, 0x95, 0x96, 0x96, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x99, 0x99, 0x99, 0x99, 0x98, 0x98, 0x97, 0x97, 0x96, 0x96, + 0x94, 0x92, 0x8e, 0x8b, 0x88, 0x83, 0x7a, 0x73, 0x6d, 0x69, 0x62, 0x5a, + 0x53, 0x4f, 0x4e, 0x4f, 0x4e, 0x4e, 0x4e, 0x4e, 0x4f, 0x4e, 0x4d, 0x4d, + 0x4d, 0x4e, 0x4d, 0x4d, 0x4d, 0x4e, 0x4f, 0x50, 0x50, 0x50, 0x50, 0x52, + 0x53, 0x55, 0x54, 0x55, 0x56, 0x58, 0x59, 0x5b, 0x5b, 0x5b, 0x5d, 0x5e, + 0x61, 0x62, 0x62, 0x63, 0x65, 0x67, 0x69, 0x6a, 0x6c, 0x6f, 0x71, 0x70, + 0x71, 0x74, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x74, 0x72, 0x71, 0x70, + 0x6e, 0x69, 0x66, 0x64, 0x61, 0x5e, 0x5b, 0x58, 0x55, 0x50, 0x4a, 0x43, + 0x3d, 0x38, 0x2f, 0x25, 0x18, 0x12, 0x11, 0x10, 0x11, 0x10, 0x10, 0x10, + 0x10, 0x11, 0x11, 0x11, 0x11, 0x12, 0x11, 0x11, 0x12, 0x12, 0x11, 0x11, + 0x5e, 0x5d, 0x5d, 0x5d, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5d, 0x5d, 0x5e, + 0x5e, 0x5f, 0x60, 0x61, 0x60, 0x61, 0x61, 0x61, 0x61, 0x64, 0x65, 0x65, + 0x64, 0x64, 0x66, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6a, 0x6a, 0x69, 0x69, + 0x6a, 0x6b, 0x6b, 0x6b, 0x69, 0x68, 0x67, 0x66, 0x66, 0x64, 0x64, 0x63, + 0x62, 0x61, 0x5f, 0x5d, 0x5b, 0x5a, 0x58, 0x56, 0x55, 0x56, 0x58, 0x5c, + 0x62, 0x69, 0x6c, 0x6e, 0x72, 0x78, 0x7d, 0x82, 0x83, 0x84, 0x85, 0x88, + 0x88, 0x87, 0x87, 0x86, 0x83, 0x82, 0x82, 0x82, 0x83, 0x84, 0x85, 0x86, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x84, 0x82, 0x81, 0x82, 0x81, 0x82, 0x83, + 0x86, 0x88, 0x89, 0x8a, 0x8c, 0x8f, 0x91, 0x90, 0x8f, 0x8c, 0x89, 0x84, + 0x83, 0x81, 0x7e, 0x7c, 0x7c, 0x7a, 0x79, 0x79, 0x79, 0x79, 0x7b, 0x7b, + 0x7c, 0x7e, 0x81, 0x83, 0x83, 0x81, 0x7c, 0x75, 0x70, 0x6b, 0x6a, 0x6e, + 0x7a, 0x89, 0x91, 0x92, 0x8f, 0x81, 0x72, 0x68, 0x65, 0x64, 0x63, 0x63, + 0x67, 0x6b, 0x6e, 0x73, 0x83, 0x85, 0x81, 0x7f, 0x91, 0x90, 0x8f, 0x92, + 0x96, 0x89, 0x8c, 0x8c, 0x85, 0x70, 0x51, 0x4b, 0x5b, 0x63, 0x63, 0x63, + 0x74, 0x72, 0x71, 0x76, 0x80, 0x71, 0x5d, 0x58, 0x5e, 0x5f, 0x51, 0x49, + 0x49, 0x4d, 0x52, 0x50, 0x4b, 0x46, 0x3c, 0x22, 0x1f, 0x2f, 0x3a, 0x45, + 0x5e, 0x8d, 0x96, 0x96, 0x96, 0x97, 0x96, 0x98, 0x99, 0x99, 0x98, 0x9a, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x96, 0x96, 0x94, 0x93, 0x8f, 0x8a, 0x87, + 0x84, 0x7e, 0x75, 0x6c, 0x67, 0x64, 0x5e, 0x56, 0x50, 0x4d, 0x4d, 0x4d, + 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4d, 0x4c, 0x4c, 0x4c, 0x4d, 0x4d, 0x4c, + 0x4e, 0x4e, 0x4e, 0x50, 0x50, 0x4f, 0x50, 0x51, 0x52, 0x54, 0x54, 0x55, + 0x57, 0x59, 0x59, 0x5b, 0x5b, 0x5c, 0x5c, 0x60, 0x61, 0x61, 0x61, 0x63, + 0x65, 0x67, 0x69, 0x6a, 0x6c, 0x6f, 0x71, 0x73, 0x73, 0x74, 0x74, 0x77, + 0x77, 0x76, 0x75, 0x74, 0x74, 0x74, 0x73, 0x72, 0x6d, 0x69, 0x66, 0x65, + 0x63, 0x60, 0x5b, 0x56, 0x54, 0x50, 0x4b, 0x43, 0x3d, 0x38, 0x31, 0x26, + 0x19, 0x14, 0x12, 0x11, 0x10, 0x11, 0x11, 0x11, 0x10, 0x11, 0x11, 0x12, + 0x12, 0x12, 0x11, 0x11, 0x11, 0x10, 0x10, 0x12, 0x60, 0x5f, 0x5e, 0x5e, + 0x5c, 0x5c, 0x5d, 0x5e, 0x5e, 0x5d, 0x5d, 0x5e, 0x5f, 0x5f, 0x5f, 0x60, + 0x60, 0x61, 0x61, 0x61, 0x62, 0x64, 0x66, 0x66, 0x65, 0x65, 0x66, 0x66, + 0x67, 0x68, 0x69, 0x6a, 0x6a, 0x6a, 0x6b, 0x6b, 0x6b, 0x6b, 0x6a, 0x6a, + 0x6a, 0x69, 0x67, 0x66, 0x66, 0x64, 0x64, 0x64, 0x62, 0x60, 0x5e, 0x5c, + 0x5b, 0x5a, 0x58, 0x56, 0x55, 0x53, 0x54, 0x56, 0x5b, 0x62, 0x67, 0x6a, + 0x6e, 0x73, 0x7a, 0x7f, 0x82, 0x83, 0x84, 0x86, 0x86, 0x88, 0x88, 0x87, + 0x85, 0x83, 0x81, 0x81, 0x82, 0x83, 0x82, 0x83, 0x84, 0x84, 0x83, 0x83, + 0x84, 0x83, 0x82, 0x81, 0x82, 0x82, 0x83, 0x84, 0x87, 0x89, 0x8a, 0x8b, + 0x8c, 0x8f, 0x91, 0x90, 0x90, 0x8d, 0x89, 0x85, 0x83, 0x81, 0x7e, 0x7c, + 0x7c, 0x7a, 0x79, 0x79, 0x79, 0x78, 0x7a, 0x7a, 0x7c, 0x7d, 0x80, 0x81, + 0x81, 0x7e, 0x78, 0x72, 0x6b, 0x67, 0x66, 0x66, 0x71, 0x82, 0x88, 0x89, + 0x84, 0x77, 0x6b, 0x67, 0x65, 0x65, 0x65, 0x66, 0x6c, 0x6e, 0x71, 0x7b, + 0x89, 0x78, 0x70, 0x76, 0x8f, 0x96, 0xad, 0xac, 0x8f, 0x7f, 0x7b, 0x7d, + 0x80, 0x7c, 0x5f, 0x53, 0x5e, 0x6d, 0x7d, 0x73, 0x81, 0x75, 0x7a, 0x92, + 0x7d, 0x6d, 0x61, 0x5a, 0x58, 0x5f, 0x51, 0x45, 0x44, 0x4c, 0x51, 0x4f, + 0x4a, 0x43, 0x33, 0x1c, 0x1f, 0x32, 0x3d, 0x4b, 0x75, 0x93, 0x95, 0x94, + 0x95, 0x97, 0x98, 0x97, 0x99, 0x99, 0x99, 0x9a, 0x9a, 0x99, 0x98, 0x99, + 0x98, 0x96, 0x94, 0x93, 0x91, 0x8c, 0x86, 0x82, 0x7f, 0x79, 0x71, 0x68, + 0x62, 0x5f, 0x58, 0x51, 0x4d, 0x4c, 0x4c, 0x4c, 0x4d, 0x4c, 0x4b, 0x4a, + 0x4a, 0x4b, 0x4a, 0x4a, 0x4a, 0x4a, 0x4b, 0x4b, 0x4c, 0x4d, 0x4e, 0x50, + 0x50, 0x50, 0x50, 0x51, 0x52, 0x54, 0x54, 0x55, 0x57, 0x58, 0x59, 0x5b, + 0x5b, 0x5c, 0x5e, 0x60, 0x60, 0x60, 0x61, 0x62, 0x65, 0x67, 0x69, 0x6a, + 0x6b, 0x6e, 0x71, 0x73, 0x73, 0x73, 0x75, 0x77, 0x77, 0x77, 0x77, 0x76, + 0x74, 0x74, 0x74, 0x72, 0x6d, 0x6a, 0x68, 0x67, 0x64, 0x60, 0x5b, 0x56, + 0x54, 0x50, 0x4a, 0x43, 0x3d, 0x39, 0x33, 0x27, 0x19, 0x14, 0x12, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x10, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x11, 0x10, 0x10, 0x12, 0x60, 0x5e, 0x5e, 0x5d, 0x5b, 0x5c, 0x5e, 0x5f, + 0x5e, 0x5d, 0x5c, 0x5e, 0x5f, 0x5f, 0x5f, 0x60, 0x60, 0x62, 0x62, 0x62, + 0x63, 0x64, 0x66, 0x66, 0x67, 0x66, 0x66, 0x66, 0x67, 0x68, 0x69, 0x6a, + 0x6a, 0x6a, 0x6b, 0x6b, 0x6a, 0x6a, 0x6a, 0x69, 0x69, 0x69, 0x69, 0x68, + 0x67, 0x64, 0x64, 0x63, 0x62, 0x60, 0x5e, 0x5b, 0x5a, 0x59, 0x58, 0x56, + 0x54, 0x53, 0x52, 0x52, 0x57, 0x5d, 0x63, 0x67, 0x6b, 0x71, 0x77, 0x7d, + 0x81, 0x83, 0x84, 0x85, 0x87, 0x89, 0x89, 0x87, 0x84, 0x81, 0x80, 0x80, + 0x81, 0x82, 0x82, 0x82, 0x83, 0x83, 0x83, 0x83, 0x84, 0x84, 0x83, 0x82, + 0x82, 0x83, 0x84, 0x85, 0x87, 0x8a, 0x8b, 0x8c, 0x8d, 0x8f, 0x90, 0x8f, + 0x8e, 0x8c, 0x89, 0x85, 0x83, 0x81, 0x7f, 0x7c, 0x7b, 0x7a, 0x79, 0x79, + 0x79, 0x78, 0x79, 0x7a, 0x7c, 0x7e, 0x80, 0x81, 0x80, 0x7c, 0x76, 0x6f, + 0x68, 0x65, 0x63, 0x63, 0x6a, 0x79, 0x7f, 0x7f, 0x7a, 0x6e, 0x67, 0x66, + 0x66, 0x65, 0x65, 0x68, 0x6d, 0x70, 0x73, 0x7e, 0x85, 0x6c, 0x60, 0x5f, + 0x64, 0x81, 0xa8, 0xac, 0x8e, 0x76, 0x7a, 0x7f, 0x80, 0x78, 0x62, 0x58, + 0x62, 0x6f, 0x7f, 0x76, 0x85, 0x94, 0x9e, 0xa3, 0x8d, 0x75, 0x6b, 0x64, + 0x5c, 0x63, 0x5a, 0x53, 0x53, 0x58, 0x50, 0x4d, 0x4e, 0x48, 0x34, 0x1c, + 0x1f, 0x34, 0x41, 0x58, 0x87, 0x95, 0x94, 0x94, 0x94, 0x97, 0x99, 0x98, + 0x99, 0x9a, 0x99, 0x9a, 0x9a, 0x99, 0x99, 0x98, 0x97, 0x94, 0x93, 0x92, + 0x8e, 0x89, 0x84, 0x7e, 0x7a, 0x75, 0x6e, 0x65, 0x5f, 0x5b, 0x55, 0x4e, + 0x4b, 0x4b, 0x4b, 0x4b, 0x4c, 0x4b, 0x4a, 0x4a, 0x4b, 0x4b, 0x4a, 0x4b, + 0x4a, 0x4a, 0x4b, 0x4b, 0x4c, 0x4c, 0x4c, 0x4e, 0x50, 0x4f, 0x50, 0x51, + 0x52, 0x54, 0x55, 0x55, 0x55, 0x57, 0x59, 0x5a, 0x5b, 0x5c, 0x5e, 0x5e, + 0x5f, 0x61, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6b, 0x6c, 0x6d, 0x70, 0x72, + 0x72, 0x72, 0x74, 0x76, 0x75, 0x76, 0x77, 0x77, 0x75, 0x75, 0x74, 0x72, + 0x6e, 0x6b, 0x69, 0x68, 0x63, 0x5f, 0x5a, 0x56, 0x53, 0x50, 0x48, 0x43, + 0x3f, 0x3b, 0x33, 0x25, 0x1a, 0x14, 0x12, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x10, 0x11, 0x11, 0x11, 0x11, 0x12, 0x13, 0x12, 0x11, 0x11, 0x11, + 0x61, 0x5e, 0x5e, 0x5e, 0x5c, 0x5d, 0x5e, 0x5e, 0x5e, 0x5e, 0x5d, 0x5e, + 0x5e, 0x5e, 0x5e, 0x60, 0x60, 0x62, 0x62, 0x62, 0x63, 0x64, 0x65, 0x66, + 0x67, 0x67, 0x67, 0x67, 0x67, 0x68, 0x69, 0x6a, 0x6a, 0x6a, 0x6b, 0x6b, + 0x69, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x69, 0x69, 0x67, 0x65, 0x64, 0x63, + 0x62, 0x60, 0x5e, 0x5c, 0x5a, 0x59, 0x58, 0x56, 0x54, 0x52, 0x51, 0x50, + 0x54, 0x5a, 0x61, 0x65, 0x69, 0x6f, 0x75, 0x7c, 0x80, 0x82, 0x84, 0x84, + 0x87, 0x89, 0x89, 0x88, 0x84, 0x81, 0x80, 0x80, 0x81, 0x82, 0x81, 0x81, + 0x81, 0x82, 0x82, 0x83, 0x84, 0x84, 0x83, 0x81, 0x82, 0x83, 0x84, 0x86, + 0x88, 0x8a, 0x8c, 0x8c, 0x8d, 0x90, 0x90, 0x8f, 0x8e, 0x8b, 0x89, 0x85, + 0x83, 0x82, 0x80, 0x7c, 0x7b, 0x7a, 0x79, 0x78, 0x79, 0x79, 0x79, 0x7a, + 0x7c, 0x7e, 0x80, 0x80, 0x7f, 0x7b, 0x75, 0x6d, 0x67, 0x65, 0x63, 0x62, + 0x67, 0x73, 0x77, 0x77, 0x72, 0x69, 0x67, 0x6b, 0x6c, 0x6a, 0x65, 0x67, + 0x6c, 0x6f, 0x72, 0x7b, 0x7a, 0x64, 0x57, 0x4d, 0x47, 0x69, 0x8c, 0x90, + 0x79, 0x6e, 0x76, 0x79, 0x78, 0x6f, 0x60, 0x5a, 0x61, 0x6c, 0x79, 0x74, + 0x89, 0xaa, 0xb4, 0xa9, 0x8e, 0x77, 0x71, 0x6b, 0x60, 0x61, 0x5e, 0x5f, + 0x61, 0x60, 0x52, 0x4b, 0x4c, 0x47, 0x33, 0x1d, 0x1f, 0x30, 0x41, 0x62, + 0x8e, 0x95, 0x93, 0x94, 0x95, 0x98, 0x99, 0x98, 0x99, 0x9a, 0x99, 0x9a, + 0x9a, 0x99, 0x99, 0x98, 0x96, 0x94, 0x92, 0x90, 0x8d, 0x87, 0x81, 0x7c, + 0x78, 0x73, 0x6c, 0x62, 0x5d, 0x59, 0x52, 0x4d, 0x4a, 0x4a, 0x4a, 0x4a, + 0x4b, 0x4a, 0x49, 0x49, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x49, 0x4a, 0x4b, + 0x4c, 0x4c, 0x4c, 0x4d, 0x4f, 0x4f, 0x50, 0x52, 0x52, 0x53, 0x54, 0x54, + 0x54, 0x56, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5d, 0x5f, 0x61, 0x62, 0x64, + 0x66, 0x67, 0x69, 0x6a, 0x6c, 0x6d, 0x70, 0x72, 0x72, 0x72, 0x74, 0x75, + 0x74, 0x75, 0x77, 0x77, 0x76, 0x74, 0x73, 0x72, 0x6f, 0x6b, 0x69, 0x67, + 0x63, 0x5f, 0x5b, 0x56, 0x54, 0x50, 0x48, 0x42, 0x3f, 0x3c, 0x32, 0x24, + 0x1a, 0x14, 0x12, 0x11, 0x11, 0x11, 0x11, 0x10, 0x11, 0x10, 0x11, 0x11, + 0x11, 0x11, 0x12, 0x13, 0x12, 0x12, 0x11, 0x11, 0x62, 0x5f, 0x5f, 0x5f, + 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5e, 0x5e, 0x5d, 0x5e, 0x60, + 0x61, 0x62, 0x62, 0x62, 0x64, 0x64, 0x65, 0x66, 0x67, 0x67, 0x67, 0x68, + 0x68, 0x67, 0x68, 0x6a, 0x6b, 0x6b, 0x6b, 0x6b, 0x6a, 0x6a, 0x6b, 0x6c, + 0x6b, 0x6b, 0x6a, 0x69, 0x67, 0x66, 0x63, 0x62, 0x61, 0x5f, 0x5e, 0x5c, + 0x5a, 0x59, 0x58, 0x56, 0x54, 0x53, 0x52, 0x50, 0x52, 0x57, 0x5d, 0x61, + 0x66, 0x6e, 0x74, 0x7b, 0x7f, 0x81, 0x83, 0x85, 0x87, 0x89, 0x89, 0x89, + 0x86, 0x82, 0x81, 0x80, 0x81, 0x81, 0x80, 0x81, 0x81, 0x80, 0x80, 0x82, + 0x84, 0x83, 0x82, 0x81, 0x81, 0x83, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8d, + 0x8e, 0x90, 0x90, 0x8e, 0x8d, 0x8a, 0x87, 0x84, 0x83, 0x82, 0x80, 0x7d, + 0x7b, 0x79, 0x79, 0x78, 0x79, 0x79, 0x78, 0x79, 0x7b, 0x7e, 0x7f, 0x7e, + 0x7c, 0x79, 0x74, 0x6d, 0x68, 0x64, 0x62, 0x62, 0x65, 0x6b, 0x6d, 0x6b, + 0x67, 0x63, 0x6e, 0x7e, 0x84, 0x7e, 0x6b, 0x64, 0x69, 0x6d, 0x6f, 0x6f, + 0x64, 0x5b, 0x50, 0x3b, 0x2e, 0x42, 0x4e, 0x4b, 0x42, 0x5c, 0x63, 0x5e, + 0x5b, 0x59, 0x5b, 0x58, 0x5d, 0x65, 0x6c, 0x6c, 0x92, 0xbd, 0xc5, 0xad, + 0x84, 0x74, 0x75, 0x70, 0x60, 0x55, 0x59, 0x67, 0x6a, 0x64, 0x5c, 0x4b, + 0x43, 0x3b, 0x2b, 0x1f, 0x22, 0x27, 0x3b, 0x6c, 0x93, 0x95, 0x95, 0x96, + 0x97, 0x97, 0x99, 0x99, 0x9a, 0x9b, 0x99, 0x99, 0x9a, 0x9a, 0x99, 0x96, + 0x94, 0x92, 0x91, 0x8f, 0x8b, 0x84, 0x7e, 0x79, 0x75, 0x6e, 0x67, 0x5d, + 0x56, 0x53, 0x4e, 0x4b, 0x4a, 0x49, 0x49, 0x49, 0x4a, 0x49, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x49, 0x49, 0x48, 0x48, 0x4b, 0x4c, 0x4c, 0x4b, 0x4c, + 0x4f, 0x4f, 0x50, 0x53, 0x53, 0x52, 0x52, 0x53, 0x54, 0x55, 0x58, 0x59, + 0x5a, 0x5b, 0x5c, 0x5c, 0x5e, 0x61, 0x62, 0x63, 0x65, 0x67, 0x68, 0x69, + 0x6b, 0x6c, 0x6f, 0x71, 0x72, 0x74, 0x74, 0x74, 0x74, 0x74, 0x75, 0x75, + 0x75, 0x74, 0x73, 0x73, 0x70, 0x6c, 0x69, 0x67, 0x63, 0x60, 0x5c, 0x58, + 0x55, 0x50, 0x48, 0x43, 0x3f, 0x3a, 0x31, 0x23, 0x19, 0x14, 0x12, 0x11, + 0x11, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, + 0x13, 0x12, 0x11, 0x11, 0x62, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x5f, 0x5f, 0x5e, 0x5e, 0x5d, 0x5d, 0x5f, 0x60, 0x62, 0x62, 0x62, + 0x63, 0x64, 0x65, 0x66, 0x67, 0x67, 0x67, 0x68, 0x67, 0x67, 0x69, 0x6b, + 0x6b, 0x6a, 0x69, 0x69, 0x6b, 0x6b, 0x6c, 0x6c, 0x6b, 0x6a, 0x69, 0x68, + 0x67, 0x66, 0x64, 0x62, 0x62, 0x60, 0x5e, 0x5c, 0x5a, 0x58, 0x57, 0x55, + 0x54, 0x53, 0x51, 0x4f, 0x4f, 0x53, 0x58, 0x5c, 0x64, 0x6b, 0x73, 0x7a, + 0x7e, 0x80, 0x83, 0x85, 0x88, 0x89, 0x89, 0x89, 0x86, 0x83, 0x81, 0x81, + 0x80, 0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x82, 0x83, 0x84, 0x82, 0x82, + 0x83, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8d, 0x8e, 0x8e, 0x90, 0x90, 0x8e, + 0x8d, 0x8a, 0x87, 0x84, 0x82, 0x82, 0x81, 0x7e, 0x7c, 0x7a, 0x79, 0x78, + 0x78, 0x79, 0x78, 0x78, 0x7a, 0x7d, 0x7e, 0x7b, 0x79, 0x77, 0x72, 0x6d, + 0x66, 0x63, 0x61, 0x61, 0x61, 0x62, 0x61, 0x60, 0x5e, 0x66, 0x82, 0xa7, + 0xb5, 0xb0, 0x8c, 0x6a, 0x67, 0x68, 0x66, 0x5f, 0x4f, 0x56, 0x58, 0x48, + 0x22, 0x1a, 0x1b, 0x1a, 0x1d, 0x37, 0x41, 0x40, 0x3e, 0x40, 0x55, 0x55, + 0x6b, 0x74, 0x6b, 0x62, 0x94, 0xbf, 0xc8, 0xb5, 0x96, 0x70, 0x6a, 0x64, + 0x52, 0x49, 0x4a, 0x57, 0x5e, 0x67, 0x6e, 0x52, 0x3e, 0x32, 0x23, 0x1e, + 0x24, 0x28, 0x39, 0x66, 0x92, 0x96, 0x95, 0x96, 0x98, 0x99, 0x9b, 0x9a, + 0x99, 0x99, 0x99, 0x9a, 0x9a, 0x99, 0x97, 0x95, 0x94, 0x90, 0x8e, 0x8b, + 0x87, 0x7f, 0x79, 0x74, 0x6f, 0x69, 0x61, 0x57, 0x51, 0x4d, 0x49, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x49, 0x48, 0x46, 0x47, 0x46, 0x47, 0x47, 0x48, + 0x49, 0x47, 0x48, 0x4b, 0x4c, 0x4d, 0x4c, 0x4c, 0x4f, 0x50, 0x51, 0x53, + 0x53, 0x52, 0x53, 0x53, 0x55, 0x56, 0x58, 0x58, 0x59, 0x59, 0x5b, 0x5c, + 0x5e, 0x5f, 0x60, 0x61, 0x63, 0x65, 0x68, 0x6a, 0x6c, 0x6d, 0x6f, 0x71, + 0x73, 0x74, 0x74, 0x75, 0x74, 0x74, 0x76, 0x76, 0x76, 0x75, 0x74, 0x73, + 0x70, 0x6b, 0x69, 0x67, 0x65, 0x60, 0x5b, 0x58, 0x55, 0x51, 0x49, 0x43, + 0x3e, 0x3a, 0x33, 0x26, 0x1a, 0x14, 0x12, 0x11, 0x11, 0x10, 0x10, 0x11, + 0x11, 0x12, 0x12, 0x12, 0x12, 0x11, 0x13, 0x14, 0x13, 0x11, 0x11, 0x11, + 0x61, 0x61, 0x61, 0x62, 0x61, 0x60, 0x61, 0x61, 0x60, 0x5e, 0x5e, 0x5e, + 0x5e, 0x5e, 0x5d, 0x5e, 0x60, 0x61, 0x62, 0x63, 0x63, 0x63, 0x65, 0x66, + 0x68, 0x67, 0x67, 0x66, 0x67, 0x68, 0x6a, 0x6b, 0x6b, 0x6b, 0x6a, 0x6a, + 0x6c, 0x6c, 0x6c, 0x6a, 0x69, 0x6a, 0x6a, 0x69, 0x68, 0x67, 0x65, 0x64, + 0x63, 0x61, 0x5e, 0x5c, 0x5a, 0x59, 0x57, 0x56, 0x55, 0x52, 0x51, 0x4e, + 0x4e, 0x51, 0x56, 0x5a, 0x60, 0x67, 0x70, 0x77, 0x7d, 0x80, 0x83, 0x84, + 0x87, 0x89, 0x89, 0x89, 0x87, 0x84, 0x83, 0x82, 0x81, 0x7f, 0x7e, 0x7f, + 0x7f, 0x7e, 0x80, 0x82, 0x82, 0x82, 0x82, 0x82, 0x84, 0x86, 0x87, 0x88, + 0x89, 0x8c, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x8f, 0x8e, 0x8b, 0x88, 0x85, + 0x82, 0x82, 0x81, 0x7e, 0x7d, 0x7b, 0x7a, 0x79, 0x78, 0x79, 0x78, 0x79, + 0x7a, 0x7c, 0x7e, 0x7b, 0x78, 0x75, 0x71, 0x6c, 0x64, 0x5f, 0x5e, 0x5e, + 0x5e, 0x5d, 0x5b, 0x5b, 0x60, 0x6c, 0x89, 0xb2, 0xc5, 0xc6, 0xa9, 0x78, + 0x66, 0x5f, 0x58, 0x53, 0x4d, 0x57, 0x63, 0x68, 0x37, 0x19, 0x15, 0x19, + 0x24, 0x2d, 0x31, 0x33, 0x34, 0x3a, 0x45, 0x4a, 0x76, 0x89, 0x7f, 0x61, + 0x7d, 0x9a, 0xa8, 0xb4, 0xa7, 0x69, 0x54, 0x50, 0x51, 0x4c, 0x4a, 0x53, + 0x60, 0x77, 0x82, 0x5f, 0x40, 0x30, 0x21, 0x1f, 0x28, 0x30, 0x3d, 0x5d, + 0x90, 0x98, 0x96, 0x97, 0x98, 0x9a, 0x9b, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, + 0x99, 0x96, 0x95, 0x95, 0x92, 0x8d, 0x8a, 0x87, 0x82, 0x7a, 0x73, 0x6d, + 0x69, 0x63, 0x5c, 0x52, 0x4c, 0x48, 0x45, 0x47, 0x47, 0x47, 0x47, 0x47, + 0x47, 0x46, 0x46, 0x46, 0x46, 0x46, 0x47, 0x47, 0x48, 0x49, 0x49, 0x4b, + 0x4c, 0x4d, 0x4e, 0x4e, 0x50, 0x50, 0x51, 0x52, 0x53, 0x53, 0x54, 0x55, + 0x56, 0x56, 0x57, 0x59, 0x59, 0x59, 0x59, 0x5c, 0x5c, 0x5d, 0x5e, 0x61, + 0x63, 0x64, 0x67, 0x69, 0x6b, 0x6b, 0x6d, 0x70, 0x71, 0x72, 0x74, 0x75, + 0x74, 0x74, 0x75, 0x75, 0x76, 0x76, 0x75, 0x72, 0x70, 0x6b, 0x68, 0x67, + 0x64, 0x5f, 0x5b, 0x56, 0x54, 0x50, 0x4a, 0x43, 0x40, 0x3d, 0x35, 0x27, + 0x1a, 0x13, 0x11, 0x11, 0x10, 0x10, 0x11, 0x11, 0x10, 0x11, 0x12, 0x13, + 0x13, 0x12, 0x13, 0x13, 0x12, 0x12, 0x11, 0x11, 0x61, 0x62, 0x62, 0x62, + 0x62, 0x61, 0x62, 0x61, 0x60, 0x5f, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, + 0x60, 0x62, 0x62, 0x63, 0x63, 0x63, 0x65, 0x66, 0x67, 0x67, 0x67, 0x66, + 0x67, 0x69, 0x6b, 0x6b, 0x6b, 0x6b, 0x6a, 0x6a, 0x6c, 0x6c, 0x6c, 0x69, + 0x69, 0x6a, 0x6a, 0x69, 0x69, 0x67, 0x64, 0x64, 0x63, 0x61, 0x5f, 0x5c, + 0x59, 0x59, 0x57, 0x56, 0x54, 0x52, 0x50, 0x4e, 0x4d, 0x4f, 0x55, 0x59, + 0x5e, 0x65, 0x6d, 0x75, 0x7b, 0x7f, 0x82, 0x85, 0x88, 0x8a, 0x8b, 0x8a, + 0x88, 0x85, 0x84, 0x83, 0x81, 0x7e, 0x7d, 0x7e, 0x7e, 0x7e, 0x7f, 0x80, + 0x81, 0x82, 0x83, 0x82, 0x84, 0x86, 0x87, 0x88, 0x8a, 0x8d, 0x8f, 0x90, + 0x91, 0x91, 0x8f, 0x8f, 0x8d, 0x8b, 0x88, 0x84, 0x83, 0x82, 0x80, 0x7e, + 0x7c, 0x7b, 0x7a, 0x79, 0x78, 0x78, 0x78, 0x78, 0x79, 0x7b, 0x7c, 0x7b, + 0x79, 0x76, 0x71, 0x6a, 0x61, 0x5d, 0x5c, 0x5c, 0x5d, 0x5c, 0x5a, 0x5b, + 0x63, 0x6e, 0x81, 0xa3, 0xb4, 0xbc, 0xab, 0x7e, 0x65, 0x5a, 0x4e, 0x4c, + 0x4f, 0x55, 0x63, 0x79, 0x5d, 0x2d, 0x24, 0x30, 0x4a, 0x48, 0x3b, 0x35, + 0x31, 0x2f, 0x34, 0x3a, 0x5c, 0x6f, 0x73, 0x5e, 0x59, 0x62, 0x7a, 0xac, + 0xb6, 0x6d, 0x51, 0x4e, 0x55, 0x5b, 0x63, 0x79, 0x88, 0x93, 0x79, 0x52, + 0x3c, 0x2f, 0x21, 0x21, 0x2a, 0x36, 0x40, 0x58, 0x8f, 0x99, 0x97, 0x98, + 0x99, 0x9a, 0x9b, 0x9a, 0x9a, 0x9a, 0x9b, 0x9a, 0x98, 0x96, 0x94, 0x93, + 0x90, 0x8a, 0x85, 0x82, 0x7d, 0x76, 0x6f, 0x69, 0x65, 0x60, 0x58, 0x4e, + 0x48, 0x46, 0x45, 0x45, 0x45, 0x45, 0x45, 0x44, 0x45, 0x45, 0x45, 0x45, + 0x45, 0x44, 0x45, 0x46, 0x47, 0x49, 0x49, 0x49, 0x4a, 0x4b, 0x4d, 0x4e, + 0x50, 0x50, 0x51, 0x53, 0x53, 0x53, 0x54, 0x55, 0x55, 0x57, 0x58, 0x5a, + 0x5a, 0x5a, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5f, 0x62, 0x63, 0x66, 0x67, + 0x69, 0x6c, 0x6d, 0x70, 0x72, 0x73, 0x74, 0x75, 0x74, 0x74, 0x76, 0x76, + 0x76, 0x76, 0x75, 0x72, 0x70, 0x6c, 0x68, 0x67, 0x64, 0x5f, 0x5a, 0x56, + 0x53, 0x50, 0x49, 0x43, 0x3f, 0x3c, 0x34, 0x27, 0x1a, 0x12, 0x11, 0x11, + 0x10, 0x10, 0x11, 0x11, 0x10, 0x11, 0x11, 0x12, 0x12, 0x12, 0x13, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x61, 0x62, 0x63, 0x63, 0x63, 0x62, 0x61, 0x60, + 0x60, 0x5f, 0x5f, 0x5f, 0x5e, 0x5e, 0x5e, 0x5e, 0x60, 0x61, 0x62, 0x64, + 0x63, 0x63, 0x65, 0x66, 0x67, 0x67, 0x67, 0x67, 0x68, 0x69, 0x6b, 0x6b, + 0x6b, 0x6b, 0x6a, 0x6a, 0x6c, 0x6c, 0x6c, 0x69, 0x69, 0x6a, 0x69, 0x69, + 0x68, 0x67, 0x64, 0x63, 0x63, 0x61, 0x5f, 0x5c, 0x5a, 0x59, 0x58, 0x56, + 0x54, 0x52, 0x51, 0x4e, 0x4c, 0x4f, 0x54, 0x58, 0x5d, 0x64, 0x6c, 0x74, + 0x7a, 0x7d, 0x81, 0x86, 0x89, 0x8b, 0x8b, 0x8a, 0x88, 0x86, 0x84, 0x83, + 0x81, 0x7e, 0x7d, 0x7e, 0x7e, 0x7d, 0x7e, 0x7f, 0x81, 0x82, 0x82, 0x82, + 0x83, 0x85, 0x86, 0x88, 0x8a, 0x8c, 0x8f, 0x90, 0x91, 0x90, 0x8f, 0x8e, + 0x8d, 0x8b, 0x89, 0x85, 0x83, 0x82, 0x80, 0x7e, 0x7c, 0x7b, 0x7a, 0x7a, + 0x78, 0x79, 0x78, 0x77, 0x78, 0x7a, 0x7c, 0x7b, 0x79, 0x76, 0x70, 0x68, + 0x5f, 0x5c, 0x5b, 0x5c, 0x5d, 0x5c, 0x5a, 0x5c, 0x64, 0x6f, 0x79, 0x92, + 0xa1, 0xab, 0xa3, 0x7f, 0x64, 0x57, 0x4c, 0x4b, 0x50, 0x53, 0x60, 0x7b, + 0x71, 0x4d, 0x41, 0x49, 0x5f, 0x59, 0x46, 0x3a, 0x34, 0x2d, 0x30, 0x34, + 0x49, 0x57, 0x61, 0x5a, 0x54, 0x57, 0x6d, 0xa3, 0xb4, 0x73, 0x5b, 0x5c, + 0x67, 0x72, 0x7d, 0x90, 0x98, 0x92, 0x67, 0x47, 0x37, 0x2d, 0x22, 0x23, + 0x2b, 0x3a, 0x42, 0x57, 0x8e, 0x9a, 0x98, 0x99, 0x9a, 0x9b, 0x9b, 0x9a, + 0x9a, 0x9a, 0x9b, 0x9a, 0x98, 0x96, 0x94, 0x92, 0x8e, 0x87, 0x82, 0x7f, + 0x7b, 0x73, 0x6d, 0x66, 0x62, 0x5d, 0x54, 0x4b, 0x47, 0x45, 0x45, 0x45, + 0x44, 0x45, 0x45, 0x43, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x46, + 0x46, 0x49, 0x49, 0x49, 0x4a, 0x4b, 0x4d, 0x4e, 0x50, 0x50, 0x51, 0x52, + 0x53, 0x53, 0x54, 0x55, 0x55, 0x57, 0x59, 0x5a, 0x5a, 0x59, 0x58, 0x59, + 0x5a, 0x5b, 0x5c, 0x5e, 0x61, 0x63, 0x65, 0x67, 0x68, 0x6c, 0x6d, 0x70, + 0x72, 0x73, 0x74, 0x74, 0x74, 0x74, 0x76, 0x76, 0x77, 0x76, 0x75, 0x72, + 0x70, 0x6d, 0x69, 0x67, 0x64, 0x5f, 0x5b, 0x57, 0x54, 0x50, 0x49, 0x44, + 0x3f, 0x3b, 0x34, 0x27, 0x19, 0x13, 0x11, 0x11, 0x10, 0x10, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x12, 0x12, 0x11, 0x12, 0x11, 0x11, 0x11, 0x10, 0x11, + 0x63, 0x62, 0x63, 0x63, 0x63, 0x62, 0x60, 0x60, 0x5f, 0x5e, 0x5f, 0x5f, + 0x5f, 0x5e, 0x5e, 0x5e, 0x60, 0x61, 0x62, 0x63, 0x64, 0x64, 0x65, 0x66, + 0x67, 0x66, 0x66, 0x67, 0x68, 0x68, 0x6a, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, + 0x6c, 0x6c, 0x6b, 0x69, 0x68, 0x69, 0x69, 0x68, 0x68, 0x67, 0x65, 0x63, + 0x63, 0x61, 0x5f, 0x5d, 0x5b, 0x5a, 0x57, 0x55, 0x54, 0x53, 0x51, 0x4d, + 0x4c, 0x4f, 0x53, 0x57, 0x5c, 0x63, 0x6a, 0x73, 0x78, 0x7c, 0x81, 0x86, + 0x89, 0x8b, 0x8b, 0x8b, 0x89, 0x86, 0x85, 0x83, 0x81, 0x7e, 0x7c, 0x7b, + 0x7c, 0x7d, 0x7d, 0x7e, 0x80, 0x81, 0x82, 0x82, 0x83, 0x84, 0x85, 0x87, + 0x8a, 0x8d, 0x8f, 0x8f, 0x90, 0x90, 0x8e, 0x8e, 0x8d, 0x8c, 0x89, 0x86, + 0x83, 0x81, 0x80, 0x7e, 0x7c, 0x7a, 0x7a, 0x7a, 0x78, 0x79, 0x78, 0x77, + 0x77, 0x79, 0x7b, 0x7a, 0x79, 0x76, 0x6e, 0x65, 0x5c, 0x59, 0x59, 0x5b, + 0x5c, 0x5b, 0x5a, 0x5d, 0x66, 0x70, 0x72, 0x7d, 0x85, 0x91, 0x96, 0x80, + 0x66, 0x58, 0x4f, 0x51, 0x53, 0x53, 0x5c, 0x72, 0x7d, 0x7f, 0x76, 0x70, + 0x6c, 0x62, 0x51, 0x45, 0x3e, 0x36, 0x38, 0x35, 0x39, 0x3f, 0x49, 0x53, + 0x64, 0x6f, 0x7b, 0x92, 0x99, 0x73, 0x6d, 0x76, 0x8b, 0x93, 0x94, 0x92, + 0x89, 0x70, 0x48, 0x3c, 0x2f, 0x28, 0x25, 0x26, 0x2e, 0x3f, 0x48, 0x56, + 0x8c, 0x9a, 0x9a, 0x9a, 0x9b, 0x9c, 0x9c, 0x9b, 0x9c, 0x9c, 0x9b, 0x9a, + 0x97, 0x95, 0x93, 0x90, 0x8b, 0x84, 0x7f, 0x7c, 0x78, 0x71, 0x69, 0x61, + 0x5d, 0x57, 0x4e, 0x46, 0x45, 0x44, 0x44, 0x44, 0x43, 0x44, 0x44, 0x43, + 0x43, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x46, 0x47, 0x48, 0x48, 0x49, + 0x4a, 0x4b, 0x4d, 0x4e, 0x50, 0x50, 0x51, 0x52, 0x52, 0x53, 0x55, 0x55, + 0x55, 0x58, 0x59, 0x59, 0x58, 0x57, 0x57, 0x58, 0x59, 0x5b, 0x5b, 0x5d, + 0x61, 0x63, 0x66, 0x67, 0x68, 0x6c, 0x6e, 0x70, 0x72, 0x73, 0x74, 0x73, + 0x74, 0x74, 0x76, 0x77, 0x77, 0x76, 0x75, 0x72, 0x6f, 0x6d, 0x69, 0x68, + 0x64, 0x60, 0x5c, 0x58, 0x55, 0x50, 0x49, 0x43, 0x3f, 0x3b, 0x34, 0x28, + 0x1a, 0x13, 0x11, 0x11, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x12, + 0x12, 0x11, 0x12, 0x11, 0x11, 0x11, 0x11, 0x11, 0x62, 0x62, 0x63, 0x63, + 0x62, 0x61, 0x60, 0x60, 0x60, 0x5f, 0x5f, 0x5f, 0x60, 0x60, 0x60, 0x5f, + 0x60, 0x61, 0x62, 0x62, 0x64, 0x64, 0x64, 0x65, 0x66, 0x66, 0x66, 0x68, + 0x68, 0x67, 0x69, 0x6b, 0x6a, 0x6b, 0x6c, 0x6c, 0x6c, 0x6c, 0x6b, 0x6a, + 0x69, 0x6a, 0x69, 0x68, 0x68, 0x68, 0x67, 0x64, 0x63, 0x62, 0x60, 0x5d, + 0x5b, 0x5a, 0x58, 0x56, 0x53, 0x53, 0x52, 0x4f, 0x4c, 0x4e, 0x54, 0x59, + 0x5e, 0x64, 0x6a, 0x72, 0x78, 0x7b, 0x81, 0x86, 0x88, 0x8a, 0x8a, 0x8b, + 0x89, 0x87, 0x85, 0x84, 0x82, 0x7e, 0x7b, 0x7a, 0x7b, 0x7c, 0x7c, 0x7e, + 0x7f, 0x80, 0x80, 0x81, 0x83, 0x83, 0x84, 0x87, 0x8b, 0x8e, 0x90, 0x90, + 0x91, 0x90, 0x8e, 0x8d, 0x8c, 0x8b, 0x88, 0x86, 0x84, 0x82, 0x81, 0x7f, + 0x7d, 0x7c, 0x7a, 0x7a, 0x78, 0x79, 0x79, 0x79, 0x78, 0x79, 0x7c, 0x7b, + 0x7a, 0x76, 0x6f, 0x64, 0x5b, 0x59, 0x5a, 0x5c, 0x5d, 0x5c, 0x5b, 0x5e, + 0x67, 0x72, 0x73, 0x77, 0x7d, 0x88, 0x97, 0x90, 0x73, 0x63, 0x5c, 0x60, + 0x5e, 0x5c, 0x5e, 0x67, 0x7b, 0x80, 0x86, 0x84, 0x76, 0x64, 0x50, 0x48, + 0x47, 0x4a, 0x48, 0x40, 0x3c, 0x3d, 0x43, 0x45, 0x53, 0x6c, 0x76, 0x78, + 0x78, 0x5e, 0x57, 0x62, 0x7a, 0x72, 0x66, 0x5b, 0x54, 0x49, 0x3a, 0x34, + 0x23, 0x1e, 0x26, 0x2b, 0x32, 0x42, 0x49, 0x55, 0x85, 0x9a, 0x9b, 0x9b, + 0x9b, 0x9c, 0x9c, 0x9d, 0x9c, 0x9b, 0x99, 0x98, 0x95, 0x92, 0x90, 0x8c, + 0x87, 0x81, 0x7b, 0x77, 0x72, 0x6c, 0x63, 0x5c, 0x58, 0x50, 0x48, 0x44, + 0x43, 0x43, 0x43, 0x42, 0x43, 0x43, 0x43, 0x43, 0x43, 0x44, 0x44, 0x44, + 0x45, 0x45, 0x46, 0x47, 0x49, 0x4a, 0x4a, 0x4a, 0x4b, 0x4c, 0x4e, 0x4f, + 0x51, 0x52, 0x52, 0x52, 0x52, 0x56, 0x57, 0x57, 0x56, 0x57, 0x59, 0x57, + 0x56, 0x56, 0x57, 0x59, 0x5a, 0x5b, 0x5d, 0x5e, 0x5f, 0x62, 0x65, 0x66, + 0x67, 0x69, 0x6e, 0x70, 0x71, 0x71, 0x73, 0x73, 0x74, 0x74, 0x75, 0x76, + 0x76, 0x76, 0x75, 0x74, 0x71, 0x6e, 0x6a, 0x67, 0x63, 0x60, 0x5c, 0x58, + 0x56, 0x50, 0x4a, 0x43, 0x40, 0x3c, 0x35, 0x29, 0x1a, 0x13, 0x12, 0x12, + 0x11, 0x10, 0x10, 0x11, 0x12, 0x12, 0x11, 0x12, 0x12, 0x12, 0x12, 0x11, + 0x11, 0x11, 0x12, 0x11, 0x60, 0x61, 0x63, 0x63, 0x61, 0x61, 0x62, 0x61, + 0x61, 0x61, 0x61, 0x5f, 0x60, 0x60, 0x5f, 0x60, 0x61, 0x61, 0x61, 0x62, + 0x63, 0x64, 0x65, 0x65, 0x64, 0x66, 0x67, 0x68, 0x68, 0x68, 0x69, 0x6a, + 0x6a, 0x6a, 0x6b, 0x6b, 0x6c, 0x6c, 0x6b, 0x6b, 0x6b, 0x6b, 0x6a, 0x6a, + 0x69, 0x69, 0x67, 0x65, 0x63, 0x61, 0x5f, 0x5c, 0x5a, 0x59, 0x58, 0x55, + 0x53, 0x53, 0x52, 0x50, 0x4e, 0x50, 0x56, 0x5a, 0x5f, 0x65, 0x6a, 0x72, + 0x77, 0x7a, 0x80, 0x85, 0x88, 0x8a, 0x8b, 0x8c, 0x8a, 0x88, 0x86, 0x85, + 0x82, 0x7e, 0x7c, 0x7b, 0x7b, 0x7c, 0x7c, 0x7d, 0x7d, 0x7e, 0x7f, 0x81, + 0x83, 0x83, 0x84, 0x87, 0x8a, 0x8e, 0x8f, 0x90, 0x91, 0x91, 0x8e, 0x8d, + 0x8c, 0x8b, 0x88, 0x86, 0x85, 0x84, 0x83, 0x80, 0x7e, 0x7d, 0x7c, 0x7b, + 0x78, 0x78, 0x79, 0x79, 0x78, 0x79, 0x7c, 0x7b, 0x7a, 0x76, 0x6e, 0x63, + 0x5b, 0x5b, 0x5d, 0x60, 0x60, 0x5c, 0x5a, 0x5e, 0x69, 0x72, 0x75, 0x7c, + 0x83, 0x91, 0xa1, 0xa2, 0x84, 0x72, 0x69, 0x6d, 0x6c, 0x6a, 0x67, 0x63, + 0x75, 0x88, 0x8e, 0x8a, 0x7d, 0x6a, 0x41, 0x36, 0x40, 0x57, 0x53, 0x47, + 0x44, 0x43, 0x43, 0x3d, 0x3c, 0x42, 0x46, 0x50, 0x68, 0x4c, 0x41, 0x43, + 0x4a, 0x4a, 0x46, 0x46, 0x46, 0x42, 0x38, 0x2e, 0x1d, 0x1b, 0x28, 0x34, + 0x3b, 0x43, 0x47, 0x51, 0x7d, 0x9b, 0x9d, 0x9c, 0x9d, 0x9e, 0x9e, 0x9d, + 0x9c, 0x9b, 0x98, 0x96, 0x92, 0x8e, 0x8b, 0x89, 0x84, 0x7c, 0x76, 0x72, + 0x6c, 0x64, 0x5b, 0x55, 0x51, 0x4a, 0x44, 0x43, 0x43, 0x43, 0x42, 0x41, + 0x42, 0x42, 0x42, 0x43, 0x43, 0x43, 0x43, 0x43, 0x45, 0x45, 0x45, 0x47, + 0x49, 0x4a, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4f, 0x50, 0x51, 0x52, 0x53, + 0x55, 0x56, 0x56, 0x57, 0x57, 0x56, 0x58, 0x58, 0x57, 0x57, 0x57, 0x59, + 0x5a, 0x5b, 0x5c, 0x5c, 0x5f, 0x63, 0x66, 0x67, 0x67, 0x69, 0x6d, 0x70, + 0x70, 0x71, 0x73, 0x73, 0x74, 0x74, 0x74, 0x76, 0x76, 0x76, 0x74, 0x73, + 0x71, 0x6e, 0x6a, 0x67, 0x63, 0x60, 0x5c, 0x58, 0x56, 0x50, 0x49, 0x44, + 0x40, 0x3d, 0x35, 0x29, 0x1a, 0x12, 0x11, 0x11, 0x11, 0x10, 0x10, 0x11, + 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x11, 0x12, 0x12, 0x12, 0x12, + 0x60, 0x60, 0x61, 0x62, 0x62, 0x63, 0x63, 0x62, 0x61, 0x60, 0x60, 0x5f, + 0x5f, 0x5f, 0x60, 0x60, 0x60, 0x61, 0x62, 0x61, 0x62, 0x65, 0x65, 0x65, + 0x65, 0x66, 0x67, 0x68, 0x68, 0x67, 0x69, 0x69, 0x69, 0x69, 0x6a, 0x6a, + 0x6c, 0x6c, 0x6b, 0x6a, 0x6a, 0x6a, 0x6b, 0x6b, 0x69, 0x69, 0x66, 0x65, + 0x64, 0x62, 0x60, 0x5d, 0x5b, 0x59, 0x58, 0x56, 0x53, 0x53, 0x52, 0x50, + 0x4e, 0x52, 0x58, 0x5c, 0x62, 0x67, 0x6b, 0x72, 0x77, 0x7a, 0x7f, 0x85, + 0x89, 0x8a, 0x8b, 0x8c, 0x8b, 0x87, 0x85, 0x84, 0x82, 0x7f, 0x7d, 0x7c, + 0x7b, 0x7b, 0x7b, 0x7b, 0x7c, 0x7d, 0x7e, 0x80, 0x82, 0x83, 0x85, 0x86, + 0x8a, 0x8d, 0x8e, 0x8f, 0x8f, 0x8f, 0x8e, 0x8d, 0x8c, 0x8a, 0x88, 0x86, + 0x85, 0x84, 0x83, 0x80, 0x7e, 0x7d, 0x7c, 0x7b, 0x78, 0x78, 0x79, 0x79, + 0x79, 0x79, 0x7b, 0x7b, 0x7a, 0x76, 0x6f, 0x64, 0x5c, 0x5f, 0x64, 0x6b, + 0x65, 0x5c, 0x5a, 0x5f, 0x69, 0x72, 0x76, 0x80, 0x88, 0x93, 0xa2, 0xa6, + 0x8e, 0x7d, 0x71, 0x77, 0x76, 0x74, 0x70, 0x64, 0x59, 0x66, 0x79, 0x80, + 0x77, 0x4e, 0x3f, 0x44, 0x4f, 0x62, 0x5b, 0x4b, 0x47, 0x46, 0x41, 0x3b, + 0x37, 0x39, 0x41, 0x51, 0x54, 0x3f, 0x3d, 0x3e, 0x40, 0x48, 0x4b, 0x46, + 0x45, 0x45, 0x39, 0x27, 0x1a, 0x19, 0x29, 0x40, 0x48, 0x49, 0x49, 0x50, + 0x78, 0x9b, 0x9e, 0x9d, 0x9e, 0x9e, 0x9e, 0x9d, 0x9c, 0x9a, 0x98, 0x94, + 0x8f, 0x8b, 0x88, 0x86, 0x7f, 0x77, 0x72, 0x6e, 0x69, 0x60, 0x56, 0x50, + 0x4c, 0x45, 0x42, 0x41, 0x42, 0x42, 0x43, 0x42, 0x41, 0x41, 0x42, 0x42, + 0x43, 0x44, 0x42, 0x42, 0x43, 0x44, 0x46, 0x48, 0x48, 0x48, 0x49, 0x4a, + 0x4b, 0x4b, 0x4d, 0x4e, 0x51, 0x52, 0x52, 0x53, 0x56, 0x57, 0x57, 0x58, + 0x58, 0x57, 0x59, 0x59, 0x59, 0x58, 0x58, 0x5a, 0x5a, 0x5c, 0x5d, 0x5d, + 0x5f, 0x63, 0x65, 0x67, 0x68, 0x6b, 0x6d, 0x6e, 0x6f, 0x70, 0x72, 0x73, + 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x73, 0x71, 0x70, 0x6c, 0x6a, 0x68, + 0x63, 0x5f, 0x5b, 0x58, 0x55, 0x50, 0x49, 0x44, 0x40, 0x3d, 0x36, 0x29, + 0x1b, 0x14, 0x11, 0x11, 0x11, 0x10, 0x10, 0x11, 0x12, 0x12, 0x11, 0x11, + 0x12, 0x13, 0x13, 0x12, 0x13, 0x13, 0x12, 0x13, 0x60, 0x5f, 0x61, 0x62, + 0x63, 0x64, 0x64, 0x62, 0x61, 0x60, 0x60, 0x5e, 0x5e, 0x5f, 0x60, 0x60, + 0x60, 0x61, 0x62, 0x61, 0x62, 0x64, 0x64, 0x64, 0x64, 0x65, 0x66, 0x68, + 0x68, 0x68, 0x68, 0x6a, 0x69, 0x69, 0x69, 0x6a, 0x6b, 0x6c, 0x6b, 0x6a, + 0x69, 0x6a, 0x6a, 0x6a, 0x69, 0x68, 0x66, 0x65, 0x65, 0x63, 0x60, 0x5e, + 0x5a, 0x59, 0x59, 0x56, 0x54, 0x53, 0x52, 0x50, 0x4f, 0x54, 0x59, 0x5d, + 0x63, 0x68, 0x6b, 0x72, 0x76, 0x79, 0x7f, 0x84, 0x88, 0x8a, 0x8b, 0x8c, + 0x8b, 0x87, 0x85, 0x83, 0x81, 0x80, 0x7e, 0x7d, 0x7b, 0x7a, 0x7b, 0x7b, + 0x7c, 0x7c, 0x7d, 0x80, 0x82, 0x83, 0x84, 0x85, 0x8a, 0x8d, 0x8d, 0x8e, + 0x8f, 0x8f, 0x8e, 0x8d, 0x8c, 0x8a, 0x88, 0x87, 0x85, 0x84, 0x83, 0x81, + 0x7f, 0x7d, 0x7c, 0x7a, 0x79, 0x78, 0x78, 0x79, 0x78, 0x78, 0x7a, 0x7b, + 0x7b, 0x76, 0x6e, 0x64, 0x5e, 0x67, 0x70, 0x78, 0x6c, 0x5d, 0x5b, 0x5f, + 0x6a, 0x72, 0x77, 0x83, 0x89, 0x90, 0x9b, 0xa1, 0x90, 0x82, 0x77, 0x7d, + 0x7a, 0x75, 0x71, 0x68, 0x59, 0x56, 0x60, 0x66, 0x62, 0x44, 0x4c, 0x5a, + 0x62, 0x68, 0x5e, 0x4c, 0x49, 0x47, 0x42, 0x3b, 0x37, 0x38, 0x42, 0x56, + 0x4a, 0x37, 0x3a, 0x3e, 0x41, 0x49, 0x4e, 0x47, 0x44, 0x43, 0x39, 0x24, + 0x17, 0x19, 0x29, 0x46, 0x50, 0x50, 0x4e, 0x51, 0x76, 0x9c, 0x9f, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9d, 0x9b, 0x9a, 0x97, 0x93, 0x8d, 0x89, 0x87, 0x83, + 0x7d, 0x74, 0x6f, 0x6b, 0x66, 0x5d, 0x53, 0x4d, 0x49, 0x43, 0x41, 0x40, + 0x42, 0x42, 0x42, 0x41, 0x41, 0x41, 0x41, 0x42, 0x43, 0x44, 0x42, 0x42, + 0x43, 0x44, 0x46, 0x48, 0x48, 0x48, 0x49, 0x4a, 0x4b, 0x4b, 0x4d, 0x4f, + 0x52, 0x52, 0x52, 0x53, 0x56, 0x57, 0x58, 0x58, 0x58, 0x58, 0x5a, 0x59, + 0x58, 0x58, 0x58, 0x5a, 0x5b, 0x5c, 0x5d, 0x5d, 0x60, 0x63, 0x65, 0x66, + 0x69, 0x6c, 0x6d, 0x6e, 0x6f, 0x6f, 0x72, 0x72, 0x74, 0x75, 0x74, 0x74, + 0x74, 0x74, 0x73, 0x71, 0x6f, 0x6c, 0x6a, 0x68, 0x63, 0x5f, 0x5b, 0x57, + 0x55, 0x50, 0x49, 0x44, 0x40, 0x3d, 0x36, 0x29, 0x1c, 0x14, 0x12, 0x11, + 0x11, 0x10, 0x10, 0x11, 0x12, 0x12, 0x12, 0x11, 0x12, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x12, 0x13, 0x60, 0x60, 0x61, 0x61, 0x63, 0x64, 0x63, 0x61, + 0x60, 0x60, 0x60, 0x5e, 0x5d, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x61, + 0x62, 0x62, 0x62, 0x62, 0x63, 0x65, 0x66, 0x67, 0x67, 0x67, 0x68, 0x6a, + 0x6a, 0x6a, 0x69, 0x6a, 0x6c, 0x6c, 0x6b, 0x6a, 0x69, 0x6a, 0x6a, 0x6a, + 0x69, 0x69, 0x66, 0x65, 0x64, 0x62, 0x60, 0x5d, 0x5b, 0x59, 0x59, 0x57, + 0x54, 0x53, 0x52, 0x50, 0x4f, 0x55, 0x5c, 0x5f, 0x63, 0x68, 0x6c, 0x71, + 0x75, 0x78, 0x7e, 0x83, 0x87, 0x88, 0x89, 0x8b, 0x8a, 0x87, 0x84, 0x83, + 0x82, 0x80, 0x7e, 0x7e, 0x7d, 0x7a, 0x7a, 0x7a, 0x7c, 0x7d, 0x7e, 0x80, + 0x82, 0x83, 0x84, 0x86, 0x8a, 0x8d, 0x8d, 0x8e, 0x8f, 0x8e, 0x8f, 0x8d, + 0x8c, 0x8a, 0x88, 0x87, 0x85, 0x84, 0x83, 0x80, 0x7e, 0x7d, 0x7d, 0x7b, + 0x7a, 0x79, 0x79, 0x79, 0x78, 0x78, 0x7b, 0x7c, 0x7b, 0x76, 0x6e, 0x64, + 0x67, 0x7d, 0x8b, 0x91, 0x7b, 0x61, 0x5d, 0x61, 0x6c, 0x74, 0x7b, 0x8a, + 0x8e, 0x88, 0x87, 0x91, 0x8b, 0x84, 0x7c, 0x84, 0x7b, 0x73, 0x71, 0x72, + 0x7a, 0x63, 0x4c, 0x44, 0x47, 0x54, 0x6f, 0x79, 0x79, 0x6e, 0x5f, 0x51, + 0x55, 0x55, 0x4b, 0x40, 0x39, 0x38, 0x41, 0x53, 0x42, 0x30, 0x35, 0x3a, + 0x3f, 0x46, 0x4a, 0x44, 0x40, 0x3d, 0x39, 0x21, 0x16, 0x18, 0x29, 0x4a, + 0x59, 0x5a, 0x56, 0x54, 0x76, 0x9d, 0xa0, 0x9e, 0x9e, 0x9e, 0x9c, 0x9c, + 0x9a, 0x98, 0x94, 0x91, 0x8b, 0x88, 0x84, 0x80, 0x77, 0x6f, 0x6a, 0x67, + 0x61, 0x58, 0x4f, 0x49, 0x45, 0x41, 0x40, 0x41, 0x40, 0x41, 0x41, 0x40, + 0x41, 0x41, 0x41, 0x42, 0x43, 0x43, 0x42, 0x42, 0x43, 0x45, 0x46, 0x48, + 0x49, 0x49, 0x4a, 0x49, 0x4a, 0x4b, 0x4d, 0x50, 0x52, 0x52, 0x52, 0x53, + 0x55, 0x57, 0x57, 0x58, 0x58, 0x58, 0x59, 0x59, 0x59, 0x59, 0x59, 0x5b, + 0x5b, 0x5d, 0x5f, 0x60, 0x61, 0x63, 0x63, 0x65, 0x68, 0x6b, 0x6c, 0x6e, + 0x6e, 0x6f, 0x72, 0x72, 0x74, 0x75, 0x75, 0x75, 0x75, 0x74, 0x74, 0x71, + 0x6f, 0x6c, 0x6a, 0x68, 0x63, 0x5f, 0x5a, 0x58, 0x55, 0x51, 0x4a, 0x44, + 0x41, 0x3d, 0x36, 0x2a, 0x1d, 0x16, 0x12, 0x11, 0x10, 0x10, 0x10, 0x11, + 0x11, 0x12, 0x13, 0x12, 0x12, 0x13, 0x13, 0x12, 0x13, 0x13, 0x12, 0x13, + 0x60, 0x60, 0x60, 0x61, 0x62, 0x63, 0x62, 0x60, 0x60, 0x61, 0x61, 0x5e, + 0x5d, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x61, 0x62, 0x61, 0x62, 0x62, + 0x63, 0x64, 0x65, 0x66, 0x66, 0x66, 0x69, 0x6a, 0x6a, 0x6b, 0x6b, 0x6b, + 0x6c, 0x6c, 0x6b, 0x6b, 0x6b, 0x6b, 0x6a, 0x6a, 0x69, 0x69, 0x68, 0x66, + 0x65, 0x62, 0x61, 0x5e, 0x5b, 0x5a, 0x58, 0x56, 0x54, 0x52, 0x50, 0x4f, + 0x51, 0x59, 0x5f, 0x62, 0x65, 0x6b, 0x6f, 0x70, 0x73, 0x76, 0x7c, 0x82, + 0x85, 0x87, 0x88, 0x89, 0x8a, 0x87, 0x85, 0x84, 0x82, 0x80, 0x80, 0x7f, + 0x7d, 0x7c, 0x7b, 0x7b, 0x7b, 0x7c, 0x7e, 0x7f, 0x82, 0x83, 0x84, 0x86, + 0x8a, 0x8c, 0x8e, 0x8e, 0x8f, 0x8f, 0x8d, 0x8c, 0x8b, 0x8b, 0x89, 0x87, + 0x86, 0x85, 0x83, 0x80, 0x7e, 0x7d, 0x7d, 0x7c, 0x7a, 0x78, 0x78, 0x78, + 0x78, 0x78, 0x7a, 0x7c, 0x7b, 0x76, 0x6e, 0x69, 0x7a, 0x99, 0xa8, 0xa9, + 0x8a, 0x67, 0x5f, 0x63, 0x6f, 0x7e, 0x8e, 0x9c, 0x98, 0x7e, 0x6c, 0x78, + 0x7e, 0x7f, 0x82, 0x8b, 0x81, 0x79, 0x76, 0x7d, 0x94, 0x95, 0x84, 0x7c, + 0x79, 0x7f, 0x7b, 0x76, 0x73, 0x6c, 0x67, 0x6a, 0x7b, 0x79, 0x5e, 0x49, + 0x40, 0x3e, 0x3e, 0x3e, 0x33, 0x2c, 0x33, 0x36, 0x37, 0x3c, 0x40, 0x40, + 0x3e, 0x3b, 0x36, 0x1e, 0x19, 0x1f, 0x32, 0x4e, 0x5a, 0x5d, 0x5a, 0x59, + 0x7f, 0x9e, 0xa1, 0x9f, 0x9e, 0x9e, 0x9d, 0x9a, 0x98, 0x96, 0x92, 0x8d, + 0x87, 0x83, 0x80, 0x7a, 0x72, 0x6a, 0x64, 0x60, 0x5a, 0x51, 0x49, 0x45, + 0x42, 0x3f, 0x3f, 0x40, 0x3f, 0x40, 0x40, 0x40, 0x41, 0x41, 0x41, 0x42, + 0x43, 0x43, 0x42, 0x41, 0x42, 0x44, 0x45, 0x47, 0x49, 0x49, 0x4b, 0x4b, + 0x4c, 0x4d, 0x4e, 0x50, 0x52, 0x53, 0x53, 0x53, 0x56, 0x57, 0x57, 0x58, + 0x59, 0x58, 0x58, 0x59, 0x5a, 0x5a, 0x5a, 0x5c, 0x5d, 0x5f, 0x60, 0x61, + 0x62, 0x63, 0x63, 0x64, 0x67, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e, 0x72, 0x73, + 0x73, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x73, 0x70, 0x6c, 0x6a, 0x68, + 0x64, 0x5f, 0x5b, 0x58, 0x55, 0x50, 0x49, 0x44, 0x40, 0x3c, 0x35, 0x29, + 0x1c, 0x15, 0x11, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x13, 0x13, 0x13, 0x13, 0x12, 0x11, 0x13, 0x5e, 0x5f, 0x5f, 0x5f, + 0x60, 0x61, 0x62, 0x60, 0x60, 0x61, 0x61, 0x5f, 0x5d, 0x5e, 0x5f, 0x5f, + 0x60, 0x61, 0x61, 0x60, 0x61, 0x61, 0x63, 0x63, 0x64, 0x63, 0x64, 0x64, + 0x65, 0x66, 0x68, 0x68, 0x69, 0x6a, 0x6b, 0x6b, 0x6c, 0x6c, 0x6c, 0x6c, + 0x6c, 0x6b, 0x69, 0x69, 0x69, 0x6a, 0x69, 0x68, 0x67, 0x64, 0x61, 0x5d, + 0x5a, 0x59, 0x57, 0x55, 0x52, 0x50, 0x50, 0x50, 0x53, 0x5d, 0x62, 0x64, + 0x68, 0x6d, 0x6f, 0x71, 0x74, 0x76, 0x7a, 0x80, 0x83, 0x86, 0x87, 0x88, + 0x89, 0x88, 0x86, 0x84, 0x81, 0x80, 0x80, 0x7f, 0x7e, 0x7c, 0x7c, 0x7b, + 0x7b, 0x7c, 0x7e, 0x7e, 0x80, 0x83, 0x83, 0x85, 0x89, 0x8b, 0x8d, 0x8d, + 0x8e, 0x8d, 0x8d, 0x8b, 0x8b, 0x8c, 0x8a, 0x87, 0x87, 0x86, 0x84, 0x80, + 0x7e, 0x7e, 0x7e, 0x7d, 0x7a, 0x7a, 0x78, 0x78, 0x78, 0x78, 0x7a, 0x7c, + 0x7b, 0x76, 0x6e, 0x6c, 0x83, 0xa1, 0xae, 0xab, 0x8f, 0x6d, 0x63, 0x66, + 0x72, 0x8a, 0xa4, 0xa7, 0x97, 0x72, 0x62, 0x70, 0x75, 0x79, 0x84, 0x90, + 0x8a, 0x83, 0x80, 0x82, 0x99, 0xa4, 0xa3, 0x9f, 0x96, 0x8a, 0x7e, 0x78, + 0x76, 0x78, 0x84, 0x7b, 0x75, 0x6f, 0x63, 0x52, 0x54, 0x51, 0x4c, 0x41, + 0x36, 0x32, 0x34, 0x32, 0x2e, 0x33, 0x3c, 0x3d, 0x3d, 0x3c, 0x32, 0x1e, + 0x1f, 0x29, 0x3f, 0x54, 0x5b, 0x59, 0x57, 0x5f, 0x90, 0xa2, 0xa1, 0x9e, + 0x9d, 0x9e, 0x9b, 0x97, 0x95, 0x93, 0x8f, 0x88, 0x80, 0x7d, 0x79, 0x74, + 0x6b, 0x63, 0x5c, 0x58, 0x53, 0x4b, 0x45, 0x42, 0x41, 0x3f, 0x3e, 0x3e, + 0x3d, 0x3d, 0x3e, 0x41, 0x42, 0x41, 0x41, 0x41, 0x43, 0x43, 0x42, 0x41, + 0x42, 0x44, 0x45, 0x47, 0x48, 0x48, 0x4a, 0x4c, 0x4d, 0x4e, 0x4e, 0x50, + 0x52, 0x54, 0x54, 0x55, 0x55, 0x57, 0x57, 0x58, 0x59, 0x59, 0x59, 0x5b, + 0x5b, 0x5b, 0x5b, 0x5d, 0x5e, 0x5e, 0x5f, 0x61, 0x62, 0x63, 0x65, 0x66, + 0x69, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e, 0x72, 0x73, 0x72, 0x73, 0x74, 0x73, + 0x73, 0x74, 0x74, 0x73, 0x70, 0x6b, 0x6a, 0x69, 0x65, 0x61, 0x5c, 0x58, + 0x54, 0x4e, 0x48, 0x43, 0x3f, 0x3b, 0x34, 0x29, 0x1c, 0x15, 0x12, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x11, 0x11, 0x11, 0x12, 0x12, 0x13, + 0x13, 0x12, 0x11, 0x13, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x61, 0x62, 0x60, + 0x60, 0x61, 0x61, 0x5f, 0x5e, 0x5e, 0x5f, 0x5f, 0x5f, 0x60, 0x60, 0x61, + 0x61, 0x61, 0x63, 0x63, 0x63, 0x63, 0x63, 0x64, 0x65, 0x67, 0x67, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6b, 0x6a, 0x69, + 0x69, 0x6a, 0x69, 0x68, 0x67, 0x64, 0x61, 0x5e, 0x5a, 0x58, 0x57, 0x55, + 0x51, 0x50, 0x50, 0x51, 0x56, 0x5f, 0x64, 0x66, 0x69, 0x6e, 0x71, 0x73, + 0x75, 0x77, 0x7a, 0x7f, 0x82, 0x85, 0x85, 0x87, 0x89, 0x88, 0x85, 0x83, + 0x81, 0x80, 0x7f, 0x7f, 0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x7c, 0x7d, 0x7e, + 0x80, 0x82, 0x84, 0x85, 0x88, 0x8a, 0x8c, 0x8e, 0x8e, 0x8e, 0x8d, 0x8c, + 0x8c, 0x8c, 0x8b, 0x89, 0x89, 0x88, 0x86, 0x82, 0x80, 0x7e, 0x7e, 0x7d, + 0x7b, 0x79, 0x79, 0x78, 0x78, 0x78, 0x7a, 0x7c, 0x7c, 0x77, 0x6f, 0x6e, + 0x84, 0xa0, 0xaa, 0xa4, 0x87, 0x6e, 0x65, 0x67, 0x75, 0x94, 0xab, 0xa1, + 0x89, 0x62, 0x5e, 0x70, 0x71, 0x74, 0x82, 0x94, 0x94, 0x8c, 0x86, 0x86, + 0x9c, 0xa7, 0xa8, 0xa5, 0x9e, 0x94, 0x8d, 0x8a, 0x8a, 0x92, 0xaa, 0x9a, + 0x98, 0x93, 0x7d, 0x63, 0x64, 0x5f, 0x58, 0x4b, 0x42, 0x40, 0x3c, 0x35, + 0x2b, 0x30, 0x3d, 0x3f, 0x40, 0x3e, 0x31, 0x20, 0x26, 0x33, 0x4a, 0x5a, + 0x5b, 0x53, 0x55, 0x6a, 0x9b, 0xa3, 0x9f, 0x9d, 0x9d, 0x9d, 0x9a, 0x95, + 0x93, 0x91, 0x8c, 0x84, 0x7c, 0x78, 0x74, 0x6f, 0x67, 0x5f, 0x58, 0x55, + 0x4f, 0x48, 0x42, 0x40, 0x3f, 0x3e, 0x3e, 0x3e, 0x3e, 0x3d, 0x3e, 0x41, + 0x42, 0x41, 0x41, 0x42, 0x44, 0x44, 0x42, 0x42, 0x43, 0x45, 0x46, 0x48, + 0x48, 0x49, 0x4a, 0x4c, 0x4d, 0x4d, 0x4e, 0x4f, 0x52, 0x53, 0x54, 0x55, + 0x55, 0x57, 0x57, 0x58, 0x5a, 0x5a, 0x5a, 0x5c, 0x5d, 0x5d, 0x5c, 0x5e, + 0x5f, 0x5f, 0x5f, 0x60, 0x61, 0x63, 0x65, 0x67, 0x68, 0x6c, 0x6d, 0x6d, + 0x6d, 0x6f, 0x72, 0x72, 0x73, 0x73, 0x74, 0x74, 0x74, 0x74, 0x74, 0x72, + 0x6f, 0x6b, 0x6a, 0x69, 0x65, 0x61, 0x5c, 0x58, 0x54, 0x4e, 0x49, 0x43, + 0x3e, 0x3a, 0x34, 0x2a, 0x1c, 0x15, 0x11, 0x10, 0x11, 0x11, 0x11, 0x11, + 0x12, 0x12, 0x11, 0x11, 0x11, 0x13, 0x13, 0x12, 0x12, 0x12, 0x11, 0x13, + 0x5e, 0x5e, 0x5d, 0x5d, 0x5e, 0x61, 0x62, 0x61, 0x60, 0x61, 0x61, 0x5f, + 0x5e, 0x5e, 0x5f, 0x5f, 0x5f, 0x60, 0x60, 0x61, 0x61, 0x61, 0x63, 0x63, + 0x63, 0x63, 0x64, 0x64, 0x65, 0x66, 0x66, 0x66, 0x67, 0x69, 0x6a, 0x6a, + 0x6b, 0x6c, 0x6c, 0x6c, 0x6c, 0x6b, 0x6a, 0x69, 0x69, 0x6a, 0x6a, 0x68, + 0x67, 0x65, 0x61, 0x5e, 0x5a, 0x58, 0x56, 0x55, 0x52, 0x51, 0x50, 0x52, + 0x58, 0x61, 0x65, 0x67, 0x6a, 0x70, 0x73, 0x75, 0x76, 0x77, 0x7a, 0x7e, + 0x81, 0x84, 0x85, 0x86, 0x88, 0x87, 0x85, 0x83, 0x81, 0x7f, 0x7f, 0x80, + 0x80, 0x7f, 0x7e, 0x7d, 0x7c, 0x7d, 0x7e, 0x7f, 0x81, 0x82, 0x83, 0x85, + 0x88, 0x89, 0x8b, 0x8d, 0x8e, 0x8e, 0x8d, 0x8c, 0x8c, 0x8c, 0x8b, 0x89, + 0x88, 0x88, 0x86, 0x83, 0x80, 0x7f, 0x7f, 0x7e, 0x7c, 0x7a, 0x79, 0x79, + 0x78, 0x78, 0x7a, 0x7c, 0x7b, 0x76, 0x70, 0x6e, 0x83, 0xa0, 0xa9, 0xa0, + 0x82, 0x6c, 0x66, 0x68, 0x78, 0x99, 0xa9, 0x98, 0x7f, 0x59, 0x5f, 0x74, + 0x74, 0x76, 0x82, 0x97, 0x9a, 0x93, 0x8d, 0x8c, 0x9e, 0xa1, 0xa5, 0xa5, + 0xa1, 0x9b, 0x97, 0x97, 0x9a, 0xa7, 0xbc, 0xa5, 0xad, 0xad, 0x94, 0x6e, + 0x6a, 0x69, 0x63, 0x56, 0x50, 0x50, 0x47, 0x3d, 0x2d, 0x2e, 0x3b, 0x40, + 0x41, 0x3f, 0x31, 0x26, 0x2f, 0x3c, 0x51, 0x5d, 0x59, 0x51, 0x56, 0x71, + 0x9d, 0xa3, 0x9e, 0x9d, 0x9c, 0x9b, 0x99, 0x94, 0x92, 0x8f, 0x8a, 0x82, + 0x7a, 0x74, 0x71, 0x6c, 0x64, 0x5c, 0x56, 0x52, 0x4c, 0x45, 0x41, 0x3f, + 0x3f, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x40, 0x41, 0x41, 0x41, 0x43, + 0x44, 0x44, 0x43, 0x42, 0x43, 0x46, 0x47, 0x49, 0x49, 0x4a, 0x4b, 0x4c, + 0x4d, 0x4d, 0x4e, 0x50, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x59, 0x5a, 0x5b, 0x5d, 0x5d, 0x5d, 0x5c, 0x5e, 0x5f, 0x5f, 0x5f, 0x60, + 0x61, 0x63, 0x65, 0x67, 0x69, 0x6c, 0x6d, 0x6d, 0x6e, 0x70, 0x71, 0x71, + 0x73, 0x73, 0x74, 0x74, 0x74, 0x74, 0x74, 0x72, 0x6f, 0x6b, 0x6a, 0x69, + 0x65, 0x61, 0x5c, 0x58, 0x55, 0x4f, 0x49, 0x43, 0x3d, 0x39, 0x33, 0x2a, + 0x1d, 0x14, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x11, 0x11, 0x11, + 0x12, 0x13, 0x13, 0x12, 0x12, 0x12, 0x11, 0x13, 0x5e, 0x5e, 0x5d, 0x5c, + 0x5c, 0x60, 0x62, 0x62, 0x61, 0x60, 0x5f, 0x5f, 0x5e, 0x5e, 0x5f, 0x60, + 0x61, 0x61, 0x61, 0x60, 0x60, 0x62, 0x63, 0x64, 0x63, 0x63, 0x64, 0x64, + 0x65, 0x66, 0x66, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6a, 0x6b, 0x6b, 0x6b, + 0x6c, 0x6b, 0x6a, 0x6a, 0x69, 0x6a, 0x69, 0x69, 0x67, 0x65, 0x61, 0x5f, + 0x5b, 0x59, 0x57, 0x56, 0x54, 0x51, 0x51, 0x53, 0x5a, 0x62, 0x66, 0x68, + 0x6c, 0x72, 0x74, 0x76, 0x76, 0x77, 0x79, 0x7d, 0x80, 0x83, 0x84, 0x85, + 0x87, 0x86, 0x85, 0x83, 0x81, 0x7f, 0x7e, 0x7f, 0x80, 0x80, 0x7f, 0x7f, + 0x7e, 0x7f, 0x7f, 0x7f, 0x81, 0x82, 0x82, 0x84, 0x87, 0x88, 0x8a, 0x8b, + 0x8c, 0x8d, 0x8c, 0x8b, 0x8b, 0x8b, 0x8b, 0x89, 0x88, 0x88, 0x86, 0x83, + 0x81, 0x80, 0x80, 0x7f, 0x7e, 0x7b, 0x79, 0x79, 0x79, 0x79, 0x79, 0x7b, + 0x7a, 0x76, 0x70, 0x6e, 0x84, 0xa4, 0xae, 0xa3, 0x80, 0x6a, 0x67, 0x6b, + 0x7b, 0x9a, 0x9d, 0x85, 0x6d, 0x52, 0x62, 0x7e, 0x80, 0x7f, 0x85, 0x98, + 0xa2, 0x9d, 0x98, 0x96, 0x9f, 0x96, 0xa2, 0xa8, 0xa5, 0xa0, 0x9f, 0xa3, + 0xaa, 0xb9, 0xbb, 0x9d, 0xac, 0xb4, 0xa6, 0x7c, 0x71, 0x80, 0x81, 0x73, + 0x70, 0x6d, 0x5d, 0x4d, 0x37, 0x2e, 0x37, 0x3f, 0x43, 0x43, 0x36, 0x32, + 0x41, 0x4e, 0x5c, 0x60, 0x57, 0x51, 0x57, 0x71, 0x98, 0xa0, 0x9e, 0x9d, + 0x9c, 0x9a, 0x97, 0x91, 0x8f, 0x8c, 0x86, 0x7d, 0x76, 0x71, 0x6d, 0x68, + 0x5f, 0x57, 0x51, 0x4d, 0x47, 0x42, 0x40, 0x3e, 0x3d, 0x3d, 0x3d, 0x3d, + 0x3f, 0x3f, 0x3f, 0x40, 0x41, 0x40, 0x41, 0x42, 0x42, 0x43, 0x43, 0x43, + 0x44, 0x47, 0x49, 0x49, 0x49, 0x4a, 0x4c, 0x4c, 0x4d, 0x4e, 0x4f, 0x51, + 0x51, 0x52, 0x53, 0x55, 0x56, 0x58, 0x59, 0x59, 0x59, 0x5a, 0x5b, 0x5e, + 0x5e, 0x5e, 0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x61, 0x63, 0x63, 0x64, 0x66, + 0x69, 0x6b, 0x6d, 0x6d, 0x6e, 0x70, 0x70, 0x72, 0x72, 0x73, 0x74, 0x74, + 0x74, 0x74, 0x73, 0x70, 0x6f, 0x6b, 0x6a, 0x69, 0x65, 0x61, 0x5b, 0x58, + 0x56, 0x51, 0x49, 0x43, 0x3d, 0x39, 0x33, 0x2a, 0x1d, 0x14, 0x12, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x13, 0x12, + 0x11, 0x11, 0x12, 0x13, 0x5d, 0x5d, 0x5c, 0x5c, 0x5c, 0x5f, 0x61, 0x61, + 0x60, 0x60, 0x5f, 0x5f, 0x5f, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61, 0x60, + 0x60, 0x61, 0x62, 0x62, 0x62, 0x61, 0x62, 0x63, 0x63, 0x65, 0x66, 0x65, + 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6a, 0x6a, 0x6b, 0x6c, 0x6c, 0x6b, 0x6b, + 0x6b, 0x6a, 0x69, 0x68, 0x68, 0x65, 0x62, 0x5f, 0x5b, 0x59, 0x56, 0x56, + 0x54, 0x52, 0x51, 0x53, 0x5e, 0x66, 0x6a, 0x6c, 0x70, 0x74, 0x76, 0x78, + 0x78, 0x79, 0x7a, 0x7c, 0x7d, 0x81, 0x83, 0x84, 0x86, 0x85, 0x83, 0x82, + 0x81, 0x7f, 0x7d, 0x7e, 0x7e, 0x7f, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x81, 0x82, 0x82, 0x83, 0x86, 0x88, 0x88, 0x89, 0x8b, 0x8c, 0x8b, 0x8b, + 0x8b, 0x8c, 0x8b, 0x89, 0x88, 0x87, 0x85, 0x85, 0x82, 0x81, 0x80, 0x80, + 0x7e, 0x7b, 0x79, 0x79, 0x79, 0x78, 0x79, 0x79, 0x78, 0x76, 0x71, 0x6f, + 0x8b, 0xaf, 0xba, 0xac, 0x7f, 0x67, 0x6a, 0x70, 0x7d, 0x8d, 0x80, 0x67, + 0x59, 0x4f, 0x66, 0x87, 0x91, 0x91, 0x8f, 0x97, 0xa6, 0xa2, 0x9e, 0x9d, + 0xa3, 0xa1, 0xa8, 0xaa, 0xa9, 0xa2, 0x9e, 0x9d, 0x9e, 0x9f, 0x9e, 0x8b, + 0x88, 0x8c, 0x91, 0x8a, 0x93, 0xb5, 0xbf, 0xb2, 0xa8, 0x8d, 0x6e, 0x5c, + 0x4a, 0x38, 0x38, 0x47, 0x51, 0x56, 0x44, 0x45, 0x57, 0x62, 0x67, 0x61, + 0x56, 0x4d, 0x4e, 0x5f, 0x8c, 0x9f, 0x9d, 0x9a, 0x99, 0x97, 0x92, 0x8c, + 0x88, 0x86, 0x81, 0x78, 0x70, 0x6b, 0x67, 0x61, 0x58, 0x51, 0x4b, 0x48, + 0x44, 0x41, 0x40, 0x3e, 0x3d, 0x3d, 0x3d, 0x3d, 0x3f, 0x40, 0x41, 0x41, + 0x42, 0x42, 0x42, 0x42, 0x43, 0x44, 0x44, 0x44, 0x45, 0x47, 0x49, 0x49, + 0x49, 0x4a, 0x4c, 0x4c, 0x4d, 0x4e, 0x4f, 0x51, 0x52, 0x52, 0x52, 0x55, + 0x56, 0x58, 0x59, 0x59, 0x58, 0x59, 0x5b, 0x5d, 0x5e, 0x5e, 0x5d, 0x5d, + 0x5f, 0x5f, 0x60, 0x62, 0x63, 0x63, 0x64, 0x67, 0x6a, 0x6c, 0x6d, 0x6e, + 0x6e, 0x6f, 0x70, 0x72, 0x72, 0x73, 0x74, 0x74, 0x74, 0x74, 0x72, 0x70, + 0x6f, 0x6b, 0x6a, 0x69, 0x65, 0x60, 0x5b, 0x57, 0x56, 0x51, 0x49, 0x42, + 0x3d, 0x3a, 0x34, 0x2a, 0x1c, 0x14, 0x12, 0x11, 0x10, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x11, 0x10, 0x11, 0x11, 0x11, + 0x5c, 0x5d, 0x5d, 0x5d, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x61, 0x60, 0x61, 0x61, 0x60, 0x5f, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x62, 0x62, 0x62, 0x64, 0x65, 0x64, 0x65, 0x66, 0x68, 0x68, + 0x6a, 0x6a, 0x6b, 0x6b, 0x6c, 0x6c, 0x6b, 0x6b, 0x6b, 0x6a, 0x69, 0x69, + 0x68, 0x66, 0x62, 0x5f, 0x5c, 0x59, 0x57, 0x56, 0x54, 0x52, 0x52, 0x56, + 0x61, 0x6a, 0x6e, 0x70, 0x72, 0x77, 0x7a, 0x7b, 0x7b, 0x7b, 0x7c, 0x7b, + 0x7c, 0x7e, 0x80, 0x82, 0x85, 0x84, 0x82, 0x81, 0x80, 0x7f, 0x7d, 0x7d, + 0x7e, 0x80, 0x82, 0x82, 0x81, 0x80, 0x81, 0x80, 0x81, 0x82, 0x83, 0x84, + 0x85, 0x86, 0x88, 0x88, 0x88, 0x8a, 0x8a, 0x8c, 0x8c, 0x8c, 0x8c, 0x8a, + 0x89, 0x88, 0x86, 0x85, 0x82, 0x80, 0x80, 0x7f, 0x7d, 0x7b, 0x79, 0x79, + 0x79, 0x78, 0x78, 0x79, 0x79, 0x77, 0x73, 0x74, 0x92, 0xb4, 0xbf, 0xaf, + 0x7e, 0x6a, 0x6d, 0x73, 0x7c, 0x80, 0x6a, 0x55, 0x4e, 0x52, 0x64, 0x81, + 0x99, 0xa0, 0x9e, 0x9b, 0xa4, 0x9c, 0x97, 0x99, 0xa2, 0xab, 0xad, 0xad, + 0xac, 0xa0, 0x9a, 0x99, 0x9a, 0x9b, 0x98, 0x93, 0x8f, 0x8f, 0x93, 0x9b, + 0xaa, 0xc2, 0xcc, 0xcb, 0xc2, 0x9d, 0x80, 0x75, 0x6d, 0x55, 0x4c, 0x5c, + 0x69, 0x6e, 0x59, 0x57, 0x63, 0x69, 0x69, 0x60, 0x52, 0x3e, 0x39, 0x4a, + 0x7d, 0x99, 0x9b, 0x99, 0x97, 0x93, 0x8e, 0x87, 0x82, 0x7f, 0x7b, 0x73, + 0x6a, 0x64, 0x61, 0x5a, 0x50, 0x4a, 0x45, 0x43, 0x42, 0x40, 0x3f, 0x3f, + 0x3e, 0x3d, 0x3d, 0x3e, 0x40, 0x41, 0x42, 0x42, 0x43, 0x43, 0x44, 0x44, + 0x44, 0x45, 0x45, 0x46, 0x46, 0x47, 0x47, 0x47, 0x48, 0x4b, 0x4d, 0x4c, + 0x4d, 0x4e, 0x4e, 0x50, 0x51, 0x52, 0x52, 0x55, 0x56, 0x58, 0x59, 0x59, + 0x58, 0x59, 0x5c, 0x5e, 0x5f, 0x5f, 0x5f, 0x5e, 0x60, 0x60, 0x61, 0x62, + 0x63, 0x63, 0x64, 0x66, 0x69, 0x6b, 0x6d, 0x6e, 0x6e, 0x70, 0x70, 0x71, + 0x71, 0x72, 0x73, 0x73, 0x74, 0x74, 0x72, 0x70, 0x6f, 0x6b, 0x6a, 0x69, + 0x66, 0x62, 0x5c, 0x56, 0x53, 0x4f, 0x48, 0x41, 0x3d, 0x3a, 0x36, 0x2a, + 0x1d, 0x15, 0x12, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x11, 0x12, 0x12, + 0x12, 0x12, 0x13, 0x11, 0x11, 0x11, 0x12, 0x12, 0x5c, 0x5d, 0x5e, 0x5d, + 0x5d, 0x5d, 0x5d, 0x60, 0x60, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x62, + 0x61, 0x61, 0x61, 0x60, 0x60, 0x60, 0x60, 0x5f, 0x5f, 0x61, 0x61, 0x61, + 0x62, 0x64, 0x65, 0x64, 0x65, 0x66, 0x66, 0x68, 0x68, 0x6a, 0x6b, 0x6b, + 0x6c, 0x6c, 0x6b, 0x6b, 0x6b, 0x6a, 0x69, 0x68, 0x68, 0x66, 0x62, 0x5f, + 0x5c, 0x5b, 0x58, 0x55, 0x53, 0x52, 0x54, 0x58, 0x62, 0x6b, 0x70, 0x72, + 0x75, 0x78, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7c, 0x7c, 0x7d, 0x7e, 0x7f, + 0x82, 0x82, 0x81, 0x81, 0x7f, 0x7e, 0x7d, 0x7d, 0x7d, 0x7f, 0x82, 0x83, + 0x82, 0x81, 0x80, 0x7f, 0x80, 0x81, 0x82, 0x84, 0x86, 0x86, 0x87, 0x87, + 0x88, 0x8a, 0x8b, 0x8c, 0x8c, 0x8c, 0x8c, 0x8a, 0x89, 0x87, 0x86, 0x85, + 0x83, 0x81, 0x80, 0x7f, 0x7d, 0x7c, 0x7b, 0x7a, 0x7a, 0x78, 0x78, 0x7a, + 0x7b, 0x7a, 0x78, 0x7b, 0x93, 0xb1, 0xb9, 0xa9, 0x7b, 0x6b, 0x6d, 0x72, + 0x7c, 0x80, 0x65, 0x4f, 0x4b, 0x53, 0x5b, 0x70, 0x94, 0xa4, 0xa9, 0xa3, + 0xa1, 0x97, 0x91, 0x8e, 0x9c, 0xa8, 0xaa, 0xaa, 0xa8, 0x9f, 0x9c, 0x9d, + 0xa0, 0xa4, 0xa2, 0xa4, 0xa3, 0xa1, 0xa2, 0xaa, 0xb1, 0xbb, 0xbf, 0xbf, + 0xb9, 0xa0, 0x93, 0x90, 0x8d, 0x79, 0x66, 0x6d, 0x73, 0x70, 0x63, 0x60, + 0x67, 0x69, 0x66, 0x59, 0x46, 0x39, 0x36, 0x42, 0x71, 0x92, 0x98, 0x97, + 0x95, 0x91, 0x8b, 0x82, 0x7e, 0x7b, 0x75, 0x6e, 0x65, 0x5f, 0x5b, 0x54, + 0x4d, 0x47, 0x43, 0x41, 0x41, 0x3f, 0x40, 0x40, 0x3f, 0x3e, 0x3e, 0x40, + 0x41, 0x42, 0x43, 0x43, 0x43, 0x44, 0x44, 0x44, 0x44, 0x46, 0x47, 0x48, + 0x47, 0x47, 0x47, 0x48, 0x49, 0x4c, 0x4d, 0x4d, 0x4d, 0x4e, 0x4f, 0x4e, + 0x50, 0x51, 0x52, 0x55, 0x56, 0x58, 0x59, 0x59, 0x58, 0x5b, 0x5c, 0x5f, + 0x5f, 0x5f, 0x60, 0x60, 0x60, 0x61, 0x62, 0x62, 0x63, 0x63, 0x65, 0x66, + 0x69, 0x6a, 0x6d, 0x6e, 0x6e, 0x70, 0x71, 0x71, 0x70, 0x71, 0x72, 0x72, + 0x74, 0x73, 0x72, 0x70, 0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x62, 0x5c, 0x56, + 0x52, 0x4e, 0x49, 0x43, 0x3e, 0x3b, 0x35, 0x29, 0x1e, 0x16, 0x12, 0x11, + 0x11, 0x12, 0x12, 0x12, 0x12, 0x11, 0x12, 0x12, 0x12, 0x13, 0x12, 0x11, + 0x12, 0x12, 0x13, 0x11, 0x5b, 0x5d, 0x5e, 0x5d, 0x5c, 0x5d, 0x5d, 0x5f, + 0x60, 0x61, 0x61, 0x61, 0x62, 0x62, 0x61, 0x61, 0x61, 0x62, 0x61, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x61, 0x60, 0x62, 0x63, 0x65, 0x65, 0x64, + 0x65, 0x66, 0x66, 0x68, 0x68, 0x6a, 0x6b, 0x6b, 0x6c, 0x6c, 0x6b, 0x6b, + 0x6b, 0x6a, 0x69, 0x68, 0x68, 0x65, 0x61, 0x5f, 0x5c, 0x5b, 0x58, 0x55, + 0x53, 0x53, 0x55, 0x5a, 0x64, 0x6c, 0x71, 0x74, 0x77, 0x7a, 0x7c, 0x7d, + 0x7d, 0x7e, 0x7e, 0x7c, 0x7c, 0x7c, 0x7d, 0x7e, 0x81, 0x80, 0x7f, 0x7f, + 0x7e, 0x7d, 0x7d, 0x7d, 0x7d, 0x7f, 0x82, 0x83, 0x82, 0x82, 0x81, 0x80, + 0x80, 0x81, 0x82, 0x83, 0x86, 0x86, 0x86, 0x87, 0x87, 0x8a, 0x8a, 0x8b, + 0x8c, 0x8c, 0x8c, 0x89, 0x88, 0x88, 0x86, 0x85, 0x83, 0x82, 0x81, 0x7f, + 0x7d, 0x7c, 0x7b, 0x7a, 0x7a, 0x78, 0x78, 0x7a, 0x7b, 0x7c, 0x7d, 0x7f, + 0x91, 0xaa, 0xb0, 0xa1, 0x7a, 0x6e, 0x6e, 0x72, 0x7d, 0x84, 0x67, 0x4e, + 0x4a, 0x51, 0x52, 0x5e, 0x87, 0x9f, 0xac, 0xa9, 0xa2, 0x9a, 0x93, 0x8e, + 0x94, 0x9e, 0xa2, 0xa4, 0xa2, 0x9d, 0x9c, 0x9e, 0xa2, 0xa8, 0xa8, 0xac, + 0xab, 0xaa, 0xa9, 0xad, 0xb1, 0xb2, 0xb2, 0xb2, 0xae, 0xa1, 0x9d, 0x9d, + 0x9c, 0x8c, 0x76, 0x75, 0x74, 0x6c, 0x64, 0x61, 0x64, 0x65, 0x60, 0x4e, + 0x41, 0x3e, 0x3b, 0x40, 0x6a, 0x8b, 0x94, 0x95, 0x94, 0x90, 0x89, 0x80, + 0x7a, 0x77, 0x71, 0x6a, 0x61, 0x5b, 0x57, 0x50, 0x4a, 0x46, 0x42, 0x41, + 0x41, 0x40, 0x41, 0x40, 0x40, 0x3e, 0x3f, 0x41, 0x41, 0x42, 0x43, 0x44, + 0x43, 0x43, 0x44, 0x45, 0x45, 0x46, 0x47, 0x48, 0x48, 0x47, 0x48, 0x49, + 0x4a, 0x4c, 0x4e, 0x4e, 0x4d, 0x4e, 0x4e, 0x4e, 0x50, 0x51, 0x52, 0x55, + 0x56, 0x58, 0x58, 0x58, 0x58, 0x5b, 0x5d, 0x5e, 0x5e, 0x5f, 0x60, 0x60, + 0x60, 0x61, 0x62, 0x62, 0x64, 0x64, 0x66, 0x67, 0x69, 0x6a, 0x6c, 0x6e, + 0x6e, 0x70, 0x71, 0x70, 0x70, 0x71, 0x72, 0x72, 0x74, 0x73, 0x72, 0x70, + 0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x61, 0x5c, 0x56, 0x51, 0x4d, 0x4a, 0x44, + 0x3e, 0x3a, 0x34, 0x29, 0x1e, 0x16, 0x12, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x12, 0x11, 0x12, 0x12, 0x12, 0x13, 0x13, 0x12, 0x13, 0x13, 0x13, 0x11, + 0x5b, 0x5d, 0x5e, 0x5d, 0x5d, 0x5e, 0x5e, 0x5f, 0x60, 0x61, 0x61, 0x60, + 0x61, 0x62, 0x62, 0x61, 0x60, 0x61, 0x61, 0x60, 0x60, 0x60, 0x61, 0x61, + 0x60, 0x61, 0x60, 0x61, 0x62, 0x64, 0x65, 0x64, 0x65, 0x66, 0x66, 0x68, + 0x68, 0x6a, 0x6b, 0x6b, 0x6c, 0x6c, 0x6b, 0x6b, 0x6b, 0x6a, 0x68, 0x68, + 0x67, 0x65, 0x62, 0x60, 0x5e, 0x5c, 0x59, 0x56, 0x53, 0x53, 0x56, 0x5d, + 0x67, 0x70, 0x75, 0x77, 0x7a, 0x7c, 0x7e, 0x80, 0x80, 0x80, 0x80, 0x7e, + 0x7d, 0x7c, 0x7c, 0x7d, 0x7d, 0x7c, 0x7c, 0x7c, 0x7b, 0x7c, 0x7c, 0x7c, + 0x7c, 0x7d, 0x81, 0x83, 0x84, 0x84, 0x83, 0x82, 0x81, 0x81, 0x82, 0x83, + 0x85, 0x86, 0x87, 0x87, 0x87, 0x89, 0x89, 0x8a, 0x8b, 0x8b, 0x8b, 0x89, + 0x89, 0x88, 0x87, 0x86, 0x83, 0x83, 0x82, 0x80, 0x7d, 0x7c, 0x7a, 0x7a, + 0x7a, 0x78, 0x79, 0x7a, 0x7c, 0x7f, 0x84, 0x83, 0x8b, 0x99, 0x9c, 0x90, + 0x79, 0x70, 0x6e, 0x72, 0x80, 0x8a, 0x6a, 0x4d, 0x48, 0x4d, 0x41, 0x3f, + 0x69, 0x88, 0xa8, 0xb0, 0xa8, 0xa4, 0xa0, 0x98, 0x8d, 0x8d, 0x92, 0x94, + 0x95, 0x94, 0x95, 0x98, 0x9c, 0xa3, 0xa7, 0xa9, 0xa7, 0xa7, 0xa8, 0xa8, + 0xa6, 0xa3, 0xa2, 0xa1, 0xa2, 0xa3, 0xa4, 0xa4, 0xa3, 0x99, 0x83, 0x74, + 0x6c, 0x63, 0x5f, 0x5d, 0x5e, 0x5b, 0x4e, 0x38, 0x3f, 0x4c, 0x4c, 0x46, + 0x5e, 0x7d, 0x89, 0x8e, 0x90, 0x8f, 0x88, 0x7d, 0x75, 0x71, 0x6b, 0x64, + 0x5c, 0x56, 0x52, 0x4c, 0x47, 0x43, 0x42, 0x41, 0x41, 0x40, 0x41, 0x40, + 0x40, 0x3f, 0x40, 0x41, 0x42, 0x42, 0x43, 0x44, 0x43, 0x43, 0x44, 0x45, + 0x46, 0x47, 0x48, 0x48, 0x49, 0x49, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, + 0x4f, 0x4f, 0x4e, 0x4e, 0x50, 0x51, 0x52, 0x54, 0x56, 0x58, 0x58, 0x58, + 0x59, 0x5b, 0x5d, 0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x60, 0x61, 0x62, 0x63, + 0x65, 0x67, 0x67, 0x67, 0x68, 0x6a, 0x6c, 0x6d, 0x6e, 0x70, 0x71, 0x71, + 0x71, 0x71, 0x72, 0x72, 0x74, 0x73, 0x72, 0x6f, 0x6e, 0x6c, 0x6a, 0x69, + 0x67, 0x61, 0x5c, 0x56, 0x51, 0x4d, 0x4a, 0x43, 0x3d, 0x39, 0x34, 0x29, + 0x1e, 0x16, 0x12, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x11, 0x12, + 0x13, 0x13, 0x13, 0x12, 0x12, 0x12, 0x11, 0x13, 0x5b, 0x5d, 0x5c, 0x5c, + 0x5c, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x62, 0x61, 0x61, 0x61, 0x61, 0x61, + 0x61, 0x61, 0x61, 0x61, 0x61, 0x60, 0x61, 0x61, 0x61, 0x62, 0x61, 0x63, + 0x63, 0x63, 0x63, 0x63, 0x64, 0x65, 0x66, 0x68, 0x68, 0x6a, 0x6b, 0x6a, + 0x6b, 0x6b, 0x6a, 0x6b, 0x6b, 0x6a, 0x69, 0x69, 0x68, 0x66, 0x63, 0x60, + 0x5d, 0x5b, 0x59, 0x57, 0x55, 0x55, 0x58, 0x60, 0x6b, 0x73, 0x77, 0x79, + 0x7b, 0x7f, 0x80, 0x84, 0x85, 0x85, 0x84, 0x82, 0x7f, 0x7d, 0x7c, 0x7b, + 0x7b, 0x7a, 0x79, 0x78, 0x77, 0x79, 0x7b, 0x7c, 0x7c, 0x7d, 0x7f, 0x82, + 0x84, 0x84, 0x84, 0x83, 0x82, 0x81, 0x81, 0x82, 0x85, 0x86, 0x87, 0x87, + 0x87, 0x88, 0x88, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x88, 0x87, + 0x84, 0x83, 0x82, 0x80, 0x7d, 0x7b, 0x7a, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, + 0x7c, 0x82, 0x89, 0x88, 0x81, 0x81, 0x82, 0x80, 0x77, 0x71, 0x6f, 0x75, + 0x83, 0x85, 0x61, 0x4b, 0x46, 0x45, 0x30, 0x25, 0x40, 0x61, 0x95, 0xb1, + 0xb1, 0xaa, 0xa4, 0x9c, 0x95, 0x8e, 0x88, 0x87, 0x85, 0x84, 0x85, 0x86, + 0x89, 0x8d, 0x8e, 0x8a, 0x88, 0x89, 0x8d, 0x91, 0x91, 0x91, 0x90, 0x90, + 0x95, 0x9a, 0x99, 0x97, 0x94, 0x87, 0x71, 0x61, 0x5b, 0x58, 0x59, 0x59, + 0x52, 0x45, 0x2e, 0x29, 0x45, 0x5f, 0x62, 0x53, 0x53, 0x67, 0x76, 0x80, + 0x86, 0x8a, 0x88, 0x7e, 0x74, 0x6e, 0x65, 0x5c, 0x53, 0x4e, 0x4b, 0x47, + 0x44, 0x42, 0x41, 0x40, 0x40, 0x40, 0x41, 0x41, 0x40, 0x40, 0x42, 0x42, + 0x43, 0x43, 0x43, 0x44, 0x44, 0x44, 0x45, 0x45, 0x46, 0x47, 0x48, 0x48, + 0x48, 0x49, 0x4a, 0x4c, 0x4d, 0x4d, 0x4d, 0x4e, 0x50, 0x50, 0x50, 0x50, + 0x50, 0x51, 0x52, 0x53, 0x56, 0x57, 0x57, 0x58, 0x59, 0x5c, 0x5c, 0x5e, + 0x5d, 0x5e, 0x5f, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x66, 0x67, 0x67, 0x67, + 0x68, 0x69, 0x6c, 0x6d, 0x6e, 0x70, 0x71, 0x72, 0x71, 0x71, 0x72, 0x73, + 0x73, 0x74, 0x73, 0x71, 0x6e, 0x6c, 0x6b, 0x69, 0x66, 0x61, 0x5b, 0x56, + 0x53, 0x50, 0x4a, 0x42, 0x3b, 0x39, 0x34, 0x2a, 0x1e, 0x16, 0x12, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x13, 0x13, 0x13, 0x12, + 0x11, 0x11, 0x12, 0x12, 0x5a, 0x5b, 0x5b, 0x5c, 0x5d, 0x5f, 0x5f, 0x60, + 0x61, 0x61, 0x61, 0x61, 0x61, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, + 0x61, 0x60, 0x61, 0x62, 0x61, 0x61, 0x61, 0x63, 0x63, 0x63, 0x63, 0x62, + 0x63, 0x64, 0x66, 0x67, 0x69, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6a, 0x6b, + 0x6b, 0x6a, 0x6a, 0x6a, 0x69, 0x67, 0x63, 0x61, 0x5e, 0x5c, 0x5b, 0x58, + 0x56, 0x57, 0x5b, 0x63, 0x6e, 0x75, 0x79, 0x7b, 0x7d, 0x80, 0x85, 0x87, + 0x88, 0x88, 0x87, 0x85, 0x82, 0x7f, 0x7e, 0x7b, 0x78, 0x78, 0x77, 0x75, + 0x72, 0x75, 0x7a, 0x7d, 0x7d, 0x7d, 0x7f, 0x82, 0x84, 0x85, 0x85, 0x84, + 0x82, 0x83, 0x83, 0x82, 0x83, 0x85, 0x86, 0x86, 0x87, 0x89, 0x89, 0x89, + 0x89, 0x88, 0x88, 0x88, 0x89, 0x89, 0x88, 0x86, 0x85, 0x83, 0x82, 0x81, + 0x7f, 0x7c, 0x7c, 0x7c, 0x7a, 0x7a, 0x7b, 0x7c, 0x7d, 0x80, 0x89, 0x8c, + 0x84, 0x7e, 0x7c, 0x7a, 0x72, 0x6d, 0x6e, 0x77, 0x8a, 0x80, 0x54, 0x44, + 0x40, 0x3a, 0x27, 0x1e, 0x2a, 0x44, 0x79, 0xa4, 0xb0, 0xb0, 0xaa, 0x9d, + 0x8d, 0x84, 0x82, 0x83, 0x87, 0x8e, 0x8f, 0x8f, 0x90, 0x91, 0x8e, 0x88, + 0x81, 0x7c, 0x77, 0x73, 0x72, 0x72, 0x73, 0x76, 0x76, 0x76, 0x75, 0x72, + 0x6b, 0x61, 0x5a, 0x5b, 0x5d, 0x61, 0x61, 0x4e, 0x33, 0x25, 0x22, 0x2b, + 0x47, 0x65, 0x6c, 0x5e, 0x48, 0x4f, 0x66, 0x79, 0x81, 0x86, 0x84, 0x7e, + 0x75, 0x6e, 0x62, 0x55, 0x4b, 0x47, 0x45, 0x43, 0x41, 0x40, 0x3f, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x42, 0x43, 0x43, 0x44, + 0x45, 0x45, 0x45, 0x46, 0x47, 0x48, 0x49, 0x49, 0x48, 0x49, 0x4b, 0x4d, + 0x4d, 0x4e, 0x4d, 0x4e, 0x50, 0x50, 0x50, 0x51, 0x51, 0x52, 0x53, 0x54, + 0x56, 0x58, 0x58, 0x58, 0x59, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x60, + 0x60, 0x63, 0x63, 0x63, 0x65, 0x67, 0x66, 0x67, 0x68, 0x69, 0x6b, 0x6d, + 0x6e, 0x70, 0x71, 0x72, 0x71, 0x72, 0x73, 0x74, 0x74, 0x74, 0x73, 0x72, + 0x6e, 0x6c, 0x6b, 0x69, 0x66, 0x60, 0x5b, 0x56, 0x53, 0x50, 0x49, 0x41, + 0x3d, 0x3a, 0x34, 0x2a, 0x1d, 0x17, 0x14, 0x11, 0x11, 0x12, 0x12, 0x11, + 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x12, 0x12, + 0x5a, 0x5c, 0x5d, 0x5d, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x61, 0x61, 0x61, + 0x61, 0x61, 0x62, 0x63, 0x63, 0x62, 0x62, 0x62, 0x61, 0x61, 0x63, 0x63, + 0x61, 0x61, 0x61, 0x63, 0x63, 0x63, 0x63, 0x64, 0x63, 0x64, 0x66, 0x67, + 0x68, 0x6a, 0x6a, 0x6a, 0x6b, 0x6b, 0x6a, 0x6b, 0x6b, 0x6a, 0x6a, 0x6a, + 0x69, 0x67, 0x64, 0x60, 0x5e, 0x5d, 0x5c, 0x5a, 0x57, 0x5a, 0x5e, 0x67, + 0x70, 0x77, 0x7b, 0x7d, 0x80, 0x83, 0x86, 0x89, 0x8a, 0x8a, 0x89, 0x87, + 0x84, 0x81, 0x7f, 0x7a, 0x76, 0x76, 0x74, 0x71, 0x6f, 0x73, 0x78, 0x7c, + 0x7e, 0x80, 0x81, 0x83, 0x85, 0x85, 0x85, 0x85, 0x83, 0x84, 0x84, 0x83, + 0x83, 0x84, 0x85, 0x86, 0x87, 0x89, 0x8a, 0x89, 0x89, 0x89, 0x89, 0x88, + 0x8a, 0x89, 0x88, 0x86, 0x84, 0x83, 0x82, 0x81, 0x7f, 0x7d, 0x7d, 0x7d, + 0x7c, 0x79, 0x7b, 0x7b, 0x7c, 0x7d, 0x86, 0x8d, 0x8b, 0x85, 0x80, 0x78, + 0x6b, 0x68, 0x6c, 0x78, 0x8e, 0x7e, 0x4e, 0x3f, 0x3b, 0x34, 0x26, 0x20, + 0x26, 0x39, 0x65, 0x93, 0xa8, 0xae, 0xae, 0xa8, 0x9c, 0x90, 0x86, 0x7d, + 0x72, 0x6d, 0x6e, 0x6f, 0x71, 0x76, 0x7e, 0x80, 0x7c, 0x78, 0x75, 0x74, + 0x78, 0x7a, 0x7c, 0x7e, 0x78, 0x6e, 0x65, 0x60, 0x5b, 0x5b, 0x61, 0x67, + 0x6b, 0x6b, 0x57, 0x32, 0x1f, 0x1d, 0x26, 0x31, 0x47, 0x62, 0x6b, 0x60, + 0x45, 0x46, 0x63, 0x7c, 0x86, 0x86, 0x81, 0x7d, 0x77, 0x70, 0x63, 0x53, + 0x48, 0x44, 0x42, 0x40, 0x3d, 0x3d, 0x3e, 0x40, 0x42, 0x44, 0x46, 0x45, + 0x43, 0x42, 0x40, 0x40, 0x42, 0x43, 0x45, 0x46, 0x46, 0x45, 0x45, 0x45, + 0x48, 0x49, 0x4a, 0x4a, 0x49, 0x49, 0x4c, 0x4d, 0x4e, 0x4f, 0x4f, 0x4f, + 0x50, 0x50, 0x50, 0x51, 0x52, 0x52, 0x53, 0x55, 0x55, 0x58, 0x58, 0x58, + 0x5a, 0x5b, 0x5c, 0x5e, 0x5e, 0x5f, 0x60, 0x60, 0x61, 0x63, 0x64, 0x65, + 0x66, 0x67, 0x66, 0x67, 0x68, 0x68, 0x6c, 0x6e, 0x6e, 0x70, 0x70, 0x71, + 0x71, 0x71, 0x73, 0x74, 0x74, 0x74, 0x73, 0x72, 0x6e, 0x6d, 0x6b, 0x69, + 0x66, 0x61, 0x5c, 0x56, 0x54, 0x4f, 0x48, 0x41, 0x3d, 0x3a, 0x35, 0x2b, + 0x1e, 0x17, 0x14, 0x12, 0x11, 0x12, 0x12, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x12, 0x13, 0x12, 0x11, 0x11, 0x12, 0x11, 0x5a, 0x5c, 0x5d, 0x5d, + 0x5d, 0x5f, 0x5f, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x62, 0x64, + 0x63, 0x62, 0x62, 0x62, 0x61, 0x62, 0x63, 0x63, 0x62, 0x61, 0x61, 0x63, + 0x63, 0x62, 0x62, 0x64, 0x63, 0x64, 0x66, 0x66, 0x68, 0x69, 0x6a, 0x6a, + 0x6b, 0x6b, 0x6a, 0x6b, 0x6b, 0x6a, 0x6a, 0x6a, 0x69, 0x67, 0x64, 0x61, + 0x5f, 0x5e, 0x5d, 0x59, 0x58, 0x5b, 0x60, 0x68, 0x71, 0x77, 0x7b, 0x7e, + 0x80, 0x85, 0x87, 0x8b, 0x8c, 0x8c, 0x8b, 0x88, 0x86, 0x82, 0x80, 0x7b, + 0x76, 0x74, 0x71, 0x70, 0x6e, 0x72, 0x78, 0x7d, 0x7f, 0x80, 0x82, 0x84, + 0x85, 0x85, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x83, 0x84, 0x84, 0x85, + 0x86, 0x88, 0x89, 0x89, 0x89, 0x89, 0x89, 0x88, 0x89, 0x89, 0x88, 0x87, + 0x85, 0x83, 0x82, 0x81, 0x7f, 0x7d, 0x7d, 0x7d, 0x7c, 0x79, 0x7b, 0x7c, + 0x7c, 0x7d, 0x83, 0x8b, 0x8c, 0x87, 0x82, 0x74, 0x65, 0x66, 0x6c, 0x7a, + 0x92, 0x7e, 0x4b, 0x3b, 0x39, 0x35, 0x2a, 0x23, 0x26, 0x34, 0x59, 0x84, + 0x9d, 0xa8, 0xac, 0xac, 0xa4, 0x99, 0x8b, 0x7f, 0x6c, 0x5e, 0x5b, 0x5b, + 0x5e, 0x64, 0x6f, 0x74, 0x72, 0x71, 0x6f, 0x71, 0x74, 0x75, 0x76, 0x78, + 0x75, 0x6d, 0x65, 0x60, 0x5e, 0x61, 0x68, 0x6b, 0x6a, 0x61, 0x47, 0x25, + 0x1b, 0x1e, 0x29, 0x34, 0x49, 0x65, 0x6e, 0x64, 0x47, 0x44, 0x65, 0x7f, + 0x88, 0x88, 0x7f, 0x7a, 0x76, 0x71, 0x65, 0x54, 0x47, 0x42, 0x40, 0x40, + 0x43, 0x4a, 0x4f, 0x52, 0x55, 0x5b, 0x5e, 0x5c, 0x5b, 0x58, 0x4f, 0x45, + 0x42, 0x42, 0x44, 0x45, 0x45, 0x45, 0x44, 0x45, 0x48, 0x49, 0x4a, 0x4a, + 0x49, 0x4a, 0x4d, 0x4e, 0x4e, 0x4f, 0x50, 0x4f, 0x50, 0x50, 0x50, 0x51, + 0x52, 0x53, 0x54, 0x55, 0x55, 0x58, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5e, + 0x5e, 0x5f, 0x60, 0x60, 0x61, 0x63, 0x65, 0x66, 0x67, 0x67, 0x67, 0x68, + 0x69, 0x69, 0x6c, 0x6d, 0x6e, 0x70, 0x70, 0x71, 0x71, 0x72, 0x72, 0x73, + 0x74, 0x74, 0x73, 0x72, 0x6e, 0x6d, 0x6b, 0x69, 0x66, 0x60, 0x5b, 0x56, + 0x53, 0x4f, 0x48, 0x41, 0x3d, 0x3a, 0x34, 0x2a, 0x1e, 0x18, 0x14, 0x12, + 0x11, 0x12, 0x12, 0x12, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x13, 0x12, + 0x11, 0x11, 0x12, 0x11, 0x59, 0x5b, 0x5c, 0x5c, 0x5e, 0x5e, 0x60, 0x60, + 0x60, 0x61, 0x61, 0x61, 0x61, 0x62, 0x63, 0x64, 0x64, 0x62, 0x62, 0x62, + 0x61, 0x61, 0x62, 0x62, 0x61, 0x61, 0x61, 0x62, 0x62, 0x61, 0x62, 0x63, + 0x63, 0x64, 0x66, 0x67, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6b, 0x6a, 0x6a, + 0x6a, 0x6b, 0x6b, 0x6a, 0x69, 0x67, 0x64, 0x61, 0x60, 0x5f, 0x5d, 0x59, + 0x58, 0x5c, 0x61, 0x6a, 0x73, 0x77, 0x7c, 0x7e, 0x81, 0x85, 0x87, 0x8b, + 0x8c, 0x8c, 0x8b, 0x89, 0x86, 0x84, 0x81, 0x7c, 0x77, 0x71, 0x6e, 0x6c, + 0x6d, 0x73, 0x79, 0x7e, 0x7f, 0x81, 0x83, 0x85, 0x86, 0x86, 0x85, 0x84, + 0x84, 0x83, 0x83, 0x83, 0x83, 0x84, 0x84, 0x85, 0x86, 0x86, 0x89, 0x89, + 0x89, 0x88, 0x88, 0x88, 0x87, 0x87, 0x88, 0x88, 0x85, 0x83, 0x83, 0x81, + 0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x79, 0x7b, 0x7d, 0x7e, 0x7f, 0x7f, 0x82, + 0x84, 0x82, 0x7b, 0x6b, 0x5e, 0x65, 0x6e, 0x7e, 0x98, 0x7c, 0x46, 0x37, + 0x38, 0x40, 0x3a, 0x2b, 0x24, 0x2d, 0x4a, 0x6d, 0x86, 0x98, 0xa0, 0xa7, + 0xa6, 0x9f, 0x96, 0x8c, 0x78, 0x61, 0x56, 0x53, 0x53, 0x55, 0x5b, 0x60, + 0x61, 0x62, 0x62, 0x62, 0x60, 0x5b, 0x5a, 0x5b, 0x62, 0x65, 0x65, 0x65, + 0x65, 0x65, 0x62, 0x5a, 0x51, 0x3e, 0x2f, 0x25, 0x23, 0x24, 0x2b, 0x37, + 0x50, 0x70, 0x7a, 0x70, 0x4e, 0x48, 0x67, 0x7f, 0x88, 0x8a, 0x7d, 0x76, + 0x74, 0x72, 0x68, 0x58, 0x49, 0x43, 0x43, 0x4b, 0x60, 0x74, 0x7e, 0x83, + 0x89, 0x90, 0x92, 0x92, 0x91, 0x8b, 0x79, 0x5a, 0x48, 0x43, 0x43, 0x44, + 0x46, 0x45, 0x45, 0x47, 0x48, 0x48, 0x4a, 0x4a, 0x49, 0x4c, 0x4e, 0x4f, + 0x4f, 0x50, 0x50, 0x50, 0x50, 0x51, 0x52, 0x53, 0x52, 0x53, 0x54, 0x54, + 0x55, 0x57, 0x59, 0x5a, 0x5a, 0x5c, 0x5c, 0x5e, 0x5f, 0x5f, 0x5f, 0x60, + 0x60, 0x62, 0x64, 0x66, 0x67, 0x67, 0x68, 0x68, 0x69, 0x6b, 0x6d, 0x6d, + 0x6e, 0x6f, 0x71, 0x71, 0x71, 0x71, 0x72, 0x73, 0x73, 0x73, 0x73, 0x72, + 0x6e, 0x6d, 0x6b, 0x69, 0x65, 0x5f, 0x5a, 0x55, 0x52, 0x4e, 0x47, 0x41, + 0x3b, 0x38, 0x31, 0x29, 0x1e, 0x17, 0x14, 0x12, 0x12, 0x11, 0x11, 0x11, + 0x11, 0x12, 0x12, 0x12, 0x12, 0x11, 0x12, 0x11, 0x12, 0x12, 0x12, 0x11, + 0x59, 0x5b, 0x5c, 0x5d, 0x5e, 0x5e, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61, + 0x61, 0x62, 0x63, 0x64, 0x62, 0x61, 0x61, 0x63, 0x63, 0x62, 0x63, 0x63, + 0x61, 0x60, 0x61, 0x62, 0x63, 0x63, 0x62, 0x64, 0x63, 0x64, 0x66, 0x66, + 0x66, 0x68, 0x69, 0x6a, 0x6b, 0x6b, 0x6a, 0x6a, 0x6a, 0x6b, 0x6a, 0x6a, + 0x69, 0x67, 0x64, 0x61, 0x5f, 0x5e, 0x5c, 0x59, 0x5a, 0x5f, 0x64, 0x6c, + 0x75, 0x79, 0x7e, 0x81, 0x84, 0x88, 0x89, 0x8d, 0x8f, 0x8f, 0x8e, 0x8c, + 0x89, 0x86, 0x83, 0x7e, 0x78, 0x6f, 0x69, 0x68, 0x6c, 0x73, 0x79, 0x7e, + 0x81, 0x81, 0x83, 0x85, 0x87, 0x87, 0x86, 0x85, 0x85, 0x84, 0x84, 0x84, + 0x83, 0x84, 0x84, 0x84, 0x85, 0x85, 0x87, 0x87, 0x87, 0x86, 0x87, 0x86, + 0x87, 0x87, 0x87, 0x88, 0x86, 0x85, 0x83, 0x82, 0x81, 0x7f, 0x7e, 0x7d, + 0x7d, 0x7a, 0x7b, 0x7f, 0x81, 0x81, 0x78, 0x71, 0x6e, 0x6b, 0x65, 0x58, + 0x55, 0x64, 0x74, 0x86, 0x9c, 0x74, 0x3f, 0x35, 0x40, 0x57, 0x56, 0x37, + 0x23, 0x23, 0x35, 0x53, 0x67, 0x78, 0x84, 0x95, 0xa0, 0xa0, 0x9b, 0x93, + 0x81, 0x6a, 0x5d, 0x58, 0x56, 0x54, 0x50, 0x53, 0x58, 0x5c, 0x5f, 0x60, + 0x5e, 0x59, 0x54, 0x4d, 0x47, 0x43, 0x43, 0x46, 0x49, 0x3f, 0x2e, 0x25, + 0x22, 0x24, 0x35, 0x38, 0x31, 0x2c, 0x2c, 0x38, 0x59, 0x77, 0x80, 0x76, + 0x56, 0x4d, 0x65, 0x7b, 0x86, 0x87, 0x77, 0x70, 0x73, 0x73, 0x6d, 0x5f, + 0x56, 0x5b, 0x66, 0x7c, 0x96, 0xa0, 0xa2, 0xa4, 0xa7, 0xa8, 0xaa, 0xaa, + 0xa9, 0xa6, 0x98, 0x7a, 0x5d, 0x4f, 0x45, 0x44, 0x44, 0x45, 0x45, 0x47, + 0x48, 0x49, 0x4a, 0x4a, 0x4a, 0x4d, 0x4d, 0x4e, 0x4f, 0x4f, 0x4f, 0x51, + 0x53, 0x53, 0x53, 0x53, 0x53, 0x54, 0x55, 0x55, 0x55, 0x56, 0x59, 0x5a, + 0x5a, 0x5c, 0x5b, 0x5d, 0x60, 0x60, 0x61, 0x61, 0x62, 0x64, 0x65, 0x65, + 0x66, 0x67, 0x68, 0x69, 0x69, 0x6b, 0x6d, 0x6d, 0x6e, 0x6f, 0x70, 0x71, + 0x71, 0x72, 0x74, 0x72, 0x73, 0x74, 0x73, 0x72, 0x6e, 0x6c, 0x6b, 0x69, + 0x65, 0x5e, 0x59, 0x54, 0x52, 0x4e, 0x47, 0x40, 0x3b, 0x38, 0x31, 0x29, + 0x1e, 0x18, 0x14, 0x12, 0x12, 0x11, 0x12, 0x11, 0x11, 0x11, 0x12, 0x12, + 0x12, 0x11, 0x12, 0x11, 0x12, 0x12, 0x11, 0x12, 0x59, 0x5b, 0x5c, 0x5c, + 0x5d, 0x5e, 0x60, 0x61, 0x61, 0x61, 0x62, 0x61, 0x61, 0x62, 0x63, 0x62, + 0x62, 0x62, 0x62, 0x63, 0x63, 0x63, 0x64, 0x64, 0x63, 0x62, 0x62, 0x63, + 0x63, 0x64, 0x63, 0x64, 0x64, 0x65, 0x66, 0x67, 0x67, 0x68, 0x68, 0x6a, + 0x6b, 0x6b, 0x6a, 0x6b, 0x6b, 0x6a, 0x6a, 0x69, 0x68, 0x66, 0x65, 0x63, + 0x61, 0x60, 0x5d, 0x59, 0x5c, 0x61, 0x66, 0x6e, 0x76, 0x7d, 0x82, 0x84, + 0x86, 0x8a, 0x8b, 0x8f, 0x90, 0x91, 0x90, 0x8e, 0x8b, 0x87, 0x84, 0x80, + 0x79, 0x6e, 0x67, 0x66, 0x6b, 0x73, 0x7a, 0x7e, 0x80, 0x80, 0x81, 0x84, + 0x86, 0x86, 0x86, 0x87, 0x85, 0x84, 0x84, 0x84, 0x85, 0x85, 0x84, 0x83, + 0x84, 0x84, 0x85, 0x85, 0x85, 0x86, 0x86, 0x86, 0x87, 0x87, 0x87, 0x88, + 0x87, 0x86, 0x85, 0x84, 0x82, 0x80, 0x7e, 0x7d, 0x7c, 0x7b, 0x7b, 0x81, + 0x86, 0x88, 0x7b, 0x65, 0x55, 0x4b, 0x45, 0x40, 0x4d, 0x62, 0x75, 0x87, + 0x94, 0x66, 0x3d, 0x3a, 0x49, 0x6a, 0x65, 0x3c, 0x25, 0x21, 0x29, 0x42, + 0x53, 0x5c, 0x65, 0x75, 0x88, 0x91, 0x91, 0x8c, 0x7e, 0x69, 0x5d, 0x59, + 0x58, 0x55, 0x4f, 0x4b, 0x4a, 0x4a, 0x4b, 0x4c, 0x4b, 0x47, 0x42, 0x37, + 0x2b, 0x22, 0x1e, 0x1e, 0x1f, 0x1c, 0x16, 0x16, 0x19, 0x23, 0x3a, 0x3d, + 0x35, 0x2f, 0x2d, 0x3a, 0x59, 0x6f, 0x74, 0x6c, 0x58, 0x4f, 0x59, 0x72, + 0x7d, 0x7d, 0x6e, 0x6b, 0x71, 0x73, 0x70, 0x6d, 0x7a, 0x8d, 0x99, 0xa3, + 0xac, 0xac, 0xaa, 0xaa, 0xab, 0xae, 0xab, 0xa9, 0xa4, 0x98, 0x8a, 0x7d, + 0x6f, 0x61, 0x4c, 0x44, 0x44, 0x46, 0x46, 0x47, 0x48, 0x4a, 0x49, 0x49, + 0x4a, 0x4d, 0x4e, 0x4e, 0x4e, 0x4e, 0x4f, 0x51, 0x53, 0x53, 0x53, 0x54, + 0x54, 0x55, 0x56, 0x56, 0x56, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5c, 0x5e, + 0x60, 0x61, 0x61, 0x61, 0x63, 0x65, 0x65, 0x65, 0x66, 0x68, 0x69, 0x69, + 0x6a, 0x6a, 0x6c, 0x6e, 0x6f, 0x70, 0x71, 0x6f, 0x70, 0x71, 0x74, 0x73, + 0x73, 0x74, 0x74, 0x72, 0x6e, 0x6c, 0x6a, 0x68, 0x64, 0x5f, 0x5a, 0x54, + 0x52, 0x4d, 0x46, 0x40, 0x3d, 0x39, 0x33, 0x29, 0x1e, 0x18, 0x15, 0x12, + 0x11, 0x11, 0x11, 0x11, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, + 0x11, 0x11, 0x11, 0x12, 0x58, 0x5b, 0x5c, 0x5c, 0x5c, 0x5e, 0x5f, 0x60, + 0x60, 0x60, 0x62, 0x61, 0x62, 0x63, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, + 0x64, 0x63, 0x64, 0x64, 0x64, 0x63, 0x63, 0x62, 0x63, 0x64, 0x64, 0x63, + 0x64, 0x65, 0x66, 0x66, 0x66, 0x68, 0x69, 0x6a, 0x6b, 0x6b, 0x6b, 0x6b, + 0x6b, 0x6b, 0x6b, 0x6a, 0x69, 0x67, 0x66, 0x64, 0x62, 0x60, 0x5e, 0x5c, + 0x5f, 0x65, 0x6b, 0x72, 0x79, 0x80, 0x84, 0x85, 0x87, 0x8b, 0x8d, 0x90, + 0x92, 0x92, 0x90, 0x8d, 0x8b, 0x88, 0x86, 0x81, 0x79, 0x6f, 0x68, 0x66, + 0x6a, 0x72, 0x79, 0x7d, 0x7e, 0x7f, 0x80, 0x83, 0x85, 0x86, 0x88, 0x89, + 0x87, 0x85, 0x85, 0x85, 0x86, 0x85, 0x84, 0x83, 0x84, 0x84, 0x85, 0x85, + 0x86, 0x87, 0x87, 0x88, 0x87, 0x87, 0x87, 0x87, 0x87, 0x85, 0x84, 0x84, + 0x82, 0x80, 0x7f, 0x7e, 0x7d, 0x7a, 0x7d, 0x87, 0x8d, 0x91, 0x84, 0x64, + 0x47, 0x34, 0x2d, 0x31, 0x53, 0x67, 0x78, 0x84, 0x8a, 0x6b, 0x4e, 0x47, + 0x53, 0x6d, 0x5e, 0x3a, 0x2e, 0x2c, 0x30, 0x3a, 0x48, 0x4d, 0x50, 0x56, + 0x65, 0x73, 0x73, 0x71, 0x69, 0x5d, 0x57, 0x54, 0x53, 0x50, 0x4f, 0x4c, + 0x4a, 0x49, 0x47, 0x3f, 0x38, 0x34, 0x2f, 0x25, 0x1b, 0x16, 0x16, 0x17, + 0x17, 0x16, 0x14, 0x16, 0x19, 0x1f, 0x2d, 0x34, 0x34, 0x32, 0x30, 0x3d, + 0x56, 0x63, 0x65, 0x61, 0x5a, 0x52, 0x56, 0x6e, 0x7a, 0x78, 0x67, 0x64, + 0x6b, 0x71, 0x78, 0x86, 0x9c, 0xa8, 0xac, 0xb0, 0xb4, 0xb5, 0xb4, 0xb2, + 0xb1, 0xb2, 0xaa, 0xa1, 0x97, 0x83, 0x72, 0x6c, 0x6d, 0x68, 0x56, 0x47, + 0x45, 0x47, 0x48, 0x49, 0x4a, 0x4a, 0x49, 0x4a, 0x4b, 0x4d, 0x4d, 0x4f, + 0x4f, 0x4f, 0x50, 0x50, 0x52, 0x53, 0x53, 0x53, 0x53, 0x55, 0x56, 0x57, + 0x56, 0x57, 0x59, 0x5b, 0x5c, 0x5e, 0x5e, 0x60, 0x60, 0x60, 0x61, 0x62, + 0x63, 0x64, 0x65, 0x64, 0x67, 0x69, 0x6a, 0x6b, 0x6b, 0x6b, 0x6c, 0x6f, + 0x70, 0x71, 0x71, 0x70, 0x71, 0x72, 0x74, 0x75, 0x75, 0x75, 0x74, 0x72, + 0x6e, 0x6b, 0x69, 0x67, 0x63, 0x60, 0x5b, 0x55, 0x52, 0x4e, 0x46, 0x40, + 0x3d, 0x3a, 0x33, 0x29, 0x1e, 0x18, 0x15, 0x13, 0x11, 0x10, 0x10, 0x10, + 0x10, 0x11, 0x11, 0x12, 0x13, 0x12, 0x13, 0x12, 0x11, 0x11, 0x11, 0x12, + 0x59, 0x5b, 0x5c, 0x5c, 0x5c, 0x5d, 0x5f, 0x60, 0x61, 0x61, 0x62, 0x61, + 0x62, 0x63, 0x64, 0x65, 0x66, 0x65, 0x64, 0x64, 0x65, 0x64, 0x64, 0x65, + 0x65, 0x64, 0x63, 0x62, 0x63, 0x64, 0x64, 0x63, 0x64, 0x65, 0x65, 0x65, + 0x67, 0x69, 0x69, 0x6a, 0x6b, 0x6b, 0x6b, 0x6b, 0x6c, 0x6b, 0x6c, 0x6b, + 0x6a, 0x68, 0x67, 0x64, 0x61, 0x5f, 0x5f, 0x5e, 0x63, 0x69, 0x6e, 0x76, + 0x7c, 0x81, 0x84, 0x86, 0x87, 0x8b, 0x8d, 0x91, 0x92, 0x93, 0x92, 0x8e, + 0x8c, 0x89, 0x87, 0x83, 0x7b, 0x71, 0x6a, 0x69, 0x6b, 0x72, 0x79, 0x7c, + 0x7d, 0x7e, 0x80, 0x82, 0x84, 0x86, 0x88, 0x89, 0x88, 0x86, 0x86, 0x86, + 0x86, 0x85, 0x84, 0x83, 0x84, 0x84, 0x85, 0x85, 0x86, 0x87, 0x87, 0x88, + 0x88, 0x88, 0x87, 0x87, 0x87, 0x85, 0x84, 0x84, 0x82, 0x81, 0x80, 0x7f, + 0x7c, 0x7b, 0x80, 0x8a, 0x90, 0x93, 0x88, 0x69, 0x48, 0x2f, 0x28, 0x34, + 0x61, 0x78, 0x85, 0x8b, 0x8d, 0x7b, 0x63, 0x54, 0x57, 0x63, 0x4f, 0x36, + 0x38, 0x3c, 0x3f, 0x40, 0x46, 0x48, 0x48, 0x49, 0x55, 0x63, 0x5f, 0x59, + 0x51, 0x4b, 0x49, 0x47, 0x46, 0x45, 0x45, 0x48, 0x49, 0x48, 0x44, 0x38, + 0x2c, 0x26, 0x22, 0x1a, 0x14, 0x13, 0x15, 0x16, 0x15, 0x14, 0x14, 0x17, + 0x1a, 0x1f, 0x26, 0x2f, 0x33, 0x33, 0x32, 0x3e, 0x55, 0x5f, 0x61, 0x5e, + 0x5a, 0x52, 0x57, 0x6e, 0x78, 0x75, 0x61, 0x5d, 0x65, 0x70, 0x82, 0x95, + 0xa7, 0xb2, 0xb4, 0xb2, 0xb5, 0xba, 0xb9, 0xb7, 0xb3, 0xb1, 0xa7, 0x98, + 0x88, 0x6d, 0x5f, 0x5d, 0x62, 0x63, 0x5c, 0x4a, 0x46, 0x47, 0x48, 0x49, + 0x4a, 0x4a, 0x4a, 0x4a, 0x4c, 0x4e, 0x4d, 0x4e, 0x4e, 0x4e, 0x50, 0x50, + 0x51, 0x53, 0x53, 0x53, 0x53, 0x55, 0x56, 0x56, 0x58, 0x58, 0x59, 0x5a, + 0x5b, 0x5e, 0x5e, 0x61, 0x62, 0x62, 0x62, 0x63, 0x64, 0x65, 0x65, 0x64, + 0x67, 0x6a, 0x6b, 0x6b, 0x6c, 0x6c, 0x6e, 0x6f, 0x6f, 0x70, 0x71, 0x70, + 0x71, 0x71, 0x74, 0x75, 0x75, 0x74, 0x73, 0x72, 0x6e, 0x6b, 0x6a, 0x67, + 0x63, 0x60, 0x5b, 0x56, 0x52, 0x4e, 0x46, 0x40, 0x3b, 0x38, 0x31, 0x28, + 0x1e, 0x18, 0x14, 0x12, 0x11, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, + 0x13, 0x13, 0x13, 0x11, 0x11, 0x11, 0x12, 0x11, 0x58, 0x5b, 0x5b, 0x5c, + 0x5c, 0x5d, 0x5f, 0x61, 0x61, 0x61, 0x63, 0x63, 0x63, 0x64, 0x65, 0x66, + 0x66, 0x66, 0x65, 0x65, 0x66, 0x65, 0x65, 0x65, 0x66, 0x65, 0x62, 0x62, + 0x63, 0x64, 0x64, 0x63, 0x64, 0x64, 0x64, 0x65, 0x67, 0x68, 0x68, 0x69, + 0x6b, 0x6b, 0x6b, 0x6b, 0x6c, 0x6c, 0x6c, 0x6c, 0x6b, 0x69, 0x67, 0x64, + 0x61, 0x60, 0x60, 0x5f, 0x64, 0x6c, 0x71, 0x78, 0x7e, 0x82, 0x86, 0x87, + 0x88, 0x8c, 0x8e, 0x92, 0x93, 0x93, 0x93, 0x8f, 0x8c, 0x8a, 0x87, 0x83, + 0x7c, 0x73, 0x6d, 0x6b, 0x6c, 0x72, 0x78, 0x7b, 0x7c, 0x7d, 0x7f, 0x82, + 0x84, 0x86, 0x88, 0x89, 0x88, 0x87, 0x87, 0x86, 0x86, 0x85, 0x84, 0x83, + 0x84, 0x84, 0x86, 0x85, 0x86, 0x87, 0x87, 0x87, 0x88, 0x88, 0x87, 0x87, + 0x87, 0x86, 0x85, 0x84, 0x83, 0x81, 0x80, 0x7f, 0x7d, 0x7c, 0x81, 0x8b, + 0x91, 0x95, 0x8a, 0x6e, 0x4c, 0x30, 0x29, 0x39, 0x6b, 0x83, 0x8c, 0x92, + 0x94, 0x86, 0x6d, 0x5a, 0x57, 0x59, 0x45, 0x35, 0x40, 0x48, 0x4b, 0x49, + 0x4b, 0x4c, 0x4c, 0x4a, 0x54, 0x60, 0x59, 0x51, 0x46, 0x3d, 0x39, 0x37, + 0x36, 0x36, 0x38, 0x3c, 0x40, 0x3f, 0x3a, 0x2e, 0x23, 0x1e, 0x1a, 0x15, + 0x12, 0x13, 0x15, 0x16, 0x15, 0x14, 0x15, 0x19, 0x1b, 0x20, 0x26, 0x2e, + 0x33, 0x34, 0x32, 0x3e, 0x54, 0x5d, 0x5e, 0x5a, 0x59, 0x51, 0x55, 0x6d, + 0x78, 0x75, 0x5f, 0x5a, 0x67, 0x74, 0x89, 0x9b, 0xaa, 0xb5, 0xb7, 0xb4, + 0xb7, 0xbb, 0xbc, 0xbb, 0xb4, 0xad, 0xa1, 0x8e, 0x7c, 0x61, 0x5b, 0x53, + 0x53, 0x56, 0x58, 0x4b, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4a, 0x4b, 0x4b, + 0x4d, 0x4e, 0x4d, 0x4f, 0x4f, 0x4f, 0x50, 0x50, 0x52, 0x53, 0x53, 0x53, + 0x54, 0x55, 0x56, 0x56, 0x58, 0x58, 0x58, 0x59, 0x5a, 0x5d, 0x5f, 0x61, + 0x62, 0x62, 0x62, 0x63, 0x64, 0x65, 0x65, 0x65, 0x67, 0x69, 0x6a, 0x6b, + 0x6c, 0x6d, 0x6e, 0x6f, 0x6f, 0x70, 0x71, 0x70, 0x71, 0x72, 0x74, 0x75, + 0x75, 0x74, 0x73, 0x71, 0x6e, 0x6c, 0x6a, 0x68, 0x63, 0x60, 0x5b, 0x56, + 0x52, 0x4d, 0x46, 0x41, 0x3a, 0x37, 0x31, 0x28, 0x1e, 0x18, 0x14, 0x12, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x13, 0x13, 0x13, 0x11, + 0x11, 0x11, 0x12, 0x12, 0x58, 0x5a, 0x5c, 0x5c, 0x5d, 0x5d, 0x60, 0x61, + 0x61, 0x62, 0x63, 0x63, 0x64, 0x64, 0x66, 0x66, 0x66, 0x66, 0x66, 0x67, + 0x68, 0x68, 0x68, 0x67, 0x65, 0x65, 0x63, 0x62, 0x63, 0x64, 0x64, 0x64, + 0x63, 0x63, 0x63, 0x65, 0x65, 0x67, 0x67, 0x68, 0x6a, 0x6a, 0x6b, 0x6b, + 0x6b, 0x6c, 0x6c, 0x6c, 0x6b, 0x69, 0x67, 0x65, 0x62, 0x61, 0x61, 0x61, + 0x67, 0x70, 0x75, 0x7b, 0x80, 0x85, 0x88, 0x8a, 0x8c, 0x8d, 0x8f, 0x92, + 0x94, 0x94, 0x94, 0x91, 0x8e, 0x8a, 0x87, 0x84, 0x7e, 0x75, 0x70, 0x6f, + 0x6e, 0x72, 0x77, 0x79, 0x7a, 0x7b, 0x7e, 0x81, 0x83, 0x85, 0x88, 0x8a, + 0x8a, 0x89, 0x88, 0x87, 0x86, 0x84, 0x84, 0x85, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x87, 0x86, 0x85, 0x87, 0x87, 0x86, 0x86, 0x85, 0x86, 0x86, 0x86, + 0x83, 0x81, 0x80, 0x7f, 0x7c, 0x7e, 0x83, 0x8c, 0x92, 0x96, 0x8e, 0x75, + 0x53, 0x36, 0x30, 0x43, 0x77, 0x8b, 0x8f, 0x95, 0x9f, 0x96, 0x78, 0x60, + 0x56, 0x4c, 0x3a, 0x3b, 0x4f, 0x59, 0x5c, 0x5b, 0x5d, 0x5e, 0x5c, 0x59, + 0x5d, 0x62, 0x59, 0x50, 0x41, 0x2d, 0x1f, 0x1c, 0x1c, 0x1d, 0x1f, 0x23, + 0x28, 0x28, 0x23, 0x1c, 0x16, 0x15, 0x14, 0x14, 0x13, 0x14, 0x15, 0x15, + 0x15, 0x15, 0x17, 0x1b, 0x1f, 0x24, 0x2a, 0x30, 0x34, 0x35, 0x34, 0x40, + 0x53, 0x5a, 0x59, 0x52, 0x52, 0x4f, 0x52, 0x6a, 0x76, 0x75, 0x5f, 0x5e, + 0x72, 0x82, 0x94, 0xa0, 0xae, 0xb7, 0xb9, 0xba, 0xbe, 0xbd, 0xc3, 0xc1, + 0xb5, 0xa5, 0x92, 0x7b, 0x6a, 0x5a, 0x5b, 0x46, 0x3e, 0x42, 0x4e, 0x4b, + 0x47, 0x48, 0x49, 0x49, 0x4a, 0x4b, 0x4c, 0x4c, 0x4c, 0x4e, 0x4e, 0x50, + 0x50, 0x50, 0x52, 0x52, 0x53, 0x53, 0x53, 0x56, 0x56, 0x56, 0x57, 0x58, + 0x59, 0x58, 0x59, 0x59, 0x5a, 0x5d, 0x5e, 0x61, 0x62, 0x62, 0x62, 0x64, + 0x63, 0x65, 0x65, 0x66, 0x67, 0x69, 0x6a, 0x6b, 0x6c, 0x6e, 0x6e, 0x6f, + 0x71, 0x71, 0x71, 0x72, 0x72, 0x73, 0x74, 0x74, 0x74, 0x73, 0x72, 0x70, + 0x6e, 0x6b, 0x6a, 0x68, 0x65, 0x5f, 0x5a, 0x55, 0x50, 0x4c, 0x48, 0x41, + 0x3a, 0x37, 0x31, 0x29, 0x20, 0x18, 0x14, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x12, 0x12, 0x11, 0x12, 0x12, 0x11, 0x13, 0x12, 0x12, 0x12, 0x11, 0x13, + 0x59, 0x5b, 0x5b, 0x5c, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x62, 0x63, 0x64, + 0x64, 0x65, 0x67, 0x68, 0x67, 0x66, 0x67, 0x68, 0x69, 0x69, 0x69, 0x69, + 0x68, 0x66, 0x64, 0x63, 0x62, 0x63, 0x64, 0x64, 0x63, 0x63, 0x63, 0x65, + 0x66, 0x66, 0x67, 0x68, 0x6a, 0x6b, 0x6c, 0x6c, 0x6c, 0x6b, 0x6c, 0x6c, + 0x6b, 0x69, 0x67, 0x65, 0x64, 0x63, 0x63, 0x64, 0x6b, 0x73, 0x78, 0x7e, + 0x84, 0x88, 0x8b, 0x8c, 0x8e, 0x90, 0x91, 0x94, 0x95, 0x96, 0x96, 0x93, + 0x8f, 0x8c, 0x89, 0x87, 0x80, 0x79, 0x75, 0x74, 0x73, 0x73, 0x74, 0x76, + 0x77, 0x78, 0x7a, 0x7f, 0x82, 0x85, 0x87, 0x89, 0x8a, 0x89, 0x89, 0x8a, + 0x88, 0x86, 0x86, 0x85, 0x86, 0x86, 0x86, 0x85, 0x86, 0x87, 0x86, 0x85, + 0x87, 0x87, 0x87, 0x86, 0x86, 0x87, 0x86, 0x86, 0x83, 0x82, 0x81, 0x7f, + 0x7e, 0x82, 0x88, 0x90, 0x96, 0x99, 0x94, 0x80, 0x5e, 0x42, 0x3d, 0x52, + 0x81, 0x8a, 0x86, 0x8e, 0xa6, 0xad, 0x88, 0x69, 0x59, 0x49, 0x3d, 0x4e, + 0x65, 0x71, 0x7a, 0x79, 0x75, 0x74, 0x73, 0x6e, 0x69, 0x60, 0x58, 0x52, + 0x46, 0x2d, 0x18, 0x12, 0x11, 0x13, 0x14, 0x14, 0x16, 0x17, 0x16, 0x15, + 0x14, 0x15, 0x16, 0x17, 0x17, 0x19, 0x1b, 0x1a, 0x19, 0x19, 0x1c, 0x20, + 0x24, 0x29, 0x2e, 0x34, 0x37, 0x38, 0x3b, 0x4a, 0x56, 0x58, 0x56, 0x51, + 0x50, 0x4f, 0x54, 0x69, 0x74, 0x76, 0x67, 0x6f, 0x85, 0x92, 0x9c, 0xa7, + 0xb3, 0xb6, 0xba, 0xc2, 0xc6, 0xc7, 0xca, 0xc4, 0xb1, 0x97, 0x79, 0x63, + 0x5d, 0x5a, 0x44, 0x3f, 0x55, 0x61, 0x62, 0x57, 0x4f, 0x4d, 0x4c, 0x4d, + 0x4d, 0x4d, 0x4e, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x50, 0x51, 0x53, 0x53, + 0x54, 0x55, 0x55, 0x56, 0x56, 0x56, 0x56, 0x58, 0x5a, 0x5a, 0x5b, 0x5b, + 0x5c, 0x5e, 0x5f, 0x60, 0x60, 0x61, 0x63, 0x65, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x71, 0x72, + 0x72, 0x73, 0x74, 0x74, 0x74, 0x73, 0x72, 0x70, 0x6e, 0x6b, 0x6a, 0x68, + 0x65, 0x5f, 0x5a, 0x54, 0x50, 0x4b, 0x47, 0x41, 0x3c, 0x38, 0x32, 0x2a, + 0x20, 0x17, 0x13, 0x11, 0x10, 0x11, 0x11, 0x11, 0x12, 0x12, 0x11, 0x12, + 0x12, 0x11, 0x13, 0x12, 0x11, 0x12, 0x13, 0x12, 0x59, 0x5c, 0x5c, 0x5c, + 0x5e, 0x5f, 0x5f, 0x61, 0x62, 0x62, 0x62, 0x63, 0x64, 0x65, 0x67, 0x68, + 0x66, 0x66, 0x67, 0x69, 0x69, 0x68, 0x68, 0x68, 0x68, 0x67, 0x66, 0x64, + 0x63, 0x63, 0x64, 0x64, 0x63, 0x63, 0x64, 0x65, 0x65, 0x67, 0x68, 0x69, + 0x6a, 0x6a, 0x6c, 0x6d, 0x6d, 0x6c, 0x6c, 0x6c, 0x6b, 0x6a, 0x68, 0x66, + 0x65, 0x64, 0x64, 0x67, 0x6e, 0x75, 0x7a, 0x81, 0x86, 0x8a, 0x8c, 0x8e, + 0x90, 0x92, 0x92, 0x95, 0x97, 0x97, 0x96, 0x94, 0x90, 0x8d, 0x8b, 0x88, + 0x82, 0x7c, 0x78, 0x77, 0x76, 0x74, 0x74, 0x74, 0x74, 0x75, 0x78, 0x7c, + 0x81, 0x83, 0x85, 0x89, 0x8a, 0x89, 0x8a, 0x8b, 0x8b, 0x88, 0x87, 0x87, + 0x85, 0x84, 0x86, 0x86, 0x86, 0x87, 0x86, 0x86, 0x86, 0x86, 0x86, 0x87, + 0x87, 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x82, 0x84, 0x8b, 0x91, 0x97, + 0x9b, 0x9e, 0x9a, 0x88, 0x6a, 0x52, 0x50, 0x64, 0x88, 0x88, 0x84, 0x8d, + 0xa8, 0xba, 0x99, 0x7f, 0x74, 0x6a, 0x61, 0x71, 0x84, 0x92, 0xa1, 0x95, + 0x7a, 0x71, 0x6d, 0x69, 0x60, 0x53, 0x53, 0x54, 0x50, 0x36, 0x1d, 0x14, + 0x15, 0x1b, 0x21, 0x20, 0x20, 0x20, 0x20, 0x21, 0x20, 0x21, 0x21, 0x21, + 0x23, 0x24, 0x25, 0x24, 0x22, 0x21, 0x23, 0x25, 0x27, 0x2b, 0x30, 0x34, + 0x38, 0x3c, 0x47, 0x5b, 0x62, 0x5c, 0x5b, 0x5d, 0x5c, 0x59, 0x60, 0x72, + 0x79, 0x77, 0x74, 0x81, 0x91, 0x9a, 0xa2, 0xaf, 0xb9, 0xbb, 0xc0, 0xca, + 0xd1, 0xd3, 0xca, 0xbd, 0xa4, 0x86, 0x70, 0x65, 0x5d, 0x49, 0x3a, 0x5e, + 0x81, 0x8b, 0x81, 0x64, 0x58, 0x4e, 0x4d, 0x53, 0x54, 0x53, 0x52, 0x50, + 0x4f, 0x50, 0x50, 0x50, 0x50, 0x50, 0x52, 0x54, 0x55, 0x55, 0x56, 0x56, + 0x56, 0x56, 0x56, 0x58, 0x5a, 0x5a, 0x5c, 0x5c, 0x5c, 0x5e, 0x5e, 0x60, + 0x61, 0x62, 0x63, 0x65, 0x66, 0x66, 0x67, 0x68, 0x6a, 0x6b, 0x6d, 0x6e, + 0x6e, 0x70, 0x71, 0x71, 0x71, 0x70, 0x71, 0x73, 0x73, 0x73, 0x73, 0x74, + 0x74, 0x74, 0x74, 0x72, 0x6f, 0x6b, 0x6a, 0x68, 0x64, 0x5e, 0x5a, 0x55, + 0x51, 0x4c, 0x46, 0x40, 0x3c, 0x38, 0x32, 0x2a, 0x20, 0x17, 0x13, 0x11, + 0x10, 0x11, 0x11, 0x11, 0x12, 0x11, 0x11, 0x11, 0x12, 0x13, 0x13, 0x13, + 0x12, 0x12, 0x13, 0x14, 0x59, 0x5a, 0x5c, 0x5d, 0x5e, 0x5f, 0x5f, 0x60, + 0x61, 0x62, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x67, 0x67, 0x68, 0x69, + 0x69, 0x68, 0x67, 0x67, 0x67, 0x67, 0x67, 0x64, 0x64, 0x63, 0x63, 0x63, + 0x63, 0x64, 0x64, 0x65, 0x65, 0x67, 0x68, 0x6a, 0x6b, 0x6a, 0x6b, 0x6c, + 0x6c, 0x6d, 0x6d, 0x6c, 0x6c, 0x6b, 0x68, 0x68, 0x66, 0x65, 0x65, 0x69, + 0x70, 0x78, 0x7c, 0x82, 0x87, 0x8a, 0x8c, 0x8e, 0x91, 0x93, 0x94, 0x96, + 0x97, 0x97, 0x96, 0x94, 0x90, 0x8e, 0x8d, 0x8a, 0x84, 0x7f, 0x7b, 0x78, + 0x77, 0x76, 0x74, 0x74, 0x73, 0x73, 0x75, 0x7a, 0x7e, 0x81, 0x84, 0x87, + 0x89, 0x8a, 0x8b, 0x8c, 0x8b, 0x89, 0x88, 0x87, 0x86, 0x84, 0x86, 0x87, + 0x87, 0x88, 0x87, 0x86, 0x86, 0x86, 0x87, 0x87, 0x87, 0x87, 0x87, 0x86, + 0x84, 0x83, 0x85, 0x88, 0x8e, 0x95, 0x9a, 0x9e, 0xa0, 0xa1, 0x9c, 0x8f, + 0x76, 0x65, 0x65, 0x77, 0x90, 0x8b, 0x89, 0x8f, 0xa5, 0xb4, 0x97, 0x8b, + 0x8f, 0x9c, 0x90, 0x85, 0x92, 0xa3, 0xb5, 0x9d, 0x6e, 0x5f, 0x5b, 0x57, + 0x4e, 0x4a, 0x55, 0x5b, 0x59, 0x3f, 0x24, 0x1c, 0x20, 0x2c, 0x35, 0x33, + 0x32, 0x32, 0x31, 0x30, 0x2e, 0x2d, 0x2d, 0x2d, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2c, 0x29, 0x28, 0x2a, 0x2a, 0x2d, 0x2f, 0x33, 0x37, 0x3e, 0x4e, 0x65, + 0x67, 0x61, 0x5f, 0x63, 0x63, 0x5b, 0x63, 0x71, 0x77, 0x76, 0x7a, 0x88, + 0x94, 0x9b, 0xa6, 0xb5, 0xbd, 0xbf, 0xc3, 0xcc, 0xd6, 0xd3, 0xc8, 0xb9, + 0x99, 0x7a, 0x75, 0x70, 0x5e, 0x3c, 0x47, 0x71, 0x96, 0x9a, 0x7e, 0x58, + 0x4f, 0x4a, 0x4d, 0x58, 0x5c, 0x59, 0x58, 0x57, 0x54, 0x51, 0x50, 0x50, + 0x51, 0x51, 0x51, 0x53, 0x54, 0x54, 0x55, 0x54, 0x56, 0x56, 0x57, 0x58, + 0x59, 0x5a, 0x5b, 0x5c, 0x5c, 0x5f, 0x5e, 0x60, 0x61, 0x61, 0x62, 0x65, + 0x65, 0x66, 0x67, 0x68, 0x69, 0x6c, 0x6e, 0x6e, 0x6e, 0x6f, 0x71, 0x70, + 0x70, 0x70, 0x72, 0x73, 0x72, 0x73, 0x73, 0x73, 0x74, 0x74, 0x74, 0x72, + 0x6f, 0x6b, 0x69, 0x68, 0x64, 0x5f, 0x58, 0x54, 0x51, 0x4c, 0x46, 0x40, + 0x3c, 0x38, 0x32, 0x2b, 0x21, 0x18, 0x14, 0x11, 0x10, 0x11, 0x10, 0x11, + 0x12, 0x11, 0x11, 0x11, 0x12, 0x13, 0x12, 0x13, 0x12, 0x11, 0x12, 0x13, + 0x58, 0x5a, 0x5c, 0x5d, 0x5e, 0x5f, 0x5f, 0x60, 0x61, 0x62, 0x62, 0x64, + 0x64, 0x65, 0x66, 0x66, 0x67, 0x67, 0x68, 0x69, 0x69, 0x68, 0x67, 0x67, + 0x67, 0x67, 0x67, 0x65, 0x64, 0x64, 0x64, 0x63, 0x63, 0x64, 0x64, 0x65, + 0x65, 0x67, 0x68, 0x69, 0x6a, 0x6a, 0x6b, 0x6c, 0x6c, 0x6e, 0x6d, 0x6c, + 0x6b, 0x6a, 0x68, 0x68, 0x67, 0x66, 0x65, 0x6a, 0x72, 0x7a, 0x7e, 0x83, + 0x87, 0x8a, 0x8d, 0x8f, 0x91, 0x93, 0x94, 0x96, 0x97, 0x97, 0x96, 0x94, + 0x90, 0x8f, 0x8e, 0x8c, 0x86, 0x81, 0x7d, 0x7a, 0x79, 0x78, 0x75, 0x73, + 0x72, 0x72, 0x74, 0x79, 0x7d, 0x7f, 0x83, 0x86, 0x88, 0x8a, 0x8b, 0x8c, + 0x8c, 0x8a, 0x89, 0x88, 0x86, 0x84, 0x85, 0x87, 0x87, 0x87, 0x87, 0x86, + 0x86, 0x86, 0x87, 0x88, 0x87, 0x87, 0x86, 0x85, 0x85, 0x8b, 0x93, 0x98, + 0x9f, 0xa3, 0xa4, 0xa6, 0xa6, 0xa5, 0xa0, 0x96, 0x85, 0x78, 0x78, 0x85, + 0x97, 0x91, 0x8d, 0x91, 0xa1, 0xad, 0x91, 0x89, 0x95, 0xb2, 0xaa, 0x8b, + 0x8f, 0x9f, 0xb5, 0x9d, 0x69, 0x58, 0x54, 0x4e, 0x44, 0x45, 0x56, 0x5f, + 0x5d, 0x44, 0x2c, 0x27, 0x2b, 0x38, 0x40, 0x3f, 0x3e, 0x3e, 0x3c, 0x3a, + 0x38, 0x36, 0x35, 0x34, 0x34, 0x34, 0x34, 0x34, 0x32, 0x2f, 0x2d, 0x2d, + 0x2e, 0x2f, 0x31, 0x34, 0x38, 0x3e, 0x4f, 0x65, 0x67, 0x61, 0x61, 0x67, + 0x69, 0x5f, 0x65, 0x70, 0x74, 0x75, 0x7c, 0x8c, 0x97, 0x9e, 0xa9, 0xb8, + 0xbe, 0xc1, 0xc4, 0xcd, 0xd6, 0xcf, 0xc4, 0xb4, 0x92, 0x74, 0x74, 0x6e, + 0x5a, 0x3b, 0x51, 0x71, 0x8d, 0x8c, 0x6d, 0x52, 0x55, 0x55, 0x56, 0x5c, + 0x61, 0x5f, 0x5d, 0x5b, 0x57, 0x53, 0x50, 0x50, 0x50, 0x51, 0x51, 0x53, + 0x53, 0x53, 0x54, 0x54, 0x56, 0x57, 0x58, 0x58, 0x59, 0x5a, 0x5b, 0x5b, + 0x5c, 0x5f, 0x5e, 0x60, 0x60, 0x61, 0x62, 0x65, 0x66, 0x67, 0x67, 0x67, + 0x69, 0x6c, 0x6e, 0x6e, 0x6d, 0x6f, 0x70, 0x70, 0x70, 0x70, 0x72, 0x73, + 0x73, 0x72, 0x72, 0x73, 0x74, 0x74, 0x73, 0x71, 0x6f, 0x6b, 0x69, 0x68, + 0x64, 0x5f, 0x58, 0x54, 0x51, 0x4c, 0x46, 0x40, 0x3b, 0x37, 0x32, 0x2a, + 0x20, 0x18, 0x14, 0x11, 0x10, 0x10, 0x11, 0x11, 0x12, 0x10, 0x11, 0x11, + 0x11, 0x12, 0x12, 0x13, 0x12, 0x11, 0x11, 0x12, 0x57, 0x59, 0x5c, 0x5d, + 0x5e, 0x5f, 0x5f, 0x60, 0x61, 0x61, 0x61, 0x63, 0x64, 0x65, 0x66, 0x66, + 0x66, 0x67, 0x68, 0x69, 0x69, 0x68, 0x68, 0x68, 0x67, 0x68, 0x67, 0x66, + 0x65, 0x65, 0x63, 0x63, 0x64, 0x64, 0x64, 0x65, 0x66, 0x67, 0x68, 0x68, + 0x69, 0x69, 0x6b, 0x6b, 0x6b, 0x6d, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x68, + 0x68, 0x67, 0x66, 0x6b, 0x74, 0x7b, 0x7f, 0x83, 0x88, 0x8a, 0x8e, 0x90, + 0x92, 0x94, 0x95, 0x97, 0x98, 0x97, 0x96, 0x94, 0x91, 0x90, 0x8f, 0x8d, + 0x88, 0x82, 0x7f, 0x7e, 0x7b, 0x7a, 0x76, 0x74, 0x72, 0x70, 0x71, 0x76, + 0x7a, 0x7d, 0x80, 0x85, 0x87, 0x8a, 0x8b, 0x8c, 0x8c, 0x8b, 0x8a, 0x88, + 0x85, 0x83, 0x84, 0x86, 0x86, 0x86, 0x87, 0x86, 0x87, 0x88, 0x87, 0x87, + 0x88, 0x87, 0x86, 0x86, 0x90, 0xa3, 0xb5, 0xbc, 0xc0, 0xbd, 0xb8, 0xb4, + 0xb1, 0xae, 0xa9, 0xa4, 0xa0, 0x98, 0x94, 0x95, 0x9d, 0x97, 0x91, 0x91, + 0x99, 0xa6, 0x8d, 0x7c, 0x8b, 0xb8, 0xbe, 0x94, 0x80, 0x88, 0xa2, 0x97, + 0x6c, 0x5a, 0x53, 0x49, 0x3d, 0x43, 0x58, 0x61, 0x60, 0x4f, 0x3f, 0x3c, + 0x3f, 0x49, 0x4e, 0x4c, 0x4b, 0x4a, 0x48, 0x45, 0x43, 0x40, 0x3f, 0x3d, + 0x3c, 0x3c, 0x3d, 0x3c, 0x3a, 0x35, 0x34, 0x33, 0x33, 0x33, 0x35, 0x37, + 0x39, 0x3c, 0x49, 0x5e, 0x62, 0x5e, 0x60, 0x6a, 0x71, 0x69, 0x69, 0x6f, + 0x71, 0x75, 0x81, 0x94, 0x9d, 0xa4, 0xaf, 0xba, 0xc1, 0xc4, 0xc7, 0xce, + 0xd3, 0xc9, 0xbc, 0xaa, 0x87, 0x74, 0x6c, 0x5a, 0x4b, 0x42, 0x62, 0x6f, + 0x76, 0x6e, 0x55, 0x5c, 0x74, 0x77, 0x70, 0x63, 0x66, 0x68, 0x64, 0x61, + 0x5c, 0x56, 0x51, 0x50, 0x50, 0x51, 0x51, 0x53, 0x53, 0x54, 0x54, 0x54, + 0x56, 0x56, 0x57, 0x58, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5e, 0x5e, 0x60, + 0x60, 0x61, 0x62, 0x65, 0x67, 0x68, 0x68, 0x68, 0x6a, 0x6b, 0x6d, 0x6e, + 0x6d, 0x6e, 0x70, 0x70, 0x6f, 0x6f, 0x71, 0x72, 0x72, 0x72, 0x72, 0x74, + 0x73, 0x73, 0x72, 0x70, 0x6f, 0x6b, 0x69, 0x68, 0x64, 0x5f, 0x58, 0x54, + 0x51, 0x4c, 0x46, 0x40, 0x3b, 0x37, 0x31, 0x29, 0x1e, 0x18, 0x14, 0x11, + 0x10, 0x10, 0x12, 0x12, 0x10, 0x10, 0x10, 0x10, 0x11, 0x12, 0x12, 0x13, + 0x12, 0x11, 0x12, 0x11, 0x57, 0x59, 0x5b, 0x5c, 0x5d, 0x5e, 0x5e, 0x5f, + 0x60, 0x61, 0x61, 0x63, 0x64, 0x65, 0x67, 0x67, 0x67, 0x69, 0x69, 0x6a, + 0x6a, 0x69, 0x69, 0x69, 0x67, 0x67, 0x66, 0x65, 0x65, 0x66, 0x65, 0x63, + 0x63, 0x63, 0x66, 0x66, 0x66, 0x67, 0x68, 0x68, 0x69, 0x6b, 0x6a, 0x6b, + 0x6c, 0x6d, 0x6d, 0x6b, 0x6a, 0x6a, 0x69, 0x69, 0x69, 0x68, 0x68, 0x6e, + 0x77, 0x7d, 0x80, 0x84, 0x89, 0x8d, 0x8f, 0x90, 0x93, 0x95, 0x95, 0x97, + 0x97, 0x97, 0x97, 0x95, 0x93, 0x93, 0x92, 0x8f, 0x8a, 0x86, 0x83, 0x81, + 0x7e, 0x7b, 0x79, 0x75, 0x73, 0x70, 0x6d, 0x72, 0x78, 0x7b, 0x7e, 0x82, + 0x87, 0x89, 0x8a, 0x8a, 0x8b, 0x8c, 0x8b, 0x8a, 0x88, 0x84, 0x83, 0x85, + 0x86, 0x87, 0x86, 0x86, 0x87, 0x88, 0x87, 0x87, 0x87, 0x86, 0x8a, 0x99, + 0xb8, 0xca, 0xd0, 0xd2, 0xd1, 0xd1, 0xce, 0xc8, 0xc2, 0xbb, 0xb5, 0xaf, + 0xac, 0xa8, 0xa6, 0xa2, 0x9b, 0x95, 0x90, 0x8f, 0x95, 0xb0, 0x9e, 0x78, + 0x79, 0xa5, 0xca, 0xb5, 0x8a, 0x7a, 0x80, 0x8f, 0x7b, 0x60, 0x53, 0x4a, + 0x43, 0x4c, 0x5d, 0x63, 0x63, 0x5b, 0x55, 0x54, 0x55, 0x59, 0x5b, 0x58, + 0x58, 0x57, 0x54, 0x51, 0x4e, 0x4b, 0x49, 0x46, 0x44, 0x44, 0x48, 0x48, + 0x44, 0x3e, 0x3b, 0x3a, 0x39, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x41, 0x4f, + 0x57, 0x58, 0x5c, 0x65, 0x70, 0x71, 0x70, 0x72, 0x75, 0x7e, 0x8d, 0x9d, + 0xa7, 0xab, 0xb3, 0xbd, 0xc3, 0xc7, 0xcb, 0xce, 0xd2, 0xc3, 0xac, 0x98, + 0x80, 0x89, 0x70, 0x3e, 0x31, 0x4a, 0x7c, 0x92, 0x8b, 0x81, 0x77, 0x88, + 0x92, 0x8d, 0x82, 0x6e, 0x66, 0x71, 0x70, 0x6c, 0x65, 0x5b, 0x54, 0x51, + 0x50, 0x51, 0x51, 0x52, 0x54, 0x55, 0x56, 0x56, 0x57, 0x58, 0x58, 0x59, + 0x5a, 0x5c, 0x5c, 0x5c, 0x5e, 0x60, 0x60, 0x61, 0x61, 0x63, 0x64, 0x65, + 0x68, 0x69, 0x69, 0x69, 0x6b, 0x6c, 0x6e, 0x6f, 0x6f, 0x70, 0x70, 0x70, + 0x70, 0x70, 0x71, 0x71, 0x71, 0x71, 0x72, 0x73, 0x73, 0x72, 0x70, 0x6f, + 0x6d, 0x6a, 0x69, 0x68, 0x64, 0x5e, 0x56, 0x52, 0x50, 0x4c, 0x46, 0x40, + 0x3a, 0x37, 0x33, 0x2b, 0x1e, 0x16, 0x13, 0x12, 0x12, 0x11, 0x11, 0x11, + 0x10, 0x11, 0x11, 0x11, 0x12, 0x13, 0x13, 0x13, 0x13, 0x12, 0x11, 0x12, + 0x59, 0x5b, 0x5c, 0x5c, 0x5c, 0x5e, 0x5e, 0x60, 0x60, 0x61, 0x60, 0x63, + 0x64, 0x65, 0x66, 0x66, 0x68, 0x69, 0x6a, 0x6b, 0x6a, 0x6a, 0x6a, 0x6a, + 0x69, 0x68, 0x68, 0x67, 0x67, 0x67, 0x67, 0x64, 0x64, 0x65, 0x66, 0x66, + 0x66, 0x67, 0x68, 0x68, 0x6a, 0x6b, 0x6a, 0x6b, 0x6d, 0x6e, 0x6d, 0x6b, + 0x6b, 0x6b, 0x6a, 0x6b, 0x6a, 0x6a, 0x6b, 0x70, 0x79, 0x7e, 0x81, 0x85, + 0x89, 0x8d, 0x8e, 0x8f, 0x93, 0x95, 0x95, 0x98, 0x98, 0x98, 0x98, 0x96, + 0x95, 0x95, 0x94, 0x90, 0x8b, 0x88, 0x84, 0x82, 0x80, 0x7d, 0x7b, 0x78, + 0x76, 0x72, 0x6f, 0x72, 0x75, 0x78, 0x7b, 0x80, 0x85, 0x88, 0x89, 0x8a, + 0x8b, 0x8c, 0x8b, 0x8a, 0x8a, 0x86, 0x84, 0x83, 0x84, 0x85, 0x86, 0x86, + 0x88, 0x88, 0x87, 0x87, 0x88, 0x93, 0xa3, 0xbe, 0xce, 0xd1, 0xd1, 0xd0, + 0xd1, 0xd3, 0xd6, 0xdb, 0xd9, 0xd1, 0xc2, 0xb8, 0xb2, 0xaf, 0xab, 0xa5, + 0xa0, 0x93, 0x8b, 0x88, 0x8c, 0xad, 0xaf, 0x88, 0x78, 0x86, 0xbe, 0xc9, + 0xad, 0x96, 0x81, 0x83, 0x7a, 0x67, 0x5f, 0x5d, 0x5f, 0x64, 0x68, 0x68, + 0x64, 0x5f, 0x5f, 0x5f, 0x60, 0x60, 0x61, 0x60, 0x5f, 0x5e, 0x5c, 0x5a, + 0x57, 0x54, 0x51, 0x4f, 0x4c, 0x4c, 0x50, 0x51, 0x4c, 0x48, 0x45, 0x43, + 0x40, 0x3f, 0x3f, 0x3f, 0x40, 0x41, 0x41, 0x46, 0x4d, 0x50, 0x51, 0x54, + 0x60, 0x6e, 0x75, 0x7b, 0x80, 0x89, 0x96, 0xa2, 0xac, 0xb3, 0xba, 0xc0, + 0xc4, 0xc9, 0xcb, 0xcd, 0xcc, 0xba, 0x9c, 0x8d, 0x89, 0x95, 0x76, 0x49, + 0x42, 0x5a, 0x70, 0x71, 0x6c, 0x74, 0x8c, 0x93, 0x8b, 0x88, 0x83, 0x74, + 0x62, 0x72, 0x7a, 0x78, 0x6f, 0x63, 0x5a, 0x54, 0x53, 0x52, 0x52, 0x52, + 0x54, 0x55, 0x55, 0x57, 0x57, 0x59, 0x5a, 0x5a, 0x5c, 0x5e, 0x5e, 0x5e, + 0x5f, 0x5f, 0x5f, 0x61, 0x61, 0x62, 0x63, 0x65, 0x67, 0x69, 0x69, 0x69, + 0x6b, 0x6d, 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x70, 0x70, 0x71, 0x71, 0x70, + 0x70, 0x71, 0x72, 0x73, 0x73, 0x72, 0x71, 0x6f, 0x6d, 0x6a, 0x69, 0x67, + 0x63, 0x5d, 0x56, 0x52, 0x50, 0x4c, 0x46, 0x40, 0x3b, 0x38, 0x34, 0x2d, + 0x1f, 0x18, 0x14, 0x12, 0x11, 0x10, 0x11, 0x11, 0x10, 0x10, 0x11, 0x11, + 0x11, 0x13, 0x13, 0x12, 0x13, 0x12, 0x11, 0x12, 0x59, 0x5b, 0x5b, 0x5b, + 0x5b, 0x5e, 0x5f, 0x60, 0x60, 0x61, 0x60, 0x63, 0x64, 0x65, 0x66, 0x68, + 0x69, 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x69, 0x69, 0x69, 0x68, + 0x68, 0x68, 0x67, 0x65, 0x66, 0x66, 0x65, 0x65, 0x65, 0x67, 0x68, 0x68, + 0x6a, 0x6a, 0x6b, 0x6b, 0x6c, 0x6e, 0x6e, 0x6d, 0x6d, 0x6c, 0x6c, 0x6c, + 0x6b, 0x6b, 0x6d, 0x72, 0x7a, 0x80, 0x83, 0x86, 0x8a, 0x8d, 0x8f, 0x90, + 0x93, 0x94, 0x95, 0x98, 0x9a, 0x9a, 0x99, 0x97, 0x97, 0x96, 0x95, 0x92, + 0x8c, 0x88, 0x87, 0x85, 0x83, 0x80, 0x7e, 0x7a, 0x78, 0x74, 0x70, 0x72, + 0x74, 0x77, 0x79, 0x7e, 0x84, 0x86, 0x88, 0x8a, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x88, 0x86, 0x84, 0x83, 0x84, 0x86, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x90, 0xad, 0xbe, 0xcb, 0xce, 0xd0, 0xcf, 0xcd, 0xcc, 0xcd, 0xd2, 0xd9, + 0xdc, 0xdd, 0xd2, 0xbf, 0xb6, 0xb1, 0xad, 0xa7, 0xa2, 0x96, 0x8b, 0x85, + 0x83, 0x9f, 0xb6, 0xa0, 0x8c, 0x7e, 0xa1, 0xb8, 0xbf, 0xb9, 0x9f, 0x7e, + 0x77, 0x77, 0x76, 0x74, 0x72, 0x73, 0x6f, 0x6c, 0x67, 0x5f, 0x5d, 0x5d, + 0x5e, 0x5f, 0x61, 0x61, 0x61, 0x61, 0x60, 0x5f, 0x5d, 0x5a, 0x58, 0x57, + 0x55, 0x55, 0x56, 0x55, 0x52, 0x51, 0x4e, 0x4b, 0x48, 0x46, 0x45, 0x44, + 0x44, 0x45, 0x46, 0x47, 0x4b, 0x4e, 0x4f, 0x50, 0x5c, 0x70, 0x7b, 0x82, + 0x86, 0x8f, 0x9b, 0xa7, 0xb1, 0xb8, 0xc0, 0xc2, 0xc5, 0xc6, 0xc9, 0xcc, + 0xca, 0xb3, 0x90, 0x88, 0x8e, 0x82, 0x87, 0x81, 0x7f, 0x8a, 0x97, 0x7b, + 0x85, 0x92, 0x9e, 0x9a, 0x86, 0x68, 0x61, 0x67, 0x60, 0x6b, 0x7d, 0x81, + 0x77, 0x69, 0x5f, 0x58, 0x55, 0x54, 0x53, 0x53, 0x54, 0x55, 0x55, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x60, 0x61, + 0x62, 0x63, 0x65, 0x66, 0x67, 0x68, 0x69, 0x69, 0x6b, 0x6d, 0x6f, 0x6f, + 0x70, 0x70, 0x70, 0x70, 0x70, 0x71, 0x71, 0x71, 0x71, 0x72, 0x73, 0x74, + 0x73, 0x72, 0x71, 0x6f, 0x6e, 0x6b, 0x69, 0x67, 0x62, 0x5e, 0x57, 0x52, + 0x50, 0x4d, 0x47, 0x40, 0x3c, 0x39, 0x35, 0x2d, 0x20, 0x18, 0x14, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x10, 0x11, 0x12, 0x11, 0x11, 0x12, 0x12, 0x13, + 0x12, 0x12, 0x12, 0x11, 0x59, 0x5b, 0x5b, 0x5b, 0x5c, 0x5d, 0x5f, 0x60, + 0x60, 0x61, 0x61, 0x62, 0x64, 0x65, 0x66, 0x68, 0x69, 0x69, 0x6a, 0x6a, + 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x69, 0x69, 0x68, 0x68, 0x67, 0x66, + 0x66, 0x66, 0x64, 0x64, 0x66, 0x68, 0x68, 0x68, 0x6a, 0x6a, 0x6b, 0x6b, + 0x6c, 0x6d, 0x6e, 0x6d, 0x6d, 0x6d, 0x6c, 0x6c, 0x6b, 0x6b, 0x6d, 0x73, + 0x7b, 0x81, 0x83, 0x87, 0x8a, 0x8e, 0x90, 0x91, 0x93, 0x94, 0x96, 0x98, + 0x9a, 0x9a, 0x9a, 0x98, 0x98, 0x98, 0x96, 0x92, 0x8c, 0x88, 0x87, 0x86, + 0x84, 0x82, 0x7f, 0x7c, 0x79, 0x76, 0x71, 0x72, 0x74, 0x76, 0x79, 0x7d, + 0x82, 0x85, 0x87, 0x89, 0x8b, 0x8b, 0x8b, 0x8c, 0x8b, 0x88, 0x86, 0x84, + 0x83, 0x84, 0x86, 0x87, 0x87, 0x87, 0x87, 0x89, 0x9b, 0xbc, 0xca, 0xcb, + 0xc8, 0xc8, 0xc6, 0xc5, 0xc4, 0xc4, 0xcd, 0xd5, 0xda, 0xde, 0xda, 0xc7, + 0xbd, 0xb4, 0xb0, 0xaa, 0xa2, 0x98, 0x8f, 0x87, 0x81, 0x96, 0xb7, 0xae, + 0x9c, 0x85, 0x93, 0xa7, 0xc0, 0xc4, 0xac, 0x82, 0x7d, 0x85, 0x85, 0x7e, + 0x7a, 0x78, 0x73, 0x6f, 0x69, 0x60, 0x5c, 0x5b, 0x5c, 0x5e, 0x60, 0x62, + 0x62, 0x62, 0x61, 0x61, 0x61, 0x5f, 0x5e, 0x5e, 0x5d, 0x5b, 0x5b, 0x5b, + 0x58, 0x57, 0x54, 0x51, 0x4f, 0x4c, 0x49, 0x48, 0x49, 0x4a, 0x4b, 0x4c, + 0x4e, 0x50, 0x51, 0x53, 0x61, 0x75, 0x80, 0x87, 0x8b, 0x93, 0x9f, 0xac, + 0xb5, 0xbc, 0xc3, 0xc4, 0xc6, 0xc6, 0xc8, 0xcb, 0xc8, 0xac, 0x8a, 0x87, + 0x95, 0x7b, 0x96, 0xa5, 0xa8, 0xab, 0xae, 0x83, 0x94, 0xa3, 0xa3, 0x94, + 0x7d, 0x5b, 0x55, 0x65, 0x64, 0x67, 0x7d, 0x83, 0x7b, 0x6e, 0x61, 0x5a, + 0x57, 0x55, 0x54, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, + 0x5c, 0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x60, 0x62, 0x63, 0x64, 0x65, 0x66, + 0x66, 0x68, 0x6a, 0x6a, 0x6c, 0x6d, 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x70, + 0x70, 0x70, 0x71, 0x71, 0x72, 0x73, 0x73, 0x74, 0x73, 0x72, 0x72, 0x70, + 0x6e, 0x6a, 0x69, 0x67, 0x62, 0x5e, 0x58, 0x53, 0x51, 0x4d, 0x46, 0x40, + 0x3c, 0x39, 0x35, 0x2c, 0x20, 0x18, 0x15, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x11, 0x11, 0x12, 0x11, 0x11, 0x13, 0x13, 0x13, 0x12, 0x12, 0x12, 0x11, + 0x59, 0x5b, 0x5b, 0x5b, 0x5c, 0x5e, 0x5e, 0x5f, 0x60, 0x62, 0x63, 0x63, + 0x64, 0x65, 0x66, 0x67, 0x69, 0x6a, 0x6a, 0x6b, 0x6a, 0x6a, 0x6b, 0x6b, + 0x6b, 0x6b, 0x6a, 0x69, 0x69, 0x69, 0x67, 0x68, 0x67, 0x67, 0x65, 0x65, + 0x67, 0x68, 0x68, 0x68, 0x6a, 0x6a, 0x6b, 0x6b, 0x6b, 0x6d, 0x6d, 0x6d, + 0x6d, 0x6c, 0x6d, 0x6c, 0x6c, 0x6d, 0x6f, 0x75, 0x7c, 0x81, 0x84, 0x88, + 0x8b, 0x8f, 0x91, 0x92, 0x92, 0x94, 0x96, 0x99, 0x9a, 0x9a, 0x99, 0x99, + 0x99, 0x98, 0x97, 0x92, 0x8e, 0x8b, 0x8a, 0x88, 0x86, 0x83, 0x81, 0x7e, + 0x7c, 0x78, 0x73, 0x73, 0x75, 0x77, 0x79, 0x7d, 0x80, 0x83, 0x85, 0x88, + 0x8a, 0x8b, 0x8c, 0x8c, 0x8c, 0x89, 0x86, 0x85, 0x84, 0x84, 0x85, 0x86, + 0x86, 0x86, 0x86, 0x8e, 0xad, 0xc6, 0xcc, 0xc2, 0xb5, 0xb0, 0xb1, 0xb3, + 0xb5, 0xb8, 0xc5, 0xce, 0xd1, 0xd7, 0xdb, 0xd7, 0xc9, 0xbb, 0xb5, 0xae, + 0xa1, 0x9a, 0x96, 0x90, 0x84, 0x89, 0xaf, 0xb7, 0xae, 0x98, 0x8e, 0x91, + 0xb0, 0xb7, 0xa4, 0x8d, 0x90, 0x95, 0x91, 0x83, 0x7b, 0x7b, 0x79, 0x75, + 0x6d, 0x62, 0x5b, 0x5a, 0x5b, 0x5e, 0x61, 0x63, 0x65, 0x65, 0x63, 0x64, + 0x67, 0x66, 0x65, 0x67, 0x66, 0x62, 0x63, 0x63, 0x61, 0x5e, 0x5a, 0x5a, + 0x58, 0x55, 0x52, 0x52, 0x53, 0x54, 0x56, 0x56, 0x57, 0x57, 0x58, 0x5d, + 0x6e, 0x7e, 0x86, 0x8d, 0x92, 0x9a, 0xa7, 0xb4, 0xbd, 0xc0, 0xc3, 0xc5, + 0xc8, 0xc7, 0xc8, 0xca, 0xc4, 0xa2, 0x81, 0x85, 0x9e, 0x82, 0xa1, 0xbc, + 0xc4, 0xc3, 0xb4, 0x82, 0x97, 0xa5, 0x9e, 0x82, 0x6f, 0x64, 0x64, 0x6c, + 0x66, 0x5c, 0x71, 0x7c, 0x7e, 0x72, 0x66, 0x5e, 0x5a, 0x57, 0x55, 0x54, + 0x54, 0x55, 0x57, 0x57, 0x59, 0x59, 0x5a, 0x5b, 0x5c, 0x5e, 0x5f, 0x5f, + 0x5e, 0x5f, 0x60, 0x63, 0x65, 0x65, 0x65, 0x66, 0x66, 0x68, 0x69, 0x6b, + 0x6d, 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x70, 0x71, 0x71, 0x71, 0x73, + 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x71, 0x6e, 0x6a, 0x68, 0x66, + 0x63, 0x5e, 0x58, 0x54, 0x52, 0x4d, 0x47, 0x3f, 0x3d, 0x3b, 0x36, 0x2c, + 0x21, 0x1a, 0x16, 0x13, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x11, 0x10, + 0x11, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x11, 0x59, 0x5b, 0x5a, 0x5b, + 0x5c, 0x5d, 0x5d, 0x5f, 0x60, 0x61, 0x63, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x69, 0x69, 0x6a, 0x6b, 0x6a, 0x6a, 0x6a, 0x6b, 0x6b, 0x6c, 0x6b, 0x69, + 0x68, 0x68, 0x68, 0x68, 0x67, 0x67, 0x68, 0x67, 0x67, 0x68, 0x68, 0x68, + 0x6a, 0x6a, 0x6b, 0x6b, 0x6b, 0x6c, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6c, + 0x6c, 0x6d, 0x70, 0x77, 0x7f, 0x83, 0x85, 0x89, 0x8d, 0x91, 0x92, 0x92, + 0x93, 0x94, 0x96, 0x99, 0x99, 0x99, 0x9a, 0x9a, 0x98, 0x98, 0x96, 0x92, + 0x8e, 0x8d, 0x8b, 0x89, 0x88, 0x85, 0x83, 0x80, 0x7d, 0x7a, 0x76, 0x77, + 0x77, 0x78, 0x7a, 0x7c, 0x7f, 0x81, 0x83, 0x86, 0x88, 0x8b, 0x8c, 0x8c, + 0x8c, 0x89, 0x87, 0x85, 0x84, 0x84, 0x83, 0x83, 0x85, 0x85, 0x88, 0x9b, + 0xbf, 0xc4, 0xba, 0xa0, 0x86, 0x88, 0x92, 0x9b, 0xa9, 0xbe, 0xbe, 0xbb, + 0xbe, 0xca, 0xd3, 0xd9, 0xd2, 0xc5, 0xbc, 0xb1, 0xa6, 0x99, 0x99, 0x96, + 0x8b, 0x82, 0x94, 0xa9, 0xaf, 0xa7, 0x95, 0x88, 0x86, 0x80, 0x74, 0x82, + 0x96, 0x9b, 0x96, 0x85, 0x75, 0x80, 0x81, 0x7d, 0x73, 0x68, 0x60, 0x5e, + 0x5e, 0x61, 0x64, 0x67, 0x6a, 0x6c, 0x6c, 0x6a, 0x6b, 0x6b, 0x6c, 0x6d, + 0x6d, 0x69, 0x68, 0x68, 0x67, 0x65, 0x61, 0x61, 0x61, 0x5e, 0x5b, 0x5e, + 0x61, 0x62, 0x62, 0x61, 0x63, 0x63, 0x64, 0x69, 0x77, 0x83, 0x8a, 0x90, + 0x97, 0xa3, 0xae, 0xba, 0xc1, 0xc4, 0xc6, 0xc8, 0xca, 0xc8, 0xc8, 0xca, + 0xc0, 0x9e, 0x7c, 0x7d, 0x95, 0x7c, 0x73, 0x93, 0xa1, 0xa3, 0xa3, 0x91, + 0xa1, 0xa6, 0x97, 0x87, 0x80, 0x8a, 0x81, 0x5b, 0x34, 0x34, 0x4e, 0x65, + 0x7e, 0x7a, 0x6d, 0x64, 0x5f, 0x59, 0x56, 0x56, 0x55, 0x56, 0x57, 0x57, + 0x59, 0x5a, 0x5a, 0x5b, 0x5d, 0x5f, 0x60, 0x60, 0x5e, 0x5f, 0x60, 0x63, + 0x64, 0x64, 0x64, 0x66, 0x66, 0x68, 0x69, 0x6b, 0x6d, 0x6e, 0x6e, 0x6f, + 0x6f, 0x71, 0x70, 0x70, 0x70, 0x71, 0x71, 0x72, 0x72, 0x72, 0x72, 0x72, + 0x73, 0x73, 0x73, 0x71, 0x6e, 0x6a, 0x68, 0x67, 0x63, 0x5d, 0x57, 0x53, + 0x51, 0x4d, 0x47, 0x40, 0x3d, 0x3b, 0x36, 0x2c, 0x22, 0x1a, 0x16, 0x12, + 0x10, 0x11, 0x11, 0x11, 0x12, 0x12, 0x11, 0x10, 0x11, 0x12, 0x11, 0x11, + 0x13, 0x13, 0x13, 0x11, 0x5a, 0x5a, 0x5a, 0x5a, 0x5b, 0x5c, 0x5c, 0x5d, + 0x5f, 0x5f, 0x62, 0x63, 0x63, 0x64, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6a, + 0x6a, 0x6b, 0x6b, 0x6b, 0x6b, 0x6c, 0x6b, 0x6a, 0x69, 0x69, 0x69, 0x67, + 0x66, 0x67, 0x68, 0x67, 0x69, 0x69, 0x69, 0x68, 0x68, 0x6a, 0x6b, 0x6b, + 0x6b, 0x6a, 0x6b, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6e, 0x72, 0x78, + 0x80, 0x84, 0x87, 0x8a, 0x8e, 0x91, 0x92, 0x92, 0x92, 0x93, 0x97, 0x99, + 0x9b, 0x9b, 0x9b, 0x9a, 0x98, 0x97, 0x96, 0x92, 0x8f, 0x8e, 0x8c, 0x8b, + 0x89, 0x87, 0x85, 0x82, 0x80, 0x7c, 0x79, 0x7a, 0x7c, 0x7c, 0x7d, 0x7c, + 0x7f, 0x81, 0x82, 0x84, 0x86, 0x8a, 0x8b, 0x8b, 0x8b, 0x88, 0x87, 0x85, + 0x84, 0x83, 0x81, 0x81, 0x84, 0x87, 0x90, 0xad, 0xbb, 0xa4, 0x8d, 0x71, + 0x61, 0x68, 0x5e, 0x66, 0x91, 0xcb, 0xc9, 0xb5, 0xaf, 0xb7, 0xc9, 0xd1, + 0xd0, 0xcd, 0xc6, 0xb7, 0xab, 0x9f, 0x99, 0x95, 0x8f, 0x8b, 0x80, 0x85, + 0x91, 0xa3, 0x9f, 0x93, 0x87, 0x75, 0x5a, 0x67, 0x85, 0x92, 0x97, 0x97, + 0x83, 0x86, 0x89, 0x86, 0x7b, 0x6e, 0x68, 0x66, 0x65, 0x64, 0x65, 0x68, + 0x6c, 0x6f, 0x73, 0x72, 0x6e, 0x6e, 0x6f, 0x72, 0x72, 0x70, 0x6d, 0x6c, + 0x6a, 0x6a, 0x69, 0x69, 0x69, 0x67, 0x66, 0x6a, 0x6c, 0x6c, 0x6c, 0x6e, + 0x6f, 0x6e, 0x6f, 0x76, 0x82, 0x89, 0x8e, 0x95, 0x9d, 0xa9, 0xb5, 0xbf, + 0xc4, 0xc6, 0xc8, 0xcc, 0xcc, 0xca, 0xcb, 0xcd, 0xbe, 0x96, 0x74, 0x77, + 0x8c, 0x5b, 0x54, 0x76, 0x85, 0x8d, 0x9a, 0x89, 0x99, 0x9b, 0x83, 0x70, + 0x8b, 0x75, 0x59, 0x33, 0x19, 0x1c, 0x2c, 0x47, 0x78, 0x7f, 0x72, 0x69, + 0x63, 0x5c, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x5a, 0x5c, 0x5c, 0x5d, + 0x5f, 0x60, 0x5f, 0x5f, 0x60, 0x60, 0x62, 0x61, 0x62, 0x63, 0x66, 0x68, + 0x68, 0x6a, 0x6b, 0x6c, 0x6c, 0x6e, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x71, + 0x71, 0x71, 0x70, 0x72, 0x71, 0x72, 0x72, 0x72, 0x73, 0x73, 0x72, 0x70, + 0x6f, 0x6b, 0x68, 0x66, 0x62, 0x5d, 0x57, 0x54, 0x51, 0x4d, 0x47, 0x40, + 0x3d, 0x3a, 0x35, 0x2d, 0x24, 0x1c, 0x16, 0x13, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x11, 0x12, 0x12, 0x12, 0x11, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x5a, 0x5a, 0x59, 0x59, 0x5a, 0x5b, 0x5d, 0x5e, 0x5f, 0x5f, 0x60, 0x62, + 0x63, 0x64, 0x65, 0x67, 0x68, 0x68, 0x68, 0x69, 0x6b, 0x6b, 0x6b, 0x6b, + 0x6b, 0x6c, 0x6b, 0x6a, 0x6a, 0x6a, 0x6a, 0x68, 0x67, 0x66, 0x67, 0x67, + 0x69, 0x69, 0x68, 0x68, 0x68, 0x69, 0x6a, 0x6b, 0x6a, 0x6a, 0x6b, 0x6d, + 0x6d, 0x6c, 0x6d, 0x6d, 0x6e, 0x70, 0x74, 0x7b, 0x82, 0x85, 0x87, 0x8b, + 0x8e, 0x90, 0x91, 0x91, 0x91, 0x93, 0x97, 0x99, 0x9b, 0x9b, 0x9b, 0x9b, + 0x98, 0x97, 0x96, 0x92, 0x8f, 0x8e, 0x8c, 0x8b, 0x8a, 0x88, 0x86, 0x84, + 0x83, 0x80, 0x7c, 0x7d, 0x7e, 0x7f, 0x7f, 0x7e, 0x7f, 0x81, 0x82, 0x84, + 0x86, 0x89, 0x89, 0x89, 0x89, 0x87, 0x86, 0x85, 0x83, 0x82, 0x81, 0x82, + 0x87, 0x8c, 0x98, 0xb7, 0xaa, 0x8b, 0x86, 0x97, 0x96, 0x8d, 0x74, 0x7b, + 0xad, 0xcd, 0xb6, 0xaf, 0xaf, 0xb0, 0xc0, 0xce, 0xcf, 0xce, 0xc9, 0xbb, + 0xb1, 0xa6, 0x9c, 0x98, 0x95, 0x93, 0x80, 0x72, 0x76, 0x8c, 0xa0, 0xa3, + 0x9f, 0x8f, 0x6d, 0x5e, 0x70, 0x8c, 0x9e, 0xab, 0x9a, 0x8c, 0x8b, 0x8b, + 0x86, 0x74, 0x6a, 0x68, 0x67, 0x67, 0x64, 0x65, 0x6c, 0x71, 0x75, 0x73, + 0x6f, 0x6f, 0x71, 0x75, 0x75, 0x75, 0x74, 0x73, 0x71, 0x72, 0x74, 0x74, + 0x73, 0x72, 0x72, 0x75, 0x77, 0x77, 0x75, 0x75, 0x75, 0x77, 0x79, 0x7e, + 0x88, 0x8c, 0x92, 0x9b, 0xa3, 0xaf, 0xbb, 0xc1, 0xc3, 0xc5, 0xc9, 0xce, + 0xcb, 0xcb, 0xcd, 0xce, 0xbb, 0x8f, 0x6f, 0x77, 0x8f, 0x4c, 0x5a, 0x80, + 0x8f, 0x8e, 0x82, 0x83, 0x8a, 0x84, 0x6e, 0x69, 0x71, 0x4a, 0x37, 0x30, + 0x19, 0x16, 0x21, 0x3a, 0x6c, 0x7f, 0x76, 0x6d, 0x68, 0x60, 0x5a, 0x58, + 0x57, 0x57, 0x57, 0x57, 0x5b, 0x5c, 0x5d, 0x5d, 0x5f, 0x60, 0x5f, 0x5f, + 0x60, 0x60, 0x61, 0x61, 0x61, 0x63, 0x66, 0x68, 0x68, 0x6a, 0x6b, 0x6b, + 0x6c, 0x6e, 0x70, 0x70, 0x70, 0x6f, 0x70, 0x71, 0x71, 0x71, 0x70, 0x71, + 0x70, 0x71, 0x72, 0x72, 0x73, 0x73, 0x72, 0x70, 0x6f, 0x6b, 0x68, 0x66, + 0x62, 0x5d, 0x57, 0x53, 0x50, 0x4c, 0x47, 0x40, 0x3c, 0x39, 0x34, 0x2b, + 0x24, 0x1c, 0x18, 0x13, 0x11, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x12, + 0x12, 0x12, 0x11, 0x13, 0x13, 0x13, 0x13, 0x12, 0x5a, 0x5a, 0x5a, 0x5a, + 0x59, 0x5b, 0x5d, 0x5e, 0x5f, 0x5f, 0x60, 0x61, 0x63, 0x64, 0x65, 0x67, + 0x68, 0x68, 0x68, 0x69, 0x6b, 0x6b, 0x6b, 0x6a, 0x6b, 0x6c, 0x6b, 0x6b, + 0x6a, 0x6b, 0x6a, 0x69, 0x68, 0x67, 0x66, 0x67, 0x69, 0x69, 0x69, 0x68, + 0x68, 0x69, 0x6a, 0x6a, 0x6b, 0x6a, 0x6c, 0x6d, 0x6d, 0x6c, 0x6d, 0x6e, + 0x6f, 0x71, 0x75, 0x7d, 0x83, 0x86, 0x88, 0x8b, 0x8e, 0x90, 0x91, 0x91, + 0x91, 0x93, 0x97, 0x99, 0x9b, 0x9b, 0x9a, 0x9b, 0x99, 0x98, 0x96, 0x92, + 0x8f, 0x8e, 0x8c, 0x8b, 0x8a, 0x88, 0x87, 0x85, 0x83, 0x81, 0x7d, 0x7e, + 0x80, 0x81, 0x80, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x86, 0x87, 0x88, 0x88, + 0x88, 0x86, 0x85, 0x84, 0x83, 0x81, 0x81, 0x85, 0x8b, 0x90, 0x9e, 0xba, + 0xaa, 0x94, 0x99, 0xb4, 0xb5, 0xab, 0x96, 0x9d, 0xc2, 0xc3, 0x9c, 0xab, + 0xb4, 0xb1, 0xba, 0xcb, 0xcf, 0xce, 0xcb, 0xc1, 0xb4, 0xa9, 0x9f, 0x9a, + 0x95, 0x94, 0x84, 0x72, 0x70, 0x80, 0x99, 0xa6, 0xa6, 0x9b, 0x7f, 0x66, + 0x6b, 0x8a, 0xa1, 0xb3, 0xa2, 0x8e, 0x8b, 0x8d, 0x8c, 0x74, 0x68, 0x66, + 0x65, 0x64, 0x61, 0x62, 0x69, 0x6e, 0x75, 0x73, 0x70, 0x70, 0x71, 0x76, + 0x78, 0x78, 0x79, 0x78, 0x75, 0x77, 0x7a, 0x7a, 0x79, 0x78, 0x79, 0x7b, + 0x7c, 0x7d, 0x7c, 0x7a, 0x7a, 0x7d, 0x80, 0x84, 0x8c, 0x8f, 0x95, 0x9e, + 0xa6, 0xb1, 0xbb, 0xc1, 0xc3, 0xc4, 0xc8, 0xce, 0xcc, 0xca, 0xcb, 0xcc, + 0xb8, 0x89, 0x6f, 0x77, 0x88, 0x47, 0x61, 0x87, 0x91, 0x89, 0x7e, 0x8c, + 0x88, 0x7c, 0x6a, 0x6b, 0x59, 0x36, 0x2e, 0x34, 0x1c, 0x14, 0x1f, 0x35, + 0x61, 0x7f, 0x79, 0x71, 0x6b, 0x63, 0x5b, 0x59, 0x58, 0x57, 0x56, 0x57, + 0x5b, 0x5c, 0x5d, 0x5d, 0x5f, 0x60, 0x5f, 0x5f, 0x60, 0x60, 0x61, 0x61, + 0x62, 0x63, 0x66, 0x68, 0x68, 0x6a, 0x6b, 0x6b, 0x6c, 0x6e, 0x70, 0x70, + 0x70, 0x70, 0x70, 0x71, 0x71, 0x71, 0x70, 0x70, 0x70, 0x71, 0x72, 0x72, + 0x73, 0x73, 0x72, 0x70, 0x6f, 0x6b, 0x68, 0x66, 0x63, 0x5e, 0x57, 0x53, + 0x50, 0x4c, 0x47, 0x3f, 0x3b, 0x38, 0x35, 0x2b, 0x24, 0x1c, 0x18, 0x13, + 0x11, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x12, 0x12, 0x12, 0x11, 0x13, + 0x13, 0x13, 0x13, 0x12, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5b, 0x5c, 0x5d, + 0x5e, 0x5f, 0x5f, 0x61, 0x63, 0x64, 0x66, 0x66, 0x67, 0x67, 0x68, 0x69, + 0x6b, 0x6c, 0x6b, 0x6b, 0x6b, 0x6c, 0x6c, 0x6b, 0x6b, 0x6c, 0x6b, 0x6a, + 0x68, 0x67, 0x67, 0x68, 0x69, 0x69, 0x6a, 0x69, 0x69, 0x6a, 0x6a, 0x6b, + 0x6b, 0x6b, 0x6c, 0x6d, 0x6d, 0x6c, 0x6d, 0x6e, 0x71, 0x74, 0x77, 0x7e, + 0x84, 0x87, 0x89, 0x8c, 0x8e, 0x91, 0x91, 0x91, 0x91, 0x93, 0x96, 0x99, + 0x9a, 0x9b, 0x9b, 0x9b, 0x99, 0x97, 0x95, 0x92, 0x8f, 0x8d, 0x8b, 0x8a, + 0x88, 0x88, 0x88, 0x86, 0x85, 0x82, 0x80, 0x81, 0x82, 0x82, 0x82, 0x81, + 0x81, 0x81, 0x82, 0x84, 0x84, 0x86, 0x86, 0x86, 0x87, 0x86, 0x84, 0x83, + 0x82, 0x80, 0x83, 0x8b, 0x92, 0x98, 0xa4, 0xb5, 0xb1, 0xb2, 0xb9, 0xc5, + 0xc0, 0xc4, 0xc4, 0xc9, 0xce, 0xb0, 0x85, 0xa6, 0xb5, 0xac, 0xb1, 0xc3, + 0xcd, 0xd0, 0xd0, 0xcb, 0xb9, 0xab, 0xa4, 0x9d, 0x92, 0x90, 0x8c, 0x7f, + 0x78, 0x78, 0x88, 0x9d, 0x9c, 0x96, 0x8d, 0x81, 0x77, 0x8e, 0xa4, 0xb8, + 0xa4, 0x92, 0x90, 0x91, 0x8f, 0x6e, 0x60, 0x5f, 0x5f, 0x5e, 0x5b, 0x5b, + 0x60, 0x66, 0x6e, 0x73, 0x70, 0x70, 0x71, 0x76, 0x79, 0x7c, 0x7c, 0x7b, + 0x79, 0x7c, 0x7f, 0x7e, 0x7e, 0x7e, 0x81, 0x81, 0x82, 0x84, 0x85, 0x83, + 0x84, 0x89, 0x8c, 0x8f, 0x91, 0x92, 0x99, 0xa3, 0xaa, 0xb2, 0xba, 0xc1, + 0xc3, 0xc4, 0xc6, 0xcb, 0xcc, 0xca, 0xc8, 0xc6, 0xb1, 0x82, 0x74, 0x78, + 0x76, 0x43, 0x6d, 0x88, 0x87, 0x7d, 0x92, 0xa1, 0x8d, 0x7e, 0x73, 0x68, + 0x3a, 0x2e, 0x32, 0x37, 0x1d, 0x15, 0x1e, 0x2d, 0x4e, 0x7c, 0x7d, 0x75, + 0x6f, 0x68, 0x5e, 0x5a, 0x59, 0x58, 0x58, 0x58, 0x5a, 0x5c, 0x5c, 0x5d, + 0x5f, 0x60, 0x5f, 0x60, 0x61, 0x60, 0x62, 0x61, 0x63, 0x64, 0x66, 0x67, + 0x67, 0x69, 0x6b, 0x6b, 0x6b, 0x6d, 0x6f, 0x6f, 0x6f, 0x6f, 0x70, 0x71, + 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x71, 0x70, + 0x6f, 0x6b, 0x68, 0x66, 0x63, 0x5e, 0x57, 0x53, 0x51, 0x4b, 0x46, 0x3f, + 0x3b, 0x39, 0x35, 0x2d, 0x24, 0x1b, 0x16, 0x13, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x11, 0x12, 0x12, 0x11, 0x13, 0x13, 0x13, 0x13, 0x12, + 0x59, 0x5a, 0x5a, 0x5a, 0x59, 0x59, 0x5a, 0x5d, 0x5d, 0x5e, 0x60, 0x61, + 0x63, 0x64, 0x65, 0x67, 0x68, 0x68, 0x69, 0x6b, 0x6b, 0x6c, 0x6d, 0x6d, + 0x6d, 0x6d, 0x6b, 0x6c, 0x6c, 0x6c, 0x6b, 0x6b, 0x69, 0x69, 0x68, 0x68, + 0x6a, 0x6a, 0x6a, 0x6a, 0x6b, 0x6b, 0x6c, 0x6c, 0x6d, 0x6c, 0x6d, 0x6d, + 0x6d, 0x6d, 0x6e, 0x6f, 0x73, 0x76, 0x79, 0x80, 0x85, 0x89, 0x8b, 0x8d, + 0x8e, 0x91, 0x92, 0x92, 0x92, 0x95, 0x96, 0x97, 0x9a, 0x9b, 0x9c, 0x9b, + 0x99, 0x96, 0x94, 0x91, 0x8e, 0x8d, 0x8b, 0x8a, 0x89, 0x89, 0x88, 0x87, + 0x86, 0x83, 0x83, 0x85, 0x85, 0x85, 0x85, 0x84, 0x83, 0x83, 0x84, 0x85, + 0x85, 0x86, 0x86, 0x85, 0x84, 0x84, 0x82, 0x81, 0x7f, 0x80, 0x88, 0x93, + 0x9a, 0xa2, 0xad, 0xab, 0xa1, 0x9c, 0xa4, 0xb9, 0xba, 0xcb, 0xd3, 0xcd, + 0xbe, 0xc0, 0xb4, 0x98, 0x85, 0x79, 0x98, 0xb4, 0xc5, 0xcf, 0xd3, 0xd2, + 0xc0, 0xad, 0xac, 0xa8, 0x9c, 0x97, 0x9a, 0x90, 0x86, 0x7b, 0x7e, 0x84, + 0x7f, 0x7f, 0x88, 0x95, 0x96, 0x9a, 0xa5, 0xb6, 0xad, 0xa0, 0x9b, 0x94, + 0x7e, 0x5a, 0x58, 0x5d, 0x5f, 0x60, 0x5b, 0x58, 0x5a, 0x5c, 0x62, 0x6a, + 0x6c, 0x6d, 0x6f, 0x75, 0x7a, 0x7b, 0x7a, 0x79, 0x7a, 0x7f, 0x81, 0x81, + 0x83, 0x86, 0x87, 0x85, 0x88, 0x8b, 0x8b, 0x89, 0x8e, 0x95, 0x97, 0x97, + 0x93, 0x96, 0x9e, 0xab, 0xb2, 0xb9, 0xbf, 0xc1, 0xc2, 0xc2, 0xc6, 0xc9, + 0xca, 0xcb, 0xca, 0xc4, 0xaa, 0x7a, 0x84, 0x8a, 0x77, 0x46, 0x78, 0x86, + 0x87, 0x8e, 0x9f, 0x9d, 0x86, 0x7e, 0x77, 0x3f, 0x25, 0x33, 0x38, 0x31, + 0x1c, 0x14, 0x19, 0x21, 0x3a, 0x76, 0x7e, 0x77, 0x73, 0x6c, 0x62, 0x5d, + 0x5c, 0x5b, 0x5b, 0x5a, 0x5a, 0x5a, 0x5b, 0x5d, 0x5f, 0x61, 0x62, 0x62, + 0x61, 0x61, 0x63, 0x63, 0x64, 0x64, 0x64, 0x66, 0x66, 0x67, 0x68, 0x6a, + 0x6b, 0x6d, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x71, 0x71, 0x72, 0x73, 0x73, + 0x73, 0x73, 0x72, 0x72, 0x73, 0x72, 0x71, 0x70, 0x6e, 0x6a, 0x68, 0x66, + 0x63, 0x5e, 0x57, 0x53, 0x51, 0x4b, 0x45, 0x40, 0x3c, 0x39, 0x35, 0x2f, + 0x24, 0x1c, 0x17, 0x13, 0x11, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, + 0x12, 0x11, 0x13, 0x13, 0x13, 0x13, 0x13, 0x11, 0x58, 0x58, 0x58, 0x59, + 0x59, 0x59, 0x59, 0x5b, 0x5c, 0x5c, 0x5f, 0x61, 0x63, 0x64, 0x65, 0x67, + 0x68, 0x69, 0x69, 0x6b, 0x6b, 0x6c, 0x6d, 0x6d, 0x6d, 0x6d, 0x6c, 0x6d, + 0x6d, 0x6d, 0x6c, 0x6c, 0x6b, 0x6a, 0x6b, 0x6b, 0x6a, 0x6a, 0x6b, 0x6b, + 0x6c, 0x6c, 0x6c, 0x6d, 0x6c, 0x6d, 0x6d, 0x6e, 0x6e, 0x6f, 0x71, 0x72, + 0x76, 0x78, 0x7c, 0x81, 0x86, 0x89, 0x8b, 0x8d, 0x8e, 0x91, 0x92, 0x93, + 0x93, 0x95, 0x96, 0x97, 0x9a, 0x9c, 0x9c, 0x9a, 0x99, 0x96, 0x94, 0x90, + 0x8d, 0x8c, 0x8d, 0x8c, 0x8b, 0x8a, 0x8a, 0x88, 0x87, 0x85, 0x85, 0x88, + 0x89, 0x89, 0x89, 0x88, 0x87, 0x87, 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, + 0x82, 0x81, 0x7f, 0x7d, 0x7d, 0x83, 0x90, 0x9b, 0xa2, 0xa9, 0xb3, 0xb4, + 0xbf, 0xaf, 0xa2, 0x97, 0x97, 0xc7, 0xd3, 0xc5, 0xab, 0xc2, 0xb8, 0x82, + 0x64, 0x59, 0x78, 0xa4, 0xbf, 0xcc, 0xd2, 0xd4, 0xc4, 0xb1, 0xae, 0xad, + 0xa8, 0x9f, 0x9d, 0x95, 0x8c, 0x7f, 0x7c, 0x7a, 0x80, 0x85, 0x8b, 0x96, + 0x9e, 0xa2, 0xa6, 0xab, 0xa8, 0x9c, 0x8c, 0x7a, 0x5c, 0x52, 0x61, 0x69, + 0x6c, 0x6c, 0x63, 0x5d, 0x5b, 0x5b, 0x5d, 0x63, 0x68, 0x6c, 0x6f, 0x73, + 0x79, 0x79, 0x77, 0x77, 0x79, 0x7e, 0x81, 0x81, 0x81, 0x84, 0x87, 0x85, + 0x8a, 0x8d, 0x90, 0x91, 0x97, 0x9c, 0x9c, 0x99, 0x95, 0x99, 0xa2, 0xac, + 0xb3, 0xbd, 0xc4, 0xc2, 0xc1, 0xc3, 0xc8, 0xc8, 0xc9, 0xd1, 0xd0, 0xc4, + 0xa7, 0x78, 0x8f, 0x94, 0x72, 0x43, 0x76, 0x91, 0x95, 0x8c, 0x79, 0x94, + 0x91, 0x81, 0x5f, 0x28, 0x28, 0x33, 0x33, 0x27, 0x1a, 0x12, 0x12, 0x16, + 0x2c, 0x6b, 0x7e, 0x79, 0x74, 0x6f, 0x66, 0x60, 0x5e, 0x5d, 0x5c, 0x5b, + 0x59, 0x5a, 0x5a, 0x5d, 0x5f, 0x61, 0x62, 0x61, 0x60, 0x60, 0x63, 0x63, + 0x64, 0x65, 0x64, 0x66, 0x66, 0x67, 0x68, 0x6b, 0x6d, 0x6e, 0x6d, 0x6e, + 0x6f, 0x6f, 0x71, 0x71, 0x71, 0x72, 0x73, 0x74, 0x74, 0x73, 0x73, 0x72, + 0x73, 0x74, 0x73, 0x71, 0x6f, 0x6a, 0x68, 0x67, 0x64, 0x5e, 0x57, 0x54, + 0x51, 0x4d, 0x46, 0x40, 0x3d, 0x3a, 0x36, 0x2e, 0x23, 0x1d, 0x18, 0x14, + 0x11, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x13, + 0x12, 0x12, 0x12, 0x12, 0x58, 0x57, 0x59, 0x59, 0x5a, 0x58, 0x59, 0x5a, + 0x5b, 0x5c, 0x5e, 0x61, 0x62, 0x63, 0x65, 0x67, 0x68, 0x68, 0x69, 0x6b, + 0x6c, 0x6c, 0x6d, 0x6e, 0x6d, 0x6d, 0x6b, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, + 0x6c, 0x6c, 0x6c, 0x6c, 0x6b, 0x6b, 0x6b, 0x6b, 0x6c, 0x6c, 0x6c, 0x6d, + 0x6c, 0x6d, 0x6d, 0x6e, 0x6f, 0x70, 0x72, 0x74, 0x78, 0x7a, 0x7d, 0x83, + 0x87, 0x8a, 0x8c, 0x8e, 0x8f, 0x91, 0x92, 0x93, 0x94, 0x95, 0x95, 0x98, + 0x99, 0x9a, 0x9a, 0x99, 0x98, 0x96, 0x94, 0x90, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8c, 0x8c, 0x8c, 0x8a, 0x89, 0x87, 0x88, 0x8a, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8a, 0x8a, 0x88, 0x87, 0x85, 0x82, 0x82, 0x81, 0x80, 0x7e, 0x7b, 0x7b, + 0x7e, 0x87, 0x96, 0xa1, 0xa6, 0xad, 0xb7, 0xb4, 0xc9, 0xbb, 0xb4, 0xb9, + 0xc2, 0xd6, 0xcc, 0xc5, 0xc5, 0xc4, 0x9d, 0x82, 0x78, 0x6e, 0x5b, 0x96, + 0xc3, 0xc7, 0xcc, 0xd4, 0xc6, 0xb6, 0xb0, 0xae, 0xab, 0xa5, 0x9e, 0x98, + 0x90, 0x83, 0x81, 0x84, 0x86, 0x87, 0x8c, 0x92, 0x9b, 0xa3, 0xa4, 0xa1, + 0x97, 0x85, 0x76, 0x6a, 0x5a, 0x5d, 0x6d, 0x74, 0x76, 0x74, 0x69, 0x61, + 0x5e, 0x5c, 0x5d, 0x61, 0x66, 0x6b, 0x6d, 0x72, 0x79, 0x7a, 0x78, 0x77, + 0x77, 0x7c, 0x7f, 0x7f, 0x7f, 0x81, 0x85, 0x81, 0x85, 0x8b, 0x92, 0x96, + 0x9b, 0x9e, 0x9e, 0x9a, 0x98, 0xa0, 0xa6, 0xab, 0xb2, 0xbd, 0xc3, 0xbf, + 0xc1, 0xc5, 0xcb, 0xcc, 0xcb, 0xce, 0xcc, 0xc1, 0xa4, 0x76, 0x8a, 0x8b, + 0x66, 0x48, 0x78, 0x98, 0x9f, 0x99, 0x86, 0x97, 0x99, 0x80, 0x40, 0x1b, + 0x25, 0x30, 0x2f, 0x23, 0x18, 0x11, 0x10, 0x13, 0x25, 0x61, 0x7d, 0x7a, + 0x76, 0x71, 0x69, 0x63, 0x61, 0x5f, 0x5f, 0x5b, 0x59, 0x5a, 0x5b, 0x5c, + 0x5e, 0x60, 0x61, 0x61, 0x5f, 0x60, 0x63, 0x64, 0x64, 0x65, 0x66, 0x65, + 0x67, 0x69, 0x69, 0x6a, 0x6d, 0x6e, 0x6e, 0x6e, 0x6f, 0x70, 0x70, 0x72, + 0x72, 0x72, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x74, 0x75, 0x74, 0x72, + 0x6f, 0x6c, 0x68, 0x66, 0x63, 0x5d, 0x58, 0x54, 0x51, 0x4d, 0x47, 0x41, + 0x3d, 0x3a, 0x36, 0x2f, 0x25, 0x1c, 0x19, 0x13, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x12, 0x12, 0x12, 0x11, 0x13, 0x13, 0x13, 0x12, 0x12, 0x13, + 0x58, 0x58, 0x59, 0x59, 0x59, 0x58, 0x58, 0x5a, 0x5a, 0x5c, 0x5e, 0x61, + 0x62, 0x63, 0x64, 0x66, 0x68, 0x68, 0x69, 0x6a, 0x6c, 0x6c, 0x6e, 0x6e, + 0x6d, 0x6d, 0x6c, 0x6b, 0x6c, 0x6d, 0x6d, 0x6e, 0x6d, 0x6d, 0x6c, 0x6d, + 0x6b, 0x6b, 0x6b, 0x6b, 0x6c, 0x6c, 0x6c, 0x6d, 0x6c, 0x6d, 0x6d, 0x6e, + 0x6f, 0x71, 0x73, 0x76, 0x79, 0x7c, 0x7e, 0x83, 0x87, 0x8a, 0x8c, 0x8e, + 0x8f, 0x91, 0x91, 0x92, 0x94, 0x96, 0x95, 0x98, 0x99, 0x9a, 0x9a, 0x98, + 0x98, 0x96, 0x94, 0x91, 0x8d, 0x8c, 0x8d, 0x8d, 0x8c, 0x8d, 0x8c, 0x8b, + 0x8a, 0x89, 0x8a, 0x8c, 0x8c, 0x8d, 0x8c, 0x8d, 0x8c, 0x8b, 0x89, 0x87, + 0x86, 0x82, 0x81, 0x81, 0x7f, 0x7c, 0x79, 0x7a, 0x7f, 0x8b, 0x9a, 0xa4, + 0xa9, 0xb0, 0xb9, 0xb3, 0xc9, 0xc0, 0xbd, 0xc9, 0xda, 0xdc, 0xc5, 0xc2, + 0xd2, 0xca, 0xa3, 0x96, 0x8f, 0x7b, 0x57, 0x95, 0xc3, 0xc2, 0xc6, 0xd3, + 0xc9, 0xbb, 0xb2, 0xae, 0xac, 0xa9, 0x9f, 0x9a, 0x94, 0x88, 0x83, 0x88, + 0x88, 0x89, 0x8b, 0x90, 0x97, 0x9f, 0x9f, 0x99, 0x8f, 0x7e, 0x70, 0x68, + 0x5f, 0x62, 0x70, 0x78, 0x7a, 0x78, 0x6d, 0x66, 0x61, 0x5f, 0x5e, 0x61, + 0x63, 0x67, 0x6b, 0x6f, 0x79, 0x7c, 0x7a, 0x78, 0x76, 0x7b, 0x7f, 0x7f, + 0x7e, 0x7f, 0x85, 0x82, 0x84, 0x89, 0x91, 0x96, 0x9c, 0x9d, 0x9c, 0x99, + 0x99, 0xa0, 0xa9, 0xad, 0xb3, 0xbd, 0xc2, 0xbf, 0xc1, 0xc6, 0xcc, 0xce, + 0xca, 0xc9, 0xc6, 0xbd, 0xa0, 0x75, 0x8c, 0x89, 0x5c, 0x48, 0x7a, 0x99, + 0xa0, 0x9a, 0x92, 0x92, 0x8e, 0x71, 0x31, 0x18, 0x21, 0x2e, 0x2e, 0x21, + 0x17, 0x11, 0x10, 0x12, 0x22, 0x5a, 0x7d, 0x7c, 0x77, 0x71, 0x6a, 0x65, + 0x62, 0x61, 0x60, 0x5c, 0x5a, 0x5a, 0x5b, 0x5c, 0x5e, 0x5f, 0x61, 0x61, + 0x60, 0x61, 0x63, 0x64, 0x64, 0x65, 0x66, 0x66, 0x68, 0x6a, 0x6a, 0x6a, + 0x6c, 0x6e, 0x6e, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x72, 0x72, 0x73, 0x73, + 0x73, 0x73, 0x74, 0x74, 0x74, 0x75, 0x74, 0x72, 0x6f, 0x6b, 0x68, 0x65, + 0x62, 0x5d, 0x58, 0x53, 0x50, 0x4d, 0x47, 0x40, 0x3d, 0x3b, 0x36, 0x30, + 0x25, 0x1d, 0x19, 0x14, 0x11, 0x11, 0x11, 0x11, 0x10, 0x10, 0x12, 0x12, + 0x12, 0x11, 0x13, 0x13, 0x13, 0x12, 0x12, 0x13, 0x58, 0x58, 0x59, 0x59, + 0x59, 0x58, 0x58, 0x5a, 0x5a, 0x5c, 0x5e, 0x60, 0x62, 0x63, 0x64, 0x65, + 0x66, 0x68, 0x69, 0x6a, 0x6c, 0x6d, 0x6e, 0x6f, 0x6d, 0x6d, 0x6d, 0x6d, + 0x6d, 0x6e, 0x6e, 0x6e, 0x6d, 0x6d, 0x6c, 0x6c, 0x6b, 0x6c, 0x6c, 0x6b, + 0x6d, 0x6d, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, + 0x7a, 0x7c, 0x7f, 0x82, 0x86, 0x89, 0x8b, 0x8d, 0x8f, 0x90, 0x91, 0x92, + 0x94, 0x95, 0x95, 0x97, 0x99, 0x99, 0x99, 0x98, 0x97, 0x95, 0x93, 0x91, + 0x8d, 0x8c, 0x8c, 0x8c, 0x8c, 0x8d, 0x8c, 0x8c, 0x8b, 0x8b, 0x8d, 0x8e, + 0x8f, 0x8f, 0x8e, 0x8f, 0x8e, 0x8c, 0x8b, 0x8a, 0x87, 0x84, 0x81, 0x7f, + 0x7d, 0x78, 0x77, 0x7c, 0x83, 0x91, 0xa0, 0xa8, 0xad, 0xb3, 0xb8, 0xb6, + 0xc7, 0xc4, 0xbf, 0xc1, 0xdb, 0xd8, 0xbf, 0xbd, 0xd0, 0xd1, 0xcb, 0xc3, + 0xb4, 0x8e, 0x73, 0xa3, 0xbd, 0xb9, 0xbc, 0xcb, 0xcd, 0xc1, 0xb3, 0xae, + 0xad, 0xac, 0xa3, 0x9f, 0x99, 0x8d, 0x83, 0x89, 0x8b, 0x8c, 0x8d, 0x8d, + 0x8f, 0x93, 0x93, 0x8f, 0x8d, 0x83, 0x77, 0x70, 0x69, 0x66, 0x6f, 0x76, + 0x79, 0x7a, 0x73, 0x6d, 0x68, 0x65, 0x61, 0x62, 0x61, 0x60, 0x62, 0x69, + 0x75, 0x7c, 0x7d, 0x7a, 0x77, 0x7a, 0x80, 0x7f, 0x7e, 0x7f, 0x85, 0x89, + 0x87, 0x88, 0x8d, 0x93, 0x99, 0x99, 0x98, 0x98, 0x99, 0x9d, 0xa9, 0xb2, + 0xb7, 0xbe, 0xc5, 0xc3, 0xc3, 0xc6, 0xcc, 0xce, 0xc6, 0xc2, 0xbf, 0xb4, + 0x98, 0x77, 0x96, 0x8e, 0x4f, 0x43, 0x7a, 0x98, 0x99, 0x8e, 0x97, 0x85, + 0x68, 0x4c, 0x23, 0x19, 0x1e, 0x2d, 0x2e, 0x20, 0x14, 0x10, 0x10, 0x12, + 0x1e, 0x4d, 0x7c, 0x7e, 0x79, 0x72, 0x6b, 0x68, 0x65, 0x64, 0x62, 0x5e, + 0x5a, 0x5a, 0x5a, 0x5b, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x63, 0x64, + 0x65, 0x66, 0x66, 0x65, 0x66, 0x69, 0x6a, 0x6a, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x74, 0x73, + 0x74, 0x74, 0x73, 0x72, 0x6d, 0x6b, 0x68, 0x66, 0x62, 0x5d, 0x57, 0x52, + 0x50, 0x4b, 0x46, 0x40, 0x3d, 0x3a, 0x37, 0x2f, 0x25, 0x1d, 0x19, 0x14, + 0x12, 0x11, 0x11, 0x10, 0x10, 0x10, 0x12, 0x12, 0x12, 0x11, 0x12, 0x14, + 0x13, 0x13, 0x12, 0x14, 0x57, 0x57, 0x58, 0x58, 0x57, 0x59, 0x59, 0x5a, + 0x5b, 0x5b, 0x5c, 0x5e, 0x60, 0x62, 0x63, 0x63, 0x65, 0x67, 0x68, 0x69, + 0x6b, 0x6c, 0x6e, 0x6f, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x6f, 0x6e, 0x6e, + 0x6d, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6e, 0x6e, 0x6c, 0x6c, + 0x6c, 0x6c, 0x6c, 0x6e, 0x70, 0x72, 0x76, 0x79, 0x7c, 0x7f, 0x80, 0x83, + 0x86, 0x88, 0x8a, 0x8c, 0x8d, 0x8f, 0x91, 0x92, 0x92, 0x93, 0x93, 0x96, + 0x97, 0x98, 0x99, 0x99, 0x97, 0x95, 0x93, 0x90, 0x8e, 0x8c, 0x8c, 0x8c, + 0x8b, 0x8d, 0x8d, 0x8c, 0x8c, 0x8d, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x93, + 0x91, 0x8e, 0x8d, 0x8c, 0x89, 0x85, 0x81, 0x7e, 0x7a, 0x75, 0x79, 0x83, + 0x8c, 0x99, 0xa5, 0xab, 0xb3, 0xb5, 0xb3, 0xb5, 0xba, 0xb7, 0xb8, 0xc1, + 0xd3, 0xd0, 0xce, 0xc7, 0xb6, 0xbc, 0xcd, 0xda, 0xd8, 0xc8, 0xb9, 0xab, + 0xa5, 0xa6, 0xae, 0xc0, 0xd1, 0xc8, 0xb7, 0xaf, 0xa9, 0xaa, 0xab, 0xa4, + 0x9a, 0x8a, 0x84, 0x8c, 0x91, 0x90, 0x8c, 0x8d, 0x8b, 0x8b, 0x8a, 0x88, + 0x88, 0x85, 0x80, 0x7b, 0x74, 0x6f, 0x74, 0x78, 0x7a, 0x7b, 0x77, 0x74, + 0x6e, 0x69, 0x66, 0x65, 0x61, 0x5b, 0x5b, 0x60, 0x6a, 0x72, 0x77, 0x78, + 0x78, 0x7b, 0x81, 0x81, 0x7f, 0x80, 0x85, 0x8a, 0x87, 0x88, 0x8e, 0x94, + 0x97, 0x96, 0x96, 0x98, 0x9b, 0xa0, 0xaa, 0xb3, 0xb8, 0xbf, 0xc7, 0xcb, + 0xc9, 0xc9, 0xc9, 0xc8, 0xc3, 0xc1, 0xbe, 0xb0, 0x8e, 0x77, 0x97, 0x8c, + 0x4b, 0x46, 0x80, 0x8e, 0x8b, 0x85, 0x93, 0x82, 0x49, 0x29, 0x17, 0x15, + 0x1c, 0x26, 0x29, 0x22, 0x15, 0x10, 0x11, 0x12, 0x1a, 0x42, 0x79, 0x7e, + 0x7a, 0x74, 0x6e, 0x6b, 0x69, 0x67, 0x65, 0x60, 0x5d, 0x5b, 0x5b, 0x5c, + 0x5d, 0x5e, 0x5f, 0x61, 0x63, 0x63, 0x63, 0x64, 0x65, 0x65, 0x66, 0x66, + 0x67, 0x69, 0x69, 0x69, 0x6a, 0x6b, 0x6d, 0x6e, 0x70, 0x71, 0x73, 0x72, + 0x72, 0x73, 0x73, 0x73, 0x73, 0x73, 0x74, 0x73, 0x74, 0x74, 0x73, 0x72, + 0x6e, 0x6b, 0x68, 0x66, 0x64, 0x5e, 0x58, 0x52, 0x50, 0x4c, 0x45, 0x40, + 0x3c, 0x3a, 0x36, 0x2e, 0x25, 0x1f, 0x1a, 0x14, 0x13, 0x12, 0x11, 0x10, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x13, 0x14, 0x13, 0x13, 0x12, 0x13, + 0x55, 0x56, 0x56, 0x56, 0x56, 0x57, 0x5a, 0x5a, 0x5a, 0x5a, 0x5b, 0x5e, + 0x60, 0x60, 0x62, 0x64, 0x65, 0x67, 0x68, 0x69, 0x6a, 0x6c, 0x6d, 0x6e, + 0x6e, 0x6f, 0x70, 0x70, 0x70, 0x6f, 0x70, 0x6f, 0x6e, 0x6e, 0x6d, 0x6e, + 0x6d, 0x6d, 0x6e, 0x6e, 0x6d, 0x6d, 0x6d, 0x6c, 0x6d, 0x6d, 0x6c, 0x6e, + 0x71, 0x75, 0x77, 0x7a, 0x7d, 0x7f, 0x81, 0x83, 0x86, 0x88, 0x8a, 0x8c, + 0x8d, 0x8f, 0x90, 0x91, 0x91, 0x92, 0x92, 0x94, 0x97, 0x98, 0x99, 0x99, + 0x96, 0x93, 0x91, 0x90, 0x8f, 0x8e, 0x8d, 0x8d, 0x8d, 0x8b, 0x8b, 0x8d, + 0x8d, 0x8e, 0x8f, 0x91, 0x93, 0x93, 0x94, 0x94, 0x92, 0x91, 0x90, 0x8d, + 0x89, 0x85, 0x80, 0x7d, 0x7a, 0x77, 0x7e, 0x8b, 0x94, 0xa0, 0xa8, 0xac, + 0xb5, 0xb7, 0xaf, 0xa2, 0xa4, 0x96, 0x9c, 0xbb, 0xc8, 0xc9, 0xc8, 0xb9, + 0x9c, 0xa7, 0xb0, 0xcd, 0xd9, 0xda, 0xd1, 0x99, 0x70, 0x91, 0xa8, 0xb7, + 0xcc, 0xc9, 0xb9, 0xae, 0xa7, 0xab, 0xb1, 0xa3, 0x97, 0x8d, 0x8b, 0x91, + 0x92, 0x93, 0x95, 0x95, 0x8f, 0x89, 0x86, 0x87, 0x89, 0x87, 0x83, 0x80, + 0x7c, 0x7a, 0x7d, 0x7e, 0x7f, 0x7e, 0x79, 0x79, 0x73, 0x70, 0x70, 0x70, + 0x69, 0x60, 0x5d, 0x5e, 0x64, 0x6d, 0x70, 0x71, 0x74, 0x79, 0x7f, 0x80, + 0x80, 0x83, 0x87, 0x8b, 0x8d, 0x8d, 0x90, 0x95, 0x95, 0x90, 0x90, 0x95, + 0x9b, 0xa3, 0xab, 0xb2, 0xb6, 0xbc, 0xc9, 0xcd, 0xc9, 0xc6, 0xc6, 0xc6, + 0xc1, 0xc1, 0xbe, 0xad, 0x85, 0x82, 0x9d, 0x8d, 0x4b, 0x4c, 0x81, 0x81, + 0x7b, 0x81, 0x93, 0x6f, 0x40, 0x28, 0x17, 0x14, 0x1b, 0x1d, 0x1f, 0x23, + 0x16, 0x10, 0x10, 0x10, 0x17, 0x3c, 0x76, 0x7d, 0x78, 0x73, 0x70, 0x6f, + 0x6d, 0x6c, 0x6a, 0x64, 0x60, 0x5e, 0x5d, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, + 0x61, 0x63, 0x64, 0x66, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6a, 0x6a, + 0x6a, 0x6b, 0x6c, 0x6d, 0x6f, 0x70, 0x71, 0x70, 0x71, 0x72, 0x73, 0x74, + 0x73, 0x73, 0x73, 0x74, 0x74, 0x73, 0x72, 0x70, 0x6e, 0x6b, 0x69, 0x67, + 0x64, 0x5f, 0x59, 0x53, 0x4f, 0x4b, 0x47, 0x41, 0x3c, 0x39, 0x36, 0x2d, + 0x26, 0x1f, 0x1a, 0x14, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, + 0x12, 0x12, 0x13, 0x12, 0x13, 0x12, 0x11, 0x12, 0x54, 0x56, 0x55, 0x55, + 0x56, 0x58, 0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5d, 0x5f, 0x60, 0x62, 0x63, + 0x64, 0x66, 0x68, 0x69, 0x6b, 0x6c, 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, + 0x6f, 0x6f, 0x70, 0x70, 0x70, 0x6f, 0x6f, 0x6f, 0x6e, 0x6e, 0x6e, 0x6f, + 0x6e, 0x6e, 0x6d, 0x6d, 0x6d, 0x6d, 0x6c, 0x6d, 0x70, 0x75, 0x78, 0x7b, + 0x7d, 0x7e, 0x81, 0x83, 0x86, 0x88, 0x89, 0x8b, 0x8c, 0x8e, 0x8f, 0x90, + 0x90, 0x91, 0x91, 0x94, 0x97, 0x98, 0x98, 0x99, 0x96, 0x92, 0x91, 0x8f, + 0x90, 0x8f, 0x8d, 0x8d, 0x8d, 0x8c, 0x8c, 0x8e, 0x8e, 0x8f, 0x90, 0x93, + 0x95, 0x95, 0x96, 0x96, 0x94, 0x93, 0x92, 0x8e, 0x89, 0x85, 0x80, 0x7e, + 0x7a, 0x7a, 0x85, 0x92, 0x9a, 0xa3, 0xa9, 0xaa, 0xac, 0xae, 0xb1, 0xab, + 0x90, 0x80, 0x89, 0xab, 0xbd, 0xc9, 0xc6, 0xc0, 0xb6, 0xac, 0xae, 0xbf, + 0xc5, 0xc5, 0xd4, 0xa6, 0x5b, 0x81, 0x9e, 0xaf, 0xc6, 0xca, 0xbb, 0xb1, + 0xaa, 0xb3, 0xb3, 0xa7, 0x9d, 0x93, 0x91, 0x96, 0x94, 0x97, 0xa0, 0x9e, + 0x92, 0x89, 0x86, 0x85, 0x86, 0x87, 0x84, 0x82, 0x80, 0x81, 0x80, 0x80, + 0x80, 0x80, 0x7c, 0x78, 0x75, 0x73, 0x75, 0x77, 0x71, 0x6a, 0x65, 0x60, + 0x65, 0x6f, 0x6f, 0x6f, 0x72, 0x76, 0x7d, 0x80, 0x81, 0x84, 0x89, 0x8b, + 0x90, 0x91, 0x91, 0x94, 0x93, 0x8d, 0x8e, 0x94, 0x99, 0xa3, 0xa9, 0xaf, + 0xb5, 0xc0, 0xcb, 0xcb, 0xc6, 0xc4, 0xc3, 0xc3, 0xbe, 0xbd, 0xba, 0xa7, + 0x7d, 0x85, 0xa3, 0x90, 0x4a, 0x4b, 0x74, 0x7c, 0x7b, 0x81, 0x90, 0x4c, + 0x2b, 0x20, 0x1a, 0x18, 0x1d, 0x1b, 0x1d, 0x23, 0x16, 0x11, 0x10, 0x10, + 0x16, 0x39, 0x75, 0x7c, 0x79, 0x74, 0x72, 0x71, 0x70, 0x70, 0x6d, 0x67, + 0x62, 0x5e, 0x5d, 0x5d, 0x5e, 0x5f, 0x61, 0x61, 0x62, 0x63, 0x64, 0x66, + 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6a, 0x6a, 0x6b, 0x6a, 0x6c, 0x6c, 0x6d, + 0x6e, 0x6f, 0x70, 0x70, 0x71, 0x73, 0x74, 0x74, 0x73, 0x73, 0x72, 0x72, + 0x73, 0x73, 0x72, 0x70, 0x6e, 0x6b, 0x69, 0x68, 0x64, 0x5f, 0x59, 0x53, + 0x4f, 0x4b, 0x47, 0x42, 0x3d, 0x39, 0x36, 0x2e, 0x27, 0x20, 0x1b, 0x14, + 0x11, 0x11, 0x11, 0x11, 0x10, 0x10, 0x11, 0x12, 0x12, 0x12, 0x13, 0x13, + 0x12, 0x11, 0x11, 0x13, 0x55, 0x56, 0x55, 0x55, 0x55, 0x58, 0x59, 0x59, + 0x59, 0x5a, 0x5b, 0x5d, 0x5f, 0x60, 0x62, 0x62, 0x63, 0x65, 0x67, 0x69, + 0x6b, 0x6c, 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x70, 0x70, + 0x70, 0x70, 0x6f, 0x70, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6d, 0x6d, + 0x6d, 0x6d, 0x6c, 0x6d, 0x70, 0x75, 0x79, 0x7c, 0x7d, 0x7e, 0x81, 0x83, + 0x86, 0x88, 0x88, 0x8a, 0x8b, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x91, 0x94, + 0x96, 0x97, 0x97, 0x97, 0x95, 0x91, 0x91, 0x8f, 0x90, 0x8f, 0x8d, 0x8d, + 0x8d, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x92, 0x95, 0x97, 0x97, 0x96, 0x96, + 0x94, 0x93, 0x92, 0x8e, 0x89, 0x85, 0x81, 0x7e, 0x7b, 0x7c, 0x89, 0x97, + 0x9e, 0xa5, 0xa9, 0xaa, 0xaa, 0xad, 0xb8, 0xb8, 0x99, 0x8c, 0x90, 0xa1, + 0xac, 0xbc, 0xc3, 0xc5, 0xc2, 0xae, 0xb4, 0xbb, 0xb7, 0xb1, 0xcb, 0xad, + 0x5a, 0x73, 0x8f, 0xa8, 0xc2, 0xcb, 0xbf, 0xb6, 0xaf, 0xb6, 0xb3, 0xaa, + 0xa2, 0x97, 0x95, 0x98, 0x95, 0x99, 0xa5, 0xa2, 0x93, 0x88, 0x85, 0x83, + 0x83, 0x87, 0x85, 0x82, 0x81, 0x82, 0x81, 0x80, 0x80, 0x80, 0x7e, 0x79, + 0x77, 0x77, 0x77, 0x79, 0x75, 0x6f, 0x6a, 0x64, 0x67, 0x70, 0x71, 0x70, + 0x72, 0x75, 0x7b, 0x80, 0x82, 0x84, 0x88, 0x8b, 0x91, 0x93, 0x92, 0x94, + 0x92, 0x8e, 0x8f, 0x93, 0x98, 0xa0, 0xa7, 0xae, 0xb6, 0xc1, 0xc9, 0xc9, + 0xc4, 0xc2, 0xbf, 0xbd, 0xba, 0xb9, 0xb6, 0xa5, 0x7c, 0x85, 0xa2, 0x8e, + 0x48, 0x49, 0x6f, 0x7c, 0x7e, 0x82, 0x84, 0x39, 0x20, 0x1d, 0x1c, 0x1d, + 0x22, 0x1e, 0x1e, 0x22, 0x16, 0x11, 0x10, 0x10, 0x16, 0x39, 0x74, 0x7c, + 0x79, 0x73, 0x72, 0x73, 0x72, 0x71, 0x6f, 0x69, 0x63, 0x5f, 0x5d, 0x5d, + 0x5f, 0x60, 0x61, 0x61, 0x62, 0x64, 0x65, 0x67, 0x67, 0x68, 0x69, 0x69, + 0x6b, 0x6b, 0x6b, 0x6b, 0x6a, 0x6c, 0x6c, 0x6d, 0x6e, 0x6e, 0x70, 0x70, + 0x71, 0x72, 0x73, 0x74, 0x73, 0x73, 0x72, 0x72, 0x73, 0x73, 0x72, 0x70, + 0x6e, 0x6b, 0x69, 0x68, 0x64, 0x5f, 0x59, 0x53, 0x50, 0x4c, 0x47, 0x42, + 0x3d, 0x3a, 0x37, 0x2f, 0x27, 0x20, 0x1b, 0x14, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x12, 0x13, 0x13, 0x13, 0x12, 0x11, 0x11, 0x13, + 0x56, 0x57, 0x56, 0x55, 0x55, 0x57, 0x58, 0x58, 0x58, 0x5a, 0x5b, 0x5d, + 0x5e, 0x60, 0x61, 0x61, 0x63, 0x64, 0x66, 0x69, 0x6b, 0x6c, 0x6d, 0x6d, + 0x6e, 0x6f, 0x70, 0x70, 0x70, 0x70, 0x6f, 0x70, 0x70, 0x70, 0x6f, 0x70, + 0x6f, 0x6e, 0x6f, 0x6f, 0x6f, 0x6f, 0x6e, 0x6d, 0x6c, 0x6d, 0x6c, 0x6e, + 0x71, 0x75, 0x7a, 0x7c, 0x7d, 0x7f, 0x81, 0x83, 0x85, 0x87, 0x88, 0x8a, + 0x8b, 0x8c, 0x8e, 0x8f, 0x90, 0x90, 0x91, 0x95, 0x97, 0x97, 0x98, 0x96, + 0x93, 0x91, 0x90, 0x8f, 0x8f, 0x8e, 0x8d, 0x8d, 0x8e, 0x8d, 0x8d, 0x8f, + 0x8f, 0x90, 0x92, 0x96, 0x98, 0x98, 0x96, 0x97, 0x95, 0x93, 0x92, 0x8f, + 0x89, 0x85, 0x82, 0x80, 0x7d, 0x81, 0x8f, 0x9c, 0xa2, 0xa6, 0xa9, 0xab, + 0xaa, 0xac, 0xb4, 0xb5, 0xab, 0xa8, 0xa6, 0x9f, 0x94, 0x9d, 0xb6, 0xbe, + 0xb5, 0xa7, 0xbd, 0xbf, 0xb4, 0xa2, 0xb4, 0xad, 0x64, 0x5a, 0x6e, 0x9c, + 0xb9, 0xca, 0xc5, 0xbe, 0xb5, 0xb8, 0xb6, 0xb0, 0xa8, 0x9d, 0x9b, 0x9a, + 0x97, 0x9c, 0xa9, 0xa6, 0x94, 0x87, 0x82, 0x7f, 0x7e, 0x88, 0x87, 0x83, + 0x81, 0x81, 0x80, 0x80, 0x81, 0x81, 0x7e, 0x7d, 0x7e, 0x7d, 0x7a, 0x7a, + 0x78, 0x74, 0x71, 0x6c, 0x6a, 0x6f, 0x74, 0x75, 0x74, 0x75, 0x7a, 0x80, + 0x82, 0x84, 0x86, 0x8a, 0x90, 0x92, 0x91, 0x91, 0x90, 0x91, 0x91, 0x93, + 0x98, 0x9e, 0xa2, 0xaf, 0xb8, 0xbf, 0xc4, 0xc5, 0xc3, 0xbf, 0xb9, 0xb5, + 0xb5, 0xb5, 0xb3, 0xa5, 0x80, 0x84, 0x9a, 0x87, 0x45, 0x49, 0x72, 0x81, + 0x85, 0x83, 0x64, 0x28, 0x1d, 0x1e, 0x22, 0x23, 0x27, 0x21, 0x21, 0x22, + 0x15, 0x10, 0x10, 0x10, 0x17, 0x3a, 0x73, 0x7c, 0x79, 0x74, 0x74, 0x74, + 0x74, 0x74, 0x73, 0x6d, 0x64, 0x5f, 0x5d, 0x5c, 0x5e, 0x60, 0x61, 0x62, + 0x63, 0x65, 0x66, 0x68, 0x68, 0x69, 0x6a, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, + 0x6b, 0x6c, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x70, 0x71, 0x72, 0x73, 0x74, + 0x73, 0x73, 0x72, 0x72, 0x73, 0x72, 0x72, 0x70, 0x6e, 0x6a, 0x69, 0x68, + 0x64, 0x5e, 0x5a, 0x56, 0x52, 0x4d, 0x47, 0x41, 0x3d, 0x3a, 0x37, 0x2e, + 0x26, 0x1e, 0x19, 0x14, 0x11, 0x11, 0x11, 0x12, 0x12, 0x11, 0x11, 0x11, + 0x11, 0x13, 0x13, 0x12, 0x12, 0x12, 0x12, 0x13, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x56, 0x56, 0x58, 0x5a, 0x5c, 0x5d, 0x5e, 0x5f, 0x61, 0x61, + 0x64, 0x65, 0x66, 0x67, 0x69, 0x6a, 0x6c, 0x6d, 0x6d, 0x6f, 0x70, 0x71, + 0x71, 0x71, 0x70, 0x71, 0x70, 0x70, 0x6f, 0x70, 0x6f, 0x6f, 0x6f, 0x70, + 0x70, 0x6f, 0x6e, 0x6d, 0x6c, 0x6c, 0x6d, 0x70, 0x72, 0x76, 0x7a, 0x7d, + 0x7e, 0x7f, 0x82, 0x83, 0x85, 0x88, 0x8a, 0x8b, 0x8b, 0x8d, 0x8e, 0x8e, + 0x8f, 0x8f, 0x91, 0x94, 0x96, 0x97, 0x98, 0x96, 0x93, 0x92, 0x91, 0x8f, + 0x8d, 0x8c, 0x8d, 0x8d, 0x8e, 0x8d, 0x8d, 0x8f, 0x90, 0x93, 0x94, 0x98, + 0x99, 0x99, 0x99, 0x98, 0x96, 0x93, 0x91, 0x8d, 0x8b, 0x87, 0x85, 0x83, + 0x83, 0x89, 0x96, 0xa2, 0xa6, 0xa7, 0xaa, 0xa9, 0x93, 0x7f, 0x66, 0x58, + 0x53, 0x68, 0x7f, 0x9e, 0xa5, 0x97, 0x95, 0x97, 0x9c, 0xa2, 0xb4, 0xcb, + 0xcc, 0xb6, 0xa7, 0xb7, 0x84, 0x4a, 0x50, 0x8e, 0xab, 0xc5, 0xc5, 0xbf, + 0xb4, 0xb4, 0xb6, 0xb2, 0xae, 0xa5, 0x9f, 0xa0, 0xa3, 0xa6, 0xaa, 0xa8, + 0x9e, 0x8e, 0x86, 0x80, 0x7d, 0x84, 0x88, 0x87, 0x82, 0x82, 0x81, 0x82, + 0x83, 0x85, 0x81, 0x7f, 0x81, 0x83, 0x82, 0x81, 0x7f, 0x7b, 0x78, 0x74, + 0x6f, 0x71, 0x77, 0x79, 0x77, 0x76, 0x79, 0x7e, 0x82, 0x87, 0x8a, 0x8b, + 0x8b, 0x8a, 0x8a, 0x8b, 0x8c, 0x90, 0x92, 0x93, 0x99, 0xa1, 0xa6, 0xac, + 0xb1, 0xba, 0xc0, 0xbf, 0xbf, 0xbc, 0xb5, 0xae, 0xaa, 0xaf, 0xb0, 0xa6, + 0x87, 0x7e, 0x91, 0x7d, 0x3e, 0x47, 0x74, 0x8a, 0x8d, 0x7b, 0x3c, 0x19, + 0x1c, 0x23, 0x28, 0x23, 0x22, 0x23, 0x23, 0x20, 0x14, 0x10, 0x10, 0x11, + 0x17, 0x3c, 0x72, 0x7a, 0x78, 0x74, 0x75, 0x76, 0x79, 0x7a, 0x79, 0x71, + 0x67, 0x61, 0x5f, 0x5c, 0x5f, 0x61, 0x62, 0x63, 0x64, 0x66, 0x67, 0x69, + 0x6a, 0x6a, 0x6a, 0x6b, 0x6c, 0x6d, 0x6d, 0x6d, 0x6d, 0x6e, 0x6e, 0x6e, + 0x6f, 0x6f, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x74, 0x73, 0x74, 0x73, 0x74, + 0x74, 0x73, 0x72, 0x70, 0x6f, 0x6d, 0x6a, 0x68, 0x64, 0x5e, 0x5a, 0x56, + 0x53, 0x4e, 0x47, 0x41, 0x3c, 0x3a, 0x37, 0x2f, 0x26, 0x1e, 0x1a, 0x15, + 0x12, 0x11, 0x12, 0x12, 0x12, 0x11, 0x10, 0x11, 0x11, 0x13, 0x13, 0x13, + 0x12, 0x12, 0x12, 0x11, 0x57, 0x58, 0x58, 0x58, 0x58, 0x57, 0x56, 0x57, + 0x58, 0x5a, 0x5c, 0x5d, 0x5e, 0x5e, 0x60, 0x61, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x6f, 0x70, 0x71, 0x70, 0x71, 0x72, + 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x72, 0x72, 0x71, 0x71, 0x70, 0x6f, + 0x6e, 0x6d, 0x6e, 0x71, 0x73, 0x76, 0x7a, 0x7d, 0x7e, 0x7f, 0x82, 0x83, + 0x85, 0x88, 0x8a, 0x8a, 0x8a, 0x8b, 0x8c, 0x8e, 0x90, 0x90, 0x91, 0x94, + 0x96, 0x96, 0x96, 0x94, 0x94, 0x92, 0x91, 0x90, 0x8d, 0x8d, 0x8e, 0x8e, + 0x8e, 0x8d, 0x8e, 0x90, 0x91, 0x93, 0x95, 0x99, 0x9a, 0x9a, 0x99, 0x98, + 0x96, 0x93, 0x90, 0x8d, 0x8b, 0x8a, 0x88, 0x87, 0x87, 0x8f, 0x9c, 0xa5, + 0xa8, 0xaa, 0xa5, 0x88, 0x5b, 0x48, 0x43, 0x3b, 0x36, 0x5e, 0x6a, 0x65, + 0x8d, 0xb0, 0xa0, 0x8b, 0x77, 0x95, 0xb5, 0xcf, 0xd5, 0xc8, 0xb9, 0xb7, + 0x97, 0x4f, 0x4c, 0x8c, 0xa6, 0xc0, 0xc6, 0xc0, 0xb4, 0xae, 0xb1, 0xb5, + 0xb4, 0xad, 0xa4, 0xa5, 0xab, 0xad, 0xac, 0xad, 0xaa, 0x97, 0x8b, 0x80, + 0x7c, 0x7c, 0x83, 0x85, 0x86, 0x83, 0x7e, 0x7f, 0x81, 0x86, 0x85, 0x81, + 0x7f, 0x7f, 0x82, 0x88, 0x89, 0x83, 0x7e, 0x77, 0x70, 0x73, 0x78, 0x7a, + 0x7c, 0x7d, 0x7f, 0x81, 0x85, 0x8c, 0x8e, 0x8d, 0x8a, 0x88, 0x87, 0x89, + 0x8b, 0x8c, 0x8e, 0x93, 0x9e, 0xab, 0xab, 0xaa, 0xae, 0xb8, 0xc0, 0xbc, + 0xb9, 0xb5, 0xaf, 0xa6, 0xa0, 0xa4, 0xa7, 0xa6, 0x8f, 0x78, 0x81, 0x6e, + 0x37, 0x3b, 0x70, 0x82, 0x84, 0x72, 0x2c, 0x15, 0x1d, 0x24, 0x2b, 0x28, + 0x22, 0x22, 0x23, 0x20, 0x14, 0x10, 0x10, 0x11, 0x19, 0x40, 0x70, 0x78, + 0x77, 0x74, 0x74, 0x78, 0x7c, 0x7e, 0x7d, 0x76, 0x6b, 0x63, 0x5f, 0x5d, + 0x5f, 0x61, 0x62, 0x63, 0x65, 0x67, 0x69, 0x6b, 0x6a, 0x6b, 0x6b, 0x6d, + 0x6f, 0x6f, 0x6f, 0x6e, 0x6f, 0x70, 0x71, 0x70, 0x6f, 0x6f, 0x6e, 0x6f, + 0x70, 0x70, 0x70, 0x73, 0x73, 0x74, 0x73, 0x74, 0x73, 0x73, 0x72, 0x70, + 0x6f, 0x6c, 0x69, 0x67, 0x64, 0x5e, 0x59, 0x55, 0x52, 0x4e, 0x47, 0x41, + 0x3d, 0x3b, 0x38, 0x2f, 0x28, 0x20, 0x1b, 0x15, 0x12, 0x11, 0x11, 0x11, + 0x12, 0x11, 0x11, 0x11, 0x12, 0x13, 0x12, 0x13, 0x13, 0x13, 0x12, 0x11, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x57, 0x57, 0x57, 0x58, 0x59, 0x5b, 0x5d, + 0x5d, 0x5e, 0x60, 0x61, 0x64, 0x66, 0x66, 0x66, 0x68, 0x6b, 0x6c, 0x6d, + 0x6e, 0x6f, 0x6f, 0x70, 0x71, 0x70, 0x71, 0x72, 0x72, 0x72, 0x71, 0x71, + 0x71, 0x72, 0x71, 0x71, 0x71, 0x71, 0x70, 0x6f, 0x6e, 0x6d, 0x6e, 0x71, + 0x74, 0x76, 0x7a, 0x7d, 0x7e, 0x7f, 0x82, 0x84, 0x85, 0x87, 0x89, 0x8a, + 0x8a, 0x8c, 0x8c, 0x8d, 0x8f, 0x90, 0x90, 0x94, 0x95, 0x95, 0x96, 0x94, + 0x93, 0x92, 0x91, 0x90, 0x8e, 0x8d, 0x8e, 0x8e, 0x8d, 0x8d, 0x8f, 0x91, + 0x93, 0x94, 0x96, 0x99, 0x9b, 0x9a, 0x99, 0x98, 0x95, 0x92, 0x90, 0x8d, + 0x8b, 0x8b, 0x8a, 0x89, 0x8a, 0x92, 0x9e, 0xa6, 0xa9, 0xaa, 0x9f, 0x6f, + 0x41, 0x35, 0x3f, 0x3f, 0x43, 0x6e, 0x6d, 0x46, 0x6e, 0xaf, 0xac, 0x94, + 0x73, 0x91, 0xb9, 0xcd, 0xcf, 0xc8, 0xc3, 0xb6, 0xa2, 0x5f, 0x58, 0x8c, + 0xa4, 0xbd, 0xc4, 0xc0, 0xb3, 0xab, 0xaf, 0xb7, 0xb7, 0xb0, 0xa9, 0xa7, + 0xac, 0xaf, 0xae, 0xb0, 0xad, 0x9b, 0x8e, 0x7f, 0x7b, 0x7b, 0x81, 0x84, + 0x86, 0x84, 0x7e, 0x7d, 0x80, 0x85, 0x86, 0x82, 0x7e, 0x7e, 0x83, 0x8a, + 0x8c, 0x87, 0x81, 0x79, 0x72, 0x75, 0x79, 0x7b, 0x7f, 0x82, 0x84, 0x86, + 0x89, 0x8f, 0x8f, 0x8d, 0x89, 0x88, 0x87, 0x89, 0x8c, 0x8c, 0x8e, 0x95, + 0xa1, 0xae, 0xac, 0xaa, 0xad, 0xb6, 0xbf, 0xbc, 0xb6, 0xb2, 0xac, 0xa1, + 0x9c, 0x9f, 0xa3, 0xa5, 0x91, 0x76, 0x7c, 0x6a, 0x36, 0x38, 0x6f, 0x7d, + 0x7c, 0x6c, 0x28, 0x15, 0x1d, 0x25, 0x2a, 0x2b, 0x25, 0x24, 0x23, 0x1f, + 0x14, 0x10, 0x11, 0x11, 0x1a, 0x43, 0x70, 0x77, 0x76, 0x74, 0x74, 0x78, + 0x7d, 0x7f, 0x7f, 0x79, 0x6d, 0x64, 0x60, 0x5e, 0x60, 0x62, 0x63, 0x64, + 0x66, 0x68, 0x6b, 0x6c, 0x6b, 0x6b, 0x6b, 0x6f, 0x70, 0x71, 0x71, 0x70, + 0x70, 0x71, 0x72, 0x71, 0x6f, 0x6e, 0x6e, 0x70, 0x70, 0x71, 0x70, 0x72, + 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x72, 0x70, 0x6f, 0x6c, 0x69, 0x67, + 0x64, 0x5e, 0x59, 0x55, 0x52, 0x4e, 0x47, 0x41, 0x3e, 0x3c, 0x37, 0x30, + 0x28, 0x21, 0x1c, 0x15, 0x12, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, + 0x13, 0x13, 0x13, 0x14, 0x14, 0x13, 0x13, 0x11, 0x59, 0x58, 0x58, 0x58, + 0x58, 0x57, 0x57, 0x57, 0x58, 0x59, 0x5b, 0x5d, 0x5d, 0x5e, 0x5f, 0x61, + 0x63, 0x65, 0x66, 0x66, 0x68, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x6f, 0x71, + 0x71, 0x70, 0x71, 0x72, 0x72, 0x71, 0x71, 0x71, 0x70, 0x71, 0x71, 0x71, + 0x72, 0x71, 0x70, 0x6f, 0x6f, 0x6d, 0x6e, 0x72, 0x74, 0x77, 0x7a, 0x7d, + 0x7e, 0x7f, 0x82, 0x84, 0x85, 0x88, 0x89, 0x8a, 0x89, 0x8b, 0x8c, 0x8d, + 0x8f, 0x90, 0x91, 0x94, 0x95, 0x95, 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, + 0x8e, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8f, 0x91, 0x93, 0x94, 0x96, 0x99, + 0x9b, 0x9b, 0x99, 0x98, 0x94, 0x93, 0x90, 0x8e, 0x8c, 0x8c, 0x8b, 0x8a, + 0x8c, 0x94, 0xa0, 0xa7, 0xaa, 0xab, 0x98, 0x5f, 0x3c, 0x35, 0x3f, 0x42, + 0x56, 0x7d, 0x74, 0x40, 0x56, 0x9a, 0xb1, 0xa5, 0x85, 0x94, 0xbb, 0xc7, + 0xc6, 0xc1, 0xc6, 0xb7, 0xad, 0x76, 0x6a, 0x89, 0x9f, 0xba, 0xc1, 0xbe, + 0xb1, 0xaa, 0xb2, 0xba, 0xba, 0xb3, 0xae, 0xaa, 0xae, 0xb0, 0xb1, 0xb0, + 0xad, 0x9e, 0x90, 0x7d, 0x7a, 0x7d, 0x82, 0x85, 0x85, 0x84, 0x7f, 0x7f, + 0x80, 0x85, 0x86, 0x82, 0x7f, 0x81, 0x85, 0x8b, 0x8d, 0x89, 0x84, 0x7b, + 0x75, 0x78, 0x7a, 0x7c, 0x81, 0x84, 0x88, 0x8a, 0x8d, 0x90, 0x8f, 0x8d, + 0x88, 0x87, 0x88, 0x89, 0x8e, 0x8e, 0x91, 0x97, 0xa3, 0xae, 0xac, 0xac, + 0xae, 0xb5, 0xbb, 0xbb, 0xb6, 0xb1, 0xa9, 0x9e, 0x99, 0x9c, 0xa0, 0xa3, + 0x90, 0x77, 0x7f, 0x6d, 0x38, 0x3a, 0x71, 0x7c, 0x79, 0x64, 0x25, 0x14, + 0x1e, 0x25, 0x29, 0x29, 0x26, 0x25, 0x23, 0x1e, 0x14, 0x11, 0x11, 0x11, + 0x1b, 0x46, 0x70, 0x78, 0x77, 0x74, 0x75, 0x7a, 0x7f, 0x81, 0x80, 0x7a, + 0x6e, 0x65, 0x61, 0x5e, 0x60, 0x63, 0x64, 0x65, 0x67, 0x69, 0x6b, 0x6c, + 0x6b, 0x6b, 0x6c, 0x6f, 0x71, 0x71, 0x71, 0x70, 0x71, 0x72, 0x72, 0x71, + 0x70, 0x6f, 0x6e, 0x70, 0x70, 0x71, 0x70, 0x72, 0x72, 0x73, 0x73, 0x73, + 0x73, 0x73, 0x72, 0x70, 0x6f, 0x6c, 0x69, 0x67, 0x64, 0x5e, 0x5a, 0x56, + 0x53, 0x4f, 0x47, 0x42, 0x3e, 0x3c, 0x38, 0x31, 0x29, 0x22, 0x1d, 0x16, + 0x12, 0x11, 0x11, 0x11, 0x12, 0x11, 0x11, 0x12, 0x13, 0x13, 0x13, 0x14, + 0x14, 0x14, 0x13, 0x11, 0x5a, 0x58, 0x58, 0x58, 0x58, 0x57, 0x58, 0x58, + 0x59, 0x59, 0x5a, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x63, 0x65, 0x66, 0x66, + 0x68, 0x6a, 0x6c, 0x6c, 0x6d, 0x6f, 0x70, 0x71, 0x71, 0x70, 0x70, 0x71, + 0x71, 0x70, 0x70, 0x70, 0x71, 0x71, 0x70, 0x70, 0x71, 0x70, 0x70, 0x70, + 0x6f, 0x6d, 0x6e, 0x71, 0x74, 0x76, 0x7a, 0x7d, 0x7d, 0x7f, 0x82, 0x84, + 0x86, 0x86, 0x87, 0x89, 0x8a, 0x8a, 0x8c, 0x8c, 0x8d, 0x8f, 0x90, 0x93, + 0x94, 0x94, 0x94, 0x93, 0x92, 0x90, 0x8f, 0x8e, 0x8e, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8f, 0x8f, 0x91, 0x92, 0x93, 0x97, 0x9a, 0x9a, 0x9a, 0x9a, 0x97, + 0x94, 0x92, 0x92, 0x8f, 0x8e, 0x8e, 0x8e, 0x8d, 0x8f, 0x98, 0xa2, 0xa8, + 0xac, 0xab, 0x85, 0x47, 0x40, 0x41, 0x3d, 0x43, 0x78, 0x95, 0x83, 0x43, + 0x34, 0x71, 0xb2, 0xc2, 0xad, 0x98, 0xb9, 0xbf, 0xbb, 0xb9, 0xc6, 0xbe, + 0xbe, 0x9c, 0x86, 0x7d, 0x94, 0xb0, 0xbb, 0xba, 0xae, 0xab, 0xb9, 0xbe, + 0xbe, 0xb9, 0xb8, 0xb0, 0xb1, 0xb3, 0xb5, 0xb3, 0xae, 0xa3, 0x95, 0x7e, + 0x7a, 0x81, 0x85, 0x84, 0x83, 0x85, 0x82, 0x81, 0x82, 0x84, 0x86, 0x82, + 0x82, 0x84, 0x89, 0x89, 0x8d, 0x8d, 0x89, 0x80, 0x7b, 0x7d, 0x7d, 0x7f, + 0x82, 0x85, 0x8b, 0x8e, 0x90, 0x90, 0x8d, 0x8a, 0x88, 0x88, 0x89, 0x8b, + 0x8f, 0x93, 0x97, 0x9e, 0xa6, 0xac, 0xac, 0xaf, 0xb0, 0xb2, 0xb5, 0xb8, + 0xb5, 0xb0, 0xa6, 0x9a, 0x95, 0x98, 0x9b, 0x9d, 0x8c, 0x7c, 0x86, 0x74, + 0x3c, 0x3e, 0x75, 0x80, 0x74, 0x51, 0x1f, 0x15, 0x21, 0x27, 0x26, 0x25, + 0x27, 0x27, 0x24, 0x1c, 0x14, 0x11, 0x10, 0x11, 0x1c, 0x49, 0x72, 0x78, + 0x77, 0x74, 0x76, 0x7b, 0x81, 0x83, 0x83, 0x7c, 0x71, 0x66, 0x62, 0x60, + 0x61, 0x64, 0x65, 0x66, 0x68, 0x6a, 0x6b, 0x6c, 0x6c, 0x6d, 0x6f, 0x6f, + 0x71, 0x72, 0x72, 0x71, 0x73, 0x74, 0x73, 0x72, 0x72, 0x71, 0x70, 0x71, + 0x71, 0x70, 0x70, 0x71, 0x71, 0x71, 0x72, 0x72, 0x73, 0x74, 0x74, 0x72, + 0x70, 0x6c, 0x6a, 0x69, 0x64, 0x60, 0x5c, 0x57, 0x54, 0x4f, 0x48, 0x43, + 0x3e, 0x3b, 0x38, 0x31, 0x29, 0x22, 0x1d, 0x16, 0x11, 0x11, 0x12, 0x12, + 0x11, 0x11, 0x11, 0x12, 0x12, 0x13, 0x14, 0x15, 0x14, 0x14, 0x12, 0x11, + 0x59, 0x57, 0x57, 0x57, 0x57, 0x57, 0x59, 0x59, 0x59, 0x59, 0x5b, 0x5c, + 0x5c, 0x5d, 0x60, 0x61, 0x63, 0x63, 0x64, 0x65, 0x67, 0x69, 0x6a, 0x6a, + 0x6c, 0x6d, 0x6f, 0x71, 0x71, 0x70, 0x71, 0x70, 0x70, 0x70, 0x71, 0x72, + 0x71, 0x70, 0x71, 0x72, 0x71, 0x71, 0x70, 0x70, 0x70, 0x6f, 0x70, 0x72, + 0x74, 0x76, 0x79, 0x7c, 0x7d, 0x7f, 0x82, 0x85, 0x86, 0x87, 0x87, 0x89, + 0x89, 0x89, 0x8b, 0x8b, 0x8c, 0x8e, 0x91, 0x93, 0x93, 0x93, 0x93, 0x92, + 0x90, 0x8f, 0x8e, 0x8f, 0x8e, 0x8d, 0x8d, 0x8d, 0x8d, 0x8e, 0x8f, 0x91, + 0x92, 0x94, 0x97, 0x9a, 0x9b, 0x9b, 0x9a, 0x97, 0x94, 0x93, 0x92, 0x92, + 0x90, 0x91, 0x90, 0x90, 0x95, 0x9e, 0xa7, 0xab, 0xaf, 0xa9, 0x6c, 0x37, + 0x43, 0x45, 0x33, 0x3f, 0x88, 0xa4, 0x8d, 0x44, 0x30, 0x7b, 0xb4, 0xc7, + 0xbf, 0x94, 0xa9, 0xbc, 0xc1, 0xc1, 0xc1, 0xc8, 0xb9, 0xa0, 0x82, 0x5f, + 0x8d, 0xa3, 0xb5, 0xb7, 0xad, 0xb3, 0xbc, 0xc2, 0xc3, 0xc1, 0xc3, 0xbc, + 0xb8, 0xb9, 0xb9, 0xba, 0xb6, 0xae, 0xa2, 0x8c, 0x7e, 0x7d, 0x80, 0x82, + 0x86, 0x89, 0x86, 0x84, 0x83, 0x82, 0x84, 0x80, 0x81, 0x84, 0x89, 0x8a, + 0x8b, 0x8c, 0x8a, 0x85, 0x83, 0x83, 0x82, 0x83, 0x84, 0x82, 0x85, 0x87, + 0x8a, 0x8c, 0x89, 0x86, 0x87, 0x89, 0x8b, 0x8d, 0x90, 0x97, 0x9d, 0xa5, + 0xa9, 0xad, 0xae, 0xb2, 0xb4, 0xb5, 0xb6, 0xb3, 0xb2, 0xae, 0xa4, 0x97, + 0x8d, 0x8d, 0x91, 0x98, 0x8e, 0x84, 0x82, 0x6d, 0x3b, 0x3b, 0x75, 0x7b, + 0x65, 0x36, 0x16, 0x18, 0x28, 0x2c, 0x24, 0x1f, 0x22, 0x23, 0x21, 0x1a, + 0x14, 0x11, 0x10, 0x13, 0x20, 0x4f, 0x73, 0x78, 0x76, 0x74, 0x77, 0x7e, + 0x84, 0x87, 0x87, 0x81, 0x74, 0x6b, 0x65, 0x61, 0x62, 0x64, 0x65, 0x66, + 0x68, 0x6b, 0x6c, 0x6e, 0x70, 0x70, 0x71, 0x70, 0x71, 0x72, 0x73, 0x75, + 0x75, 0x75, 0x75, 0x75, 0x74, 0x73, 0x71, 0x71, 0x70, 0x6f, 0x71, 0x70, + 0x71, 0x71, 0x71, 0x73, 0x73, 0x74, 0x74, 0x72, 0x70, 0x6d, 0x6a, 0x68, + 0x64, 0x60, 0x5c, 0x58, 0x54, 0x4e, 0x48, 0x44, 0x3f, 0x3d, 0x39, 0x32, + 0x28, 0x22, 0x1d, 0x16, 0x12, 0x11, 0x12, 0x12, 0x11, 0x11, 0x11, 0x12, + 0x13, 0x14, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x59, 0x58, 0x59, 0x59, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5f, 0x61, + 0x63, 0x63, 0x64, 0x65, 0x67, 0x67, 0x69, 0x6a, 0x6c, 0x6d, 0x6e, 0x70, + 0x70, 0x71, 0x71, 0x72, 0x71, 0x72, 0x73, 0x74, 0x72, 0x72, 0x73, 0x73, + 0x73, 0x73, 0x73, 0x72, 0x71, 0x6f, 0x70, 0x72, 0x73, 0x75, 0x79, 0x7d, + 0x7e, 0x80, 0x83, 0x85, 0x86, 0x86, 0x87, 0x88, 0x89, 0x89, 0x89, 0x8a, + 0x8b, 0x8c, 0x90, 0x93, 0x93, 0x93, 0x93, 0x91, 0x8f, 0x8f, 0x8e, 0x8e, + 0x8d, 0x8c, 0x8d, 0x8d, 0x8d, 0x8f, 0x8f, 0x91, 0x92, 0x94, 0x98, 0x9b, + 0x9b, 0x9b, 0x99, 0x97, 0x94, 0x94, 0x94, 0x93, 0x92, 0x92, 0x94, 0x97, + 0x9e, 0xa8, 0xaf, 0xb3, 0xb6, 0xa9, 0x5b, 0x33, 0x3e, 0x3c, 0x28, 0x3a, + 0x8c, 0xab, 0x92, 0x49, 0x4c, 0xa3, 0xb8, 0xba, 0xb9, 0xa9, 0x98, 0xa0, + 0xaa, 0xb3, 0xb2, 0xba, 0xaa, 0x9a, 0x7a, 0x4f, 0x87, 0x9c, 0xb2, 0xb6, + 0xae, 0xb7, 0xba, 0xc0, 0xc3, 0xc5, 0xcb, 0xc6, 0xc0, 0xbe, 0xbb, 0xb7, + 0xb5, 0xb0, 0xa7, 0x97, 0x85, 0x7c, 0x7c, 0x7e, 0x84, 0x8c, 0x8b, 0x89, + 0x87, 0x85, 0x84, 0x81, 0x82, 0x83, 0x86, 0x8b, 0x8a, 0x88, 0x88, 0x88, + 0x85, 0x84, 0x87, 0x89, 0x8b, 0x87, 0x86, 0x85, 0x85, 0x86, 0x87, 0x85, + 0x87, 0x89, 0x8b, 0x8f, 0x96, 0x9b, 0x9e, 0xa3, 0xaa, 0xad, 0xaf, 0xb4, + 0xb5, 0xb4, 0xb2, 0xb0, 0xb0, 0xab, 0x9d, 0x8c, 0x80, 0x7f, 0x84, 0x91, + 0x95, 0x8c, 0x7b, 0x63, 0x38, 0x34, 0x67, 0x67, 0x52, 0x29, 0x15, 0x1c, + 0x2d, 0x30, 0x25, 0x19, 0x1a, 0x1b, 0x1c, 0x1a, 0x16, 0x12, 0x12, 0x19, + 0x31, 0x57, 0x74, 0x77, 0x76, 0x75, 0x79, 0x80, 0x85, 0x88, 0x89, 0x83, + 0x77, 0x6e, 0x68, 0x62, 0x62, 0x65, 0x67, 0x68, 0x69, 0x6c, 0x6c, 0x6e, + 0x71, 0x71, 0x72, 0x71, 0x72, 0x74, 0x75, 0x76, 0x77, 0x77, 0x76, 0x76, + 0x76, 0x76, 0x73, 0x71, 0x71, 0x70, 0x70, 0x71, 0x71, 0x71, 0x71, 0x73, + 0x73, 0x74, 0x74, 0x72, 0x70, 0x6d, 0x6a, 0x69, 0x65, 0x60, 0x5b, 0x57, + 0x54, 0x4e, 0x4a, 0x45, 0x41, 0x3e, 0x39, 0x32, 0x28, 0x21, 0x1d, 0x17, + 0x12, 0x12, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x13, 0x13, 0x13, 0x14, + 0x14, 0x14, 0x13, 0x14, 0x5a, 0x59, 0x5a, 0x5a, 0x59, 0x59, 0x57, 0x57, + 0x57, 0x59, 0x5a, 0x5b, 0x5b, 0x5c, 0x5d, 0x60, 0x62, 0x62, 0x63, 0x64, + 0x65, 0x67, 0x6a, 0x6b, 0x6c, 0x6c, 0x6e, 0x6f, 0x70, 0x71, 0x71, 0x72, + 0x72, 0x73, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x73, + 0x70, 0x6f, 0x71, 0x72, 0x73, 0x75, 0x79, 0x7d, 0x7f, 0x80, 0x82, 0x84, + 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x89, 0x89, 0x89, 0x8b, 0x8f, 0x92, + 0x92, 0x92, 0x92, 0x90, 0x8f, 0x8f, 0x8f, 0x8d, 0x8c, 0x8c, 0x8d, 0x8d, + 0x8d, 0x8e, 0x91, 0x92, 0x93, 0x95, 0x98, 0x9c, 0x9b, 0x9a, 0x98, 0x96, + 0x95, 0x94, 0x94, 0x94, 0x93, 0x94, 0x99, 0x9e, 0xa6, 0xb0, 0xb6, 0xb9, + 0xba, 0xa8, 0x55, 0x33, 0x3e, 0x3c, 0x2a, 0x3a, 0x8f, 0xae, 0x96, 0x57, + 0x73, 0xb4, 0xbd, 0xb6, 0xa8, 0x98, 0xa7, 0xa3, 0xa7, 0xbb, 0xbe, 0xb3, + 0xae, 0xa9, 0x88, 0x4e, 0x7a, 0x92, 0xad, 0xb5, 0xb0, 0xb8, 0xb8, 0xbe, + 0xc2, 0xc8, 0xd1, 0xd0, 0xcb, 0xc6, 0xc1, 0xb9, 0xb2, 0xae, 0xa8, 0x9d, + 0x8c, 0x7d, 0x7c, 0x7e, 0x83, 0x8a, 0x8c, 0x8c, 0x8b, 0x87, 0x86, 0x85, + 0x84, 0x83, 0x85, 0x8a, 0x8c, 0x8a, 0x89, 0x88, 0x87, 0x87, 0x89, 0x8a, + 0x8c, 0x89, 0x88, 0x87, 0x85, 0x84, 0x87, 0x86, 0x88, 0x8b, 0x90, 0x92, + 0x97, 0x9e, 0xa0, 0xa2, 0xa9, 0xab, 0xae, 0xb0, 0xb1, 0xb1, 0xb0, 0xad, + 0xad, 0xa8, 0x97, 0x7f, 0x75, 0x72, 0x78, 0x89, 0x95, 0x8a, 0x74, 0x5d, + 0x39, 0x33, 0x5b, 0x59, 0x48, 0x2a, 0x16, 0x1d, 0x2b, 0x2d, 0x24, 0x17, + 0x16, 0x17, 0x18, 0x1b, 0x1a, 0x13, 0x15, 0x24, 0x46, 0x5c, 0x72, 0x75, + 0x75, 0x77, 0x7b, 0x80, 0x85, 0x87, 0x89, 0x85, 0x79, 0x70, 0x6a, 0x64, + 0x63, 0x65, 0x67, 0x68, 0x6a, 0x6c, 0x6d, 0x6f, 0x71, 0x71, 0x72, 0x73, + 0x74, 0x76, 0x77, 0x78, 0x77, 0x78, 0x77, 0x76, 0x76, 0x76, 0x73, 0x73, + 0x72, 0x71, 0x70, 0x6f, 0x70, 0x70, 0x71, 0x72, 0x73, 0x74, 0x74, 0x72, + 0x70, 0x6c, 0x6a, 0x69, 0x65, 0x5f, 0x5b, 0x57, 0x54, 0x4e, 0x4a, 0x46, + 0x42, 0x3f, 0x3b, 0x32, 0x29, 0x23, 0x1e, 0x17, 0x11, 0x12, 0x12, 0x12, + 0x12, 0x10, 0x11, 0x12, 0x12, 0x12, 0x13, 0x14, 0x13, 0x13, 0x13, 0x13, + 0x5a, 0x59, 0x5a, 0x5a, 0x5a, 0x59, 0x57, 0x56, 0x57, 0x59, 0x5a, 0x5a, + 0x5b, 0x5b, 0x5d, 0x60, 0x62, 0x62, 0x62, 0x63, 0x65, 0x66, 0x6a, 0x6b, + 0x6b, 0x6c, 0x6e, 0x6f, 0x6f, 0x70, 0x71, 0x72, 0x72, 0x73, 0x74, 0x74, + 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x73, 0x70, 0x6f, 0x71, 0x73, + 0x74, 0x75, 0x79, 0x7c, 0x7f, 0x80, 0x81, 0x83, 0x85, 0x86, 0x86, 0x87, + 0x89, 0x8a, 0x89, 0x89, 0x88, 0x8b, 0x8e, 0x92, 0x92, 0x92, 0x92, 0x90, + 0x8f, 0x8f, 0x8e, 0x8c, 0x8c, 0x8c, 0x8d, 0x8d, 0x8d, 0x8d, 0x91, 0x92, + 0x93, 0x95, 0x99, 0x9b, 0x9a, 0x99, 0x98, 0x96, 0x95, 0x94, 0x94, 0x94, + 0x94, 0x98, 0x9f, 0xa5, 0xad, 0xb5, 0xb9, 0xbc, 0xbc, 0xa7, 0x51, 0x32, + 0x3b, 0x39, 0x29, 0x3a, 0x93, 0xb1, 0x98, 0x60, 0x8c, 0xbb, 0xbf, 0xb1, + 0x8e, 0x7a, 0xaa, 0xac, 0xae, 0xbe, 0xc4, 0xb5, 0xb4, 0xb2, 0x90, 0x4e, + 0x71, 0x8d, 0xa9, 0xb4, 0xb5, 0xba, 0xb6, 0xbc, 0xc1, 0xc7, 0xd0, 0xd4, + 0xd1, 0xcd, 0xc5, 0xbb, 0xb2, 0xaf, 0xab, 0xa1, 0x91, 0x81, 0x7e, 0x80, + 0x84, 0x88, 0x8b, 0x8b, 0x8b, 0x88, 0x87, 0x86, 0x85, 0x84, 0x85, 0x88, + 0x8c, 0x8c, 0x8c, 0x8b, 0x8a, 0x87, 0x87, 0x89, 0x8c, 0x8a, 0x88, 0x87, + 0x86, 0x86, 0x8a, 0x89, 0x8b, 0x8d, 0x93, 0x94, 0x99, 0x9e, 0xa1, 0xa5, + 0xa9, 0xab, 0xae, 0xaf, 0xaf, 0xb0, 0xaf, 0xaa, 0xa9, 0xa3, 0x91, 0x78, + 0x6d, 0x6a, 0x71, 0x84, 0x94, 0x87, 0x70, 0x59, 0x36, 0x2f, 0x52, 0x57, + 0x4d, 0x36, 0x1b, 0x1c, 0x25, 0x26, 0x1f, 0x15, 0x15, 0x15, 0x17, 0x1c, + 0x1a, 0x14, 0x1b, 0x2c, 0x4e, 0x5e, 0x72, 0x75, 0x75, 0x77, 0x7c, 0x80, + 0x85, 0x88, 0x8a, 0x86, 0x7b, 0x71, 0x6c, 0x65, 0x63, 0x65, 0x68, 0x69, + 0x6a, 0x6c, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x74, 0x75, 0x77, 0x78, 0x79, + 0x78, 0x78, 0x77, 0x77, 0x77, 0x77, 0x74, 0x73, 0x73, 0x72, 0x70, 0x6f, + 0x6f, 0x70, 0x70, 0x72, 0x73, 0x74, 0x73, 0x72, 0x70, 0x6c, 0x6a, 0x69, + 0x65, 0x5f, 0x5b, 0x57, 0x54, 0x4e, 0x4a, 0x46, 0x42, 0x3f, 0x3b, 0x32, + 0x29, 0x23, 0x1e, 0x17, 0x11, 0x12, 0x12, 0x12, 0x12, 0x10, 0x11, 0x12, + 0x12, 0x12, 0x13, 0x13, 0x13, 0x12, 0x12, 0x12, 0x5b, 0x5a, 0x5a, 0x5a, + 0x59, 0x59, 0x57, 0x57, 0x57, 0x58, 0x59, 0x5a, 0x5a, 0x5a, 0x5c, 0x5f, + 0x61, 0x60, 0x61, 0x63, 0x64, 0x66, 0x68, 0x6a, 0x6b, 0x6b, 0x6d, 0x6d, + 0x6e, 0x70, 0x71, 0x72, 0x72, 0x73, 0x74, 0x74, 0x73, 0x74, 0x74, 0x73, + 0x73, 0x74, 0x74, 0x73, 0x70, 0x6f, 0x72, 0x73, 0x75, 0x76, 0x78, 0x7a, + 0x7d, 0x7f, 0x80, 0x82, 0x84, 0x85, 0x85, 0x86, 0x87, 0x88, 0x88, 0x87, + 0x87, 0x89, 0x8d, 0x90, 0x90, 0x90, 0x90, 0x8e, 0x8d, 0x8e, 0x8e, 0x8c, + 0x8c, 0x8c, 0x8d, 0x8d, 0x8d, 0x8e, 0x91, 0x92, 0x93, 0x94, 0x98, 0x9a, + 0x99, 0x98, 0x97, 0x95, 0x95, 0x95, 0x95, 0x95, 0x98, 0xa1, 0xaa, 0xb0, + 0xb6, 0xbb, 0xbd, 0xbf, 0xbd, 0xa4, 0x4e, 0x30, 0x33, 0x30, 0x24, 0x39, + 0x93, 0xad, 0x94, 0x62, 0xa3, 0xc0, 0xbc, 0x9e, 0x59, 0x48, 0x90, 0xb4, + 0xb9, 0xb7, 0xc3, 0xbe, 0xb8, 0xb6, 0x92, 0x4b, 0x6a, 0x8d, 0xa9, 0xb8, + 0xc1, 0xbd, 0xb3, 0xb9, 0xc0, 0xc7, 0xcc, 0xd5, 0xd8, 0xd6, 0xcd, 0xbf, + 0xb5, 0xb4, 0xb2, 0xa7, 0x97, 0x8a, 0x85, 0x84, 0x86, 0x88, 0x8a, 0x8a, + 0x89, 0x88, 0x89, 0x87, 0x87, 0x87, 0x86, 0x86, 0x8b, 0x8e, 0x90, 0x94, + 0x92, 0x85, 0x84, 0x86, 0x8c, 0x8b, 0x88, 0x88, 0x89, 0x8b, 0x8e, 0x8f, + 0x8e, 0x8f, 0x94, 0x97, 0x9c, 0xa0, 0xa3, 0xa7, 0xaa, 0xac, 0xaf, 0xb0, + 0xb0, 0xaf, 0xae, 0xa5, 0xa0, 0x99, 0x86, 0x72, 0x64, 0x63, 0x6a, 0x7f, + 0x92, 0x84, 0x6c, 0x53, 0x2e, 0x25, 0x4a, 0x5a, 0x5c, 0x52, 0x31, 0x1f, + 0x1b, 0x19, 0x16, 0x12, 0x12, 0x14, 0x18, 0x1d, 0x17, 0x19, 0x2b, 0x3b, + 0x4e, 0x5f, 0x71, 0x75, 0x75, 0x77, 0x7c, 0x80, 0x85, 0x87, 0x8a, 0x87, + 0x7c, 0x73, 0x6e, 0x67, 0x64, 0x66, 0x68, 0x6a, 0x6b, 0x6d, 0x6f, 0x70, + 0x70, 0x71, 0x72, 0x74, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7a, 0x79, 0x78, + 0x78, 0x76, 0x75, 0x75, 0x74, 0x72, 0x71, 0x6f, 0x6f, 0x70, 0x70, 0x72, + 0x72, 0x73, 0x73, 0x72, 0x70, 0x6c, 0x6a, 0x69, 0x65, 0x5f, 0x5b, 0x56, + 0x53, 0x4e, 0x4a, 0x45, 0x42, 0x3f, 0x3b, 0x32, 0x28, 0x22, 0x1e, 0x17, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x10, 0x11, 0x12, 0x12, 0x12, 0x13, 0x13, + 0x13, 0x13, 0x12, 0x12, 0x5b, 0x5a, 0x5a, 0x5a, 0x59, 0x57, 0x58, 0x58, + 0x58, 0x58, 0x59, 0x5a, 0x5a, 0x59, 0x5b, 0x5e, 0x60, 0x61, 0x61, 0x61, + 0x63, 0x64, 0x66, 0x67, 0x69, 0x6b, 0x6c, 0x6c, 0x6d, 0x6e, 0x6f, 0x72, + 0x74, 0x74, 0x73, 0x74, 0x73, 0x74, 0x74, 0x73, 0x73, 0x74, 0x73, 0x73, + 0x72, 0x70, 0x72, 0x75, 0x76, 0x76, 0x77, 0x7a, 0x7b, 0x7c, 0x7f, 0x81, + 0x83, 0x84, 0x85, 0x85, 0x85, 0x86, 0x86, 0x86, 0x86, 0x88, 0x8d, 0x90, + 0x8f, 0x8e, 0x8d, 0x8d, 0x8b, 0x8c, 0x8c, 0x8c, 0x8c, 0x8b, 0x8c, 0x8c, + 0x8c, 0x8d, 0x90, 0x92, 0x93, 0x95, 0x98, 0x99, 0x98, 0x97, 0x96, 0x95, + 0x96, 0x96, 0x97, 0x9a, 0xa1, 0xac, 0xb4, 0xb9, 0xbe, 0xbf, 0xbd, 0xbf, + 0xbd, 0xa3, 0x4f, 0x30, 0x30, 0x2c, 0x22, 0x37, 0x7c, 0x7e, 0x65, 0x4a, + 0x92, 0xb7, 0x98, 0x6f, 0x33, 0x27, 0x4f, 0x96, 0xb1, 0xb3, 0xc0, 0xba, + 0xb1, 0xae, 0x8c, 0x49, 0x6a, 0x97, 0xc0, 0xd1, 0xd3, 0xc2, 0xb7, 0xbe, + 0xc5, 0xcb, 0xcc, 0xd3, 0xdc, 0xdf, 0xda, 0xca, 0xba, 0xb5, 0xb2, 0xab, + 0xa0, 0x94, 0x8d, 0x8d, 0x8d, 0x8a, 0x8a, 0x8b, 0x8c, 0x8e, 0x8e, 0x8c, + 0x88, 0x87, 0x88, 0x8a, 0x8d, 0x90, 0x95, 0x9f, 0x9d, 0x8a, 0x87, 0x89, + 0x8d, 0x8f, 0x8d, 0x8e, 0x8d, 0x8d, 0x90, 0x93, 0x92, 0x92, 0x95, 0x9a, + 0xa0, 0xa2, 0xa3, 0xa6, 0xac, 0xb1, 0xb0, 0xb0, 0xb0, 0xaf, 0xad, 0xa4, + 0x98, 0x8d, 0x7b, 0x68, 0x5e, 0x5e, 0x65, 0x77, 0x8c, 0x7f, 0x65, 0x52, + 0x38, 0x2b, 0x52, 0x53, 0x59, 0x6d, 0x63, 0x47, 0x32, 0x27, 0x1b, 0x14, + 0x14, 0x17, 0x1a, 0x1d, 0x1b, 0x2f, 0x4a, 0x51, 0x4e, 0x66, 0x73, 0x74, + 0x74, 0x77, 0x7d, 0x82, 0x86, 0x88, 0x89, 0x88, 0x80, 0x76, 0x70, 0x6a, + 0x65, 0x66, 0x68, 0x6a, 0x6d, 0x6f, 0x70, 0x72, 0x72, 0x73, 0x74, 0x75, + 0x77, 0x79, 0x79, 0x79, 0x7b, 0x7b, 0x7b, 0x7a, 0x79, 0x77, 0x75, 0x75, + 0x75, 0x72, 0x71, 0x71, 0x70, 0x6f, 0x70, 0x71, 0x71, 0x72, 0x72, 0x72, + 0x71, 0x6d, 0x6b, 0x69, 0x66, 0x60, 0x5b, 0x56, 0x53, 0x4f, 0x49, 0x45, + 0x41, 0x3e, 0x39, 0x32, 0x27, 0x21, 0x1d, 0x16, 0x12, 0x10, 0x11, 0x11, + 0x12, 0x10, 0x10, 0x11, 0x11, 0x13, 0x13, 0x13, 0x13, 0x13, 0x12, 0x12, + 0x5c, 0x5a, 0x5a, 0x5a, 0x59, 0x58, 0x58, 0x59, 0x58, 0x57, 0x59, 0x5a, + 0x5a, 0x59, 0x5b, 0x5d, 0x5f, 0x60, 0x60, 0x5f, 0x60, 0x64, 0x65, 0x66, + 0x68, 0x6a, 0x6c, 0x6c, 0x6d, 0x6f, 0x6f, 0x72, 0x74, 0x74, 0x73, 0x74, + 0x74, 0x75, 0x75, 0x74, 0x74, 0x74, 0x73, 0x73, 0x74, 0x73, 0x73, 0x76, + 0x77, 0x75, 0x75, 0x78, 0x79, 0x7a, 0x7d, 0x7f, 0x81, 0x82, 0x83, 0x84, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x88, 0x8c, 0x8f, 0x8e, 0x8c, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8c, 0x8b, 0x8c, 0x8c, 0x8c, 0x8e, 0x91, 0x92, + 0x92, 0x95, 0x96, 0x97, 0x97, 0x96, 0x95, 0x95, 0x97, 0x99, 0x9b, 0xa1, + 0xa8, 0xb3, 0xbb, 0xbe, 0xbf, 0xbd, 0xb9, 0xb9, 0xb8, 0xa2, 0x51, 0x30, + 0x2e, 0x2b, 0x24, 0x33, 0x4b, 0x45, 0x37, 0x29, 0x4d, 0x84, 0x5a, 0x39, + 0x27, 0x22, 0x29, 0x53, 0x79, 0xa9, 0xbb, 0xb0, 0xb5, 0xb4, 0x8f, 0x43, + 0x55, 0x8f, 0xc7, 0xdc, 0xda, 0xc7, 0xbb, 0xc7, 0xcd, 0xcd, 0xcb, 0xd3, + 0xde, 0xe2, 0xe1, 0xd8, 0xc8, 0xba, 0xb3, 0xad, 0xa7, 0x9a, 0x92, 0x91, + 0x91, 0x90, 0x8d, 0x8d, 0x8e, 0x8f, 0x92, 0x90, 0x8e, 0x8c, 0x8a, 0x8b, + 0x8c, 0x8e, 0x91, 0x95, 0x97, 0x8f, 0x8c, 0x8d, 0x8e, 0x91, 0x93, 0x92, + 0x91, 0x90, 0x92, 0x96, 0x95, 0x97, 0x9b, 0x9e, 0x9f, 0x9f, 0xa2, 0xa8, + 0xb1, 0xb4, 0xb4, 0xb3, 0xb0, 0xab, 0xa7, 0xa0, 0x8f, 0x82, 0x71, 0x62, + 0x64, 0x62, 0x63, 0x6c, 0x7f, 0x7c, 0x66, 0x57, 0x43, 0x2f, 0x57, 0x5f, + 0x63, 0x6d, 0x6a, 0x73, 0x6c, 0x5f, 0x48, 0x33, 0x29, 0x25, 0x26, 0x2c, + 0x42, 0x55, 0x49, 0x46, 0x54, 0x70, 0x73, 0x72, 0x74, 0x7a, 0x80, 0x85, + 0x88, 0x8a, 0x8a, 0x88, 0x81, 0x78, 0x72, 0x6b, 0x66, 0x66, 0x68, 0x6a, + 0x6d, 0x6f, 0x70, 0x72, 0x74, 0x75, 0x77, 0x77, 0x78, 0x7a, 0x7a, 0x7a, + 0x7c, 0x7c, 0x7c, 0x7b, 0x7a, 0x7a, 0x78, 0x76, 0x75, 0x74, 0x73, 0x72, + 0x70, 0x6f, 0x6f, 0x71, 0x71, 0x72, 0x73, 0x72, 0x71, 0x6d, 0x6a, 0x69, + 0x66, 0x60, 0x5c, 0x57, 0x54, 0x51, 0x4a, 0x45, 0x40, 0x3d, 0x39, 0x33, + 0x28, 0x20, 0x1b, 0x15, 0x11, 0x10, 0x11, 0x11, 0x12, 0x10, 0x10, 0x11, + 0x11, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x12, 0x5d, 0x5b, 0x5a, 0x59, + 0x5a, 0x5a, 0x5a, 0x59, 0x57, 0x56, 0x57, 0x59, 0x5a, 0x5a, 0x5c, 0x5d, + 0x5e, 0x5e, 0x5f, 0x60, 0x60, 0x63, 0x64, 0x65, 0x67, 0x69, 0x6b, 0x6d, + 0x6d, 0x6e, 0x71, 0x72, 0x73, 0x73, 0x73, 0x74, 0x74, 0x75, 0x75, 0x75, + 0x75, 0x74, 0x73, 0x73, 0x74, 0x74, 0x75, 0x77, 0x77, 0x75, 0x75, 0x77, + 0x79, 0x7a, 0x7b, 0x7e, 0x80, 0x80, 0x81, 0x83, 0x84, 0x85, 0x84, 0x84, + 0x83, 0x88, 0x8c, 0x8e, 0x8d, 0x8c, 0x8b, 0x8b, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8c, 0x8d, 0x8d, 0x8c, 0x8e, 0x91, 0x92, 0x93, 0x93, 0x95, 0x95, + 0x96, 0x96, 0x96, 0x96, 0x98, 0x9d, 0xa0, 0xa4, 0xad, 0xb6, 0xbc, 0xbd, + 0xbd, 0xba, 0xb6, 0xb5, 0xb4, 0xa2, 0x5a, 0x32, 0x2a, 0x27, 0x24, 0x31, + 0x38, 0x2d, 0x25, 0x1e, 0x27, 0x3f, 0x2f, 0x2a, 0x32, 0x2e, 0x21, 0x2d, + 0x52, 0x9a, 0xac, 0xa6, 0xbd, 0xbc, 0x95, 0x48, 0x5e, 0x95, 0xca, 0xde, + 0xdd, 0xc8, 0xbf, 0xce, 0xd4, 0xcf, 0xcb, 0xcf, 0xd9, 0xdf, 0xe2, 0xe0, + 0xd6, 0xc4, 0xbb, 0xb4, 0xab, 0x9e, 0x96, 0x92, 0x92, 0x91, 0x90, 0x8f, + 0x8f, 0x90, 0x93, 0x94, 0x92, 0x91, 0x8f, 0x8d, 0x8d, 0x90, 0x91, 0x8f, + 0x8f, 0x8f, 0x8d, 0x8d, 0x8f, 0x91, 0x95, 0x95, 0x95, 0x94, 0x94, 0x97, + 0x9a, 0x9b, 0x9b, 0x9a, 0x9d, 0xa3, 0xa7, 0xae, 0xb2, 0xb3, 0xb7, 0xb4, + 0xb0, 0xa8, 0xa3, 0x99, 0x84, 0x77, 0x6c, 0x64, 0x67, 0x64, 0x64, 0x68, + 0x79, 0x7a, 0x66, 0x58, 0x45, 0x2f, 0x57, 0x69, 0x6e, 0x70, 0x68, 0x7a, + 0x6e, 0x6c, 0x76, 0x75, 0x62, 0x55, 0x55, 0x64, 0x7d, 0x5d, 0x41, 0x42, + 0x5f, 0x77, 0x74, 0x73, 0x76, 0x7c, 0x83, 0x86, 0x8a, 0x8c, 0x8c, 0x89, + 0x83, 0x79, 0x73, 0x6c, 0x68, 0x68, 0x69, 0x6b, 0x6d, 0x6f, 0x6f, 0x72, + 0x75, 0x76, 0x77, 0x79, 0x79, 0x7b, 0x7b, 0x7b, 0x7d, 0x7d, 0x7c, 0x7d, + 0x7b, 0x7b, 0x79, 0x78, 0x77, 0x75, 0x74, 0x73, 0x71, 0x70, 0x70, 0x72, + 0x71, 0x72, 0x72, 0x72, 0x70, 0x6c, 0x6b, 0x69, 0x66, 0x61, 0x5c, 0x57, + 0x54, 0x51, 0x4a, 0x45, 0x3f, 0x3b, 0x38, 0x34, 0x2a, 0x22, 0x1c, 0x16, + 0x12, 0x10, 0x11, 0x11, 0x11, 0x10, 0x10, 0x11, 0x11, 0x12, 0x12, 0x13, + 0x14, 0x14, 0x13, 0x12, 0x5d, 0x5c, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x58, + 0x57, 0x56, 0x57, 0x59, 0x59, 0x5a, 0x5c, 0x5c, 0x5d, 0x5d, 0x5e, 0x60, + 0x61, 0x62, 0x64, 0x64, 0x66, 0x68, 0x6b, 0x6d, 0x6d, 0x6e, 0x70, 0x71, + 0x72, 0x72, 0x73, 0x74, 0x74, 0x75, 0x75, 0x75, 0x75, 0x74, 0x73, 0x73, + 0x74, 0x74, 0x75, 0x77, 0x77, 0x76, 0x76, 0x77, 0x78, 0x79, 0x79, 0x7d, + 0x7f, 0x7f, 0x80, 0x82, 0x83, 0x83, 0x83, 0x83, 0x83, 0x88, 0x8c, 0x8d, + 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x89, 0x89, 0x89, 0x8a, 0x8c, 0x8d, 0x8d, + 0x8c, 0x8e, 0x91, 0x93, 0x93, 0x93, 0x95, 0x95, 0x96, 0x96, 0x97, 0x98, + 0x9a, 0x9f, 0xa2, 0xa6, 0xaf, 0xb8, 0xbb, 0xbc, 0xbb, 0xb7, 0xb3, 0xb1, + 0xb0, 0xa1, 0x62, 0x34, 0x28, 0x25, 0x24, 0x2f, 0x32, 0x27, 0x21, 0x1e, + 0x1d, 0x26, 0x29, 0x2f, 0x38, 0x34, 0x20, 0x20, 0x3e, 0x81, 0xa1, 0x9c, + 0xb9, 0xb9, 0x92, 0x48, 0x62, 0x9c, 0xcc, 0xde, 0xdc, 0xc5, 0xbe, 0xcf, + 0xd5, 0xd0, 0xcb, 0xcc, 0xd3, 0xd8, 0xde, 0xe1, 0xdc, 0xcc, 0xc3, 0xba, + 0xae, 0xa3, 0x9a, 0x96, 0x93, 0x92, 0x92, 0x92, 0x90, 0x91, 0x92, 0x94, + 0x93, 0x93, 0x92, 0x90, 0x8f, 0x91, 0x91, 0x8d, 0x8d, 0x8f, 0x8d, 0x8c, + 0x90, 0x92, 0x95, 0x97, 0x97, 0x97, 0x96, 0x9a, 0x9d, 0x9e, 0x9d, 0x9a, + 0x9f, 0xa6, 0xaa, 0xb0, 0xb2, 0xb3, 0xb8, 0xb4, 0xaf, 0xa6, 0x9f, 0x92, + 0x7d, 0x71, 0x69, 0x63, 0x66, 0x64, 0x64, 0x68, 0x74, 0x77, 0x67, 0x5b, + 0x48, 0x2d, 0x51, 0x65, 0x6a, 0x6b, 0x68, 0x77, 0x67, 0x65, 0x77, 0x7f, + 0x78, 0x6e, 0x6d, 0x7b, 0x84, 0x52, 0x3e, 0x47, 0x67, 0x7c, 0x76, 0x75, + 0x78, 0x7e, 0x84, 0x88, 0x8a, 0x8c, 0x8c, 0x8a, 0x83, 0x7a, 0x74, 0x6d, + 0x69, 0x68, 0x6a, 0x6b, 0x6e, 0x70, 0x70, 0x72, 0x75, 0x76, 0x78, 0x7a, + 0x7a, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, 0x7d, 0x7c, 0x7c, 0x7a, 0x79, + 0x78, 0x76, 0x75, 0x74, 0x72, 0x71, 0x70, 0x72, 0x71, 0x71, 0x72, 0x72, + 0x6f, 0x6c, 0x6a, 0x69, 0x66, 0x61, 0x5b, 0x57, 0x54, 0x51, 0x4a, 0x45, + 0x3f, 0x3b, 0x38, 0x34, 0x2a, 0x23, 0x1e, 0x17, 0x12, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x10, 0x11, 0x11, 0x12, 0x12, 0x13, 0x14, 0x14, 0x13, 0x12, + 0x5c, 0x5b, 0x5b, 0x5a, 0x5a, 0x5a, 0x5a, 0x58, 0x57, 0x57, 0x57, 0x57, + 0x58, 0x59, 0x5b, 0x5c, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x62, + 0x65, 0x66, 0x68, 0x6b, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x71, 0x74, 0x75, + 0x74, 0x75, 0x75, 0x74, 0x74, 0x75, 0x74, 0x74, 0x74, 0x73, 0x74, 0x76, + 0x77, 0x76, 0x75, 0x76, 0x76, 0x77, 0x78, 0x7a, 0x7d, 0x7e, 0x7f, 0x80, + 0x81, 0x80, 0x80, 0x80, 0x82, 0x86, 0x8b, 0x8c, 0x8c, 0x8b, 0x89, 0x88, + 0x89, 0x89, 0x89, 0x88, 0x89, 0x8c, 0x8d, 0x8d, 0x8c, 0x8e, 0x91, 0x93, + 0x93, 0x93, 0x94, 0x94, 0x95, 0x96, 0x97, 0x99, 0x9b, 0xa0, 0xa3, 0xa8, + 0xb1, 0xb7, 0xb8, 0xb7, 0xb6, 0xb3, 0xae, 0xaa, 0xa8, 0x9f, 0x70, 0x37, + 0x27, 0x24, 0x23, 0x29, 0x2b, 0x25, 0x22, 0x20, 0x1e, 0x25, 0x36, 0x3d, + 0x3b, 0x34, 0x21, 0x1b, 0x26, 0x4f, 0x91, 0x91, 0xab, 0xac, 0x88, 0x41, + 0x59, 0xa4, 0xce, 0xdb, 0xd7, 0xbd, 0xb8, 0xc9, 0xd2, 0xd1, 0xc9, 0xc6, + 0xc9, 0xcd, 0xd7, 0xde, 0xde, 0xd7, 0xd0, 0xc3, 0xb4, 0xac, 0xa4, 0x9f, + 0x99, 0x95, 0x95, 0x95, 0x95, 0x92, 0x8f, 0x90, 0x92, 0x94, 0x96, 0x95, + 0x93, 0x93, 0x92, 0x8f, 0x8f, 0x8f, 0x8e, 0x8e, 0x91, 0x94, 0x95, 0x97, + 0x98, 0x99, 0x9a, 0x9e, 0x9f, 0xa0, 0x9f, 0xa1, 0xa4, 0xaa, 0xad, 0xb0, + 0xb3, 0xb5, 0xb7, 0xb5, 0xb0, 0xa5, 0x99, 0x86, 0x74, 0x6a, 0x63, 0x5f, + 0x61, 0x62, 0x64, 0x68, 0x6e, 0x71, 0x68, 0x60, 0x4d, 0x2a, 0x40, 0x5a, + 0x5f, 0x5e, 0x6e, 0x70, 0x60, 0x57, 0x55, 0x5d, 0x6c, 0x72, 0x72, 0x70, + 0x60, 0x39, 0x42, 0x55, 0x71, 0x80, 0x7b, 0x7a, 0x7d, 0x82, 0x86, 0x88, + 0x8a, 0x8b, 0x8c, 0x89, 0x83, 0x7b, 0x75, 0x6d, 0x6a, 0x69, 0x6b, 0x6c, + 0x6e, 0x70, 0x72, 0x74, 0x76, 0x77, 0x78, 0x7b, 0x7b, 0x7d, 0x7d, 0x7e, + 0x7e, 0x7d, 0x7e, 0x7d, 0x7c, 0x7c, 0x7a, 0x79, 0x78, 0x76, 0x75, 0x74, + 0x73, 0x72, 0x71, 0x71, 0x70, 0x70, 0x71, 0x71, 0x6f, 0x6b, 0x6a, 0x68, + 0x64, 0x61, 0x5c, 0x57, 0x55, 0x51, 0x4a, 0x45, 0x3f, 0x3d, 0x39, 0x33, + 0x29, 0x23, 0x1e, 0x17, 0x12, 0x11, 0x10, 0x10, 0x10, 0x11, 0x10, 0x11, + 0x11, 0x12, 0x13, 0x14, 0x14, 0x14, 0x14, 0x12, 0x5c, 0x5b, 0x5b, 0x5a, + 0x5a, 0x5a, 0x5a, 0x59, 0x58, 0x57, 0x58, 0x57, 0x58, 0x59, 0x5a, 0x5a, + 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x5f, 0x61, 0x61, 0x63, 0x65, 0x67, 0x6a, + 0x6b, 0x6c, 0x6e, 0x70, 0x71, 0x71, 0x74, 0x75, 0x73, 0x74, 0x74, 0x74, + 0x74, 0x74, 0x74, 0x74, 0x73, 0x71, 0x71, 0x74, 0x75, 0x76, 0x75, 0x75, + 0x75, 0x74, 0x75, 0x77, 0x7a, 0x7a, 0x7b, 0x7d, 0x7e, 0x7d, 0x7d, 0x7e, + 0x80, 0x86, 0x8a, 0x8a, 0x8b, 0x8a, 0x88, 0x87, 0x88, 0x88, 0x88, 0x87, + 0x88, 0x8b, 0x8c, 0x8c, 0x8c, 0x8d, 0x90, 0x92, 0x92, 0x92, 0x93, 0x93, + 0x95, 0x96, 0x99, 0x9a, 0x9e, 0xa1, 0xa3, 0xa8, 0xb0, 0xb2, 0xb0, 0xaf, + 0xad, 0xa9, 0xa5, 0x9f, 0x9d, 0x9b, 0x81, 0x3a, 0x26, 0x24, 0x25, 0x22, + 0x23, 0x23, 0x21, 0x20, 0x20, 0x22, 0x29, 0x2c, 0x2d, 0x31, 0x25, 0x1c, + 0x1c, 0x2d, 0x6f, 0x94, 0xb3, 0xb4, 0x8f, 0x45, 0x57, 0xab, 0xd1, 0xd9, + 0xcc, 0xb2, 0xb9, 0xcb, 0xd1, 0xd1, 0xc6, 0xbd, 0xc0, 0xc5, 0xce, 0xd7, + 0xdc, 0xdb, 0xd7, 0xce, 0xc0, 0xb6, 0xb0, 0xac, 0xa6, 0x9d, 0x9c, 0x9c, + 0x9b, 0x96, 0x91, 0x8f, 0x92, 0x94, 0x94, 0x94, 0x95, 0x96, 0x96, 0x92, + 0x94, 0x93, 0x93, 0x94, 0x96, 0x99, 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9c, + 0xa0, 0xa1, 0xa4, 0xa8, 0xac, 0xb3, 0xb5, 0xb6, 0xb6, 0xb4, 0xb1, 0xb1, + 0xae, 0xa4, 0x91, 0x78, 0x68, 0x61, 0x5d, 0x5c, 0x5e, 0x62, 0x66, 0x6b, + 0x69, 0x6c, 0x68, 0x5f, 0x49, 0x26, 0x34, 0x5d, 0x6c, 0x6d, 0x77, 0x69, + 0x60, 0x5a, 0x58, 0x66, 0x53, 0x5c, 0x5c, 0x50, 0x59, 0x45, 0x53, 0x67, + 0x83, 0x8b, 0x86, 0x84, 0x84, 0x85, 0x88, 0x89, 0x8b, 0x8b, 0x8b, 0x87, + 0x81, 0x7b, 0x75, 0x6d, 0x6a, 0x69, 0x6a, 0x6c, 0x6f, 0x71, 0x73, 0x75, + 0x77, 0x78, 0x79, 0x7b, 0x7d, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7e, 0x7e, + 0x7d, 0x7d, 0x7b, 0x7a, 0x7a, 0x78, 0x76, 0x75, 0x74, 0x73, 0x71, 0x71, + 0x70, 0x70, 0x70, 0x71, 0x6f, 0x6b, 0x6a, 0x68, 0x64, 0x61, 0x5a, 0x57, + 0x54, 0x50, 0x4a, 0x45, 0x40, 0x3d, 0x39, 0x32, 0x2a, 0x22, 0x1d, 0x16, + 0x12, 0x11, 0x10, 0x10, 0x10, 0x11, 0x10, 0x11, 0x11, 0x12, 0x13, 0x14, + 0x14, 0x14, 0x14, 0x12, 0x5d, 0x5c, 0x5b, 0x5b, 0x5b, 0x5a, 0x58, 0x58, + 0x58, 0x58, 0x59, 0x58, 0x59, 0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5c, 0x5c, + 0x5d, 0x5e, 0x60, 0x62, 0x63, 0x65, 0x66, 0x69, 0x6b, 0x6c, 0x6d, 0x6f, + 0x71, 0x71, 0x72, 0x74, 0x73, 0x73, 0x74, 0x75, 0x74, 0x74, 0x74, 0x74, + 0x73, 0x71, 0x71, 0x74, 0x75, 0x75, 0x74, 0x74, 0x74, 0x74, 0x74, 0x75, + 0x77, 0x79, 0x7a, 0x7a, 0x7c, 0x7c, 0x7c, 0x7d, 0x80, 0x87, 0x89, 0x89, + 0x8a, 0x8a, 0x88, 0x88, 0x88, 0x88, 0x89, 0x89, 0x8c, 0x8e, 0x8f, 0x8f, + 0x8f, 0x8f, 0x90, 0x91, 0x91, 0x91, 0x92, 0x93, 0x96, 0x98, 0x9a, 0x9c, + 0x9e, 0xa0, 0xa2, 0xa7, 0xac, 0xaa, 0xa8, 0xa6, 0xa4, 0x9f, 0x97, 0x91, + 0x90, 0x99, 0x9a, 0x4e, 0x28, 0x23, 0x29, 0x22, 0x21, 0x21, 0x21, 0x20, + 0x21, 0x20, 0x20, 0x21, 0x24, 0x2b, 0x23, 0x1e, 0x1d, 0x22, 0x4c, 0x86, + 0xa6, 0xae, 0x92, 0x4e, 0x59, 0xa4, 0xc4, 0xc7, 0xb8, 0xa8, 0xbc, 0xcc, + 0xd0, 0xcb, 0xbe, 0xb2, 0xbb, 0xc1, 0xc5, 0xcf, 0xd8, 0xdc, 0xdd, 0xdb, + 0xd3, 0xc6, 0xbd, 0xb8, 0xb1, 0xa8, 0xa7, 0xa6, 0xa4, 0xa1, 0x9f, 0x98, + 0x94, 0x93, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x95, 0x97, 0x97, 0x98, + 0x97, 0x99, 0x99, 0x9c, 0x9d, 0x9c, 0x9c, 0x9e, 0xa1, 0xa3, 0xa7, 0xae, + 0xb2, 0xb4, 0xb5, 0xb6, 0xb8, 0xb6, 0xaf, 0xac, 0xa8, 0x9d, 0x85, 0x6f, + 0x62, 0x5e, 0x5b, 0x5a, 0x59, 0x60, 0x66, 0x6d, 0x67, 0x66, 0x6a, 0x64, + 0x4d, 0x2e, 0x2e, 0x52, 0x62, 0x60, 0x5c, 0x61, 0x7f, 0x7c, 0x5d, 0x61, + 0x5e, 0x61, 0x5b, 0x4c, 0x4e, 0x5b, 0x6c, 0x7c, 0x92, 0x96, 0x91, 0x8e, + 0x8b, 0x89, 0x8b, 0x8b, 0x8b, 0x8a, 0x8a, 0x86, 0x80, 0x7a, 0x74, 0x6c, + 0x68, 0x6a, 0x6b, 0x6c, 0x6e, 0x71, 0x75, 0x77, 0x79, 0x79, 0x79, 0x7b, + 0x7e, 0x81, 0x81, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x7d, 0x7c, 0x7c, + 0x7b, 0x7a, 0x77, 0x76, 0x74, 0x73, 0x72, 0x71, 0x72, 0x71, 0x71, 0x71, + 0x70, 0x6b, 0x69, 0x67, 0x64, 0x60, 0x5b, 0x58, 0x55, 0x51, 0x4c, 0x46, + 0x40, 0x3d, 0x38, 0x31, 0x29, 0x22, 0x1d, 0x16, 0x13, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x12, 0x13, 0x13, 0x14, 0x14, 0x14, 0x13, 0x12, + 0x5d, 0x5c, 0x5b, 0x5b, 0x5b, 0x5a, 0x58, 0x57, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x58, 0x58, 0x59, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5e, 0x60, 0x61, + 0x62, 0x63, 0x65, 0x68, 0x6a, 0x6b, 0x6d, 0x6e, 0x70, 0x71, 0x72, 0x73, + 0x74, 0x74, 0x75, 0x75, 0x74, 0x74, 0x74, 0x74, 0x74, 0x72, 0x72, 0x74, + 0x75, 0x75, 0x74, 0x74, 0x74, 0x73, 0x73, 0x73, 0x75, 0x76, 0x77, 0x77, + 0x79, 0x7a, 0x7b, 0x7c, 0x80, 0x87, 0x88, 0x88, 0x89, 0x89, 0x88, 0x88, + 0x89, 0x8b, 0x8c, 0x8f, 0x93, 0x96, 0x97, 0x97, 0x97, 0x95, 0x93, 0x92, + 0x91, 0x91, 0x92, 0x93, 0x96, 0x98, 0x99, 0x9c, 0x9f, 0xa1, 0xa2, 0xa7, + 0xa8, 0xa5, 0xa2, 0x9f, 0x9b, 0x95, 0x8f, 0x8a, 0x8a, 0x94, 0x9e, 0x6b, + 0x32, 0x22, 0x29, 0x25, 0x21, 0x20, 0x1f, 0x1f, 0x21, 0x20, 0x1f, 0x20, + 0x21, 0x26, 0x1f, 0x1d, 0x1b, 0x1f, 0x49, 0x7b, 0x98, 0xa1, 0x86, 0x46, + 0x54, 0xa1, 0xbd, 0xbe, 0xb2, 0xa7, 0xbe, 0xcb, 0xcc, 0xc7, 0xb9, 0xa8, + 0xb6, 0xbd, 0xbd, 0xc9, 0xd5, 0xdc, 0xde, 0xdd, 0xdc, 0xd7, 0xce, 0xc6, + 0xbb, 0xae, 0xaa, 0xa9, 0xa8, 0xa6, 0xa7, 0xa1, 0x9c, 0x98, 0x95, 0x94, + 0x91, 0x91, 0x93, 0x95, 0x96, 0x99, 0x9a, 0x98, 0x96, 0x98, 0x98, 0x9a, + 0x9b, 0x9c, 0x9f, 0xa0, 0xa1, 0xa3, 0xa6, 0xab, 0xb1, 0xb3, 0xb4, 0xb7, + 0xba, 0xb7, 0xad, 0xa5, 0xa0, 0x95, 0x7e, 0x6a, 0x5f, 0x5b, 0x58, 0x57, + 0x56, 0x5c, 0x61, 0x69, 0x68, 0x62, 0x68, 0x66, 0x53, 0x2f, 0x27, 0x4b, + 0x5d, 0x65, 0x68, 0x5e, 0x82, 0x86, 0x65, 0x4a, 0x5a, 0x67, 0x67, 0x58, + 0x44, 0x5e, 0x7a, 0x8a, 0x98, 0x99, 0x97, 0x93, 0x90, 0x8d, 0x8d, 0x8c, + 0x8a, 0x89, 0x88, 0x84, 0x7e, 0x78, 0x73, 0x6b, 0x66, 0x6a, 0x6c, 0x6d, + 0x6f, 0x72, 0x76, 0x78, 0x7a, 0x7b, 0x7a, 0x7d, 0x80, 0x82, 0x82, 0x81, + 0x82, 0x81, 0x80, 0x80, 0x80, 0x7f, 0x7d, 0x7d, 0x7d, 0x7b, 0x79, 0x76, + 0x75, 0x74, 0x73, 0x71, 0x71, 0x72, 0x71, 0x71, 0x6f, 0x6b, 0x69, 0x67, + 0x63, 0x60, 0x5c, 0x59, 0x56, 0x50, 0x4c, 0x46, 0x40, 0x3d, 0x38, 0x30, + 0x2a, 0x22, 0x1d, 0x17, 0x13, 0x11, 0x10, 0x11, 0x11, 0x11, 0x11, 0x12, + 0x12, 0x13, 0x12, 0x13, 0x14, 0x14, 0x13, 0x12, 0x5d, 0x5c, 0x5b, 0x5b, + 0x5b, 0x5a, 0x58, 0x58, 0x58, 0x59, 0x58, 0x58, 0x57, 0x57, 0x57, 0x58, + 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, 0x5d, 0x5f, 0x60, 0x61, 0x62, 0x65, 0x68, + 0x69, 0x6b, 0x6c, 0x6d, 0x6f, 0x70, 0x71, 0x73, 0x74, 0x74, 0x75, 0x75, + 0x74, 0x74, 0x74, 0x74, 0x74, 0x72, 0x71, 0x73, 0x75, 0x75, 0x74, 0x73, + 0x73, 0x73, 0x72, 0x73, 0x74, 0x75, 0x76, 0x76, 0x78, 0x79, 0x7a, 0x7c, + 0x80, 0x87, 0x88, 0x88, 0x88, 0x89, 0x88, 0x8a, 0x8d, 0x90, 0x92, 0x94, + 0x99, 0x9c, 0x9c, 0x9c, 0x9c, 0x9a, 0x97, 0x94, 0x93, 0x91, 0x92, 0x93, + 0x96, 0x97, 0x99, 0x9c, 0x9f, 0xa2, 0xa3, 0xa6, 0xa5, 0xa1, 0x9d, 0x9a, + 0x95, 0x90, 0x8c, 0x88, 0x89, 0x90, 0x9b, 0x7e, 0x3d, 0x25, 0x27, 0x25, + 0x20, 0x20, 0x20, 0x1f, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x1d, 0x1b, + 0x1b, 0x25, 0x55, 0x78, 0x94, 0x9c, 0x80, 0x40, 0x53, 0xa1, 0xba, 0xb9, + 0xad, 0xa7, 0xc1, 0xcb, 0xcb, 0xc5, 0xb7, 0xa7, 0xb6, 0xbd, 0xbc, 0xc7, + 0xd2, 0xd9, 0xdc, 0xdb, 0xdd, 0xdd, 0xd7, 0xd0, 0xc2, 0xb3, 0xac, 0xaa, + 0xa9, 0xa7, 0xa8, 0xa4, 0xa0, 0x9d, 0x98, 0x95, 0x93, 0x92, 0x93, 0x97, + 0x96, 0x98, 0x99, 0x98, 0x95, 0x97, 0x99, 0x9a, 0x9b, 0x9d, 0xa1, 0xa2, + 0xa3, 0xa4, 0xa6, 0xab, 0xb1, 0xb3, 0xb4, 0xb8, 0xba, 0xb6, 0xab, 0xa1, + 0x9a, 0x8e, 0x78, 0x68, 0x5e, 0x59, 0x56, 0x55, 0x54, 0x59, 0x5e, 0x64, + 0x68, 0x62, 0x67, 0x67, 0x57, 0x2f, 0x23, 0x43, 0x56, 0x67, 0x70, 0x5f, + 0x7a, 0x83, 0x6e, 0x4d, 0x56, 0x67, 0x6a, 0x5d, 0x48, 0x62, 0x80, 0x8f, + 0x99, 0x9a, 0x9a, 0x97, 0x93, 0x8f, 0x8d, 0x8b, 0x8a, 0x89, 0x87, 0x83, + 0x7d, 0x77, 0x72, 0x6a, 0x66, 0x69, 0x6c, 0x6d, 0x6f, 0x73, 0x76, 0x79, + 0x7b, 0x7b, 0x7b, 0x7d, 0x80, 0x82, 0x82, 0x82, 0x82, 0x81, 0x81, 0x81, + 0x81, 0x80, 0x7e, 0x7e, 0x7d, 0x7c, 0x79, 0x77, 0x75, 0x75, 0x73, 0x71, + 0x70, 0x71, 0x71, 0x71, 0x6f, 0x6b, 0x69, 0x67, 0x63, 0x60, 0x5c, 0x59, + 0x56, 0x50, 0x4c, 0x46, 0x41, 0x3d, 0x37, 0x30, 0x2a, 0x22, 0x1d, 0x18, + 0x13, 0x11, 0x10, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x13, 0x11, 0x12, + 0x14, 0x14, 0x12, 0x12, 0x5d, 0x5c, 0x5b, 0x5b, 0x5b, 0x5b, 0x59, 0x59, + 0x58, 0x59, 0x59, 0x58, 0x57, 0x57, 0x57, 0x57, 0x58, 0x59, 0x59, 0x5a, + 0x5c, 0x5d, 0x5e, 0x5f, 0x61, 0x61, 0x63, 0x66, 0x68, 0x69, 0x6b, 0x6d, + 0x6f, 0x6f, 0x70, 0x73, 0x73, 0x73, 0x73, 0x74, 0x74, 0x74, 0x74, 0x75, + 0x74, 0x71, 0x70, 0x72, 0x73, 0x74, 0x74, 0x72, 0x72, 0x72, 0x72, 0x73, + 0x73, 0x74, 0x75, 0x76, 0x76, 0x77, 0x79, 0x7a, 0x80, 0x86, 0x87, 0x87, + 0x88, 0x88, 0x8a, 0x8e, 0x93, 0x98, 0x9b, 0x9f, 0xa1, 0xa3, 0xa4, 0xa3, + 0xa4, 0xa4, 0xa1, 0x9d, 0x98, 0x94, 0x92, 0x93, 0x96, 0x97, 0x98, 0x9b, + 0xa0, 0xa3, 0xa4, 0xa4, 0xa0, 0x9b, 0x96, 0x93, 0x8f, 0x8c, 0x8c, 0x8b, + 0x8c, 0x91, 0x99, 0x8f, 0x5c, 0x3d, 0x29, 0x21, 0x20, 0x24, 0x23, 0x1f, + 0x1e, 0x1e, 0x1e, 0x1f, 0x1e, 0x1c, 0x1a, 0x1a, 0x23, 0x43, 0x75, 0x7e, + 0x94, 0x9b, 0x7d, 0x3d, 0x58, 0xa4, 0xb5, 0xb0, 0xa3, 0xaa, 0xc6, 0xce, + 0xcc, 0xc4, 0xb6, 0xaf, 0xbb, 0xc0, 0xc0, 0xc7, 0xcd, 0xd3, 0xd5, 0xd5, + 0xda, 0xdd, 0xdc, 0xd8, 0xcd, 0xbf, 0xb4, 0xaf, 0xab, 0xa6, 0xa3, 0xa3, + 0xa3, 0xa1, 0x9c, 0x99, 0x95, 0x96, 0x97, 0x9a, 0x98, 0x99, 0x99, 0x98, + 0x97, 0x98, 0x9c, 0x9d, 0x9d, 0x9d, 0xa2, 0xa6, 0xa9, 0xaa, 0xab, 0xae, + 0xb3, 0xb5, 0xb6, 0xba, 0xba, 0xb5, 0xa9, 0x9b, 0x91, 0x81, 0x6f, 0x63, + 0x5a, 0x57, 0x54, 0x53, 0x53, 0x58, 0x5b, 0x5e, 0x67, 0x63, 0x66, 0x67, + 0x5c, 0x35, 0x20, 0x33, 0x46, 0x5e, 0x6d, 0x63, 0x67, 0x70, 0x79, 0x6a, + 0x54, 0x5e, 0x61, 0x59, 0x55, 0x6f, 0x86, 0x90, 0x98, 0x9b, 0x9d, 0x9a, + 0x97, 0x90, 0x8c, 0x8a, 0x89, 0x88, 0x86, 0x81, 0x7b, 0x75, 0x71, 0x6a, + 0x66, 0x6a, 0x6c, 0x6e, 0x70, 0x74, 0x78, 0x7a, 0x7b, 0x7c, 0x7c, 0x7e, + 0x81, 0x83, 0x83, 0x83, 0x83, 0x82, 0x82, 0x82, 0x83, 0x82, 0x80, 0x7f, + 0x7e, 0x7d, 0x7a, 0x78, 0x76, 0x75, 0x72, 0x71, 0x70, 0x70, 0x70, 0x71, + 0x6f, 0x6b, 0x69, 0x67, 0x63, 0x60, 0x5c, 0x59, 0x56, 0x50, 0x4b, 0x44, + 0x41, 0x3e, 0x38, 0x30, 0x29, 0x22, 0x1d, 0x18, 0x12, 0x10, 0x11, 0x11, + 0x11, 0x10, 0x11, 0x12, 0x12, 0x13, 0x12, 0x14, 0x14, 0x14, 0x12, 0x13, + 0x5d, 0x5c, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5a, 0x5a, 0x5a, 0x59, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x58, 0x58, 0x58, 0x5a, 0x5c, 0x5d, 0x5f, 0x5f, + 0x60, 0x62, 0x62, 0x63, 0x64, 0x66, 0x69, 0x6c, 0x6d, 0x6e, 0x6f, 0x71, + 0x71, 0x71, 0x72, 0x73, 0x74, 0x73, 0x74, 0x75, 0x74, 0x72, 0x70, 0x72, + 0x72, 0x72, 0x72, 0x72, 0x71, 0x71, 0x71, 0x72, 0x72, 0x73, 0x74, 0x74, + 0x74, 0x77, 0x78, 0x7b, 0x81, 0x85, 0x87, 0x89, 0x8b, 0x8d, 0x90, 0x96, + 0x9e, 0xa6, 0xa9, 0xad, 0xaf, 0xb0, 0xaf, 0xae, 0xae, 0xb0, 0xaf, 0xac, + 0xa8, 0x9f, 0x98, 0x97, 0x98, 0x98, 0x98, 0x9b, 0xa2, 0xa5, 0xa6, 0xa3, + 0x9e, 0x98, 0x93, 0x91, 0x90, 0x90, 0x93, 0x95, 0x97, 0x9b, 0x9e, 0x86, + 0x91, 0x84, 0x4d, 0x25, 0x21, 0x28, 0x28, 0x1f, 0x1c, 0x1d, 0x1d, 0x1c, + 0x1c, 0x1d, 0x2c, 0x3f, 0x57, 0x84, 0x99, 0x94, 0x8d, 0x97, 0x7e, 0x3f, + 0x5e, 0xa5, 0xad, 0xa7, 0xa4, 0xba, 0xcb, 0xcd, 0xca, 0xc1, 0xba, 0xbb, + 0xc1, 0xc2, 0xc1, 0xc3, 0xc9, 0xcb, 0xcd, 0xd0, 0xd6, 0xd9, 0xd9, 0xd8, + 0xd6, 0xd1, 0xc7, 0xc2, 0xbd, 0xb3, 0xa9, 0xa4, 0xa4, 0xa4, 0xa3, 0xa1, + 0x9b, 0x9a, 0x9b, 0x9c, 0x9c, 0x9e, 0x9b, 0x9b, 0x9b, 0x9b, 0xa0, 0xa2, + 0xa1, 0xa0, 0xa3, 0xa8, 0xad, 0xae, 0xae, 0xb1, 0xb5, 0xb9, 0xba, 0xbb, + 0xb9, 0xb4, 0xa6, 0x96, 0x89, 0x76, 0x67, 0x5b, 0x58, 0x56, 0x55, 0x51, + 0x52, 0x57, 0x59, 0x5c, 0x66, 0x64, 0x65, 0x66, 0x60, 0x40, 0x20, 0x28, + 0x38, 0x52, 0x5b, 0x5c, 0x4b, 0x4f, 0x6b, 0x6d, 0x59, 0x4e, 0x4b, 0x4d, + 0x56, 0x76, 0x89, 0x92, 0x9c, 0xa0, 0x9f, 0x9a, 0x96, 0x8f, 0x8b, 0x8a, + 0x89, 0x88, 0x85, 0x7f, 0x77, 0x72, 0x6e, 0x69, 0x65, 0x69, 0x6d, 0x6e, + 0x71, 0x75, 0x79, 0x7b, 0x7d, 0x7f, 0x80, 0x80, 0x83, 0x84, 0x84, 0x85, + 0x84, 0x84, 0x83, 0x83, 0x83, 0x83, 0x81, 0x81, 0x80, 0x7e, 0x7d, 0x7a, + 0x77, 0x76, 0x74, 0x72, 0x70, 0x70, 0x70, 0x71, 0x6f, 0x6b, 0x69, 0x67, + 0x63, 0x60, 0x5b, 0x57, 0x55, 0x50, 0x4b, 0x44, 0x40, 0x3d, 0x38, 0x31, + 0x29, 0x23, 0x1e, 0x17, 0x12, 0x11, 0x11, 0x11, 0x10, 0x12, 0x12, 0x11, + 0x11, 0x13, 0x13, 0x14, 0x13, 0x13, 0x13, 0x13, 0x5e, 0x5d, 0x5b, 0x5a, + 0x5b, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x57, 0x58, + 0x59, 0x58, 0x58, 0x58, 0x5a, 0x5c, 0x5d, 0x5e, 0x5e, 0x60, 0x61, 0x62, + 0x62, 0x65, 0x68, 0x6b, 0x6c, 0x6d, 0x6f, 0x71, 0x71, 0x71, 0x72, 0x73, + 0x73, 0x73, 0x73, 0x73, 0x73, 0x72, 0x70, 0x71, 0x71, 0x71, 0x72, 0x72, + 0x71, 0x70, 0x71, 0x70, 0x71, 0x72, 0x73, 0x73, 0x74, 0x77, 0x79, 0x7b, + 0x81, 0x86, 0x89, 0x8d, 0x90, 0x93, 0x98, 0xa1, 0xaa, 0xb1, 0xb5, 0xb8, + 0xba, 0xb9, 0xb8, 0xb7, 0xb7, 0xb9, 0xb9, 0xb8, 0xb6, 0xaf, 0xa4, 0x9d, + 0x9d, 0x9d, 0x9d, 0xa0, 0xa5, 0xa7, 0xa7, 0xa3, 0x9e, 0x9b, 0x98, 0x97, + 0x97, 0x99, 0x9e, 0xa0, 0xa1, 0xa4, 0xa8, 0x92, 0x92, 0x96, 0x90, 0x52, + 0x2f, 0x25, 0x22, 0x20, 0x1d, 0x1d, 0x1f, 0x23, 0x2d, 0x49, 0x7c, 0x97, + 0x9a, 0x90, 0x98, 0x98, 0x91, 0x99, 0x7e, 0x3e, 0x5d, 0xa8, 0xb2, 0xb0, + 0xb4, 0xc6, 0xca, 0xc9, 0xc7, 0xc1, 0xbd, 0xbe, 0xbf, 0xbf, 0xbd, 0xbf, + 0xc3, 0xc6, 0xc8, 0xcb, 0xcf, 0xd2, 0xd3, 0xd4, 0xd7, 0xd9, 0xd6, 0xd3, + 0xcf, 0xc6, 0xb8, 0xaa, 0xa6, 0xa7, 0xa8, 0xa7, 0xa5, 0xa1, 0xa0, 0x9e, + 0x9e, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0xa3, 0xa6, 0xa8, 0xa8, 0xa9, 0xac, + 0xaf, 0xb1, 0xb3, 0xb7, 0xba, 0xbd, 0xbf, 0xbf, 0xba, 0xaf, 0x9c, 0x8b, + 0x7e, 0x6d, 0x5d, 0x57, 0x57, 0x57, 0x55, 0x50, 0x53, 0x57, 0x5a, 0x5f, + 0x67, 0x6c, 0x6d, 0x6c, 0x67, 0x4d, 0x23, 0x1b, 0x28, 0x49, 0x5c, 0x61, + 0x58, 0x50, 0x4a, 0x5c, 0x5b, 0x47, 0x45, 0x56, 0x69, 0x7e, 0x8e, 0x97, + 0xa3, 0xa6, 0x9f, 0x98, 0x92, 0x8e, 0x8a, 0x8a, 0x8a, 0x89, 0x85, 0x7d, + 0x75, 0x6f, 0x6c, 0x68, 0x64, 0x68, 0x6c, 0x6e, 0x71, 0x77, 0x7b, 0x7d, + 0x7f, 0x80, 0x81, 0x83, 0x84, 0x86, 0x87, 0x87, 0x86, 0x87, 0x86, 0x86, + 0x86, 0x85, 0x82, 0x82, 0x82, 0x80, 0x80, 0x7d, 0x79, 0x77, 0x75, 0x72, + 0x70, 0x70, 0x70, 0x70, 0x6f, 0x6b, 0x69, 0x67, 0x64, 0x60, 0x5b, 0x57, + 0x55, 0x50, 0x4b, 0x44, 0x40, 0x3d, 0x37, 0x31, 0x29, 0x23, 0x1f, 0x18, + 0x12, 0x10, 0x11, 0x11, 0x10, 0x12, 0x12, 0x11, 0x11, 0x12, 0x12, 0x14, + 0x15, 0x14, 0x13, 0x12, 0x5d, 0x5c, 0x5b, 0x5a, 0x5b, 0x5b, 0x5a, 0x5b, + 0x5b, 0x59, 0x58, 0x57, 0x57, 0x57, 0x57, 0x59, 0x59, 0x58, 0x58, 0x58, + 0x59, 0x5a, 0x5c, 0x5c, 0x5d, 0x60, 0x61, 0x61, 0x62, 0x64, 0x67, 0x6a, + 0x6b, 0x6c, 0x6e, 0x70, 0x71, 0x72, 0x72, 0x73, 0x72, 0x72, 0x72, 0x72, + 0x71, 0x71, 0x70, 0x70, 0x70, 0x70, 0x71, 0x72, 0x71, 0x71, 0x71, 0x70, + 0x71, 0x71, 0x72, 0x72, 0x73, 0x75, 0x78, 0x7b, 0x80, 0x85, 0x8a, 0x91, + 0x95, 0x99, 0x9f, 0xa9, 0xb4, 0xba, 0xbc, 0xbe, 0xbf, 0xbf, 0xbe, 0xbd, + 0xbc, 0xbc, 0xbd, 0xbd, 0xbc, 0xb9, 0xaf, 0xa3, 0xa0, 0xa0, 0xa3, 0xa7, + 0xaa, 0xa9, 0xa7, 0xa4, 0xa1, 0x9e, 0x9d, 0x9d, 0x9e, 0xa2, 0xa6, 0xa6, + 0xa6, 0xa7, 0xae, 0x9f, 0x7c, 0x7c, 0x9c, 0x93, 0x61, 0x39, 0x2a, 0x26, + 0x23, 0x28, 0x34, 0x46, 0x6b, 0x99, 0xab, 0x9e, 0x95, 0x94, 0xa3, 0xa1, + 0xa9, 0x99, 0x76, 0x3e, 0x68, 0xae, 0xba, 0xbd, 0xc4, 0xca, 0xca, 0xca, + 0xc8, 0xc3, 0xbf, 0xbd, 0xbc, 0xbc, 0xbc, 0xbc, 0xbe, 0xc3, 0xc7, 0xca, + 0xcb, 0xce, 0xd0, 0xd2, 0xd5, 0xd9, 0xd9, 0xd9, 0xd7, 0xd2, 0xc4, 0xb4, + 0xad, 0xab, 0xab, 0xa9, 0xa9, 0xa6, 0xa3, 0x9f, 0x9f, 0xa0, 0xa1, 0xa2, + 0xa4, 0xa4, 0xa4, 0xa8, 0xab, 0xaf, 0xb0, 0xb1, 0xb4, 0xb6, 0xb8, 0xbd, + 0xbe, 0xbe, 0xc0, 0xc3, 0xbc, 0xae, 0x97, 0x81, 0x74, 0x64, 0x52, 0x54, + 0x56, 0x55, 0x53, 0x4f, 0x53, 0x57, 0x5b, 0x61, 0x6f, 0x79, 0x75, 0x71, + 0x6d, 0x59, 0x2e, 0x1a, 0x20, 0x3e, 0x59, 0x5f, 0x62, 0x56, 0x3b, 0x45, + 0x57, 0x4f, 0x50, 0x61, 0x73, 0x84, 0x94, 0x9d, 0xa5, 0xa6, 0x9e, 0x95, + 0x90, 0x8c, 0x8a, 0x89, 0x88, 0x88, 0x84, 0x7c, 0x73, 0x6d, 0x6a, 0x66, + 0x62, 0x67, 0x6c, 0x6f, 0x72, 0x77, 0x7c, 0x7e, 0x81, 0x82, 0x82, 0x84, + 0x84, 0x86, 0x86, 0x87, 0x87, 0x89, 0x88, 0x88, 0x87, 0x85, 0x83, 0x83, + 0x82, 0x82, 0x81, 0x7e, 0x7b, 0x79, 0x77, 0x73, 0x71, 0x71, 0x71, 0x70, + 0x6d, 0x6b, 0x6a, 0x68, 0x65, 0x60, 0x5b, 0x57, 0x55, 0x51, 0x4b, 0x44, + 0x40, 0x3d, 0x37, 0x30, 0x29, 0x23, 0x1f, 0x18, 0x12, 0x11, 0x11, 0x11, + 0x10, 0x11, 0x12, 0x12, 0x12, 0x12, 0x12, 0x14, 0x15, 0x15, 0x13, 0x12, + 0x5e, 0x5c, 0x5b, 0x5a, 0x5b, 0x5b, 0x5a, 0x5b, 0x5a, 0x59, 0x58, 0x57, + 0x57, 0x57, 0x57, 0x59, 0x58, 0x58, 0x58, 0x58, 0x5a, 0x5a, 0x5b, 0x5b, + 0x5d, 0x5f, 0x60, 0x61, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6d, 0x70, + 0x71, 0x72, 0x72, 0x73, 0x71, 0x71, 0x72, 0x72, 0x70, 0x70, 0x70, 0x6f, + 0x6f, 0x6f, 0x70, 0x71, 0x71, 0x71, 0x71, 0x70, 0x70, 0x71, 0x71, 0x72, + 0x72, 0x74, 0x78, 0x7a, 0x7f, 0x86, 0x8c, 0x93, 0x98, 0x9c, 0xa3, 0xae, + 0xb9, 0xbe, 0xc0, 0xc2, 0xc3, 0xc2, 0xc1, 0xc0, 0xbf, 0xbf, 0xbf, 0xbf, + 0xbf, 0xbd, 0xb5, 0xa9, 0xa4, 0xa3, 0xa6, 0xab, 0xad, 0xaa, 0xa8, 0xa5, + 0xa3, 0xa2, 0xa2, 0xa1, 0xa2, 0xa6, 0xa9, 0xa9, 0xa8, 0xa8, 0xae, 0xa4, + 0x7a, 0x74, 0x90, 0x9f, 0x86, 0x64, 0x56, 0x51, 0x4f, 0x54, 0x63, 0x75, + 0x94, 0xab, 0xa4, 0x97, 0x93, 0x99, 0x9f, 0x9f, 0xaf, 0x95, 0x6e, 0x40, + 0x73, 0xb2, 0xbe, 0xc1, 0xc8, 0xcb, 0xca, 0xcc, 0xca, 0xc4, 0xc0, 0xbd, + 0xba, 0xba, 0xbb, 0xba, 0xbc, 0xc2, 0xc5, 0xc8, 0xc9, 0xcb, 0xce, 0xd0, + 0xd3, 0xd6, 0xd9, 0xd9, 0xd9, 0xd6, 0xca, 0xbb, 0xb3, 0xb0, 0xae, 0xab, + 0xab, 0xa9, 0xa7, 0xa3, 0xa1, 0xa1, 0xa2, 0xa4, 0xa7, 0xa7, 0xa6, 0xa8, + 0xac, 0xb1, 0xb5, 0xb5, 0xb7, 0xb8, 0xbb, 0xbf, 0xc1, 0xc2, 0xc3, 0xc7, + 0xbe, 0xb0, 0x99, 0x7f, 0x70, 0x5e, 0x4f, 0x54, 0x54, 0x53, 0x51, 0x4f, + 0x54, 0x59, 0x5c, 0x64, 0x75, 0x7d, 0x77, 0x72, 0x6d, 0x5f, 0x3a, 0x1e, + 0x1d, 0x34, 0x51, 0x59, 0x5e, 0x57, 0x42, 0x49, 0x57, 0x56, 0x59, 0x66, + 0x75, 0x86, 0x96, 0x9f, 0xa5, 0xa6, 0x9e, 0x94, 0x8f, 0x8c, 0x89, 0x88, + 0x87, 0x86, 0x83, 0x7c, 0x72, 0x6c, 0x69, 0x66, 0x62, 0x66, 0x6c, 0x6e, + 0x72, 0x77, 0x7c, 0x7f, 0x81, 0x82, 0x83, 0x85, 0x85, 0x86, 0x87, 0x87, + 0x87, 0x89, 0x89, 0x89, 0x88, 0x86, 0x84, 0x83, 0x83, 0x83, 0x81, 0x7f, + 0x7c, 0x7a, 0x77, 0x73, 0x71, 0x71, 0x70, 0x6f, 0x6d, 0x6b, 0x6a, 0x68, + 0x64, 0x60, 0x5b, 0x58, 0x55, 0x51, 0x4b, 0x44, 0x40, 0x3d, 0x38, 0x32, + 0x2a, 0x23, 0x1f, 0x18, 0x13, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, + 0x12, 0x12, 0x13, 0x14, 0x15, 0x15, 0x13, 0x12, 0x60, 0x5d, 0x5b, 0x5b, + 0x5a, 0x5b, 0x5a, 0x5b, 0x5a, 0x58, 0x58, 0x57, 0x57, 0x57, 0x57, 0x59, + 0x58, 0x57, 0x57, 0x57, 0x59, 0x59, 0x59, 0x5a, 0x5c, 0x5f, 0x60, 0x60, + 0x62, 0x63, 0x65, 0x67, 0x69, 0x6a, 0x6c, 0x6f, 0x70, 0x70, 0x71, 0x71, + 0x70, 0x71, 0x71, 0x71, 0x6f, 0x6f, 0x6e, 0x6e, 0x6e, 0x6e, 0x6f, 0x71, + 0x71, 0x71, 0x70, 0x70, 0x6f, 0x6f, 0x70, 0x71, 0x71, 0x73, 0x77, 0x7a, + 0x7f, 0x88, 0x90, 0x98, 0x9d, 0xa1, 0xa9, 0xb4, 0xbc, 0xc2, 0xc5, 0xc7, + 0xc9, 0xc7, 0xc4, 0xc2, 0xc1, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xbc, 0xb2, + 0xab, 0xa9, 0xab, 0xb0, 0xb2, 0xae, 0xab, 0xa8, 0xa7, 0xa8, 0xa9, 0xa9, + 0xa8, 0xa9, 0xab, 0xaa, 0xa9, 0xa7, 0xa8, 0xa5, 0x8f, 0x82, 0x7a, 0x83, + 0xa4, 0xa9, 0xa8, 0xa9, 0xab, 0xa7, 0xb0, 0xb6, 0xb0, 0x8c, 0x7a, 0x99, + 0xa8, 0xa3, 0x88, 0x90, 0xa1, 0x80, 0x5f, 0x45, 0x80, 0xb6, 0xbf, 0xc0, + 0xc6, 0xca, 0xcb, 0xcd, 0xcd, 0xc8, 0xc0, 0xbc, 0xb9, 0xb8, 0xba, 0xba, + 0xba, 0xc0, 0xc3, 0xc4, 0xc7, 0xc7, 0xc9, 0xcc, 0xce, 0xd1, 0xd5, 0xd7, + 0xd8, 0xd7, 0xd1, 0xc7, 0xbe, 0xb9, 0xb5, 0xb1, 0xaf, 0xae, 0xad, 0xaa, + 0xa5, 0xa4, 0xa5, 0xa7, 0xaa, 0xad, 0xac, 0xab, 0xac, 0xb3, 0xb9, 0xb9, + 0xb9, 0xb9, 0xbe, 0xc2, 0xc6, 0xc9, 0xcb, 0xcd, 0xc2, 0xb6, 0xa1, 0x82, + 0x6f, 0x5d, 0x53, 0x57, 0x54, 0x52, 0x52, 0x52, 0x58, 0x5e, 0x61, 0x67, + 0x77, 0x7e, 0x76, 0x6f, 0x67, 0x63, 0x4f, 0x2d, 0x1f, 0x23, 0x42, 0x4e, + 0x4f, 0x52, 0x5c, 0x67, 0x5f, 0x5d, 0x60, 0x67, 0x73, 0x88, 0x98, 0x9f, + 0xa5, 0xa6, 0x9f, 0x94, 0x8f, 0x8b, 0x89, 0x87, 0x86, 0x85, 0x83, 0x7c, + 0x72, 0x6b, 0x68, 0x65, 0x61, 0x65, 0x6a, 0x6e, 0x72, 0x79, 0x7e, 0x80, + 0x82, 0x83, 0x84, 0x86, 0x87, 0x88, 0x88, 0x88, 0x89, 0x8a, 0x89, 0x89, + 0x88, 0x86, 0x84, 0x84, 0x84, 0x84, 0x82, 0x80, 0x7d, 0x7b, 0x78, 0x74, + 0x72, 0x71, 0x71, 0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x64, 0x5f, 0x5b, 0x57, + 0x54, 0x50, 0x4a, 0x43, 0x3f, 0x3d, 0x39, 0x33, 0x2c, 0x25, 0x20, 0x18, + 0x13, 0x12, 0x11, 0x11, 0x11, 0x11, 0x10, 0x11, 0x11, 0x12, 0x12, 0x13, + 0x15, 0x15, 0x13, 0x12, 0x66, 0x60, 0x5d, 0x5c, 0x5b, 0x5b, 0x5b, 0x5b, + 0x5a, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, + 0x58, 0x58, 0x58, 0x59, 0x5b, 0x5e, 0x60, 0x61, 0x62, 0x63, 0x64, 0x67, + 0x68, 0x69, 0x6b, 0x6e, 0x6e, 0x6f, 0x70, 0x71, 0x71, 0x71, 0x71, 0x70, + 0x6f, 0x6e, 0x6d, 0x6d, 0x6d, 0x6c, 0x6d, 0x6f, 0x6f, 0x6f, 0x6f, 0x6e, + 0x6d, 0x6e, 0x6f, 0x6f, 0x70, 0x73, 0x77, 0x7b, 0x82, 0x8d, 0x96, 0x9f, + 0xa4, 0xa8, 0xb1, 0xb9, 0xc0, 0xc6, 0xc8, 0xca, 0xcb, 0xca, 0xc8, 0xc7, + 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc4, 0xc1, 0xbc, 0xb5, 0xb2, 0xb1, 0xb6, + 0xb7, 0xb3, 0xb0, 0xac, 0xab, 0xad, 0xae, 0xae, 0xae, 0xac, 0xac, 0xab, + 0xab, 0xa8, 0xa7, 0xaa, 0xa2, 0x96, 0x88, 0x8c, 0x8c, 0x8a, 0x90, 0xa1, + 0xa4, 0x95, 0x9f, 0xa2, 0x9a, 0x8e, 0x89, 0xab, 0xba, 0xaf, 0x8b, 0x99, + 0x96, 0x5d, 0x41, 0x47, 0x86, 0xb7, 0xbe, 0xc0, 0xc4, 0xc9, 0xca, 0xcc, + 0xcc, 0xc9, 0xbe, 0xb8, 0xb6, 0xb6, 0xb8, 0xb8, 0xb8, 0xbb, 0xbe, 0xbf, + 0xc2, 0xc2, 0xc4, 0xc5, 0xc8, 0xcd, 0xd1, 0xd2, 0xd3, 0xd5, 0xd8, 0xd3, + 0xc9, 0xc2, 0xbb, 0xb7, 0xb7, 0xb6, 0xb5, 0xb3, 0xac, 0xa7, 0xa7, 0xa8, + 0xad, 0xb1, 0xb1, 0xb0, 0xb0, 0xb3, 0xba, 0xbd, 0xbb, 0xbc, 0xc1, 0xc5, + 0xcb, 0xd0, 0xd2, 0xd1, 0xc4, 0xbb, 0xa6, 0x84, 0x6f, 0x5f, 0x5a, 0x5a, + 0x54, 0x51, 0x52, 0x55, 0x5a, 0x5f, 0x60, 0x62, 0x71, 0x7c, 0x74, 0x6a, + 0x60, 0x61, 0x60, 0x48, 0x33, 0x1e, 0x29, 0x3e, 0x41, 0x4b, 0x63, 0x6d, + 0x5f, 0x56, 0x58, 0x66, 0x74, 0x88, 0x97, 0x9f, 0xa5, 0xa5, 0x9c, 0x91, + 0x8c, 0x88, 0x86, 0x86, 0x86, 0x85, 0x82, 0x7c, 0x72, 0x6c, 0x69, 0x66, + 0x60, 0x62, 0x69, 0x6d, 0x72, 0x7a, 0x80, 0x82, 0x83, 0x84, 0x87, 0x88, + 0x89, 0x8b, 0x8b, 0x8b, 0x8b, 0x8c, 0x8b, 0x8a, 0x8a, 0x88, 0x86, 0x86, + 0x85, 0x85, 0x83, 0x81, 0x7f, 0x7c, 0x79, 0x76, 0x74, 0x72, 0x71, 0x6f, + 0x6c, 0x6b, 0x69, 0x67, 0x64, 0x5e, 0x5b, 0x57, 0x54, 0x51, 0x4b, 0x43, + 0x3f, 0x3d, 0x38, 0x32, 0x2b, 0x25, 0x20, 0x18, 0x13, 0x11, 0x11, 0x11, + 0x12, 0x11, 0x10, 0x11, 0x12, 0x12, 0x12, 0x13, 0x15, 0x14, 0x13, 0x12, + 0x6b, 0x64, 0x5f, 0x5c, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x59, 0x56, + 0x56, 0x56, 0x57, 0x57, 0x56, 0x57, 0x57, 0x58, 0x58, 0x58, 0x58, 0x5a, + 0x5b, 0x5c, 0x5e, 0x61, 0x62, 0x63, 0x64, 0x65, 0x67, 0x69, 0x69, 0x6b, + 0x6c, 0x6e, 0x70, 0x72, 0x72, 0x71, 0x71, 0x70, 0x6f, 0x6d, 0x6c, 0x6c, + 0x6c, 0x6c, 0x6c, 0x6d, 0x6c, 0x6c, 0x6d, 0x6d, 0x6c, 0x6d, 0x6d, 0x6d, + 0x6d, 0x70, 0x77, 0x7d, 0x86, 0x93, 0x9c, 0xa6, 0xac, 0xb0, 0xb7, 0xbd, + 0xc3, 0xc8, 0xca, 0xca, 0xca, 0xcb, 0xca, 0xc9, 0xc8, 0xc6, 0xc7, 0xc8, + 0xc7, 0xc6, 0xc3, 0xbf, 0xbb, 0xb8, 0xb6, 0xb9, 0xba, 0xb8, 0xb6, 0xb1, + 0xae, 0xb0, 0xb1, 0xb1, 0xb0, 0xad, 0xad, 0xad, 0xac, 0xaa, 0xa8, 0xa7, + 0x98, 0x91, 0x92, 0x9b, 0x95, 0x8e, 0x92, 0x9e, 0x90, 0x98, 0x92, 0x90, + 0x95, 0x91, 0xa0, 0xb5, 0xba, 0xb0, 0x9b, 0xad, 0x8f, 0x45, 0x31, 0x51, + 0x8f, 0xb7, 0xc2, 0xc3, 0xc3, 0xc7, 0xc4, 0xc7, 0xc7, 0xc2, 0xba, 0xb5, + 0xb5, 0xb7, 0xb9, 0xb5, 0xb8, 0xb9, 0xb9, 0xbd, 0xc0, 0xbe, 0xbe, 0xbf, + 0xc2, 0xc8, 0xcb, 0xcc, 0xcd, 0xd0, 0xd9, 0xda, 0xd2, 0xcb, 0xc1, 0xb9, + 0xbd, 0xbe, 0xbe, 0xbb, 0xb5, 0xb0, 0xae, 0xae, 0xb1, 0xb5, 0xb6, 0xb3, + 0xb3, 0xb6, 0xbd, 0xc2, 0xc1, 0xc2, 0xc5, 0xc4, 0xc7, 0xca, 0xcc, 0xcc, + 0xc4, 0xbc, 0xa5, 0x85, 0x72, 0x60, 0x5e, 0x5b, 0x55, 0x52, 0x53, 0x57, + 0x5b, 0x5b, 0x5b, 0x5d, 0x6d, 0x7c, 0x7c, 0x77, 0x6d, 0x64, 0x65, 0x5d, + 0x4b, 0x2b, 0x1f, 0x2c, 0x3f, 0x4c, 0x5b, 0x5f, 0x58, 0x55, 0x5a, 0x68, + 0x74, 0x86, 0x93, 0x9a, 0xa2, 0xa1, 0x98, 0x8e, 0x89, 0x85, 0x83, 0x84, + 0x85, 0x84, 0x81, 0x79, 0x70, 0x6a, 0x67, 0x64, 0x5f, 0x60, 0x67, 0x6b, + 0x71, 0x7a, 0x80, 0x84, 0x85, 0x86, 0x88, 0x89, 0x8b, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8d, 0x8c, 0x8c, 0x8b, 0x89, 0x88, 0x87, 0x87, 0x86, 0x85, 0x82, + 0x81, 0x7f, 0x7b, 0x78, 0x75, 0x73, 0x72, 0x70, 0x6d, 0x6b, 0x68, 0x66, + 0x63, 0x5d, 0x5a, 0x55, 0x52, 0x50, 0x4a, 0x44, 0x40, 0x3d, 0x37, 0x30, + 0x2b, 0x22, 0x1d, 0x18, 0x13, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, + 0x13, 0x13, 0x12, 0x13, 0x15, 0x15, 0x13, 0x12, 0x6f, 0x68, 0x62, 0x5f, + 0x5c, 0x5b, 0x5b, 0x5b, 0x5b, 0x59, 0x59, 0x57, 0x57, 0x56, 0x56, 0x57, + 0x58, 0x57, 0x58, 0x59, 0x58, 0x57, 0x58, 0x59, 0x5b, 0x5c, 0x5d, 0x5f, + 0x60, 0x61, 0x63, 0x64, 0x66, 0x67, 0x6a, 0x6c, 0x6d, 0x6e, 0x70, 0x72, + 0x72, 0x71, 0x71, 0x71, 0x70, 0x6d, 0x6c, 0x6c, 0x6b, 0x6c, 0x6b, 0x6c, + 0x6b, 0x6b, 0x6c, 0x6c, 0x6b, 0x6c, 0x6c, 0x6b, 0x6d, 0x71, 0x79, 0x80, + 0x8c, 0x98, 0xa0, 0xaa, 0xb1, 0xb5, 0xb9, 0xbf, 0xc5, 0xc9, 0xca, 0xcb, + 0xcc, 0xcd, 0xcc, 0xcb, 0xc9, 0xc7, 0xc5, 0xc6, 0xc6, 0xc6, 0xc2, 0xbf, + 0xbd, 0xbc, 0xba, 0xbb, 0xbd, 0xbd, 0xba, 0xb5, 0xb1, 0xb0, 0xb2, 0xb2, + 0xb1, 0xae, 0xad, 0xad, 0xad, 0xab, 0xa9, 0xa8, 0xa2, 0x9f, 0xa1, 0xa5, + 0x8e, 0x8f, 0x8f, 0x8b, 0x99, 0xa8, 0xa5, 0x9e, 0x97, 0xa8, 0xb4, 0xb3, + 0xa5, 0x8e, 0xa1, 0xa7, 0x78, 0x36, 0x2a, 0x53, 0x99, 0xbb, 0xc4, 0xc4, + 0xc4, 0xc5, 0xc2, 0xc3, 0xc2, 0xbb, 0xbb, 0xb8, 0xb7, 0xb8, 0xb9, 0xb7, + 0xba, 0xb8, 0xb8, 0xbb, 0xbf, 0xbe, 0xbd, 0xbd, 0xbf, 0xc3, 0xc6, 0xc6, + 0xc7, 0xcc, 0xd9, 0xde, 0xd9, 0xd2, 0xc5, 0xbb, 0xc0, 0xc5, 0xc5, 0xc3, + 0xbd, 0xb8, 0xb5, 0xb4, 0xb3, 0xb8, 0xba, 0xb7, 0xb8, 0xbc, 0xc2, 0xc6, + 0xc6, 0xc6, 0xc4, 0xc1, 0xc0, 0xc4, 0xc6, 0xc7, 0xc3, 0xb8, 0xa1, 0x8b, + 0x79, 0x63, 0x60, 0x5d, 0x57, 0x54, 0x53, 0x59, 0x5d, 0x5a, 0x5a, 0x61, + 0x73, 0x82, 0x85, 0x82, 0x76, 0x68, 0x66, 0x63, 0x5a, 0x44, 0x32, 0x31, + 0x43, 0x4c, 0x4f, 0x55, 0x5b, 0x5a, 0x5c, 0x68, 0x74, 0x83, 0x8f, 0x95, + 0x9b, 0x9a, 0x93, 0x8c, 0x88, 0x84, 0x82, 0x83, 0x84, 0x83, 0x80, 0x78, + 0x6f, 0x69, 0x67, 0x63, 0x5e, 0x5f, 0x66, 0x6b, 0x71, 0x7b, 0x82, 0x85, + 0x86, 0x87, 0x88, 0x8b, 0x8c, 0x8d, 0x8d, 0x8e, 0x8e, 0x8d, 0x8d, 0x8c, + 0x8c, 0x8a, 0x89, 0x89, 0x89, 0x88, 0x86, 0x85, 0x83, 0x81, 0x7c, 0x78, + 0x75, 0x73, 0x72, 0x70, 0x6d, 0x6b, 0x68, 0x66, 0x63, 0x5e, 0x5a, 0x55, + 0x52, 0x4f, 0x48, 0x44, 0x40, 0x3c, 0x36, 0x30, 0x2a, 0x22, 0x1d, 0x18, + 0x13, 0x12, 0x11, 0x11, 0x11, 0x12, 0x11, 0x12, 0x13, 0x13, 0x12, 0x13, + 0x15, 0x16, 0x14, 0x12, 0x73, 0x6b, 0x64, 0x60, 0x5c, 0x5c, 0x5c, 0x5c, + 0x5b, 0x5a, 0x59, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58, 0x58, 0x59, + 0x58, 0x58, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5e, 0x5f, 0x60, 0x62, 0x63, + 0x66, 0x67, 0x6a, 0x6c, 0x6d, 0x6f, 0x70, 0x72, 0x71, 0x71, 0x71, 0x71, + 0x70, 0x6d, 0x6c, 0x6c, 0x6b, 0x6b, 0x6a, 0x6b, 0x6a, 0x6b, 0x6c, 0x6c, + 0x6a, 0x6b, 0x6b, 0x6a, 0x6c, 0x72, 0x7b, 0x83, 0x8f, 0x9b, 0xa3, 0xad, + 0xb3, 0xb7, 0xba, 0xc0, 0xc6, 0xc9, 0xca, 0xcb, 0xcc, 0xce, 0xce, 0xcd, + 0xca, 0xc7, 0xc4, 0xc4, 0xc5, 0xc5, 0xc2, 0xbe, 0xbd, 0xbc, 0xba, 0xbb, + 0xbe, 0xbf, 0xbd, 0xb8, 0xb3, 0xb2, 0xb3, 0xb4, 0xb2, 0xaf, 0xae, 0xae, + 0xae, 0xad, 0xaa, 0xa9, 0xab, 0xa9, 0xa6, 0xa3, 0x94, 0x98, 0x95, 0x8c, + 0xa6, 0xac, 0xa1, 0x9b, 0x9f, 0xb3, 0xb8, 0xab, 0x9b, 0x8a, 0xa2, 0xa2, + 0x6a, 0x2f, 0x29, 0x58, 0xa0, 0xbe, 0xc4, 0xc5, 0xc4, 0xc6, 0xc4, 0xc4, + 0xc0, 0xb9, 0xbb, 0xba, 0xb7, 0xb7, 0xb9, 0xb8, 0xba, 0xb8, 0xb7, 0xba, + 0xbe, 0xbe, 0xbe, 0xbe, 0xbd, 0xc0, 0xc1, 0xc2, 0xc4, 0xc9, 0xd7, 0xde, + 0xda, 0xd4, 0xc6, 0xbc, 0xc0, 0xc7, 0xc8, 0xc8, 0xc3, 0xbe, 0xbb, 0xb8, + 0xb6, 0xb9, 0xbc, 0xba, 0xbb, 0xbf, 0xc3, 0xc7, 0xc8, 0xc6, 0xc2, 0xbe, + 0xbe, 0xc0, 0xc3, 0xc6, 0xc3, 0xb3, 0x9e, 0x8f, 0x80, 0x68, 0x62, 0x5f, + 0x59, 0x55, 0x54, 0x5a, 0x5f, 0x5c, 0x5c, 0x66, 0x75, 0x80, 0x86, 0x85, + 0x7a, 0x6c, 0x67, 0x65, 0x60, 0x53, 0x41, 0x3b, 0x48, 0x4f, 0x51, 0x57, + 0x5f, 0x5a, 0x5c, 0x67, 0x73, 0x80, 0x8b, 0x91, 0x96, 0x96, 0x90, 0x8b, + 0x88, 0x83, 0x82, 0x83, 0x83, 0x82, 0x7f, 0x77, 0x6e, 0x68, 0x66, 0x63, + 0x5e, 0x5e, 0x65, 0x6a, 0x71, 0x7b, 0x82, 0x85, 0x87, 0x87, 0x89, 0x8b, + 0x8d, 0x8d, 0x8e, 0x8f, 0x8f, 0x8e, 0x8d, 0x8d, 0x8d, 0x8b, 0x8a, 0x8a, + 0x8a, 0x89, 0x87, 0x86, 0x84, 0x82, 0x7d, 0x78, 0x75, 0x74, 0x72, 0x70, + 0x6d, 0x6a, 0x68, 0x66, 0x64, 0x5f, 0x5a, 0x55, 0x52, 0x4e, 0x48, 0x43, + 0x40, 0x3c, 0x36, 0x31, 0x2a, 0x23, 0x1e, 0x18, 0x14, 0x12, 0x11, 0x11, + 0x11, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x14, 0x15, 0x14, 0x12, + 0x78, 0x6f, 0x68, 0x64, 0x5f, 0x5c, 0x5d, 0x5d, 0x5c, 0x5b, 0x59, 0x59, + 0x58, 0x57, 0x57, 0x57, 0x58, 0x59, 0x59, 0x58, 0x59, 0x59, 0x59, 0x59, + 0x59, 0x5b, 0x5c, 0x5e, 0x5f, 0x61, 0x62, 0x64, 0x66, 0x68, 0x69, 0x6b, + 0x6d, 0x6f, 0x70, 0x71, 0x71, 0x70, 0x70, 0x71, 0x70, 0x6d, 0x6b, 0x6b, + 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6b, 0x6b, 0x69, 0x6a, 0x6a, 0x6a, + 0x6b, 0x73, 0x7f, 0x88, 0x94, 0xa1, 0xa9, 0xb0, 0xb5, 0xb7, 0xbb, 0xc0, + 0xc6, 0xc8, 0xc9, 0xcb, 0xce, 0xd0, 0xd0, 0xd0, 0xcd, 0xc8, 0xc4, 0xc3, + 0xc2, 0xc2, 0xc1, 0xbe, 0xbc, 0xbb, 0xb9, 0xba, 0xbf, 0xc0, 0xbf, 0xbb, + 0xb6, 0xb4, 0xb5, 0xb5, 0xb3, 0xaf, 0xaf, 0xaf, 0xaf, 0xae, 0xaa, 0xab, + 0xb2, 0xb0, 0xa3, 0x9b, 0xad, 0xb1, 0xad, 0xa8, 0xb3, 0xa2, 0x87, 0x8c, + 0xad, 0xb1, 0xab, 0x99, 0x98, 0xa4, 0xa1, 0xa0, 0x5e, 0x2e, 0x32, 0x6a, + 0xab, 0xc0, 0xc5, 0xc6, 0xc5, 0xca, 0xca, 0xc7, 0xc1, 0xb9, 0xbc, 0xb9, + 0xb4, 0xb4, 0xb8, 0xba, 0xb8, 0xb6, 0xb6, 0xb8, 0xbd, 0xbe, 0xbe, 0xbd, + 0xbb, 0xbc, 0xbc, 0xbc, 0xbe, 0xc5, 0xd3, 0xdb, 0xd8, 0xd1, 0xc6, 0xbe, + 0xc1, 0xc6, 0xc9, 0xca, 0xc7, 0xc4, 0xc2, 0xc0, 0xbc, 0xbb, 0xbe, 0xbe, + 0xbf, 0xc2, 0xc3, 0xc5, 0xc7, 0xc5, 0xbd, 0xba, 0xbb, 0xbe, 0xc2, 0xc6, + 0xc1, 0xac, 0x9b, 0x94, 0x89, 0x72, 0x66, 0x61, 0x5b, 0x57, 0x55, 0x5a, + 0x5e, 0x61, 0x64, 0x6a, 0x70, 0x76, 0x81, 0x82, 0x7b, 0x73, 0x6a, 0x65, + 0x62, 0x5c, 0x52, 0x4b, 0x4f, 0x56, 0x60, 0x63, 0x5f, 0x55, 0x57, 0x65, + 0x73, 0x7c, 0x84, 0x8a, 0x90, 0x91, 0x8e, 0x8a, 0x87, 0x83, 0x81, 0x82, + 0x82, 0x81, 0x7e, 0x76, 0x6e, 0x67, 0x64, 0x61, 0x5e, 0x5d, 0x64, 0x69, + 0x71, 0x7b, 0x83, 0x86, 0x87, 0x88, 0x8a, 0x8d, 0x8f, 0x8f, 0x8f, 0x90, + 0x8f, 0x8f, 0x8f, 0x8e, 0x8e, 0x8e, 0x8b, 0x8b, 0x8b, 0x89, 0x88, 0x87, + 0x85, 0x83, 0x7f, 0x7b, 0x77, 0x75, 0x73, 0x71, 0x6c, 0x6a, 0x68, 0x66, + 0x63, 0x5e, 0x5a, 0x56, 0x53, 0x4e, 0x49, 0x42, 0x3e, 0x3b, 0x36, 0x31, + 0x2c, 0x27, 0x22, 0x1a, 0x13, 0x12, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x14, 0x14, 0x15, 0x16, 0x15, 0x14, 0x80, 0x76, 0x6e, 0x6a, + 0x64, 0x5f, 0x5c, 0x5d, 0x5d, 0x5c, 0x5a, 0x5a, 0x58, 0x57, 0x57, 0x58, + 0x5a, 0x59, 0x59, 0x58, 0x58, 0x5a, 0x5a, 0x5a, 0x59, 0x5b, 0x5d, 0x5e, + 0x5f, 0x60, 0x61, 0x64, 0x65, 0x67, 0x67, 0x6a, 0x6d, 0x6e, 0x6e, 0x6f, + 0x71, 0x70, 0x71, 0x71, 0x6f, 0x6d, 0x6b, 0x6b, 0x6a, 0x69, 0x69, 0x69, + 0x6a, 0x6a, 0x69, 0x69, 0x66, 0x67, 0x68, 0x68, 0x6c, 0x79, 0x87, 0x8f, + 0x9a, 0xa5, 0xac, 0xb2, 0xb7, 0xba, 0xbd, 0xc2, 0xc6, 0xc7, 0xc8, 0xcb, + 0xcf, 0xd1, 0xd2, 0xd2, 0xcf, 0xca, 0xc5, 0xc2, 0xc0, 0xbe, 0xbf, 0xbd, + 0xbb, 0xb9, 0xb7, 0xb9, 0xbe, 0xc1, 0xc0, 0xbd, 0xb9, 0xb6, 0xb6, 0xb6, + 0xb4, 0xb0, 0xae, 0xaf, 0xb0, 0xaf, 0xac, 0xac, 0xaf, 0xae, 0xa9, 0xaa, + 0xaf, 0xb8, 0xbc, 0xb9, 0x9d, 0x84, 0x93, 0xa3, 0xae, 0x9d, 0x97, 0x92, + 0x9c, 0xb2, 0xa2, 0x99, 0x4f, 0x37, 0x4c, 0x89, 0xb3, 0xc1, 0xc7, 0xc9, + 0xcb, 0xcf, 0xcf, 0xca, 0xc5, 0xbe, 0xbe, 0xbd, 0xbb, 0xb9, 0xb7, 0xbb, + 0xb8, 0xb6, 0xb6, 0xb7, 0xbb, 0xbc, 0xba, 0xb9, 0xba, 0xbc, 0xb9, 0xb8, + 0xba, 0xbf, 0xcb, 0xd1, 0xcb, 0xc6, 0xc1, 0xbd, 0xc0, 0xc4, 0xc7, 0xc9, + 0xc8, 0xc6, 0xc7, 0xc6, 0xc1, 0xbd, 0xbe, 0xc0, 0xc1, 0xc1, 0xc1, 0xc1, + 0xc1, 0xbf, 0xba, 0xba, 0xbd, 0xc0, 0xc3, 0xc6, 0xba, 0xa3, 0x97, 0x95, + 0x8e, 0x7b, 0x6b, 0x64, 0x60, 0x5d, 0x5a, 0x5e, 0x63, 0x65, 0x67, 0x6b, + 0x6e, 0x75, 0x7f, 0x81, 0x7d, 0x78, 0x6c, 0x66, 0x63, 0x5e, 0x5b, 0x55, + 0x52, 0x54, 0x5d, 0x5c, 0x55, 0x4c, 0x4f, 0x63, 0x73, 0x79, 0x7e, 0x81, + 0x87, 0x8a, 0x89, 0x86, 0x84, 0x82, 0x81, 0x83, 0x83, 0x82, 0x7d, 0x75, + 0x6c, 0x65, 0x63, 0x60, 0x5c, 0x5b, 0x61, 0x67, 0x70, 0x7c, 0x84, 0x87, + 0x89, 0x8a, 0x8c, 0x8e, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x90, 0x90, + 0x90, 0x8f, 0x8d, 0x8d, 0x8d, 0x8b, 0x8a, 0x88, 0x86, 0x84, 0x82, 0x7d, + 0x79, 0x77, 0x76, 0x72, 0x6e, 0x6a, 0x67, 0x65, 0x61, 0x5d, 0x5a, 0x55, + 0x53, 0x4e, 0x47, 0x41, 0x3d, 0x3a, 0x35, 0x31, 0x2b, 0x27, 0x22, 0x1a, + 0x13, 0x12, 0x11, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x14, + 0x16, 0x16, 0x14, 0x15, 0x85, 0x7d, 0x76, 0x71, 0x69, 0x61, 0x5c, 0x5d, + 0x5d, 0x5b, 0x5a, 0x5a, 0x58, 0x58, 0x58, 0x5b, 0x5c, 0x5b, 0x5b, 0x59, + 0x58, 0x58, 0x58, 0x59, 0x5a, 0x5b, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x64, + 0x64, 0x65, 0x67, 0x68, 0x6b, 0x6c, 0x6d, 0x6e, 0x70, 0x70, 0x70, 0x70, + 0x6f, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x68, 0x69, 0x69, 0x69, 0x67, 0x66, + 0x64, 0x64, 0x64, 0x66, 0x6e, 0x7e, 0x8e, 0x96, 0xa0, 0xaa, 0xb0, 0xb4, + 0xb8, 0xbb, 0xbd, 0xc3, 0xc6, 0xc7, 0xc8, 0xcb, 0xd0, 0xd3, 0xd3, 0xd3, + 0xd1, 0xcd, 0xc8, 0xc4, 0xc1, 0xbd, 0xbb, 0xbb, 0xb9, 0xb8, 0xb7, 0xb9, + 0xbe, 0xc1, 0xc2, 0xc1, 0xbd, 0xb8, 0xb7, 0xb7, 0xb5, 0xb1, 0xae, 0xaf, + 0xaf, 0xae, 0xae, 0xae, 0xae, 0xb1, 0xb4, 0xb3, 0xb2, 0xb8, 0xb1, 0x99, + 0x91, 0xa3, 0xb5, 0xbb, 0xb1, 0x8d, 0xad, 0xb4, 0xb3, 0xb3, 0xa8, 0x89, + 0x46, 0x51, 0x6f, 0x9e, 0xb8, 0xc3, 0xc8, 0xca, 0xcd, 0xcf, 0xce, 0xc9, + 0xc6, 0xc1, 0xbc, 0xbd, 0xbd, 0xbb, 0xb7, 0xb6, 0xb5, 0xb5, 0xb5, 0xb5, + 0xba, 0xbc, 0xbb, 0xbb, 0xbe, 0xbe, 0xbb, 0xb9, 0xba, 0xbf, 0xc5, 0xc4, + 0xc0, 0xbe, 0xbe, 0xbe, 0xc0, 0xc4, 0xc6, 0xc7, 0xc7, 0xc7, 0xc6, 0xc5, + 0xc3, 0xc0, 0xbf, 0xc0, 0xc0, 0xbf, 0xbc, 0xbc, 0xbb, 0xba, 0xb9, 0xbc, + 0xc0, 0xc4, 0xc5, 0xc2, 0xaf, 0x9c, 0x95, 0x94, 0x8f, 0x81, 0x71, 0x6c, + 0x68, 0x63, 0x5b, 0x5f, 0x65, 0x67, 0x67, 0x68, 0x6f, 0x74, 0x7c, 0x80, + 0x80, 0x7d, 0x75, 0x6e, 0x68, 0x60, 0x5c, 0x58, 0x50, 0x50, 0x58, 0x58, + 0x4e, 0x47, 0x4c, 0x5f, 0x73, 0x77, 0x78, 0x7a, 0x7f, 0x82, 0x81, 0x80, + 0x7f, 0x7d, 0x7c, 0x7e, 0x7f, 0x7e, 0x7a, 0x73, 0x6a, 0x65, 0x62, 0x5f, + 0x5b, 0x59, 0x5e, 0x64, 0x6e, 0x7c, 0x85, 0x89, 0x8b, 0x8c, 0x8d, 0x90, + 0x92, 0x92, 0x92, 0x92, 0x92, 0x94, 0x93, 0x92, 0x91, 0x91, 0x8f, 0x90, + 0x8f, 0x8e, 0x8c, 0x8b, 0x88, 0x87, 0x84, 0x81, 0x7c, 0x79, 0x77, 0x74, + 0x70, 0x6c, 0x67, 0x64, 0x60, 0x5c, 0x59, 0x55, 0x52, 0x4c, 0x47, 0x40, + 0x3b, 0x38, 0x33, 0x2f, 0x29, 0x24, 0x20, 0x19, 0x13, 0x12, 0x11, 0x11, + 0x12, 0x12, 0x11, 0x13, 0x13, 0x13, 0x14, 0x13, 0x14, 0x14, 0x13, 0x14, + 0x8a, 0x82, 0x7b, 0x75, 0x6d, 0x64, 0x5e, 0x5b, 0x5a, 0x5a, 0x5a, 0x59, + 0x58, 0x58, 0x58, 0x5b, 0x5c, 0x5b, 0x5b, 0x59, 0x59, 0x58, 0x59, 0x59, + 0x59, 0x5a, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x64, 0x65, 0x65, 0x66, 0x67, + 0x6a, 0x6d, 0x6e, 0x6e, 0x70, 0x6f, 0x6e, 0x6e, 0x6d, 0x6c, 0x6b, 0x6b, + 0x6a, 0x69, 0x67, 0x67, 0x67, 0x67, 0x66, 0x66, 0x63, 0x63, 0x63, 0x65, + 0x70, 0x84, 0x94, 0x9d, 0xa5, 0xac, 0xb2, 0xb5, 0xb8, 0xbb, 0xbf, 0xc3, + 0xc6, 0xc7, 0xc8, 0xcc, 0xd0, 0xd3, 0xd3, 0xd3, 0xd3, 0xd0, 0xca, 0xc7, + 0xc3, 0xbe, 0xba, 0xb9, 0xb8, 0xb8, 0xb6, 0xb9, 0xbe, 0xc1, 0xc2, 0xc3, + 0xbf, 0xba, 0xb7, 0xb7, 0xb6, 0xb2, 0xaf, 0xae, 0xae, 0xae, 0xaf, 0xaf, + 0xaf, 0xb1, 0xb4, 0xaf, 0xb6, 0xb3, 0x9c, 0x76, 0xa1, 0xc0, 0xc2, 0xc0, + 0xaf, 0x7f, 0xac, 0xbd, 0xba, 0xaf, 0xa7, 0x79, 0x47, 0x6b, 0x8c, 0xaa, + 0xbc, 0xc4, 0xca, 0xcc, 0xcc, 0xcc, 0xcb, 0xc9, 0xc6, 0xc1, 0xbb, 0xbc, + 0xbc, 0xbb, 0xba, 0xb6, 0xb3, 0xb3, 0xb3, 0xb5, 0xb9, 0xbd, 0xbe, 0xbe, + 0xc1, 0xbf, 0xbb, 0xbc, 0xbf, 0xc7, 0xcb, 0xc6, 0xc1, 0xbf, 0xbf, 0xc0, + 0xc3, 0xc5, 0xc6, 0xc5, 0xc6, 0xc6, 0xc5, 0xc4, 0xc3, 0xc1, 0xc0, 0xc0, + 0xbf, 0xbd, 0xbb, 0xbb, 0xba, 0xb8, 0xb8, 0xbc, 0xc2, 0xc5, 0xc4, 0xbd, + 0xa8, 0x98, 0x92, 0x91, 0x8d, 0x80, 0x71, 0x6e, 0x6c, 0x66, 0x5b, 0x60, + 0x66, 0x67, 0x67, 0x66, 0x6f, 0x75, 0x7a, 0x7e, 0x81, 0x80, 0x7e, 0x76, + 0x6f, 0x66, 0x5d, 0x59, 0x51, 0x51, 0x56, 0x58, 0x4e, 0x48, 0x4c, 0x5e, + 0x74, 0x76, 0x75, 0x76, 0x7a, 0x7d, 0x7b, 0x7a, 0x78, 0x76, 0x75, 0x77, + 0x7a, 0x7b, 0x78, 0x71, 0x6a, 0x65, 0x63, 0x60, 0x5a, 0x58, 0x5c, 0x62, + 0x6d, 0x7b, 0x84, 0x89, 0x8b, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x94, 0x94, + 0x95, 0x95, 0x95, 0x94, 0x93, 0x91, 0x91, 0x92, 0x91, 0x90, 0x8e, 0x8c, + 0x8b, 0x8a, 0x87, 0x84, 0x7f, 0x7b, 0x78, 0x75, 0x71, 0x6c, 0x68, 0x65, + 0x61, 0x5c, 0x59, 0x56, 0x52, 0x4d, 0x48, 0x40, 0x3c, 0x39, 0x32, 0x2e, + 0x28, 0x23, 0x20, 0x1a, 0x14, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, + 0x13, 0x13, 0x15, 0x13, 0x13, 0x14, 0x13, 0x15, 0x8c, 0x85, 0x7e, 0x79, + 0x70, 0x67, 0x5f, 0x5c, 0x5a, 0x5a, 0x5a, 0x58, 0x58, 0x58, 0x58, 0x5b, + 0x5c, 0x5b, 0x5b, 0x59, 0x59, 0x58, 0x59, 0x59, 0x58, 0x59, 0x5c, 0x5d, + 0x5f, 0x60, 0x61, 0x63, 0x64, 0x64, 0x64, 0x66, 0x69, 0x6c, 0x6e, 0x6e, + 0x70, 0x6f, 0x6e, 0x6d, 0x6d, 0x6c, 0x6b, 0x6b, 0x6a, 0x69, 0x66, 0x66, + 0x66, 0x66, 0x65, 0x64, 0x63, 0x62, 0x62, 0x65, 0x73, 0x88, 0x98, 0x9f, + 0xa7, 0xad, 0xb2, 0xb6, 0xb9, 0xbc, 0xc0, 0xc4, 0xc6, 0xc7, 0xc8, 0xcd, + 0xd0, 0xd3, 0xd4, 0xd4, 0xd4, 0xd2, 0xcc, 0xc8, 0xc5, 0xbf, 0xba, 0xb8, + 0xb8, 0xb8, 0xb6, 0xb9, 0xbd, 0xc1, 0xc3, 0xc4, 0xc0, 0xbb, 0xb8, 0xb8, + 0xb7, 0xb2, 0xb0, 0xad, 0xad, 0xae, 0xb0, 0xb0, 0xb0, 0xb1, 0xb3, 0xb1, + 0xb8, 0xae, 0x96, 0x77, 0xb0, 0xc5, 0xb5, 0xac, 0xa1, 0x7e, 0xa0, 0xb6, + 0xb7, 0xad, 0xa1, 0x6a, 0x51, 0x7b, 0x98, 0xb0, 0xbe, 0xc4, 0xc8, 0xc9, + 0xc7, 0xc8, 0xc8, 0xc7, 0xc4, 0xbe, 0xba, 0xbb, 0xbb, 0xbb, 0xbb, 0xb6, + 0xb2, 0xb3, 0xb4, 0xb5, 0xb8, 0xbc, 0xbd, 0xbf, 0xc1, 0xbf, 0xbd, 0xbf, + 0xc2, 0xcb, 0xd1, 0xcb, 0xc7, 0xc5, 0xc3, 0xc2, 0xc3, 0xc5, 0xc5, 0xc5, + 0xc7, 0xc6, 0xc5, 0xc4, 0xc3, 0xc2, 0xc1, 0xc0, 0xbf, 0xbc, 0xbb, 0xba, + 0xb9, 0xb9, 0xb8, 0xbb, 0xc1, 0xc3, 0xc1, 0xb8, 0xa3, 0x95, 0x90, 0x8f, + 0x8b, 0x7e, 0x6e, 0x6b, 0x6c, 0x67, 0x5b, 0x60, 0x66, 0x66, 0x65, 0x66, + 0x6d, 0x75, 0x7b, 0x7f, 0x82, 0x81, 0x80, 0x79, 0x73, 0x6a, 0x60, 0x5b, + 0x54, 0x52, 0x56, 0x57, 0x4e, 0x47, 0x4b, 0x5d, 0x74, 0x75, 0x72, 0x73, + 0x77, 0x7a, 0x78, 0x76, 0x75, 0x73, 0x71, 0x73, 0x76, 0x77, 0x76, 0x70, + 0x68, 0x64, 0x62, 0x5f, 0x5a, 0x58, 0x5b, 0x60, 0x6b, 0x7a, 0x83, 0x89, + 0x8b, 0x8c, 0x8e, 0x91, 0x93, 0x95, 0x95, 0x96, 0x96, 0x96, 0x95, 0x95, + 0x94, 0x92, 0x93, 0x93, 0x92, 0x91, 0x8f, 0x8d, 0x8c, 0x8b, 0x8a, 0x86, + 0x81, 0x7d, 0x7a, 0x76, 0x72, 0x6c, 0x69, 0x66, 0x62, 0x5d, 0x59, 0x55, + 0x52, 0x4e, 0x49, 0x41, 0x3d, 0x3a, 0x33, 0x30, 0x29, 0x24, 0x20, 0x1b, + 0x15, 0x12, 0x11, 0x11, 0x10, 0x10, 0x10, 0x12, 0x13, 0x13, 0x14, 0x13, + 0x13, 0x14, 0x13, 0x15, 0x90, 0x89, 0x83, 0x7d, 0x75, 0x6b, 0x62, 0x5e, + 0x5c, 0x5a, 0x59, 0x58, 0x58, 0x58, 0x58, 0x5b, 0x5c, 0x5b, 0x5a, 0x58, + 0x58, 0x58, 0x59, 0x59, 0x58, 0x58, 0x5b, 0x5c, 0x5d, 0x5f, 0x60, 0x62, + 0x63, 0x64, 0x65, 0x65, 0x69, 0x6b, 0x6d, 0x6d, 0x6e, 0x6e, 0x6d, 0x6d, + 0x6d, 0x6c, 0x6b, 0x6b, 0x6a, 0x68, 0x65, 0x65, 0x64, 0x64, 0x64, 0x63, + 0x61, 0x61, 0x62, 0x67, 0x77, 0x8d, 0x9b, 0xa2, 0xa8, 0xae, 0xb2, 0xb6, + 0xba, 0xbc, 0xc0, 0xc4, 0xc6, 0xc6, 0xc8, 0xcc, 0xd0, 0xd4, 0xd5, 0xd5, + 0xd5, 0xd3, 0xce, 0xca, 0xc7, 0xc2, 0xbc, 0xb8, 0xb9, 0xb8, 0xb6, 0xb8, + 0xbc, 0xc0, 0xc3, 0xc6, 0xc3, 0xbe, 0xbb, 0xb9, 0xb8, 0xb3, 0xaf, 0xac, + 0xac, 0xae, 0xb1, 0xb1, 0xaf, 0xaf, 0xb3, 0xbd, 0xb9, 0xa9, 0x9e, 0x9c, + 0xbd, 0xb4, 0x8e, 0x82, 0x8b, 0x91, 0x91, 0xa2, 0xab, 0xaa, 0x8e, 0x54, + 0x69, 0x8e, 0xa2, 0xb4, 0xbf, 0xc0, 0xc1, 0xc0, 0xc0, 0xc4, 0xc5, 0xc3, + 0xc1, 0xba, 0xb9, 0xb8, 0xba, 0xba, 0xb9, 0xb5, 0xb4, 0xb6, 0xb6, 0xb6, + 0xb7, 0xba, 0xbd, 0xbe, 0xbf, 0xc0, 0xc0, 0xc2, 0xc7, 0xcf, 0xd6, 0xd5, + 0xd3, 0xd1, 0xcd, 0xc5, 0xc3, 0xc4, 0xc5, 0xc5, 0xc7, 0xc7, 0xc5, 0xc4, + 0xc3, 0xc1, 0xc0, 0xbf, 0xbe, 0xbe, 0xbb, 0xba, 0xb9, 0xb7, 0xb6, 0xb8, + 0xbc, 0xbe, 0xbb, 0xaf, 0x9c, 0x91, 0x8e, 0x8c, 0x87, 0x79, 0x67, 0x63, + 0x6a, 0x69, 0x5f, 0x60, 0x64, 0x64, 0x63, 0x66, 0x6d, 0x74, 0x7d, 0x81, + 0x82, 0x82, 0x81, 0x7c, 0x78, 0x6f, 0x65, 0x5e, 0x57, 0x54, 0x54, 0x55, + 0x4c, 0x46, 0x4a, 0x5b, 0x72, 0x73, 0x70, 0x70, 0x73, 0x76, 0x74, 0x72, + 0x71, 0x70, 0x6e, 0x6e, 0x70, 0x71, 0x71, 0x6d, 0x66, 0x62, 0x60, 0x5d, + 0x58, 0x56, 0x5a, 0x5f, 0x69, 0x77, 0x82, 0x88, 0x8a, 0x8b, 0x8d, 0x91, + 0x93, 0x96, 0x96, 0x96, 0x97, 0x97, 0x96, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x94, 0x93, 0x92, 0x8f, 0x8e, 0x8d, 0x8b, 0x88, 0x84, 0x7f, 0x7c, 0x78, + 0x74, 0x6e, 0x6a, 0x68, 0x63, 0x5e, 0x59, 0x55, 0x52, 0x4f, 0x49, 0x43, + 0x3f, 0x3c, 0x37, 0x33, 0x2c, 0x27, 0x24, 0x1f, 0x17, 0x14, 0x13, 0x12, + 0x11, 0x10, 0x10, 0x11, 0x12, 0x13, 0x13, 0x13, 0x14, 0x14, 0x13, 0x13, + 0x93, 0x8d, 0x88, 0x84, 0x7b, 0x6f, 0x66, 0x61, 0x5e, 0x5b, 0x5a, 0x59, + 0x59, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x59, 0x58, 0x58, 0x58, 0x59, + 0x59, 0x59, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x64, 0x65, + 0x67, 0x6a, 0x6c, 0x6c, 0x6e, 0x6e, 0x6d, 0x6e, 0x6e, 0x6e, 0x6c, 0x6a, + 0x69, 0x68, 0x65, 0x64, 0x63, 0x63, 0x64, 0x62, 0x61, 0x61, 0x62, 0x69, + 0x7d, 0x93, 0xa0, 0xa6, 0xab, 0xb0, 0xb3, 0xb7, 0xbb, 0xbe, 0xc1, 0xc4, + 0xc5, 0xc6, 0xc8, 0xc9, 0xce, 0xd3, 0xd5, 0xd6, 0xd6, 0xd4, 0xd1, 0xcd, + 0xca, 0xc5, 0xbe, 0xb9, 0xb8, 0xb8, 0xb7, 0xb6, 0xbb, 0xc0, 0xc4, 0xc8, + 0xc7, 0xc1, 0xbc, 0xba, 0xb9, 0xb5, 0xaf, 0xac, 0xab, 0xad, 0xb1, 0xb2, + 0xb0, 0xae, 0xb1, 0xbb, 0xb7, 0xa3, 0xa3, 0xb4, 0xb1, 0x91, 0x91, 0x9b, + 0xa9, 0xae, 0xa2, 0x93, 0x93, 0x96, 0x67, 0x58, 0x82, 0xa2, 0xb0, 0xb9, + 0xc0, 0xc3, 0xc3, 0xc4, 0xc7, 0xc7, 0xc3, 0xc1, 0xbe, 0xb9, 0xb8, 0xb8, + 0xb9, 0xb9, 0xb9, 0xb7, 0xb8, 0xb9, 0xb9, 0xb7, 0xb6, 0xb9, 0xbc, 0xbd, + 0xbd, 0xc0, 0xc5, 0xc8, 0xcb, 0xcf, 0xd6, 0xd8, 0xd9, 0xda, 0xd7, 0xcd, + 0xc4, 0xc2, 0xc3, 0xc5, 0xc6, 0xc9, 0xc7, 0xc6, 0xc3, 0xc2, 0xc0, 0xbe, + 0xbf, 0xbf, 0xbc, 0xbb, 0xb8, 0xb7, 0xb5, 0xb3, 0xb8, 0xba, 0xb5, 0xa6, + 0x94, 0x8e, 0x89, 0x84, 0x7f, 0x74, 0x63, 0x62, 0x6c, 0x6f, 0x67, 0x60, + 0x63, 0x64, 0x65, 0x69, 0x6d, 0x72, 0x7c, 0x81, 0x83, 0x84, 0x81, 0x80, + 0x7d, 0x75, 0x6a, 0x62, 0x5b, 0x57, 0x53, 0x52, 0x49, 0x44, 0x48, 0x59, + 0x71, 0x73, 0x6f, 0x6e, 0x6f, 0x72, 0x72, 0x71, 0x72, 0x72, 0x71, 0x70, + 0x70, 0x6f, 0x6e, 0x6a, 0x63, 0x60, 0x5d, 0x5b, 0x57, 0x56, 0x59, 0x5e, + 0x67, 0x76, 0x81, 0x87, 0x89, 0x8a, 0x8c, 0x91, 0x95, 0x97, 0x97, 0x96, + 0x98, 0x98, 0x97, 0x96, 0x96, 0x96, 0x97, 0x96, 0x96, 0x95, 0x94, 0x92, + 0x90, 0x8f, 0x8d, 0x8a, 0x86, 0x83, 0x80, 0x7b, 0x76, 0x70, 0x6c, 0x69, + 0x65, 0x60, 0x5d, 0x59, 0x57, 0x53, 0x4d, 0x46, 0x43, 0x42, 0x3f, 0x3b, + 0x35, 0x30, 0x2c, 0x27, 0x20, 0x1b, 0x19, 0x18, 0x15, 0x12, 0x11, 0x12, + 0x13, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x13, 0x98, 0x92, 0x8c, 0x87, + 0x7f, 0x75, 0x69, 0x63, 0x60, 0x5d, 0x5a, 0x5a, 0x5a, 0x59, 0x59, 0x5a, + 0x5a, 0x5b, 0x5b, 0x5a, 0x58, 0x58, 0x58, 0x58, 0x59, 0x59, 0x5b, 0x5c, + 0x5c, 0x5c, 0x5f, 0x5f, 0x62, 0x63, 0x64, 0x66, 0x67, 0x6a, 0x6a, 0x6b, + 0x6d, 0x6e, 0x6f, 0x6f, 0x6f, 0x6e, 0x6c, 0x69, 0x68, 0x68, 0x66, 0x64, + 0x63, 0x62, 0x63, 0x61, 0x5f, 0x60, 0x61, 0x6b, 0x82, 0x98, 0xa3, 0xa9, + 0xae, 0xb1, 0xb3, 0xb7, 0xbc, 0xbf, 0xc2, 0xc4, 0xc5, 0xc6, 0xc7, 0xc9, + 0xce, 0xd2, 0xd4, 0xd5, 0xd5, 0xd4, 0xd2, 0xcf, 0xcb, 0xc5, 0xbe, 0xb9, + 0xb8, 0xb8, 0xb7, 0xb6, 0xbb, 0xc2, 0xc7, 0xcc, 0xcb, 0xc5, 0xbf, 0xbd, + 0xbb, 0xb6, 0xb0, 0xae, 0xad, 0xae, 0xb0, 0xb2, 0xb1, 0xaf, 0xaf, 0xb6, + 0xba, 0xa5, 0x9b, 0x9b, 0x97, 0x93, 0xaa, 0xb5, 0xb1, 0xa6, 0xa4, 0x9a, + 0x8d, 0x73, 0x56, 0x75, 0x8d, 0xac, 0xb9, 0xbe, 0xc2, 0xc7, 0xca, 0xcb, + 0xc9, 0xc8, 0xc4, 0xc1, 0xbe, 0xba, 0xb8, 0xb9, 0xba, 0xba, 0xba, 0xb8, + 0xba, 0xba, 0xb9, 0xb7, 0xb7, 0xba, 0xbf, 0xc0, 0xbe, 0xbf, 0xc5, 0xc7, + 0xc8, 0xca, 0xce, 0xd3, 0xda, 0xdd, 0xdd, 0xd3, 0xc4, 0xbf, 0xbf, 0xc4, + 0xc6, 0xca, 0xc9, 0xc7, 0xc5, 0xc3, 0xc1, 0xc0, 0xc0, 0xc0, 0xbc, 0xb9, + 0xb8, 0xb8, 0xb5, 0xb2, 0xb3, 0xb2, 0xad, 0x9f, 0x92, 0x8e, 0x87, 0x81, + 0x7c, 0x74, 0x63, 0x61, 0x6c, 0x6f, 0x69, 0x61, 0x62, 0x67, 0x6a, 0x6e, + 0x6f, 0x72, 0x79, 0x7e, 0x83, 0x84, 0x83, 0x86, 0x86, 0x81, 0x71, 0x66, + 0x60, 0x5b, 0x54, 0x51, 0x48, 0x45, 0x48, 0x57, 0x6f, 0x72, 0x6c, 0x6b, + 0x6e, 0x74, 0x76, 0x78, 0x79, 0x7a, 0x78, 0x74, 0x71, 0x70, 0x6e, 0x69, + 0x62, 0x5e, 0x5c, 0x5a, 0x57, 0x55, 0x59, 0x5e, 0x66, 0x74, 0x7e, 0x83, + 0x87, 0x89, 0x8b, 0x91, 0x95, 0x97, 0x97, 0x98, 0x9a, 0x9a, 0x99, 0x99, + 0x98, 0x97, 0x98, 0x97, 0x96, 0x96, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8d, + 0x88, 0x86, 0x84, 0x7f, 0x78, 0x73, 0x6e, 0x6b, 0x67, 0x64, 0x61, 0x5e, + 0x5b, 0x56, 0x52, 0x4c, 0x4a, 0x48, 0x46, 0x43, 0x3e, 0x39, 0x36, 0x31, + 0x2a, 0x25, 0x24, 0x23, 0x1f, 0x18, 0x15, 0x15, 0x14, 0x13, 0x14, 0x14, + 0x13, 0x13, 0x14, 0x14, 0x9c, 0x95, 0x8e, 0x8a, 0x83, 0x78, 0x6c, 0x65, + 0x62, 0x5e, 0x5b, 0x5a, 0x59, 0x59, 0x59, 0x5a, 0x5a, 0x59, 0x59, 0x5a, + 0x59, 0x58, 0x58, 0x58, 0x59, 0x59, 0x5b, 0x5a, 0x5a, 0x5c, 0x5e, 0x60, + 0x62, 0x63, 0x64, 0x67, 0x68, 0x69, 0x6a, 0x6a, 0x6c, 0x6d, 0x6f, 0x6f, + 0x6f, 0x6c, 0x6b, 0x69, 0x68, 0x68, 0x66, 0x64, 0x62, 0x61, 0x61, 0x60, + 0x5e, 0x5f, 0x62, 0x6f, 0x87, 0x9c, 0xa8, 0xad, 0xb1, 0xb2, 0xb4, 0xb9, + 0xbe, 0xc1, 0xc4, 0xc5, 0xc5, 0xc6, 0xc7, 0xc9, 0xcd, 0xd1, 0xd3, 0xd4, + 0xd3, 0xd4, 0xd2, 0xce, 0xcb, 0xc6, 0xbf, 0xbb, 0xb7, 0xb6, 0xb7, 0xb6, + 0xba, 0xc2, 0xc8, 0xce, 0xcf, 0xca, 0xc3, 0xbf, 0xbc, 0xb7, 0xb2, 0xaf, + 0xaf, 0xaf, 0xb1, 0xb2, 0xb1, 0xaf, 0xaf, 0xb4, 0xba, 0xb7, 0xa8, 0x8d, + 0x91, 0x96, 0x92, 0x94, 0x9e, 0xa0, 0x8d, 0x7b, 0x6c, 0x5a, 0x6e, 0x82, + 0x97, 0xb1, 0xbc, 0xc1, 0xc3, 0xc6, 0xca, 0xca, 0xc9, 0xc8, 0xc0, 0xbd, + 0xbc, 0xbb, 0xba, 0xb9, 0xba, 0xba, 0xb9, 0xb7, 0xb9, 0xb9, 0xb9, 0xb9, + 0xb9, 0xbd, 0xc2, 0xc2, 0xbf, 0xbf, 0xc1, 0xc3, 0xc4, 0xc2, 0xc3, 0xce, + 0xd9, 0xdd, 0xdc, 0xd8, 0xc9, 0xc1, 0xc0, 0xc3, 0xc5, 0xc7, 0xc8, 0xc7, + 0xc6, 0xc4, 0xc2, 0xc1, 0xc1, 0xc0, 0xbb, 0xba, 0xba, 0xb9, 0xb6, 0xb0, + 0xac, 0xa9, 0xa4, 0x9a, 0x92, 0x8f, 0x88, 0x84, 0x81, 0x79, 0x6a, 0x64, + 0x6a, 0x6d, 0x6a, 0x66, 0x65, 0x6a, 0x6e, 0x70, 0x72, 0x76, 0x7b, 0x7f, + 0x85, 0x86, 0x88, 0x90, 0x92, 0x8b, 0x7a, 0x6c, 0x67, 0x63, 0x59, 0x52, + 0x47, 0x45, 0x48, 0x55, 0x6d, 0x6f, 0x69, 0x69, 0x70, 0x78, 0x7d, 0x80, + 0x81, 0x83, 0x80, 0x7b, 0x76, 0x74, 0x71, 0x6a, 0x61, 0x5c, 0x59, 0x57, + 0x56, 0x54, 0x57, 0x5d, 0x66, 0x72, 0x7b, 0x80, 0x84, 0x87, 0x8b, 0x8f, + 0x95, 0x99, 0x9b, 0x9b, 0x9d, 0x9d, 0x9c, 0x9c, 0x9b, 0x9a, 0x99, 0x99, + 0x98, 0x96, 0x95, 0x94, 0x93, 0x92, 0x91, 0x8f, 0x8b, 0x89, 0x87, 0x83, + 0x7d, 0x78, 0x73, 0x6f, 0x6b, 0x67, 0x65, 0x62, 0x60, 0x5c, 0x59, 0x54, + 0x51, 0x4f, 0x4d, 0x49, 0x44, 0x42, 0x3f, 0x3a, 0x33, 0x2f, 0x2e, 0x2d, + 0x2a, 0x24, 0x1e, 0x1b, 0x19, 0x16, 0x14, 0x14, 0x13, 0x13, 0x12, 0x12, + 0x9d, 0x95, 0x8f, 0x8a, 0x84, 0x79, 0x6d, 0x67, 0x64, 0x5f, 0x5c, 0x5a, + 0x5a, 0x5a, 0x5a, 0x5a, 0x5b, 0x5a, 0x5a, 0x59, 0x5a, 0x59, 0x59, 0x5a, + 0x5a, 0x5a, 0x5b, 0x5a, 0x59, 0x5a, 0x5e, 0x61, 0x63, 0x64, 0x65, 0x67, + 0x67, 0x69, 0x69, 0x6a, 0x6d, 0x6e, 0x6e, 0x6e, 0x6e, 0x6c, 0x6b, 0x69, + 0x68, 0x68, 0x66, 0x64, 0x62, 0x61, 0x61, 0x60, 0x5e, 0x60, 0x64, 0x71, + 0x8b, 0x9f, 0xaa, 0xae, 0xb2, 0xb2, 0xb5, 0xb9, 0xbe, 0xc0, 0xc3, 0xc4, + 0xc5, 0xc5, 0xc6, 0xc9, 0xcd, 0xd0, 0xd2, 0xd3, 0xd2, 0xd3, 0xd1, 0xcf, + 0xcd, 0xc7, 0xc1, 0xbd, 0xb9, 0xb7, 0xb6, 0xb5, 0xb9, 0xc1, 0xc7, 0xcd, + 0xd0, 0xcd, 0xc7, 0xc2, 0xbd, 0xba, 0xb6, 0xb2, 0xaf, 0xaf, 0xb2, 0xb4, + 0xb2, 0xb0, 0xb0, 0xb4, 0xb7, 0xc0, 0xb9, 0x99, 0x79, 0x79, 0x7a, 0x7a, + 0x7c, 0x80, 0x5b, 0x4c, 0x52, 0x69, 0x79, 0x84, 0xa7, 0xb7, 0xbc, 0xc1, + 0xc5, 0xc6, 0xc5, 0xc7, 0xc9, 0xc7, 0xbf, 0xbd, 0xbc, 0xba, 0xba, 0xb9, + 0xb8, 0xb9, 0xb9, 0xb8, 0xb7, 0xba, 0xba, 0xba, 0xba, 0xbe, 0xc2, 0xc3, + 0xc0, 0xbe, 0xbf, 0xc1, 0xc0, 0xbd, 0xbc, 0xcb, 0xd8, 0xdb, 0xdb, 0xd9, + 0xcf, 0xc7, 0xc4, 0xc4, 0xc5, 0xc7, 0xc9, 0xc9, 0xc8, 0xc4, 0xc2, 0xc1, + 0xc0, 0xbf, 0xbd, 0xba, 0xbb, 0xbb, 0xb7, 0xaf, 0xa8, 0xa3, 0x9f, 0x97, + 0x93, 0x8f, 0x8b, 0x89, 0x86, 0x7d, 0x6e, 0x69, 0x6b, 0x6c, 0x6b, 0x68, + 0x68, 0x6b, 0x6e, 0x71, 0x74, 0x7a, 0x7e, 0x82, 0x89, 0x8c, 0x8c, 0x8f, + 0x90, 0x8e, 0x83, 0x73, 0x6e, 0x68, 0x5d, 0x51, 0x46, 0x44, 0x47, 0x54, + 0x6b, 0x6d, 0x65, 0x65, 0x6d, 0x77, 0x7f, 0x84, 0x86, 0x89, 0x87, 0x83, + 0x7d, 0x79, 0x74, 0x6b, 0x61, 0x5a, 0x58, 0x56, 0x55, 0x53, 0x57, 0x5c, + 0x66, 0x70, 0x79, 0x7e, 0x81, 0x84, 0x89, 0x8f, 0x95, 0x9a, 0x9c, 0x9d, + 0x9f, 0x9f, 0x9d, 0x9d, 0x9d, 0x9b, 0x99, 0x99, 0x99, 0x98, 0x96, 0x96, + 0x95, 0x94, 0x91, 0x8f, 0x8e, 0x8c, 0x8b, 0x87, 0x80, 0x7b, 0x77, 0x73, + 0x6f, 0x6a, 0x67, 0x64, 0x62, 0x60, 0x5c, 0x59, 0x56, 0x54, 0x51, 0x4c, + 0x49, 0x46, 0x44, 0x3f, 0x38, 0x35, 0x34, 0x33, 0x31, 0x2c, 0x27, 0x23, + 0x20, 0x1d, 0x19, 0x17, 0x15, 0x14, 0x12, 0x12, 0x9d, 0x95, 0x8f, 0x8b, + 0x83, 0x79, 0x6d, 0x68, 0x64, 0x60, 0x5c, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, + 0x5b, 0x5b, 0x5a, 0x59, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5b, 0x5a, + 0x5a, 0x5a, 0x5d, 0x61, 0x63, 0x64, 0x65, 0x67, 0x67, 0x69, 0x6a, 0x6a, + 0x6d, 0x6e, 0x6e, 0x6d, 0x6d, 0x6b, 0x6b, 0x69, 0x68, 0x67, 0x65, 0x64, + 0x62, 0x62, 0x61, 0x60, 0x5f, 0x60, 0x65, 0x73, 0x8d, 0xa0, 0xaa, 0xae, + 0xb1, 0xb3, 0xb6, 0xba, 0xbe, 0xc1, 0xc3, 0xc4, 0xc4, 0xc5, 0xc6, 0xc9, + 0xcd, 0xd0, 0xd2, 0xd2, 0xd1, 0xd3, 0xd2, 0xd0, 0xce, 0xc8, 0xc2, 0xbe, + 0xb9, 0xb7, 0xb5, 0xb4, 0xb8, 0xc0, 0xc6, 0xce, 0xd1, 0xce, 0xc8, 0xc4, + 0xbe, 0xbb, 0xb7, 0xb3, 0xb1, 0xb0, 0xb2, 0xb4, 0xb2, 0xb1, 0xb1, 0xb4, + 0xb5, 0xbf, 0xbe, 0xa8, 0x7b, 0x6e, 0x6e, 0x6c, 0x69, 0x6f, 0x52, 0x48, + 0x55, 0x79, 0x86, 0x8f, 0xb0, 0xba, 0xbc, 0xc0, 0xc7, 0xc6, 0xc4, 0xc5, + 0xc8, 0xc6, 0xbf, 0xbd, 0xbc, 0xba, 0xba, 0xb9, 0xb8, 0xb8, 0xb9, 0xb9, + 0xb7, 0xb9, 0xba, 0xba, 0xba, 0xbe, 0xc2, 0xc3, 0xc1, 0xbd, 0xbf, 0xbf, + 0xbe, 0xba, 0xbb, 0xcb, 0xd6, 0xd9, 0xd9, 0xd9, 0xd2, 0xcb, 0xc8, 0xc5, + 0xc6, 0xc7, 0xc9, 0xca, 0xc8, 0xc5, 0xc2, 0xc1, 0xc0, 0xc0, 0xbd, 0xbb, + 0xbb, 0xbb, 0xb7, 0xaf, 0xa6, 0xa2, 0x9d, 0x97, 0x92, 0x8f, 0x8d, 0x8c, + 0x88, 0x7f, 0x71, 0x6a, 0x6b, 0x6c, 0x6b, 0x6a, 0x69, 0x6b, 0x6e, 0x73, + 0x76, 0x7d, 0x82, 0x86, 0x8b, 0x8e, 0x8c, 0x8d, 0x8d, 0x8d, 0x85, 0x79, + 0x72, 0x6d, 0x61, 0x53, 0x48, 0x43, 0x45, 0x52, 0x69, 0x6b, 0x63, 0x63, + 0x6a, 0x75, 0x7e, 0x84, 0x87, 0x89, 0x89, 0x86, 0x81, 0x7c, 0x76, 0x6c, + 0x60, 0x5a, 0x57, 0x55, 0x54, 0x52, 0x56, 0x5b, 0x65, 0x6f, 0x78, 0x7d, + 0x7f, 0x82, 0x88, 0x8f, 0x95, 0x9a, 0x9c, 0x9d, 0xa0, 0xa0, 0x9e, 0x9e, + 0x9d, 0x9c, 0x9a, 0x9a, 0x9a, 0x9a, 0x97, 0x97, 0x96, 0x94, 0x92, 0x90, + 0x8f, 0x8d, 0x8c, 0x88, 0x82, 0x7d, 0x79, 0x75, 0x70, 0x6c, 0x69, 0x66, + 0x65, 0x62, 0x5f, 0x5c, 0x58, 0x56, 0x54, 0x4f, 0x4c, 0x49, 0x47, 0x42, + 0x3c, 0x38, 0x37, 0x37, 0x36, 0x32, 0x2d, 0x29, 0x27, 0x24, 0x1e, 0x1a, + 0x17, 0x15, 0x13, 0x12, 0x9c, 0x93, 0x8e, 0x8a, 0x83, 0x79, 0x6d, 0x68, + 0x64, 0x60, 0x5c, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x59, + 0x59, 0x5a, 0x5a, 0x5a, 0x59, 0x5b, 0x5b, 0x5a, 0x5a, 0x5a, 0x5d, 0x60, + 0x62, 0x63, 0x64, 0x65, 0x66, 0x68, 0x69, 0x6a, 0x6c, 0x6e, 0x6e, 0x6d, + 0x6d, 0x6c, 0x6b, 0x69, 0x68, 0x67, 0x64, 0x64, 0x63, 0x62, 0x61, 0x5f, + 0x5f, 0x61, 0x66, 0x75, 0x8e, 0xa2, 0xab, 0xb0, 0xb2, 0xb4, 0xb7, 0xbb, + 0xbf, 0xc1, 0xc3, 0xc4, 0xc4, 0xc5, 0xc6, 0xc9, 0xce, 0xd0, 0xd1, 0xd1, + 0xd1, 0xd2, 0xd3, 0xd1, 0xcf, 0xca, 0xc4, 0xc0, 0xbb, 0xb9, 0xb6, 0xb4, + 0xb7, 0xbe, 0xc5, 0xce, 0xd2, 0xcf, 0xc9, 0xc5, 0xc0, 0xbc, 0xb8, 0xb6, + 0xb4, 0xb1, 0xb1, 0xb4, 0xb2, 0xb1, 0xb1, 0xb5, 0xb4, 0xb6, 0xba, 0xbb, + 0xa1, 0x7c, 0x6b, 0x65, 0x63, 0x6d, 0x73, 0x73, 0x7a, 0x91, 0xa3, 0xaa, + 0xb6, 0xba, 0xbc, 0xbe, 0xc6, 0xc5, 0xc4, 0xc4, 0xc6, 0xc5, 0xbf, 0xbd, + 0xbb, 0xba, 0xba, 0xb8, 0xb8, 0xb9, 0xba, 0xb9, 0xb7, 0xb7, 0xb8, 0xb8, + 0xb9, 0xbc, 0xc1, 0xc2, 0xc1, 0xbe, 0xbe, 0xbe, 0xbc, 0xbb, 0xbe, 0xca, + 0xd2, 0xd5, 0xd6, 0xd9, 0xd5, 0xcf, 0xcc, 0xc8, 0xc7, 0xc8, 0xc9, 0xc9, + 0xc8, 0xc4, 0xc2, 0xc1, 0xc1, 0xc0, 0xc0, 0xbc, 0xbc, 0xbb, 0xb5, 0xad, + 0xa4, 0xa1, 0x9d, 0x97, 0x93, 0x92, 0x91, 0x8e, 0x8a, 0x80, 0x73, 0x6c, + 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6d, 0x6f, 0x75, 0x79, 0x81, 0x87, 0x8a, + 0x8d, 0x8c, 0x88, 0x89, 0x8a, 0x89, 0x84, 0x7d, 0x79, 0x74, 0x67, 0x56, + 0x4d, 0x45, 0x44, 0x50, 0x65, 0x67, 0x5f, 0x5f, 0x67, 0x73, 0x7c, 0x80, + 0x83, 0x88, 0x89, 0x87, 0x82, 0x7e, 0x79, 0x6d, 0x60, 0x58, 0x55, 0x54, + 0x53, 0x50, 0x54, 0x5a, 0x64, 0x6e, 0x76, 0x7b, 0x7e, 0x80, 0x87, 0x8e, + 0x96, 0x9a, 0x9c, 0x9d, 0xa0, 0xa1, 0xa0, 0x9f, 0x9f, 0x9d, 0x9b, 0x9b, + 0x9b, 0x9a, 0x98, 0x97, 0x96, 0x96, 0x94, 0x92, 0x90, 0x8e, 0x8d, 0x8a, + 0x86, 0x80, 0x7b, 0x78, 0x73, 0x6f, 0x6d, 0x6b, 0x69, 0x66, 0x63, 0x5f, + 0x5d, 0x5c, 0x58, 0x54, 0x51, 0x4f, 0x4c, 0x47, 0x41, 0x3f, 0x3d, 0x3c, + 0x3c, 0x39, 0x36, 0x33, 0x32, 0x2f, 0x29, 0x22, 0x1d, 0x1a, 0x16, 0x13, + 0x9b, 0x93, 0x8c, 0x88, 0x83, 0x79, 0x6e, 0x68, 0x65, 0x61, 0x5d, 0x5a, + 0x5a, 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5b, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, + 0x5a, 0x5b, 0x5b, 0x5a, 0x5a, 0x5b, 0x5d, 0x60, 0x60, 0x61, 0x62, 0x64, + 0x65, 0x66, 0x68, 0x6a, 0x6d, 0x6e, 0x6e, 0x6e, 0x6e, 0x6c, 0x6b, 0x6a, + 0x69, 0x66, 0x64, 0x64, 0x63, 0x62, 0x60, 0x5f, 0x5f, 0x61, 0x67, 0x77, + 0x90, 0xa4, 0xad, 0xb1, 0xb4, 0xb5, 0xb8, 0xbc, 0xbf, 0xc1, 0xc2, 0xc4, + 0xc4, 0xc5, 0xc7, 0xc9, 0xcd, 0xd0, 0xcf, 0xce, 0xcf, 0xd2, 0xd3, 0xd2, + 0xd0, 0xcd, 0xc6, 0xc1, 0xbd, 0xba, 0xb7, 0xb3, 0xb5, 0xbb, 0xc2, 0xcd, + 0xd2, 0xd0, 0xcb, 0xc7, 0xc2, 0xbe, 0xba, 0xb7, 0xb5, 0xb1, 0xb2, 0xb3, + 0xb2, 0xb1, 0xb0, 0xb3, 0xb4, 0xb0, 0xb2, 0xba, 0xbd, 0xb0, 0x9c, 0x91, + 0x88, 0x8b, 0x98, 0xa3, 0xab, 0xb3, 0xb7, 0xb4, 0xb3, 0xb7, 0xb9, 0xbc, + 0xc1, 0xc0, 0xc2, 0xc3, 0xc3, 0xc3, 0xc0, 0xbd, 0xbc, 0xba, 0xba, 0xb8, + 0xb8, 0xb9, 0xbb, 0xba, 0xb8, 0xb7, 0xb7, 0xb6, 0xb7, 0xbb, 0xc0, 0xc2, + 0xc3, 0xc0, 0xbd, 0xbc, 0xbd, 0xbe, 0xc4, 0xc9, 0xce, 0xd0, 0xd3, 0xd9, + 0xda, 0xd5, 0xd1, 0xcc, 0xc9, 0xc8, 0xc9, 0xc9, 0xc8, 0xc4, 0xc1, 0xc1, + 0xc2, 0xc2, 0xc2, 0xbe, 0xbd, 0xba, 0xb4, 0xab, 0xa1, 0x9e, 0x9c, 0x97, + 0x93, 0x96, 0x97, 0x93, 0x8d, 0x82, 0x75, 0x6e, 0x6d, 0x6e, 0x6e, 0x6e, + 0x6e, 0x6f, 0x71, 0x74, 0x78, 0x81, 0x85, 0x86, 0x87, 0x84, 0x81, 0x85, + 0x86, 0x83, 0x81, 0x7f, 0x80, 0x7c, 0x6f, 0x56, 0x4e, 0x48, 0x46, 0x4d, + 0x62, 0x64, 0x5c, 0x5a, 0x63, 0x6e, 0x77, 0x7c, 0x7f, 0x83, 0x86, 0x86, + 0x82, 0x80, 0x7a, 0x6e, 0x60, 0x57, 0x54, 0x53, 0x52, 0x50, 0x54, 0x59, + 0x62, 0x6c, 0x73, 0x78, 0x7b, 0x7e, 0x86, 0x8f, 0x97, 0x9c, 0x9d, 0x9f, + 0xa2, 0xa3, 0xa3, 0xa2, 0xa1, 0x9f, 0x9e, 0x9d, 0x9c, 0x9c, 0x9b, 0x98, + 0x97, 0x97, 0x96, 0x94, 0x91, 0x8f, 0x8f, 0x8d, 0x89, 0x83, 0x7f, 0x7c, + 0x77, 0x73, 0x71, 0x6e, 0x6d, 0x6a, 0x68, 0x64, 0x62, 0x60, 0x5e, 0x5a, + 0x58, 0x55, 0x53, 0x4e, 0x48, 0x46, 0x45, 0x44, 0x42, 0x3f, 0x3e, 0x3b, + 0x39, 0x36, 0x32, 0x2d, 0x27, 0x24, 0x1e, 0x18, 0x99, 0x91, 0x8c, 0x87, + 0x81, 0x77, 0x6e, 0x68, 0x65, 0x61, 0x5c, 0x5a, 0x59, 0x59, 0x5a, 0x5b, + 0x5b, 0x5b, 0x5b, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5b, 0x5c, 0x5b, + 0x5b, 0x5d, 0x5d, 0x5e, 0x60, 0x61, 0x62, 0x64, 0x65, 0x65, 0x66, 0x69, + 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6d, 0x6b, 0x69, 0x68, 0x66, 0x64, 0x64, + 0x63, 0x62, 0x60, 0x5f, 0x5f, 0x61, 0x67, 0x78, 0x92, 0xa6, 0xaf, 0xb3, + 0xb5, 0xb6, 0xb9, 0xbb, 0xbe, 0xbf, 0xc1, 0xc3, 0xc5, 0xc7, 0xc8, 0xca, + 0xcd, 0xcf, 0xcf, 0xcf, 0xcf, 0xd3, 0xd3, 0xd2, 0xd2, 0xd0, 0xca, 0xc5, + 0xc1, 0xbe, 0xba, 0xb5, 0xb4, 0xba, 0xc0, 0xca, 0xd1, 0xd1, 0xcf, 0xcb, + 0xc4, 0xbf, 0xbb, 0xb8, 0xb7, 0xb3, 0xb2, 0xb3, 0xb4, 0xb2, 0xb2, 0xb4, + 0xb5, 0xb2, 0xb1, 0xb2, 0xba, 0xbe, 0xbd, 0xbc, 0xba, 0xba, 0xba, 0xb7, + 0xb5, 0xb3, 0xb6, 0xb5, 0xb2, 0xb4, 0xb6, 0xb8, 0xbc, 0xbd, 0xbe, 0xc0, + 0xc2, 0xc2, 0xc1, 0xbf, 0xbd, 0xba, 0xb8, 0xb8, 0xb8, 0xb8, 0xba, 0xbc, + 0xbb, 0xb9, 0xb8, 0xb7, 0xb7, 0xbb, 0xbf, 0xc2, 0xc3, 0xc0, 0xbe, 0xbe, + 0xc0, 0xc4, 0xcb, 0xce, 0xce, 0xcf, 0xd3, 0xd8, 0xda, 0xd8, 0xd5, 0xd1, + 0xcc, 0xc9, 0xc9, 0xc8, 0xc7, 0xc3, 0xc1, 0xc1, 0xc1, 0xc3, 0xc4, 0xc2, + 0xbe, 0xbb, 0xb3, 0xa7, 0x9e, 0x9b, 0x9a, 0x98, 0x95, 0x98, 0x99, 0x96, + 0x91, 0x84, 0x75, 0x6d, 0x6e, 0x6f, 0x6e, 0x6d, 0x6f, 0x71, 0x72, 0x73, + 0x77, 0x80, 0x84, 0x82, 0x7c, 0x79, 0x79, 0x81, 0x83, 0x7f, 0x7e, 0x81, + 0x81, 0x80, 0x77, 0x5b, 0x4f, 0x4c, 0x4b, 0x4c, 0x5d, 0x64, 0x5b, 0x5a, + 0x61, 0x6b, 0x73, 0x76, 0x79, 0x7d, 0x82, 0x84, 0x82, 0x7f, 0x79, 0x6e, + 0x61, 0x58, 0x55, 0x53, 0x50, 0x4e, 0x52, 0x58, 0x61, 0x6b, 0x71, 0x75, + 0x78, 0x7d, 0x85, 0x8f, 0x97, 0x9d, 0xa0, 0xa2, 0xa4, 0xa3, 0xa4, 0xa3, + 0xa1, 0xa1, 0x9f, 0x9f, 0x9e, 0x9e, 0x9c, 0x9b, 0x9a, 0x99, 0x97, 0x95, + 0x93, 0x91, 0x90, 0x8f, 0x8b, 0x84, 0x81, 0x7f, 0x7b, 0x76, 0x73, 0x70, + 0x6f, 0x6d, 0x6b, 0x69, 0x65, 0x64, 0x62, 0x5f, 0x5d, 0x5b, 0x59, 0x55, + 0x50, 0x4c, 0x4b, 0x4a, 0x48, 0x46, 0x45, 0x43, 0x41, 0x3d, 0x38, 0x35, + 0x32, 0x2f, 0x29, 0x21, 0x97, 0x90, 0x8a, 0x86, 0x7e, 0x76, 0x6e, 0x68, + 0x65, 0x60, 0x5b, 0x5b, 0x59, 0x59, 0x5a, 0x5b, 0x5a, 0x5a, 0x5a, 0x5b, + 0x5b, 0x5b, 0x5a, 0x59, 0x59, 0x5b, 0x5b, 0x5a, 0x5b, 0x5d, 0x5e, 0x5e, + 0x5e, 0x5f, 0x61, 0x63, 0x64, 0x64, 0x65, 0x68, 0x6b, 0x6b, 0x6b, 0x6c, + 0x6b, 0x6b, 0x69, 0x68, 0x66, 0x66, 0x64, 0x64, 0x63, 0x61, 0x5f, 0x5f, + 0x61, 0x62, 0x68, 0x7a, 0x93, 0xa7, 0xb0, 0xb4, 0xb5, 0xb6, 0xb9, 0xbb, + 0xbe, 0xbf, 0xc1, 0xc3, 0xc6, 0xc8, 0xca, 0xcb, 0xce, 0xcf, 0xd0, 0xd0, + 0xd1, 0xd2, 0xd4, 0xd4, 0xd3, 0xd1, 0xcd, 0xc8, 0xc4, 0xc1, 0xbd, 0xb7, + 0xb5, 0xba, 0xbf, 0xc9, 0xd1, 0xd2, 0xd0, 0xcc, 0xc5, 0xbf, 0xbc, 0xba, + 0xb8, 0xb4, 0xb2, 0xb4, 0xb5, 0xb4, 0xb2, 0xb4, 0xb7, 0xb6, 0xb3, 0xb0, + 0xb4, 0xba, 0xbf, 0xc1, 0xc2, 0xc0, 0xbd, 0xb7, 0xaf, 0xa6, 0xb1, 0xb4, + 0xb3, 0xb6, 0xb7, 0xb8, 0xba, 0xbc, 0xbf, 0xc1, 0xc2, 0xc1, 0xbf, 0xbd, + 0xbb, 0xb9, 0xb6, 0xb8, 0xb7, 0xb8, 0xb9, 0xbc, 0xbd, 0xbb, 0xba, 0xb8, + 0xb8, 0xbb, 0xbf, 0xc2, 0xc3, 0xc1, 0xc0, 0xc1, 0xc4, 0xca, 0xd0, 0xd1, + 0xd0, 0xd0, 0xd2, 0xd7, 0xd9, 0xd8, 0xd7, 0xd3, 0xcd, 0xc9, 0xc9, 0xc8, + 0xc6, 0xc3, 0xc1, 0xc1, 0xc2, 0xc3, 0xc6, 0xc3, 0xbe, 0xb9, 0xb1, 0xa5, + 0x9c, 0x98, 0x97, 0x96, 0x94, 0x98, 0x9b, 0x98, 0x92, 0x85, 0x75, 0x6f, + 0x6f, 0x6f, 0x6d, 0x6b, 0x6d, 0x72, 0x73, 0x74, 0x79, 0x81, 0x85, 0x82, + 0x78, 0x73, 0x76, 0x7e, 0x81, 0x80, 0x7f, 0x81, 0x7f, 0x7e, 0x79, 0x60, + 0x4f, 0x4f, 0x4e, 0x4d, 0x5b, 0x64, 0x5d, 0x5b, 0x61, 0x69, 0x70, 0x72, + 0x74, 0x78, 0x80, 0x83, 0x84, 0x81, 0x78, 0x6d, 0x61, 0x59, 0x55, 0x52, + 0x4f, 0x4e, 0x50, 0x55, 0x5f, 0x69, 0x6e, 0x72, 0x77, 0x7c, 0x85, 0x90, + 0x9a, 0x9f, 0xa2, 0xa4, 0xa6, 0xa6, 0xa6, 0xa5, 0xa4, 0xa3, 0xa1, 0xa0, + 0xa0, 0xa0, 0x9e, 0x9d, 0x9c, 0x9b, 0x99, 0x98, 0x95, 0x92, 0x91, 0x8f, + 0x8c, 0x86, 0x83, 0x82, 0x7f, 0x79, 0x75, 0x73, 0x72, 0x70, 0x6f, 0x6c, + 0x68, 0x67, 0x65, 0x65, 0x61, 0x5f, 0x5d, 0x5a, 0x55, 0x51, 0x4f, 0x4e, + 0x4d, 0x4c, 0x4a, 0x4a, 0x48, 0x44, 0x3f, 0x3c, 0x3a, 0x37, 0x31, 0x27, + 0x96, 0x8e, 0x89, 0x84, 0x7d, 0x75, 0x6d, 0x67, 0x63, 0x5f, 0x5b, 0x5b, + 0x5a, 0x5a, 0x5b, 0x5b, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5b, 0x5a, 0x5a, + 0x59, 0x5b, 0x5b, 0x5b, 0x5c, 0x5d, 0x5e, 0x5d, 0x5e, 0x5f, 0x60, 0x63, + 0x64, 0x65, 0x65, 0x67, 0x6a, 0x6a, 0x6b, 0x6b, 0x6b, 0x6b, 0x69, 0x67, + 0x66, 0x65, 0x64, 0x64, 0x63, 0x61, 0x5f, 0x5e, 0x62, 0x63, 0x69, 0x7b, + 0x94, 0xa8, 0xb1, 0xb5, 0xb6, 0xb6, 0xb9, 0xbb, 0xbe, 0xbf, 0xc1, 0xc3, + 0xc6, 0xc9, 0xca, 0xcb, 0xce, 0xcf, 0xd1, 0xd1, 0xd1, 0xd3, 0xd5, 0xd4, + 0xd3, 0xd0, 0xcd, 0xc9, 0xc6, 0xc3, 0xbe, 0xb9, 0xb6, 0xba, 0xbf, 0xc8, + 0xd1, 0xd2, 0xd0, 0xcc, 0xc5, 0xbf, 0xbc, 0xba, 0xb8, 0xb4, 0xb3, 0xb4, + 0xb4, 0xb4, 0xb2, 0xb3, 0xb8, 0xb7, 0xb5, 0xb0, 0xb1, 0xb6, 0xbc, 0xbf, + 0xc1, 0xbe, 0xbc, 0xb7, 0xb0, 0xa7, 0xb0, 0xb3, 0xb3, 0xb6, 0xb7, 0xb8, + 0xb9, 0xbb, 0xbf, 0xc0, 0xc1, 0xc0, 0xbe, 0xbc, 0xba, 0xb8, 0xb6, 0xb8, + 0xb6, 0xb6, 0xb8, 0xbb, 0xbd, 0xbc, 0xbb, 0xb9, 0xb8, 0xbb, 0xc0, 0xc2, + 0xc3, 0xc1, 0xc1, 0xc3, 0xc5, 0xcc, 0xd2, 0xd2, 0xd1, 0xd0, 0xd2, 0xd6, + 0xd8, 0xd7, 0xd6, 0xd3, 0xcc, 0xc9, 0xc9, 0xc8, 0xc6, 0xc2, 0xc2, 0xc2, + 0xc2, 0xc4, 0xc6, 0xc4, 0xbe, 0xb9, 0xb1, 0xa4, 0x9b, 0x98, 0x96, 0x95, + 0x92, 0x96, 0x9b, 0x98, 0x92, 0x86, 0x75, 0x70, 0x70, 0x70, 0x6d, 0x6a, + 0x6d, 0x72, 0x74, 0x75, 0x7b, 0x82, 0x85, 0x83, 0x79, 0x73, 0x74, 0x7d, + 0x81, 0x82, 0x7f, 0x80, 0x7f, 0x7f, 0x7a, 0x62, 0x51, 0x4f, 0x4e, 0x4d, + 0x5a, 0x65, 0x5f, 0x5e, 0x63, 0x6a, 0x6f, 0x71, 0x72, 0x76, 0x7e, 0x83, + 0x83, 0x80, 0x77, 0x6c, 0x61, 0x59, 0x56, 0x52, 0x4e, 0x4e, 0x50, 0x54, + 0x5e, 0x67, 0x6d, 0x71, 0x75, 0x7b, 0x85, 0x91, 0x9b, 0xa0, 0xa3, 0xa6, + 0xa7, 0xa7, 0xa8, 0xa7, 0xa6, 0xa4, 0xa2, 0xa1, 0xa2, 0xa1, 0x9f, 0x9e, + 0x9d, 0x9c, 0x9a, 0x99, 0x97, 0x94, 0x91, 0x8f, 0x8d, 0x88, 0x84, 0x82, + 0x80, 0x7b, 0x77, 0x75, 0x74, 0x72, 0x70, 0x6e, 0x6b, 0x6a, 0x68, 0x67, + 0x64, 0x62, 0x60, 0x5d, 0x58, 0x55, 0x52, 0x51, 0x50, 0x50, 0x4d, 0x4d, + 0x4b, 0x48, 0x44, 0x40, 0x3d, 0x3b, 0x35, 0x2b, 0x94, 0x8d, 0x86, 0x81, + 0x7b, 0x73, 0x6b, 0x65, 0x62, 0x5f, 0x5c, 0x5b, 0x5c, 0x5c, 0x5c, 0x5b, + 0x5c, 0x5c, 0x5c, 0x5c, 0x5d, 0x5c, 0x5c, 0x5c, 0x5a, 0x5a, 0x5c, 0x5d, + 0x5d, 0x5d, 0x5e, 0x5d, 0x5e, 0x5e, 0x60, 0x63, 0x64, 0x65, 0x65, 0x66, + 0x69, 0x6a, 0x6b, 0x6b, 0x6c, 0x6b, 0x68, 0x66, 0x65, 0x65, 0x64, 0x63, + 0x62, 0x60, 0x5e, 0x5e, 0x62, 0x65, 0x6b, 0x7b, 0x94, 0xa8, 0xb1, 0xb5, + 0xb6, 0xb6, 0xb8, 0xbb, 0xbe, 0xbf, 0xc1, 0xc4, 0xc7, 0xc9, 0xca, 0xcd, + 0xcd, 0xcf, 0xd2, 0xd2, 0xd4, 0xd4, 0xd4, 0xd4, 0xd3, 0xcf, 0xcc, 0xca, + 0xc7, 0xc5, 0xc1, 0xba, 0xb6, 0xba, 0xbf, 0xc8, 0xd0, 0xd1, 0xce, 0xcb, + 0xc4, 0xbf, 0xbc, 0xb8, 0xb6, 0xb5, 0xb3, 0xb4, 0xb3, 0xb2, 0xb1, 0xb2, + 0xb8, 0xb9, 0xb7, 0xb3, 0xb0, 0xb2, 0xb4, 0xb6, 0xbb, 0xbb, 0xbb, 0xba, + 0xb8, 0xb5, 0xb3, 0xb3, 0xb2, 0xb5, 0xb7, 0xb8, 0xbb, 0xbc, 0xbe, 0xbf, + 0xbf, 0xbe, 0xbe, 0xbd, 0xbb, 0xb8, 0xb7, 0xb7, 0xb6, 0xb6, 0xb7, 0xba, + 0xbc, 0xbb, 0xba, 0xba, 0xbb, 0xbd, 0xc0, 0xc2, 0xc3, 0xc2, 0xc2, 0xc4, + 0xc7, 0xcd, 0xd2, 0xd2, 0xd2, 0xd1, 0xd2, 0xd5, 0xd6, 0xd6, 0xd5, 0xd2, + 0xcc, 0xca, 0xc9, 0xc8, 0xc5, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc6, 0xc3, + 0xbe, 0xb9, 0xb1, 0xa4, 0x9b, 0x97, 0x95, 0x93, 0x90, 0x94, 0x9a, 0x98, + 0x93, 0x88, 0x79, 0x72, 0x72, 0x71, 0x6e, 0x6b, 0x6d, 0x71, 0x73, 0x76, + 0x7c, 0x82, 0x85, 0x83, 0x7b, 0x73, 0x73, 0x7a, 0x80, 0x83, 0x7d, 0x7c, + 0x80, 0x80, 0x79, 0x63, 0x53, 0x4f, 0x4d, 0x4d, 0x5a, 0x65, 0x63, 0x63, + 0x68, 0x6e, 0x71, 0x71, 0x72, 0x75, 0x7d, 0x81, 0x81, 0x7f, 0x78, 0x6c, + 0x60, 0x5b, 0x57, 0x53, 0x4e, 0x4d, 0x4e, 0x52, 0x5c, 0x65, 0x6a, 0x6f, + 0x75, 0x7b, 0x86, 0x93, 0x9d, 0xa2, 0xa4, 0xa7, 0xa9, 0xaa, 0xa9, 0xa9, + 0xa7, 0xa5, 0xa4, 0xa3, 0xa3, 0xa2, 0xa0, 0xa0, 0x9e, 0x9d, 0x9b, 0x9a, + 0x97, 0x95, 0x93, 0x90, 0x8f, 0x8a, 0x86, 0x84, 0x81, 0x7d, 0x7a, 0x78, + 0x77, 0x74, 0x73, 0x70, 0x6e, 0x6d, 0x6b, 0x6a, 0x68, 0x66, 0x64, 0x61, + 0x5d, 0x5b, 0x59, 0x58, 0x57, 0x54, 0x52, 0x50, 0x4f, 0x4c, 0x49, 0x44, + 0x41, 0x3f, 0x3b, 0x32, 0x91, 0x89, 0x82, 0x7d, 0x76, 0x6e, 0x67, 0x63, + 0x61, 0x5f, 0x5c, 0x5a, 0x5c, 0x5c, 0x5c, 0x5b, 0x5c, 0x5d, 0x5d, 0x5c, + 0x5c, 0x5d, 0x5d, 0x5c, 0x5a, 0x5b, 0x5d, 0x5d, 0x5d, 0x5c, 0x5d, 0x5c, + 0x5e, 0x5f, 0x61, 0x63, 0x63, 0x64, 0x65, 0x66, 0x69, 0x69, 0x6a, 0x6b, + 0x6b, 0x6a, 0x67, 0x66, 0x66, 0x65, 0x64, 0x61, 0x60, 0x5f, 0x5f, 0x5f, + 0x63, 0x67, 0x6c, 0x7a, 0x92, 0xa6, 0xb1, 0xb4, 0xb6, 0xb6, 0xb9, 0xbb, + 0xbe, 0xbf, 0xc1, 0xc5, 0xc7, 0xc9, 0xcb, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, + 0xd5, 0xd5, 0xd5, 0xd4, 0xd3, 0xd0, 0xcd, 0xca, 0xc7, 0xc5, 0xc3, 0xbd, + 0xb8, 0xb9, 0xbd, 0xc5, 0xcf, 0xcf, 0xcc, 0xc9, 0xc3, 0xbf, 0xbb, 0xb8, + 0xb6, 0xb5, 0xb5, 0xb4, 0xb2, 0xb2, 0xb1, 0xb3, 0xb7, 0xb8, 0xb8, 0xb7, + 0xb5, 0xaf, 0xac, 0xae, 0xb5, 0xb8, 0xb9, 0xb9, 0xb8, 0xb7, 0xb3, 0xb2, + 0xb4, 0xb8, 0xba, 0xbb, 0xbd, 0xc0, 0xc0, 0xc1, 0xc1, 0xc1, 0xc3, 0xc3, + 0xc1, 0xbc, 0xba, 0xb9, 0xb9, 0xb8, 0xba, 0xbb, 0xbd, 0xbb, 0xba, 0xb9, + 0xbb, 0xbe, 0xc1, 0xc2, 0xc2, 0xc2, 0xc4, 0xc6, 0xc8, 0xcc, 0xd1, 0xd2, + 0xd2, 0xd2, 0xd2, 0xd5, 0xd5, 0xd5, 0xd5, 0xd2, 0xcf, 0xcc, 0xca, 0xc9, + 0xc7, 0xc5, 0xc4, 0xc4, 0xc3, 0xc3, 0xc3, 0xbf, 0xbb, 0xb6, 0xaf, 0xa4, + 0x9b, 0x97, 0x95, 0x91, 0x8e, 0x93, 0x99, 0x98, 0x94, 0x8c, 0x7e, 0x77, + 0x75, 0x74, 0x70, 0x6b, 0x6b, 0x6f, 0x72, 0x76, 0x7c, 0x7f, 0x81, 0x80, + 0x7a, 0x74, 0x73, 0x76, 0x7b, 0x82, 0x7b, 0x75, 0x7d, 0x7f, 0x78, 0x63, + 0x54, 0x4f, 0x4e, 0x50, 0x5b, 0x66, 0x66, 0x69, 0x70, 0x75, 0x76, 0x77, + 0x77, 0x78, 0x7f, 0x83, 0x81, 0x7e, 0x78, 0x6d, 0x63, 0x5d, 0x5a, 0x55, + 0x4f, 0x4d, 0x4d, 0x50, 0x5a, 0x63, 0x68, 0x6d, 0x74, 0x7b, 0x88, 0x95, + 0x9f, 0xa4, 0xa7, 0xaa, 0xac, 0xad, 0xac, 0xab, 0xa9, 0xa8, 0xa6, 0xa5, + 0xa4, 0xa4, 0xa3, 0xa2, 0xa0, 0x9f, 0x9d, 0x9b, 0x98, 0x97, 0x96, 0x93, + 0x91, 0x8d, 0x89, 0x86, 0x84, 0x80, 0x7e, 0x7c, 0x7b, 0x78, 0x76, 0x74, + 0x73, 0x72, 0x70, 0x6f, 0x6c, 0x6a, 0x68, 0x66, 0x63, 0x61, 0x60, 0x5f, + 0x5e, 0x5b, 0x58, 0x56, 0x55, 0x53, 0x50, 0x4d, 0x4a, 0x47, 0x43, 0x3a, + 0x8c, 0x84, 0x7d, 0x78, 0x71, 0x69, 0x63, 0x61, 0x5f, 0x5e, 0x5c, 0x5b, + 0x5b, 0x5c, 0x5c, 0x5b, 0x5c, 0x5d, 0x5d, 0x5c, 0x5c, 0x5d, 0x5d, 0x5c, + 0x5a, 0x5b, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5f, 0x5f, 0x61, 0x63, + 0x63, 0x64, 0x65, 0x66, 0x68, 0x69, 0x69, 0x6a, 0x6b, 0x69, 0x67, 0x66, + 0x65, 0x65, 0x63, 0x60, 0x5f, 0x5f, 0x5e, 0x60, 0x65, 0x67, 0x6c, 0x7a, + 0x91, 0xa4, 0xaf, 0xb3, 0xb4, 0xb6, 0xb7, 0xbb, 0xbd, 0xbe, 0xc1, 0xc5, + 0xc7, 0xc9, 0xca, 0xcd, 0xce, 0xd1, 0xd3, 0xd5, 0xd5, 0xd5, 0xd5, 0xd3, + 0xd2, 0xd1, 0xce, 0xca, 0xc7, 0xc6, 0xc5, 0xc0, 0xbb, 0xbb, 0xbd, 0xc3, + 0xcc, 0xcc, 0xca, 0xc8, 0xc4, 0xc0, 0xbb, 0xb8, 0xb7, 0xb5, 0xb4, 0xb3, + 0xb3, 0xb3, 0xb2, 0xb3, 0xb6, 0xb7, 0xb7, 0xb6, 0xb7, 0xb3, 0xb2, 0xb3, + 0xb4, 0xb5, 0xb6, 0xb6, 0xb6, 0xb3, 0xb1, 0xb4, 0xb7, 0xbb, 0xbd, 0xc0, + 0xc3, 0xc4, 0xc5, 0xc6, 0xc6, 0xc3, 0xc2, 0xc2, 0xc1, 0xbd, 0xbb, 0xbc, + 0xbc, 0xbc, 0xbb, 0xbd, 0xbe, 0xbb, 0xb9, 0xb9, 0xbc, 0xbf, 0xc1, 0xc2, + 0xc2, 0xc3, 0xc6, 0xc8, 0xc9, 0xcd, 0xd0, 0xd1, 0xd1, 0xd1, 0xd2, 0xd5, + 0xd6, 0xd5, 0xd4, 0xd1, 0xce, 0xcd, 0xcc, 0xcb, 0xc8, 0xc6, 0xc4, 0xc4, + 0xc3, 0xc1, 0xbf, 0xbc, 0xb8, 0xb4, 0xae, 0xa4, 0x9c, 0x97, 0x94, 0x90, + 0x8c, 0x91, 0x97, 0x98, 0x95, 0x8d, 0x80, 0x79, 0x76, 0x75, 0x71, 0x6c, + 0x6b, 0x6f, 0x71, 0x74, 0x7a, 0x7b, 0x7e, 0x7d, 0x77, 0x73, 0x74, 0x76, + 0x79, 0x7e, 0x7b, 0x72, 0x75, 0x76, 0x72, 0x61, 0x55, 0x51, 0x51, 0x54, + 0x60, 0x67, 0x67, 0x69, 0x73, 0x7b, 0x80, 0x81, 0x81, 0x82, 0x87, 0x89, + 0x86, 0x82, 0x7d, 0x72, 0x68, 0x60, 0x5c, 0x58, 0x50, 0x4c, 0x4c, 0x50, + 0x58, 0x60, 0x65, 0x6b, 0x74, 0x7c, 0x89, 0x97, 0xa1, 0xa7, 0xa9, 0xac, + 0xae, 0xaf, 0xae, 0xad, 0xab, 0xab, 0xaa, 0xa8, 0xa7, 0xa7, 0xa5, 0xa3, + 0xa2, 0xa1, 0x9f, 0x9c, 0x99, 0x99, 0x98, 0x96, 0x93, 0x8f, 0x8b, 0x88, + 0x87, 0x83, 0x81, 0x80, 0x7e, 0x7c, 0x7a, 0x78, 0x77, 0x77, 0x75, 0x74, + 0x72, 0x6f, 0x6d, 0x6c, 0x68, 0x66, 0x66, 0x66, 0x63, 0x61, 0x5e, 0x5d, + 0x5c, 0x5a, 0x57, 0x54, 0x50, 0x4e, 0x4a, 0x43, 0x87, 0x7f, 0x79, 0x74, + 0x6d, 0x65, 0x61, 0x5f, 0x5e, 0x5b, 0x5b, 0x5b, 0x5a, 0x5a, 0x5b, 0x5c, + 0x5d, 0x5d, 0x5d, 0x5b, 0x5b, 0x5c, 0x5d, 0x5c, 0x5b, 0x5c, 0x5d, 0x5d, + 0x5d, 0x5d, 0x5e, 0x5e, 0x5f, 0x60, 0x61, 0x63, 0x63, 0x65, 0x65, 0x66, + 0x68, 0x6a, 0x6a, 0x6b, 0x6b, 0x69, 0x68, 0x66, 0x65, 0x64, 0x63, 0x60, + 0x5f, 0x5f, 0x60, 0x60, 0x65, 0x68, 0x6c, 0x79, 0x90, 0xa3, 0xad, 0xb1, + 0xb3, 0xb5, 0xb6, 0xba, 0xbd, 0xbe, 0xc1, 0xc4, 0xc7, 0xc8, 0xca, 0xcc, + 0xce, 0xd0, 0xd3, 0xd4, 0xd5, 0xd5, 0xd4, 0xd2, 0xd2, 0xd1, 0xcf, 0xcc, + 0xc9, 0xc8, 0xc6, 0xc1, 0xbc, 0xbb, 0xbc, 0xc1, 0xc8, 0xca, 0xc8, 0xc6, + 0xc4, 0xc0, 0xbc, 0xba, 0xb8, 0xb5, 0xb4, 0xb4, 0xb5, 0xb5, 0xb4, 0xb2, + 0xb4, 0xb6, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb6, 0xb6, 0xb6, 0xb5, + 0xb3, 0xb2, 0xb3, 0xb7, 0xba, 0xbd, 0xbf, 0xc1, 0xc3, 0xc5, 0xc9, 0xcc, + 0xcc, 0xc5, 0xc1, 0xc2, 0xc0, 0xbe, 0xbd, 0xbd, 0xbe, 0xbd, 0xbc, 0xbd, + 0xbe, 0xbb, 0xba, 0xba, 0xbc, 0xbf, 0xc0, 0xc1, 0xc3, 0xc6, 0xc9, 0xcb, + 0xcc, 0xce, 0xd0, 0xd1, 0xd1, 0xd0, 0xd1, 0xd5, 0xd6, 0xd5, 0xd3, 0xd0, + 0xce, 0xce, 0xcd, 0xcc, 0xca, 0xc7, 0xc4, 0xc3, 0xc2, 0xc0, 0xbf, 0xb9, + 0xb5, 0xb2, 0xac, 0xa4, 0x9d, 0x97, 0x93, 0x8f, 0x8a, 0x90, 0x98, 0x99, + 0x95, 0x8c, 0x7f, 0x78, 0x76, 0x75, 0x72, 0x6d, 0x6c, 0x6e, 0x70, 0x72, + 0x77, 0x79, 0x7c, 0x7b, 0x75, 0x73, 0x76, 0x78, 0x7a, 0x7d, 0x7b, 0x6f, + 0x6e, 0x6f, 0x6f, 0x5f, 0x54, 0x52, 0x53, 0x57, 0x67, 0x68, 0x65, 0x67, + 0x71, 0x7c, 0x83, 0x85, 0x87, 0x8a, 0x8e, 0x8e, 0x8c, 0x88, 0x82, 0x78, + 0x6d, 0x64, 0x5f, 0x59, 0x53, 0x4d, 0x4d, 0x4e, 0x56, 0x5e, 0x63, 0x6b, + 0x75, 0x7d, 0x89, 0x97, 0xa2, 0xa9, 0xab, 0xae, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xae, 0xab, 0xab, 0xaa, 0xa9, 0xa7, 0xa5, 0xa4, 0xa2, 0xa0, 0x9d, + 0x9c, 0x9b, 0x99, 0x97, 0x95, 0x91, 0x8d, 0x8b, 0x88, 0x85, 0x83, 0x82, + 0x81, 0x7f, 0x7d, 0x7b, 0x7a, 0x79, 0x79, 0x77, 0x75, 0x72, 0x71, 0x70, + 0x6d, 0x6a, 0x6a, 0x6a, 0x67, 0x67, 0x64, 0x62, 0x61, 0x5f, 0x5d, 0x59, + 0x55, 0x53, 0x4f, 0x49, 0x83, 0x7b, 0x75, 0x71, 0x6a, 0x62, 0x5e, 0x5d, + 0x5d, 0x5b, 0x5a, 0x5b, 0x5a, 0x5a, 0x5a, 0x5d, 0x5d, 0x5d, 0x5d, 0x5c, + 0x5c, 0x5c, 0x5d, 0x5c, 0x5c, 0x5d, 0x5c, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, + 0x5f, 0x61, 0x62, 0x63, 0x63, 0x65, 0x65, 0x66, 0x68, 0x6a, 0x6a, 0x6a, + 0x6b, 0x69, 0x68, 0x67, 0x66, 0x64, 0x63, 0x60, 0x5f, 0x5f, 0x60, 0x61, + 0x66, 0x68, 0x6c, 0x77, 0x8e, 0xa1, 0xab, 0xaf, 0xb2, 0xb4, 0xb6, 0xb9, + 0xbd, 0xbf, 0xc1, 0xc5, 0xc7, 0xc8, 0xc9, 0xcb, 0xce, 0xd0, 0xd3, 0xd3, + 0xd5, 0xd4, 0xd4, 0xd3, 0xd2, 0xd1, 0xd0, 0xcc, 0xca, 0xc9, 0xc6, 0xc2, + 0xbc, 0xbb, 0xbb, 0xbf, 0xc6, 0xc8, 0xc7, 0xc6, 0xc4, 0xc0, 0xbc, 0xba, + 0xb9, 0xb6, 0xb4, 0xb6, 0xb7, 0xb7, 0xb5, 0xb1, 0xb4, 0xb6, 0xb7, 0xb8, + 0xb7, 0xb9, 0xba, 0xb9, 0xb7, 0xb7, 0xb6, 0xb3, 0xb2, 0xb2, 0xb5, 0xb9, + 0xbb, 0xbe, 0xc0, 0xc3, 0xc3, 0xc5, 0xc9, 0xcc, 0xcc, 0xc6, 0xc2, 0xc1, + 0xc1, 0xbf, 0xbf, 0xbf, 0xbf, 0xbe, 0xbd, 0xbd, 0xbe, 0xbc, 0xbb, 0xba, + 0xbd, 0xbe, 0xbf, 0xc1, 0xc4, 0xc7, 0xcb, 0xcd, 0xcd, 0xce, 0xd0, 0xd1, + 0xd0, 0xd0, 0xd1, 0xd5, 0xd6, 0xd5, 0xd3, 0xd0, 0xce, 0xcf, 0xcf, 0xce, + 0xce, 0xc9, 0xc5, 0xc3, 0xc1, 0xbf, 0xbe, 0xb8, 0xb3, 0xb1, 0xac, 0xa3, + 0x9d, 0x97, 0x94, 0x8e, 0x89, 0x91, 0x99, 0x99, 0x95, 0x8b, 0x7e, 0x78, + 0x76, 0x75, 0x73, 0x6e, 0x6c, 0x6e, 0x70, 0x73, 0x76, 0x78, 0x7b, 0x7a, + 0x74, 0x73, 0x77, 0x78, 0x79, 0x7c, 0x7a, 0x6b, 0x69, 0x6c, 0x6c, 0x5c, + 0x52, 0x51, 0x52, 0x59, 0x6c, 0x69, 0x64, 0x65, 0x70, 0x7b, 0x82, 0x86, + 0x88, 0x8c, 0x8f, 0x90, 0x8e, 0x8b, 0x85, 0x7b, 0x70, 0x67, 0x62, 0x5b, + 0x54, 0x4e, 0x4c, 0x4e, 0x54, 0x5c, 0x62, 0x6b, 0x76, 0x7e, 0x89, 0x98, + 0xa3, 0xaa, 0xac, 0xaf, 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xaf, 0xad, 0xac, + 0xac, 0xaa, 0xa9, 0xa7, 0xa5, 0xa4, 0xa1, 0x9e, 0x9d, 0x9c, 0x9b, 0x97, + 0x96, 0x92, 0x8f, 0x8d, 0x8a, 0x87, 0x85, 0x84, 0x82, 0x80, 0x7f, 0x7e, + 0x7c, 0x7b, 0x7b, 0x7a, 0x77, 0x75, 0x74, 0x73, 0x70, 0x6d, 0x6d, 0x6c, + 0x6a, 0x6a, 0x67, 0x65, 0x64, 0x63, 0x62, 0x5d, 0x59, 0x56, 0x52, 0x4d, + 0x7b, 0x73, 0x6e, 0x6b, 0x65, 0x5e, 0x5c, 0x5c, 0x5b, 0x59, 0x5a, 0x5c, + 0x5c, 0x5b, 0x5b, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5c, 0x5c, 0x5c, 0x5c, + 0x5d, 0x5d, 0x5c, 0x5d, 0x5e, 0x5d, 0x5e, 0x5f, 0x60, 0x60, 0x62, 0x63, + 0x63, 0x65, 0x66, 0x67, 0x68, 0x6a, 0x69, 0x69, 0x69, 0x69, 0x69, 0x67, + 0x65, 0x63, 0x61, 0x5f, 0x5e, 0x5e, 0x5f, 0x62, 0x66, 0x68, 0x6b, 0x75, + 0x8b, 0x9e, 0xa8, 0xae, 0xb1, 0xb3, 0xb6, 0xba, 0xbd, 0xbe, 0xc1, 0xc5, + 0xc6, 0xc7, 0xc8, 0xcc, 0xcf, 0xd1, 0xd3, 0xd4, 0xd5, 0xd5, 0xd5, 0xd4, + 0xd2, 0xd2, 0xd0, 0xcb, 0xc9, 0xc8, 0xc6, 0xc2, 0xbc, 0xba, 0xba, 0xbe, + 0xc4, 0xc6, 0xc6, 0xc5, 0xc3, 0xbe, 0xbb, 0xbb, 0xb9, 0xb7, 0xb5, 0xb8, + 0xb9, 0xb9, 0xb6, 0xb1, 0xb2, 0xb6, 0xb7, 0xb7, 0xb7, 0xba, 0xbb, 0xba, + 0xb8, 0xb7, 0xb7, 0xb3, 0xb2, 0xb4, 0xb8, 0xbb, 0xbd, 0xc1, 0xc3, 0xc5, + 0xc5, 0xc5, 0xc7, 0xc8, 0xc8, 0xc7, 0xc5, 0xc2, 0xc0, 0xbf, 0xc1, 0xc1, + 0xc1, 0xc0, 0xbf, 0xbe, 0xbf, 0xbd, 0xbc, 0xbc, 0xbe, 0xbe, 0xbe, 0xc0, + 0xc5, 0xca, 0xcd, 0xcf, 0xcf, 0xcf, 0xd1, 0xd0, 0xcf, 0xce, 0xd0, 0xd4, + 0xd6, 0xd4, 0xd2, 0xd0, 0xd1, 0xd0, 0xd1, 0xd2, 0xd3, 0xce, 0xc7, 0xc2, + 0xc0, 0xbf, 0xbc, 0xb7, 0xb2, 0xb0, 0xab, 0xa3, 0x9e, 0x99, 0x95, 0x8e, + 0x8a, 0x91, 0x9a, 0x9a, 0x94, 0x87, 0x7a, 0x74, 0x74, 0x75, 0x72, 0x6e, + 0x6a, 0x6c, 0x6f, 0x73, 0x76, 0x77, 0x78, 0x77, 0x73, 0x72, 0x76, 0x78, + 0x79, 0x7a, 0x75, 0x67, 0x66, 0x68, 0x65, 0x58, 0x50, 0x4f, 0x51, 0x5d, + 0x73, 0x6b, 0x63, 0x64, 0x6d, 0x76, 0x7d, 0x83, 0x86, 0x8b, 0x8d, 0x8f, + 0x8d, 0x8b, 0x85, 0x7f, 0x74, 0x6b, 0x65, 0x5e, 0x56, 0x4f, 0x4d, 0x4f, + 0x53, 0x5a, 0x5f, 0x69, 0x76, 0x7f, 0x8c, 0x9a, 0xa5, 0xab, 0xae, 0xb1, + 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb1, 0xae, 0xae, 0xae, 0xac, 0xab, 0xa9, + 0xa7, 0xa5, 0xa3, 0xa0, 0x9e, 0x9e, 0x9d, 0x9a, 0x96, 0x93, 0x90, 0x8f, + 0x8b, 0x89, 0x87, 0x87, 0x86, 0x83, 0x82, 0x81, 0x80, 0x7f, 0x7f, 0x7d, + 0x7b, 0x7a, 0x7a, 0x78, 0x74, 0x71, 0x70, 0x70, 0x6e, 0x6d, 0x6b, 0x6a, + 0x69, 0x68, 0x67, 0x63, 0x5e, 0x5b, 0x57, 0x50, 0x70, 0x68, 0x64, 0x61, + 0x5d, 0x59, 0x59, 0x5a, 0x5a, 0x59, 0x5b, 0x5d, 0x5c, 0x5c, 0x5d, 0x5d, + 0x5d, 0x5d, 0x5d, 0x5e, 0x5e, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5c, 0x5e, + 0x5e, 0x5d, 0x5e, 0x5e, 0x5f, 0x61, 0x62, 0x63, 0x63, 0x65, 0x66, 0x67, + 0x68, 0x68, 0x69, 0x69, 0x69, 0x68, 0x68, 0x66, 0x65, 0x64, 0x60, 0x5e, + 0x5d, 0x5d, 0x5f, 0x63, 0x67, 0x69, 0x6c, 0x74, 0x88, 0x9a, 0xa5, 0xaa, + 0xaf, 0xb3, 0xb7, 0xbb, 0xbd, 0xbe, 0xc1, 0xc5, 0xc7, 0xc8, 0xc9, 0xca, + 0xce, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd5, 0xd5, 0xd3, 0xd1, 0xcd, + 0xca, 0xc9, 0xc6, 0xc2, 0xbd, 0xbc, 0xbd, 0xc0, 0xc5, 0xc7, 0xc6, 0xc4, + 0xc2, 0xbf, 0xbc, 0xbb, 0xbb, 0xb9, 0xb6, 0xb8, 0xb9, 0xb8, 0xb6, 0xb2, + 0xb3, 0xb5, 0xb6, 0xb5, 0xb6, 0xb8, 0xb9, 0xb8, 0xb8, 0xb8, 0xb9, 0xb7, + 0xb6, 0xb8, 0xb9, 0xbd, 0xc0, 0xc4, 0xc7, 0xc8, 0xc9, 0xc7, 0xc7, 0xc7, + 0xc6, 0xc6, 0xc6, 0xc3, 0xc1, 0xbf, 0xc2, 0xc3, 0xc3, 0xc2, 0xc1, 0xc1, + 0xc1, 0xbf, 0xbe, 0xbd, 0xbd, 0xbe, 0xbe, 0xc0, 0xc5, 0xcc, 0xcf, 0xd0, + 0xd0, 0xcf, 0xd1, 0xd1, 0xcf, 0xce, 0xcf, 0xd3, 0xd6, 0xd7, 0xd6, 0xd2, + 0xd1, 0xd1, 0xd4, 0xd5, 0xd7, 0xd2, 0xc7, 0xc0, 0xbe, 0xbd, 0xba, 0xb4, + 0xb1, 0xae, 0xaa, 0xa3, 0x9e, 0x99, 0x96, 0x8f, 0x8a, 0x91, 0x9a, 0x99, + 0x94, 0x85, 0x77, 0x71, 0x73, 0x74, 0x72, 0x6c, 0x66, 0x6a, 0x6d, 0x70, + 0x73, 0x73, 0x73, 0x72, 0x70, 0x6f, 0x70, 0x6f, 0x70, 0x6f, 0x6c, 0x66, + 0x64, 0x62, 0x5d, 0x5b, 0x58, 0x54, 0x58, 0x69, 0x7b, 0x6d, 0x64, 0x64, + 0x6b, 0x72, 0x79, 0x7e, 0x81, 0x85, 0x88, 0x89, 0x86, 0x84, 0x80, 0x7b, + 0x74, 0x6c, 0x67, 0x5f, 0x58, 0x51, 0x4e, 0x4e, 0x50, 0x57, 0x5d, 0x68, + 0x76, 0x80, 0x8d, 0x9c, 0xa7, 0xad, 0xb0, 0xb3, 0xb5, 0xb5, 0xb5, 0xb5, + 0xb5, 0xb2, 0xb0, 0xb0, 0xaf, 0xad, 0xab, 0xa9, 0xa9, 0xa8, 0xa6, 0xa2, + 0x9f, 0x9f, 0x9e, 0x9b, 0x98, 0x94, 0x92, 0x90, 0x8d, 0x8b, 0x8a, 0x89, + 0x89, 0x87, 0x85, 0x84, 0x82, 0x82, 0x81, 0x80, 0x7f, 0x7f, 0x7f, 0x7e, + 0x7b, 0x78, 0x77, 0x76, 0x73, 0x71, 0x71, 0x70, 0x6f, 0x6d, 0x6b, 0x67, + 0x63, 0x60, 0x5b, 0x55, 0x64, 0x5d, 0x58, 0x56, 0x54, 0x54, 0x56, 0x58, + 0x58, 0x59, 0x5c, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5c, 0x5c, 0x5e, + 0x5d, 0x5d, 0x5c, 0x5c, 0x5d, 0x5e, 0x5d, 0x5e, 0x5d, 0x5d, 0x5d, 0x5e, + 0x5f, 0x61, 0x62, 0x63, 0x63, 0x64, 0x65, 0x66, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x67, 0x66, 0x65, 0x64, 0x63, 0x61, 0x5d, 0x5d, 0x5d, 0x5f, 0x63, + 0x67, 0x69, 0x6b, 0x72, 0x84, 0x96, 0xa1, 0xa7, 0xae, 0xb2, 0xb7, 0xbb, + 0xbe, 0xbf, 0xc1, 0xc5, 0xc7, 0xc8, 0xc9, 0xca, 0xce, 0xd0, 0xd1, 0xd2, + 0xd3, 0xd4, 0xd5, 0xd6, 0xd5, 0xd4, 0xd4, 0xd2, 0xcf, 0xcd, 0xc9, 0xc5, + 0xc3, 0xc4, 0xc5, 0xc6, 0xc9, 0xca, 0xc8, 0xc6, 0xc5, 0xc0, 0xbd, 0xbd, + 0xbc, 0xbb, 0xb7, 0xb0, 0xad, 0xaf, 0xb2, 0xb2, 0xb2, 0xb4, 0xb4, 0xb3, + 0xb5, 0xb7, 0xb8, 0xb8, 0xb9, 0xb8, 0xbb, 0xbb, 0xba, 0xbb, 0xbb, 0xbe, + 0xc2, 0xc6, 0xc8, 0xc9, 0xc8, 0xc8, 0xc7, 0xc6, 0xc7, 0xc6, 0xc7, 0xc6, + 0xc4, 0xc2, 0xc3, 0xc5, 0xc6, 0xc5, 0xc5, 0xc5, 0xc5, 0xc3, 0xc1, 0xbf, + 0xbe, 0xbd, 0xbf, 0xc2, 0xc8, 0xce, 0xd0, 0xd0, 0xcf, 0xcf, 0xcf, 0xd1, + 0xd0, 0xcf, 0xcf, 0xd3, 0xd8, 0xd7, 0xd6, 0xd2, 0xd1, 0xd1, 0xd4, 0xd7, + 0xd8, 0xd2, 0xc6, 0xbf, 0xbd, 0xbc, 0xb8, 0xb2, 0xae, 0xac, 0xa8, 0xa3, + 0x9e, 0x9b, 0x98, 0x92, 0x8b, 0x8f, 0x97, 0x96, 0x92, 0x85, 0x78, 0x74, + 0x74, 0x73, 0x6f, 0x68, 0x65, 0x68, 0x6b, 0x6e, 0x6f, 0x6c, 0x6b, 0x6b, + 0x6c, 0x69, 0x66, 0x64, 0x64, 0x63, 0x63, 0x61, 0x5a, 0x57, 0x58, 0x61, + 0x60, 0x5b, 0x61, 0x74, 0x7d, 0x6d, 0x66, 0x67, 0x6b, 0x70, 0x77, 0x7b, + 0x7e, 0x80, 0x81, 0x81, 0x7e, 0x7c, 0x7a, 0x74, 0x6e, 0x6a, 0x66, 0x60, + 0x58, 0x51, 0x4f, 0x4e, 0x50, 0x55, 0x5a, 0x67, 0x76, 0x80, 0x8f, 0x9e, + 0xa9, 0xaf, 0xb2, 0xb5, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb6, 0xb3, 0xb3, + 0xb2, 0xb0, 0xae, 0xac, 0xab, 0xaa, 0xa7, 0xa3, 0xa1, 0xa0, 0x9f, 0x9c, + 0x98, 0x95, 0x93, 0x92, 0x8f, 0x8e, 0x8d, 0x8c, 0x8a, 0x88, 0x88, 0x87, + 0x85, 0x84, 0x83, 0x84, 0x82, 0x83, 0x83, 0x82, 0x80, 0x7d, 0x7c, 0x7b, + 0x79, 0x76, 0x74, 0x74, 0x73, 0x72, 0x6d, 0x69, 0x67, 0x65, 0x61, 0x5a, + 0x5a, 0x55, 0x52, 0x51, 0x50, 0x52, 0x55, 0x58, 0x59, 0x59, 0x5c, 0x5d, + 0x5d, 0x5c, 0x5d, 0x5c, 0x5d, 0x5c, 0x5c, 0x5d, 0x5d, 0x5c, 0x5c, 0x5c, + 0x5d, 0x5e, 0x5e, 0x5e, 0x5e, 0x5d, 0x5d, 0x5d, 0x5f, 0x5f, 0x61, 0x63, + 0x63, 0x65, 0x66, 0x66, 0x68, 0x68, 0x67, 0x67, 0x67, 0x67, 0x66, 0x64, + 0x63, 0x61, 0x60, 0x5e, 0x5c, 0x5c, 0x5f, 0x63, 0x67, 0x68, 0x69, 0x70, + 0x81, 0x93, 0x9f, 0xa5, 0xad, 0xb1, 0xb7, 0xbb, 0xbe, 0xbf, 0xc2, 0xc5, + 0xc7, 0xc8, 0xc9, 0xca, 0xce, 0xd0, 0xd2, 0xd3, 0xd4, 0xd4, 0xd4, 0xd5, + 0xd5, 0xd5, 0xd6, 0xd4, 0xd1, 0xcf, 0xcd, 0xca, 0xca, 0xcc, 0xcd, 0xcd, + 0xcc, 0xcb, 0xca, 0xca, 0xc7, 0xc4, 0xc0, 0xbf, 0xbe, 0xbb, 0xb4, 0xa5, + 0xa1, 0xa3, 0xad, 0xb1, 0xb3, 0xb5, 0xb6, 0xb4, 0xb5, 0xb7, 0xb9, 0xba, + 0xb8, 0xb7, 0xbb, 0xbd, 0xbd, 0xbc, 0xbb, 0xbe, 0xc3, 0xc6, 0xc7, 0xc6, + 0xc8, 0xc9, 0xc7, 0xc6, 0xc7, 0xc8, 0xc7, 0xc7, 0xc6, 0xc4, 0xc5, 0xc7, + 0xc9, 0xc9, 0xc8, 0xc8, 0xc8, 0xc5, 0xc3, 0xbf, 0xbe, 0xbe, 0xc2, 0xc5, + 0xcb, 0xd0, 0xd2, 0xd1, 0xd1, 0xcf, 0xcf, 0xd1, 0xd0, 0xd0, 0xd1, 0xd5, + 0xd8, 0xd7, 0xd6, 0xd2, 0xd1, 0xd1, 0xd4, 0xd6, 0xd8, 0xd2, 0xc6, 0xc0, + 0xbd, 0xba, 0xb6, 0xb1, 0xad, 0xaa, 0xa6, 0xa1, 0x9f, 0x9b, 0x98, 0x93, + 0x8c, 0x8e, 0x93, 0x93, 0x90, 0x86, 0x7b, 0x77, 0x75, 0x73, 0x6e, 0x67, + 0x63, 0x65, 0x69, 0x6d, 0x6c, 0x69, 0x68, 0x68, 0x68, 0x67, 0x62, 0x60, + 0x5f, 0x5c, 0x5d, 0x5c, 0x58, 0x55, 0x56, 0x5d, 0x5f, 0x5e, 0x66, 0x79, + 0x7a, 0x6a, 0x67, 0x68, 0x6c, 0x71, 0x77, 0x7c, 0x7e, 0x7f, 0x7f, 0x7d, + 0x7c, 0x7a, 0x76, 0x6e, 0x66, 0x63, 0x61, 0x5e, 0x58, 0x52, 0x4f, 0x4e, + 0x50, 0x53, 0x58, 0x67, 0x78, 0x83, 0x91, 0xa0, 0xac, 0xb1, 0xb3, 0xb6, + 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb7, 0xb5, 0xb4, 0xb4, 0xb2, 0xb0, 0xac, + 0xab, 0xaa, 0xa9, 0xa4, 0xa2, 0xa1, 0xa0, 0x9e, 0x99, 0x96, 0x96, 0x95, + 0x92, 0x90, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x8a, 0x88, 0x87, 0x86, 0x86, + 0x85, 0x85, 0x85, 0x84, 0x81, 0x80, 0x7f, 0x7e, 0x7d, 0x7b, 0x78, 0x77, + 0x77, 0x75, 0x70, 0x6c, 0x6b, 0x6a, 0x65, 0x60, 0x55, 0x51, 0x4f, 0x4e, + 0x4e, 0x51, 0x55, 0x58, 0x5a, 0x5a, 0x5c, 0x5d, 0x5c, 0x5c, 0x5c, 0x5d, + 0x5d, 0x5c, 0x5c, 0x5e, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5e, 0x5e, 0x5e, + 0x5e, 0x5e, 0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x63, 0x63, 0x64, 0x66, 0x66, + 0x68, 0x68, 0x67, 0x66, 0x66, 0x67, 0x66, 0x64, 0x63, 0x61, 0x5f, 0x5d, + 0x5c, 0x5c, 0x5f, 0x64, 0x67, 0x68, 0x69, 0x70, 0x7f, 0x91, 0x9d, 0xa4, + 0xac, 0xb0, 0xb7, 0xbb, 0xbe, 0xbe, 0xc1, 0xc4, 0xc6, 0xc8, 0xc9, 0xcb, + 0xce, 0xd1, 0xd2, 0xd3, 0xd4, 0xd3, 0xd3, 0xd5, 0xd5, 0xd5, 0xd6, 0xd5, + 0xd2, 0xd0, 0xce, 0xcd, 0xcd, 0xcf, 0xd0, 0xd0, 0xcf, 0xcd, 0xcd, 0xcd, + 0xca, 0xc5, 0xc1, 0xc0, 0xbf, 0xbb, 0xb1, 0x9f, 0x9a, 0x9d, 0xa8, 0xb0, + 0xb4, 0xb6, 0xb6, 0xb5, 0xb5, 0xb6, 0xba, 0xba, 0xb8, 0xb7, 0xbb, 0xbe, + 0xbe, 0xbd, 0xbb, 0xbe, 0xc4, 0xc7, 0xc7, 0xc6, 0xc7, 0xc9, 0xc7, 0xc7, + 0xc8, 0xc8, 0xc7, 0xc7, 0xc7, 0xc5, 0xc6, 0xc7, 0xca, 0xca, 0xc9, 0xc9, + 0xc9, 0xc6, 0xc3, 0xbf, 0xbe, 0xbf, 0xc4, 0xc8, 0xcd, 0xd0, 0xd2, 0xd1, + 0xd1, 0xd0, 0xcf, 0xd1, 0xd0, 0xcf, 0xd1, 0xd6, 0xd9, 0xd7, 0xd6, 0xd2, + 0xd1, 0xd1, 0xd4, 0xd6, 0xd8, 0xd2, 0xc6, 0xbf, 0xbc, 0xb8, 0xb3, 0xae, + 0xab, 0xa8, 0xa4, 0xa0, 0x9d, 0x9a, 0x97, 0x93, 0x8d, 0x8e, 0x91, 0x91, + 0x8e, 0x86, 0x7c, 0x78, 0x75, 0x72, 0x6c, 0x65, 0x62, 0x64, 0x68, 0x6c, + 0x6a, 0x68, 0x67, 0x66, 0x64, 0x63, 0x5f, 0x5d, 0x5c, 0x59, 0x5a, 0x5a, + 0x58, 0x55, 0x53, 0x58, 0x5d, 0x62, 0x6b, 0x7b, 0x78, 0x67, 0x66, 0x68, + 0x6d, 0x73, 0x7a, 0x7e, 0x7f, 0x80, 0x7e, 0x7c, 0x7c, 0x7b, 0x75, 0x6c, + 0x63, 0x5f, 0x5d, 0x5c, 0x57, 0x52, 0x4f, 0x4f, 0x4f, 0x52, 0x57, 0x67, + 0x78, 0x83, 0x92, 0xa2, 0xac, 0xb1, 0xb3, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, + 0xb8, 0xb8, 0xb6, 0xb5, 0xb4, 0xb3, 0xb1, 0xad, 0xac, 0xab, 0xa9, 0xa5, + 0xa2, 0xa2, 0xa1, 0x9e, 0x9a, 0x97, 0x97, 0x96, 0x94, 0x91, 0x90, 0x8f, + 0x8e, 0x8c, 0x8b, 0x8b, 0x8a, 0x89, 0x88, 0x88, 0x87, 0x87, 0x86, 0x86, + 0x84, 0x83, 0x81, 0x80, 0x7f, 0x7d, 0x7a, 0x79, 0x79, 0x78, 0x73, 0x6f, + 0x6d, 0x6c, 0x68, 0x63, 0x4e, 0x4d, 0x4d, 0x4d, 0x4f, 0x53, 0x55, 0x58, + 0x5a, 0x5b, 0x5d, 0x5d, 0x5c, 0x5c, 0x5c, 0x5d, 0x5d, 0x5c, 0x5d, 0x5e, + 0x5e, 0x5d, 0x5d, 0x5d, 0x5c, 0x5d, 0x5e, 0x5e, 0x5e, 0x5f, 0x60, 0x60, + 0x5f, 0x5f, 0x61, 0x61, 0x63, 0x63, 0x64, 0x66, 0x68, 0x66, 0x67, 0x67, + 0x67, 0x66, 0x66, 0x65, 0x63, 0x60, 0x5e, 0x5d, 0x5d, 0x5d, 0x5f, 0x64, + 0x67, 0x67, 0x68, 0x6e, 0x7e, 0x8e, 0x99, 0xa1, 0xaa, 0xb0, 0xb6, 0xbb, + 0xbd, 0xbe, 0xbf, 0xc3, 0xc6, 0xc7, 0xc8, 0xca, 0xcd, 0xd1, 0xd2, 0xd2, + 0xd2, 0xd2, 0xd2, 0xd3, 0xd4, 0xd4, 0xd6, 0xd5, 0xd2, 0xd0, 0xcf, 0xcf, + 0xd1, 0xd2, 0xd2, 0xd2, 0xd3, 0xd3, 0xd2, 0xd0, 0xcd, 0xc8, 0xc3, 0xc0, + 0xbf, 0xba, 0xab, 0x98, 0x95, 0x99, 0xa2, 0xad, 0xb5, 0xb6, 0xb6, 0xb5, + 0xb6, 0xb7, 0xb9, 0xb9, 0xb8, 0xb7, 0xbb, 0xbe, 0xbe, 0xbd, 0xbd, 0xbf, + 0xc6, 0xc9, 0xc8, 0xc6, 0xc6, 0xc7, 0xc8, 0xc9, 0xc9, 0xc7, 0xc7, 0xc7, + 0xc7, 0xc5, 0xc6, 0xc8, 0xc9, 0xca, 0xc9, 0xca, 0xc9, 0xc5, 0xc2, 0xbe, + 0xbe, 0xc1, 0xc7, 0xcb, 0xce, 0xd1, 0xd2, 0xd1, 0xd1, 0xd0, 0xd0, 0xd0, + 0xce, 0xce, 0xd1, 0xd6, 0xd9, 0xd8, 0xd6, 0xd2, 0xd1, 0xd1, 0xd3, 0xd5, + 0xd6, 0xd1, 0xc5, 0xbe, 0xba, 0xb3, 0xab, 0xa6, 0xa5, 0xa3, 0x9f, 0x9c, + 0x99, 0x95, 0x93, 0x8f, 0x8c, 0x8e, 0x90, 0x8e, 0x8b, 0x84, 0x7c, 0x77, + 0x73, 0x6f, 0x6a, 0x63, 0x61, 0x63, 0x66, 0x69, 0x68, 0x66, 0x63, 0x62, + 0x5e, 0x5c, 0x5b, 0x59, 0x58, 0x56, 0x58, 0x5c, 0x58, 0x53, 0x4c, 0x54, + 0x5f, 0x6a, 0x73, 0x7d, 0x71, 0x61, 0x63, 0x66, 0x6d, 0x74, 0x7d, 0x81, + 0x81, 0x81, 0x7f, 0x7f, 0x80, 0x7e, 0x77, 0x6b, 0x5f, 0x59, 0x58, 0x57, + 0x56, 0x51, 0x4f, 0x4f, 0x4f, 0x51, 0x55, 0x65, 0x78, 0x84, 0x93, 0xa2, + 0xab, 0xaf, 0xb1, 0xb4, 0xb5, 0xb4, 0xb4, 0xb5, 0xb7, 0xb8, 0xb6, 0xb5, + 0xb4, 0xb4, 0xb3, 0xb0, 0xac, 0xab, 0xab, 0xa8, 0xa4, 0xa3, 0xa2, 0x9f, + 0x9b, 0x99, 0x97, 0x96, 0x95, 0x94, 0x91, 0x90, 0x8f, 0x8e, 0x8c, 0x8c, + 0x8b, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x89, 0x89, 0x86, 0x85, 0x83, 0x82, + 0x82, 0x7f, 0x7e, 0x7c, 0x7b, 0x7b, 0x78, 0x74, 0x71, 0x6f, 0x6b, 0x68, + 0x49, 0x4b, 0x4c, 0x4d, 0x4f, 0x52, 0x55, 0x59, 0x5a, 0x5b, 0x5d, 0x5d, + 0x5c, 0x5c, 0x5c, 0x5e, 0x5d, 0x5e, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, + 0x5d, 0x5d, 0x5e, 0x5e, 0x5e, 0x5f, 0x61, 0x61, 0x5f, 0x5f, 0x61, 0x61, + 0x63, 0x63, 0x63, 0x65, 0x67, 0x67, 0x67, 0x67, 0x67, 0x66, 0x64, 0x64, + 0x62, 0x60, 0x5e, 0x5c, 0x5c, 0x5e, 0x61, 0x65, 0x67, 0x67, 0x68, 0x6c, + 0x7a, 0x8a, 0x96, 0x9d, 0xa7, 0xb0, 0xb6, 0xbb, 0xbc, 0xbd, 0xbe, 0xc2, + 0xc5, 0xc6, 0xc7, 0xc9, 0xcc, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xcf, + 0xcf, 0xd1, 0xd3, 0xd5, 0xd2, 0xd0, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd4, + 0xd7, 0xd7, 0xd7, 0xd5, 0xd2, 0xce, 0xc8, 0xc4, 0xc1, 0xbb, 0xa7, 0x96, + 0x98, 0x9c, 0xa0, 0xa9, 0xb4, 0xb6, 0xb6, 0xb5, 0xb6, 0xb9, 0xbb, 0xbb, + 0xbb, 0xb9, 0xba, 0xbc, 0xbd, 0xbd, 0xbf, 0xc1, 0xc5, 0xc8, 0xc9, 0xc7, + 0xc6, 0xc6, 0xca, 0xcb, 0xc9, 0xc7, 0xc6, 0xc5, 0xc5, 0xc4, 0xc6, 0xc8, + 0xca, 0xcb, 0xcc, 0xca, 0xc7, 0xc4, 0xc1, 0xc0, 0xc1, 0xc4, 0xc9, 0xcd, + 0xcf, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd2, 0xd0, 0xce, 0xce, 0xd1, 0xd6, + 0xd9, 0xd8, 0xd6, 0xd3, 0xd0, 0xd0, 0xd2, 0xd4, 0xd5, 0xce, 0xc3, 0xba, + 0xb3, 0xaa, 0x9f, 0x98, 0x97, 0x97, 0x95, 0x93, 0x91, 0x8e, 0x8c, 0x88, + 0x88, 0x8e, 0x90, 0x8c, 0x88, 0x80, 0x78, 0x73, 0x70, 0x6e, 0x6a, 0x64, + 0x61, 0x63, 0x65, 0x65, 0x65, 0x62, 0x5e, 0x5d, 0x5b, 0x59, 0x58, 0x55, + 0x54, 0x53, 0x59, 0x5d, 0x56, 0x50, 0x4d, 0x5c, 0x6a, 0x75, 0x7c, 0x7d, + 0x67, 0x5b, 0x60, 0x65, 0x6c, 0x76, 0x7f, 0x83, 0x84, 0x84, 0x85, 0x86, + 0x87, 0x86, 0x7c, 0x6b, 0x5d, 0x56, 0x55, 0x54, 0x55, 0x52, 0x50, 0x50, + 0x4f, 0x50, 0x53, 0x66, 0x7b, 0x87, 0x96, 0xa1, 0xa8, 0xac, 0xae, 0xb1, + 0xb2, 0xb0, 0xb1, 0xb2, 0xb4, 0xb7, 0xb8, 0xb7, 0xb6, 0xb4, 0xb3, 0xb0, + 0xad, 0xac, 0xab, 0xa8, 0xa4, 0xa3, 0xa2, 0x9f, 0x9c, 0x9a, 0x98, 0x97, + 0x97, 0x95, 0x92, 0x91, 0x90, 0x8f, 0x8e, 0x8e, 0x8d, 0x8c, 0x8d, 0x8d, + 0x8d, 0x8c, 0x8c, 0x8b, 0x8a, 0x8a, 0x89, 0x88, 0x87, 0x84, 0x82, 0x80, + 0x7f, 0x7e, 0x7d, 0x79, 0x76, 0x73, 0x6f, 0x6c, 0x48, 0x4a, 0x4c, 0x4d, + 0x50, 0x51, 0x55, 0x58, 0x5a, 0x5b, 0x5c, 0x5d, 0x5c, 0x5c, 0x5d, 0x5d, + 0x5d, 0x5d, 0x5c, 0x5d, 0x5c, 0x5d, 0x5d, 0x5d, 0x5e, 0x5e, 0x5f, 0x5f, + 0x5f, 0x5f, 0x60, 0x61, 0x60, 0x60, 0x61, 0x61, 0x63, 0x63, 0x63, 0x65, + 0x66, 0x66, 0x67, 0x67, 0x66, 0x65, 0x63, 0x62, 0x60, 0x5e, 0x5d, 0x5c, + 0x5e, 0x5f, 0x63, 0x66, 0x67, 0x67, 0x67, 0x6a, 0x77, 0x86, 0x92, 0x9b, + 0xa5, 0xae, 0xb5, 0xba, 0xbb, 0xbc, 0xbd, 0xc0, 0xc4, 0xc6, 0xc7, 0xc7, + 0xc9, 0xcd, 0xce, 0xce, 0xcd, 0xce, 0xce, 0xcc, 0xcc, 0xcd, 0xd0, 0xcf, + 0xcd, 0xcb, 0xca, 0xcc, 0xcd, 0xce, 0xcf, 0xd2, 0xd6, 0xd8, 0xd8, 0xd8, + 0xd7, 0xd5, 0xd1, 0xcc, 0xc9, 0xc3, 0xb1, 0x9e, 0xa2, 0xa7, 0xaa, 0xac, + 0xb3, 0xb6, 0xb6, 0xb7, 0xb7, 0xba, 0xbc, 0xbb, 0xbb, 0xbb, 0xba, 0xba, + 0xbb, 0xbc, 0xbf, 0xc1, 0xc4, 0xc7, 0xc8, 0xc8, 0xc6, 0xc5, 0xca, 0xcb, + 0xc7, 0xc7, 0xc6, 0xc5, 0xc5, 0xc6, 0xc6, 0xca, 0xce, 0xcf, 0xcd, 0xc9, + 0xc7, 0xc4, 0xc3, 0xc3, 0xc3, 0xc6, 0xcc, 0xce, 0xd0, 0xd1, 0xd2, 0xd2, + 0xd2, 0xd2, 0xd2, 0xd1, 0xd0, 0xd1, 0xd5, 0xd8, 0xd9, 0xd8, 0xd6, 0xd3, + 0xcf, 0xce, 0xd0, 0xd2, 0xd2, 0xc8, 0xbd, 0xb2, 0xac, 0xa3, 0x96, 0x8d, + 0x8d, 0x8d, 0x8c, 0x89, 0x85, 0x85, 0x85, 0x84, 0x86, 0x8d, 0x8e, 0x88, + 0x84, 0x7d, 0x75, 0x6f, 0x6e, 0x6d, 0x68, 0x63, 0x62, 0x63, 0x63, 0x61, + 0x60, 0x5e, 0x5c, 0x5c, 0x5c, 0x58, 0x54, 0x52, 0x52, 0x56, 0x5b, 0x58, + 0x51, 0x50, 0x5a, 0x6c, 0x77, 0x7f, 0x80, 0x7a, 0x5f, 0x59, 0x60, 0x65, + 0x6b, 0x74, 0x7c, 0x7f, 0x81, 0x83, 0x85, 0x88, 0x8b, 0x8a, 0x82, 0x70, + 0x5e, 0x57, 0x55, 0x54, 0x54, 0x52, 0x51, 0x51, 0x50, 0x4e, 0x52, 0x67, + 0x7d, 0x89, 0x94, 0x9d, 0xa5, 0xa9, 0xac, 0xad, 0xac, 0xad, 0xaf, 0xaf, + 0xb1, 0xb4, 0xb7, 0xb8, 0xb7, 0xb4, 0xb2, 0xb0, 0xad, 0xac, 0xab, 0xa8, + 0xa5, 0xa3, 0xa1, 0x9f, 0x9e, 0x9b, 0x9a, 0x99, 0x97, 0x95, 0x94, 0x92, + 0x91, 0x91, 0x90, 0x90, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x8f, 0x8e, 0x8e, + 0x8e, 0x8c, 0x8c, 0x8c, 0x8a, 0x89, 0x87, 0x84, 0x83, 0x82, 0x81, 0x7e, + 0x7a, 0x78, 0x75, 0x71, 0x47, 0x49, 0x4b, 0x4d, 0x50, 0x51, 0x54, 0x58, + 0x5a, 0x5b, 0x5b, 0x5d, 0x5d, 0x5d, 0x5c, 0x5d, 0x5d, 0x5c, 0x5c, 0x5c, + 0x5d, 0x5e, 0x5d, 0x5d, 0x5f, 0x60, 0x60, 0x60, 0x60, 0x60, 0x61, 0x61, + 0x60, 0x60, 0x61, 0x61, 0x63, 0x63, 0x64, 0x65, 0x66, 0x66, 0x66, 0x66, + 0x64, 0x64, 0x63, 0x61, 0x5f, 0x5e, 0x5b, 0x5b, 0x5e, 0x5f, 0x63, 0x66, + 0x68, 0x67, 0x67, 0x6a, 0x75, 0x83, 0x8f, 0x98, 0xa3, 0xab, 0xb3, 0xb9, + 0xbc, 0xbc, 0xbc, 0xbf, 0xc3, 0xc6, 0xc6, 0xc6, 0xc6, 0xca, 0xcc, 0xcc, + 0xcb, 0xcc, 0xcc, 0xcb, 0xcb, 0xcb, 0xcd, 0xcc, 0xc9, 0xc8, 0xc8, 0xca, + 0xca, 0xcc, 0xcd, 0xcf, 0xd3, 0xd6, 0xd9, 0xda, 0xda, 0xd9, 0xd6, 0xd2, + 0xcf, 0xca, 0xbe, 0xad, 0xaa, 0xac, 0xb1, 0xb3, 0xb6, 0xb7, 0xb8, 0xb7, + 0xb7, 0xba, 0xbc, 0xbc, 0xbb, 0xbd, 0xba, 0xb9, 0xba, 0xbb, 0xbd, 0xbf, + 0xc1, 0xc6, 0xc8, 0xc8, 0xc8, 0xc6, 0xc9, 0xca, 0xc7, 0xc6, 0xc7, 0xc8, + 0xc8, 0xc6, 0xc7, 0xca, 0xce, 0xcf, 0xcd, 0xca, 0xc8, 0xc6, 0xc5, 0xc4, + 0xc4, 0xc6, 0xcc, 0xce, 0xd0, 0xd0, 0xd1, 0xd2, 0xd2, 0xd2, 0xd1, 0xd1, + 0xd2, 0xd4, 0xd8, 0xda, 0xda, 0xd8, 0xd6, 0xd3, 0xcf, 0xcc, 0xce, 0xce, + 0xcd, 0xc4, 0xb7, 0xac, 0xa6, 0x9f, 0x95, 0x8a, 0x89, 0x8a, 0x89, 0x83, + 0x7c, 0x7f, 0x82, 0x85, 0x87, 0x8c, 0x8d, 0x87, 0x82, 0x7d, 0x75, 0x6f, + 0x6e, 0x6c, 0x66, 0x60, 0x60, 0x61, 0x61, 0x60, 0x5d, 0x5c, 0x5b, 0x5b, + 0x5c, 0x54, 0x4f, 0x4e, 0x52, 0x5a, 0x5b, 0x5a, 0x56, 0x5a, 0x68, 0x79, + 0x82, 0x86, 0x84, 0x77, 0x5a, 0x5a, 0x61, 0x66, 0x6c, 0x74, 0x7a, 0x7d, + 0x7e, 0x7f, 0x82, 0x86, 0x89, 0x88, 0x82, 0x72, 0x61, 0x58, 0x56, 0x57, + 0x55, 0x53, 0x51, 0x50, 0x50, 0x4e, 0x53, 0x69, 0x7e, 0x88, 0x91, 0x9a, + 0xa1, 0xa5, 0xa7, 0xa8, 0xa7, 0xa9, 0xab, 0xac, 0xae, 0xb3, 0xb6, 0xb7, + 0xb6, 0xb4, 0xb3, 0xb0, 0xad, 0xac, 0xaa, 0xa7, 0xa4, 0xa2, 0xa2, 0x9f, + 0x9e, 0x9b, 0x9a, 0x99, 0x98, 0x95, 0x94, 0x93, 0x92, 0x92, 0x92, 0x91, + 0x92, 0x92, 0x92, 0x92, 0x92, 0x90, 0x90, 0x8f, 0x8f, 0x8d, 0x8e, 0x8d, + 0x8c, 0x8b, 0x88, 0x87, 0x86, 0x84, 0x83, 0x7f, 0x7d, 0x7b, 0x78, 0x74, + 0x46, 0x48, 0x4a, 0x4d, 0x50, 0x51, 0x54, 0x58, 0x59, 0x5b, 0x5b, 0x5d, + 0x5c, 0x5c, 0x5b, 0x5c, 0x5c, 0x5b, 0x5b, 0x5b, 0x5d, 0x5e, 0x5d, 0x5d, + 0x5f, 0x60, 0x60, 0x60, 0x60, 0x60, 0x61, 0x61, 0x60, 0x60, 0x61, 0x61, + 0x63, 0x63, 0x63, 0x65, 0x66, 0x66, 0x66, 0x65, 0x64, 0x64, 0x62, 0x60, + 0x5f, 0x5d, 0x5b, 0x5b, 0x5e, 0x5f, 0x63, 0x66, 0x67, 0x67, 0x66, 0x69, + 0x73, 0x81, 0x8d, 0x96, 0xa1, 0xaa, 0xb3, 0xb9, 0xbc, 0xbc, 0xbc, 0xbf, + 0xc2, 0xc5, 0xc6, 0xc5, 0xc5, 0xc8, 0xca, 0xca, 0xca, 0xca, 0xca, 0xc9, + 0xca, 0xca, 0xcb, 0xc9, 0xc6, 0xc5, 0xc6, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, + 0xd0, 0xd4, 0xd8, 0xd9, 0xda, 0xda, 0xd9, 0xd6, 0xd3, 0xcf, 0xc6, 0xb8, + 0xb0, 0xaf, 0xb2, 0xb5, 0xb6, 0xb8, 0xb8, 0xb6, 0xb7, 0xba, 0xbb, 0xbb, + 0xbb, 0xbd, 0xbb, 0xba, 0xba, 0xbb, 0xbc, 0xbd, 0xc1, 0xc4, 0xc6, 0xc8, + 0xc8, 0xc6, 0xc8, 0xc8, 0xc6, 0xc4, 0xc7, 0xc9, 0xc9, 0xc7, 0xc7, 0xc9, + 0xcc, 0xce, 0xcd, 0xcb, 0xc9, 0xc7, 0xc6, 0xc4, 0xc4, 0xc5, 0xca, 0xcc, + 0xce, 0xcf, 0xcf, 0xd0, 0xd1, 0xd1, 0xd0, 0xd0, 0xd1, 0xd4, 0xd8, 0xdb, + 0xd9, 0xd8, 0xd6, 0xd3, 0xcf, 0xcc, 0xcb, 0xcb, 0xc9, 0xc0, 0xb3, 0xa7, + 0xa1, 0x9e, 0x95, 0x8a, 0x89, 0x8a, 0x8a, 0x81, 0x78, 0x7e, 0x82, 0x87, + 0x88, 0x8c, 0x8c, 0x85, 0x81, 0x7d, 0x76, 0x70, 0x6e, 0x6b, 0x63, 0x5e, + 0x5e, 0x60, 0x60, 0x5f, 0x5b, 0x5b, 0x5c, 0x5c, 0x5b, 0x53, 0x4f, 0x4f, + 0x53, 0x5c, 0x5b, 0x5c, 0x5e, 0x64, 0x73, 0x81, 0x88, 0x88, 0x83, 0x72, + 0x58, 0x5a, 0x62, 0x67, 0x6d, 0x74, 0x79, 0x7b, 0x7c, 0x7d, 0x7f, 0x83, + 0x85, 0x85, 0x80, 0x71, 0x61, 0x5a, 0x58, 0x58, 0x56, 0x54, 0x52, 0x50, + 0x4f, 0x4d, 0x54, 0x6a, 0x7c, 0x86, 0x8f, 0x97, 0x9e, 0xa2, 0xa4, 0xa5, + 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xb2, 0xb5, 0xb7, 0xb6, 0xb4, 0xb3, 0xb0, + 0xac, 0xab, 0xa9, 0xa6, 0xa3, 0xa2, 0xa1, 0x9f, 0x9d, 0x9a, 0x99, 0x99, + 0x97, 0x95, 0x94, 0x93, 0x92, 0x92, 0x93, 0x92, 0x93, 0x93, 0x93, 0x93, + 0x92, 0x92, 0x91, 0x8f, 0x8f, 0x8e, 0x8e, 0x8e, 0x8d, 0x8c, 0x89, 0x88, + 0x87, 0x85, 0x84, 0x81, 0x7e, 0x7d, 0x7a, 0x76, 0x45, 0x47, 0x49, 0x4c, + 0x4f, 0x51, 0x54, 0x58, 0x59, 0x5a, 0x5c, 0x5c, 0x5b, 0x5a, 0x5a, 0x5a, + 0x5b, 0x5b, 0x5b, 0x5b, 0x5c, 0x5e, 0x5d, 0x5d, 0x5e, 0x5f, 0x60, 0x60, + 0x60, 0x5f, 0x60, 0x61, 0x60, 0x60, 0x61, 0x61, 0x63, 0x63, 0x63, 0x64, + 0x66, 0x66, 0x66, 0x66, 0x64, 0x63, 0x61, 0x5f, 0x5e, 0x5d, 0x5a, 0x5c, + 0x5e, 0x60, 0x63, 0x65, 0x67, 0x66, 0x66, 0x67, 0x71, 0x80, 0x8a, 0x92, + 0x9e, 0xaa, 0xb2, 0xb8, 0xbc, 0xbc, 0xbc, 0xbf, 0xc2, 0xc4, 0xc6, 0xc4, + 0xc3, 0xc5, 0xc6, 0xc7, 0xc8, 0xc8, 0xc7, 0xc7, 0xc8, 0xc9, 0xcb, 0xc8, + 0xc3, 0xc1, 0xc2, 0xc4, 0xc6, 0xc7, 0xc7, 0xc8, 0xcc, 0xcf, 0xd3, 0xd5, + 0xd7, 0xd9, 0xdc, 0xdd, 0xdc, 0xd7, 0xcf, 0xc4, 0xba, 0xb4, 0xaf, 0xb4, + 0xb7, 0xb7, 0xb7, 0xb6, 0xb8, 0xba, 0xbb, 0xbc, 0xbb, 0xbb, 0xbc, 0xbb, + 0xbc, 0xbd, 0xbb, 0xbc, 0xc0, 0xc3, 0xc4, 0xc8, 0xc9, 0xc6, 0xc6, 0xc6, + 0xc5, 0xc3, 0xc6, 0xc9, 0xca, 0xc8, 0xc7, 0xc5, 0xc8, 0xca, 0xca, 0xc9, + 0xc9, 0xc7, 0xc6, 0xc4, 0xc3, 0xc3, 0xc5, 0xc7, 0xc9, 0xcb, 0xcc, 0xcd, + 0xcd, 0xce, 0xcd, 0xcc, 0xcd, 0xcf, 0xd3, 0xd7, 0xd6, 0xd5, 0xd4, 0xd2, + 0xce, 0xca, 0xc8, 0xc7, 0xc4, 0xba, 0xac, 0xa0, 0x9c, 0x9b, 0x95, 0x8b, + 0x8a, 0x8c, 0x8c, 0x80, 0x78, 0x7f, 0x85, 0x89, 0x89, 0x8b, 0x8b, 0x84, + 0x80, 0x7c, 0x77, 0x71, 0x6c, 0x68, 0x60, 0x5c, 0x5d, 0x5e, 0x5e, 0x5c, + 0x5a, 0x5c, 0x5d, 0x5d, 0x59, 0x52, 0x54, 0x54, 0x57, 0x5e, 0x5d, 0x60, + 0x6b, 0x76, 0x84, 0x8a, 0x8b, 0x85, 0x7b, 0x66, 0x55, 0x5c, 0x64, 0x68, + 0x6d, 0x75, 0x78, 0x7a, 0x7a, 0x79, 0x7b, 0x7e, 0x80, 0x7f, 0x79, 0x6d, + 0x61, 0x5b, 0x59, 0x5a, 0x58, 0x56, 0x52, 0x50, 0x4e, 0x4e, 0x53, 0x67, + 0x78, 0x81, 0x8c, 0x94, 0x9a, 0x9e, 0x9f, 0xa0, 0x9f, 0xa0, 0xa3, 0xa5, + 0xa9, 0xae, 0xb2, 0xb5, 0xb5, 0xb3, 0xb2, 0xaf, 0xac, 0xab, 0xa8, 0xa5, + 0xa2, 0xa1, 0xa0, 0x9e, 0x9d, 0x9a, 0x98, 0x97, 0x97, 0x95, 0x94, 0x92, + 0x92, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x94, 0x93, 0x92, 0x92, 0x90, + 0x90, 0x8f, 0x8f, 0x8f, 0x8e, 0x8d, 0x8b, 0x8a, 0x89, 0x87, 0x86, 0x83, + 0x81, 0x80, 0x7d, 0x78, 0x44, 0x47, 0x4a, 0x4c, 0x4f, 0x50, 0x53, 0x57, + 0x58, 0x59, 0x5a, 0x5a, 0x59, 0x5a, 0x5b, 0x5a, 0x5a, 0x5b, 0x5b, 0x5a, + 0x5b, 0x5d, 0x5d, 0x5c, 0x5d, 0x60, 0x60, 0x5f, 0x5e, 0x5f, 0x61, 0x61, + 0x61, 0x61, 0x62, 0x61, 0x63, 0x64, 0x64, 0x63, 0x64, 0x66, 0x66, 0x65, + 0x63, 0x61, 0x5f, 0x5e, 0x5e, 0x5c, 0x5a, 0x5b, 0x5e, 0x60, 0x63, 0x64, + 0x65, 0x67, 0x67, 0x68, 0x6f, 0x7d, 0x88, 0x90, 0x9c, 0xa7, 0xb0, 0xb7, + 0xbb, 0xbc, 0xbc, 0xbd, 0xc1, 0xc4, 0xc5, 0xc5, 0xc3, 0xc2, 0xc4, 0xc6, + 0xc7, 0xc6, 0xc6, 0xc6, 0xc7, 0xca, 0xcd, 0xc9, 0xc4, 0xc1, 0xc0, 0xc0, + 0xc1, 0xc1, 0xc3, 0xc6, 0xc9, 0xcb, 0xce, 0xd0, 0xd3, 0xd6, 0xdb, 0xe1, + 0xe3, 0xe0, 0xd9, 0xd0, 0xc8, 0xbf, 0xb2, 0xb1, 0xb5, 0xb7, 0xb8, 0xb7, + 0xb7, 0xb9, 0xba, 0xbb, 0xbc, 0xba, 0xba, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbf, 0xc2, 0xc3, 0xc5, 0xc8, 0xc7, 0xc4, 0xc3, 0xc3, 0xc2, 0xc4, 0xc7, + 0xc8, 0xc7, 0xc5, 0xc4, 0xc7, 0xc8, 0xc8, 0xc7, 0xc6, 0xc5, 0xc4, 0xc5, + 0xc4, 0xc2, 0xc2, 0xc3, 0xc4, 0xc5, 0xc7, 0xc8, 0xc8, 0xc8, 0xc7, 0xc5, + 0xc3, 0xc4, 0xc8, 0xce, 0xd1, 0xd0, 0xd0, 0xce, 0xcb, 0xc7, 0xc5, 0xc3, + 0xbe, 0xb6, 0xa8, 0x9b, 0x97, 0x97, 0x8f, 0x87, 0x87, 0x89, 0x8c, 0x85, + 0x7e, 0x85, 0x89, 0x8a, 0x89, 0x8b, 0x89, 0x82, 0x7e, 0x79, 0x76, 0x70, + 0x6b, 0x66, 0x5f, 0x5c, 0x5d, 0x5d, 0x5c, 0x5a, 0x5b, 0x5d, 0x5d, 0x5a, + 0x54, 0x53, 0x5a, 0x5b, 0x5e, 0x63, 0x69, 0x74, 0x83, 0x8c, 0x92, 0x8f, + 0x87, 0x76, 0x68, 0x55, 0x53, 0x5d, 0x64, 0x68, 0x6f, 0x75, 0x77, 0x77, + 0x77, 0x76, 0x77, 0x79, 0x79, 0x77, 0x70, 0x67, 0x5f, 0x5c, 0x5b, 0x5a, + 0x5a, 0x57, 0x54, 0x52, 0x50, 0x4f, 0x54, 0x62, 0x71, 0x7a, 0x84, 0x8f, + 0x95, 0x98, 0x9a, 0x9a, 0x99, 0x99, 0x9c, 0xa0, 0xa5, 0xa9, 0xaf, 0xb3, + 0xb4, 0xb3, 0xb1, 0xaf, 0xac, 0xab, 0xa8, 0xa4, 0xa2, 0xa0, 0x9f, 0x9e, + 0x9d, 0x99, 0x97, 0x96, 0x95, 0x93, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x92, 0x94, 0x94, 0x93, 0x93, 0x92, 0x92, 0x90, 0x90, 0x90, + 0x8f, 0x90, 0x8e, 0x8d, 0x8b, 0x8a, 0x89, 0x86, 0x84, 0x82, 0x80, 0x7c, + 0x43, 0x46, 0x4a, 0x4d, 0x4f, 0x50, 0x52, 0x55, 0x57, 0x58, 0x5a, 0x5a, + 0x59, 0x5a, 0x5c, 0x5c, 0x5b, 0x5b, 0x5b, 0x5a, 0x5b, 0x5d, 0x5d, 0x5c, + 0x5e, 0x60, 0x60, 0x5f, 0x5f, 0x5f, 0x61, 0x61, 0x60, 0x61, 0x62, 0x61, + 0x63, 0x64, 0x63, 0x63, 0x64, 0x65, 0x66, 0x65, 0x63, 0x61, 0x5e, 0x5d, + 0x5d, 0x5c, 0x5a, 0x5b, 0x5d, 0x5f, 0x63, 0x63, 0x64, 0x65, 0x66, 0x66, + 0x6d, 0x7a, 0x85, 0x8d, 0x98, 0xa5, 0xad, 0xb5, 0xba, 0xbb, 0xbb, 0xbc, + 0xbf, 0xc3, 0xc5, 0xc6, 0xc4, 0xc2, 0xc4, 0xc6, 0xc7, 0xc6, 0xc8, 0xc7, + 0xc9, 0xcc, 0xd0, 0xcf, 0xcb, 0xc8, 0xc5, 0xc1, 0xbd, 0xbd, 0xbf, 0xc4, + 0xc8, 0xca, 0xcd, 0xce, 0xd0, 0xd2, 0xd5, 0xdc, 0xe0, 0xe3, 0xe2, 0xdc, + 0xd5, 0xcc, 0xbd, 0xad, 0xaf, 0xb6, 0xb8, 0xb7, 0xb6, 0xb7, 0xba, 0xbc, + 0xbd, 0xba, 0xb8, 0xb8, 0xb9, 0xba, 0xbb, 0xba, 0xbc, 0xbf, 0xc1, 0xc2, + 0xc7, 0xc9, 0xc4, 0xc2, 0xc1, 0xc1, 0xc0, 0xc1, 0xc2, 0xc1, 0xc1, 0xc1, + 0xc3, 0xc4, 0xc4, 0xc2, 0xc2, 0xc1, 0xc1, 0xc3, 0xc3, 0xbf, 0xc0, 0xc1, + 0xc1, 0xc1, 0xc2, 0xc3, 0xc3, 0xc2, 0xc2, 0xbf, 0xbd, 0xbc, 0xbe, 0xc3, + 0xc8, 0xc9, 0xca, 0xc9, 0xc7, 0xc5, 0xc2, 0xbf, 0xba, 0xb4, 0xa8, 0x9a, + 0x94, 0x91, 0x8a, 0x84, 0x87, 0x8a, 0x8c, 0x87, 0x83, 0x89, 0x8b, 0x89, + 0x87, 0x8a, 0x88, 0x81, 0x7d, 0x78, 0x73, 0x6c, 0x66, 0x62, 0x5d, 0x5c, + 0x5e, 0x5c, 0x5b, 0x5a, 0x5f, 0x5f, 0x58, 0x54, 0x50, 0x57, 0x5f, 0x68, + 0x6e, 0x77, 0x81, 0x8a, 0x8e, 0x90, 0x8f, 0x8a, 0x72, 0x57, 0x4d, 0x4b, + 0x56, 0x60, 0x67, 0x6a, 0x70, 0x75, 0x75, 0x73, 0x71, 0x6f, 0x71, 0x73, + 0x70, 0x6e, 0x69, 0x61, 0x5b, 0x5a, 0x5a, 0x5a, 0x5b, 0x59, 0x55, 0x53, + 0x51, 0x50, 0x51, 0x5c, 0x69, 0x72, 0x7c, 0x87, 0x8e, 0x93, 0x93, 0x94, + 0x92, 0x93, 0x96, 0x9a, 0x9f, 0xa5, 0xaa, 0xae, 0xb0, 0xb1, 0xb0, 0xae, + 0xab, 0xa9, 0xa8, 0xa5, 0xa1, 0xa0, 0x9e, 0x9d, 0x9b, 0x97, 0x95, 0x93, + 0x93, 0x91, 0x91, 0x91, 0x91, 0x91, 0x92, 0x91, 0x92, 0x92, 0x91, 0x92, + 0x92, 0x92, 0x92, 0x93, 0x92, 0x90, 0x90, 0x90, 0x91, 0x92, 0x91, 0x8e, + 0x8d, 0x8b, 0x8a, 0x88, 0x86, 0x84, 0x83, 0x7f, 0x42, 0x46, 0x4a, 0x4c, + 0x4f, 0x51, 0x52, 0x55, 0x57, 0x58, 0x5a, 0x5b, 0x5b, 0x5b, 0x5b, 0x5c, + 0x5b, 0x5c, 0x5c, 0x5b, 0x5b, 0x5d, 0x5d, 0x5c, 0x5d, 0x5f, 0x60, 0x5f, + 0x5f, 0x60, 0x62, 0x62, 0x61, 0x61, 0x62, 0x61, 0x63, 0x63, 0x63, 0x62, + 0x63, 0x65, 0x66, 0x65, 0x64, 0x61, 0x5e, 0x5c, 0x5c, 0x5c, 0x5b, 0x5c, + 0x5e, 0x60, 0x62, 0x64, 0x63, 0x64, 0x65, 0x65, 0x6b, 0x79, 0x84, 0x8b, + 0x95, 0xa3, 0xab, 0xb4, 0xb9, 0xbb, 0xbc, 0xbd, 0xbf, 0xc1, 0xc3, 0xc6, + 0xc5, 0xc3, 0xc4, 0xc5, 0xc6, 0xc6, 0xc8, 0xc9, 0xca, 0xce, 0xd2, 0xd2, + 0xd1, 0xcf, 0xcb, 0xc6, 0xbf, 0xbc, 0xbd, 0xc2, 0xc7, 0xca, 0xcc, 0xcd, + 0xce, 0xcf, 0xd1, 0xd3, 0xd7, 0xde, 0xe4, 0xe3, 0xde, 0xd8, 0xc9, 0xb0, + 0xa4, 0xad, 0xb4, 0xb7, 0xb6, 0xb7, 0xb9, 0xba, 0xbb, 0xb9, 0xb9, 0xbb, + 0xbb, 0xba, 0xba, 0xb9, 0xba, 0xbb, 0xbb, 0xbd, 0xc4, 0xc8, 0xc5, 0xc2, + 0xc1, 0xc0, 0xbe, 0xbd, 0xbe, 0xbd, 0xbf, 0xbe, 0xbe, 0xbf, 0xbf, 0xbe, + 0xbf, 0xbe, 0xbf, 0xc1, 0xc2, 0xbe, 0xbe, 0xbf, 0xbf, 0xbe, 0xc0, 0xbf, + 0xbf, 0xbd, 0xbd, 0xbc, 0xbd, 0xbd, 0xbc, 0xbf, 0xc3, 0xc5, 0xc5, 0xc4, + 0xc5, 0xc2, 0xbf, 0xbb, 0xb7, 0xb1, 0xa7, 0x9a, 0x95, 0x8f, 0x88, 0x86, + 0x8b, 0x8e, 0x8f, 0x88, 0x84, 0x89, 0x8b, 0x89, 0x88, 0x8a, 0x88, 0x80, + 0x7c, 0x77, 0x71, 0x69, 0x62, 0x5e, 0x5c, 0x5e, 0x5f, 0x5e, 0x5c, 0x5d, + 0x61, 0x5d, 0x54, 0x50, 0x51, 0x5d, 0x6a, 0x77, 0x7f, 0x87, 0x8e, 0x8f, + 0x8f, 0x90, 0x8d, 0x7a, 0x54, 0x41, 0x3f, 0x4b, 0x5b, 0x63, 0x68, 0x6d, + 0x72, 0x74, 0x72, 0x6e, 0x6c, 0x6c, 0x6e, 0x6e, 0x6c, 0x6a, 0x65, 0x5e, + 0x59, 0x57, 0x57, 0x57, 0x59, 0x57, 0x55, 0x53, 0x51, 0x50, 0x50, 0x56, + 0x61, 0x69, 0x75, 0x81, 0x8a, 0x8e, 0x90, 0x90, 0x8e, 0x8f, 0x92, 0x95, + 0x9a, 0xa1, 0xa7, 0xaa, 0xac, 0xaf, 0xaf, 0xad, 0xaa, 0xa9, 0xa8, 0xa6, + 0xa1, 0x9f, 0x9d, 0x9c, 0x98, 0x94, 0x93, 0x92, 0x91, 0x8f, 0x90, 0x90, + 0x90, 0x90, 0x91, 0x90, 0x91, 0x91, 0x90, 0x91, 0x91, 0x91, 0x91, 0x92, + 0x92, 0x91, 0x91, 0x92, 0x92, 0x92, 0x91, 0x8f, 0x8e, 0x8d, 0x8c, 0x8a, + 0x88, 0x87, 0x85, 0x82, 0x42, 0x45, 0x4a, 0x4c, 0x4e, 0x51, 0x52, 0x55, + 0x57, 0x58, 0x5b, 0x5c, 0x5c, 0x5c, 0x5b, 0x5b, 0x5b, 0x5c, 0x5c, 0x5b, + 0x5c, 0x5d, 0x5d, 0x5d, 0x5e, 0x5f, 0x5f, 0x5e, 0x5f, 0x61, 0x62, 0x62, + 0x61, 0x61, 0x62, 0x61, 0x63, 0x63, 0x63, 0x62, 0x63, 0x65, 0x66, 0x65, + 0x64, 0x61, 0x5e, 0x5c, 0x5c, 0x5c, 0x5b, 0x5c, 0x5f, 0x60, 0x62, 0x64, + 0x63, 0x64, 0x64, 0x64, 0x69, 0x77, 0x82, 0x89, 0x94, 0xa1, 0xaa, 0xb3, + 0xb8, 0xba, 0xbc, 0xbd, 0xbe, 0xc1, 0xc2, 0xc5, 0xc5, 0xc4, 0xc5, 0xc5, + 0xc6, 0xc7, 0xc8, 0xca, 0xcb, 0xce, 0xd2, 0xd3, 0xd3, 0xd2, 0xcf, 0xca, + 0xc4, 0xbf, 0xbe, 0xc1, 0xc5, 0xc9, 0xcc, 0xcd, 0xcd, 0xcf, 0xcf, 0xcf, + 0xd2, 0xda, 0xe2, 0xe4, 0xe1, 0xdd, 0xd1, 0xb8, 0xa1, 0xa4, 0xab, 0xb4, + 0xb7, 0xb7, 0xb8, 0xb9, 0xb9, 0xb8, 0xb9, 0xbb, 0xbb, 0xb9, 0xb8, 0xb7, + 0xb7, 0xb7, 0xb8, 0xb9, 0xc0, 0xc7, 0xc4, 0xc2, 0xc0, 0xbf, 0xbc, 0xbc, + 0xbb, 0xbc, 0xbc, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbd, 0xbc, 0xbd, 0xc0, + 0xc0, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbe, 0xbd, 0xbd, 0xbb, 0xbb, 0xbb, + 0xbc, 0xbc, 0xbc, 0xbe, 0xc1, 0xc3, 0xc3, 0xc3, 0xc3, 0xc1, 0xbd, 0xba, + 0xb5, 0xaf, 0xa5, 0x9a, 0x95, 0x8f, 0x89, 0x8a, 0x8e, 0x91, 0x92, 0x89, + 0x84, 0x88, 0x89, 0x88, 0x87, 0x89, 0x87, 0x81, 0x7d, 0x77, 0x71, 0x67, + 0x60, 0x5d, 0x5c, 0x5f, 0x60, 0x5e, 0x5d, 0x5e, 0x5f, 0x5b, 0x52, 0x51, + 0x57, 0x65, 0x74, 0x80, 0x87, 0x8e, 0x92, 0x90, 0x90, 0x8e, 0x84, 0x67, + 0x42, 0x39, 0x3d, 0x4e, 0x5e, 0x66, 0x6a, 0x6c, 0x70, 0x71, 0x6e, 0x6c, + 0x6b, 0x6b, 0x6c, 0x6c, 0x69, 0x67, 0x63, 0x5c, 0x57, 0x55, 0x55, 0x55, + 0x58, 0x57, 0x55, 0x53, 0x51, 0x4f, 0x4d, 0x52, 0x5c, 0x63, 0x6f, 0x7d, + 0x87, 0x8c, 0x8e, 0x8e, 0x8d, 0x8e, 0x91, 0x93, 0x98, 0x9f, 0xa4, 0xa8, + 0xaa, 0xad, 0xae, 0xad, 0xaa, 0xa9, 0xa9, 0xa6, 0xa1, 0x9f, 0x9d, 0x9a, + 0x97, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8e, 0x8f, 0x91, 0x91, 0x91, 0x92, 0x92, 0x91, 0x91, 0x92, + 0x91, 0x91, 0x91, 0x8f, 0x8f, 0x8e, 0x8d, 0x8b, 0x8a, 0x88, 0x87, 0x84, + 0x43, 0x46, 0x49, 0x4b, 0x4e, 0x52, 0x53, 0x55, 0x57, 0x58, 0x5b, 0x5c, + 0x5c, 0x5b, 0x5a, 0x5b, 0x5a, 0x5c, 0x5c, 0x5c, 0x5d, 0x5e, 0x5d, 0x5d, + 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x61, 0x63, 0x63, 0x62, 0x62, 0x62, 0x62, + 0x61, 0x62, 0x63, 0x63, 0x63, 0x65, 0x65, 0x65, 0x62, 0x60, 0x5d, 0x5c, + 0x5c, 0x5b, 0x5c, 0x5f, 0x60, 0x61, 0x61, 0x63, 0x63, 0x63, 0x63, 0x62, + 0x66, 0x75, 0x81, 0x88, 0x92, 0x9f, 0xa8, 0xb0, 0xb6, 0xb8, 0xbb, 0xbc, + 0xbd, 0xc0, 0xc2, 0xc5, 0xc6, 0xc5, 0xc6, 0xc6, 0xc6, 0xc8, 0xc9, 0xc9, + 0xcb, 0xce, 0xd0, 0xd3, 0xd4, 0xd4, 0xd2, 0xd0, 0xcb, 0xc7, 0xc4, 0xc1, + 0xc3, 0xc7, 0xca, 0xcb, 0xce, 0xcf, 0xd0, 0xcf, 0xd0, 0xd4, 0xda, 0xe0, + 0xe3, 0xe1, 0xdb, 0xc8, 0xa9, 0x9a, 0x9a, 0xa8, 0xb5, 0xb7, 0xb7, 0xb8, + 0xb8, 0xb8, 0xb7, 0xb9, 0xb8, 0xb5, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb5, + 0xbb, 0xc2, 0xc1, 0xbf, 0xbe, 0xbc, 0xbb, 0xba, 0xba, 0xba, 0xb9, 0xb7, + 0xb5, 0xb5, 0xb6, 0xb6, 0xb9, 0xba, 0xba, 0xbc, 0xbd, 0xba, 0xb9, 0xba, + 0xba, 0xba, 0xba, 0xba, 0xba, 0xb9, 0xb9, 0xba, 0xbb, 0xbb, 0xbb, 0xbc, + 0xbf, 0xc1, 0xc1, 0xc1, 0xc2, 0xc0, 0xbd, 0xb9, 0xb3, 0xab, 0xa1, 0x98, + 0x94, 0x90, 0x8b, 0x90, 0x93, 0x96, 0x96, 0x8d, 0x84, 0x85, 0x87, 0x88, + 0x86, 0x84, 0x84, 0x81, 0x7e, 0x78, 0x70, 0x66, 0x5f, 0x5d, 0x5d, 0x60, + 0x5f, 0x5e, 0x5c, 0x5b, 0x5b, 0x58, 0x54, 0x58, 0x68, 0x77, 0x82, 0x89, + 0x8e, 0x94, 0x94, 0x91, 0x8b, 0x81, 0x68, 0x44, 0x36, 0x3a, 0x43, 0x54, + 0x63, 0x69, 0x69, 0x6a, 0x6b, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6b, 0x6a, + 0x66, 0x63, 0x60, 0x5a, 0x57, 0x54, 0x53, 0x54, 0x57, 0x56, 0x54, 0x52, + 0x50, 0x4b, 0x49, 0x4c, 0x53, 0x5b, 0x67, 0x76, 0x82, 0x89, 0x8d, 0x8f, + 0x90, 0x8f, 0x90, 0x91, 0x95, 0x9b, 0xa0, 0xa3, 0xa6, 0xa9, 0xab, 0xab, + 0xaa, 0xa9, 0xa8, 0xa5, 0xa1, 0x9f, 0x9c, 0x98, 0x94, 0x92, 0x90, 0x8f, + 0x8e, 0x8c, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8f, 0x8f, 0x8f, 0x90, 0x8f, 0x90, 0x91, 0x91, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x8f, 0x8d, 0x8b, 0x8a, 0x89, 0x87, 0x85, 0x43, 0x45, 0x48, 0x4a, + 0x4c, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5b, 0x5c, 0x5b, 0x5a, 0x5b, + 0x5b, 0x5a, 0x5a, 0x5b, 0x5d, 0x5e, 0x5d, 0x5d, 0x5d, 0x5e, 0x5e, 0x5e, + 0x5f, 0x61, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x61, 0x61, 0x62, 0x63, + 0x63, 0x64, 0x64, 0x63, 0x62, 0x60, 0x5d, 0x5c, 0x5b, 0x5b, 0x5c, 0x5f, + 0x61, 0x61, 0x60, 0x61, 0x61, 0x61, 0x61, 0x60, 0x64, 0x71, 0x7f, 0x86, + 0x8f, 0x9c, 0xa5, 0xad, 0xb3, 0xb6, 0xb9, 0xbb, 0xbc, 0xbf, 0xc1, 0xc3, + 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc8, 0xc9, 0xcb, 0xcd, 0xce, 0xcf, 0xd2, + 0xd5, 0xd6, 0xd6, 0xd6, 0xd4, 0xd1, 0xce, 0xc8, 0xc4, 0xc3, 0xc6, 0xc9, + 0xcb, 0xcc, 0xce, 0xcf, 0xcf, 0xd0, 0xd2, 0xd7, 0xdb, 0xde, 0xe1, 0xdb, + 0xc6, 0xa9, 0x99, 0x8f, 0xa0, 0xb0, 0xb4, 0xb5, 0xb5, 0xb5, 0xb3, 0xb3, + 0xb3, 0xb3, 0xb3, 0xb3, 0xb1, 0xb0, 0xb1, 0xb1, 0xb1, 0xb7, 0xb9, 0xb9, + 0xba, 0xb9, 0xb9, 0xba, 0xb9, 0xb8, 0xb6, 0xb4, 0xb2, 0xb2, 0xb2, 0xb2, + 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb4, 0xb4, 0xb5, 0xb5, 0xb6, 0xb5, 0xb5, + 0xb6, 0xb6, 0xb6, 0xb8, 0xb9, 0xba, 0xba, 0xbb, 0xbe, 0xc0, 0xc0, 0xbe, + 0xbe, 0xbd, 0xba, 0xb6, 0xaf, 0xa5, 0x9c, 0x98, 0x96, 0x93, 0x90, 0x95, + 0x98, 0x98, 0x97, 0x90, 0x86, 0x84, 0x84, 0x85, 0x83, 0x80, 0x81, 0x80, + 0x7e, 0x77, 0x6e, 0x66, 0x60, 0x5e, 0x60, 0x5f, 0x5d, 0x59, 0x57, 0x56, + 0x5b, 0x64, 0x6b, 0x72, 0x7f, 0x89, 0x8e, 0x93, 0x95, 0x95, 0x8c, 0x77, + 0x5f, 0x50, 0x40, 0x35, 0x37, 0x41, 0x4a, 0x5a, 0x67, 0x6a, 0x67, 0x66, + 0x66, 0x6a, 0x6c, 0x6e, 0x6e, 0x6d, 0x6b, 0x67, 0x63, 0x61, 0x5e, 0x5a, + 0x55, 0x52, 0x51, 0x53, 0x57, 0x56, 0x52, 0x4f, 0x4b, 0x46, 0x44, 0x44, + 0x48, 0x4e, 0x5a, 0x6d, 0x7d, 0x87, 0x8c, 0x92, 0x95, 0x92, 0x90, 0x8f, + 0x91, 0x95, 0x99, 0x9d, 0xa0, 0xa3, 0xa5, 0xa6, 0xa5, 0xa5, 0xa4, 0xa2, + 0x9f, 0x9c, 0x9a, 0x96, 0x92, 0x90, 0x8f, 0x8e, 0x8c, 0x8a, 0x8b, 0x8b, + 0x8b, 0x8a, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8d, 0x8e, 0x8e, 0x8d, + 0x8d, 0x8e, 0x8e, 0x8f, 0x90, 0x91, 0x91, 0x90, 0x8f, 0x8f, 0x8e, 0x8c, + 0x8a, 0x89, 0x89, 0x86, 0x42, 0x45, 0x48, 0x4a, 0x4b, 0x4f, 0x53, 0x55, + 0x56, 0x58, 0x5a, 0x5b, 0x5b, 0x5a, 0x59, 0x5a, 0x59, 0x5a, 0x5a, 0x5b, + 0x5c, 0x5c, 0x5e, 0x5f, 0x5f, 0x5e, 0x60, 0x61, 0x61, 0x60, 0x61, 0x62, + 0x61, 0x61, 0x61, 0x62, 0x63, 0x63, 0x62, 0x62, 0x63, 0x64, 0x63, 0x62, + 0x60, 0x5f, 0x5d, 0x5b, 0x5a, 0x5b, 0x5d, 0x60, 0x61, 0x61, 0x60, 0x61, + 0x61, 0x60, 0x5f, 0x5f, 0x62, 0x6f, 0x7d, 0x85, 0x8e, 0x99, 0xa2, 0xab, + 0xb1, 0xb4, 0xb8, 0xba, 0xbb, 0xbd, 0xbe, 0xc1, 0xc3, 0xc4, 0xc7, 0xc8, + 0xc7, 0xc6, 0xc9, 0xcc, 0xce, 0xcf, 0xcf, 0xd0, 0xd3, 0xd5, 0xd7, 0xd7, + 0xd7, 0xd7, 0xd5, 0xd0, 0xca, 0xc2, 0xc2, 0xc4, 0xc7, 0xcb, 0xcd, 0xd0, + 0xd1, 0xd2, 0xd1, 0xd1, 0xd2, 0xd5, 0xdc, 0xde, 0xd8, 0xca, 0xb8, 0x97, + 0x85, 0x9b, 0xab, 0xaf, 0xac, 0xab, 0xaa, 0xac, 0xad, 0xad, 0xaf, 0xad, + 0xac, 0xad, 0xac, 0xab, 0xa7, 0xa9, 0xae, 0xb1, 0xb3, 0xb1, 0xb5, 0xb9, + 0xb9, 0xb5, 0xb2, 0xb3, 0xb3, 0xb2, 0xb1, 0xb1, 0xb2, 0xb1, 0xb0, 0xaf, + 0xaf, 0xb0, 0xaf, 0xb0, 0xb0, 0xb0, 0xb2, 0xb3, 0xb3, 0xb3, 0xb4, 0xb5, + 0xb7, 0xb8, 0xb9, 0xbb, 0xbd, 0xbe, 0xbd, 0xba, 0xb9, 0xb9, 0xb6, 0xb1, + 0xa9, 0x9f, 0x9b, 0x98, 0x95, 0x90, 0x90, 0x96, 0x99, 0x99, 0x98, 0x92, + 0x89, 0x84, 0x82, 0x81, 0x80, 0x7e, 0x7f, 0x7e, 0x7c, 0x76, 0x6d, 0x67, + 0x62, 0x60, 0x61, 0x5f, 0x5c, 0x5b, 0x5b, 0x61, 0x6f, 0x7c, 0x84, 0x88, + 0x8e, 0x93, 0x95, 0x92, 0x8c, 0x79, 0x5b, 0x44, 0x3a, 0x39, 0x39, 0x3a, + 0x3f, 0x47, 0x50, 0x5d, 0x67, 0x66, 0x63, 0x64, 0x68, 0x6d, 0x70, 0x71, + 0x71, 0x6f, 0x6b, 0x67, 0x63, 0x61, 0x5f, 0x5b, 0x55, 0x52, 0x51, 0x53, + 0x58, 0x55, 0x50, 0x4b, 0x46, 0x40, 0x3d, 0x3d, 0x3f, 0x43, 0x50, 0x67, + 0x7c, 0x89, 0x8f, 0x95, 0x98, 0x96, 0x93, 0x90, 0x8e, 0x8f, 0x93, 0x98, + 0x9b, 0x9d, 0x9f, 0x9f, 0x9f, 0x9f, 0x9d, 0x9c, 0x9a, 0x98, 0x96, 0x93, + 0x8f, 0x8e, 0x8e, 0x8e, 0x8d, 0x8a, 0x8a, 0x8a, 0x8a, 0x89, 0x89, 0x88, + 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8c, 0x8c, 0x8d, 0x8d, + 0x8f, 0x90, 0x90, 0x8f, 0x8f, 0x90, 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x88, + 0x41, 0x46, 0x49, 0x4a, 0x4c, 0x4e, 0x53, 0x55, 0x56, 0x57, 0x5a, 0x5b, + 0x5b, 0x5a, 0x59, 0x5a, 0x59, 0x59, 0x5a, 0x5a, 0x5c, 0x5c, 0x5e, 0x5f, + 0x5e, 0x5f, 0x61, 0x62, 0x61, 0x60, 0x61, 0x62, 0x62, 0x61, 0x61, 0x61, + 0x63, 0x64, 0x64, 0x64, 0x63, 0x63, 0x62, 0x61, 0x60, 0x5d, 0x5b, 0x5b, + 0x5a, 0x5b, 0x5e, 0x61, 0x61, 0x61, 0x61, 0x61, 0x60, 0x60, 0x5f, 0x5f, + 0x61, 0x6d, 0x7b, 0x84, 0x8d, 0x98, 0xa0, 0xa9, 0xaf, 0xb3, 0xb7, 0xb9, + 0xbb, 0xbc, 0xbe, 0xc0, 0xc2, 0xc5, 0xc8, 0xc9, 0xc7, 0xc6, 0xc9, 0xce, + 0xd0, 0xd1, 0xd0, 0xcf, 0xd2, 0xd4, 0xd6, 0xd7, 0xd7, 0xd8, 0xd8, 0xd5, + 0xd0, 0xc6, 0xc0, 0xc0, 0xc4, 0xc8, 0xcd, 0xd1, 0xd5, 0xd6, 0xd4, 0xd0, + 0xce, 0xd0, 0xd6, 0xdc, 0xdd, 0xdb, 0xd2, 0xb8, 0x95, 0x9d, 0xaf, 0xb3, + 0xab, 0xa5, 0xa2, 0xa4, 0xa4, 0xa2, 0xa4, 0xa6, 0xa4, 0xa6, 0xa7, 0xa6, + 0xa1, 0xa0, 0xa4, 0xa6, 0xa6, 0xa1, 0xae, 0xb7, 0xb8, 0xb3, 0xb2, 0xb2, + 0xb2, 0xb0, 0xaf, 0xaf, 0xaf, 0xae, 0xad, 0xab, 0xab, 0xac, 0xac, 0xac, + 0xab, 0xab, 0xad, 0xaf, 0xb0, 0xb1, 0xb1, 0xb3, 0xb5, 0xb7, 0xb8, 0xba, + 0xbc, 0xbc, 0xba, 0xb7, 0xb4, 0xb5, 0xb1, 0xac, 0xa3, 0x9b, 0x9b, 0x98, + 0x94, 0x8f, 0x90, 0x98, 0x9a, 0x9a, 0x98, 0x92, 0x8c, 0x87, 0x84, 0x80, + 0x7e, 0x7e, 0x7e, 0x7d, 0x7b, 0x75, 0x6d, 0x68, 0x64, 0x62, 0x60, 0x61, + 0x65, 0x69, 0x6d, 0x75, 0x82, 0x8a, 0x8e, 0x91, 0x94, 0x99, 0x8f, 0x73, + 0x5f, 0x48, 0x39, 0x35, 0x37, 0x39, 0x3c, 0x3e, 0x43, 0x4c, 0x53, 0x5e, + 0x62, 0x61, 0x61, 0x63, 0x6b, 0x70, 0x73, 0x73, 0x72, 0x70, 0x6c, 0x66, + 0x63, 0x61, 0x5e, 0x5b, 0x55, 0x52, 0x53, 0x55, 0x57, 0x53, 0x4e, 0x4a, + 0x43, 0x3c, 0x3a, 0x38, 0x37, 0x3c, 0x4b, 0x64, 0x7c, 0x8a, 0x91, 0x96, + 0x99, 0x97, 0x94, 0x91, 0x8d, 0x8c, 0x8e, 0x92, 0x95, 0x98, 0x9a, 0x9a, + 0x9a, 0x99, 0x97, 0x96, 0x94, 0x92, 0x91, 0x8f, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8c, 0x8a, 0x89, 0x89, 0x88, 0x87, 0x87, 0x87, 0x88, 0x89, 0x88, 0x88, + 0x88, 0x89, 0x89, 0x89, 0x8b, 0x8c, 0x8c, 0x8b, 0x8c, 0x8e, 0x8e, 0x8f, + 0x8f, 0x8f, 0x8e, 0x8f, 0x8f, 0x8e, 0x8d, 0x8a, 0x41, 0x46, 0x4a, 0x4b, + 0x4c, 0x4e, 0x53, 0x55, 0x56, 0x57, 0x5a, 0x5b, 0x5b, 0x5b, 0x59, 0x5a, + 0x59, 0x59, 0x5a, 0x5a, 0x5c, 0x5d, 0x5e, 0x5f, 0x5e, 0x5f, 0x61, 0x62, + 0x62, 0x60, 0x61, 0x62, 0x62, 0x61, 0x61, 0x61, 0x63, 0x64, 0x64, 0x64, + 0x62, 0x62, 0x62, 0x62, 0x60, 0x5d, 0x5b, 0x5a, 0x5a, 0x5b, 0x5f, 0x61, + 0x61, 0x61, 0x61, 0x60, 0x5f, 0x60, 0x5f, 0x5f, 0x60, 0x6b, 0x79, 0x82, + 0x8c, 0x96, 0x9f, 0xa7, 0xad, 0xb1, 0xb6, 0xb8, 0xba, 0xbc, 0xbd, 0xc0, + 0xc2, 0xc5, 0xc7, 0xc8, 0xc7, 0xc6, 0xca, 0xcf, 0xd1, 0xd1, 0xd0, 0xcf, + 0xd2, 0xd4, 0xd5, 0xd6, 0xd6, 0xd8, 0xd8, 0xd6, 0xd2, 0xc9, 0xc1, 0xbf, + 0xc1, 0xc7, 0xcc, 0xd2, 0xd5, 0xd8, 0xd7, 0xd1, 0xcf, 0xcf, 0xd3, 0xd9, + 0xde, 0xe1, 0xdd, 0xca, 0xa7, 0xa3, 0xb2, 0xb7, 0xb5, 0xaf, 0xa7, 0xa5, + 0xa2, 0x9c, 0x9a, 0x9e, 0x9c, 0x9f, 0xa0, 0xa1, 0x9d, 0x9b, 0x9c, 0x9d, + 0x9d, 0x97, 0xa5, 0xb0, 0xb3, 0xb0, 0xaf, 0xb1, 0xb0, 0xae, 0xac, 0xac, + 0xad, 0xac, 0xab, 0xa9, 0xa9, 0xaa, 0xaa, 0xaa, 0xa9, 0xa9, 0xaa, 0xac, + 0xad, 0xae, 0xae, 0xb1, 0xb4, 0xb5, 0xb7, 0xb9, 0xbb, 0xba, 0xb8, 0xb5, + 0xb2, 0xb1, 0xad, 0xa8, 0x9f, 0x98, 0x9a, 0x98, 0x94, 0x8e, 0x91, 0x99, + 0x9c, 0x9b, 0x99, 0x94, 0x8e, 0x89, 0x86, 0x80, 0x7d, 0x7e, 0x7e, 0x7c, + 0x79, 0x73, 0x6d, 0x69, 0x64, 0x62, 0x63, 0x69, 0x70, 0x75, 0x79, 0x81, + 0x8b, 0x8f, 0x92, 0x94, 0x95, 0x90, 0x79, 0x58, 0x44, 0x34, 0x30, 0x35, + 0x3a, 0x3b, 0x3e, 0x3f, 0x45, 0x4e, 0x56, 0x5f, 0x60, 0x5e, 0x61, 0x65, + 0x6d, 0x73, 0x74, 0x72, 0x70, 0x6c, 0x69, 0x64, 0x62, 0x61, 0x5e, 0x5a, + 0x55, 0x53, 0x54, 0x56, 0x57, 0x53, 0x4e, 0x4a, 0x43, 0x3c, 0x38, 0x35, + 0x34, 0x3a, 0x4a, 0x64, 0x7c, 0x8b, 0x92, 0x97, 0x99, 0x97, 0x94, 0x92, + 0x8d, 0x8a, 0x8a, 0x8e, 0x90, 0x93, 0x94, 0x95, 0x94, 0x94, 0x92, 0x90, + 0x8e, 0x8c, 0x8b, 0x8b, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x88, 0x88, 0x88, + 0x87, 0x85, 0x85, 0x85, 0x87, 0x87, 0x87, 0x86, 0x87, 0x87, 0x87, 0x88, + 0x8a, 0x8b, 0x8b, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x8f, 0x8e, 0x8f, + 0x8f, 0x8e, 0x8d, 0x8a, 0x41, 0x47, 0x4a, 0x4b, 0x4c, 0x4f, 0x52, 0x54, + 0x55, 0x58, 0x5a, 0x5b, 0x5b, 0x5b, 0x5a, 0x59, 0x59, 0x59, 0x5a, 0x5a, + 0x5c, 0x5d, 0x5e, 0x5e, 0x5f, 0x5f, 0x61, 0x61, 0x61, 0x60, 0x61, 0x62, + 0x61, 0x62, 0x62, 0x62, 0x63, 0x64, 0x64, 0x64, 0x62, 0x61, 0x62, 0x61, + 0x5f, 0x5d, 0x5b, 0x5a, 0x5b, 0x5d, 0x5f, 0x61, 0x61, 0x61, 0x60, 0x5e, + 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x67, 0x76, 0x80, 0x8a, 0x95, 0x9d, 0xa4, + 0xab, 0xaf, 0xb4, 0xb6, 0xb9, 0xbc, 0xbd, 0xbe, 0xc1, 0xc3, 0xc7, 0xc8, + 0xc7, 0xc6, 0xcb, 0xd1, 0xd2, 0xd1, 0xcf, 0xd0, 0xd2, 0xd3, 0xd5, 0xd5, + 0xd5, 0xd5, 0xd6, 0xd5, 0xd3, 0xcd, 0xc5, 0xc0, 0xbe, 0xc4, 0xcc, 0xd2, + 0xd5, 0xd7, 0xda, 0xd7, 0xd4, 0xd2, 0xd1, 0xd7, 0xde, 0xe3, 0xe3, 0xd8, + 0xbf, 0xb0, 0xb3, 0xb9, 0xc5, 0xc9, 0xbd, 0xb3, 0xad, 0xa1, 0x95, 0x97, + 0x95, 0x94, 0x94, 0x98, 0x9a, 0x96, 0x94, 0x95, 0x95, 0x8f, 0x98, 0xa1, + 0xa4, 0xa3, 0xa5, 0xa8, 0xa9, 0xa8, 0xa7, 0xa6, 0xa8, 0xa7, 0xa6, 0xa5, + 0xa5, 0xa6, 0xa7, 0xa7, 0xa7, 0xa5, 0xa6, 0xa8, 0xa9, 0xa9, 0xaa, 0xae, + 0xb2, 0xb4, 0xb6, 0xb8, 0xb9, 0xb7, 0xb6, 0xb4, 0xb1, 0xae, 0xa9, 0xa4, + 0x9c, 0x95, 0x97, 0x96, 0x93, 0x90, 0x94, 0x9a, 0x9d, 0x9d, 0x9c, 0x98, + 0x93, 0x8d, 0x88, 0x7f, 0x7b, 0x7d, 0x7c, 0x7a, 0x77, 0x72, 0x6b, 0x65, + 0x63, 0x65, 0x6e, 0x7b, 0x82, 0x86, 0x88, 0x8c, 0x91, 0x94, 0x93, 0x91, + 0x87, 0x6b, 0x47, 0x36, 0x32, 0x31, 0x32, 0x37, 0x3c, 0x3e, 0x3f, 0x41, + 0x48, 0x52, 0x59, 0x5f, 0x5d, 0x5d, 0x63, 0x69, 0x70, 0x74, 0x71, 0x6b, + 0x67, 0x63, 0x62, 0x61, 0x60, 0x5e, 0x5d, 0x59, 0x56, 0x55, 0x56, 0x58, + 0x57, 0x53, 0x4f, 0x4c, 0x45, 0x3e, 0x3a, 0x37, 0x37, 0x3d, 0x4c, 0x66, + 0x7e, 0x8c, 0x92, 0x97, 0x9a, 0x98, 0x95, 0x92, 0x8c, 0x87, 0x85, 0x87, + 0x8a, 0x8c, 0x8a, 0x89, 0x89, 0x89, 0x87, 0x84, 0x82, 0x81, 0x80, 0x81, + 0x81, 0x83, 0x83, 0x84, 0x84, 0x84, 0x85, 0x85, 0x84, 0x83, 0x82, 0x84, + 0x86, 0x86, 0x85, 0x84, 0x86, 0x85, 0x85, 0x86, 0x88, 0x89, 0x89, 0x89, + 0x8a, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8c, 0x8d, 0x8c, 0x8c, 0x8c, 0x8a, + 0x40, 0x46, 0x49, 0x4b, 0x4c, 0x4e, 0x52, 0x54, 0x56, 0x58, 0x5b, 0x5b, + 0x5a, 0x59, 0x59, 0x58, 0x58, 0x59, 0x5a, 0x59, 0x5b, 0x5d, 0x5d, 0x5e, + 0x5f, 0x5e, 0x60, 0x5f, 0x5f, 0x5f, 0x60, 0x60, 0x62, 0x62, 0x62, 0x61, + 0x63, 0x64, 0x64, 0x64, 0x62, 0x61, 0x61, 0x60, 0x5d, 0x5c, 0x5c, 0x5c, + 0x5d, 0x5d, 0x5f, 0x5f, 0x60, 0x60, 0x5f, 0x5e, 0x5f, 0x5f, 0x5e, 0x5e, + 0x5e, 0x64, 0x72, 0x7d, 0x8a, 0x95, 0x9c, 0xa1, 0xa7, 0xab, 0xb0, 0xb4, + 0xb7, 0xbb, 0xbc, 0xbd, 0xbf, 0xc3, 0xc5, 0xc6, 0xc6, 0xc6, 0xcc, 0xd1, + 0xd2, 0xcf, 0xce, 0xd1, 0xd4, 0xd5, 0xd5, 0xd5, 0xd4, 0xd1, 0xd1, 0xd3, + 0xd3, 0xd0, 0xc9, 0xc5, 0xbf, 0xc1, 0xc8, 0xce, 0xd2, 0xd6, 0xda, 0xdb, + 0xd8, 0xd6, 0xd3, 0xd5, 0xdb, 0xde, 0xdf, 0xde, 0xd9, 0xc7, 0xb8, 0xb3, + 0xb5, 0xc6, 0xd1, 0xd0, 0xce, 0xc8, 0xbf, 0xb8, 0xad, 0xa4, 0x9f, 0x9d, + 0x9f, 0xa0, 0x9e, 0x9d, 0x9c, 0x99, 0x95, 0x96, 0x95, 0x91, 0x8f, 0x91, + 0x95, 0x98, 0x9a, 0x99, 0x99, 0x97, 0x97, 0x96, 0x97, 0x98, 0x9c, 0x9e, + 0x9e, 0x9e, 0xa1, 0xa3, 0xa3, 0xa4, 0xa6, 0xaa, 0xaf, 0xb2, 0xb6, 0xb7, + 0xb8, 0xb6, 0xb5, 0xb3, 0xaf, 0xa9, 0xa4, 0xa0, 0x9a, 0x94, 0x96, 0x98, + 0x98, 0x97, 0x99, 0x9e, 0xa1, 0xa2, 0xa0, 0x9c, 0x98, 0x91, 0x8b, 0x82, + 0x7a, 0x79, 0x78, 0x77, 0x75, 0x6e, 0x67, 0x61, 0x68, 0x71, 0x7f, 0x8e, + 0x93, 0x94, 0x95, 0x95, 0x95, 0x8d, 0x7b, 0x68, 0x4b, 0x34, 0x2f, 0x31, + 0x33, 0x34, 0x35, 0x39, 0x3c, 0x3f, 0x40, 0x42, 0x4b, 0x57, 0x5c, 0x5e, + 0x5c, 0x60, 0x6b, 0x70, 0x75, 0x73, 0x6b, 0x65, 0x61, 0x5d, 0x5d, 0x5e, + 0x5f, 0x5e, 0x5d, 0x5a, 0x58, 0x58, 0x59, 0x59, 0x58, 0x54, 0x50, 0x4d, + 0x4a, 0x47, 0x44, 0x42, 0x43, 0x47, 0x54, 0x6a, 0x80, 0x8e, 0x93, 0x98, + 0x9a, 0x9a, 0x97, 0x94, 0x8f, 0x88, 0x81, 0x80, 0x80, 0x80, 0x7b, 0x75, + 0x74, 0x74, 0x73, 0x70, 0x6f, 0x6e, 0x6f, 0x72, 0x75, 0x77, 0x79, 0x7a, + 0x7a, 0x7b, 0x7c, 0x7e, 0x7e, 0x7e, 0x80, 0x81, 0x82, 0x82, 0x82, 0x83, + 0x83, 0x83, 0x83, 0x84, 0x85, 0x84, 0x85, 0x86, 0x87, 0x87, 0x89, 0x89, + 0x89, 0x8a, 0x8c, 0x8c, 0x8c, 0x8c, 0x8b, 0x8a, 0x41, 0x44, 0x48, 0x4a, + 0x4c, 0x4f, 0x53, 0x54, 0x55, 0x57, 0x59, 0x59, 0x58, 0x57, 0x57, 0x58, + 0x58, 0x59, 0x59, 0x59, 0x5b, 0x5d, 0x5d, 0x5e, 0x5f, 0x5e, 0x5f, 0x60, + 0x5f, 0x5f, 0x60, 0x60, 0x61, 0x62, 0x61, 0x61, 0x63, 0x63, 0x63, 0x63, + 0x62, 0x61, 0x61, 0x60, 0x5d, 0x5b, 0x5c, 0x5c, 0x5d, 0x5d, 0x5f, 0x5f, + 0x5f, 0x5f, 0x60, 0x5e, 0x5f, 0x5e, 0x5e, 0x5e, 0x5d, 0x60, 0x6d, 0x79, + 0x89, 0x95, 0x9c, 0xa0, 0xa5, 0xa9, 0xad, 0xb2, 0xb7, 0xba, 0xbb, 0xbc, + 0xbe, 0xc2, 0xc4, 0xc4, 0xc4, 0xc4, 0xcb, 0xcf, 0xd0, 0xd0, 0xd0, 0xd2, + 0xd5, 0xd6, 0xd6, 0xd7, 0xd3, 0xcf, 0xcd, 0xce, 0xd0, 0xd2, 0xce, 0xca, + 0xc5, 0xc4, 0xc3, 0xc8, 0xcd, 0xd4, 0xda, 0xdd, 0xdc, 0xdb, 0xd7, 0xd4, + 0xd3, 0xd5, 0xd7, 0xda, 0xdd, 0xd6, 0xc8, 0xbd, 0xaf, 0xab, 0xc6, 0xd4, + 0xd6, 0xd4, 0xd2, 0xce, 0xca, 0xc6, 0xc4, 0xc1, 0xbf, 0xbf, 0xbf, 0xbe, + 0xbb, 0xb5, 0xab, 0xac, 0xaa, 0xa2, 0x95, 0x90, 0x94, 0x98, 0x9d, 0x9a, + 0x92, 0x8c, 0x88, 0x84, 0x82, 0x82, 0x85, 0x87, 0x8c, 0x92, 0x97, 0x9b, + 0x9c, 0x9e, 0xa2, 0xa6, 0xaa, 0xad, 0xb3, 0xb5, 0xb6, 0xb5, 0xb4, 0xb2, + 0xab, 0xa4, 0xa0, 0x9e, 0x9b, 0x98, 0x99, 0x9c, 0x9d, 0x9e, 0x9e, 0xa1, + 0xa4, 0xa4, 0xa2, 0x9d, 0x98, 0x91, 0x8c, 0x83, 0x7b, 0x75, 0x72, 0x71, + 0x6e, 0x69, 0x67, 0x6a, 0x79, 0x84, 0x90, 0x99, 0x9a, 0x9a, 0x98, 0x92, + 0x7f, 0x5a, 0x3a, 0x2d, 0x27, 0x28, 0x2f, 0x34, 0x35, 0x36, 0x37, 0x3a, + 0x3e, 0x40, 0x42, 0x47, 0x51, 0x5c, 0x5f, 0x5e, 0x5d, 0x69, 0x76, 0x79, + 0x76, 0x70, 0x67, 0x60, 0x5c, 0x59, 0x5a, 0x5c, 0x5d, 0x5c, 0x5a, 0x59, + 0x58, 0x59, 0x5a, 0x5b, 0x59, 0x54, 0x51, 0x50, 0x50, 0x52, 0x51, 0x51, + 0x52, 0x56, 0x5f, 0x70, 0x83, 0x8f, 0x94, 0x98, 0x9a, 0x9c, 0x9a, 0x98, + 0x93, 0x8d, 0x83, 0x7d, 0x7a, 0x75, 0x6b, 0x62, 0x5f, 0x5f, 0x60, 0x5e, + 0x5e, 0x5e, 0x5f, 0x63, 0x66, 0x68, 0x6b, 0x6b, 0x6c, 0x6e, 0x70, 0x74, + 0x76, 0x78, 0x7b, 0x7e, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x81, + 0x80, 0x81, 0x83, 0x84, 0x85, 0x84, 0x86, 0x86, 0x87, 0x88, 0x8a, 0x8a, + 0x8a, 0x8a, 0x88, 0x87, 0x40, 0x43, 0x47, 0x49, 0x4b, 0x50, 0x53, 0x54, + 0x54, 0x56, 0x58, 0x58, 0x57, 0x57, 0x56, 0x58, 0x59, 0x58, 0x59, 0x58, + 0x5a, 0x5c, 0x5d, 0x5d, 0x5e, 0x5f, 0x5f, 0x60, 0x60, 0x60, 0x60, 0x61, + 0x61, 0x61, 0x62, 0x62, 0x63, 0x64, 0x64, 0x62, 0x63, 0x62, 0x61, 0x60, + 0x5d, 0x5c, 0x5c, 0x5c, 0x5d, 0x5d, 0x5f, 0x60, 0x60, 0x60, 0x60, 0x5e, + 0x5f, 0x5e, 0x5e, 0x5e, 0x5c, 0x5f, 0x6b, 0x76, 0x88, 0x95, 0x9b, 0x9f, + 0xa3, 0xa6, 0xac, 0xb2, 0xb7, 0xb9, 0xba, 0xbb, 0xbe, 0xc0, 0xc1, 0xc1, + 0xc1, 0xc3, 0xcb, 0xce, 0xcf, 0xcf, 0xd1, 0xd4, 0xd6, 0xd6, 0xd7, 0xd8, + 0xd4, 0xcf, 0xcc, 0xcb, 0xce, 0xd0, 0xd0, 0xcf, 0xcc, 0xc7, 0xc2, 0xc2, + 0xc6, 0xd0, 0xda, 0xde, 0xde, 0xdd, 0xd9, 0xd4, 0xce, 0xd1, 0xd4, 0xd7, + 0xdb, 0xdd, 0xd3, 0xc8, 0xb6, 0xa5, 0xb3, 0xcc, 0xd5, 0xd2, 0xd0, 0xd0, + 0xd0, 0xd0, 0xcf, 0xcf, 0xcd, 0xcc, 0xcc, 0xcc, 0xcb, 0xc5, 0xb9, 0xc2, + 0xc5, 0xc1, 0xb6, 0xb0, 0xb1, 0xb4, 0xb5, 0xb0, 0xa5, 0x9d, 0x97, 0x8d, + 0x85, 0x7f, 0x7f, 0x80, 0x83, 0x8b, 0x90, 0x92, 0x93, 0x94, 0x99, 0x9e, + 0xa3, 0xa7, 0xac, 0xaf, 0xb0, 0xb2, 0xb2, 0xb0, 0xa8, 0xa0, 0x9d, 0x9c, + 0x9c, 0x9b, 0x9c, 0x9f, 0x9f, 0xa0, 0xa0, 0xa1, 0xa2, 0xa2, 0xa0, 0x9c, + 0x96, 0x8f, 0x89, 0x83, 0x7b, 0x74, 0x6e, 0x6b, 0x6a, 0x69, 0x71, 0x7e, + 0x8c, 0x93, 0x99, 0x9d, 0x9a, 0x93, 0x8a, 0x76, 0x51, 0x30, 0x22, 0x20, + 0x24, 0x2a, 0x31, 0x35, 0x36, 0x37, 0x39, 0x3b, 0x3e, 0x3f, 0x42, 0x49, + 0x56, 0x5e, 0x5f, 0x5c, 0x5f, 0x74, 0x7f, 0x7e, 0x75, 0x6b, 0x64, 0x5d, + 0x59, 0x58, 0x5a, 0x5c, 0x5d, 0x5c, 0x5a, 0x58, 0x59, 0x5a, 0x5c, 0x5c, + 0x5a, 0x55, 0x53, 0x53, 0x56, 0x5b, 0x5c, 0x5c, 0x5d, 0x5f, 0x67, 0x74, + 0x86, 0x91, 0x96, 0x99, 0x9b, 0x9c, 0x9b, 0x9a, 0x96, 0x90, 0x87, 0x80, + 0x7b, 0x73, 0x66, 0x59, 0x55, 0x54, 0x55, 0x55, 0x55, 0x56, 0x57, 0x59, + 0x5b, 0x5e, 0x60, 0x60, 0x61, 0x63, 0x67, 0x6c, 0x6f, 0x73, 0x78, 0x7b, + 0x7c, 0x7d, 0x7d, 0x7e, 0x7f, 0x7f, 0x7e, 0x7e, 0x7e, 0x80, 0x82, 0x82, + 0x82, 0x82, 0x83, 0x84, 0x84, 0x86, 0x87, 0x87, 0x87, 0x87, 0x86, 0x85, + 0x40, 0x43, 0x47, 0x49, 0x4b, 0x4f, 0x53, 0x54, 0x55, 0x56, 0x58, 0x58, + 0x58, 0x57, 0x57, 0x58, 0x58, 0x58, 0x58, 0x58, 0x5a, 0x5b, 0x5c, 0x5d, + 0x5d, 0x5e, 0x5e, 0x5f, 0x60, 0x5f, 0x61, 0x62, 0x61, 0x61, 0x62, 0x61, + 0x62, 0x64, 0x64, 0x62, 0x63, 0x62, 0x61, 0x60, 0x5e, 0x5c, 0x5b, 0x5c, + 0x5d, 0x5e, 0x60, 0x60, 0x60, 0x60, 0x60, 0x5e, 0x5f, 0x5e, 0x5e, 0x5e, + 0x5c, 0x5f, 0x6a, 0x75, 0x87, 0x94, 0x9b, 0x9f, 0xa2, 0xa5, 0xab, 0xb1, + 0xb6, 0xb9, 0xba, 0xbb, 0xbd, 0xbf, 0xc0, 0xbf, 0xbf, 0xc3, 0xca, 0xcd, + 0xce, 0xce, 0xd1, 0xd3, 0xd5, 0xd7, 0xd7, 0xd7, 0xd3, 0xcf, 0xcc, 0xcb, + 0xcc, 0xcf, 0xd0, 0xd0, 0xcf, 0xc9, 0xc5, 0xc1, 0xc3, 0xcb, 0xd8, 0xdf, + 0xe0, 0xde, 0xda, 0xd6, 0xce, 0xd1, 0xd4, 0xd6, 0xda, 0xdf, 0xd8, 0xce, + 0xbe, 0xaa, 0xaa, 0xc3, 0xcf, 0xd0, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, + 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xcc, 0xc2, 0xcc, 0xd0, 0xce, 0xc8, 0xc2, + 0xc3, 0xc4, 0xc4, 0xbf, 0xb6, 0xad, 0xa8, 0x9d, 0x93, 0x8c, 0x8a, 0x89, + 0x89, 0x8e, 0x90, 0x90, 0x8f, 0x8f, 0x94, 0x9a, 0x9f, 0xa2, 0xa6, 0xa9, + 0xab, 0xad, 0xae, 0xac, 0xa4, 0x9d, 0x9c, 0x9b, 0x9b, 0x9c, 0x9e, 0x9e, + 0x9f, 0xa0, 0xa1, 0xa0, 0xa1, 0xa0, 0x9e, 0x9a, 0x94, 0x8c, 0x87, 0x81, + 0x78, 0x71, 0x6d, 0x6c, 0x6d, 0x6f, 0x7b, 0x8a, 0x96, 0x9a, 0x9c, 0x97, + 0x8b, 0x7f, 0x74, 0x5e, 0x3b, 0x22, 0x1e, 0x21, 0x27, 0x2b, 0x31, 0x35, + 0x37, 0x39, 0x3b, 0x3d, 0x3f, 0x40, 0x43, 0x4b, 0x57, 0x5e, 0x5e, 0x5b, + 0x63, 0x7d, 0x85, 0x81, 0x74, 0x69, 0x62, 0x5b, 0x58, 0x59, 0x5c, 0x5d, + 0x5e, 0x5d, 0x5b, 0x59, 0x59, 0x5b, 0x5c, 0x5d, 0x5a, 0x58, 0x57, 0x57, + 0x5c, 0x62, 0x63, 0x62, 0x63, 0x65, 0x6b, 0x78, 0x88, 0x92, 0x96, 0x99, + 0x9a, 0x9b, 0x9b, 0x9a, 0x97, 0x91, 0x89, 0x81, 0x7c, 0x74, 0x66, 0x57, + 0x52, 0x52, 0x53, 0x53, 0x53, 0x53, 0x53, 0x55, 0x56, 0x59, 0x5b, 0x5b, + 0x5b, 0x5d, 0x61, 0x67, 0x6a, 0x70, 0x77, 0x7a, 0x7c, 0x7c, 0x7c, 0x7d, + 0x7e, 0x7e, 0x7d, 0x7d, 0x7d, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x82, 0x83, + 0x83, 0x84, 0x85, 0x85, 0x86, 0x86, 0x85, 0x84, 0x41, 0x43, 0x47, 0x48, + 0x4b, 0x50, 0x53, 0x54, 0x55, 0x56, 0x58, 0x59, 0x59, 0x59, 0x59, 0x59, + 0x59, 0x58, 0x58, 0x5a, 0x5a, 0x5a, 0x5a, 0x5c, 0x5d, 0x5e, 0x5e, 0x5f, + 0x60, 0x5f, 0x61, 0x62, 0x61, 0x61, 0x61, 0x61, 0x62, 0x63, 0x64, 0x63, + 0x63, 0x61, 0x61, 0x60, 0x5f, 0x5e, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x5f, 0x5d, 0x5d, 0x5e, 0x5e, 0x5c, 0x5f, 0x68, 0x72, + 0x85, 0x93, 0x9c, 0x9f, 0xa1, 0xa3, 0xa8, 0xb0, 0xb6, 0xb9, 0xbb, 0xbb, + 0xbc, 0xbd, 0xbe, 0xbe, 0xbe, 0xc1, 0xc8, 0xc9, 0xcb, 0xcd, 0xd0, 0xd2, + 0xd4, 0xd5, 0xd6, 0xd5, 0xd2, 0xcf, 0xcd, 0xcc, 0xcc, 0xcc, 0xcf, 0xd0, + 0xce, 0xcd, 0xcb, 0xc5, 0xc2, 0xc4, 0xd1, 0xde, 0xdf, 0xde, 0xdc, 0xdb, + 0xd5, 0xd3, 0xd3, 0xd4, 0xd6, 0xdc, 0xd9, 0xd4, 0xc9, 0xb7, 0xa8, 0xb2, + 0xbd, 0xca, 0xd0, 0xd0, 0xd0, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd1, 0xd1, + 0xd1, 0xd0, 0xcf, 0xd1, 0xd2, 0xd2, 0xd1, 0xcf, 0xce, 0xce, 0xce, 0xcb, + 0xc7, 0xc3, 0xbf, 0xb8, 0xb2, 0xac, 0xaa, 0xa7, 0xa3, 0x9f, 0x9a, 0x96, + 0x93, 0x90, 0x94, 0x99, 0x9b, 0x9c, 0x9f, 0xa1, 0xa2, 0xa5, 0xa6, 0xa5, + 0x9f, 0x9a, 0x99, 0x99, 0x99, 0x9b, 0x9b, 0x9c, 0x9c, 0x9e, 0x9e, 0x9c, + 0x9b, 0x99, 0x98, 0x95, 0x8e, 0x88, 0x83, 0x7d, 0x73, 0x6f, 0x71, 0x76, + 0x7a, 0x80, 0x8c, 0x96, 0x9b, 0x9a, 0x92, 0x7d, 0x64, 0x55, 0x4d, 0x43, + 0x30, 0x23, 0x22, 0x25, 0x29, 0x2e, 0x33, 0x37, 0x39, 0x3b, 0x3d, 0x40, + 0x41, 0x42, 0x45, 0x4f, 0x5a, 0x5d, 0x5c, 0x5b, 0x6d, 0x88, 0x8b, 0x83, + 0x72, 0x66, 0x60, 0x5b, 0x5a, 0x5d, 0x60, 0x61, 0x5f, 0x5e, 0x5c, 0x5a, + 0x5a, 0x5c, 0x5d, 0x5e, 0x5d, 0x5c, 0x5d, 0x5f, 0x65, 0x6b, 0x6d, 0x6c, + 0x6c, 0x6d, 0x73, 0x7e, 0x8a, 0x92, 0x95, 0x98, 0x99, 0x9a, 0x9a, 0x99, + 0x96, 0x91, 0x89, 0x83, 0x7e, 0x76, 0x6a, 0x5a, 0x55, 0x53, 0x54, 0x54, + 0x54, 0x55, 0x55, 0x54, 0x55, 0x57, 0x57, 0x57, 0x57, 0x57, 0x59, 0x5e, + 0x64, 0x6d, 0x76, 0x7a, 0x7b, 0x7c, 0x7b, 0x7c, 0x7d, 0x7c, 0x7c, 0x7c, + 0x7d, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x80, 0x81, 0x82, 0x81, 0x82, 0x83, + 0x84, 0x84, 0x83, 0x83, 0x42, 0x44, 0x47, 0x49, 0x4b, 0x50, 0x53, 0x54, + 0x54, 0x55, 0x58, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x58, 0x58, 0x5a, + 0x59, 0x59, 0x5a, 0x5b, 0x5d, 0x5d, 0x5e, 0x5f, 0x60, 0x5f, 0x61, 0x62, + 0x61, 0x61, 0x62, 0x61, 0x62, 0x64, 0x64, 0x62, 0x63, 0x61, 0x60, 0x60, + 0x5f, 0x5e, 0x5d, 0x5e, 0x5e, 0x5e, 0x60, 0x5f, 0x5f, 0x5f, 0x5f, 0x60, + 0x5d, 0x5e, 0x5f, 0x5f, 0x5f, 0x61, 0x65, 0x6e, 0x82, 0x93, 0x9c, 0x9f, + 0x9f, 0xa1, 0xa7, 0xaf, 0xb6, 0xba, 0xbb, 0xbb, 0xba, 0xbb, 0xbb, 0xbb, + 0xbc, 0xbf, 0xc4, 0xc6, 0xc7, 0xca, 0xce, 0xcf, 0xd1, 0xd3, 0xd4, 0xd4, + 0xd0, 0xcf, 0xce, 0xcc, 0xcb, 0xca, 0xcd, 0xcd, 0xca, 0xcb, 0xcc, 0xca, + 0xc8, 0xc4, 0xc8, 0xd5, 0xde, 0xe1, 0xe0, 0xdf, 0xdb, 0xd6, 0xd2, 0xcd, + 0xcd, 0xd6, 0xd9, 0xd5, 0xc9, 0xb4, 0x9c, 0x8f, 0x91, 0xa3, 0xb5, 0xbe, + 0xc2, 0xc6, 0xc8, 0xc9, 0xcb, 0xcc, 0xcd, 0xcf, 0xd0, 0xd2, 0xd2, 0xd2, + 0xd2, 0xd1, 0xd1, 0xd0, 0xcf, 0xcf, 0xd2, 0xd2, 0xd0, 0xce, 0xce, 0xcc, + 0xca, 0xc8, 0xc6, 0xc3, 0xbd, 0xb6, 0xb0, 0xac, 0xa8, 0xa4, 0xa4, 0xa6, + 0xa5, 0xa3, 0xa0, 0x9f, 0x9d, 0x9c, 0x9c, 0x9b, 0x97, 0x95, 0x95, 0x95, + 0x95, 0x96, 0x96, 0x95, 0x95, 0x96, 0x95, 0x91, 0x8e, 0x8e, 0x8f, 0x8d, + 0x89, 0x84, 0x80, 0x7b, 0x77, 0x7a, 0x83, 0x8a, 0x8f, 0x95, 0x9b, 0x97, + 0x8a, 0x7e, 0x69, 0x53, 0x49, 0x46, 0x44, 0x3d, 0x2c, 0x24, 0x26, 0x29, + 0x2e, 0x31, 0x35, 0x3a, 0x3c, 0x3f, 0x41, 0x43, 0x44, 0x45, 0x48, 0x54, + 0x5e, 0x5e, 0x5c, 0x5f, 0x7d, 0x90, 0x8b, 0x80, 0x6e, 0x65, 0x60, 0x5d, + 0x5e, 0x62, 0x66, 0x65, 0x63, 0x60, 0x5e, 0x5c, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x62, 0x64, 0x67, 0x6e, 0x75, 0x77, 0x75, 0x75, 0x75, 0x79, 0x81, + 0x8d, 0x93, 0x95, 0x97, 0x97, 0x98, 0x98, 0x98, 0x95, 0x90, 0x88, 0x81, + 0x7d, 0x77, 0x70, 0x64, 0x5e, 0x5b, 0x59, 0x58, 0x57, 0x57, 0x57, 0x57, + 0x58, 0x58, 0x57, 0x57, 0x57, 0x55, 0x55, 0x5c, 0x63, 0x6e, 0x79, 0x7e, + 0x80, 0x80, 0x80, 0x7f, 0x80, 0x80, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x7f, 0x7f, 0x81, 0x81, 0x81, 0x80, 0x81, 0x81, 0x82, 0x83, 0x84, 0x85, + 0x44, 0x45, 0x47, 0x49, 0x4c, 0x51, 0x51, 0x53, 0x53, 0x55, 0x58, 0x58, + 0x58, 0x58, 0x59, 0x59, 0x59, 0x58, 0x58, 0x59, 0x59, 0x59, 0x5b, 0x5c, + 0x5d, 0x5c, 0x5f, 0x61, 0x60, 0x5f, 0x5f, 0x61, 0x61, 0x62, 0x62, 0x62, + 0x62, 0x63, 0x64, 0x62, 0x63, 0x61, 0x60, 0x60, 0x5e, 0x5d, 0x5e, 0x5e, + 0x5e, 0x5e, 0x5f, 0x5e, 0x5e, 0x5f, 0x60, 0x61, 0x60, 0x61, 0x61, 0x5f, + 0x60, 0x62, 0x65, 0x6d, 0x80, 0x91, 0x9a, 0x9f, 0x9f, 0xa0, 0xa5, 0xad, + 0xb4, 0xb9, 0xbb, 0xba, 0xb8, 0xb8, 0xba, 0xb9, 0xb8, 0xbc, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc9, 0xcb, 0xcd, 0xcf, 0xd0, 0xd1, 0xce, 0xcd, 0xcd, 0xcc, + 0xca, 0xc8, 0xcb, 0xcb, 0xc8, 0xc7, 0xc9, 0xcb, 0xcb, 0xc9, 0xcb, 0xcf, + 0xd5, 0xda, 0xde, 0xda, 0xd2, 0xcb, 0xc9, 0xcb, 0xce, 0xca, 0xce, 0xc9, + 0xb2, 0x8e, 0x74, 0x67, 0x60, 0x5b, 0x65, 0x73, 0x7d, 0x89, 0x90, 0x96, + 0x99, 0x9e, 0xa5, 0xab, 0xb1, 0xb8, 0xba, 0xbb, 0xbc, 0xbe, 0xc1, 0xc4, + 0xc5, 0xc7, 0xcb, 0xcf, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2, 0xd0, 0xd0, 0xcf, + 0xcb, 0xc8, 0xc7, 0xc5, 0xc3, 0xc0, 0xbf, 0xbd, 0xbc, 0xb9, 0xb3, 0xae, + 0xa7, 0xa0, 0x9c, 0x98, 0x94, 0x93, 0x92, 0x91, 0x91, 0x90, 0x8d, 0x8c, + 0x8c, 0x8d, 0x8d, 0x8b, 0x8b, 0x8c, 0x8f, 0x8f, 0x8d, 0x8b, 0x8a, 0x8a, + 0x89, 0x90, 0x98, 0x9c, 0x9d, 0x9d, 0x90, 0x70, 0x52, 0x46, 0x44, 0x4d, + 0x50, 0x4c, 0x47, 0x3c, 0x2a, 0x25, 0x2b, 0x2e, 0x31, 0x34, 0x38, 0x3c, + 0x3e, 0x41, 0x45, 0x45, 0x45, 0x47, 0x4c, 0x58, 0x5d, 0x5b, 0x5c, 0x66, + 0x86, 0x90, 0x82, 0x77, 0x6b, 0x66, 0x62, 0x61, 0x63, 0x67, 0x6a, 0x68, + 0x65, 0x63, 0x60, 0x5d, 0x5c, 0x5f, 0x60, 0x62, 0x64, 0x67, 0x6b, 0x70, + 0x77, 0x7c, 0x7e, 0x7d, 0x7a, 0x79, 0x7a, 0x81, 0x8b, 0x92, 0x94, 0x94, + 0x94, 0x94, 0x95, 0x95, 0x93, 0x8d, 0x86, 0x80, 0x7c, 0x78, 0x76, 0x6f, + 0x69, 0x67, 0x64, 0x5f, 0x5c, 0x5a, 0x5a, 0x5b, 0x5a, 0x5a, 0x59, 0x58, + 0x57, 0x56, 0x59, 0x61, 0x68, 0x73, 0x7f, 0x86, 0x87, 0x87, 0x87, 0x88, + 0x87, 0x87, 0x88, 0x89, 0x89, 0x88, 0x87, 0x87, 0x87, 0x88, 0x87, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x87, 0x88, 0x8b, 0x8d, 0x46, 0x46, 0x47, 0x49, + 0x4c, 0x50, 0x51, 0x52, 0x53, 0x56, 0x58, 0x58, 0x58, 0x58, 0x59, 0x59, + 0x59, 0x58, 0x58, 0x59, 0x59, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5f, 0x61, + 0x61, 0x5f, 0x60, 0x62, 0x63, 0x63, 0x62, 0x62, 0x62, 0x64, 0x64, 0x63, + 0x63, 0x61, 0x61, 0x61, 0x5f, 0x5d, 0x5d, 0x5e, 0x5f, 0x60, 0x60, 0x5f, + 0x5f, 0x5f, 0x5f, 0x60, 0x61, 0x63, 0x62, 0x61, 0x62, 0x64, 0x67, 0x6e, + 0x7e, 0x90, 0x98, 0x9e, 0x9e, 0x9f, 0xa3, 0xab, 0xb4, 0xb9, 0xba, 0xb9, + 0xb8, 0xb8, 0xb9, 0xb9, 0xb7, 0xb9, 0xbe, 0xc0, 0xc0, 0xbe, 0xc2, 0xc7, + 0xc9, 0xcb, 0xcd, 0xce, 0xcc, 0xcc, 0xcb, 0xc9, 0xc8, 0xc6, 0xc8, 0xca, + 0xcd, 0xd2, 0xd2, 0xcb, 0xc6, 0xc4, 0xcc, 0xd0, 0xd1, 0xd0, 0xce, 0xc8, + 0xc5, 0xc6, 0xcb, 0xd5, 0xd3, 0xb8, 0xb3, 0xb0, 0x9c, 0x74, 0x5b, 0x4f, + 0x4a, 0x4d, 0x5e, 0x59, 0x46, 0x42, 0x42, 0x42, 0x41, 0x47, 0x51, 0x58, + 0x63, 0x71, 0x79, 0x7e, 0x82, 0x88, 0x95, 0xa1, 0xaa, 0xaf, 0xb7, 0xc2, + 0xcb, 0xd0, 0xd1, 0xd3, 0xd2, 0xd0, 0xd1, 0xd2, 0xd1, 0xd0, 0xd1, 0xd0, + 0xcf, 0xcd, 0xcd, 0xcc, 0xca, 0xc8, 0xc4, 0xbf, 0xb7, 0xae, 0xa9, 0xa1, + 0x9c, 0x98, 0x93, 0x90, 0x8f, 0x8c, 0x8b, 0x8b, 0x8c, 0x90, 0x93, 0x95, + 0x96, 0x97, 0x99, 0x99, 0x97, 0x96, 0x96, 0x97, 0x98, 0x9c, 0x9f, 0x9d, + 0x98, 0x8c, 0x6e, 0x46, 0x2f, 0x2b, 0x38, 0x50, 0x58, 0x50, 0x48, 0x39, + 0x28, 0x28, 0x2e, 0x32, 0x34, 0x36, 0x3a, 0x3e, 0x40, 0x44, 0x47, 0x46, + 0x46, 0x48, 0x4f, 0x59, 0x5b, 0x58, 0x5b, 0x6a, 0x87, 0x8c, 0x7a, 0x70, + 0x6a, 0x68, 0x65, 0x66, 0x68, 0x6b, 0x6c, 0x68, 0x65, 0x63, 0x60, 0x5e, + 0x5d, 0x60, 0x61, 0x63, 0x67, 0x6b, 0x71, 0x75, 0x7a, 0x7f, 0x82, 0x81, + 0x7d, 0x7b, 0x7a, 0x7d, 0x86, 0x8e, 0x92, 0x92, 0x92, 0x91, 0x92, 0x92, + 0x90, 0x8a, 0x85, 0x80, 0x7d, 0x7b, 0x7a, 0x77, 0x74, 0x72, 0x70, 0x6a, + 0x63, 0x5f, 0x5d, 0x5c, 0x5c, 0x5c, 0x5a, 0x59, 0x57, 0x58, 0x5e, 0x68, + 0x6e, 0x7a, 0x86, 0x8d, 0x8f, 0x8f, 0x8e, 0x8e, 0x8e, 0x8f, 0x90, 0x8f, + 0x90, 0x90, 0x8f, 0x8f, 0x8f, 0x90, 0x8f, 0x8e, 0x8e, 0x8e, 0x8d, 0x8d, + 0x8e, 0x8f, 0x90, 0x92, 0x48, 0x46, 0x48, 0x49, 0x4c, 0x4f, 0x51, 0x52, + 0x54, 0x57, 0x59, 0x58, 0x58, 0x58, 0x59, 0x58, 0x59, 0x59, 0x59, 0x59, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5f, 0x60, 0x60, 0x60, 0x61, 0x63, + 0x63, 0x63, 0x62, 0x61, 0x62, 0x64, 0x64, 0x63, 0x63, 0x62, 0x61, 0x61, + 0x60, 0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x60, 0x60, 0x60, 0x5f, 0x60, 0x61, + 0x62, 0x63, 0x63, 0x63, 0x64, 0x67, 0x6a, 0x6f, 0x7d, 0x8f, 0x98, 0x9d, + 0x9e, 0x9f, 0xa2, 0xaa, 0xb2, 0xb8, 0xb9, 0xb8, 0xb7, 0xb8, 0xba, 0xba, + 0xb6, 0xb7, 0xbb, 0xbe, 0xbd, 0xba, 0xbe, 0xc5, 0xc7, 0xc9, 0xcc, 0xce, + 0xcc, 0xcc, 0xcc, 0xca, 0xc7, 0xc5, 0xc8, 0xcb, 0xd1, 0xd8, 0xcf, 0xbf, + 0xb9, 0xbd, 0xca, 0xd0, 0xcf, 0xcd, 0xc8, 0xc1, 0xc1, 0xc6, 0xcd, 0xd9, + 0xd3, 0xab, 0xa7, 0xa6, 0x9a, 0x81, 0x70, 0x64, 0x61, 0x67, 0x73, 0x65, + 0x4a, 0x3c, 0x35, 0x2a, 0x20, 0x24, 0x2d, 0x33, 0x3b, 0x48, 0x50, 0x55, + 0x59, 0x5f, 0x6c, 0x78, 0x82, 0x88, 0x91, 0xa2, 0xb4, 0xbf, 0xc4, 0xc9, + 0xcd, 0xcc, 0xcf, 0xd1, 0xd2, 0xd2, 0xd3, 0xd2, 0xd2, 0xd1, 0xd1, 0xd0, + 0xd0, 0xcf, 0xcc, 0xc8, 0xc0, 0xb8, 0xb3, 0xab, 0xa6, 0xa1, 0x9a, 0x96, + 0x93, 0x8f, 0x8f, 0x91, 0x93, 0x97, 0x9b, 0x9d, 0x9e, 0x9f, 0xa0, 0x9e, + 0x9c, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, 0x97, 0x8f, 0x87, 0x77, 0x59, 0x37, + 0x27, 0x27, 0x36, 0x51, 0x59, 0x50, 0x46, 0x36, 0x27, 0x2b, 0x30, 0x33, + 0x36, 0x38, 0x3c, 0x40, 0x42, 0x45, 0x48, 0x47, 0x48, 0x4a, 0x52, 0x5a, + 0x59, 0x56, 0x5a, 0x6c, 0x86, 0x86, 0x74, 0x6c, 0x6a, 0x69, 0x67, 0x69, + 0x6b, 0x6d, 0x6c, 0x67, 0x64, 0x61, 0x60, 0x5d, 0x5d, 0x60, 0x61, 0x64, + 0x69, 0x6e, 0x74, 0x78, 0x7c, 0x81, 0x82, 0x82, 0x7d, 0x7b, 0x79, 0x7b, + 0x81, 0x8a, 0x8e, 0x91, 0x91, 0x8f, 0x90, 0x8f, 0x8e, 0x89, 0x84, 0x80, + 0x7e, 0x7c, 0x7c, 0x7b, 0x7a, 0x7a, 0x79, 0x73, 0x6a, 0x65, 0x62, 0x5f, + 0x5f, 0x5e, 0x5d, 0x5b, 0x5a, 0x5b, 0x62, 0x6c, 0x73, 0x7d, 0x8a, 0x92, + 0x93, 0x94, 0x93, 0x93, 0x94, 0x95, 0x95, 0x95, 0x94, 0x95, 0x95, 0x95, + 0x95, 0x96, 0x95, 0x94, 0x94, 0x93, 0x93, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x49, 0x47, 0x47, 0x48, 0x4a, 0x4f, 0x51, 0x54, 0x56, 0x58, 0x5a, 0x5a, + 0x59, 0x58, 0x59, 0x58, 0x59, 0x59, 0x59, 0x59, 0x57, 0x58, 0x59, 0x5a, + 0x5b, 0x5d, 0x5f, 0x60, 0x60, 0x61, 0x62, 0x63, 0x63, 0x62, 0x61, 0x61, + 0x62, 0x64, 0x64, 0x64, 0x64, 0x62, 0x62, 0x61, 0x60, 0x5e, 0x5e, 0x60, + 0x60, 0x5f, 0x60, 0x61, 0x62, 0x62, 0x61, 0x62, 0x64, 0x65, 0x65, 0x66, + 0x69, 0x6c, 0x6f, 0x72, 0x7c, 0x8d, 0x97, 0x9d, 0x9e, 0x9f, 0xa1, 0xa8, + 0xb1, 0xb7, 0xb8, 0xb6, 0xb5, 0xb6, 0xb9, 0xb8, 0xb4, 0xb4, 0xb8, 0xba, + 0xb8, 0xb4, 0xbb, 0xc4, 0xc7, 0xc9, 0xcd, 0xd0, 0xd1, 0xd1, 0xd0, 0xcd, + 0xc9, 0xc6, 0xc9, 0xce, 0xd6, 0xd7, 0xbe, 0xa7, 0xa5, 0xb5, 0xc7, 0xca, + 0xcd, 0xcd, 0xc8, 0xc2, 0xc6, 0xca, 0xcf, 0xd5, 0xc7, 0x9b, 0xa0, 0xa5, + 0xa4, 0xaf, 0xb1, 0xa9, 0xa5, 0xa5, 0x9b, 0x8b, 0x7c, 0x6f, 0x62, 0x4a, + 0x33, 0x29, 0x28, 0x28, 0x29, 0x2d, 0x2f, 0x31, 0x32, 0x31, 0x34, 0x38, + 0x3e, 0x42, 0x48, 0x5c, 0x77, 0x8c, 0x98, 0xa5, 0xb2, 0xb9, 0xc1, 0xc6, + 0xcb, 0xce, 0xcf, 0xcf, 0xcf, 0xd0, 0xd1, 0xd1, 0xd0, 0xcf, 0xce, 0xcd, + 0xc7, 0xc3, 0xbf, 0xba, 0xb6, 0xb1, 0xaa, 0xa5, 0xa0, 0x9d, 0x9e, 0xa0, + 0xa3, 0xa5, 0xa7, 0xa6, 0xa6, 0xa6, 0xa5, 0xa1, 0x9e, 0x9c, 0x9b, 0x9a, + 0x95, 0x8a, 0x77, 0x69, 0x61, 0x57, 0x48, 0x3b, 0x32, 0x30, 0x36, 0x4d, + 0x57, 0x4e, 0x43, 0x32, 0x28, 0x2e, 0x34, 0x35, 0x37, 0x3b, 0x3e, 0x42, + 0x44, 0x47, 0x49, 0x49, 0x4b, 0x4f, 0x56, 0x5b, 0x57, 0x53, 0x58, 0x6c, + 0x7f, 0x7b, 0x6d, 0x69, 0x6c, 0x6b, 0x6a, 0x6c, 0x6e, 0x6e, 0x6a, 0x64, + 0x61, 0x60, 0x5e, 0x5c, 0x5d, 0x5f, 0x61, 0x65, 0x6b, 0x72, 0x79, 0x7c, + 0x7f, 0x82, 0x82, 0x81, 0x7d, 0x7a, 0x76, 0x75, 0x7a, 0x83, 0x88, 0x8d, + 0x8e, 0x8d, 0x8c, 0x8d, 0x8c, 0x88, 0x82, 0x80, 0x7f, 0x7f, 0x81, 0x82, + 0x83, 0x84, 0x84, 0x7f, 0x77, 0x71, 0x6d, 0x68, 0x65, 0x63, 0x62, 0x62, + 0x60, 0x62, 0x69, 0x72, 0x78, 0x82, 0x8d, 0x96, 0x99, 0x9a, 0x9a, 0x9a, + 0x9c, 0x9d, 0x9c, 0x9c, 0x9b, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9c, 0x9c, 0x9c, 0x9b, 0x9a, 0x9b, 0x9c, 0x9d, 0x4d, 0x48, 0x48, 0x48, + 0x4b, 0x4f, 0x52, 0x55, 0x57, 0x58, 0x5a, 0x5a, 0x59, 0x58, 0x58, 0x58, + 0x59, 0x59, 0x58, 0x57, 0x57, 0x58, 0x58, 0x59, 0x5a, 0x5c, 0x5d, 0x5f, + 0x5f, 0x61, 0x62, 0x63, 0x62, 0x62, 0x61, 0x63, 0x63, 0x63, 0x63, 0x62, + 0x63, 0x63, 0x62, 0x61, 0x5f, 0x5f, 0x61, 0x62, 0x62, 0x61, 0x62, 0x64, + 0x64, 0x64, 0x64, 0x65, 0x68, 0x69, 0x6a, 0x6b, 0x6e, 0x71, 0x73, 0x76, + 0x7d, 0x8b, 0x97, 0x9d, 0x9e, 0x9f, 0xa1, 0xa6, 0xae, 0xb4, 0xb6, 0xb5, + 0xb5, 0xb6, 0xb8, 0xb7, 0xb3, 0xb3, 0xb6, 0xb5, 0xb4, 0xb3, 0xbf, 0xc7, + 0xcb, 0xcd, 0xd1, 0xd4, 0xd5, 0xd6, 0xd7, 0xd5, 0xd0, 0xca, 0xce, 0xd3, + 0xd6, 0xc9, 0xb0, 0xb2, 0xbb, 0xc8, 0xcb, 0xc8, 0xc9, 0xc8, 0xc5, 0xc4, + 0xc7, 0xc5, 0xc5, 0xc5, 0xaf, 0x8b, 0x9b, 0xa3, 0xa1, 0xa7, 0xb6, 0xb8, + 0xb7, 0xb6, 0xae, 0x9e, 0x98, 0x91, 0x8a, 0x81, 0x72, 0x50, 0x35, 0x2d, + 0x2e, 0x31, 0x30, 0x2f, 0x2c, 0x26, 0x26, 0x2c, 0x2d, 0x2d, 0x2c, 0x31, + 0x3c, 0x44, 0x4b, 0x57, 0x6b, 0x7e, 0x8d, 0x97, 0xa2, 0xaf, 0xb5, 0xb7, + 0xb9, 0xbc, 0xc2, 0xc4, 0xc5, 0xc6, 0xc6, 0xc8, 0xc6, 0xc5, 0xc5, 0xc3, + 0xc0, 0xbc, 0xb7, 0xb3, 0xae, 0xab, 0xa7, 0xa8, 0xa8, 0xa7, 0xa7, 0xa5, + 0xa3, 0xa2, 0xa1, 0x9c, 0x99, 0x96, 0x93, 0x88, 0x72, 0x5d, 0x4d, 0x48, + 0x4a, 0x4f, 0x4d, 0x45, 0x40, 0x3c, 0x38, 0x44, 0x4f, 0x46, 0x3b, 0x2c, + 0x2a, 0x32, 0x36, 0x37, 0x38, 0x3d, 0x42, 0x45, 0x47, 0x49, 0x49, 0x4c, + 0x51, 0x54, 0x59, 0x5b, 0x54, 0x52, 0x58, 0x69, 0x76, 0x6e, 0x69, 0x69, + 0x6d, 0x6e, 0x6e, 0x6f, 0x6f, 0x6d, 0x67, 0x61, 0x5e, 0x5e, 0x5d, 0x5d, + 0x5e, 0x5f, 0x61, 0x66, 0x6d, 0x75, 0x7d, 0x80, 0x82, 0x84, 0x83, 0x80, + 0x7c, 0x79, 0x73, 0x6e, 0x70, 0x77, 0x7c, 0x81, 0x86, 0x89, 0x8c, 0x8d, + 0x8b, 0x87, 0x82, 0x81, 0x82, 0x82, 0x86, 0x8b, 0x8e, 0x8f, 0x8f, 0x8c, + 0x85, 0x80, 0x7d, 0x78, 0x73, 0x70, 0x6f, 0x6e, 0x6d, 0x6e, 0x74, 0x7b, + 0x81, 0x89, 0x92, 0x9a, 0x9e, 0x9f, 0xa0, 0xa3, 0xa4, 0xa3, 0xa4, 0xa5, + 0xa5, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0x4f, 0x49, 0x48, 0x49, 0x4b, 0x4f, 0x52, 0x55, + 0x57, 0x58, 0x5a, 0x5a, 0x59, 0x58, 0x58, 0x58, 0x59, 0x59, 0x57, 0x57, + 0x57, 0x58, 0x58, 0x59, 0x5b, 0x5b, 0x5c, 0x5d, 0x5d, 0x5f, 0x61, 0x62, + 0x62, 0x62, 0x62, 0x62, 0x63, 0x63, 0x62, 0x62, 0x63, 0x63, 0x62, 0x61, + 0x5f, 0x5f, 0x61, 0x63, 0x62, 0x63, 0x65, 0x66, 0x66, 0x67, 0x68, 0x69, + 0x6c, 0x6e, 0x6f, 0x70, 0x73, 0x76, 0x79, 0x7b, 0x7f, 0x8a, 0x95, 0x9c, + 0x9e, 0x9f, 0xa0, 0xa4, 0xaa, 0xb0, 0xb3, 0xb5, 0xb6, 0xb7, 0xb7, 0xb6, + 0xb5, 0xb2, 0xb4, 0xb4, 0xb5, 0xbb, 0xc8, 0xcc, 0xce, 0xd0, 0xd5, 0xd7, + 0xd6, 0xd8, 0xd8, 0xd8, 0xd6, 0xce, 0xd1, 0xd3, 0xd2, 0xca, 0xc4, 0xc8, + 0xcb, 0xcd, 0xcb, 0xc6, 0xc4, 0xc2, 0xc2, 0xc0, 0xb6, 0xa4, 0x9e, 0x9a, + 0x83, 0x83, 0xa3, 0xac, 0xa2, 0x9f, 0xa8, 0xaf, 0xae, 0xaa, 0xac, 0xab, + 0xaa, 0x9d, 0x98, 0x99, 0x94, 0x7d, 0x64, 0x5b, 0x5b, 0x60, 0x59, 0x4c, + 0x40, 0x2f, 0x2a, 0x34, 0x35, 0x34, 0x30, 0x32, 0x37, 0x3b, 0x3d, 0x42, + 0x47, 0x4c, 0x50, 0x53, 0x5a, 0x68, 0x73, 0x79, 0x7d, 0x83, 0x8d, 0x94, + 0x9a, 0x9e, 0xa3, 0xa9, 0xaf, 0xb5, 0xb8, 0xba, 0xba, 0xb7, 0xb3, 0xaf, + 0xaa, 0xa6, 0xa1, 0xa2, 0xa1, 0xa0, 0x9e, 0x9d, 0x9c, 0x9a, 0x97, 0x91, + 0x86, 0x7a, 0x6e, 0x58, 0x3f, 0x3e, 0x42, 0x45, 0x49, 0x50, 0x52, 0x4d, + 0x4a, 0x46, 0x3e, 0x3c, 0x43, 0x3c, 0x32, 0x28, 0x2c, 0x34, 0x37, 0x38, + 0x39, 0x3f, 0x44, 0x48, 0x4a, 0x4b, 0x4b, 0x50, 0x57, 0x5a, 0x5d, 0x59, + 0x51, 0x52, 0x58, 0x66, 0x6e, 0x68, 0x68, 0x6a, 0x6d, 0x6f, 0x70, 0x70, + 0x6e, 0x6a, 0x64, 0x5f, 0x5c, 0x5b, 0x5d, 0x5f, 0x5f, 0x5e, 0x61, 0x67, + 0x6e, 0x79, 0x7f, 0x81, 0x82, 0x84, 0x83, 0x80, 0x7c, 0x77, 0x70, 0x68, + 0x66, 0x69, 0x6e, 0x74, 0x79, 0x80, 0x86, 0x89, 0x8b, 0x8a, 0x86, 0x84, + 0x84, 0x85, 0x8b, 0x91, 0x96, 0x97, 0x98, 0x95, 0x90, 0x8c, 0x89, 0x86, + 0x82, 0x80, 0x7f, 0x7e, 0x7d, 0x7c, 0x80, 0x86, 0x8a, 0x91, 0x99, 0xa0, + 0xa3, 0xa4, 0xa6, 0xa8, 0xa9, 0xaa, 0xaa, 0xa9, 0xaa, 0xa9, 0xaa, 0xab, + 0xab, 0xaa, 0xaa, 0xab, 0xac, 0xab, 0xa9, 0xaa, 0xa9, 0xa9, 0xa8, 0xa9, + 0x52, 0x4a, 0x48, 0x4a, 0x4d, 0x50, 0x52, 0x56, 0x58, 0x58, 0x59, 0x5a, + 0x5a, 0x59, 0x59, 0x58, 0x58, 0x58, 0x58, 0x57, 0x57, 0x57, 0x57, 0x58, + 0x5b, 0x5c, 0x5c, 0x5c, 0x5d, 0x5e, 0x60, 0x61, 0x61, 0x61, 0x61, 0x63, + 0x62, 0x62, 0x61, 0x60, 0x62, 0x62, 0x61, 0x61, 0x61, 0x61, 0x62, 0x63, + 0x64, 0x65, 0x66, 0x67, 0x69, 0x6a, 0x6b, 0x6c, 0x6f, 0x70, 0x71, 0x74, + 0x77, 0x7a, 0x7d, 0x7e, 0x80, 0x89, 0x93, 0x9c, 0x9f, 0xa1, 0xa2, 0xa3, + 0xa8, 0xae, 0xb2, 0xb5, 0xb6, 0xb6, 0xb6, 0xb6, 0xb5, 0xb3, 0xb3, 0xb5, + 0xb8, 0xc1, 0xcd, 0xcd, 0xce, 0xd0, 0xd5, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, + 0xd7, 0xd0, 0xce, 0xcc, 0xc7, 0xc5, 0xc7, 0xca, 0xcb, 0xcc, 0xcd, 0xc4, + 0xbb, 0xb8, 0xb3, 0x9f, 0x88, 0x79, 0x74, 0x72, 0x67, 0x7b, 0x9a, 0xa1, + 0x97, 0x99, 0x9c, 0xa8, 0xad, 0xae, 0xb3, 0xb5, 0xb7, 0xb5, 0xb4, 0xb5, + 0xaf, 0x9e, 0x8a, 0x7e, 0x73, 0x77, 0x83, 0x7d, 0x6f, 0x4f, 0x35, 0x39, + 0x3b, 0x39, 0x36, 0x37, 0x3c, 0x40, 0x42, 0x45, 0x48, 0x48, 0x48, 0x46, + 0x46, 0x49, 0x4f, 0x51, 0x53, 0x56, 0x5b, 0x60, 0x63, 0x66, 0x6c, 0x77, + 0x88, 0x95, 0x9d, 0xa4, 0xa9, 0xa9, 0xa6, 0xa4, 0xa1, 0x9d, 0x9b, 0x9c, + 0x9d, 0x9e, 0x9c, 0x9a, 0x98, 0x95, 0x8b, 0x79, 0x60, 0x4c, 0x40, 0x31, + 0x29, 0x36, 0x42, 0x46, 0x48, 0x4c, 0x4e, 0x4e, 0x4f, 0x4d, 0x45, 0x3d, + 0x3b, 0x33, 0x2c, 0x26, 0x2d, 0x34, 0x36, 0x37, 0x3a, 0x41, 0x47, 0x4a, + 0x4c, 0x4c, 0x4d, 0x53, 0x5b, 0x5d, 0x5d, 0x57, 0x50, 0x52, 0x59, 0x66, + 0x6a, 0x68, 0x69, 0x6a, 0x6c, 0x6f, 0x70, 0x6f, 0x6d, 0x68, 0x61, 0x5d, + 0x5c, 0x5c, 0x5d, 0x60, 0x5f, 0x5f, 0x61, 0x67, 0x6f, 0x7b, 0x80, 0x82, + 0x83, 0x83, 0x82, 0x80, 0x7c, 0x78, 0x6f, 0x64, 0x5e, 0x60, 0x64, 0x6a, + 0x71, 0x79, 0x80, 0x84, 0x8a, 0x8c, 0x8a, 0x88, 0x87, 0x88, 0x8e, 0x95, + 0x99, 0x9b, 0x9d, 0x9b, 0x96, 0x93, 0x92, 0x8f, 0x8c, 0x8b, 0x8a, 0x89, + 0x88, 0x86, 0x89, 0x8d, 0x90, 0x95, 0x9d, 0xa3, 0xa5, 0xa7, 0xa8, 0xa9, + 0xab, 0xac, 0xac, 0xad, 0xae, 0xac, 0xac, 0xad, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xad, 0xab, 0xaa, 0xaa, 0xac, 0x54, 0x4b, 0x49, 0x4a, + 0x4d, 0x4f, 0x52, 0x56, 0x57, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5a, 0x58, + 0x58, 0x57, 0x58, 0x58, 0x57, 0x57, 0x57, 0x58, 0x5a, 0x5c, 0x5b, 0x5c, + 0x5d, 0x5e, 0x5f, 0x61, 0x61, 0x61, 0x61, 0x63, 0x62, 0x61, 0x61, 0x60, + 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x63, 0x63, 0x64, 0x66, 0x66, 0x68, + 0x6b, 0x6d, 0x6d, 0x6e, 0x70, 0x72, 0x74, 0x77, 0x7a, 0x7d, 0x7f, 0x80, + 0x81, 0x88, 0x92, 0x9c, 0xa0, 0xa1, 0xa2, 0xa3, 0xa7, 0xac, 0xb0, 0xb4, + 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb4, 0xb4, 0xb7, 0xbb, 0xc5, 0xd0, 0xce, + 0xce, 0xd0, 0xd6, 0xd8, 0xd8, 0xd8, 0xd7, 0xd7, 0xd7, 0xcf, 0xca, 0xc7, + 0xc3, 0xc5, 0xc9, 0xca, 0xc9, 0xc5, 0xc1, 0xb4, 0xa8, 0xa4, 0xa0, 0x89, + 0x72, 0x68, 0x65, 0x65, 0x63, 0x7b, 0x92, 0x96, 0x8f, 0x94, 0x95, 0xa0, + 0xa7, 0xb0, 0xb9, 0xbc, 0xbf, 0xc1, 0xc2, 0xc0, 0xb8, 0xa8, 0x97, 0x8a, + 0x7a, 0x7a, 0x8d, 0x8e, 0x7f, 0x5c, 0x3b, 0x3b, 0x3e, 0x3c, 0x39, 0x3a, + 0x3e, 0x42, 0x45, 0x48, 0x4b, 0x4c, 0x4a, 0x48, 0x45, 0x44, 0x46, 0x48, + 0x48, 0x4a, 0x4b, 0x4d, 0x4e, 0x50, 0x54, 0x5f, 0x6f, 0x7b, 0x81, 0x8a, + 0x92, 0x98, 0x98, 0x98, 0x98, 0x96, 0x96, 0x97, 0x98, 0x99, 0x95, 0x8f, + 0x8b, 0x85, 0x77, 0x5e, 0x45, 0x35, 0x2d, 0x25, 0x26, 0x35, 0x42, 0x45, + 0x46, 0x48, 0x4b, 0x4d, 0x51, 0x50, 0x4a, 0x40, 0x39, 0x2e, 0x28, 0x26, + 0x30, 0x35, 0x37, 0x38, 0x3b, 0x42, 0x48, 0x4b, 0x4c, 0x4b, 0x4e, 0x55, + 0x5c, 0x5e, 0x5c, 0x56, 0x50, 0x52, 0x59, 0x65, 0x69, 0x69, 0x6a, 0x6b, + 0x6c, 0x6e, 0x6f, 0x6e, 0x6c, 0x67, 0x60, 0x5c, 0x5c, 0x5d, 0x5e, 0x60, + 0x5f, 0x5f, 0x61, 0x67, 0x70, 0x7c, 0x81, 0x83, 0x83, 0x83, 0x83, 0x80, + 0x7d, 0x78, 0x70, 0x63, 0x5a, 0x5b, 0x5d, 0x63, 0x6b, 0x73, 0x7a, 0x7f, + 0x85, 0x8a, 0x8a, 0x89, 0x89, 0x8a, 0x8e, 0x96, 0x9a, 0x9d, 0x9f, 0x9e, + 0x9a, 0x98, 0x96, 0x93, 0x91, 0x90, 0x90, 0x8f, 0x8e, 0x8c, 0x8d, 0x90, + 0x93, 0x97, 0x9e, 0xa4, 0xa7, 0xa9, 0xa9, 0xaa, 0xac, 0xad, 0xad, 0xaf, + 0xb0, 0xaf, 0xae, 0xae, 0xaf, 0xaf, 0xb0, 0xaf, 0xaf, 0xaf, 0xb0, 0xae, + 0xad, 0xac, 0xac, 0xad, 0x54, 0x4c, 0x48, 0x49, 0x4c, 0x4f, 0x53, 0x56, + 0x57, 0x58, 0x5a, 0x59, 0x5a, 0x5a, 0x59, 0x58, 0x58, 0x57, 0x57, 0x58, + 0x57, 0x57, 0x57, 0x57, 0x59, 0x5b, 0x5b, 0x5b, 0x5c, 0x5d, 0x5f, 0x60, + 0x61, 0x61, 0x61, 0x62, 0x61, 0x62, 0x61, 0x61, 0x62, 0x61, 0x60, 0x60, + 0x60, 0x62, 0x64, 0x65, 0x66, 0x68, 0x68, 0x6a, 0x6d, 0x6f, 0x70, 0x71, + 0x75, 0x77, 0x79, 0x7c, 0x7f, 0x81, 0x83, 0x83, 0x84, 0x87, 0x90, 0x9a, + 0x9f, 0xa0, 0xa2, 0xa2, 0xa5, 0xab, 0xaf, 0xb3, 0xb4, 0xb3, 0xb2, 0xb3, + 0xb5, 0xb4, 0xb5, 0xba, 0xc0, 0xcb, 0xd4, 0xd1, 0xd0, 0xd2, 0xd7, 0xd9, + 0xd9, 0xd7, 0xd5, 0xd5, 0xd4, 0xcb, 0xc6, 0xc4, 0xc3, 0xc5, 0xc7, 0xc4, + 0xbd, 0xad, 0x9c, 0x8d, 0x83, 0x80, 0x81, 0x79, 0x6d, 0x68, 0x67, 0x69, + 0x72, 0x82, 0x89, 0x8a, 0x88, 0x8e, 0x8c, 0x8f, 0x96, 0xa7, 0xbb, 0xc3, + 0xc5, 0xc4, 0xc2, 0xbe, 0xb2, 0x9e, 0x90, 0x87, 0x79, 0x72, 0x7d, 0x80, + 0x75, 0x56, 0x3e, 0x3e, 0x40, 0x3f, 0x3c, 0x3c, 0x41, 0x46, 0x48, 0x4b, + 0x4e, 0x50, 0x4f, 0x4d, 0x49, 0x47, 0x49, 0x4b, 0x4c, 0x4e, 0x4e, 0x4f, + 0x4f, 0x4f, 0x50, 0x53, 0x56, 0x58, 0x5a, 0x5f, 0x69, 0x74, 0x7b, 0x7f, + 0x82, 0x83, 0x83, 0x85, 0x86, 0x85, 0x7d, 0x73, 0x6b, 0x63, 0x50, 0x36, + 0x2b, 0x29, 0x29, 0x27, 0x29, 0x33, 0x41, 0x45, 0x46, 0x46, 0x46, 0x4a, + 0x50, 0x52, 0x51, 0x47, 0x38, 0x2a, 0x25, 0x27, 0x33, 0x37, 0x38, 0x39, + 0x3d, 0x44, 0x4a, 0x4d, 0x4d, 0x4d, 0x50, 0x56, 0x5b, 0x5c, 0x59, 0x53, + 0x50, 0x54, 0x5a, 0x63, 0x69, 0x6b, 0x6d, 0x6d, 0x6d, 0x6d, 0x6e, 0x6c, + 0x6a, 0x65, 0x5e, 0x5c, 0x5e, 0x5f, 0x61, 0x61, 0x5f, 0x5f, 0x61, 0x67, + 0x73, 0x7e, 0x82, 0x83, 0x84, 0x84, 0x84, 0x81, 0x7d, 0x79, 0x71, 0x64, + 0x59, 0x56, 0x55, 0x58, 0x60, 0x6a, 0x71, 0x75, 0x7d, 0x83, 0x86, 0x88, + 0x88, 0x8b, 0x8f, 0x96, 0x9a, 0x9d, 0xa0, 0xa1, 0x9e, 0x9d, 0x9c, 0x98, + 0x97, 0x96, 0x96, 0x96, 0x96, 0x93, 0x92, 0x94, 0x96, 0x9a, 0xa0, 0xa5, + 0xa8, 0xaa, 0xab, 0xac, 0xae, 0xaf, 0xaf, 0xb0, 0xb1, 0xb0, 0xb0, 0xb0, + 0xb0, 0xb2, 0xb2, 0xb2, 0xb1, 0xb1, 0xb2, 0xb1, 0xae, 0xad, 0xae, 0xaf, + 0x57, 0x4e, 0x4a, 0x4b, 0x4e, 0x52, 0x54, 0x56, 0x57, 0x58, 0x5a, 0x59, + 0x5a, 0x5a, 0x59, 0x59, 0x57, 0x58, 0x58, 0x56, 0x56, 0x57, 0x57, 0x56, + 0x57, 0x5a, 0x59, 0x5a, 0x5b, 0x5d, 0x60, 0x60, 0x61, 0x61, 0x61, 0x61, + 0x61, 0x61, 0x61, 0x61, 0x63, 0x62, 0x63, 0x62, 0x61, 0x62, 0x65, 0x68, + 0x69, 0x6b, 0x6c, 0x6e, 0x70, 0x71, 0x72, 0x75, 0x78, 0x7c, 0x7f, 0x82, + 0x84, 0x86, 0x86, 0x86, 0x86, 0x87, 0x8e, 0x98, 0x9e, 0xa0, 0xa1, 0xa2, + 0xa5, 0xaa, 0xae, 0xb2, 0xb3, 0xb0, 0xaf, 0xb0, 0xb5, 0xb7, 0xb7, 0xbd, + 0xc5, 0xd0, 0xd8, 0xd6, 0xd5, 0xd4, 0xd3, 0xcf, 0xcb, 0xca, 0xcb, 0xcb, + 0xca, 0xc5, 0xc1, 0xc0, 0xbd, 0xb1, 0xa7, 0x9a, 0x91, 0x86, 0x7c, 0x7b, + 0x78, 0x78, 0x7b, 0x80, 0x77, 0x72, 0x73, 0x78, 0x83, 0x8a, 0x88, 0x86, + 0x84, 0x80, 0x7e, 0x7a, 0x7d, 0x8d, 0xa7, 0xb5, 0xb6, 0xb0, 0xad, 0xa6, + 0x93, 0x77, 0x6c, 0x68, 0x62, 0x5b, 0x55, 0x55, 0x52, 0x48, 0x41, 0x41, + 0x42, 0x41, 0x3e, 0x3e, 0x42, 0x48, 0x4a, 0x4e, 0x51, 0x53, 0x53, 0x51, + 0x4d, 0x48, 0x48, 0x4a, 0x4b, 0x4f, 0x51, 0x52, 0x52, 0x52, 0x53, 0x55, + 0x54, 0x52, 0x51, 0x4e, 0x4a, 0x48, 0x49, 0x4a, 0x4a, 0x4a, 0x4d, 0x53, + 0x58, 0x5e, 0x5c, 0x57, 0x55, 0x52, 0x47, 0x2e, 0x27, 0x28, 0x29, 0x2a, + 0x2a, 0x2f, 0x3f, 0x48, 0x4a, 0x47, 0x44, 0x47, 0x4d, 0x50, 0x54, 0x4f, + 0x3b, 0x29, 0x25, 0x2a, 0x35, 0x38, 0x39, 0x3b, 0x40, 0x47, 0x4b, 0x4d, + 0x4e, 0x4f, 0x55, 0x59, 0x5b, 0x5a, 0x57, 0x4f, 0x4f, 0x55, 0x5a, 0x61, + 0x68, 0x6c, 0x6e, 0x6f, 0x6e, 0x6c, 0x6c, 0x6a, 0x67, 0x61, 0x5c, 0x5c, + 0x60, 0x62, 0x64, 0x62, 0x5e, 0x5d, 0x60, 0x67, 0x75, 0x7f, 0x82, 0x83, + 0x84, 0x85, 0x87, 0x83, 0x80, 0x7c, 0x73, 0x66, 0x5c, 0x55, 0x52, 0x51, + 0x54, 0x5c, 0x62, 0x67, 0x6f, 0x78, 0x7e, 0x82, 0x84, 0x87, 0x8c, 0x95, + 0x99, 0x9c, 0xa0, 0xa2, 0xa3, 0xa2, 0xa1, 0xa0, 0x9e, 0x9f, 0x9f, 0x9f, + 0x9e, 0x9b, 0x99, 0x99, 0x9a, 0x9d, 0xa3, 0xa6, 0xa9, 0xaa, 0xab, 0xad, + 0xb0, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb2, 0xb2, 0xb3, 0xb4, + 0xb4, 0xb5, 0xb5, 0xb4, 0xb1, 0xb0, 0xb0, 0xb0, 0x5a, 0x51, 0x4d, 0x4d, + 0x4f, 0x52, 0x55, 0x57, 0x58, 0x59, 0x5b, 0x5b, 0x5b, 0x5a, 0x59, 0x59, + 0x58, 0x59, 0x59, 0x57, 0x57, 0x57, 0x56, 0x56, 0x57, 0x59, 0x59, 0x5a, + 0x5a, 0x5e, 0x60, 0x61, 0x60, 0x5f, 0x60, 0x5f, 0x60, 0x60, 0x60, 0x61, + 0x63, 0x63, 0x64, 0x65, 0x63, 0x64, 0x66, 0x69, 0x6b, 0x6d, 0x6e, 0x71, + 0x72, 0x72, 0x75, 0x79, 0x7d, 0x81, 0x83, 0x85, 0x87, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x8d, 0x94, 0x9c, 0x9f, 0xa1, 0xa2, 0xa5, 0xa9, 0xac, 0xb0, + 0xb2, 0xad, 0xac, 0xae, 0xb4, 0xb9, 0xba, 0xbf, 0xc5, 0xce, 0xd6, 0xd4, + 0xcb, 0xc2, 0xb4, 0xa6, 0xa2, 0xa9, 0xaf, 0xb5, 0xb4, 0xad, 0xa8, 0xa5, + 0xa3, 0x96, 0x8d, 0x86, 0x84, 0x85, 0x82, 0x82, 0x85, 0x86, 0x87, 0x87, + 0x80, 0x7c, 0x7b, 0x7f, 0x86, 0x8c, 0x89, 0x88, 0x87, 0x81, 0x78, 0x6f, + 0x6f, 0x79, 0x86, 0x8d, 0x8a, 0x80, 0x7c, 0x7a, 0x71, 0x69, 0x69, 0x67, + 0x61, 0x58, 0x4c, 0x4c, 0x4a, 0x45, 0x43, 0x40, 0x42, 0x42, 0x40, 0x3e, + 0x42, 0x46, 0x49, 0x4d, 0x52, 0x53, 0x53, 0x53, 0x50, 0x4a, 0x48, 0x48, + 0x49, 0x4c, 0x51, 0x54, 0x55, 0x56, 0x56, 0x59, 0x5a, 0x59, 0x58, 0x54, + 0x4a, 0x3f, 0x39, 0x35, 0x32, 0x31, 0x36, 0x42, 0x4c, 0x56, 0x55, 0x4f, + 0x51, 0x53, 0x4e, 0x36, 0x2a, 0x29, 0x2a, 0x2a, 0x2a, 0x2d, 0x3b, 0x4b, + 0x4f, 0x4b, 0x45, 0x43, 0x47, 0x4b, 0x51, 0x51, 0x3e, 0x2c, 0x28, 0x2f, + 0x38, 0x3a, 0x3a, 0x3c, 0x42, 0x49, 0x4c, 0x50, 0x51, 0x51, 0x57, 0x5a, + 0x59, 0x57, 0x53, 0x4b, 0x4e, 0x56, 0x5b, 0x60, 0x68, 0x6b, 0x6d, 0x6c, + 0x6c, 0x6c, 0x69, 0x66, 0x63, 0x5f, 0x5c, 0x5f, 0x64, 0x67, 0x69, 0x65, + 0x5d, 0x5a, 0x5d, 0x69, 0x79, 0x7f, 0x81, 0x82, 0x83, 0x87, 0x89, 0x86, + 0x83, 0x7f, 0x75, 0x67, 0x5d, 0x58, 0x56, 0x52, 0x51, 0x51, 0x54, 0x59, + 0x60, 0x69, 0x72, 0x78, 0x7a, 0x7d, 0x84, 0x8d, 0x92, 0x95, 0x99, 0x9d, + 0xa3, 0xa4, 0xa5, 0xa4, 0xa4, 0xa5, 0xa5, 0xa4, 0xa3, 0x9f, 0x9d, 0x9d, + 0x9e, 0x9f, 0xa3, 0xa6, 0xa8, 0xa9, 0xaa, 0xae, 0xb0, 0xb1, 0xb1, 0xb1, + 0xb1, 0xb1, 0xb2, 0xb1, 0xb1, 0xb1, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb5, + 0xb2, 0xb2, 0xb1, 0xb2, 0x5d, 0x54, 0x4f, 0x4e, 0x4f, 0x52, 0x54, 0x57, + 0x58, 0x59, 0x5a, 0x5a, 0x5b, 0x5a, 0x59, 0x59, 0x58, 0x59, 0x59, 0x57, + 0x57, 0x57, 0x56, 0x56, 0x56, 0x59, 0x59, 0x5a, 0x5b, 0x5e, 0x60, 0x61, + 0x5f, 0x5f, 0x60, 0x5f, 0x61, 0x60, 0x60, 0x60, 0x62, 0x63, 0x64, 0x64, + 0x64, 0x66, 0x67, 0x6b, 0x6c, 0x6e, 0x6f, 0x72, 0x73, 0x75, 0x78, 0x7e, + 0x81, 0x85, 0x86, 0x88, 0x88, 0x8a, 0x8b, 0x8b, 0x8b, 0x8b, 0x8d, 0x93, + 0x9a, 0x9e, 0xa0, 0xa2, 0xa4, 0xa9, 0xab, 0xb0, 0xb1, 0xac, 0xab, 0xae, + 0xb4, 0xb9, 0xbb, 0xc0, 0xc4, 0xc9, 0xca, 0xc3, 0xb1, 0xa4, 0x95, 0x8b, + 0x8b, 0x92, 0x97, 0x9d, 0x9f, 0x9b, 0x9b, 0x9a, 0x97, 0x90, 0x8d, 0x8b, + 0x8b, 0x8a, 0x88, 0x87, 0x87, 0x88, 0x8a, 0x85, 0x80, 0x80, 0x81, 0x84, + 0x85, 0x8c, 0x8c, 0x8b, 0x89, 0x8a, 0x80, 0x73, 0x70, 0x72, 0x75, 0x73, + 0x71, 0x69, 0x69, 0x6e, 0x6a, 0x6b, 0x6c, 0x6a, 0x63, 0x5b, 0x51, 0x4f, + 0x4d, 0x4a, 0x47, 0x40, 0x42, 0x43, 0x41, 0x3f, 0x40, 0x43, 0x46, 0x4b, + 0x50, 0x52, 0x54, 0x55, 0x54, 0x4e, 0x49, 0x47, 0x47, 0x4a, 0x50, 0x54, + 0x56, 0x57, 0x58, 0x5b, 0x5f, 0x5f, 0x5e, 0x5a, 0x51, 0x43, 0x3b, 0x36, + 0x32, 0x30, 0x38, 0x47, 0x51, 0x5b, 0x57, 0x4e, 0x50, 0x54, 0x52, 0x3d, + 0x2d, 0x2c, 0x2c, 0x2a, 0x28, 0x2b, 0x37, 0x49, 0x51, 0x50, 0x46, 0x42, + 0x43, 0x46, 0x4d, 0x4f, 0x3e, 0x2d, 0x2b, 0x32, 0x3a, 0x3b, 0x3b, 0x3d, + 0x42, 0x47, 0x4c, 0x51, 0x53, 0x55, 0x5b, 0x5b, 0x58, 0x55, 0x4f, 0x48, + 0x4e, 0x58, 0x5d, 0x62, 0x68, 0x6c, 0x6b, 0x6b, 0x6b, 0x6b, 0x67, 0x63, + 0x60, 0x5d, 0x5c, 0x61, 0x69, 0x6c, 0x6d, 0x67, 0x5d, 0x59, 0x5e, 0x6c, + 0x7b, 0x7f, 0x7f, 0x80, 0x82, 0x87, 0x89, 0x89, 0x85, 0x81, 0x77, 0x68, + 0x5e, 0x5c, 0x59, 0x55, 0x52, 0x4f, 0x4f, 0x50, 0x53, 0x5b, 0x65, 0x6c, + 0x70, 0x75, 0x7c, 0x84, 0x88, 0x8b, 0x90, 0x96, 0x9e, 0xa3, 0xa4, 0xa6, + 0xa7, 0xa8, 0xa8, 0xa8, 0xa6, 0xa3, 0x9f, 0xa0, 0xa0, 0xa2, 0xa5, 0xa6, + 0xa8, 0xa9, 0xab, 0xac, 0xaf, 0xb0, 0xb0, 0xb1, 0xb0, 0xb1, 0xb0, 0xb0, + 0xaf, 0xaf, 0xb2, 0xb3, 0xb4, 0xb6, 0xb7, 0xb6, 0xb4, 0xb3, 0xb2, 0xb2, + 0x5f, 0x55, 0x50, 0x4e, 0x4f, 0x53, 0x55, 0x57, 0x58, 0x59, 0x5b, 0x5b, + 0x5b, 0x5a, 0x59, 0x59, 0x58, 0x59, 0x58, 0x57, 0x56, 0x56, 0x56, 0x56, + 0x56, 0x59, 0x59, 0x5a, 0x5a, 0x5d, 0x60, 0x60, 0x5f, 0x5f, 0x5f, 0x5f, + 0x60, 0x60, 0x60, 0x5f, 0x62, 0x63, 0x64, 0x64, 0x64, 0x67, 0x68, 0x6b, + 0x6c, 0x6e, 0x70, 0x73, 0x75, 0x77, 0x7a, 0x80, 0x84, 0x86, 0x88, 0x8a, + 0x8a, 0x8c, 0x8b, 0x8c, 0x8c, 0x8c, 0x8d, 0x91, 0x98, 0x9c, 0xa0, 0xa1, + 0xa3, 0xa8, 0xab, 0xaf, 0xb0, 0xab, 0xaa, 0xad, 0xb4, 0xba, 0xbc, 0xc1, + 0xc4, 0xc4, 0xb9, 0xa9, 0x9c, 0x95, 0x8f, 0x89, 0x89, 0x8c, 0x8e, 0x92, + 0x95, 0x95, 0x98, 0x99, 0x94, 0x90, 0x8f, 0x8f, 0x8f, 0x8d, 0x8a, 0x88, + 0x88, 0x89, 0x8a, 0x85, 0x81, 0x83, 0x84, 0x85, 0x84, 0x8b, 0x8e, 0x8d, + 0x89, 0x8c, 0x86, 0x7a, 0x75, 0x73, 0x71, 0x69, 0x68, 0x65, 0x67, 0x6e, + 0x6b, 0x6e, 0x6e, 0x6b, 0x64, 0x5c, 0x53, 0x51, 0x50, 0x4e, 0x4a, 0x40, + 0x41, 0x43, 0x43, 0x40, 0x3f, 0x41, 0x44, 0x48, 0x4e, 0x51, 0x54, 0x55, + 0x55, 0x50, 0x4a, 0x48, 0x48, 0x49, 0x4e, 0x53, 0x56, 0x58, 0x59, 0x5c, + 0x61, 0x62, 0x61, 0x5d, 0x55, 0x48, 0x3e, 0x39, 0x33, 0x32, 0x3b, 0x4b, + 0x55, 0x5f, 0x58, 0x4d, 0x50, 0x54, 0x55, 0x40, 0x2f, 0x2c, 0x2c, 0x2b, + 0x29, 0x2a, 0x34, 0x47, 0x4f, 0x52, 0x49, 0x42, 0x42, 0x45, 0x4b, 0x4c, + 0x3c, 0x2e, 0x2c, 0x35, 0x3c, 0x3d, 0x3d, 0x3f, 0x43, 0x46, 0x4c, 0x52, + 0x54, 0x57, 0x5b, 0x5b, 0x57, 0x53, 0x4c, 0x47, 0x4e, 0x59, 0x5e, 0x63, + 0x68, 0x6b, 0x6b, 0x6a, 0x6a, 0x6a, 0x67, 0x62, 0x5f, 0x5c, 0x5e, 0x64, + 0x6b, 0x6f, 0x71, 0x68, 0x5c, 0x5a, 0x60, 0x6f, 0x7c, 0x80, 0x80, 0x80, + 0x81, 0x86, 0x8a, 0x8a, 0x86, 0x82, 0x78, 0x69, 0x5f, 0x5c, 0x5a, 0x57, + 0x53, 0x4f, 0x4e, 0x4e, 0x4e, 0x54, 0x5c, 0x63, 0x68, 0x6e, 0x76, 0x7c, + 0x80, 0x82, 0x86, 0x90, 0x9b, 0xa1, 0xa3, 0xa5, 0xa8, 0xa9, 0xa9, 0xa9, + 0xa7, 0xa3, 0xa0, 0xa1, 0xa2, 0xa3, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xac, + 0xaf, 0xb0, 0xb0, 0xb1, 0xb0, 0xb1, 0xb0, 0xb0, 0xb0, 0xb0, 0xb1, 0xb2, + 0xb3, 0xb5, 0xb6, 0xb6, 0xb4, 0xb3, 0xb3, 0xb2, 0x62, 0x58, 0x52, 0x50, + 0x4f, 0x53, 0x56, 0x57, 0x58, 0x5a, 0x5b, 0x5b, 0x5a, 0x5a, 0x5a, 0x58, + 0x58, 0x57, 0x56, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x58, 0x5a, 0x59, + 0x5a, 0x5c, 0x5f, 0x5f, 0x5e, 0x5e, 0x5e, 0x60, 0x60, 0x5f, 0x5f, 0x5f, + 0x62, 0x64, 0x65, 0x65, 0x65, 0x67, 0x69, 0x6b, 0x6c, 0x6e, 0x72, 0x75, + 0x78, 0x7a, 0x7e, 0x83, 0x87, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8d, 0x8d, + 0x8e, 0x8e, 0x8d, 0x8f, 0x95, 0x99, 0x9d, 0xa1, 0xa4, 0xa7, 0xaa, 0xae, + 0xaf, 0xa9, 0xa9, 0xac, 0xb4, 0xba, 0xbd, 0xc3, 0xc4, 0xbe, 0x9c, 0x7f, + 0x88, 0x93, 0x9b, 0x97, 0x95, 0x93, 0x90, 0x8e, 0x93, 0x92, 0x98, 0x99, + 0x94, 0x90, 0x90, 0x90, 0x91, 0x90, 0x8d, 0x8c, 0x8d, 0x8d, 0x8c, 0x88, + 0x87, 0x88, 0x88, 0x86, 0x85, 0x8a, 0x90, 0x90, 0x89, 0x89, 0x89, 0x83, + 0x7e, 0x78, 0x74, 0x6b, 0x69, 0x6b, 0x6e, 0x71, 0x71, 0x71, 0x6f, 0x6d, + 0x65, 0x5b, 0x53, 0x52, 0x53, 0x54, 0x4c, 0x3e, 0x3e, 0x42, 0x45, 0x41, + 0x3d, 0x3e, 0x3f, 0x43, 0x4a, 0x4f, 0x53, 0x54, 0x55, 0x52, 0x4e, 0x4b, + 0x4a, 0x49, 0x4a, 0x50, 0x57, 0x5a, 0x5b, 0x5e, 0x63, 0x66, 0x67, 0x64, + 0x5b, 0x4e, 0x41, 0x3b, 0x34, 0x33, 0x3e, 0x50, 0x5b, 0x62, 0x59, 0x4c, + 0x4e, 0x54, 0x57, 0x46, 0x30, 0x2c, 0x2c, 0x2d, 0x2b, 0x2a, 0x32, 0x41, + 0x4b, 0x54, 0x4e, 0x45, 0x45, 0x47, 0x4a, 0x49, 0x39, 0x30, 0x30, 0x39, + 0x3f, 0x40, 0x40, 0x40, 0x43, 0x45, 0x4d, 0x53, 0x55, 0x58, 0x5c, 0x5b, + 0x55, 0x50, 0x49, 0x46, 0x51, 0x5c, 0x61, 0x65, 0x67, 0x6a, 0x6a, 0x69, + 0x69, 0x6a, 0x66, 0x61, 0x5f, 0x5e, 0x62, 0x69, 0x71, 0x75, 0x74, 0x69, + 0x5d, 0x5d, 0x64, 0x72, 0x7e, 0x81, 0x80, 0x80, 0x80, 0x86, 0x8c, 0x8c, + 0x88, 0x83, 0x79, 0x6b, 0x61, 0x5c, 0x5a, 0x59, 0x55, 0x51, 0x50, 0x4f, + 0x4d, 0x4d, 0x51, 0x57, 0x5b, 0x61, 0x6a, 0x6f, 0x72, 0x74, 0x78, 0x87, + 0x97, 0x9f, 0xa2, 0xa4, 0xa8, 0xaa, 0xaa, 0xa9, 0xa7, 0xa2, 0xa0, 0xa0, + 0xa1, 0xa3, 0xa7, 0xa8, 0xa8, 0xa9, 0xaa, 0xab, 0xad, 0xae, 0xae, 0xaf, + 0xaf, 0xb0, 0xb0, 0xb0, 0xaf, 0xaf, 0xb0, 0xb1, 0xb1, 0xb3, 0xb5, 0xb6, + 0xb5, 0xb4, 0xb4, 0xb1, 0x65, 0x5c, 0x56, 0x54, 0x52, 0x54, 0x56, 0x57, + 0x58, 0x5a, 0x5c, 0x5c, 0x5a, 0x5a, 0x5a, 0x59, 0x58, 0x56, 0x55, 0x56, + 0x56, 0x55, 0x55, 0x56, 0x57, 0x58, 0x58, 0x59, 0x5a, 0x5c, 0x5f, 0x5f, + 0x5e, 0x5e, 0x5e, 0x60, 0x60, 0x5f, 0x5f, 0x5f, 0x61, 0x64, 0x64, 0x65, + 0x66, 0x69, 0x6c, 0x6e, 0x6f, 0x71, 0x74, 0x7a, 0x7d, 0x7f, 0x82, 0x86, + 0x8a, 0x8c, 0x8c, 0x8d, 0x8e, 0x8f, 0x8f, 0x8f, 0x8e, 0x8e, 0x8e, 0x8f, + 0x93, 0x96, 0x9c, 0xa0, 0xa3, 0xa6, 0xa9, 0xac, 0xad, 0xaa, 0xab, 0xae, + 0xb5, 0xba, 0xbd, 0xc2, 0xc5, 0xbd, 0x98, 0x89, 0x9e, 0xa9, 0xaa, 0xa7, + 0xa5, 0xa2, 0x9f, 0x9a, 0x96, 0x95, 0x99, 0x9a, 0x97, 0x92, 0x93, 0x93, + 0x93, 0x95, 0x94, 0x95, 0x96, 0x96, 0x94, 0x93, 0x8e, 0x8a, 0x89, 0x8a, + 0x8b, 0x89, 0x8e, 0x90, 0x8f, 0x88, 0x8a, 0x89, 0x85, 0x7f, 0x7c, 0x79, + 0x78, 0x79, 0x79, 0x77, 0x73, 0x70, 0x6f, 0x6e, 0x69, 0x5b, 0x56, 0x59, + 0x5d, 0x5e, 0x4f, 0x3d, 0x3d, 0x41, 0x47, 0x44, 0x3c, 0x3a, 0x3b, 0x3f, + 0x46, 0x4d, 0x53, 0x55, 0x57, 0x57, 0x54, 0x52, 0x50, 0x4b, 0x49, 0x4e, + 0x55, 0x59, 0x5d, 0x60, 0x65, 0x6b, 0x6d, 0x6d, 0x65, 0x58, 0x48, 0x3f, + 0x38, 0x35, 0x43, 0x56, 0x61, 0x68, 0x5d, 0x4d, 0x4e, 0x54, 0x59, 0x4d, + 0x33, 0x2c, 0x2c, 0x2e, 0x2c, 0x2b, 0x30, 0x3a, 0x44, 0x52, 0x53, 0x4d, + 0x4c, 0x4c, 0x4c, 0x48, 0x37, 0x31, 0x35, 0x3f, 0x43, 0x43, 0x42, 0x42, + 0x44, 0x47, 0x4f, 0x56, 0x58, 0x5b, 0x5d, 0x58, 0x4f, 0x49, 0x44, 0x47, + 0x53, 0x5e, 0x63, 0x66, 0x68, 0x6a, 0x6a, 0x6a, 0x6a, 0x68, 0x62, 0x5f, + 0x5f, 0x62, 0x6a, 0x73, 0x7a, 0x7c, 0x78, 0x6b, 0x60, 0x63, 0x6a, 0x77, + 0x81, 0x81, 0x7f, 0x7e, 0x80, 0x86, 0x8c, 0x8f, 0x8c, 0x87, 0x7d, 0x70, + 0x64, 0x5d, 0x5b, 0x5a, 0x56, 0x54, 0x52, 0x51, 0x4e, 0x4c, 0x4b, 0x4c, + 0x4e, 0x52, 0x5a, 0x60, 0x60, 0x61, 0x67, 0x7a, 0x90, 0x9b, 0xa0, 0xa4, + 0xa7, 0xa8, 0xa9, 0xa8, 0xa5, 0xa2, 0x9f, 0x9f, 0x9f, 0xa2, 0xa6, 0xa8, + 0xa8, 0xa9, 0xab, 0xac, 0xac, 0xac, 0xac, 0xad, 0xad, 0xaf, 0xaf, 0xaf, + 0xae, 0xae, 0xae, 0xae, 0xaf, 0xb1, 0xb3, 0xb5, 0xb5, 0xb5, 0xb4, 0xb1, + 0x69, 0x60, 0x5b, 0x58, 0x57, 0x55, 0x56, 0x58, 0x5a, 0x5b, 0x5d, 0x5d, + 0x5c, 0x5b, 0x5a, 0x5a, 0x59, 0x56, 0x56, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x58, 0x57, 0x58, 0x5a, 0x5a, 0x5c, 0x5e, 0x5e, 0x5d, 0x5e, 0x5f, 0x60, + 0x5f, 0x5f, 0x5f, 0x5f, 0x62, 0x63, 0x65, 0x66, 0x69, 0x6c, 0x6e, 0x70, + 0x71, 0x74, 0x78, 0x7e, 0x81, 0x83, 0x86, 0x8a, 0x8d, 0x8e, 0x8f, 0x90, + 0x91, 0x91, 0x91, 0x91, 0x90, 0x8f, 0x90, 0x8f, 0x90, 0x93, 0x98, 0xa0, + 0xa3, 0xa6, 0xa8, 0xa9, 0xab, 0xaa, 0xad, 0xb0, 0xb5, 0xb9, 0xbb, 0xc2, + 0xc6, 0xc7, 0xc2, 0xc6, 0xc5, 0xbd, 0xad, 0xa9, 0xa9, 0xa5, 0xa2, 0x9f, + 0x9a, 0x9a, 0x9c, 0x9c, 0x9b, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9b, 0x99, + 0x9a, 0x98, 0x94, 0x91, 0x8f, 0x90, 0x91, 0x91, 0x88, 0x7b, 0x84, 0x8d, + 0x93, 0x8d, 0x88, 0x8a, 0x89, 0x85, 0x83, 0x82, 0x80, 0x7e, 0x7c, 0x7b, + 0x77, 0x73, 0x70, 0x70, 0x6d, 0x64, 0x63, 0x69, 0x6b, 0x66, 0x4a, 0x39, + 0x3b, 0x40, 0x46, 0x48, 0x41, 0x3c, 0x3b, 0x3e, 0x44, 0x4c, 0x53, 0x57, + 0x5a, 0x5c, 0x5b, 0x5a, 0x58, 0x53, 0x4c, 0x4d, 0x51, 0x55, 0x5c, 0x63, + 0x67, 0x6b, 0x6e, 0x72, 0x70, 0x63, 0x52, 0x47, 0x3c, 0x39, 0x48, 0x5c, + 0x67, 0x6d, 0x60, 0x4d, 0x4e, 0x53, 0x5a, 0x52, 0x36, 0x2c, 0x2b, 0x2e, + 0x2d, 0x2b, 0x2d, 0x33, 0x3c, 0x4b, 0x53, 0x4f, 0x4e, 0x4e, 0x4e, 0x47, + 0x36, 0x34, 0x39, 0x44, 0x46, 0x45, 0x44, 0x46, 0x47, 0x4a, 0x52, 0x57, + 0x59, 0x5d, 0x5f, 0x58, 0x4d, 0x47, 0x44, 0x4b, 0x57, 0x61, 0x65, 0x67, + 0x6a, 0x6b, 0x6b, 0x6a, 0x6a, 0x66, 0x61, 0x61, 0x63, 0x68, 0x72, 0x79, + 0x7d, 0x7d, 0x76, 0x6a, 0x65, 0x6c, 0x72, 0x7b, 0x82, 0x82, 0x7f, 0x7e, + 0x80, 0x86, 0x8d, 0x91, 0x90, 0x8c, 0x82, 0x74, 0x67, 0x5f, 0x5c, 0x5b, + 0x59, 0x57, 0x55, 0x53, 0x50, 0x4d, 0x4b, 0x4a, 0x4b, 0x4c, 0x4e, 0x52, + 0x52, 0x53, 0x5c, 0x74, 0x8d, 0x98, 0x9e, 0xa3, 0xa6, 0xa7, 0xa7, 0xa6, + 0xa4, 0xa0, 0x9e, 0x9e, 0x9e, 0xa1, 0xa5, 0xa8, 0xa8, 0xa9, 0xab, 0xac, + 0xac, 0xab, 0xab, 0xab, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xae, + 0xae, 0xb0, 0xb3, 0xb5, 0xb5, 0xb5, 0xb4, 0xb1, 0x6d, 0x64, 0x60, 0x5e, + 0x5b, 0x58, 0x58, 0x59, 0x5a, 0x5b, 0x5d, 0x5d, 0x5d, 0x5d, 0x5c, 0x5b, + 0x5a, 0x58, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58, 0x58, 0x58, 0x59, 0x59, + 0x5a, 0x5b, 0x5c, 0x5d, 0x5d, 0x5e, 0x60, 0x60, 0x5f, 0x5e, 0x5f, 0x60, + 0x62, 0x65, 0x67, 0x68, 0x6b, 0x6d, 0x6f, 0x71, 0x72, 0x75, 0x7b, 0x80, + 0x83, 0x86, 0x88, 0x8c, 0x8f, 0x90, 0x90, 0x91, 0x91, 0x90, 0x91, 0x90, + 0x90, 0x8f, 0x90, 0x90, 0x90, 0x92, 0x96, 0x9e, 0xa2, 0xa5, 0xa6, 0xa7, + 0xaa, 0xab, 0xaf, 0xb2, 0xb5, 0xb7, 0xbd, 0xc7, 0xce, 0xd4, 0xd9, 0xdc, + 0xd4, 0xc5, 0xab, 0xa6, 0xa9, 0xa9, 0xa7, 0xa4, 0xa1, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa0, 0x9e, 0x9f, 0x9f, 0x9e, 0x9b, 0x97, 0x96, 0x94, 0x91, 0x92, + 0x95, 0x97, 0x98, 0x92, 0x76, 0x69, 0x7c, 0x8a, 0x93, 0x90, 0x8a, 0x8b, + 0x8c, 0x8b, 0x88, 0x84, 0x81, 0x7e, 0x7d, 0x7b, 0x78, 0x77, 0x74, 0x72, + 0x71, 0x6e, 0x6f, 0x70, 0x70, 0x66, 0x41, 0x36, 0x3a, 0x3e, 0x44, 0x4b, + 0x47, 0x3e, 0x3c, 0x3e, 0x44, 0x4d, 0x55, 0x59, 0x5c, 0x5f, 0x60, 0x5f, + 0x5d, 0x58, 0x50, 0x4d, 0x4f, 0x52, 0x5a, 0x64, 0x68, 0x6b, 0x6e, 0x75, + 0x79, 0x6d, 0x5d, 0x51, 0x42, 0x3c, 0x4b, 0x60, 0x6b, 0x70, 0x63, 0x4e, + 0x4e, 0x53, 0x5b, 0x55, 0x39, 0x2b, 0x2a, 0x2e, 0x2e, 0x2d, 0x2a, 0x2e, + 0x35, 0x45, 0x51, 0x52, 0x4f, 0x4f, 0x4f, 0x47, 0x37, 0x37, 0x3c, 0x47, + 0x49, 0x48, 0x47, 0x47, 0x4a, 0x4d, 0x54, 0x58, 0x5b, 0x60, 0x61, 0x57, + 0x4b, 0x45, 0x43, 0x4c, 0x5a, 0x63, 0x67, 0x6a, 0x6c, 0x6d, 0x6d, 0x6c, + 0x6a, 0x64, 0x61, 0x64, 0x67, 0x6e, 0x78, 0x7d, 0x7e, 0x7a, 0x72, 0x69, + 0x68, 0x70, 0x77, 0x7e, 0x82, 0x82, 0x80, 0x7f, 0x7f, 0x85, 0x8c, 0x92, + 0x91, 0x8e, 0x85, 0x78, 0x6a, 0x60, 0x5c, 0x5b, 0x59, 0x58, 0x57, 0x56, + 0x53, 0x51, 0x4e, 0x4c, 0x4c, 0x4c, 0x4d, 0x4e, 0x4e, 0x51, 0x5c, 0x75, + 0x8c, 0x98, 0x9e, 0xa2, 0xa5, 0xa6, 0xa6, 0xa5, 0xa1, 0x9f, 0x9e, 0x9d, + 0x9f, 0xa2, 0xa6, 0xa8, 0xa8, 0xa9, 0xaa, 0xab, 0xab, 0xac, 0xab, 0xac, + 0xac, 0xab, 0xab, 0xab, 0xab, 0xac, 0xab, 0xac, 0xad, 0xaf, 0xb2, 0xb4, + 0xb4, 0xb4, 0xb3, 0xb1, 0x6f, 0x67, 0x62, 0x60, 0x5d, 0x59, 0x59, 0x5a, + 0x5a, 0x5b, 0x5d, 0x5e, 0x5e, 0x5d, 0x5c, 0x5a, 0x5a, 0x59, 0x58, 0x57, + 0x57, 0x57, 0x58, 0x58, 0x58, 0x59, 0x59, 0x59, 0x59, 0x5a, 0x5b, 0x5c, + 0x5d, 0x5e, 0x5f, 0x5f, 0x5e, 0x5e, 0x5f, 0x60, 0x62, 0x65, 0x67, 0x69, + 0x6b, 0x6d, 0x71, 0x72, 0x74, 0x78, 0x7d, 0x82, 0x85, 0x87, 0x8a, 0x8d, + 0x8f, 0x90, 0x91, 0x92, 0x92, 0x91, 0x91, 0x91, 0x91, 0x90, 0x90, 0x90, + 0x90, 0x91, 0x95, 0x9c, 0xa1, 0xa4, 0xa5, 0xa7, 0xa9, 0xab, 0xaf, 0xb3, + 0xb6, 0xba, 0xc3, 0xce, 0xd4, 0xda, 0xdf, 0xe0, 0xd9, 0xc9, 0xac, 0xa4, + 0xa8, 0xa8, 0xa8, 0xa7, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa2, 0x9e, 0x9d, + 0x9d, 0x9d, 0x9a, 0x97, 0x96, 0x95, 0x93, 0x95, 0x98, 0x99, 0x97, 0x8b, + 0x65, 0x5b, 0x75, 0x86, 0x91, 0x90, 0x8b, 0x8c, 0x8d, 0x8d, 0x8a, 0x86, + 0x82, 0x80, 0x7e, 0x7e, 0x7b, 0x7a, 0x77, 0x75, 0x72, 0x71, 0x72, 0x72, + 0x6f, 0x61, 0x3a, 0x33, 0x39, 0x3d, 0x43, 0x4c, 0x4b, 0x43, 0x3f, 0x40, + 0x45, 0x4e, 0x56, 0x5b, 0x5e, 0x62, 0x63, 0x62, 0x60, 0x5b, 0x53, 0x4e, + 0x4d, 0x50, 0x58, 0x63, 0x68, 0x6b, 0x6e, 0x76, 0x7e, 0x73, 0x65, 0x58, + 0x45, 0x3e, 0x4d, 0x62, 0x6d, 0x71, 0x65, 0x4f, 0x4e, 0x53, 0x5b, 0x57, + 0x3b, 0x2a, 0x28, 0x2d, 0x30, 0x2e, 0x2a, 0x2c, 0x32, 0x41, 0x51, 0x52, + 0x50, 0x4f, 0x50, 0x47, 0x38, 0x39, 0x3f, 0x49, 0x4a, 0x49, 0x48, 0x49, + 0x4b, 0x4f, 0x55, 0x5a, 0x5d, 0x62, 0x62, 0x55, 0x49, 0x44, 0x43, 0x4e, + 0x5d, 0x65, 0x68, 0x6b, 0x6c, 0x6e, 0x6d, 0x6c, 0x69, 0x63, 0x61, 0x66, + 0x6a, 0x71, 0x7b, 0x7e, 0x7b, 0x77, 0x6f, 0x68, 0x6a, 0x73, 0x79, 0x7f, + 0x83, 0x82, 0x80, 0x7f, 0x7f, 0x85, 0x8c, 0x92, 0x92, 0x90, 0x87, 0x7a, + 0x6d, 0x62, 0x5d, 0x5b, 0x58, 0x57, 0x57, 0x57, 0x55, 0x53, 0x50, 0x4f, + 0x4f, 0x4e, 0x4e, 0x4e, 0x4f, 0x53, 0x60, 0x78, 0x8d, 0x99, 0x9d, 0xa1, + 0xa3, 0xa5, 0xa5, 0xa4, 0xa1, 0x9f, 0x9d, 0x9d, 0x9e, 0xa1, 0xa5, 0xa7, + 0xa8, 0xa9, 0xaa, 0xaa, 0xaa, 0xab, 0xab, 0xab, 0xab, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xab, 0xae, 0xb1, 0xb4, 0xb5, 0xb4, 0xb3, 0xb1, + 0x71, 0x6a, 0x65, 0x63, 0x60, 0x5c, 0x5a, 0x5b, 0x5b, 0x5c, 0x5e, 0x5f, + 0x5e, 0x5d, 0x5b, 0x5a, 0x5a, 0x59, 0x58, 0x58, 0x56, 0x56, 0x58, 0x58, + 0x58, 0x59, 0x58, 0x59, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5e, 0x5e, + 0x5d, 0x5e, 0x5e, 0x60, 0x62, 0x64, 0x66, 0x68, 0x6b, 0x6e, 0x71, 0x75, + 0x78, 0x7b, 0x80, 0x85, 0x88, 0x89, 0x8b, 0x8e, 0x90, 0x91, 0x91, 0x93, + 0x93, 0x91, 0x90, 0x91, 0x92, 0x92, 0x91, 0x91, 0x8f, 0x8f, 0x93, 0x99, + 0x9f, 0xa2, 0xa3, 0xa5, 0xa7, 0xab, 0xb1, 0xb6, 0xbe, 0xc8, 0xd2, 0xd9, + 0xdc, 0xdc, 0xdf, 0xe1, 0xde, 0xd1, 0xb5, 0xa7, 0xa5, 0xa5, 0xa6, 0xa9, + 0xab, 0xaa, 0xa8, 0xa8, 0xa6, 0xa3, 0x9b, 0x99, 0x99, 0x9a, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9b, 0x9a, 0x99, 0x93, 0x8c, 0x79, 0x56, 0x53, 0x6e, 0x7e, + 0x8b, 0x8f, 0x8b, 0x8b, 0x8b, 0x8b, 0x89, 0x88, 0x85, 0x82, 0x82, 0x81, + 0x80, 0x7e, 0x7a, 0x77, 0x74, 0x71, 0x71, 0x71, 0x6b, 0x55, 0x36, 0x32, + 0x37, 0x3a, 0x40, 0x4b, 0x51, 0x4b, 0x46, 0x42, 0x46, 0x50, 0x58, 0x5d, + 0x62, 0x66, 0x67, 0x66, 0x65, 0x60, 0x58, 0x51, 0x4e, 0x4e, 0x55, 0x62, + 0x69, 0x6c, 0x6e, 0x76, 0x82, 0x7b, 0x70, 0x63, 0x4c, 0x3f, 0x50, 0x65, + 0x70, 0x74, 0x69, 0x51, 0x4d, 0x52, 0x5c, 0x5b, 0x40, 0x2b, 0x26, 0x2d, + 0x32, 0x30, 0x2c, 0x2b, 0x2e, 0x3c, 0x50, 0x55, 0x52, 0x51, 0x51, 0x48, + 0x3a, 0x3d, 0x44, 0x4b, 0x4b, 0x4b, 0x4a, 0x4b, 0x4d, 0x51, 0x58, 0x5d, + 0x61, 0x66, 0x63, 0x54, 0x46, 0x42, 0x43, 0x51, 0x61, 0x69, 0x6b, 0x6c, + 0x6c, 0x6d, 0x6d, 0x6c, 0x68, 0x62, 0x63, 0x6a, 0x6f, 0x75, 0x7e, 0x7c, + 0x75, 0x70, 0x6a, 0x68, 0x6d, 0x77, 0x7d, 0x82, 0x84, 0x82, 0x80, 0x7e, + 0x7e, 0x84, 0x8c, 0x92, 0x94, 0x92, 0x8c, 0x7f, 0x70, 0x65, 0x60, 0x5c, + 0x56, 0x56, 0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x52, 0x52, 0x52, 0x51, + 0x53, 0x59, 0x67, 0x7c, 0x8e, 0x97, 0x9c, 0x9f, 0xa1, 0xa3, 0xa2, 0xa1, + 0xa0, 0x9f, 0x9c, 0x9c, 0x9d, 0xa0, 0xa4, 0xa6, 0xa9, 0xa9, 0xa9, 0xaa, + 0xaa, 0xa8, 0xa8, 0xa8, 0xa9, 0xa9, 0xa8, 0xa8, 0xa9, 0xa8, 0xa7, 0xa6, + 0xa7, 0xab, 0xaf, 0xb2, 0xb3, 0xb3, 0xb2, 0xb0, 0x75, 0x6e, 0x6b, 0x68, + 0x65, 0x5f, 0x5c, 0x5c, 0x5d, 0x5e, 0x5f, 0x5e, 0x5e, 0x5d, 0x5b, 0x5a, + 0x5a, 0x5a, 0x59, 0x58, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58, 0x59, 0x59, + 0x59, 0x5a, 0x5c, 0x5c, 0x5d, 0x5e, 0x5f, 0x5e, 0x5f, 0x5f, 0x5f, 0x60, + 0x64, 0x65, 0x67, 0x69, 0x6a, 0x6d, 0x73, 0x79, 0x7c, 0x7f, 0x83, 0x86, + 0x89, 0x8b, 0x8e, 0x90, 0x91, 0x92, 0x92, 0x93, 0x93, 0x91, 0x91, 0x91, + 0x92, 0x93, 0x91, 0x92, 0x90, 0x90, 0x91, 0x95, 0x9b, 0x9f, 0xa2, 0xa4, + 0xa9, 0xb6, 0xc2, 0xca, 0xd2, 0xd9, 0xdc, 0xde, 0xde, 0xdd, 0xdd, 0xe0, + 0xe1, 0xd9, 0xc5, 0xb3, 0xac, 0xa7, 0xa6, 0xa9, 0xa9, 0xa9, 0xa8, 0xa6, + 0xa5, 0xa5, 0xa0, 0x9d, 0x9d, 0x9e, 0xa2, 0xa4, 0xa3, 0xa3, 0xa0, 0x9a, + 0x90, 0x7e, 0x75, 0x71, 0x75, 0x7e, 0x84, 0x86, 0x88, 0x8a, 0x87, 0x87, + 0x88, 0x87, 0x85, 0x82, 0x80, 0x80, 0x81, 0x80, 0x7e, 0x7d, 0x7b, 0x7a, + 0x78, 0x77, 0x71, 0x66, 0x5b, 0x4c, 0x40, 0x37, 0x36, 0x37, 0x3d, 0x47, + 0x55, 0x58, 0x54, 0x49, 0x49, 0x54, 0x5d, 0x62, 0x66, 0x6b, 0x6b, 0x6c, + 0x6b, 0x68, 0x61, 0x57, 0x51, 0x50, 0x53, 0x5d, 0x68, 0x6c, 0x6e, 0x74, + 0x83, 0x88, 0x7d, 0x70, 0x59, 0x46, 0x52, 0x67, 0x72, 0x78, 0x6c, 0x52, + 0x4e, 0x52, 0x5c, 0x5f, 0x48, 0x2e, 0x27, 0x2c, 0x33, 0x34, 0x30, 0x2e, + 0x2f, 0x39, 0x4f, 0x5a, 0x58, 0x56, 0x55, 0x4a, 0x3b, 0x41, 0x48, 0x4e, + 0x4d, 0x4c, 0x4c, 0x4d, 0x51, 0x56, 0x5d, 0x61, 0x64, 0x68, 0x64, 0x52, + 0x45, 0x42, 0x47, 0x58, 0x68, 0x6d, 0x6f, 0x6e, 0x6d, 0x6d, 0x6c, 0x6b, + 0x67, 0x62, 0x66, 0x6e, 0x73, 0x78, 0x7b, 0x75, 0x6d, 0x68, 0x64, 0x69, + 0x73, 0x7b, 0x7f, 0x83, 0x84, 0x82, 0x7f, 0x7e, 0x7d, 0x83, 0x8b, 0x92, + 0x94, 0x94, 0x90, 0x84, 0x74, 0x6a, 0x65, 0x5e, 0x57, 0x55, 0x55, 0x56, + 0x55, 0x54, 0x54, 0x55, 0x55, 0x55, 0x55, 0x56, 0x5a, 0x60, 0x6d, 0x7f, + 0x8e, 0x97, 0x9a, 0x9d, 0x9f, 0xa0, 0x9f, 0x9f, 0x9e, 0x9d, 0x9c, 0x9c, + 0x9d, 0x9f, 0xa2, 0xa5, 0xa7, 0xa8, 0xa8, 0xa8, 0xa8, 0xa7, 0xa6, 0xa7, + 0xa5, 0xa6, 0xa5, 0xa6, 0xa7, 0xa5, 0xa3, 0xa3, 0xa4, 0xa7, 0xab, 0xaf, + 0xb1, 0xb1, 0xb0, 0xae, 0x77, 0x72, 0x6f, 0x6d, 0x69, 0x63, 0x5f, 0x5e, + 0x5e, 0x60, 0x60, 0x60, 0x5f, 0x5e, 0x5c, 0x5c, 0x5c, 0x5b, 0x5a, 0x58, + 0x57, 0x57, 0x57, 0x58, 0x59, 0x59, 0x5a, 0x59, 0x5a, 0x5b, 0x5c, 0x5c, + 0x5d, 0x5e, 0x5e, 0x5e, 0x61, 0x61, 0x61, 0x61, 0x64, 0x66, 0x68, 0x6a, + 0x6c, 0x70, 0x78, 0x7c, 0x7f, 0x82, 0x85, 0x87, 0x8a, 0x8c, 0x8e, 0x91, + 0x91, 0x92, 0x92, 0x92, 0x93, 0x92, 0x92, 0x92, 0x92, 0x92, 0x90, 0x91, + 0x90, 0x8f, 0x8e, 0x91, 0x99, 0xa1, 0xa7, 0xb1, 0xc1, 0xd0, 0xd7, 0xda, + 0xdb, 0xdd, 0xdc, 0xdd, 0xde, 0xdd, 0xde, 0xe1, 0xe2, 0xe0, 0xd4, 0xbd, + 0xb3, 0xaf, 0xae, 0xad, 0xac, 0xac, 0xab, 0xab, 0xa9, 0xaa, 0xa8, 0xa5, + 0xa5, 0xa5, 0xa6, 0xa7, 0xa5, 0xa2, 0x9e, 0x97, 0x92, 0x8d, 0x8e, 0x96, + 0xa8, 0xb2, 0xb3, 0xb1, 0xa7, 0x97, 0x87, 0x81, 0x7f, 0x7f, 0x81, 0x81, + 0x80, 0x81, 0x81, 0x7f, 0x7c, 0x7e, 0x80, 0x80, 0x7d, 0x72, 0x61, 0x55, + 0x52, 0x52, 0x51, 0x48, 0x3d, 0x39, 0x3a, 0x43, 0x56, 0x65, 0x66, 0x5a, + 0x4e, 0x57, 0x62, 0x67, 0x6c, 0x6f, 0x6f, 0x70, 0x70, 0x6e, 0x67, 0x5f, + 0x58, 0x54, 0x52, 0x59, 0x66, 0x6c, 0x6f, 0x72, 0x7f, 0x91, 0x8a, 0x80, + 0x6a, 0x4f, 0x53, 0x67, 0x74, 0x7e, 0x6f, 0x53, 0x4d, 0x51, 0x5c, 0x62, + 0x50, 0x36, 0x2b, 0x2a, 0x32, 0x36, 0x35, 0x32, 0x32, 0x37, 0x48, 0x5b, + 0x5e, 0x5d, 0x59, 0x4d, 0x3e, 0x45, 0x4d, 0x52, 0x51, 0x50, 0x51, 0x53, + 0x58, 0x5d, 0x61, 0x65, 0x67, 0x67, 0x61, 0x4f, 0x45, 0x44, 0x4d, 0x61, + 0x6f, 0x72, 0x72, 0x6f, 0x6d, 0x6d, 0x6b, 0x69, 0x65, 0x63, 0x6a, 0x73, + 0x76, 0x77, 0x73, 0x69, 0x60, 0x5d, 0x61, 0x6d, 0x77, 0x7e, 0x80, 0x83, + 0x83, 0x81, 0x7f, 0x7d, 0x7c, 0x82, 0x89, 0x90, 0x94, 0x94, 0x93, 0x8c, + 0x7c, 0x71, 0x6b, 0x62, 0x5a, 0x56, 0x55, 0x55, 0x54, 0x54, 0x55, 0x55, + 0x55, 0x56, 0x56, 0x59, 0x5d, 0x63, 0x6f, 0x80, 0x8e, 0x95, 0x98, 0x9a, + 0x9c, 0x9d, 0x9c, 0x9b, 0x9c, 0x9b, 0x9a, 0x9b, 0x9b, 0x9d, 0xa1, 0xa4, + 0xa6, 0xa7, 0xa6, 0xa6, 0xa6, 0xa5, 0xa4, 0xa4, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa4, 0xa2, 0x9f, 0x9f, 0x9f, 0xa1, 0xa6, 0xab, 0xad, 0xad, 0xac, 0xaa, + 0x7a, 0x77, 0x74, 0x71, 0x6e, 0x68, 0x62, 0x60, 0x60, 0x61, 0x62, 0x61, + 0x60, 0x5f, 0x5e, 0x5d, 0x5d, 0x5d, 0x5b, 0x59, 0x58, 0x59, 0x59, 0x59, + 0x58, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5c, 0x5e, 0x5e, 0x5e, 0x5f, 0x5e, + 0x60, 0x60, 0x60, 0x61, 0x63, 0x67, 0x69, 0x6b, 0x6e, 0x74, 0x7b, 0x7f, + 0x82, 0x84, 0x87, 0x89, 0x8c, 0x8d, 0x8f, 0x91, 0x91, 0x92, 0x92, 0x92, + 0x93, 0x92, 0x92, 0x93, 0x92, 0x91, 0x8f, 0x8f, 0x8f, 0x90, 0x91, 0x9c, + 0xae, 0xbe, 0xc6, 0xcf, 0xd8, 0xdc, 0xdd, 0xdc, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xdd, 0xc9, 0xb8, 0xb3, 0xb1, 0xae, + 0xac, 0xac, 0xac, 0xac, 0xab, 0xab, 0xa9, 0xa7, 0xa6, 0xa7, 0xa6, 0xa5, + 0xa1, 0xa1, 0xa4, 0xad, 0xb6, 0xbb, 0xbd, 0xbe, 0xbf, 0xc0, 0xc2, 0xc2, + 0xc0, 0xb9, 0xa5, 0x8a, 0x7b, 0x72, 0x77, 0x7e, 0x7f, 0x80, 0x80, 0x7f, + 0x7e, 0x79, 0x78, 0x74, 0x69, 0x5b, 0x55, 0x56, 0x59, 0x5e, 0x64, 0x5f, + 0x54, 0x4a, 0x3e, 0x3f, 0x54, 0x6e, 0x7a, 0x78, 0x5c, 0x59, 0x64, 0x6b, + 0x73, 0x77, 0x78, 0x78, 0x76, 0x73, 0x6e, 0x66, 0x60, 0x5b, 0x57, 0x56, + 0x60, 0x6a, 0x6f, 0x72, 0x7c, 0x8e, 0x98, 0x93, 0x7b, 0x5e, 0x55, 0x63, + 0x72, 0x80, 0x73, 0x55, 0x4e, 0x52, 0x5c, 0x63, 0x56, 0x40, 0x34, 0x2c, + 0x30, 0x37, 0x39, 0x38, 0x37, 0x36, 0x3e, 0x53, 0x5f, 0x61, 0x5d, 0x4f, + 0x42, 0x49, 0x4f, 0x54, 0x54, 0x54, 0x56, 0x5a, 0x60, 0x65, 0x66, 0x68, + 0x68, 0x66, 0x5c, 0x4d, 0x45, 0x47, 0x54, 0x67, 0x71, 0x73, 0x73, 0x71, + 0x6f, 0x6c, 0x69, 0x66, 0x62, 0x65, 0x6e, 0x74, 0x75, 0x70, 0x64, 0x59, + 0x53, 0x55, 0x5f, 0x70, 0x7c, 0x82, 0x83, 0x83, 0x83, 0x81, 0x7e, 0x7c, + 0x7c, 0x80, 0x89, 0x8f, 0x93, 0x94, 0x95, 0x91, 0x86, 0x7a, 0x72, 0x66, + 0x5d, 0x57, 0x55, 0x55, 0x54, 0x54, 0x55, 0x54, 0x55, 0x55, 0x56, 0x5a, + 0x5f, 0x64, 0x6e, 0x7f, 0x8c, 0x91, 0x94, 0x96, 0x98, 0x98, 0x98, 0x98, + 0x99, 0x98, 0x99, 0x99, 0x99, 0x9c, 0x9f, 0xa3, 0xa4, 0xa5, 0xa5, 0xa5, + 0xa4, 0xa3, 0xa3, 0xa2, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0x9e, 0x9b, 0x9a, + 0x9a, 0x9c, 0xa1, 0xa6, 0xa9, 0xa9, 0xa7, 0xa4, 0x7d, 0x7a, 0x77, 0x75, + 0x71, 0x6c, 0x65, 0x62, 0x61, 0x61, 0x62, 0x62, 0x61, 0x60, 0x5e, 0x5d, + 0x5c, 0x5c, 0x5b, 0x5a, 0x59, 0x5a, 0x59, 0x59, 0x58, 0x59, 0x5a, 0x5a, + 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x5f, 0x5f, 0x5d, 0x5e, 0x5f, 0x5f, 0x60, + 0x63, 0x66, 0x69, 0x6c, 0x71, 0x77, 0x7e, 0x82, 0x83, 0x86, 0x89, 0x8b, + 0x8d, 0x8e, 0x8f, 0x91, 0x92, 0x93, 0x93, 0x93, 0x92, 0x90, 0x90, 0x91, + 0x91, 0x8f, 0x8d, 0x91, 0x99, 0xa0, 0xac, 0xbd, 0xcd, 0xd5, 0xd8, 0xda, + 0xdc, 0xdc, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe2, 0xe3, 0xe1, + 0xe2, 0xe2, 0xe0, 0xd2, 0xbb, 0xb2, 0xaf, 0xab, 0xa9, 0xa9, 0xaa, 0xaa, + 0xa9, 0xa9, 0xa8, 0xa6, 0xa4, 0xa1, 0x9e, 0xa2, 0xa9, 0xaf, 0xb8, 0xc3, + 0xc8, 0xca, 0xc9, 0xc7, 0xc7, 0xc7, 0xc9, 0xca, 0xc9, 0xc9, 0xc1, 0xb2, + 0xa2, 0x87, 0x75, 0x73, 0x6d, 0x73, 0x79, 0x7a, 0x6c, 0x5e, 0x5a, 0x59, + 0x56, 0x54, 0x59, 0x5e, 0x64, 0x6f, 0x7a, 0x78, 0x6c, 0x60, 0x4b, 0x3e, + 0x52, 0x6c, 0x80, 0x8f, 0x70, 0x5b, 0x64, 0x6e, 0x79, 0x7e, 0x80, 0x80, + 0x7d, 0x79, 0x73, 0x6d, 0x66, 0x61, 0x5a, 0x56, 0x5c, 0x68, 0x6e, 0x73, + 0x78, 0x89, 0x9c, 0x9d, 0x88, 0x6c, 0x59, 0x60, 0x6c, 0x7d, 0x76, 0x58, + 0x4f, 0x51, 0x5b, 0x64, 0x5a, 0x48, 0x3c, 0x31, 0x2f, 0x37, 0x3b, 0x3c, + 0x3b, 0x38, 0x38, 0x4a, 0x5a, 0x5f, 0x5c, 0x51, 0x45, 0x4d, 0x53, 0x57, + 0x57, 0x58, 0x5b, 0x5f, 0x65, 0x68, 0x68, 0x69, 0x68, 0x64, 0x58, 0x4a, + 0x46, 0x4a, 0x58, 0x6a, 0x73, 0x74, 0x73, 0x71, 0x6f, 0x6b, 0x66, 0x63, + 0x60, 0x66, 0x6f, 0x71, 0x6f, 0x66, 0x56, 0x4f, 0x4f, 0x54, 0x60, 0x72, + 0x7d, 0x82, 0x83, 0x82, 0x82, 0x7f, 0x7d, 0x7c, 0x7c, 0x7f, 0x88, 0x8e, + 0x92, 0x94, 0x95, 0x93, 0x8b, 0x82, 0x79, 0x6a, 0x5e, 0x58, 0x55, 0x54, + 0x54, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x59, 0x5e, 0x62, 0x6b, 0x7c, + 0x8a, 0x8e, 0x91, 0x93, 0x95, 0x96, 0x96, 0x97, 0x98, 0x98, 0x97, 0x97, + 0x98, 0x9b, 0x9e, 0xa2, 0xa4, 0xa4, 0xa5, 0xa4, 0xa3, 0xa3, 0xa2, 0xa0, + 0x9e, 0x9d, 0x9d, 0x9e, 0x9e, 0x9b, 0x99, 0x97, 0x96, 0x98, 0x9b, 0xa1, + 0xa5, 0xa5, 0xa2, 0x9f, 0x80, 0x7c, 0x7a, 0x77, 0x74, 0x6e, 0x68, 0x63, + 0x62, 0x61, 0x62, 0x62, 0x61, 0x60, 0x5e, 0x5d, 0x5c, 0x5c, 0x5b, 0x5a, + 0x5a, 0x5a, 0x5a, 0x59, 0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5d, 0x5d, 0x5e, + 0x5f, 0x5f, 0x5f, 0x5d, 0x5d, 0x5e, 0x5f, 0x60, 0x63, 0x66, 0x69, 0x6b, + 0x72, 0x79, 0x7f, 0x83, 0x85, 0x87, 0x8a, 0x8c, 0x8e, 0x8f, 0x8f, 0x91, + 0x91, 0x93, 0x93, 0x93, 0x92, 0x8f, 0x8f, 0x8e, 0x8f, 0x91, 0x94, 0x9e, + 0xaa, 0xb3, 0xc0, 0xcf, 0xd9, 0xdc, 0xdd, 0xdc, 0xdd, 0xdc, 0xdd, 0xde, + 0xe0, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe1, 0xe1, 0xe1, 0xe0, 0xd5, + 0xbd, 0xb1, 0xad, 0xa9, 0xa6, 0xa6, 0xa7, 0xa7, 0xa6, 0xa5, 0xa3, 0xa2, + 0xa1, 0xa0, 0xa1, 0xa9, 0xb2, 0xba, 0xc4, 0xcb, 0xcd, 0xcc, 0xcb, 0xca, + 0xca, 0xcc, 0xcd, 0xce, 0xce, 0xce, 0xcb, 0xc6, 0xbb, 0x9f, 0x85, 0x79, + 0x69, 0x6e, 0x76, 0x7d, 0x67, 0x51, 0x4e, 0x4f, 0x53, 0x59, 0x62, 0x6b, + 0x72, 0x7e, 0x89, 0x86, 0x7d, 0x71, 0x5a, 0x45, 0x50, 0x68, 0x7e, 0x98, + 0x82, 0x61, 0x64, 0x6d, 0x7c, 0x84, 0x85, 0x85, 0x83, 0x7e, 0x78, 0x71, + 0x6a, 0x64, 0x5d, 0x57, 0x5a, 0x65, 0x6d, 0x75, 0x77, 0x84, 0x9a, 0x9f, + 0x90, 0x75, 0x5e, 0x60, 0x69, 0x79, 0x76, 0x5a, 0x4f, 0x51, 0x5c, 0x65, + 0x5d, 0x4d, 0x41, 0x34, 0x30, 0x37, 0x3d, 0x3e, 0x3d, 0x3a, 0x38, 0x44, + 0x53, 0x59, 0x58, 0x4f, 0x47, 0x50, 0x55, 0x59, 0x5a, 0x5d, 0x60, 0x63, + 0x68, 0x6a, 0x69, 0x69, 0x67, 0x62, 0x55, 0x49, 0x48, 0x4c, 0x5b, 0x6c, + 0x74, 0x75, 0x73, 0x70, 0x6f, 0x6a, 0x64, 0x61, 0x60, 0x67, 0x6d, 0x6d, + 0x69, 0x5e, 0x4f, 0x4b, 0x4f, 0x55, 0x61, 0x72, 0x7e, 0x82, 0x83, 0x83, + 0x81, 0x7e, 0x7c, 0x7c, 0x7a, 0x7e, 0x86, 0x8d, 0x91, 0x93, 0x95, 0x94, + 0x8f, 0x86, 0x7e, 0x6f, 0x61, 0x59, 0x55, 0x53, 0x53, 0x53, 0x53, 0x55, + 0x55, 0x54, 0x54, 0x57, 0x5c, 0x60, 0x68, 0x79, 0x87, 0x8d, 0x8f, 0x91, + 0x93, 0x95, 0x95, 0x96, 0x97, 0x97, 0x96, 0x96, 0x97, 0x9a, 0x9d, 0xa1, + 0xa3, 0xa4, 0xa5, 0xa4, 0xa2, 0xa2, 0xa1, 0x9f, 0x9c, 0x9b, 0x9c, 0x9c, + 0x9c, 0x99, 0x96, 0x94, 0x93, 0x95, 0x98, 0x9e, 0xa2, 0xa2, 0x9e, 0x9a, + 0x84, 0x80, 0x7d, 0x7b, 0x76, 0x70, 0x6b, 0x66, 0x64, 0x62, 0x63, 0x62, + 0x62, 0x61, 0x60, 0x5e, 0x5c, 0x5c, 0x5b, 0x5b, 0x5b, 0x5a, 0x5a, 0x5a, + 0x5a, 0x5a, 0x5a, 0x5a, 0x5b, 0x5d, 0x5e, 0x5d, 0x5d, 0x5d, 0x5d, 0x5e, + 0x5e, 0x5e, 0x5f, 0x61, 0x63, 0x65, 0x69, 0x6d, 0x74, 0x7b, 0x81, 0x85, + 0x86, 0x88, 0x8a, 0x8d, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x92, 0x92, 0x91, + 0x8f, 0x8e, 0x8e, 0x90, 0x95, 0xa0, 0xb0, 0xc0, 0xca, 0xcf, 0xd5, 0xda, + 0xdc, 0xdc, 0xdc, 0xdd, 0xdf, 0xdf, 0xdf, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, + 0xe1, 0xe2, 0xe1, 0xdf, 0xe0, 0xdf, 0xdd, 0xd3, 0xc0, 0xb2, 0xac, 0xa8, + 0xa5, 0xa4, 0xa2, 0xa1, 0xa0, 0x9d, 0x9c, 0x9f, 0xa1, 0xa7, 0xb0, 0xbc, + 0xc3, 0xc7, 0xcc, 0xce, 0xcd, 0xcc, 0xcc, 0xce, 0xd1, 0xd3, 0xd2, 0xd2, + 0xd2, 0xd1, 0xcf, 0xce, 0xcb, 0xc0, 0xaa, 0x95, 0x7a, 0x72, 0x7c, 0x8e, + 0x77, 0x55, 0x4f, 0x53, 0x5f, 0x6b, 0x7a, 0x87, 0x8e, 0x94, 0x99, 0x97, + 0x91, 0x89, 0x75, 0x57, 0x51, 0x62, 0x76, 0x97, 0x9b, 0x73, 0x67, 0x6c, + 0x7d, 0x89, 0x8c, 0x8b, 0x8a, 0x85, 0x80, 0x76, 0x6f, 0x69, 0x62, 0x59, + 0x58, 0x5f, 0x68, 0x75, 0x77, 0x7e, 0x92, 0x9c, 0x9c, 0x81, 0x68, 0x61, + 0x64, 0x72, 0x75, 0x5d, 0x51, 0x51, 0x5b, 0x66, 0x60, 0x51, 0x46, 0x3a, + 0x34, 0x39, 0x3f, 0x40, 0x40, 0x3e, 0x3a, 0x3d, 0x47, 0x4c, 0x4f, 0x4b, + 0x4a, 0x54, 0x5a, 0x5c, 0x5f, 0x65, 0x68, 0x6a, 0x6c, 0x6c, 0x69, 0x67, + 0x65, 0x5e, 0x51, 0x48, 0x4b, 0x52, 0x61, 0x6f, 0x75, 0x73, 0x71, 0x6f, + 0x6d, 0x67, 0x61, 0x5f, 0x60, 0x67, 0x69, 0x64, 0x5e, 0x54, 0x49, 0x4a, + 0x50, 0x57, 0x64, 0x74, 0x7f, 0x82, 0x83, 0x82, 0x80, 0x7e, 0x7c, 0x7b, + 0x79, 0x7b, 0x83, 0x8c, 0x90, 0x92, 0x94, 0x95, 0x92, 0x8d, 0x87, 0x79, + 0x69, 0x5d, 0x57, 0x54, 0x52, 0x51, 0x52, 0x53, 0x54, 0x53, 0x53, 0x55, + 0x59, 0x5c, 0x64, 0x73, 0x83, 0x89, 0x8c, 0x8f, 0x90, 0x93, 0x93, 0x94, + 0x94, 0x94, 0x95, 0x94, 0x95, 0x98, 0x9b, 0x9f, 0xa0, 0xa1, 0xa3, 0xa3, + 0xa1, 0xa0, 0x9f, 0x9d, 0x9a, 0x99, 0x9a, 0x9b, 0x9a, 0x96, 0x93, 0x91, + 0x90, 0x91, 0x94, 0x99, 0x9b, 0x9b, 0x98, 0x94, 0x87, 0x84, 0x80, 0x7e, + 0x7b, 0x75, 0x6f, 0x68, 0x65, 0x63, 0x64, 0x62, 0x62, 0x62, 0x61, 0x5f, + 0x5d, 0x5c, 0x5c, 0x5b, 0x5c, 0x5a, 0x59, 0x59, 0x5a, 0x5c, 0x5c, 0x5b, + 0x5b, 0x5c, 0x5d, 0x5d, 0x5d, 0x5c, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, + 0x64, 0x67, 0x6b, 0x6f, 0x77, 0x7d, 0x82, 0x85, 0x87, 0x8a, 0x8c, 0x8e, + 0x8e, 0x8e, 0x8f, 0x90, 0x8f, 0x8f, 0x8e, 0x8e, 0x8f, 0x96, 0xa0, 0xa9, + 0xb8, 0xc7, 0xd2, 0xd8, 0xda, 0xdb, 0xdc, 0xdd, 0xdd, 0xdd, 0xde, 0xdf, + 0xdf, 0xe0, 0xdf, 0xdf, 0xe0, 0xe1, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xdf, + 0xe0, 0xde, 0xdb, 0xd2, 0xc8, 0xc1, 0xbc, 0xb6, 0xb3, 0xaf, 0xac, 0xaa, + 0xa7, 0xaa, 0xaf, 0xb4, 0xb8, 0xbc, 0xc1, 0xc8, 0xcc, 0xcd, 0xce, 0xcf, + 0xcf, 0xcf, 0xd0, 0xd2, 0xd6, 0xd8, 0xd7, 0xd6, 0xd6, 0xd6, 0xd4, 0xd3, + 0xd2, 0xd0, 0xc8, 0xb8, 0x9c, 0x86, 0x8a, 0xa5, 0xa5, 0x76, 0x5c, 0x5c, + 0x73, 0x8a, 0x99, 0xa2, 0xa6, 0xa8, 0xa9, 0xa6, 0xa1, 0x9b, 0x8f, 0x75, + 0x5d, 0x60, 0x6c, 0x88, 0xa9, 0x97, 0x76, 0x6d, 0x79, 0x8c, 0x93, 0x93, + 0x91, 0x8d, 0x88, 0x7f, 0x77, 0x71, 0x69, 0x5f, 0x58, 0x59, 0x61, 0x73, + 0x7b, 0x7a, 0x85, 0x92, 0xa1, 0x93, 0x78, 0x69, 0x66, 0x6d, 0x73, 0x60, + 0x52, 0x51, 0x5a, 0x66, 0x65, 0x57, 0x4d, 0x42, 0x3d, 0x40, 0x44, 0x45, + 0x44, 0x41, 0x3e, 0x3b, 0x3d, 0x40, 0x44, 0x46, 0x4e, 0x5b, 0x61, 0x62, + 0x65, 0x6d, 0x6f, 0x6f, 0x6f, 0x6d, 0x6a, 0x66, 0x62, 0x5a, 0x4e, 0x48, + 0x4f, 0x59, 0x68, 0x73, 0x75, 0x70, 0x6d, 0x6c, 0x6c, 0x65, 0x5f, 0x5e, + 0x61, 0x66, 0x61, 0x56, 0x4f, 0x4a, 0x49, 0x4e, 0x53, 0x5a, 0x68, 0x77, + 0x80, 0x82, 0x82, 0x82, 0x80, 0x7d, 0x7b, 0x7a, 0x78, 0x7a, 0x81, 0x8a, + 0x8e, 0x91, 0x93, 0x96, 0x94, 0x91, 0x8e, 0x85, 0x74, 0x67, 0x5f, 0x5b, + 0x57, 0x54, 0x53, 0x53, 0x53, 0x54, 0x54, 0x57, 0x5a, 0x5d, 0x63, 0x70, + 0x7e, 0x86, 0x88, 0x8b, 0x8f, 0x90, 0x90, 0x90, 0x91, 0x92, 0x94, 0x94, + 0x94, 0x95, 0x98, 0x9d, 0x9f, 0xa0, 0xa0, 0xa1, 0xa0, 0x9f, 0x9d, 0x9b, + 0x98, 0x97, 0x99, 0x99, 0x97, 0x94, 0x91, 0x8e, 0x8d, 0x8d, 0x90, 0x93, + 0x94, 0x94, 0x91, 0x8d, 0x8a, 0x86, 0x83, 0x81, 0x7e, 0x78, 0x71, 0x6b, + 0x68, 0x65, 0x65, 0x63, 0x61, 0x61, 0x60, 0x60, 0x5d, 0x5d, 0x5d, 0x5d, + 0x5c, 0x5a, 0x5a, 0x5a, 0x5c, 0x5d, 0x5c, 0x5c, 0x5c, 0x5c, 0x5d, 0x5e, + 0x5d, 0x5c, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x62, 0x65, 0x68, 0x6d, 0x71, + 0x78, 0x7e, 0x83, 0x86, 0x88, 0x8b, 0x8c, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, + 0x8d, 0x8e, 0x91, 0x99, 0xaa, 0xbe, 0xcb, 0xd1, 0xd6, 0xda, 0xdb, 0xdc, + 0xdc, 0xdc, 0xdd, 0xdd, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xde, 0xde, + 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe1, 0xe2, 0xe2, 0xe3, 0xe1, 0xdd, + 0xd8, 0xd6, 0xd4, 0xd1, 0xcf, 0xcd, 0xcb, 0xca, 0xc8, 0xc4, 0xc4, 0xc2, + 0xc2, 0xc2, 0xc5, 0xc8, 0xca, 0xcb, 0xcc, 0xce, 0xcf, 0xd2, 0xd4, 0xd5, + 0xd8, 0xd8, 0xd8, 0xd8, 0xd7, 0xd9, 0xd8, 0xd7, 0xd6, 0xd4, 0xd1, 0xcc, + 0xbd, 0xa7, 0x9c, 0x9d, 0xb6, 0xa3, 0x76, 0x6b, 0x80, 0xa0, 0xaf, 0xb3, + 0xb4, 0xb3, 0xb2, 0xae, 0xa9, 0xa5, 0x9d, 0x8d, 0x75, 0x67, 0x68, 0x7b, + 0xa2, 0xb3, 0x99, 0x84, 0x74, 0x86, 0x95, 0x99, 0x98, 0x95, 0x90, 0x8b, + 0x82, 0x7c, 0x72, 0x66, 0x5c, 0x57, 0x5b, 0x6a, 0x7d, 0x7c, 0x7e, 0x87, + 0x9b, 0xa1, 0x8a, 0x7a, 0x74, 0x72, 0x71, 0x60, 0x52, 0x51, 0x5a, 0x66, + 0x68, 0x5d, 0x55, 0x49, 0x46, 0x4b, 0x4e, 0x4d, 0x4a, 0x45, 0x3f, 0x3b, + 0x3a, 0x3b, 0x3f, 0x4a, 0x59, 0x64, 0x68, 0x68, 0x6a, 0x6f, 0x70, 0x70, + 0x70, 0x6c, 0x68, 0x61, 0x5d, 0x55, 0x49, 0x49, 0x56, 0x60, 0x6d, 0x74, + 0x72, 0x6c, 0x6a, 0x6b, 0x69, 0x62, 0x5e, 0x5e, 0x62, 0x63, 0x57, 0x4c, + 0x49, 0x4a, 0x4d, 0x52, 0x58, 0x5f, 0x6b, 0x77, 0x7e, 0x80, 0x81, 0x80, + 0x7f, 0x7e, 0x7c, 0x7a, 0x78, 0x79, 0x7f, 0x87, 0x8c, 0x8f, 0x92, 0x95, + 0x96, 0x94, 0x92, 0x8c, 0x7f, 0x70, 0x68, 0x64, 0x5e, 0x5b, 0x59, 0x58, + 0x59, 0x59, 0x5b, 0x5c, 0x5d, 0x5f, 0x65, 0x70, 0x7d, 0x85, 0x88, 0x8b, + 0x8d, 0x8f, 0x90, 0x8f, 0x90, 0x91, 0x93, 0x94, 0x94, 0x94, 0x96, 0x9a, + 0x9c, 0x9d, 0x9e, 0x9e, 0x9f, 0x9e, 0x9d, 0x9b, 0x98, 0x97, 0x97, 0x97, + 0x96, 0x94, 0x90, 0x8d, 0x8c, 0x8b, 0x8e, 0x8f, 0x8e, 0x8d, 0x8c, 0x88, + 0x8c, 0x89, 0x86, 0x84, 0x82, 0x7b, 0x75, 0x6e, 0x6b, 0x67, 0x65, 0x65, + 0x62, 0x61, 0x60, 0x60, 0x5f, 0x5e, 0x5e, 0x5d, 0x5d, 0x5c, 0x5c, 0x5c, + 0x5d, 0x5d, 0x5c, 0x5d, 0x5d, 0x5c, 0x5e, 0x5e, 0x5e, 0x5d, 0x5c, 0x5d, + 0x5d, 0x5e, 0x5f, 0x62, 0x65, 0x69, 0x6f, 0x74, 0x7a, 0x7f, 0x84, 0x87, + 0x89, 0x8b, 0x8c, 0x8e, 0x8e, 0x8d, 0x8c, 0x8b, 0x8f, 0x9c, 0xa8, 0xb9, + 0xcb, 0xd5, 0xda, 0xdb, 0xdc, 0xdb, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdd, + 0xdf, 0xde, 0xdf, 0xdf, 0xdf, 0xde, 0xdf, 0xdf, 0xdf, 0xe1, 0xe1, 0xe2, + 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe2, 0xe0, 0xdd, 0xdc, 0xdc, 0xda, + 0xd8, 0xd8, 0xd8, 0xd8, 0xd6, 0xd3, 0xd2, 0xd2, 0xd0, 0xcd, 0xcc, 0xc9, + 0xc7, 0xc8, 0xc9, 0xcd, 0xd0, 0xd5, 0xd7, 0xd8, 0xd9, 0xd9, 0xda, 0xda, + 0xd9, 0xda, 0xd9, 0xd9, 0xd9, 0xd6, 0xd4, 0xd3, 0xcd, 0xc1, 0xb3, 0xa0, + 0xab, 0xb6, 0x93, 0x80, 0x82, 0xa5, 0xb8, 0xba, 0xba, 0xb8, 0xb5, 0xb1, + 0xad, 0xa9, 0xa4, 0x99, 0x85, 0x70, 0x6b, 0x77, 0x98, 0xb7, 0xb4, 0xa0, + 0x7c, 0x7f, 0x93, 0x9b, 0x9c, 0x9b, 0x97, 0x91, 0x89, 0x83, 0x79, 0x6d, + 0x61, 0x59, 0x58, 0x63, 0x7c, 0x7f, 0x7e, 0x82, 0x92, 0xa4, 0x98, 0x88, + 0x80, 0x7b, 0x74, 0x60, 0x53, 0x51, 0x5a, 0x65, 0x6a, 0x62, 0x5a, 0x4e, + 0x4a, 0x51, 0x56, 0x52, 0x4d, 0x46, 0x3d, 0x3a, 0x3a, 0x3c, 0x45, 0x57, + 0x66, 0x6d, 0x6e, 0x6b, 0x6d, 0x6f, 0x70, 0x70, 0x71, 0x6d, 0x65, 0x5e, + 0x59, 0x51, 0x47, 0x4c, 0x5a, 0x64, 0x6e, 0x74, 0x6f, 0x69, 0x67, 0x69, + 0x66, 0x5f, 0x5d, 0x5f, 0x63, 0x5f, 0x51, 0x4a, 0x49, 0x4c, 0x4f, 0x55, + 0x5b, 0x61, 0x6c, 0x77, 0x7d, 0x7f, 0x80, 0x80, 0x7f, 0x7e, 0x7c, 0x7a, + 0x77, 0x78, 0x7e, 0x86, 0x8a, 0x8d, 0x91, 0x94, 0x97, 0x97, 0x95, 0x90, + 0x86, 0x77, 0x6e, 0x69, 0x63, 0x5f, 0x5e, 0x5e, 0x5e, 0x5e, 0x5f, 0x5e, + 0x5f, 0x62, 0x67, 0x71, 0x7d, 0x84, 0x88, 0x8a, 0x8c, 0x8e, 0x8f, 0x8f, + 0x90, 0x91, 0x92, 0x92, 0x92, 0x93, 0x95, 0x97, 0x9a, 0x9b, 0x9d, 0x9d, + 0x9e, 0x9d, 0x9d, 0x9a, 0x97, 0x96, 0x97, 0x97, 0x95, 0x94, 0x91, 0x8e, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8b, 0x8b, 0x88, 0x84, 0x8d, 0x8a, 0x89, 0x87, + 0x83, 0x7d, 0x77, 0x70, 0x6c, 0x68, 0x65, 0x65, 0x63, 0x62, 0x61, 0x61, + 0x60, 0x5f, 0x5f, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5c, 0x5d, + 0x5d, 0x5d, 0x5d, 0x5e, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5e, 0x5e, 0x61, + 0x65, 0x6a, 0x70, 0x75, 0x7a, 0x7f, 0x84, 0x88, 0x88, 0x8a, 0x8b, 0x8d, + 0x8d, 0x8c, 0x8b, 0x8d, 0x9a, 0xae, 0xbb, 0xcc, 0xd7, 0xdb, 0xdb, 0xdc, + 0xdc, 0xdb, 0xdc, 0xdc, 0xdc, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xdf, 0xdf, + 0xe0, 0xdf, 0xe0, 0xe0, 0xe0, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, + 0xe3, 0xe2, 0xe1, 0xe0, 0xde, 0xdd, 0xdc, 0xdc, 0xda, 0xda, 0xdb, 0xdb, + 0xda, 0xd8, 0xd9, 0xd8, 0xd7, 0xd4, 0xd2, 0xce, 0xcb, 0xcb, 0xcb, 0xce, + 0xd1, 0xd5, 0xd7, 0xd8, 0xda, 0xd9, 0xdb, 0xdb, 0xda, 0xdb, 0xda, 0xda, + 0xda, 0xd8, 0xd5, 0xd4, 0xd2, 0xcb, 0xbf, 0xa8, 0xa5, 0xb8, 0xa3, 0x8f, + 0x83, 0xa3, 0xba, 0xbd, 0xbd, 0xbb, 0xb7, 0xb3, 0xaf, 0xab, 0xa7, 0x9e, + 0x8d, 0x79, 0x70, 0x74, 0x91, 0xb4, 0xbf, 0xb1, 0x8a, 0x7c, 0x8e, 0x99, + 0x9c, 0x9d, 0x9a, 0x94, 0x8d, 0x87, 0x7c, 0x71, 0x65, 0x5c, 0x59, 0x5f, + 0x78, 0x80, 0x7e, 0x80, 0x8d, 0xa3, 0x9f, 0x91, 0x89, 0x82, 0x77, 0x60, + 0x53, 0x52, 0x59, 0x64, 0x6a, 0x65, 0x5d, 0x51, 0x4c, 0x53, 0x59, 0x57, + 0x52, 0x47, 0x39, 0x36, 0x3c, 0x43, 0x4f, 0x63, 0x6e, 0x70, 0x6f, 0x6d, + 0x6f, 0x6f, 0x6f, 0x70, 0x71, 0x6c, 0x63, 0x5b, 0x56, 0x4e, 0x47, 0x4f, + 0x5e, 0x67, 0x6f, 0x73, 0x6e, 0x68, 0x66, 0x67, 0x64, 0x5e, 0x5e, 0x60, + 0x64, 0x5d, 0x4e, 0x4a, 0x4a, 0x4e, 0x51, 0x57, 0x5e, 0x64, 0x6e, 0x77, + 0x7d, 0x7f, 0x80, 0x7f, 0x7e, 0x7d, 0x7b, 0x79, 0x77, 0x77, 0x7d, 0x84, + 0x89, 0x8b, 0x90, 0x94, 0x97, 0x97, 0x96, 0x93, 0x8a, 0x7c, 0x73, 0x6d, + 0x66, 0x62, 0x61, 0x61, 0x61, 0x60, 0x61, 0x61, 0x62, 0x64, 0x68, 0x72, + 0x7d, 0x84, 0x88, 0x8b, 0x8c, 0x8e, 0x8f, 0x90, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x92, 0x95, 0x96, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9b, 0x9b, 0x99, + 0x97, 0x96, 0x97, 0x97, 0x95, 0x94, 0x91, 0x8e, 0x8d, 0x8c, 0x8c, 0x8b, + 0x8a, 0x89, 0x87, 0x82, 0x90, 0x8d, 0x8a, 0x88, 0x85, 0x80, 0x77, 0x72, + 0x6f, 0x69, 0x66, 0x65, 0x64, 0x63, 0x62, 0x61, 0x5f, 0x5e, 0x5d, 0x5d, + 0x5d, 0x5c, 0x5c, 0x5c, 0x5c, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5c, + 0x5e, 0x5e, 0x5c, 0x5d, 0x5d, 0x5d, 0x5e, 0x61, 0x66, 0x6c, 0x72, 0x76, + 0x7b, 0x80, 0x85, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x89, 0x89, 0x8d, 0x9d, + 0xba, 0xcd, 0xd4, 0xd9, 0xdb, 0xdc, 0xdb, 0xdb, 0xdc, 0xdc, 0xdc, 0xdd, + 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xe0, 0xe1, 0xe1, 0xe1, + 0xe1, 0xe2, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe1, 0xdf, + 0xdd, 0xdd, 0xdc, 0xdc, 0xd9, 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, + 0xda, 0xda, 0xd8, 0xd7, 0xd7, 0xd6, 0xd4, 0xd2, 0xd2, 0xd4, 0xd5, 0xd7, + 0xd9, 0xd9, 0xdb, 0xdb, 0xdb, 0xda, 0xdb, 0xdb, 0xdb, 0xda, 0xd7, 0xd5, + 0xd3, 0xd1, 0xcb, 0xba, 0xa6, 0xae, 0xb1, 0xa3, 0x88, 0x9c, 0xb8, 0xc0, + 0xc0, 0xbe, 0xb9, 0xb5, 0xb1, 0xaf, 0xac, 0xa3, 0x95, 0x86, 0x7b, 0x73, + 0x87, 0xa9, 0xc0, 0xbf, 0xa3, 0x7e, 0x84, 0x8e, 0x95, 0x9b, 0x9c, 0x98, + 0x92, 0x8c, 0x83, 0x77, 0x6c, 0x62, 0x5c, 0x5c, 0x6d, 0x7e, 0x80, 0x80, + 0x88, 0x9e, 0xa5, 0x9f, 0x99, 0x8f, 0x7d, 0x60, 0x53, 0x52, 0x57, 0x61, + 0x68, 0x66, 0x61, 0x56, 0x50, 0x55, 0x5b, 0x5c, 0x59, 0x4b, 0x34, 0x32, + 0x47, 0x55, 0x65, 0x74, 0x76, 0x72, 0x6f, 0x6f, 0x73, 0x71, 0x70, 0x70, + 0x71, 0x6a, 0x60, 0x58, 0x53, 0x4c, 0x49, 0x55, 0x64, 0x6b, 0x71, 0x72, + 0x6c, 0x65, 0x63, 0x64, 0x61, 0x5d, 0x60, 0x63, 0x63, 0x5a, 0x4d, 0x4b, + 0x4d, 0x4f, 0x53, 0x5b, 0x64, 0x6a, 0x71, 0x78, 0x7d, 0x7f, 0x7f, 0x7f, + 0x7d, 0x7c, 0x7a, 0x78, 0x76, 0x75, 0x7b, 0x83, 0x87, 0x8a, 0x8e, 0x93, + 0x97, 0x98, 0x98, 0x96, 0x8e, 0x84, 0x7a, 0x74, 0x6c, 0x66, 0x65, 0x64, + 0x63, 0x63, 0x64, 0x64, 0x66, 0x68, 0x6d, 0x75, 0x7f, 0x85, 0x88, 0x8b, + 0x8e, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x8f, 0x90, 0x93, 0x95, + 0x97, 0x98, 0x99, 0x9b, 0x9b, 0x99, 0x98, 0x98, 0x97, 0x95, 0x96, 0x95, + 0x95, 0x94, 0x92, 0x8f, 0x8e, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x87, 0x82, + 0x91, 0x8e, 0x8d, 0x8b, 0x88, 0x83, 0x7c, 0x76, 0x72, 0x6b, 0x67, 0x66, + 0x65, 0x64, 0x63, 0x62, 0x5f, 0x5e, 0x5d, 0x5e, 0x5d, 0x5d, 0x5c, 0x5c, + 0x5c, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5c, 0x5d, 0x5d, 0x5c, 0x5e, + 0x5f, 0x5e, 0x5f, 0x63, 0x68, 0x6e, 0x72, 0x76, 0x7b, 0x80, 0x84, 0x85, + 0x86, 0x87, 0x87, 0x86, 0x89, 0x91, 0xa6, 0xc5, 0xd7, 0xdb, 0xdc, 0xdb, + 0xdb, 0xdd, 0xdc, 0xdd, 0xdc, 0xdd, 0xdd, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, + 0xdf, 0xdf, 0xdf, 0xdf, 0xe1, 0xe1, 0xe1, 0xe1, 0xe0, 0xe0, 0xe0, 0xe0, + 0xe1, 0xe1, 0xe1, 0xe0, 0xe1, 0xe0, 0xdf, 0xdf, 0xde, 0xdd, 0xdc, 0xdb, + 0xda, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd8, 0xd8, 0xd8, 0xd9, + 0xdb, 0xdc, 0xdc, 0xda, 0xd7, 0xd6, 0xd6, 0xd6, 0xd8, 0xd9, 0xda, 0xda, + 0xdb, 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xd9, 0xd6, 0xd5, 0xd3, 0xd1, 0xcc, + 0xb9, 0xa9, 0xb1, 0xac, 0x94, 0x8e, 0xad, 0xbc, 0xc0, 0xc0, 0xbc, 0xb8, + 0xb5, 0xb3, 0xaf, 0xa9, 0x9f, 0x94, 0x8a, 0x7b, 0x7b, 0x98, 0xb4, 0xbe, + 0xba, 0x92, 0x79, 0x78, 0x81, 0x94, 0x9e, 0x9d, 0x99, 0x94, 0x8d, 0x80, + 0x73, 0x6a, 0x64, 0x5c, 0x62, 0x77, 0x82, 0x84, 0x85, 0x97, 0xa6, 0xa7, + 0xa5, 0x9e, 0x88, 0x61, 0x54, 0x54, 0x58, 0x5d, 0x64, 0x66, 0x64, 0x5d, + 0x56, 0x58, 0x5d, 0x60, 0x5e, 0x50, 0x37, 0x3d, 0x5f, 0x71, 0x7c, 0x81, + 0x7a, 0x72, 0x71, 0x73, 0x76, 0x72, 0x70, 0x6f, 0x6e, 0x65, 0x5c, 0x55, + 0x50, 0x4a, 0x4c, 0x5d, 0x6a, 0x70, 0x73, 0x71, 0x69, 0x64, 0x63, 0x62, + 0x5c, 0x5e, 0x63, 0x65, 0x62, 0x55, 0x4e, 0x4f, 0x50, 0x52, 0x57, 0x60, + 0x6b, 0x70, 0x75, 0x79, 0x7d, 0x7e, 0x7e, 0x7e, 0x7e, 0x7b, 0x79, 0x77, + 0x74, 0x74, 0x78, 0x81, 0x86, 0x89, 0x8c, 0x93, 0x96, 0x99, 0x9a, 0x98, + 0x92, 0x8a, 0x82, 0x7d, 0x74, 0x6d, 0x69, 0x68, 0x68, 0x69, 0x6a, 0x6c, + 0x70, 0x72, 0x76, 0x7b, 0x82, 0x86, 0x88, 0x89, 0x8d, 0x90, 0x90, 0x90, + 0x91, 0x90, 0x90, 0x90, 0x90, 0x8f, 0x91, 0x92, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x97, 0x96, 0x96, 0x95, 0x93, 0x92, 0x93, 0x93, 0x93, 0x92, 0x8f, + 0x8f, 0x90, 0x8f, 0x8d, 0x8d, 0x8b, 0x88, 0x84, 0x93, 0x90, 0x8e, 0x8c, + 0x89, 0x84, 0x7e, 0x79, 0x74, 0x6e, 0x69, 0x67, 0x66, 0x64, 0x63, 0x62, + 0x60, 0x5e, 0x5d, 0x5e, 0x5d, 0x5c, 0x5c, 0x5c, 0x5c, 0x5d, 0x5d, 0x5d, + 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5c, 0x5d, 0x5f, 0x60, 0x60, 0x60, 0x63, + 0x69, 0x6f, 0x74, 0x77, 0x7b, 0x80, 0x84, 0x86, 0x86, 0x85, 0x85, 0x93, + 0xab, 0xbb, 0xce, 0xda, 0xdc, 0xdb, 0xdc, 0xdc, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdc, 0xdc, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, + 0xe0, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe1, 0xe1, 0xe0, 0xe0, 0xe1, + 0xe0, 0xe0, 0xdf, 0xdf, 0xde, 0xdd, 0xdd, 0xdd, 0xdb, 0xda, 0xd9, 0xd9, + 0xd9, 0xd8, 0xd9, 0xd8, 0xd7, 0xd7, 0xd6, 0xd7, 0xd9, 0xd9, 0xd9, 0xda, + 0xdb, 0xda, 0xda, 0xda, 0xd8, 0xd8, 0xd9, 0xda, 0xdb, 0xdb, 0xdb, 0xda, + 0xda, 0xd9, 0xd9, 0xd7, 0xd7, 0xd5, 0xd4, 0xd2, 0xca, 0xb9, 0xad, 0xa9, + 0x9f, 0x86, 0x9c, 0xb3, 0xbc, 0xbf, 0xbe, 0xba, 0xb8, 0xb6, 0xb3, 0xad, + 0xa5, 0x9d, 0x96, 0x88, 0x77, 0x82, 0x9e, 0xb1, 0xc0, 0xae, 0x84, 0x75, + 0x78, 0x88, 0x9b, 0xa1, 0x9e, 0x9b, 0x95, 0x88, 0x7b, 0x72, 0x6c, 0x62, + 0x5e, 0x6d, 0x7c, 0x81, 0x84, 0x91, 0xa2, 0xa8, 0xa9, 0xa5, 0x90, 0x64, + 0x56, 0x55, 0x57, 0x5b, 0x61, 0x65, 0x66, 0x62, 0x5c, 0x5c, 0x60, 0x62, + 0x5f, 0x52, 0x41, 0x59, 0x77, 0x84, 0x86, 0x82, 0x7a, 0x74, 0x74, 0x78, + 0x79, 0x73, 0x70, 0x6f, 0x6a, 0x61, 0x59, 0x52, 0x4d, 0x48, 0x52, 0x64, + 0x6f, 0x73, 0x74, 0x70, 0x68, 0x64, 0x62, 0x5f, 0x5b, 0x60, 0x65, 0x65, + 0x5e, 0x52, 0x51, 0x52, 0x53, 0x56, 0x5c, 0x67, 0x71, 0x75, 0x78, 0x7a, + 0x7b, 0x7c, 0x7d, 0x7e, 0x7e, 0x7b, 0x78, 0x75, 0x73, 0x72, 0x76, 0x7e, + 0x84, 0x88, 0x8d, 0x93, 0x97, 0x9b, 0x9c, 0x9c, 0x97, 0x90, 0x8a, 0x86, + 0x7e, 0x76, 0x70, 0x6e, 0x6e, 0x70, 0x73, 0x77, 0x7c, 0x7f, 0x80, 0x83, + 0x85, 0x87, 0x89, 0x89, 0x8d, 0x8f, 0x90, 0x90, 0x91, 0x90, 0x90, 0x90, + 0x8f, 0x8e, 0x8f, 0x91, 0x92, 0x93, 0x95, 0x96, 0x96, 0x94, 0x93, 0x92, + 0x92, 0x90, 0x8f, 0x90, 0x91, 0x93, 0x93, 0x91, 0x90, 0x91, 0x90, 0x8f, + 0x8d, 0x8c, 0x8a, 0x87, 0x95, 0x91, 0x90, 0x8e, 0x8b, 0x87, 0x80, 0x7a, + 0x76, 0x6f, 0x69, 0x68, 0x66, 0x64, 0x63, 0x63, 0x62, 0x5f, 0x5f, 0x5f, + 0x5e, 0x5d, 0x5d, 0x5d, 0x5d, 0x5e, 0x5d, 0x5d, 0x5d, 0x5c, 0x5d, 0x5d, + 0x5c, 0x5c, 0x5d, 0x5e, 0x60, 0x5f, 0x60, 0x62, 0x68, 0x70, 0x74, 0x77, + 0x7b, 0x80, 0x83, 0x84, 0x83, 0x80, 0x8d, 0xb4, 0xcd, 0xd8, 0xdd, 0xdd, + 0xdc, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, 0xdc, 0xdc, 0xdc, 0xde, 0xde, + 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xdf, 0xde, 0xde, 0xde, + 0xde, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, + 0xe1, 0xe1, 0xe1, 0xe0, 0xdf, 0xde, 0xdd, 0xdd, 0xdc, 0xda, 0xda, 0xd8, + 0xd8, 0xd7, 0xd6, 0xd8, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xda, 0xdb, 0xdc, + 0xdb, 0xd9, 0xd8, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xd9, 0xd9, 0xd8, 0xd6, + 0xd7, 0xd6, 0xd4, 0xd3, 0xcf, 0xc4, 0xb7, 0xaf, 0xa3, 0x8a, 0x8e, 0xaa, + 0xb8, 0xbf, 0xbe, 0xbb, 0xb8, 0xb7, 0xb4, 0xaf, 0xa8, 0xa2, 0x9c, 0x92, + 0x7f, 0x76, 0x8b, 0x9f, 0xba, 0xbe, 0x9f, 0x8b, 0x81, 0x7e, 0x94, 0xa2, + 0xa1, 0x9e, 0x98, 0x8e, 0x82, 0x77, 0x72, 0x69, 0x5f, 0x66, 0x74, 0x7c, + 0x83, 0x8e, 0xa0, 0xa9, 0xab, 0xa8, 0x93, 0x68, 0x58, 0x55, 0x58, 0x5a, + 0x60, 0x64, 0x65, 0x64, 0x60, 0x5f, 0x62, 0x63, 0x5f, 0x53, 0x4a, 0x6c, + 0x84, 0x8a, 0x86, 0x81, 0x7a, 0x78, 0x78, 0x7b, 0x7a, 0x74, 0x71, 0x6d, + 0x67, 0x5e, 0x58, 0x4f, 0x4a, 0x4a, 0x5a, 0x6a, 0x72, 0x74, 0x74, 0x6e, + 0x67, 0x63, 0x60, 0x5c, 0x5b, 0x62, 0x66, 0x65, 0x5c, 0x53, 0x52, 0x55, + 0x56, 0x5a, 0x61, 0x6c, 0x74, 0x77, 0x78, 0x7a, 0x7a, 0x7b, 0x7d, 0x7e, + 0x7d, 0x7a, 0x76, 0x74, 0x72, 0x71, 0x75, 0x7d, 0x84, 0x88, 0x8d, 0x94, + 0x99, 0x9c, 0x9d, 0x9d, 0x9a, 0x94, 0x8e, 0x8a, 0x83, 0x7c, 0x77, 0x75, + 0x75, 0x76, 0x7a, 0x7e, 0x82, 0x85, 0x86, 0x88, 0x87, 0x88, 0x88, 0x8a, + 0x8b, 0x8e, 0x8e, 0x8f, 0x90, 0x8f, 0x90, 0x8f, 0x8e, 0x8e, 0x8e, 0x90, + 0x91, 0x92, 0x93, 0x95, 0x94, 0x92, 0x91, 0x90, 0x90, 0x8f, 0x8f, 0x8f, + 0x91, 0x92, 0x92, 0x92, 0x92, 0x92, 0x90, 0x8f, 0x8d, 0x8c, 0x8a, 0x88, + 0x95, 0x92, 0x91, 0x8f, 0x8c, 0x88, 0x81, 0x7b, 0x76, 0x6f, 0x6a, 0x68, + 0x65, 0x64, 0x63, 0x63, 0x62, 0x60, 0x5f, 0x5f, 0x5e, 0x5e, 0x5d, 0x5d, + 0x5d, 0x5e, 0x5d, 0x5d, 0x5c, 0x5d, 0x5c, 0x5d, 0x5c, 0x5c, 0x5d, 0x5d, + 0x5f, 0x60, 0x61, 0x62, 0x68, 0x70, 0x75, 0x78, 0x7b, 0x7f, 0x81, 0x81, + 0x81, 0x84, 0x9e, 0xc8, 0xda, 0xdf, 0xdf, 0xdd, 0xdc, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdc, 0xdc, 0xdc, 0xdc, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, + 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe1, 0xe1, 0xe2, + 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe2, 0xe2, 0xe3, 0xe2, 0xe2, + 0xe1, 0xe1, 0xe0, 0xe0, 0xdf, 0xdd, 0xdc, 0xda, 0xd9, 0xd8, 0xd7, 0xd8, + 0xd7, 0xd7, 0xd7, 0xd6, 0xd6, 0xd8, 0xda, 0xdc, 0xdc, 0xd9, 0xd9, 0xd9, + 0xda, 0xda, 0xda, 0xda, 0xd9, 0xd9, 0xd8, 0xd6, 0xd7, 0xd6, 0xd5, 0xd3, + 0xd1, 0xca, 0xbe, 0xb6, 0xa8, 0x8e, 0x87, 0xa2, 0xb3, 0xbd, 0xbe, 0xbc, + 0xb9, 0xb8, 0xb5, 0xb1, 0xab, 0xa5, 0xa0, 0x97, 0x85, 0x75, 0x7f, 0x91, + 0xb0, 0xc1, 0xb0, 0x9d, 0x8d, 0x7c, 0x8f, 0xa0, 0xa2, 0xa0, 0x9b, 0x91, + 0x86, 0x7c, 0x76, 0x6e, 0x62, 0x63, 0x6f, 0x78, 0x82, 0x8c, 0x9f, 0xa9, + 0xac, 0xa8, 0x94, 0x6b, 0x5a, 0x56, 0x58, 0x5a, 0x5f, 0x63, 0x65, 0x65, + 0x62, 0x60, 0x63, 0x63, 0x5e, 0x53, 0x51, 0x76, 0x88, 0x8b, 0x86, 0x81, + 0x7b, 0x7b, 0x7c, 0x7d, 0x7a, 0x74, 0x70, 0x6c, 0x64, 0x5b, 0x57, 0x4e, + 0x4a, 0x4c, 0x5e, 0x6e, 0x74, 0x75, 0x73, 0x6d, 0x66, 0x62, 0x5f, 0x5b, + 0x5b, 0x63, 0x66, 0x63, 0x5a, 0x54, 0x54, 0x56, 0x58, 0x5c, 0x64, 0x6f, + 0x76, 0x78, 0x78, 0x7a, 0x7a, 0x7b, 0x7c, 0x7e, 0x7d, 0x7a, 0x76, 0x74, + 0x72, 0x71, 0x75, 0x7d, 0x85, 0x89, 0x8e, 0x94, 0x9a, 0x9d, 0x9e, 0x9d, + 0x9a, 0x95, 0x90, 0x8c, 0x86, 0x80, 0x7b, 0x7a, 0x7a, 0x7b, 0x7f, 0x82, + 0x85, 0x87, 0x89, 0x8a, 0x89, 0x88, 0x88, 0x8a, 0x8a, 0x8d, 0x8e, 0x8f, + 0x90, 0x90, 0x90, 0x8e, 0x8d, 0x8d, 0x8d, 0x8f, 0x91, 0x91, 0x92, 0x93, + 0x92, 0x90, 0x8f, 0x8f, 0x90, 0x8f, 0x8f, 0x8e, 0x90, 0x92, 0x91, 0x92, + 0x92, 0x92, 0x90, 0x8f, 0x8d, 0x8c, 0x8a, 0x89, 0x98, 0x95, 0x93, 0x91, + 0x8e, 0x89, 0x83, 0x7d, 0x79, 0x71, 0x6b, 0x68, 0x66, 0x65, 0x65, 0x64, + 0x63, 0x61, 0x60, 0x60, 0x5f, 0x5e, 0x5e, 0x5e, 0x5c, 0x5d, 0x5d, 0x5c, + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5d, 0x5c, 0x5e, 0x60, 0x61, 0x62, + 0x69, 0x70, 0x75, 0x77, 0x7a, 0x7e, 0x7e, 0x7d, 0x82, 0x98, 0xc1, 0xd9, + 0xde, 0xdf, 0xdd, 0xdc, 0xdc, 0xdd, 0xdd, 0xdd, 0xdc, 0xdd, 0xdc, 0xdd, + 0xdc, 0xdc, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, + 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe2, 0xe2, 0xe2, 0xe2, 0xe1, 0xe2, 0xe3, + 0xe3, 0xe3, 0xe3, 0xe2, 0xe2, 0xe3, 0xe3, 0xe2, 0xe3, 0xe3, 0xe2, 0xe2, + 0xe2, 0xe1, 0xdf, 0xde, 0xdd, 0xdb, 0xda, 0xd8, 0xd9, 0xd9, 0xd8, 0xd5, + 0xd5, 0xd6, 0xd6, 0xd9, 0xda, 0xda, 0xdb, 0xdb, 0xda, 0xd9, 0xd9, 0xd9, + 0xd9, 0xda, 0xd8, 0xd6, 0xd7, 0xd6, 0xd6, 0xd4, 0xd2, 0xce, 0xc8, 0xc1, + 0xb3, 0x97, 0x82, 0x97, 0xa8, 0xb9, 0xbe, 0xbc, 0xbb, 0xb9, 0xb6, 0xb2, + 0xae, 0xaa, 0xa5, 0x9c, 0x8f, 0x7d, 0x74, 0x7c, 0x9a, 0xbb, 0xc0, 0xb3, + 0xa1, 0x83, 0x85, 0x9b, 0xa2, 0xa2, 0x9d, 0x95, 0x8d, 0x84, 0x7d, 0x74, + 0x68, 0x64, 0x6a, 0x72, 0x7f, 0x8a, 0x9e, 0xa8, 0xac, 0xa9, 0x96, 0x6f, + 0x5c, 0x57, 0x59, 0x5b, 0x5e, 0x63, 0x65, 0x67, 0x65, 0x63, 0x65, 0x64, + 0x5e, 0x55, 0x60, 0x80, 0x8a, 0x8a, 0x86, 0x82, 0x7e, 0x7f, 0x80, 0x7f, + 0x7b, 0x74, 0x6e, 0x69, 0x5f, 0x5a, 0x56, 0x4d, 0x4a, 0x51, 0x64, 0x70, + 0x76, 0x77, 0x73, 0x6a, 0x64, 0x61, 0x5f, 0x5c, 0x5e, 0x64, 0x64, 0x60, + 0x57, 0x55, 0x55, 0x59, 0x5b, 0x61, 0x68, 0x73, 0x78, 0x7a, 0x7a, 0x7a, + 0x79, 0x7b, 0x7b, 0x7c, 0x7b, 0x79, 0x75, 0x72, 0x70, 0x70, 0x74, 0x7d, + 0x85, 0x89, 0x8f, 0x95, 0x9a, 0x9e, 0x9f, 0x9f, 0x9c, 0x96, 0x91, 0x8e, + 0x8a, 0x85, 0x82, 0x81, 0x81, 0x82, 0x86, 0x89, 0x8b, 0x8c, 0x8d, 0x8d, + 0x8a, 0x88, 0x88, 0x89, 0x89, 0x8b, 0x8c, 0x8e, 0x8f, 0x90, 0x8f, 0x8d, + 0x8d, 0x8d, 0x8c, 0x8d, 0x8f, 0x8f, 0x8f, 0x90, 0x8f, 0x8d, 0x8c, 0x8d, + 0x8e, 0x8d, 0x8e, 0x8e, 0x8f, 0x90, 0x90, 0x91, 0x91, 0x91, 0x8f, 0x8e, + 0x8d, 0x8c, 0x8b, 0x8a, 0x9a, 0x96, 0x93, 0x91, 0x8f, 0x8a, 0x84, 0x7d, + 0x79, 0x72, 0x6c, 0x69, 0x68, 0x67, 0x65, 0x65, 0x62, 0x62, 0x62, 0x61, + 0x60, 0x60, 0x60, 0x5f, 0x5d, 0x5c, 0x5d, 0x5d, 0x5d, 0x5d, 0x5b, 0x5a, + 0x5b, 0x5c, 0x5c, 0x5c, 0x5d, 0x5e, 0x60, 0x63, 0x6a, 0x70, 0x75, 0x77, + 0x78, 0x7a, 0x7c, 0x89, 0x9d, 0xc3, 0xdb, 0xe0, 0xdf, 0xde, 0xde, 0xdd, + 0xdc, 0xdd, 0xdd, 0xdd, 0xdc, 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, + 0xdf, 0xde, 0xde, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe0, 0xe0, 0xe1, + 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe0, 0xe1, + 0xe1, 0xe3, 0xe3, 0xe2, 0xe2, 0xe2, 0xe1, 0xe2, 0xe2, 0xe1, 0xe0, 0xe1, + 0xe1, 0xe0, 0xdf, 0xdc, 0xdb, 0xdb, 0xd9, 0xd8, 0xd8, 0xd6, 0xd5, 0xd5, + 0xd5, 0xd8, 0xd9, 0xd9, 0xda, 0xda, 0xd9, 0xd8, 0xd9, 0xd9, 0xd8, 0xd8, + 0xd8, 0xd7, 0xd6, 0xd5, 0xd2, 0xd0, 0xcd, 0xca, 0xc1, 0xaa, 0x8a, 0x86, + 0x92, 0xae, 0xbc, 0xbb, 0xbb, 0xba, 0xb7, 0xb3, 0xb1, 0xae, 0xab, 0xa4, + 0x99, 0x8b, 0x7b, 0x75, 0x7e, 0xa5, 0xbe, 0xc1, 0xb8, 0x9c, 0x7d, 0x8f, + 0x9f, 0xa2, 0xa0, 0x9b, 0x94, 0x8b, 0x84, 0x79, 0x70, 0x68, 0x67, 0x6c, + 0x79, 0x87, 0x9c, 0xa7, 0xab, 0xa8, 0x97, 0x75, 0x5e, 0x57, 0x59, 0x5c, + 0x5f, 0x62, 0x64, 0x67, 0x67, 0x67, 0x67, 0x63, 0x5e, 0x5a, 0x73, 0x89, + 0x8a, 0x88, 0x85, 0x83, 0x81, 0x82, 0x83, 0x81, 0x7b, 0x72, 0x69, 0x63, + 0x5c, 0x58, 0x54, 0x4d, 0x4e, 0x5a, 0x6c, 0x75, 0x79, 0x78, 0x73, 0x68, + 0x63, 0x60, 0x5e, 0x5c, 0x62, 0x65, 0x60, 0x5b, 0x55, 0x57, 0x5a, 0x5d, + 0x60, 0x67, 0x6f, 0x76, 0x79, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7a, + 0x78, 0x76, 0x73, 0x72, 0x70, 0x6f, 0x74, 0x7e, 0x85, 0x8a, 0x90, 0x97, + 0x9c, 0x9f, 0xa1, 0xa0, 0x9d, 0x98, 0x94, 0x91, 0x8d, 0x8a, 0x88, 0x87, + 0x88, 0x89, 0x8b, 0x8e, 0x90, 0x91, 0x90, 0x8f, 0x8c, 0x89, 0x88, 0x87, + 0x87, 0x8a, 0x8b, 0x8c, 0x8e, 0x8e, 0x8e, 0x8e, 0x8d, 0x8c, 0x8c, 0x8c, + 0x8d, 0x8d, 0x8d, 0x8c, 0x8c, 0x8b, 0x8b, 0x8a, 0x8b, 0x8b, 0x8c, 0x8c, + 0x8d, 0x8f, 0x90, 0x90, 0x8f, 0x90, 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8c, + 0x9b, 0x98, 0x94, 0x92, 0x90, 0x8c, 0x84, 0x7e, 0x79, 0x73, 0x6e, 0x6b, + 0x69, 0x68, 0x67, 0x65, 0x63, 0x64, 0x63, 0x62, 0x60, 0x60, 0x60, 0x5f, + 0x5d, 0x5e, 0x5e, 0x5e, 0x5e, 0x5d, 0x5a, 0x59, 0x59, 0x5a, 0x5b, 0x5d, + 0x5d, 0x5f, 0x61, 0x65, 0x6a, 0x6e, 0x73, 0x75, 0x76, 0x77, 0x8c, 0xb3, + 0xca, 0xda, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdd, 0xdc, 0xdd, 0xde, 0xdf, + 0xdf, 0xde, 0xde, 0xdf, 0xe0, 0xe0, 0xdf, 0xde, 0xde, 0xde, 0xde, 0xdf, + 0xe0, 0xdf, 0xdf, 0xdf, 0xe1, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, + 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, + 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xdf, + 0xde, 0xdd, 0xdd, 0xdb, 0xda, 0xd9, 0xd7, 0xd5, 0xd5, 0xd4, 0xd4, 0xd4, + 0xd6, 0xd8, 0xda, 0xd9, 0xd9, 0xd9, 0xd8, 0xd8, 0xd7, 0xd7, 0xd6, 0xd5, + 0xd3, 0xd1, 0xce, 0xcd, 0xc9, 0xbe, 0xa0, 0x83, 0x84, 0xa0, 0xb6, 0xbc, + 0xbb, 0xba, 0xb9, 0xb6, 0xb4, 0xb2, 0xaf, 0xa9, 0xa1, 0x95, 0x8b, 0x82, + 0x76, 0x86, 0xa7, 0xb7, 0xb9, 0xac, 0x84, 0x83, 0x94, 0x9d, 0xa2, 0xa0, + 0x9a, 0x93, 0x8c, 0x81, 0x76, 0x6e, 0x67, 0x66, 0x70, 0x83, 0x98, 0xa7, + 0xac, 0xa9, 0x98, 0x7a, 0x61, 0x59, 0x5a, 0x5d, 0x5f, 0x61, 0x63, 0x67, + 0x69, 0x6a, 0x69, 0x61, 0x5e, 0x66, 0x83, 0x8d, 0x8a, 0x88, 0x85, 0x85, + 0x84, 0x86, 0x85, 0x81, 0x78, 0x6c, 0x62, 0x5d, 0x59, 0x58, 0x52, 0x4e, + 0x54, 0x64, 0x75, 0x78, 0x79, 0x78, 0x71, 0x65, 0x60, 0x5d, 0x5c, 0x5e, + 0x65, 0x64, 0x5b, 0x56, 0x56, 0x5b, 0x5f, 0x62, 0x65, 0x6b, 0x72, 0x76, + 0x78, 0x79, 0x79, 0x7a, 0x7b, 0x7b, 0x7b, 0x79, 0x76, 0x74, 0x72, 0x71, + 0x70, 0x6f, 0x75, 0x7f, 0x86, 0x8b, 0x92, 0x9a, 0xa0, 0xa2, 0xa2, 0xa2, + 0x9f, 0x9a, 0x96, 0x94, 0x90, 0x8e, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x92, + 0x92, 0x92, 0x91, 0x8f, 0x8c, 0x88, 0x86, 0x84, 0x84, 0x87, 0x89, 0x8a, + 0x8b, 0x8b, 0x8c, 0x8d, 0x8d, 0x8c, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x89, + 0x89, 0x88, 0x87, 0x87, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8c, 0x8e, 0x8e, + 0x8e, 0x8c, 0x8d, 0x8d, 0x8b, 0x8b, 0x8a, 0x8c, 0x9c, 0x98, 0x96, 0x94, + 0x92, 0x8d, 0x86, 0x80, 0x7b, 0x75, 0x6f, 0x6b, 0x69, 0x68, 0x67, 0x66, + 0x64, 0x64, 0x64, 0x63, 0x61, 0x61, 0x61, 0x5f, 0x5e, 0x5e, 0x5d, 0x5d, + 0x5d, 0x5d, 0x5a, 0x5a, 0x59, 0x5a, 0x5b, 0x5c, 0x5e, 0x60, 0x62, 0x66, + 0x6a, 0x6d, 0x71, 0x73, 0x73, 0x79, 0xaa, 0xcf, 0xdc, 0xdf, 0xdf, 0xde, + 0xde, 0xde, 0xde, 0xdd, 0xdd, 0xde, 0xdf, 0xe0, 0xe0, 0xde, 0xde, 0xde, + 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xde, 0xdf, 0xe1, 0xe1, 0xe1, 0xdf, + 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xdf, + 0xdf, 0xdf, 0xdf, 0xe0, 0xdf, 0xdf, 0xdf, 0xdf, 0xe2, 0xe2, 0xe1, 0xe1, + 0xe2, 0xe2, 0xe0, 0xe0, 0xe0, 0xe1, 0xe0, 0xe0, 0xe0, 0xe0, 0xde, 0xde, + 0xdd, 0xdb, 0xda, 0xd7, 0xd6, 0xd4, 0xd2, 0xd2, 0xd3, 0xd4, 0xd8, 0xd9, + 0xda, 0xd9, 0xd8, 0xd7, 0xd7, 0xd6, 0xd6, 0xd5, 0xd5, 0xd3, 0xd0, 0xce, + 0xcb, 0xc5, 0xb1, 0x94, 0x8a, 0x94, 0xb0, 0xbc, 0xbb, 0xba, 0xb8, 0xb6, + 0xb5, 0xb3, 0xb1, 0xac, 0xa5, 0x9b, 0x94, 0x8c, 0x7c, 0x76, 0x8c, 0x9e, + 0xa8, 0xae, 0x93, 0x7a, 0x89, 0x96, 0xa0, 0xa2, 0x9d, 0x98, 0x93, 0x88, + 0x7a, 0x71, 0x68, 0x65, 0x6a, 0x7e, 0x93, 0xa5, 0xac, 0xab, 0x9a, 0x7e, + 0x64, 0x5b, 0x5a, 0x5c, 0x5f, 0x61, 0x63, 0x66, 0x6a, 0x6c, 0x68, 0x5f, + 0x5f, 0x71, 0x8c, 0x90, 0x8c, 0x89, 0x87, 0x87, 0x87, 0x89, 0x88, 0x82, + 0x76, 0x68, 0x5e, 0x5a, 0x5a, 0x58, 0x52, 0x52, 0x5a, 0x6d, 0x7e, 0x7d, + 0x7a, 0x77, 0x6f, 0x64, 0x5d, 0x5b, 0x5c, 0x60, 0x67, 0x64, 0x5a, 0x56, + 0x58, 0x5d, 0x62, 0x66, 0x69, 0x6d, 0x73, 0x76, 0x76, 0x77, 0x78, 0x7a, + 0x7a, 0x7a, 0x7a, 0x78, 0x75, 0x72, 0x70, 0x70, 0x6f, 0x70, 0x76, 0x7f, + 0x87, 0x8c, 0x94, 0x9c, 0xa2, 0xa3, 0xa4, 0xa3, 0xa0, 0x9b, 0x97, 0x95, + 0x92, 0x90, 0x90, 0x90, 0x91, 0x92, 0x93, 0x94, 0x93, 0x93, 0x90, 0x8e, + 0x8b, 0x87, 0x85, 0x83, 0x83, 0x85, 0x87, 0x88, 0x8a, 0x8b, 0x8c, 0x8c, + 0x8c, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x89, 0x88, 0x87, 0x86, 0x85, 0x83, + 0x84, 0x84, 0x86, 0x87, 0x89, 0x89, 0x8c, 0x8c, 0x8c, 0x8b, 0x8b, 0x8b, + 0x8a, 0x8a, 0x8a, 0x8c, 0x9d, 0x99, 0x97, 0x95, 0x92, 0x8c, 0x86, 0x7f, + 0x7c, 0x76, 0x70, 0x6c, 0x6a, 0x69, 0x67, 0x66, 0x65, 0x64, 0x64, 0x63, + 0x61, 0x61, 0x61, 0x5f, 0x5e, 0x5e, 0x5d, 0x5d, 0x5d, 0x5d, 0x5b, 0x5a, + 0x5a, 0x5a, 0x5b, 0x5c, 0x5e, 0x61, 0x63, 0x66, 0x6a, 0x6d, 0x71, 0x72, + 0x72, 0x84, 0xbc, 0xd9, 0xe0, 0xdf, 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdd, + 0xdd, 0xdf, 0xdf, 0xe0, 0xe0, 0xde, 0xde, 0xde, 0xdf, 0xde, 0xe0, 0xe0, + 0xe0, 0xe0, 0xde, 0xdf, 0xe1, 0xe1, 0xe1, 0xdf, 0xe0, 0xdf, 0xe1, 0xe2, + 0xe1, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, + 0xdf, 0xdf, 0xdf, 0xdf, 0xe2, 0xe2, 0xe1, 0xe1, 0xe2, 0xe1, 0xdf, 0xdf, + 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xdf, 0xdf, 0xde, 0xdc, 0xdb, 0xd9, + 0xd8, 0xd4, 0xd3, 0xd2, 0xd2, 0xd3, 0xd5, 0xd8, 0xd9, 0xd9, 0xd8, 0xd6, + 0xd7, 0xd6, 0xd6, 0xd5, 0xd4, 0xd3, 0xd0, 0xce, 0xcc, 0xc8, 0xb9, 0xa2, + 0x95, 0x91, 0xaa, 0xba, 0xbc, 0xbb, 0xb7, 0xb5, 0xb5, 0xb3, 0xb1, 0xad, + 0xa7, 0x9d, 0x97, 0x90, 0x82, 0x73, 0x7c, 0x8a, 0x97, 0xa9, 0x9b, 0x78, + 0x82, 0x8f, 0x9d, 0xa3, 0x9f, 0x9b, 0x96, 0x8c, 0x7d, 0x74, 0x6a, 0x65, + 0x66, 0x7b, 0x90, 0xa4, 0xac, 0xab, 0x9c, 0x81, 0x67, 0x5c, 0x5a, 0x5c, + 0x5f, 0x61, 0x63, 0x66, 0x6a, 0x6c, 0x68, 0x5f, 0x63, 0x79, 0x90, 0x90, + 0x8d, 0x8a, 0x88, 0x88, 0x89, 0x8a, 0x89, 0x82, 0x75, 0x65, 0x5c, 0x5a, + 0x5a, 0x56, 0x52, 0x56, 0x5e, 0x72, 0x83, 0x80, 0x7c, 0x77, 0x6d, 0x62, + 0x5d, 0x5b, 0x5d, 0x62, 0x68, 0x64, 0x5a, 0x57, 0x5b, 0x60, 0x64, 0x68, + 0x6a, 0x6e, 0x72, 0x75, 0x75, 0x76, 0x78, 0x79, 0x79, 0x79, 0x79, 0x78, + 0x74, 0x71, 0x70, 0x6f, 0x6f, 0x6f, 0x76, 0x7f, 0x87, 0x8d, 0x94, 0x9d, + 0xa2, 0xa4, 0xa5, 0xa3, 0xa0, 0x9b, 0x98, 0x96, 0x93, 0x92, 0x91, 0x92, + 0x92, 0x93, 0x94, 0x94, 0x93, 0x92, 0x8f, 0x8d, 0x8a, 0x87, 0x85, 0x83, + 0x82, 0x84, 0x86, 0x87, 0x89, 0x8a, 0x8b, 0x8c, 0x8b, 0x89, 0x89, 0x8a, + 0x89, 0x89, 0x88, 0x86, 0x86, 0x84, 0x83, 0x82, 0x83, 0x84, 0x84, 0x86, + 0x88, 0x88, 0x8b, 0x8c, 0x8c, 0x8a, 0x89, 0x8a, 0x89, 0x89, 0x8a, 0x8c, + 0x9e, 0x9b, 0x98, 0x96, 0x92, 0x8b, 0x85, 0x7f, 0x7c, 0x76, 0x70, 0x6c, + 0x6a, 0x68, 0x67, 0x66, 0x65, 0x64, 0x64, 0x63, 0x61, 0x61, 0x61, 0x60, + 0x5e, 0x5f, 0x5e, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5a, 0x5a, 0x5b, 0x5c, + 0x60, 0x61, 0x63, 0x66, 0x6a, 0x6e, 0x6f, 0x70, 0x76, 0x9f, 0xcf, 0xdd, + 0xdf, 0xdf, 0xde, 0xde, 0xdf, 0xdf, 0xe0, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, + 0xe0, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xdf, 0xdf, + 0xe1, 0xe2, 0xe2, 0xe0, 0xe0, 0xe0, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, + 0xe2, 0xe2, 0xe2, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe0, 0xe0, 0xe0, 0xe0, + 0xe2, 0xe1, 0xe0, 0xe0, 0xe1, 0xdf, 0xde, 0xde, 0xdf, 0xdf, 0xe0, 0xdf, + 0xdf, 0xde, 0xde, 0xde, 0xdf, 0xdd, 0xdc, 0xdb, 0xd8, 0xd6, 0xd5, 0xd4, + 0xd3, 0xd1, 0xd2, 0xd5, 0xd6, 0xd8, 0xd8, 0xd6, 0xd6, 0xd5, 0xd4, 0xd4, + 0xd3, 0xd2, 0xcf, 0xce, 0xcb, 0xc9, 0xc1, 0xb5, 0xa8, 0x97, 0xa2, 0xb3, + 0xbb, 0xbb, 0xb6, 0xb4, 0xb4, 0xb4, 0xb2, 0xae, 0xa8, 0xa1, 0x9b, 0x95, + 0x8a, 0x79, 0x6e, 0x72, 0x7f, 0x99, 0xa0, 0x7d, 0x79, 0x83, 0x97, 0xa3, + 0xa2, 0x9e, 0x99, 0x90, 0x85, 0x78, 0x6f, 0x68, 0x62, 0x74, 0x8b, 0xa1, + 0xaa, 0xab, 0x9d, 0x83, 0x6b, 0x60, 0x5a, 0x5c, 0x5e, 0x61, 0x63, 0x65, + 0x6a, 0x6b, 0x68, 0x66, 0x6d, 0x84, 0x93, 0x91, 0x8e, 0x8c, 0x8b, 0x8c, + 0x8c, 0x8c, 0x8a, 0x81, 0x72, 0x61, 0x5b, 0x59, 0x5b, 0x55, 0x53, 0x5c, + 0x66, 0x76, 0x86, 0x84, 0x7e, 0x77, 0x6a, 0x60, 0x5d, 0x5d, 0x5f, 0x64, + 0x68, 0x62, 0x5b, 0x5a, 0x5e, 0x61, 0x66, 0x6a, 0x6d, 0x6e, 0x70, 0x75, + 0x75, 0x75, 0x77, 0x78, 0x77, 0x77, 0x77, 0x77, 0x73, 0x70, 0x70, 0x6f, + 0x6f, 0x70, 0x74, 0x7f, 0x89, 0x8f, 0x96, 0x9e, 0xa3, 0xa5, 0xa5, 0xa3, + 0xa0, 0x9b, 0x98, 0x96, 0x95, 0x93, 0x93, 0x94, 0x94, 0x95, 0x94, 0x94, + 0x92, 0x91, 0x8e, 0x8c, 0x89, 0x86, 0x85, 0x82, 0x81, 0x82, 0x84, 0x86, + 0x88, 0x89, 0x8a, 0x8a, 0x8a, 0x89, 0x87, 0x87, 0x87, 0x86, 0x85, 0x85, + 0x83, 0x81, 0x80, 0x80, 0x82, 0x83, 0x83, 0x84, 0x86, 0x86, 0x89, 0x8a, + 0x89, 0x89, 0x88, 0x88, 0x88, 0x88, 0x89, 0x8b, 0xa0, 0x9c, 0x98, 0x95, + 0x91, 0x8a, 0x85, 0x7f, 0x7c, 0x77, 0x71, 0x6d, 0x6a, 0x68, 0x67, 0x66, + 0x65, 0x64, 0x63, 0x62, 0x61, 0x61, 0x61, 0x60, 0x5e, 0x5f, 0x5e, 0x5b, + 0x5b, 0x5c, 0x5c, 0x5c, 0x5b, 0x5a, 0x5a, 0x5c, 0x60, 0x61, 0x62, 0x65, + 0x6a, 0x6c, 0x6b, 0x72, 0x8d, 0xc4, 0xdd, 0xdf, 0xdf, 0xe0, 0xdf, 0xde, + 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, + 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe0, 0xe1, 0xe1, 0xe1, 0xe2, + 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe2, 0xe2, 0xe1, + 0xe2, 0xe2, 0xe3, 0xe3, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe1, 0xe1, + 0xe1, 0xe0, 0xe0, 0xe0, 0xe0, 0xdf, 0xdf, 0xdf, 0xdd, 0xdd, 0xdd, 0xdc, + 0xdd, 0xdd, 0xdd, 0xdc, 0xda, 0xd8, 0xd8, 0xd7, 0xd5, 0xd2, 0xd0, 0xd1, + 0xd2, 0xd3, 0xd6, 0xd6, 0xd6, 0xd5, 0xd4, 0xd5, 0xd3, 0xd2, 0xd0, 0xce, + 0xcd, 0xca, 0xc4, 0xbf, 0xb7, 0xa7, 0x9e, 0xab, 0xb6, 0xb9, 0xb6, 0xb2, + 0xb3, 0xb4, 0xb2, 0xaf, 0xaa, 0xa5, 0x9f, 0x9a, 0x92, 0x84, 0x72, 0x6b, + 0x70, 0x82, 0x9e, 0x8b, 0x73, 0x74, 0x8c, 0x9f, 0xa4, 0xa2, 0x9f, 0x98, + 0x8d, 0x7f, 0x76, 0x6d, 0x62, 0x69, 0x83, 0x9b, 0xa6, 0xab, 0xa2, 0x87, + 0x70, 0x63, 0x5a, 0x5c, 0x5e, 0x61, 0x63, 0x66, 0x6b, 0x6c, 0x6c, 0x76, + 0x81, 0x90, 0x95, 0x92, 0x8d, 0x8c, 0x8d, 0x90, 0x90, 0x8e, 0x89, 0x7e, + 0x6c, 0x5c, 0x59, 0x59, 0x5a, 0x52, 0x55, 0x63, 0x6d, 0x79, 0x87, 0x85, + 0x7e, 0x76, 0x66, 0x5e, 0x5d, 0x60, 0x62, 0x66, 0x67, 0x5f, 0x5d, 0x5e, + 0x61, 0x64, 0x68, 0x6c, 0x6d, 0x6f, 0x70, 0x73, 0x74, 0x75, 0x76, 0x76, + 0x74, 0x74, 0x75, 0x77, 0x73, 0x6f, 0x6f, 0x6f, 0x6f, 0x70, 0x74, 0x81, + 0x8c, 0x92, 0x99, 0xa0, 0xa6, 0xa7, 0xa7, 0xa5, 0xa1, 0x9b, 0x98, 0x96, + 0x96, 0x95, 0x95, 0x96, 0x96, 0x96, 0x95, 0x93, 0x90, 0x8e, 0x8d, 0x8b, + 0x88, 0x86, 0x84, 0x81, 0x7f, 0x7e, 0x80, 0x81, 0x84, 0x87, 0x88, 0x88, + 0x88, 0x87, 0x85, 0x85, 0x84, 0x82, 0x81, 0x81, 0x80, 0x7f, 0x7e, 0x7e, + 0x80, 0x81, 0x81, 0x81, 0x83, 0x85, 0x87, 0x87, 0x87, 0x86, 0x87, 0x87, + 0x86, 0x86, 0x87, 0x89, 0x9e, 0x9b, 0x98, 0x96, 0x90, 0x8a, 0x84, 0x7f, + 0x7b, 0x76, 0x72, 0x6d, 0x6b, 0x6a, 0x68, 0x65, 0x64, 0x65, 0x64, 0x63, + 0x62, 0x60, 0x60, 0x60, 0x5e, 0x5d, 0x5c, 0x5b, 0x5b, 0x5c, 0x5d, 0x5c, + 0x5b, 0x5b, 0x5b, 0x5c, 0x60, 0x61, 0x62, 0x65, 0x68, 0x69, 0x70, 0x85, + 0xb8, 0xda, 0xde, 0xde, 0xdf, 0xe0, 0xde, 0xde, 0xdf, 0xe0, 0xe0, 0xe0, + 0xe0, 0xdf, 0xdf, 0xde, 0xe1, 0xe1, 0xe1, 0xe1, 0xdf, 0xdf, 0xe1, 0xe0, + 0xe2, 0xe2, 0xe1, 0xe2, 0xe1, 0xe1, 0xe2, 0xe3, 0xe3, 0xe2, 0xe3, 0xe3, + 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe1, 0xe1, 0xe0, 0xe1, 0xe1, 0xe0, 0xe1, + 0xe1, 0xe1, 0xe0, 0xe1, 0xe1, 0xe2, 0xe2, 0xe1, 0xdf, 0xdf, 0xe0, 0xe0, + 0xdf, 0xdf, 0xdf, 0xde, 0xdc, 0xdb, 0xdb, 0xdc, 0xdb, 0xdc, 0xdc, 0xdc, + 0xdb, 0xda, 0xda, 0xd9, 0xd8, 0xd5, 0xd3, 0xd3, 0xd1, 0xd1, 0xd1, 0xd3, + 0xd5, 0xd5, 0xd5, 0xd5, 0xd4, 0xd1, 0xd0, 0xcf, 0xcf, 0xcc, 0xc8, 0xc4, + 0xc0, 0xb5, 0xa4, 0xa3, 0xad, 0xb2, 0xb5, 0xb2, 0xb1, 0xb2, 0xb2, 0xb0, + 0xac, 0xa8, 0xa3, 0x9e, 0x96, 0x8c, 0x81, 0x79, 0x74, 0x73, 0x8e, 0x94, + 0x77, 0x6f, 0x7f, 0x98, 0xa3, 0xa5, 0xa5, 0xa0, 0x95, 0x89, 0x7e, 0x74, + 0x65, 0x62, 0x79, 0x90, 0x9d, 0xa9, 0xa5, 0x8b, 0x75, 0x68, 0x5b, 0x5b, + 0x5d, 0x5f, 0x60, 0x64, 0x69, 0x6b, 0x73, 0x86, 0x90, 0x97, 0x97, 0x92, + 0x8c, 0x8c, 0x90, 0x94, 0x94, 0x91, 0x8b, 0x7d, 0x67, 0x5a, 0x59, 0x5a, + 0x59, 0x53, 0x59, 0x67, 0x71, 0x7c, 0x87, 0x85, 0x7c, 0x72, 0x63, 0x5b, + 0x5c, 0x60, 0x63, 0x67, 0x65, 0x5d, 0x5e, 0x61, 0x64, 0x67, 0x6a, 0x6c, + 0x6d, 0x6f, 0x71, 0x71, 0x73, 0x74, 0x74, 0x75, 0x72, 0x72, 0x73, 0x75, + 0x73, 0x6f, 0x6e, 0x6e, 0x6e, 0x70, 0x74, 0x82, 0x8e, 0x94, 0x9b, 0xa5, + 0xa8, 0xa9, 0xa8, 0xa5, 0xa0, 0x9a, 0x99, 0x97, 0x97, 0x96, 0x97, 0x96, + 0x96, 0x95, 0x94, 0x91, 0x8e, 0x8c, 0x8b, 0x8a, 0x88, 0x86, 0x84, 0x81, + 0x7e, 0x7b, 0x7d, 0x7e, 0x80, 0x83, 0x85, 0x86, 0x86, 0x85, 0x83, 0x82, + 0x81, 0x7f, 0x7f, 0x7f, 0x7e, 0x7c, 0x7b, 0x7b, 0x7d, 0x7f, 0x80, 0x81, + 0x82, 0x85, 0x86, 0x85, 0x85, 0x84, 0x84, 0x83, 0x84, 0x85, 0x87, 0x88, + 0x9e, 0x9a, 0x96, 0x93, 0x8f, 0x89, 0x83, 0x7d, 0x7a, 0x76, 0x72, 0x6e, + 0x6b, 0x6a, 0x68, 0x66, 0x64, 0x65, 0x65, 0x64, 0x62, 0x61, 0x61, 0x61, + 0x60, 0x5e, 0x5d, 0x5b, 0x5b, 0x5b, 0x5c, 0x5c, 0x5c, 0x5c, 0x5b, 0x5b, + 0x60, 0x62, 0x63, 0x64, 0x66, 0x6b, 0x85, 0xa2, 0xce, 0xde, 0xde, 0xde, + 0xde, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xdf, 0xde, 0xde, + 0xe1, 0xe1, 0xe1, 0xe1, 0xe0, 0xe0, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, + 0xe1, 0xe1, 0xe1, 0xe3, 0xe3, 0xe3, 0xe2, 0xe2, 0xe2, 0xe1, 0xe1, 0xe1, + 0xe1, 0xe0, 0xe1, 0xe0, 0xe0, 0xe0, 0xdf, 0xe0, 0xe0, 0xe0, 0xdf, 0xe0, + 0xe0, 0xe0, 0xe1, 0xe0, 0xdf, 0xdf, 0xdf, 0xe0, 0xdf, 0xde, 0xde, 0xde, + 0xdc, 0xdb, 0xdc, 0xdc, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xda, 0xda, 0xd9, + 0xd9, 0xd7, 0xd4, 0xd4, 0xd3, 0xd1, 0xd1, 0xd1, 0xd4, 0xd4, 0xd4, 0xd3, + 0xd3, 0xd1, 0xcf, 0xcf, 0xce, 0xcc, 0xc8, 0xc6, 0xc3, 0xbc, 0xac, 0xa0, + 0xa5, 0xab, 0xb3, 0xb2, 0xaf, 0xb0, 0xb0, 0xb1, 0xae, 0xa9, 0xa6, 0xa2, + 0x99, 0x91, 0x8c, 0x85, 0x7d, 0x71, 0x7e, 0x94, 0x7f, 0x73, 0x76, 0x91, + 0xa2, 0xa7, 0xa7, 0xa3, 0x9c, 0x91, 0x84, 0x79, 0x68, 0x5e, 0x72, 0x87, + 0x95, 0xa8, 0xa7, 0x91, 0x7a, 0x6a, 0x5b, 0x59, 0x5b, 0x5d, 0x5f, 0x63, + 0x67, 0x69, 0x7b, 0x8d, 0x95, 0x9a, 0x99, 0x94, 0x8e, 0x8e, 0x93, 0x96, + 0x95, 0x91, 0x8b, 0x7a, 0x63, 0x59, 0x59, 0x59, 0x56, 0x53, 0x5f, 0x6b, + 0x73, 0x7d, 0x89, 0x86, 0x7a, 0x6f, 0x5f, 0x5a, 0x5e, 0x62, 0x65, 0x67, + 0x63, 0x5d, 0x5f, 0x62, 0x65, 0x68, 0x6c, 0x6e, 0x6e, 0x6f, 0x70, 0x72, + 0x74, 0x74, 0x74, 0x74, 0x73, 0x73, 0x73, 0x75, 0x73, 0x6f, 0x6e, 0x6e, + 0x6d, 0x6f, 0x74, 0x84, 0x90, 0x96, 0x9e, 0xa6, 0xa9, 0xa9, 0xa8, 0xa5, + 0xa0, 0x9a, 0x98, 0x97, 0x97, 0x96, 0x97, 0x96, 0x96, 0x95, 0x94, 0x90, + 0x8c, 0x8b, 0x8a, 0x8a, 0x89, 0x87, 0x85, 0x81, 0x7c, 0x7a, 0x7b, 0x7c, + 0x7e, 0x82, 0x84, 0x85, 0x85, 0x83, 0x82, 0x80, 0x7e, 0x7d, 0x7d, 0x7c, + 0x7c, 0x7a, 0x7a, 0x7a, 0x7c, 0x7d, 0x7f, 0x80, 0x81, 0x84, 0x85, 0x84, + 0x83, 0x82, 0x80, 0x80, 0x81, 0x82, 0x86, 0x87, 0x9d, 0x99, 0x95, 0x92, + 0x8e, 0x89, 0x82, 0x7c, 0x79, 0x76, 0x73, 0x6f, 0x6b, 0x6a, 0x68, 0x66, + 0x64, 0x65, 0x65, 0x64, 0x62, 0x62, 0x61, 0x61, 0x61, 0x5f, 0x5d, 0x5c, + 0x5b, 0x5b, 0x5b, 0x5c, 0x5d, 0x5d, 0x5b, 0x5b, 0x60, 0x62, 0x63, 0x64, + 0x66, 0x70, 0x98, 0xb7, 0xd6, 0xde, 0xde, 0xdd, 0xde, 0xdf, 0xdf, 0xe0, + 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xdf, 0xdf, 0xdf, 0xe1, 0xe1, 0xe1, 0xe1, + 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe1, 0xe0, 0xe1, 0xe3, + 0xe3, 0xe3, 0xe3, 0xe3, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe0, 0xe1, 0xe0, + 0xe0, 0xdf, 0xde, 0xdf, 0xdf, 0xde, 0xde, 0xdf, 0xde, 0xdf, 0xdf, 0xdf, + 0xde, 0xde, 0xde, 0xdf, 0xde, 0xdd, 0xdd, 0xde, 0xdc, 0xdc, 0xdc, 0xdc, + 0xda, 0xda, 0xda, 0xda, 0xda, 0xd9, 0xda, 0xd9, 0xd9, 0xd7, 0xd5, 0xd5, + 0xd4, 0xd2, 0xd1, 0xd0, 0xd2, 0xd3, 0xd3, 0xd3, 0xd3, 0xd1, 0xcf, 0xce, + 0xce, 0xcd, 0xc9, 0xc7, 0xc4, 0xbf, 0xb1, 0xa1, 0xa0, 0xa5, 0xb0, 0xb1, + 0xaf, 0xaf, 0xaf, 0xb1, 0xae, 0xaa, 0xa7, 0xa3, 0x9c, 0x93, 0x90, 0x8b, + 0x83, 0x75, 0x77, 0x8f, 0x85, 0x78, 0x73, 0x8d, 0xa0, 0xa7, 0xa7, 0xa5, + 0x9f, 0x95, 0x88, 0x7d, 0x6c, 0x5e, 0x6d, 0x80, 0x90, 0xa5, 0xa9, 0x95, + 0x7d, 0x6d, 0x5c, 0x59, 0x5a, 0x5c, 0x5e, 0x63, 0x66, 0x6a, 0x81, 0x92, + 0x98, 0x9b, 0x9a, 0x94, 0x90, 0x90, 0x96, 0x97, 0x95, 0x90, 0x88, 0x77, + 0x61, 0x59, 0x5a, 0x58, 0x53, 0x54, 0x63, 0x6e, 0x75, 0x7e, 0x8a, 0x86, + 0x77, 0x6b, 0x5d, 0x59, 0x5e, 0x63, 0x66, 0x67, 0x62, 0x5e, 0x61, 0x64, + 0x66, 0x69, 0x6c, 0x6f, 0x6f, 0x6f, 0x70, 0x73, 0x74, 0x74, 0x74, 0x74, + 0x74, 0x73, 0x73, 0x74, 0x72, 0x6f, 0x6e, 0x6e, 0x6d, 0x6e, 0x74, 0x85, + 0x92, 0x98, 0xa0, 0xa7, 0xaa, 0xa9, 0xa8, 0xa5, 0x9f, 0x9b, 0x98, 0x97, + 0x96, 0x95, 0x96, 0x96, 0x95, 0x94, 0x93, 0x8e, 0x8b, 0x8a, 0x8a, 0x8a, + 0x89, 0x87, 0x85, 0x81, 0x7b, 0x79, 0x7a, 0x7b, 0x7d, 0x81, 0x84, 0x85, + 0x84, 0x83, 0x80, 0x7f, 0x7d, 0x7c, 0x7c, 0x7b, 0x7a, 0x78, 0x78, 0x7a, + 0x7b, 0x7c, 0x7f, 0x80, 0x81, 0x83, 0x84, 0x83, 0x83, 0x81, 0x7f, 0x7f, + 0x81, 0x82, 0x85, 0x87, 0x9c, 0x98, 0x94, 0x91, 0x8c, 0x87, 0x81, 0x7c, + 0x79, 0x76, 0x73, 0x6f, 0x6c, 0x6a, 0x68, 0x67, 0x65, 0x65, 0x65, 0x64, + 0x62, 0x61, 0x61, 0x61, 0x61, 0x60, 0x5f, 0x5d, 0x5c, 0x5a, 0x5b, 0x5d, + 0x5e, 0x5e, 0x5d, 0x5d, 0x60, 0x62, 0x63, 0x64, 0x67, 0x81, 0xb6, 0xd0, + 0xdc, 0xde, 0xdd, 0xdd, 0xde, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, + 0xdf, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, + 0xe2, 0xe2, 0xe2, 0xe2, 0xe1, 0xe1, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, + 0xe3, 0xe3, 0xe3, 0xe2, 0xe2, 0xe1, 0xe0, 0xdf, 0xdf, 0xde, 0xdd, 0xdd, + 0xdc, 0xdd, 0xdd, 0xdd, 0xdc, 0xdc, 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, + 0xde, 0xdd, 0xdd, 0xdd, 0xdc, 0xdb, 0xda, 0xdb, 0xd9, 0xd9, 0xd9, 0xd8, + 0xd8, 0xd8, 0xd9, 0xd9, 0xd8, 0xd7, 0xd6, 0xd6, 0xd5, 0xd4, 0xd2, 0xcf, + 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd2, 0xd0, 0xd0, 0xcf, 0xcd, 0xca, 0xc8, + 0xc6, 0xc1, 0xb6, 0xa6, 0x9c, 0x9c, 0xa7, 0xaf, 0xaf, 0xad, 0xad, 0xae, + 0xad, 0xaa, 0xa7, 0xa4, 0x9e, 0x97, 0x92, 0x8f, 0x8a, 0x7e, 0x74, 0x86, + 0x8b, 0x81, 0x6f, 0x83, 0x9c, 0xa6, 0xa7, 0xa7, 0xa3, 0x9b, 0x90, 0x85, + 0x73, 0x60, 0x66, 0x76, 0x86, 0xa0, 0xab, 0x9c, 0x84, 0x72, 0x5e, 0x57, + 0x59, 0x5b, 0x5d, 0x60, 0x62, 0x6e, 0x8c, 0x98, 0x9b, 0x9c, 0x9b, 0x96, + 0x93, 0x95, 0x98, 0x98, 0x92, 0x8b, 0x83, 0x73, 0x5e, 0x59, 0x59, 0x56, + 0x50, 0x57, 0x69, 0x72, 0x78, 0x82, 0x8b, 0x84, 0x73, 0x67, 0x5a, 0x59, + 0x5f, 0x64, 0x66, 0x66, 0x60, 0x60, 0x63, 0x66, 0x68, 0x6b, 0x6e, 0x6f, + 0x6f, 0x6f, 0x70, 0x73, 0x74, 0x74, 0x74, 0x74, 0x73, 0x72, 0x72, 0x73, + 0x71, 0x6e, 0x6e, 0x6e, 0x6d, 0x6f, 0x75, 0x87, 0x95, 0x9c, 0xa3, 0xa9, + 0xaa, 0xa9, 0xa7, 0xa3, 0x9d, 0x99, 0x96, 0x95, 0x95, 0x94, 0x94, 0x93, + 0x91, 0x90, 0x8f, 0x8c, 0x8a, 0x89, 0x89, 0x8a, 0x89, 0x88, 0x86, 0x82, + 0x7c, 0x78, 0x78, 0x79, 0x7b, 0x80, 0x82, 0x84, 0x84, 0x82, 0x80, 0x7e, + 0x7c, 0x7b, 0x7a, 0x79, 0x78, 0x78, 0x78, 0x79, 0x7a, 0x7b, 0x7f, 0x80, + 0x80, 0x82, 0x82, 0x82, 0x82, 0x80, 0x80, 0x80, 0x81, 0x82, 0x84, 0x85, + 0x99, 0x95, 0x92, 0x90, 0x8b, 0x86, 0x7f, 0x7c, 0x7a, 0x76, 0x73, 0x6f, + 0x6c, 0x6b, 0x69, 0x67, 0x66, 0x66, 0x66, 0x65, 0x63, 0x61, 0x61, 0x61, + 0x60, 0x60, 0x60, 0x5f, 0x5e, 0x5d, 0x5d, 0x5e, 0x60, 0x60, 0x5f, 0x5f, + 0x61, 0x63, 0x63, 0x63, 0x6d, 0xa7, 0xd0, 0xdc, 0xdd, 0xdd, 0xdd, 0xde, + 0xde, 0xdd, 0xde, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xdf, 0xe0, 0xe1, 0xe1, + 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, + 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe2, + 0xe2, 0xe2, 0xe2, 0xe0, 0xe0, 0xdf, 0xde, 0xde, 0xdd, 0xdd, 0xde, 0xdd, + 0xda, 0xd9, 0xdb, 0xdb, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdb, 0xdc, 0xdc, + 0xdc, 0xdb, 0xda, 0xda, 0xda, 0xd9, 0xd9, 0xd9, 0xd8, 0xd7, 0xd7, 0xd7, + 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd4, 0xd2, 0xd2, 0xd1, 0xd0, 0xd1, + 0xd1, 0xd2, 0xd1, 0xd1, 0xcf, 0xcc, 0xcb, 0xc9, 0xc7, 0xc2, 0xbb, 0xaf, + 0xa1, 0x9c, 0x9e, 0xaa, 0xae, 0xad, 0xad, 0xac, 0xab, 0xa9, 0xa8, 0xa5, + 0xa0, 0x9b, 0x97, 0x95, 0x91, 0x87, 0x78, 0x7d, 0x8a, 0x85, 0x6f, 0x76, + 0x94, 0xa3, 0xa7, 0xa8, 0xa7, 0xa2, 0x99, 0x8e, 0x7a, 0x65, 0x62, 0x6e, + 0x7d, 0x96, 0xaa, 0xa3, 0x8c, 0x79, 0x60, 0x53, 0x54, 0x56, 0x57, 0x57, + 0x5f, 0x7b, 0x9a, 0x9f, 0x9e, 0x9d, 0x9a, 0x98, 0x98, 0x98, 0x97, 0x95, + 0x8b, 0x82, 0x7b, 0x6d, 0x5d, 0x59, 0x55, 0x51, 0x50, 0x5d, 0x6f, 0x78, + 0x7e, 0x87, 0x8d, 0x82, 0x6e, 0x62, 0x58, 0x59, 0x61, 0x66, 0x67, 0x64, + 0x5f, 0x62, 0x65, 0x67, 0x6a, 0x6c, 0x6e, 0x70, 0x70, 0x70, 0x73, 0x74, + 0x73, 0x73, 0x73, 0x74, 0x73, 0x72, 0x72, 0x72, 0x70, 0x6f, 0x6e, 0x6d, + 0x6d, 0x70, 0x7a, 0x8d, 0x99, 0xa0, 0xa7, 0xac, 0xab, 0xa9, 0xa6, 0xa0, + 0x98, 0x94, 0x91, 0x90, 0x8e, 0x8d, 0x8e, 0x8d, 0x8c, 0x89, 0x88, 0x86, + 0x85, 0x84, 0x86, 0x87, 0x87, 0x86, 0x85, 0x82, 0x7c, 0x79, 0x77, 0x78, + 0x7a, 0x7e, 0x82, 0x83, 0x83, 0x82, 0x7f, 0x7e, 0x7c, 0x7b, 0x7a, 0x78, + 0x78, 0x78, 0x79, 0x7a, 0x79, 0x7b, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x82, + 0x82, 0x80, 0x81, 0x80, 0x82, 0x82, 0x84, 0x86, 0x97, 0x93, 0x90, 0x8d, + 0x89, 0x83, 0x7f, 0x7c, 0x79, 0x76, 0x73, 0x6f, 0x6d, 0x6c, 0x6b, 0x68, + 0x66, 0x66, 0x66, 0x65, 0x63, 0x62, 0x62, 0x62, 0x61, 0x60, 0x60, 0x60, + 0x60, 0x5e, 0x5e, 0x5e, 0x5f, 0x60, 0x60, 0x60, 0x62, 0x64, 0x63, 0x64, + 0x82, 0xc5, 0xdb, 0xde, 0xdd, 0xdf, 0xde, 0xdd, 0xdd, 0xde, 0xde, 0xdf, + 0xe0, 0xe0, 0xe0, 0xdf, 0xdf, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe0, 0xe1, + 0xe2, 0xe2, 0xe2, 0xe2, 0xe1, 0xe1, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, + 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe2, 0xe2, 0xe2, 0xe1, + 0xe1, 0xe1, 0xe0, 0xe1, 0xe0, 0xdf, 0xdf, 0xde, 0xdb, 0xda, 0xd9, 0xd9, + 0xd9, 0xd9, 0xd9, 0xd8, 0xd8, 0xd9, 0xdb, 0xdb, 0xdb, 0xda, 0xd8, 0xd8, + 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd6, 0xd6, 0xd5, 0xd5, 0xd4, 0xd5, 0xd5, + 0xd5, 0xd5, 0xd4, 0xd2, 0xd3, 0xd2, 0xd1, 0xd0, 0xcf, 0xd0, 0xd1, 0xd0, + 0xcf, 0xcc, 0xcb, 0xc8, 0xc7, 0xc3, 0xbf, 0xb6, 0xad, 0xa5, 0x9b, 0xa0, + 0xa9, 0xab, 0xab, 0xaa, 0xaa, 0xa9, 0xa8, 0xa6, 0xa3, 0x9f, 0x9d, 0x9b, + 0x97, 0x8e, 0x82, 0x7b, 0x84, 0x82, 0x71, 0x6d, 0x8b, 0x9e, 0xa5, 0xa8, + 0xaa, 0xa6, 0xa1, 0x96, 0x80, 0x6b, 0x61, 0x69, 0x74, 0x88, 0xa6, 0xa9, + 0x97, 0x84, 0x65, 0x4f, 0x4d, 0x4c, 0x4d, 0x52, 0x6b, 0x8c, 0xa3, 0xa5, + 0xa2, 0x9d, 0x98, 0x98, 0x9c, 0x9b, 0x95, 0x8f, 0x84, 0x7c, 0x74, 0x67, + 0x5b, 0x57, 0x4f, 0x4d, 0x54, 0x66, 0x73, 0x7e, 0x85, 0x8d, 0x8f, 0x7e, + 0x68, 0x5d, 0x57, 0x5c, 0x63, 0x66, 0x65, 0x60, 0x60, 0x65, 0x67, 0x68, + 0x6a, 0x6b, 0x6e, 0x71, 0x71, 0x71, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, + 0x72, 0x71, 0x71, 0x72, 0x72, 0x70, 0x6f, 0x6e, 0x6d, 0x71, 0x7f, 0x93, + 0x9f, 0xa5, 0xaa, 0xad, 0xab, 0xa7, 0xa4, 0x9c, 0x94, 0x8f, 0x8a, 0x87, + 0x84, 0x83, 0x83, 0x82, 0x81, 0x7f, 0x7e, 0x7c, 0x7b, 0x7c, 0x7e, 0x80, + 0x81, 0x82, 0x83, 0x82, 0x7f, 0x7b, 0x79, 0x79, 0x7a, 0x7d, 0x80, 0x81, + 0x81, 0x80, 0x7d, 0x7d, 0x7c, 0x7b, 0x79, 0x78, 0x77, 0x77, 0x78, 0x79, + 0x79, 0x7b, 0x7e, 0x80, 0x81, 0x83, 0x84, 0x83, 0x83, 0x82, 0x82, 0x81, + 0x82, 0x83, 0x85, 0x87, 0x94, 0x91, 0x8e, 0x8c, 0x88, 0x82, 0x7f, 0x7c, + 0x7a, 0x77, 0x73, 0x70, 0x6e, 0x6d, 0x6c, 0x69, 0x67, 0x65, 0x65, 0x65, + 0x62, 0x63, 0x62, 0x62, 0x61, 0x60, 0x60, 0x5f, 0x60, 0x5f, 0x5e, 0x5e, + 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x61, 0x67, 0x9d, 0xd3, 0xdd, 0xde, + 0xde, 0xdf, 0xdf, 0xde, 0xde, 0xdf, 0xdf, 0xde, 0xdf, 0xdf, 0xdf, 0xe0, + 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, + 0xe2, 0xe1, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, + 0xe3, 0xe3, 0xe3, 0xe2, 0xe2, 0xe2, 0xe1, 0xe2, 0xe2, 0xe2, 0xe1, 0xe1, + 0xe1, 0xe1, 0xe1, 0xe0, 0xde, 0xdd, 0xdb, 0xda, 0xd8, 0xd7, 0xd6, 0xd6, + 0xd7, 0xd8, 0xd9, 0xda, 0xda, 0xd9, 0xd8, 0xd7, 0xd5, 0xd6, 0xd6, 0xd6, + 0xd6, 0xd6, 0xd6, 0xd5, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd3, 0xd3, + 0xd3, 0xd2, 0xd1, 0xd1, 0xd0, 0xd0, 0xd0, 0xd0, 0xcf, 0xcd, 0xcb, 0xc8, + 0xc6, 0xc4, 0xc0, 0xb9, 0xb4, 0xac, 0x9f, 0x9a, 0xa5, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa8, 0xa7, 0xa6, 0xa4, 0xa0, 0x9f, 0x9e, 0x9b, 0x93, 0x88, 0x7d, + 0x7f, 0x7e, 0x73, 0x68, 0x83, 0x9a, 0xa3, 0xa8, 0xab, 0xaa, 0xa7, 0x9d, + 0x87, 0x6f, 0x62, 0x66, 0x6d, 0x7e, 0xa0, 0xab, 0x9f, 0x8d, 0x6a, 0x4c, + 0x45, 0x46, 0x4a, 0x59, 0x79, 0x94, 0xa4, 0xa7, 0xa4, 0x9c, 0x96, 0x9a, + 0x9f, 0x9e, 0x96, 0x8a, 0x80, 0x79, 0x72, 0x65, 0x5b, 0x56, 0x4d, 0x4d, + 0x58, 0x6b, 0x77, 0x81, 0x89, 0x91, 0x8f, 0x7b, 0x64, 0x5a, 0x57, 0x5c, + 0x63, 0x66, 0x64, 0x5f, 0x60, 0x65, 0x68, 0x69, 0x6a, 0x6b, 0x6f, 0x71, + 0x72, 0x72, 0x73, 0x74, 0x73, 0x73, 0x73, 0x73, 0x70, 0x71, 0x72, 0x72, + 0x72, 0x71, 0x70, 0x6e, 0x6d, 0x73, 0x84, 0x98, 0xa3, 0xa8, 0xab, 0xac, + 0xaa, 0xa5, 0xa0, 0x98, 0x8f, 0x88, 0x81, 0x7d, 0x7a, 0x79, 0x79, 0x78, + 0x77, 0x75, 0x75, 0x73, 0x73, 0x74, 0x75, 0x79, 0x7c, 0x7f, 0x80, 0x80, + 0x7f, 0x7d, 0x7b, 0x7a, 0x7a, 0x7c, 0x7f, 0x80, 0x81, 0x80, 0x7d, 0x7b, + 0x7b, 0x7a, 0x78, 0x77, 0x77, 0x78, 0x78, 0x78, 0x79, 0x7d, 0x7e, 0x7f, + 0x82, 0x84, 0x84, 0x84, 0x84, 0x82, 0x83, 0x83, 0x83, 0x84, 0x86, 0x88, + 0x93, 0x8f, 0x8d, 0x8a, 0x87, 0x82, 0x7f, 0x7c, 0x7a, 0x77, 0x72, 0x70, + 0x6e, 0x6d, 0x6c, 0x6a, 0x67, 0x65, 0x64, 0x64, 0x62, 0x62, 0x62, 0x62, + 0x61, 0x60, 0x60, 0x60, 0x60, 0x5f, 0x5e, 0x5d, 0x5e, 0x5f, 0x60, 0x61, + 0x62, 0x62, 0x61, 0x6b, 0xaf, 0xd8, 0xdd, 0xdd, 0xdd, 0xdf, 0xdf, 0xdf, + 0xdf, 0xdf, 0xdf, 0xde, 0xdf, 0xdf, 0xde, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, + 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe1, 0xe1, 0xe2, 0xe2, + 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe2, + 0xe2, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe0, 0xe1, 0xe0, 0xe1, 0xe0, 0xe1, + 0xdf, 0xdf, 0xdd, 0xdc, 0xda, 0xd8, 0xd6, 0xd6, 0xd6, 0xd7, 0xd8, 0xd9, + 0xda, 0xd9, 0xd7, 0xd6, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd6, 0xd5, + 0xd3, 0xd3, 0xd2, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd2, 0xd1, 0xd1, + 0xd0, 0xd0, 0xcf, 0xcf, 0xcf, 0xcd, 0xcb, 0xc8, 0xc6, 0xc4, 0xc1, 0xba, + 0xb6, 0xb0, 0xa3, 0x98, 0xa2, 0xa6, 0xa8, 0xa8, 0xa8, 0xa7, 0xa7, 0xa6, + 0xa4, 0xa0, 0x9f, 0x9e, 0x9c, 0x96, 0x8b, 0x7f, 0x7e, 0x7c, 0x74, 0x67, + 0x7d, 0x95, 0xa0, 0xa7, 0xac, 0xac, 0xaa, 0xa0, 0x8a, 0x71, 0x63, 0x63, + 0x69, 0x7a, 0x9a, 0xab, 0xa4, 0x93, 0x6f, 0x4a, 0x44, 0x4c, 0x54, 0x63, + 0x7e, 0x95, 0xa3, 0xa6, 0xa3, 0x99, 0x97, 0x9f, 0xa3, 0xa1, 0x97, 0x87, + 0x7c, 0x77, 0x70, 0x65, 0x5a, 0x53, 0x4c, 0x4e, 0x5b, 0x6d, 0x78, 0x84, + 0x8c, 0x93, 0x8f, 0x79, 0x61, 0x58, 0x57, 0x5c, 0x63, 0x64, 0x62, 0x5e, + 0x60, 0x66, 0x68, 0x6a, 0x6b, 0x6c, 0x6e, 0x71, 0x71, 0x71, 0x74, 0x74, + 0x73, 0x73, 0x74, 0x72, 0x70, 0x71, 0x72, 0x73, 0x73, 0x72, 0x70, 0x6f, + 0x6e, 0x75, 0x88, 0x9a, 0xa4, 0xa9, 0xac, 0xac, 0xa8, 0xa2, 0x9c, 0x93, + 0x89, 0x81, 0x7b, 0x77, 0x75, 0x73, 0x74, 0x73, 0x73, 0x71, 0x70, 0x6f, + 0x6f, 0x70, 0x71, 0x75, 0x78, 0x7c, 0x7e, 0x7e, 0x7e, 0x7d, 0x7c, 0x7c, + 0x7b, 0x7c, 0x7e, 0x7f, 0x7f, 0x7f, 0x7d, 0x7b, 0x7b, 0x79, 0x77, 0x77, + 0x76, 0x77, 0x78, 0x77, 0x79, 0x7d, 0x7e, 0x80, 0x82, 0x85, 0x85, 0x85, + 0x84, 0x83, 0x84, 0x84, 0x83, 0x84, 0x87, 0x88, 0x90, 0x8d, 0x8a, 0x88, + 0x85, 0x80, 0x7e, 0x7b, 0x79, 0x77, 0x72, 0x6f, 0x6e, 0x6d, 0x6c, 0x69, + 0x67, 0x65, 0x64, 0x64, 0x62, 0x62, 0x62, 0x62, 0x61, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x5e, 0x5e, 0x5e, 0x5e, 0x60, 0x61, 0x63, 0x60, 0x62, 0x78, + 0xc1, 0xdb, 0xdc, 0xdc, 0xde, 0xdf, 0xdf, 0xdf, 0xe0, 0xdf, 0xdf, 0xdf, + 0xdf, 0xdf, 0xdf, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe1, 0xe1, + 0xe2, 0xe2, 0xe2, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, + 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe2, 0xe2, 0xe1, 0xe0, 0xe1, + 0xe1, 0xe0, 0xdf, 0xdf, 0xe0, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xdf, 0xde, + 0xdd, 0xdb, 0xd8, 0xd7, 0xd5, 0xd4, 0xd3, 0xd6, 0xd8, 0xd8, 0xd8, 0xd7, + 0xd4, 0xd3, 0xd3, 0xd3, 0xd3, 0xd5, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd2, + 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd2, 0xd2, 0xd1, 0xd0, 0xd0, 0xcf, 0xce, + 0xce, 0xcd, 0xcb, 0xc8, 0xc7, 0xc5, 0xc1, 0xbc, 0xb8, 0xb3, 0xa8, 0x99, + 0x9b, 0xa0, 0xa4, 0xa6, 0xa8, 0xa8, 0xa8, 0xa6, 0xa3, 0xa1, 0x9f, 0x9e, + 0x9c, 0x99, 0x90, 0x83, 0x7d, 0x7b, 0x76, 0x66, 0x73, 0x8c, 0x9a, 0xa4, + 0xac, 0xae, 0xab, 0xa4, 0x90, 0x74, 0x64, 0x61, 0x65, 0x73, 0x8e, 0xa8, + 0xaa, 0x9c, 0x78, 0x4a, 0x4b, 0x64, 0x70, 0x76, 0x7e, 0x91, 0xa0, 0xa3, + 0x9f, 0x94, 0x9c, 0xac, 0xae, 0xa9, 0x98, 0x82, 0x78, 0x71, 0x6b, 0x62, + 0x59, 0x4f, 0x4b, 0x4f, 0x61, 0x6f, 0x79, 0x87, 0x8f, 0x95, 0x8e, 0x75, + 0x5f, 0x57, 0x58, 0x5e, 0x62, 0x60, 0x5f, 0x5e, 0x61, 0x67, 0x69, 0x6a, + 0x6b, 0x6c, 0x6f, 0x70, 0x71, 0x72, 0x74, 0x74, 0x73, 0x73, 0x73, 0x71, + 0x6f, 0x72, 0x73, 0x75, 0x76, 0x74, 0x71, 0x6f, 0x71, 0x7a, 0x8c, 0x9c, + 0xa6, 0xaa, 0xac, 0xab, 0xa3, 0x9a, 0x94, 0x88, 0x7d, 0x76, 0x72, 0x70, + 0x70, 0x6f, 0x70, 0x6f, 0x6e, 0x6c, 0x6b, 0x6b, 0x6c, 0x6c, 0x6f, 0x72, + 0x74, 0x77, 0x79, 0x7b, 0x7b, 0x7d, 0x7e, 0x7d, 0x7d, 0x7b, 0x7c, 0x7e, + 0x7e, 0x7d, 0x7b, 0x79, 0x79, 0x78, 0x76, 0x76, 0x75, 0x76, 0x77, 0x76, + 0x79, 0x7e, 0x7f, 0x80, 0x82, 0x85, 0x86, 0x87, 0x86, 0x85, 0x86, 0x86, + 0x84, 0x85, 0x87, 0x88, 0x8c, 0x8a, 0x88, 0x87, 0x84, 0x80, 0x7d, 0x79, + 0x78, 0x76, 0x72, 0x6f, 0x6e, 0x6e, 0x6c, 0x69, 0x67, 0x66, 0x65, 0x64, + 0x62, 0x62, 0x62, 0x61, 0x61, 0x60, 0x5f, 0x60, 0x60, 0x5f, 0x60, 0x5f, + 0x5e, 0x5e, 0x5f, 0x62, 0x61, 0x5c, 0x6a, 0x9b, 0xd2, 0xdc, 0xdb, 0xdc, + 0xdd, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xde, 0xde, 0xe0, + 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, + 0xe1, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, + 0xe3, 0xe3, 0xe3, 0xe2, 0xe2, 0xe2, 0xe2, 0xe0, 0xe0, 0xe0, 0xdf, 0xdf, + 0xdf, 0xde, 0xdd, 0xdd, 0xdc, 0xdd, 0xde, 0xde, 0xde, 0xdc, 0xdb, 0xda, + 0xd8, 0xd6, 0xd3, 0xd3, 0xd3, 0xd4, 0xd5, 0xd7, 0xd6, 0xd5, 0xd4, 0xd2, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd3, 0xd3, 0xd2, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, + 0xd2, 0xd1, 0xd1, 0xd1, 0xcf, 0xcf, 0xce, 0xce, 0xcd, 0xcb, 0xcb, 0xc9, + 0xc7, 0xc5, 0xc1, 0xbe, 0xbb, 0xb7, 0xaf, 0xa2, 0x96, 0x98, 0x9c, 0xa1, + 0xa5, 0xa7, 0xa7, 0xa6, 0xa4, 0xa1, 0x9e, 0x9e, 0x9d, 0x9c, 0x94, 0x89, + 0x7f, 0x7c, 0x78, 0x69, 0x6a, 0x81, 0x90, 0xa0, 0xab, 0xaf, 0xae, 0xa9, + 0x97, 0x77, 0x66, 0x61, 0x63, 0x6e, 0x83, 0xa2, 0xae, 0xa7, 0x87, 0x54, + 0x5c, 0x7f, 0x8c, 0x88, 0x79, 0x87, 0x9c, 0xa3, 0x9e, 0x91, 0xa2, 0xbc, + 0xbf, 0xb6, 0x9f, 0x87, 0x77, 0x6c, 0x65, 0x5c, 0x54, 0x4b, 0x4d, 0x56, + 0x67, 0x70, 0x7d, 0x8d, 0x95, 0x99, 0x8e, 0x71, 0x5c, 0x56, 0x59, 0x5f, + 0x60, 0x5c, 0x5b, 0x5f, 0x64, 0x68, 0x6a, 0x6b, 0x6c, 0x6d, 0x70, 0x71, + 0x71, 0x72, 0x74, 0x75, 0x74, 0x73, 0x73, 0x71, 0x71, 0x73, 0x75, 0x78, + 0x7a, 0x78, 0x74, 0x72, 0x74, 0x80, 0x92, 0xa0, 0xa7, 0xaa, 0xaa, 0xa4, + 0x99, 0x8c, 0x84, 0x7a, 0x72, 0x6d, 0x6b, 0x69, 0x69, 0x6a, 0x6a, 0x69, + 0x68, 0x67, 0x66, 0x66, 0x66, 0x67, 0x6b, 0x6e, 0x72, 0x75, 0x77, 0x7a, + 0x7b, 0x7d, 0x7e, 0x7d, 0x7d, 0x7b, 0x7b, 0x7c, 0x7c, 0x7b, 0x7a, 0x77, + 0x76, 0x76, 0x75, 0x75, 0x77, 0x78, 0x78, 0x78, 0x7b, 0x7f, 0x80, 0x82, + 0x84, 0x86, 0x87, 0x88, 0x87, 0x86, 0x87, 0x87, 0x86, 0x86, 0x87, 0x87, + 0x89, 0x86, 0x85, 0x84, 0x81, 0x7d, 0x7a, 0x78, 0x76, 0x74, 0x72, 0x70, + 0x6f, 0x6e, 0x6c, 0x6a, 0x67, 0x66, 0x66, 0x65, 0x62, 0x62, 0x62, 0x62, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x5f, 0x5f, 0x5f, 0x5f, 0x60, 0x5f, 0x61, + 0x5e, 0x5f, 0x79, 0xb9, 0xd9, 0xdb, 0xdb, 0xdb, 0xdd, 0xde, 0xde, 0xde, + 0xde, 0xdd, 0xdd, 0xdd, 0xdc, 0xdd, 0xde, 0xde, 0xde, 0xe0, 0xe1, 0xe1, + 0xe2, 0xe2, 0xe2, 0xe2, 0xe1, 0xe0, 0xe2, 0xe1, 0xe1, 0xe0, 0xe0, 0xe1, + 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe2, + 0xe2, 0xe2, 0xe2, 0xe0, 0xe1, 0xe1, 0xe1, 0xe0, 0xe0, 0xdf, 0xde, 0xde, + 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdb, 0xda, 0xdb, 0xdb, 0xda, 0xd6, 0xd3, + 0xd2, 0xd2, 0xd2, 0xd4, 0xd5, 0xd5, 0xd4, 0xd3, 0xcf, 0xcd, 0xcd, 0xce, + 0xd0, 0xd2, 0xd2, 0xd1, 0xd0, 0xce, 0xce, 0xcf, 0xd0, 0xcf, 0xcf, 0xcf, + 0xce, 0xce, 0xcd, 0xcd, 0xcc, 0xca, 0xca, 0xc9, 0xc8, 0xc6, 0xc2, 0xbf, + 0xbc, 0xb9, 0xb3, 0xa8, 0x99, 0x92, 0x92, 0x99, 0xa0, 0xa3, 0xa5, 0xa5, + 0xa3, 0xa2, 0xa0, 0x9f, 0x9f, 0x9d, 0x98, 0x8e, 0x84, 0x7f, 0x7a, 0x6d, + 0x65, 0x74, 0x83, 0x98, 0xa8, 0xae, 0xb0, 0xac, 0x9c, 0x78, 0x67, 0x63, + 0x64, 0x6b, 0x7a, 0x98, 0xac, 0xae, 0x95, 0x63, 0x68, 0x87, 0x93, 0x8d, + 0x77, 0x79, 0x94, 0xa2, 0xa0, 0x95, 0x9a, 0xb1, 0xbb, 0xb7, 0xa4, 0x8e, + 0x78, 0x68, 0x60, 0x59, 0x4e, 0x49, 0x53, 0x5d, 0x6a, 0x6f, 0x82, 0x94, + 0x9b, 0x9b, 0x8c, 0x6d, 0x5b, 0x56, 0x5a, 0x5f, 0x5e, 0x5c, 0x5d, 0x61, + 0x66, 0x69, 0x6a, 0x6b, 0x6c, 0x6f, 0x72, 0x73, 0x73, 0x75, 0x75, 0x74, + 0x74, 0x74, 0x72, 0x71, 0x73, 0x74, 0x76, 0x7b, 0x7e, 0x7c, 0x79, 0x77, + 0x79, 0x86, 0x96, 0xa2, 0xa8, 0xa8, 0xa4, 0x98, 0x87, 0x7b, 0x75, 0x70, + 0x6c, 0x68, 0x65, 0x65, 0x64, 0x66, 0x67, 0x66, 0x65, 0x63, 0x63, 0x64, + 0x64, 0x65, 0x69, 0x6d, 0x71, 0x73, 0x74, 0x78, 0x7b, 0x7e, 0x7e, 0x7e, + 0x7d, 0x7a, 0x7a, 0x7a, 0x7a, 0x79, 0x78, 0x77, 0x75, 0x75, 0x75, 0x77, + 0x79, 0x7b, 0x7c, 0x7c, 0x80, 0x82, 0x84, 0x85, 0x87, 0x88, 0x87, 0x89, + 0x89, 0x88, 0x88, 0x87, 0x86, 0x86, 0x87, 0x85, 0x86, 0x84, 0x82, 0x81, + 0x7e, 0x7a, 0x78, 0x75, 0x74, 0x73, 0x71, 0x70, 0x6e, 0x6d, 0x6b, 0x6a, + 0x67, 0x66, 0x66, 0x65, 0x62, 0x61, 0x62, 0x62, 0x60, 0x60, 0x60, 0x5f, + 0x5f, 0x5f, 0x60, 0x5f, 0x60, 0x60, 0x60, 0x60, 0x5f, 0x6e, 0x8d, 0xc7, + 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xde, 0xdf, 0xdf, 0xde, 0xde, 0xde, 0xdd, + 0xdd, 0xdd, 0xdf, 0xdf, 0xdf, 0xe0, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, + 0xe2, 0xe1, 0xe2, 0xe1, 0xe1, 0xe0, 0xe0, 0xe1, 0xe3, 0xe3, 0xe3, 0xe2, + 0xe3, 0xe3, 0xe2, 0xe2, 0xe3, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe1, + 0xe2, 0xe2, 0xe2, 0xe1, 0xe1, 0xe0, 0xdf, 0xdf, 0xde, 0xde, 0xdc, 0xdc, + 0xda, 0xda, 0xd9, 0xda, 0xda, 0xdb, 0xd9, 0xd7, 0xd6, 0xd4, 0xd2, 0xd2, + 0xd2, 0xd3, 0xd3, 0xd3, 0xd1, 0xcd, 0xcb, 0xcb, 0xcc, 0xce, 0xd1, 0xd1, + 0xd0, 0xce, 0xcc, 0xcd, 0xce, 0xcf, 0xcf, 0xce, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcb, 0xc9, 0xca, 0xc9, 0xc8, 0xc7, 0xc4, 0xbf, 0xbb, 0xb9, 0xb5, 0xac, + 0x9e, 0x92, 0x8e, 0x93, 0x9b, 0xa1, 0xa4, 0xa4, 0xa2, 0xa3, 0xa2, 0xa1, + 0xa0, 0x9e, 0x9b, 0x92, 0x88, 0x82, 0x7d, 0x71, 0x66, 0x6d, 0x79, 0x91, + 0xa4, 0xae, 0xb1, 0xaf, 0xa0, 0x7a, 0x69, 0x65, 0x65, 0x6a, 0x76, 0x8e, + 0xa8, 0xaf, 0x9f, 0x71, 0x70, 0x89, 0x93, 0x8d, 0x78, 0x6d, 0x8a, 0x9f, + 0xa3, 0x9b, 0x8d, 0x96, 0xa8, 0xac, 0xa4, 0x91, 0x77, 0x66, 0x5e, 0x55, + 0x4a, 0x48, 0x57, 0x62, 0x6a, 0x70, 0x88, 0x99, 0x9f, 0x9a, 0x88, 0x69, + 0x59, 0x57, 0x5c, 0x5f, 0x5d, 0x5d, 0x5f, 0x62, 0x67, 0x6a, 0x6c, 0x6c, + 0x6d, 0x70, 0x72, 0x73, 0x74, 0x76, 0x76, 0x74, 0x74, 0x74, 0x73, 0x72, + 0x73, 0x74, 0x77, 0x7d, 0x81, 0x7f, 0x7d, 0x7c, 0x7e, 0x89, 0x98, 0xa2, + 0xa6, 0xa5, 0x9c, 0x8b, 0x79, 0x70, 0x6d, 0x69, 0x67, 0x64, 0x64, 0x64, + 0x63, 0x64, 0x65, 0x65, 0x63, 0x62, 0x62, 0x63, 0x65, 0x66, 0x6a, 0x6e, + 0x71, 0x72, 0x74, 0x77, 0x7b, 0x7e, 0x7e, 0x7e, 0x7d, 0x7a, 0x78, 0x77, + 0x76, 0x77, 0x76, 0x76, 0x76, 0x77, 0x78, 0x7a, 0x7c, 0x7f, 0x7f, 0x80, + 0x84, 0x86, 0x86, 0x87, 0x89, 0x8a, 0x89, 0x8a, 0x8a, 0x89, 0x88, 0x87, + 0x86, 0x86, 0x86, 0x85, 0x84, 0x82, 0x80, 0x7f, 0x7c, 0x78, 0x77, 0x74, + 0x73, 0x73, 0x70, 0x6f, 0x6e, 0x6c, 0x6a, 0x69, 0x67, 0x66, 0x65, 0x65, + 0x63, 0x62, 0x62, 0x61, 0x60, 0x60, 0x60, 0x5f, 0x5f, 0x60, 0x60, 0x5f, + 0x60, 0x60, 0x5f, 0x5f, 0x61, 0x7e, 0x9e, 0xce, 0xdb, 0xdb, 0xdc, 0xdd, + 0xdd, 0xde, 0xdf, 0xde, 0xde, 0xdf, 0xde, 0xde, 0xdd, 0xde, 0xdf, 0xdf, + 0xdf, 0xe0, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe1, 0xe2, 0xe1, + 0xe1, 0xe1, 0xe0, 0xe1, 0xe3, 0xe3, 0xe3, 0xe2, 0xe3, 0xe3, 0xe2, 0xe2, + 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe2, 0xe2, 0xe2, 0xe2, 0xe1, + 0xe1, 0xe0, 0xe0, 0xe0, 0xdf, 0xdf, 0xde, 0xdd, 0xdb, 0xdb, 0xd9, 0xda, + 0xda, 0xdb, 0xda, 0xd9, 0xd8, 0xd6, 0xd4, 0xd2, 0xd1, 0xd1, 0xd2, 0xd3, + 0xd2, 0xce, 0xcb, 0xca, 0xc9, 0xcb, 0xcf, 0xd0, 0xd0, 0xce, 0xcd, 0xcc, + 0xcd, 0xce, 0xce, 0xce, 0xcd, 0xcd, 0xcc, 0xcc, 0xcb, 0xca, 0xc9, 0xc9, + 0xc8, 0xc7, 0xc4, 0xc0, 0xbc, 0xb9, 0xb6, 0xae, 0xa1, 0x95, 0x8f, 0x8f, + 0x98, 0xa0, 0xa3, 0xa3, 0xa2, 0xa3, 0xa3, 0xa2, 0xa1, 0x9f, 0x9c, 0x93, + 0x8a, 0x85, 0x7f, 0x73, 0x66, 0x68, 0x74, 0x8d, 0xa2, 0xae, 0xb2, 0xb0, + 0xa3, 0x7c, 0x69, 0x66, 0x66, 0x6a, 0x74, 0x89, 0xa4, 0xae, 0xa3, 0x7a, + 0x75, 0x8b, 0x94, 0x8d, 0x78, 0x67, 0x82, 0x9b, 0xa2, 0x9d, 0x8a, 0x84, + 0x96, 0x9f, 0x9e, 0x90, 0x76, 0x64, 0x5b, 0x52, 0x47, 0x4a, 0x5b, 0x64, + 0x6c, 0x72, 0x8c, 0x9c, 0x9f, 0x9a, 0x86, 0x65, 0x58, 0x57, 0x5c, 0x5e, + 0x5c, 0x5e, 0x60, 0x63, 0x68, 0x6b, 0x6c, 0x6c, 0x6d, 0x71, 0x73, 0x74, + 0x74, 0x76, 0x76, 0x74, 0x75, 0x75, 0x74, 0x73, 0x74, 0x76, 0x79, 0x7f, + 0x83, 0x82, 0x7f, 0x7e, 0x80, 0x8b, 0x99, 0xa2, 0xa3, 0xa0, 0x95, 0x82, + 0x72, 0x6c, 0x68, 0x65, 0x63, 0x62, 0x63, 0x64, 0x63, 0x65, 0x65, 0x64, + 0x63, 0x62, 0x61, 0x63, 0x65, 0x67, 0x6a, 0x6f, 0x72, 0x73, 0x73, 0x76, + 0x7a, 0x7d, 0x7e, 0x7e, 0x7d, 0x7a, 0x78, 0x76, 0x75, 0x75, 0x76, 0x77, + 0x77, 0x78, 0x7a, 0x7c, 0x7e, 0x80, 0x81, 0x82, 0x86, 0x87, 0x88, 0x89, + 0x8a, 0x8b, 0x8a, 0x8a, 0x8a, 0x89, 0x88, 0x87, 0x86, 0x86, 0x85, 0x84, + 0x81, 0x81, 0x7f, 0x7d, 0x7b, 0x77, 0x75, 0x74, 0x74, 0x72, 0x70, 0x70, + 0x6d, 0x6c, 0x6a, 0x69, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62, 0x61, 0x61, + 0x61, 0x60, 0x5f, 0x5f, 0x5f, 0x60, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5e, + 0x65, 0x97, 0xb9, 0xd4, 0xda, 0xdb, 0xdc, 0xdc, 0xdc, 0xdc, 0xde, 0xdf, + 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xde, 0xde, 0xe0, 0xe1, 0xe1, + 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe1, 0xe1, 0xe0, 0xe0, 0xe1, 0xe1, 0xe2, + 0xe3, 0xe3, 0xe3, 0xe2, 0xe2, 0xe2, 0xe2, 0xe1, 0xe2, 0xe1, 0xe1, 0xe1, + 0xe2, 0xe2, 0xe2, 0xe1, 0xe2, 0xe2, 0xe2, 0xe1, 0xe1, 0xe0, 0xe1, 0xe1, + 0xe1, 0xe1, 0xdf, 0xdf, 0xdd, 0xdd, 0xdb, 0xdb, 0xdb, 0xda, 0xd9, 0xd8, + 0xd9, 0xda, 0xd8, 0xd5, 0xd2, 0xd1, 0xd1, 0xd2, 0xd3, 0xd1, 0xce, 0xcc, + 0xc9, 0xc7, 0xcb, 0xcd, 0xcf, 0xcf, 0xcd, 0xcb, 0xcb, 0xcc, 0xcc, 0xcd, + 0xcc, 0xcb, 0xcc, 0xcc, 0xcc, 0xcb, 0xc8, 0xc8, 0xc8, 0xc7, 0xc5, 0xc0, + 0xbd, 0xbb, 0xb7, 0xb1, 0xa7, 0x9c, 0x94, 0x8d, 0x94, 0x9d, 0xa0, 0xa1, + 0xa1, 0xa2, 0xa3, 0xa3, 0xa1, 0x9f, 0x9c, 0x96, 0x8f, 0x8a, 0x81, 0x74, + 0x68, 0x64, 0x6c, 0x86, 0x9f, 0xac, 0xb2, 0xb1, 0xa5, 0x7f, 0x6a, 0x67, + 0x67, 0x68, 0x71, 0x84, 0x9e, 0xa9, 0xa7, 0x89, 0x81, 0x94, 0x99, 0x8f, + 0x78, 0x63, 0x78, 0x93, 0x9e, 0x9d, 0x8c, 0x74, 0x7a, 0x83, 0x8c, 0x8a, + 0x73, 0x5e, 0x54, 0x4a, 0x46, 0x50, 0x60, 0x6a, 0x70, 0x79, 0x93, 0x9e, + 0x9f, 0x97, 0x81, 0x61, 0x57, 0x58, 0x5c, 0x5e, 0x5c, 0x5e, 0x60, 0x65, + 0x68, 0x6b, 0x6b, 0x6b, 0x6e, 0x72, 0x74, 0x75, 0x75, 0x75, 0x75, 0x75, + 0x76, 0x76, 0x76, 0x74, 0x76, 0x79, 0x7d, 0x83, 0x86, 0x84, 0x81, 0x81, + 0x83, 0x8c, 0x97, 0x9e, 0x9d, 0x96, 0x88, 0x77, 0x6c, 0x67, 0x64, 0x62, + 0x61, 0x61, 0x63, 0x64, 0x65, 0x66, 0x65, 0x63, 0x63, 0x62, 0x61, 0x63, + 0x65, 0x67, 0x6b, 0x70, 0x72, 0x74, 0x74, 0x74, 0x77, 0x7c, 0x7e, 0x7f, + 0x7d, 0x7a, 0x76, 0x74, 0x74, 0x75, 0x76, 0x79, 0x7a, 0x7a, 0x7c, 0x7f, + 0x81, 0x82, 0x83, 0x86, 0x88, 0x89, 0x89, 0x8a, 0x8b, 0x8c, 0x8c, 0x8b, + 0x8a, 0x89, 0x87, 0x86, 0x86, 0x85, 0x85, 0x84, 0x7f, 0x7e, 0x7c, 0x7a, + 0x77, 0x75, 0x75, 0x74, 0x73, 0x72, 0x70, 0x6f, 0x6e, 0x6c, 0x69, 0x68, + 0x66, 0x65, 0x64, 0x62, 0x63, 0x62, 0x61, 0x61, 0x61, 0x60, 0x5f, 0x5f, + 0x5f, 0x5f, 0x5f, 0x5e, 0x5f, 0x5f, 0x5f, 0x5e, 0x71, 0xb0, 0xcf, 0xd8, + 0xda, 0xdb, 0xdc, 0xdc, 0xdc, 0xdb, 0xdc, 0xdd, 0xdd, 0xde, 0xde, 0xdf, + 0xdf, 0xdf, 0xde, 0xde, 0xdf, 0xe0, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, + 0xe2, 0xe2, 0xe1, 0xe0, 0xe0, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe1, 0xe0, + 0xe1, 0xe1, 0xe0, 0xe0, 0xe1, 0xe0, 0xe0, 0xe1, 0xe1, 0xe0, 0xdf, 0xe0, + 0xe0, 0xe0, 0xe1, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe0, + 0xde, 0xde, 0xde, 0xde, 0xde, 0xdc, 0xda, 0xd8, 0xd9, 0xd9, 0xd8, 0xd7, + 0xd6, 0xd4, 0xd4, 0xd2, 0xd3, 0xd3, 0xd2, 0xd0, 0xcb, 0xc6, 0xc6, 0xc8, + 0xca, 0xcd, 0xce, 0xcc, 0xc9, 0xc8, 0xc9, 0xc9, 0xcb, 0xc9, 0xca, 0xca, + 0xcb, 0xcb, 0xc9, 0xc7, 0xc7, 0xc6, 0xc5, 0xc2, 0xbf, 0xbc, 0xb8, 0xb2, + 0xac, 0xa4, 0x9c, 0x90, 0x8d, 0x96, 0x9a, 0x9c, 0x9f, 0xa0, 0xa1, 0xa1, + 0xa0, 0x9e, 0x9e, 0x99, 0x93, 0x8e, 0x86, 0x78, 0x6a, 0x62, 0x66, 0x7b, + 0x97, 0xa9, 0xb1, 0xb2, 0xa8, 0x85, 0x6b, 0x68, 0x68, 0x6a, 0x70, 0x7e, + 0x94, 0xa1, 0xab, 0x9a, 0x91, 0xa8, 0xab, 0x93, 0x7a, 0x63, 0x6f, 0x89, + 0x95, 0x9b, 0x91, 0x6d, 0x5d, 0x5d, 0x69, 0x77, 0x6b, 0x59, 0x4f, 0x48, + 0x4d, 0x59, 0x65, 0x6c, 0x74, 0x82, 0x9a, 0xa0, 0x9d, 0x93, 0x79, 0x5d, + 0x57, 0x59, 0x5e, 0x5d, 0x5d, 0x5f, 0x61, 0x65, 0x69, 0x6b, 0x6b, 0x6c, + 0x6f, 0x72, 0x76, 0x78, 0x78, 0x77, 0x76, 0x75, 0x76, 0x77, 0x77, 0x77, + 0x7a, 0x7f, 0x83, 0x88, 0x88, 0x86, 0x83, 0x83, 0x85, 0x8d, 0x95, 0x96, + 0x8f, 0x86, 0x77, 0x6b, 0x65, 0x62, 0x61, 0x60, 0x61, 0x62, 0x64, 0x65, + 0x66, 0x66, 0x66, 0x64, 0x63, 0x62, 0x62, 0x64, 0x67, 0x69, 0x6d, 0x70, + 0x73, 0x74, 0x74, 0x74, 0x75, 0x79, 0x7d, 0x7e, 0x7d, 0x7a, 0x76, 0x73, + 0x73, 0x76, 0x79, 0x7e, 0x80, 0x80, 0x81, 0x83, 0x86, 0x86, 0x87, 0x89, + 0x8c, 0x8c, 0x8d, 0x8e, 0x8e, 0x8e, 0x8d, 0x8b, 0x8a, 0x89, 0x87, 0x86, + 0x85, 0x85, 0x85, 0x84, 0x7d, 0x7b, 0x79, 0x78, 0x76, 0x75, 0x73, 0x72, + 0x71, 0x71, 0x70, 0x6e, 0x6d, 0x6b, 0x68, 0x67, 0x64, 0x64, 0x63, 0x62, + 0x63, 0x61, 0x60, 0x61, 0x61, 0x60, 0x5f, 0x5f, 0x5f, 0x5f, 0x5e, 0x5e, + 0x5e, 0x5f, 0x5f, 0x62, 0x88, 0xc1, 0xd7, 0xd8, 0xd9, 0xdb, 0xdc, 0xdc, + 0xdd, 0xdc, 0xdc, 0xdc, 0xdc, 0xdd, 0xde, 0xde, 0xdf, 0xdf, 0xde, 0xde, + 0xde, 0xe0, 0xe1, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, + 0xe1, 0xe1, 0xe2, 0xe2, 0xe0, 0xe1, 0xe0, 0xdf, 0xe0, 0xe0, 0xdf, 0xdf, + 0xe0, 0xe0, 0xdf, 0xe0, 0xe0, 0xe0, 0xde, 0xdf, 0xdf, 0xdf, 0xde, 0xdf, + 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xdf, 0xe0, 0xe0, 0xe0, + 0xe0, 0xdf, 0xdd, 0xdc, 0xda, 0xda, 0xd9, 0xd7, 0xd6, 0xd6, 0xd5, 0xd5, + 0xd4, 0xd2, 0xd2, 0xd1, 0xcf, 0xcb, 0xc5, 0xc4, 0xc4, 0xc7, 0xcb, 0xcd, + 0xcb, 0xc8, 0xc6, 0xc5, 0xc8, 0xc9, 0xc9, 0xc9, 0xc8, 0xca, 0xc9, 0xc7, + 0xc6, 0xc5, 0xc5, 0xc2, 0xc0, 0xbe, 0xba, 0xb3, 0xad, 0xa7, 0xa1, 0x96, + 0x8a, 0x8d, 0x93, 0x97, 0x9b, 0x9d, 0xa1, 0xa2, 0xa1, 0x9f, 0x9e, 0x9b, + 0x95, 0x92, 0x8b, 0x7f, 0x70, 0x64, 0x64, 0x71, 0x8e, 0xa5, 0xaf, 0xb1, + 0xa9, 0x8a, 0x6d, 0x68, 0x69, 0x6c, 0x6f, 0x7a, 0x8a, 0x97, 0xa9, 0xa2, + 0x93, 0xb0, 0xb5, 0x9b, 0x7e, 0x65, 0x6b, 0x83, 0x8f, 0x95, 0x95, 0x75, + 0x59, 0x4e, 0x4d, 0x58, 0x5a, 0x56, 0x55, 0x57, 0x5c, 0x60, 0x65, 0x69, + 0x72, 0x86, 0x9d, 0x9e, 0x99, 0x8b, 0x70, 0x5a, 0x59, 0x5b, 0x5d, 0x5b, + 0x5f, 0x61, 0x63, 0x65, 0x69, 0x6b, 0x6b, 0x6c, 0x6f, 0x72, 0x76, 0x78, + 0x78, 0x78, 0x77, 0x75, 0x76, 0x78, 0x79, 0x7b, 0x7f, 0x83, 0x86, 0x89, + 0x88, 0x85, 0x82, 0x82, 0x84, 0x8a, 0x8f, 0x89, 0x7d, 0x75, 0x6c, 0x64, + 0x61, 0x60, 0x5f, 0x5f, 0x60, 0x63, 0x65, 0x66, 0x68, 0x68, 0x67, 0x66, + 0x65, 0x64, 0x63, 0x66, 0x69, 0x6b, 0x6e, 0x72, 0x74, 0x74, 0x74, 0x73, + 0x74, 0x77, 0x7c, 0x7d, 0x7c, 0x7a, 0x75, 0x73, 0x74, 0x78, 0x7e, 0x82, + 0x85, 0x86, 0x87, 0x89, 0x8b, 0x8c, 0x8c, 0x8c, 0x8e, 0x90, 0x91, 0x91, + 0x90, 0x90, 0x8e, 0x8c, 0x8b, 0x8a, 0x87, 0x86, 0x85, 0x84, 0x84, 0x82, + 0x7e, 0x7a, 0x79, 0x78, 0x76, 0x75, 0x73, 0x71, 0x71, 0x70, 0x6e, 0x6c, + 0x6b, 0x6a, 0x68, 0x66, 0x65, 0x63, 0x63, 0x62, 0x62, 0x60, 0x60, 0x61, + 0x61, 0x5f, 0x5e, 0x5e, 0x5f, 0x60, 0x60, 0x5f, 0x60, 0x60, 0x5f, 0x65, + 0x9c, 0xca, 0xd9, 0xd8, 0xd8, 0xda, 0xdb, 0xdc, 0xdc, 0xdb, 0xdb, 0xdc, + 0xdc, 0xdc, 0xdc, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, + 0xdf, 0xdf, 0xdf, 0xe0, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe1, 0xe1, + 0xdf, 0xdf, 0xdf, 0xde, 0xdf, 0xdf, 0xde, 0xde, 0xde, 0xdf, 0xde, 0xde, + 0xde, 0xdf, 0xdf, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, + 0xde, 0xde, 0xdf, 0xdf, 0xde, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xde, 0xde, + 0xdc, 0xdb, 0xd9, 0xd8, 0xd6, 0xd5, 0xd5, 0xd6, 0xd4, 0xd3, 0xd3, 0xd3, + 0xd1, 0xce, 0xc8, 0xc3, 0xc2, 0xc3, 0xc8, 0xcd, 0xcd, 0xc9, 0xc6, 0xc5, + 0xc5, 0xc8, 0xc9, 0xc9, 0xc8, 0xc9, 0xc7, 0xc7, 0xc6, 0xc5, 0xc4, 0xc1, + 0xc0, 0xbf, 0xbb, 0xb4, 0xaf, 0xaa, 0xa5, 0x9b, 0x8b, 0x88, 0x8e, 0x93, + 0x98, 0x9c, 0xa0, 0xa1, 0xa1, 0xa0, 0x9f, 0x9c, 0x96, 0x92, 0x8e, 0x85, + 0x75, 0x68, 0x64, 0x6b, 0x89, 0xa2, 0xad, 0xb0, 0xaa, 0x8f, 0x6d, 0x67, + 0x69, 0x6d, 0x70, 0x7a, 0x85, 0x91, 0xa6, 0xa6, 0x93, 0xa9, 0xb1, 0xa0, + 0x83, 0x66, 0x68, 0x7e, 0x89, 0x8e, 0x93, 0x7d, 0x62, 0x52, 0x44, 0x42, + 0x4d, 0x5d, 0x65, 0x6b, 0x6a, 0x64, 0x64, 0x66, 0x6e, 0x86, 0x9c, 0x9b, + 0x94, 0x83, 0x6a, 0x59, 0x59, 0x5b, 0x5c, 0x5b, 0x60, 0x62, 0x64, 0x66, + 0x69, 0x6b, 0x6c, 0x6d, 0x6f, 0x71, 0x75, 0x77, 0x77, 0x76, 0x77, 0x77, + 0x77, 0x78, 0x7b, 0x7d, 0x82, 0x85, 0x87, 0x87, 0x86, 0x84, 0x82, 0x82, + 0x83, 0x85, 0x85, 0x7c, 0x72, 0x6c, 0x67, 0x61, 0x5e, 0x5e, 0x5e, 0x5f, + 0x61, 0x65, 0x66, 0x68, 0x69, 0x69, 0x68, 0x66, 0x65, 0x65, 0x65, 0x67, + 0x6a, 0x6b, 0x6e, 0x72, 0x75, 0x75, 0x74, 0x72, 0x73, 0x76, 0x7a, 0x7c, + 0x7c, 0x7a, 0x75, 0x74, 0x76, 0x7b, 0x81, 0x85, 0x88, 0x88, 0x8a, 0x8c, + 0x8d, 0x8f, 0x8f, 0x8f, 0x90, 0x92, 0x93, 0x93, 0x92, 0x91, 0x8e, 0x8c, + 0x8b, 0x89, 0x87, 0x85, 0x84, 0x83, 0x81, 0x80, 0x7d, 0x7a, 0x79, 0x78, + 0x76, 0x74, 0x72, 0x71, 0x70, 0x6f, 0x6d, 0x6b, 0x6a, 0x69, 0x68, 0x66, + 0x65, 0x63, 0x63, 0x62, 0x61, 0x5f, 0x60, 0x61, 0x61, 0x5f, 0x5d, 0x5d, + 0x5e, 0x60, 0x61, 0x60, 0x60, 0x60, 0x5f, 0x66, 0xa7, 0xd0, 0xda, 0xd8, + 0xd8, 0xd9, 0xdb, 0xdc, 0xdc, 0xdb, 0xdb, 0xdc, 0xdc, 0xdb, 0xdb, 0xdc, + 0xdd, 0xdd, 0xde, 0xdf, 0xde, 0xdf, 0xdf, 0xde, 0xde, 0xdf, 0xde, 0xdf, + 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe1, 0xe1, 0xdf, 0xdf, 0xdf, 0xde, + 0xdf, 0xdf, 0xde, 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdc, + 0xdc, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xdd, 0xde, 0xde, + 0xdd, 0xde, 0xdf, 0xe0, 0xe0, 0xe0, 0xde, 0xdd, 0xdd, 0xdc, 0xda, 0xd9, + 0xd7, 0xd5, 0xd5, 0xd5, 0xd3, 0xd3, 0xd3, 0xd3, 0xd2, 0xd0, 0xcb, 0xc5, + 0xc2, 0xc1, 0xc5, 0xcb, 0xcd, 0xca, 0xc8, 0xc5, 0xc4, 0xc7, 0xc8, 0xc8, + 0xc7, 0xc8, 0xc7, 0xc7, 0xc6, 0xc5, 0xc2, 0xc0, 0xc0, 0xbf, 0xbb, 0xb4, + 0xaf, 0xab, 0xa7, 0x9e, 0x8d, 0x85, 0x8a, 0x8f, 0x96, 0x9b, 0x9f, 0xa0, + 0xa0, 0xa0, 0xa0, 0x9d, 0x97, 0x93, 0x90, 0x87, 0x79, 0x6b, 0x66, 0x68, + 0x83, 0x9f, 0xab, 0xae, 0xaa, 0x91, 0x6d, 0x67, 0x69, 0x6d, 0x70, 0x7a, + 0x84, 0x90, 0xa3, 0xa8, 0x93, 0xa1, 0xa9, 0xa1, 0x87, 0x69, 0x67, 0x7a, + 0x84, 0x8a, 0x91, 0x7f, 0x66, 0x56, 0x44, 0x3b, 0x4b, 0x64, 0x70, 0x76, + 0x70, 0x66, 0x63, 0x64, 0x6b, 0x88, 0x9a, 0x97, 0x8f, 0x7e, 0x66, 0x59, + 0x5a, 0x5b, 0x5b, 0x5c, 0x60, 0x63, 0x65, 0x67, 0x68, 0x6b, 0x6d, 0x6d, + 0x6e, 0x70, 0x74, 0x75, 0x75, 0x75, 0x76, 0x76, 0x76, 0x78, 0x7a, 0x7d, + 0x81, 0x84, 0x84, 0x84, 0x82, 0x81, 0x80, 0x7f, 0x7f, 0x7f, 0x7d, 0x74, + 0x6d, 0x69, 0x64, 0x5e, 0x5e, 0x5e, 0x5e, 0x60, 0x62, 0x66, 0x68, 0x69, + 0x6a, 0x69, 0x68, 0x66, 0x66, 0x65, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x72, + 0x75, 0x75, 0x74, 0x72, 0x73, 0x75, 0x78, 0x79, 0x7a, 0x79, 0x76, 0x77, + 0x78, 0x7d, 0x83, 0x88, 0x89, 0x8a, 0x8c, 0x8d, 0x8f, 0x90, 0x91, 0x91, + 0x91, 0x93, 0x93, 0x93, 0x92, 0x90, 0x8e, 0x8c, 0x8b, 0x89, 0x86, 0x84, + 0x83, 0x82, 0x80, 0x7e, 0x7d, 0x7a, 0x79, 0x78, 0x76, 0x75, 0x72, 0x71, + 0x70, 0x6f, 0x6b, 0x68, 0x68, 0x68, 0x67, 0x64, 0x63, 0x62, 0x61, 0x61, + 0x60, 0x60, 0x61, 0x61, 0x61, 0x5f, 0x5d, 0x5e, 0x5e, 0x60, 0x61, 0x61, + 0x61, 0x61, 0x5e, 0x6b, 0xb6, 0xd4, 0xd9, 0xd8, 0xd8, 0xd9, 0xda, 0xda, + 0xda, 0xdb, 0xdb, 0xdb, 0xda, 0xda, 0xdb, 0xdd, 0xdd, 0xdd, 0xde, 0xdf, + 0xde, 0xdf, 0xe0, 0xdf, 0xdf, 0xdf, 0xde, 0xdf, 0xe1, 0xe2, 0xe2, 0xe2, + 0xe2, 0xe2, 0xe2, 0xe1, 0xdf, 0xe0, 0xe0, 0xe0, 0xdf, 0xdf, 0xde, 0xdd, + 0xdd, 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdd, 0xdd, 0xdd, 0xde, 0xde, + 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xde, 0xde, 0xdd, 0xdd, 0xdd, 0xde, 0xde, + 0xde, 0xde, 0xdd, 0xdc, 0xdc, 0xdc, 0xdc, 0xdb, 0xd9, 0xd8, 0xd7, 0xd5, + 0xd3, 0xd2, 0xd3, 0xd3, 0xd2, 0xd1, 0xce, 0xca, 0xc6, 0xc0, 0xc0, 0xc5, + 0xca, 0xcc, 0xcb, 0xc6, 0xc2, 0xc4, 0xc5, 0xc6, 0xc5, 0xc5, 0xc5, 0xc6, + 0xc6, 0xc5, 0xc1, 0xc0, 0xbf, 0xbe, 0xbc, 0xb6, 0xb0, 0xad, 0xaa, 0xa2, + 0x92, 0x84, 0x83, 0x87, 0x91, 0x99, 0x9d, 0x9e, 0x9e, 0x9f, 0x9f, 0x9e, + 0x99, 0x96, 0x92, 0x8b, 0x7f, 0x72, 0x6b, 0x67, 0x7b, 0x99, 0xa7, 0xac, + 0xa9, 0x92, 0x6e, 0x64, 0x66, 0x6d, 0x6f, 0x79, 0x86, 0x90, 0xa0, 0xaa, + 0x98, 0x95, 0x9c, 0xa3, 0x8d, 0x6d, 0x66, 0x73, 0x7a, 0x82, 0x8c, 0x7f, + 0x69, 0x5b, 0x4b, 0x41, 0x53, 0x6e, 0x7b, 0x7f, 0x74, 0x66, 0x62, 0x63, + 0x6c, 0x8b, 0x99, 0x91, 0x88, 0x77, 0x61, 0x58, 0x5b, 0x5c, 0x5b, 0x5d, + 0x60, 0x63, 0x64, 0x67, 0x68, 0x6a, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x73, + 0x74, 0x74, 0x74, 0x74, 0x74, 0x75, 0x78, 0x7a, 0x7d, 0x7e, 0x7d, 0x7a, + 0x79, 0x7a, 0x79, 0x78, 0x78, 0x76, 0x72, 0x6b, 0x66, 0x63, 0x5f, 0x5d, + 0x5d, 0x5e, 0x5e, 0x60, 0x62, 0x66, 0x68, 0x6a, 0x6a, 0x6a, 0x69, 0x67, + 0x67, 0x66, 0x67, 0x69, 0x6c, 0x6d, 0x6f, 0x72, 0x75, 0x74, 0x73, 0x71, + 0x71, 0x72, 0x74, 0x75, 0x76, 0x76, 0x76, 0x79, 0x7c, 0x81, 0x86, 0x8b, + 0x8d, 0x8d, 0x8e, 0x90, 0x92, 0x92, 0x92, 0x92, 0x91, 0x93, 0x93, 0x93, + 0x92, 0x90, 0x8d, 0x8b, 0x8a, 0x87, 0x84, 0x80, 0x80, 0x7f, 0x7d, 0x7e, + 0x7b, 0x79, 0x78, 0x78, 0x76, 0x74, 0x71, 0x6f, 0x6e, 0x6d, 0x69, 0x67, + 0x66, 0x66, 0x65, 0x62, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x61, 0x62, + 0x61, 0x5f, 0x5e, 0x60, 0x60, 0x60, 0x61, 0x62, 0x63, 0x62, 0x60, 0x75, + 0xc1, 0xd6, 0xd8, 0xd7, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xdb, 0xdb, 0xdb, + 0xdb, 0xdb, 0xdb, 0xdc, 0xdc, 0xdc, 0xde, 0xdf, 0xde, 0xdf, 0xdf, 0xdf, + 0xdf, 0xdf, 0xde, 0xdf, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, + 0xdf, 0xe0, 0xe0, 0xe0, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, + 0xe0, 0xe0, 0xdf, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xde, 0xdd, 0xde, + 0xde, 0xdd, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdb, 0xdb, + 0xdc, 0xdc, 0xdd, 0xdd, 0xda, 0xda, 0xd9, 0xd7, 0xd6, 0xd3, 0xd3, 0xd2, + 0xd2, 0xd2, 0xd1, 0xce, 0xcb, 0xc5, 0xc0, 0xbf, 0xc5, 0xc9, 0xcb, 0xc9, + 0xc4, 0xc0, 0xc1, 0xc3, 0xc4, 0xc4, 0xc4, 0xc5, 0xc4, 0xc4, 0xc2, 0xbe, + 0xbe, 0xbe, 0xbc, 0xb8, 0xb2, 0xaf, 0xad, 0xa6, 0x9a, 0x89, 0x7f, 0x80, + 0x8a, 0x96, 0x99, 0x9b, 0x9c, 0x9d, 0x9e, 0x9e, 0x9b, 0x98, 0x95, 0x90, + 0x86, 0x7a, 0x71, 0x67, 0x70, 0x90, 0xa4, 0xab, 0xa9, 0x94, 0x6e, 0x62, + 0x63, 0x6d, 0x70, 0x77, 0x87, 0x91, 0x9d, 0xaa, 0x9d, 0x8f, 0x92, 0xa3, + 0x92, 0x72, 0x69, 0x6b, 0x6f, 0x77, 0x81, 0x78, 0x6a, 0x63, 0x5b, 0x56, + 0x62, 0x75, 0x7e, 0x80, 0x70, 0x62, 0x62, 0x65, 0x6f, 0x89, 0x94, 0x8b, + 0x81, 0x70, 0x5a, 0x57, 0x5c, 0x5d, 0x5b, 0x5e, 0x61, 0x64, 0x65, 0x67, + 0x69, 0x6a, 0x6d, 0x6e, 0x6f, 0x6f, 0x70, 0x71, 0x71, 0x71, 0x72, 0x71, + 0x72, 0x72, 0x73, 0x73, 0x73, 0x73, 0x72, 0x71, 0x72, 0x73, 0x73, 0x73, + 0x71, 0x6d, 0x69, 0x63, 0x60, 0x5e, 0x5c, 0x5d, 0x5d, 0x5e, 0x5f, 0x5f, + 0x62, 0x66, 0x69, 0x6a, 0x6c, 0x6c, 0x6a, 0x69, 0x68, 0x67, 0x68, 0x6a, + 0x6d, 0x6e, 0x71, 0x74, 0x76, 0x74, 0x73, 0x71, 0x70, 0x70, 0x70, 0x70, + 0x71, 0x73, 0x76, 0x7a, 0x7d, 0x83, 0x8a, 0x8f, 0x90, 0x91, 0x91, 0x93, + 0x95, 0x94, 0x94, 0x93, 0x91, 0x93, 0x92, 0x92, 0x91, 0x8f, 0x8b, 0x89, + 0x88, 0x85, 0x81, 0x7e, 0x7c, 0x7c, 0x7b, 0x7a, 0x79, 0x78, 0x78, 0x77, + 0x75, 0x73, 0x72, 0x6f, 0x6d, 0x6c, 0x68, 0x66, 0x65, 0x64, 0x63, 0x60, + 0x5f, 0x5f, 0x60, 0x61, 0x61, 0x60, 0x61, 0x62, 0x63, 0x61, 0x5f, 0x60, + 0x60, 0x60, 0x62, 0x64, 0x63, 0x62, 0x65, 0x88, 0xc8, 0xd7, 0xd6, 0xd6, + 0xd7, 0xd8, 0xd8, 0xd8, 0xd9, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, + 0xdb, 0xdb, 0xdc, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, + 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xdf, + 0xde, 0xde, 0xe0, 0xe0, 0xdf, 0xdf, 0xde, 0xdf, 0xe0, 0xdf, 0xde, 0xdf, + 0xde, 0xde, 0xdf, 0xdf, 0xde, 0xdd, 0xdc, 0xdd, 0xdd, 0xdd, 0xdc, 0xdc, + 0xdc, 0xdb, 0xdb, 0xdb, 0xdb, 0xdc, 0xdc, 0xdb, 0xdc, 0xdc, 0xdc, 0xdb, + 0xdb, 0xdb, 0xdb, 0xd9, 0xd8, 0xd6, 0xd3, 0xd2, 0xd1, 0xd1, 0xd1, 0xd1, + 0xcf, 0xcc, 0xc5, 0xbd, 0xbe, 0xc3, 0xc6, 0xc8, 0xc7, 0xc2, 0xbe, 0xbf, + 0xc2, 0xc4, 0xc3, 0xc3, 0xc3, 0xc3, 0xc2, 0xbe, 0xbd, 0xbc, 0xba, 0xb7, + 0xb3, 0xb0, 0xae, 0xa9, 0x9f, 0x8f, 0x82, 0x7f, 0x82, 0x8e, 0x95, 0x97, + 0x99, 0x9b, 0x9d, 0x9d, 0x9b, 0x98, 0x96, 0x93, 0x8a, 0x7c, 0x72, 0x67, + 0x6a, 0x88, 0x9f, 0xa8, 0xa8, 0x96, 0x70, 0x61, 0x61, 0x6b, 0x72, 0x76, + 0x85, 0x8f, 0x9a, 0xa8, 0xa3, 0x8e, 0x8f, 0xa2, 0x97, 0x77, 0x6b, 0x67, + 0x68, 0x6e, 0x77, 0x6f, 0x67, 0x64, 0x62, 0x62, 0x6d, 0x79, 0x7f, 0x81, + 0x6e, 0x5f, 0x62, 0x68, 0x71, 0x7e, 0x86, 0x83, 0x7c, 0x69, 0x58, 0x58, + 0x5d, 0x5e, 0x5c, 0x5f, 0x63, 0x64, 0x66, 0x68, 0x6a, 0x6b, 0x6c, 0x6c, + 0x6e, 0x6e, 0x6e, 0x6f, 0x70, 0x6f, 0x70, 0x70, 0x6f, 0x70, 0x70, 0x6f, + 0x6d, 0x6c, 0x6d, 0x6e, 0x70, 0x6f, 0x70, 0x6f, 0x6d, 0x67, 0x62, 0x5e, + 0x5d, 0x5c, 0x5c, 0x5c, 0x5d, 0x5f, 0x60, 0x60, 0x63, 0x67, 0x6a, 0x6b, + 0x6c, 0x6d, 0x6b, 0x6a, 0x69, 0x68, 0x69, 0x6b, 0x6d, 0x6e, 0x72, 0x76, + 0x75, 0x72, 0x71, 0x70, 0x6f, 0x6f, 0x6e, 0x6e, 0x6f, 0x71, 0x75, 0x79, + 0x7d, 0x83, 0x8a, 0x8f, 0x91, 0x92, 0x92, 0x95, 0x96, 0x96, 0x95, 0x95, + 0x93, 0x91, 0x91, 0x8f, 0x8e, 0x8c, 0x88, 0x85, 0x83, 0x81, 0x7f, 0x7e, + 0x7b, 0x79, 0x78, 0x77, 0x79, 0x79, 0x78, 0x77, 0x75, 0x73, 0x71, 0x6e, + 0x6c, 0x69, 0x66, 0x65, 0x63, 0x62, 0x60, 0x5e, 0x5f, 0x5f, 0x60, 0x61, + 0x61, 0x60, 0x61, 0x62, 0x63, 0x61, 0x60, 0x60, 0x60, 0x61, 0x63, 0x65, + 0x64, 0x62, 0x67, 0x9a, 0xce, 0xd6, 0xd5, 0xd5, 0xd6, 0xd7, 0xd8, 0xd8, + 0xd9, 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdc, 0xdb, 0xdb, 0xdd, 0xde, + 0xde, 0xdf, 0xdf, 0xdf, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, + 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xdf, 0xdf, 0xdf, 0xdf, + 0xde, 0xdd, 0xde, 0xdf, 0xdf, 0xde, 0xdd, 0xde, 0xdd, 0xdd, 0xde, 0xdd, + 0xde, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, 0xdc, 0xdc, 0xdb, 0xdc, + 0xdc, 0xdc, 0xdb, 0xdb, 0xdb, 0xdb, 0xda, 0xd9, 0xdb, 0xdc, 0xdc, 0xdb, + 0xd9, 0xd7, 0xd6, 0xd5, 0xd3, 0xd1, 0xd0, 0xd0, 0xd0, 0xcf, 0xcb, 0xc1, + 0xbb, 0xbd, 0xc0, 0xc4, 0xc8, 0xc5, 0xc0, 0xbe, 0xc0, 0xc2, 0xc2, 0xc2, + 0xc2, 0xc2, 0xc2, 0xc0, 0xbd, 0xbb, 0xb8, 0xb7, 0xb5, 0xb1, 0xaf, 0xab, + 0xa3, 0x95, 0x8a, 0x82, 0x7d, 0x87, 0x8f, 0x93, 0x95, 0x99, 0x9c, 0x9e, + 0x9c, 0x9a, 0x96, 0x94, 0x8d, 0x7e, 0x74, 0x67, 0x68, 0x82, 0x9b, 0xa5, + 0xa7, 0x97, 0x71, 0x60, 0x5f, 0x68, 0x72, 0x75, 0x81, 0x8b, 0x9a, 0xa6, + 0xa6, 0x90, 0x8e, 0x9e, 0x99, 0x79, 0x6a, 0x66, 0x66, 0x6a, 0x76, 0x6f, + 0x63, 0x5f, 0x60, 0x66, 0x72, 0x78, 0x7c, 0x81, 0x70, 0x5e, 0x62, 0x69, + 0x71, 0x72, 0x77, 0x7b, 0x77, 0x66, 0x57, 0x59, 0x5c, 0x5c, 0x5c, 0x60, + 0x64, 0x66, 0x67, 0x68, 0x6a, 0x6b, 0x6b, 0x6c, 0x6d, 0x6e, 0x6d, 0x6e, + 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6d, 0x6d, 0x6b, 0x6a, 0x6b, 0x6c, + 0x6e, 0x6f, 0x6e, 0x6c, 0x69, 0x63, 0x5f, 0x5d, 0x5c, 0x5b, 0x5c, 0x5b, + 0x5c, 0x5e, 0x5f, 0x61, 0x65, 0x69, 0x6b, 0x6c, 0x6e, 0x6e, 0x6b, 0x6b, + 0x6a, 0x69, 0x69, 0x6c, 0x6d, 0x6f, 0x72, 0x76, 0x74, 0x71, 0x6f, 0x6f, + 0x6e, 0x6d, 0x6c, 0x6d, 0x6e, 0x6f, 0x72, 0x76, 0x7a, 0x80, 0x87, 0x8b, + 0x8f, 0x91, 0x92, 0x94, 0x96, 0x95, 0x95, 0x94, 0x92, 0x91, 0x8f, 0x8e, + 0x8c, 0x8a, 0x85, 0x82, 0x80, 0x7d, 0x7d, 0x7c, 0x79, 0x77, 0x76, 0x75, + 0x7a, 0x79, 0x77, 0x76, 0x74, 0x73, 0x71, 0x6d, 0x6c, 0x68, 0x65, 0x63, + 0x62, 0x60, 0x5f, 0x5e, 0x5f, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x63, + 0x63, 0x62, 0x61, 0x61, 0x61, 0x61, 0x64, 0x65, 0x64, 0x61, 0x69, 0xa5, + 0xd0, 0xd5, 0xd4, 0xd4, 0xd5, 0xd7, 0xd8, 0xd8, 0xd9, 0xda, 0xd9, 0xda, + 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdd, 0xde, 0xde, 0xdf, 0xdf, 0xdf, + 0xde, 0xdf, 0xdf, 0xdf, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, + 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xde, 0xde, 0xdc, 0xdd, 0xdf, + 0xde, 0xdd, 0xdd, 0xdd, 0xdc, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, 0xdd, + 0xdd, 0xdd, 0xdc, 0xdc, 0xdc, 0xdc, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, + 0xdb, 0xdb, 0xda, 0xd9, 0xdb, 0xdc, 0xdc, 0xda, 0xd9, 0xd8, 0xd8, 0xd7, + 0xd5, 0xd1, 0xcf, 0xcf, 0xcf, 0xd0, 0xce, 0xc5, 0xbc, 0xba, 0xbb, 0xc1, + 0xc7, 0xc6, 0xc1, 0xbf, 0xbe, 0xc1, 0xc2, 0xc1, 0xc1, 0xc1, 0xc1, 0xc0, + 0xbe, 0xbb, 0xb8, 0xb6, 0xb5, 0xb2, 0xb0, 0xad, 0xa4, 0x98, 0x8f, 0x86, + 0x7c, 0x83, 0x8c, 0x90, 0x93, 0x97, 0x9b, 0x9d, 0x9c, 0x9a, 0x97, 0x95, + 0x8d, 0x7f, 0x74, 0x68, 0x67, 0x7c, 0x96, 0xa2, 0xa6, 0x98, 0x72, 0x60, + 0x5f, 0x66, 0x71, 0x76, 0x7e, 0x88, 0x99, 0xa7, 0xa7, 0x92, 0x8f, 0x9c, + 0x9a, 0x7b, 0x68, 0x64, 0x63, 0x67, 0x78, 0x72, 0x62, 0x5c, 0x5e, 0x68, + 0x74, 0x76, 0x7a, 0x80, 0x71, 0x5e, 0x61, 0x68, 0x71, 0x6b, 0x6b, 0x71, + 0x6f, 0x62, 0x57, 0x5a, 0x5b, 0x5c, 0x5d, 0x61, 0x65, 0x66, 0x67, 0x68, + 0x6a, 0x6b, 0x6b, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6c, + 0x6d, 0x6d, 0x6c, 0x6c, 0x6a, 0x6a, 0x6a, 0x6c, 0x6e, 0x6d, 0x6b, 0x6a, + 0x67, 0x61, 0x5e, 0x5d, 0x5b, 0x5b, 0x5b, 0x5b, 0x5c, 0x5e, 0x5f, 0x62, + 0x66, 0x6a, 0x6c, 0x6d, 0x6e, 0x6e, 0x6c, 0x6c, 0x6b, 0x69, 0x6a, 0x6c, + 0x6d, 0x6f, 0x72, 0x76, 0x74, 0x70, 0x6f, 0x6e, 0x6c, 0x6c, 0x6c, 0x6c, + 0x6d, 0x6e, 0x70, 0x73, 0x76, 0x7c, 0x84, 0x89, 0x8d, 0x8f, 0x91, 0x93, + 0x94, 0x93, 0x93, 0x93, 0x90, 0x8f, 0x8d, 0x8b, 0x89, 0x88, 0x82, 0x7f, + 0x7d, 0x7a, 0x7b, 0x7a, 0x77, 0x76, 0x75, 0x73, 0x7a, 0x79, 0x76, 0x74, + 0x73, 0x72, 0x6f, 0x6b, 0x69, 0x68, 0x63, 0x61, 0x5e, 0x5d, 0x5d, 0x5e, + 0x5f, 0x60, 0x60, 0x5f, 0x5f, 0x61, 0x63, 0x63, 0x64, 0x63, 0x62, 0x62, + 0x62, 0x62, 0x64, 0x64, 0x63, 0x62, 0x6d, 0xb3, 0xd3, 0xd4, 0xd3, 0xd4, + 0xd6, 0xd8, 0xd8, 0xd8, 0xd9, 0xdb, 0xda, 0xd9, 0xd8, 0xd8, 0xd8, 0xda, + 0xda, 0xda, 0xdc, 0xdd, 0xdd, 0xde, 0xdf, 0xdf, 0xdd, 0xde, 0xde, 0xde, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, + 0xdd, 0xde, 0xdd, 0xdc, 0xdc, 0xdc, 0xdc, 0xdd, 0xdd, 0xdc, 0xdc, 0xdb, + 0xdc, 0xdc, 0xdb, 0xdb, 0xdb, 0xdb, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, + 0xdb, 0xdb, 0xdb, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, + 0xda, 0xda, 0xda, 0xd9, 0xd9, 0xd8, 0xd8, 0xd8, 0xd7, 0xd4, 0xd1, 0xce, + 0xcd, 0xce, 0xce, 0xca, 0xc0, 0xba, 0xb8, 0xbb, 0xc3, 0xc7, 0xc6, 0xc3, + 0xbe, 0xbd, 0xc0, 0xc0, 0xc0, 0xbf, 0xc0, 0xc0, 0xbf, 0xbd, 0xb9, 0xb6, + 0xb6, 0xb3, 0xb1, 0xae, 0xa6, 0x9c, 0x94, 0x8b, 0x7f, 0x7d, 0x87, 0x8d, + 0x90, 0x95, 0x9a, 0x9c, 0x9b, 0x99, 0x98, 0x97, 0x8f, 0x80, 0x76, 0x6a, + 0x66, 0x74, 0x8f, 0x9e, 0xa5, 0x99, 0x73, 0x60, 0x5d, 0x64, 0x71, 0x77, + 0x7a, 0x82, 0x96, 0xa7, 0xaa, 0x98, 0x91, 0x98, 0x9c, 0x7c, 0x61, 0x5c, + 0x5c, 0x60, 0x79, 0x77, 0x61, 0x59, 0x5e, 0x6f, 0x77, 0x73, 0x73, 0x7b, + 0x75, 0x61, 0x5d, 0x63, 0x6c, 0x65, 0x5a, 0x5d, 0x5e, 0x59, 0x55, 0x59, + 0x5a, 0x5b, 0x5e, 0x62, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6b, + 0x6b, 0x6c, 0x6c, 0x6c, 0x6c, 0x6b, 0x6c, 0x6b, 0x6c, 0x6c, 0x6b, 0x69, + 0x69, 0x69, 0x6a, 0x6c, 0x6d, 0x6c, 0x68, 0x65, 0x62, 0x5f, 0x5d, 0x5c, + 0x5b, 0x5a, 0x5a, 0x5b, 0x5d, 0x5e, 0x60, 0x62, 0x67, 0x6b, 0x6e, 0x6f, + 0x6f, 0x6f, 0x6e, 0x6b, 0x6a, 0x69, 0x69, 0x6b, 0x6d, 0x70, 0x73, 0x76, + 0x74, 0x71, 0x6f, 0x6c, 0x6c, 0x6c, 0x6b, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, + 0x70, 0x74, 0x7c, 0x82, 0x86, 0x89, 0x8c, 0x8f, 0x90, 0x8f, 0x8f, 0x8e, + 0x8c, 0x8a, 0x87, 0x85, 0x83, 0x81, 0x7c, 0x7a, 0x78, 0x77, 0x76, 0x75, + 0x74, 0x73, 0x73, 0x71, 0x7a, 0x77, 0x75, 0x74, 0x71, 0x70, 0x6c, 0x68, + 0x66, 0x64, 0x60, 0x5e, 0x5c, 0x5c, 0x5b, 0x5c, 0x5e, 0x5f, 0x5e, 0x5e, + 0x5f, 0x61, 0x62, 0x63, 0x63, 0x63, 0x63, 0x64, 0x65, 0x65, 0x64, 0x64, + 0x62, 0x62, 0x74, 0xbe, 0xd3, 0xd1, 0xd1, 0xd4, 0xd6, 0xd7, 0xd7, 0xd7, + 0xd8, 0xd9, 0xda, 0xd9, 0xd8, 0xd8, 0xd8, 0xda, 0xda, 0xda, 0xdc, 0xdd, + 0xdc, 0xde, 0xde, 0xdf, 0xde, 0xde, 0xde, 0xde, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xdd, 0xdd, 0xdd, 0xdc, 0xdb, + 0xdb, 0xdc, 0xdc, 0xdc, 0xdb, 0xdb, 0xda, 0xda, 0xdb, 0xda, 0xd9, 0xd9, + 0xd9, 0xd9, 0xd9, 0xd9, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, + 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xd8, 0xd7, 0xd7, 0xd8, + 0xd8, 0xd8, 0xd8, 0xd8, 0xd7, 0xd6, 0xd4, 0xd1, 0xcf, 0xcd, 0xcd, 0xcd, + 0xc8, 0xc2, 0xbd, 0xb8, 0xba, 0xc3, 0xc7, 0xc7, 0xc1, 0xba, 0xba, 0xbd, + 0xbe, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbb, 0xb6, 0xb5, 0xb3, 0xb1, 0xaf, + 0xa9, 0xa0, 0x99, 0x92, 0x85, 0x79, 0x7f, 0x85, 0x8a, 0x90, 0x96, 0x99, + 0x9a, 0x99, 0x98, 0x97, 0x8f, 0x85, 0x7b, 0x6e, 0x68, 0x6d, 0x86, 0x97, + 0xa3, 0x9a, 0x76, 0x62, 0x5c, 0x60, 0x6f, 0x7c, 0x7a, 0x7e, 0x92, 0xa7, + 0xad, 0xa0, 0x97, 0x95, 0x9f, 0x83, 0x5d, 0x53, 0x52, 0x56, 0x70, 0x74, + 0x5e, 0x57, 0x60, 0x77, 0x82, 0x78, 0x75, 0x79, 0x79, 0x66, 0x58, 0x5a, + 0x65, 0x5f, 0x4c, 0x45, 0x47, 0x4d, 0x54, 0x59, 0x59, 0x5b, 0x5f, 0x63, + 0x65, 0x67, 0x67, 0x67, 0x68, 0x69, 0x69, 0x6a, 0x6a, 0x69, 0x69, 0x6a, + 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x68, 0x69, 0x6a, 0x6b, 0x6c, + 0x6c, 0x68, 0x64, 0x61, 0x5e, 0x5c, 0x5b, 0x5b, 0x5a, 0x5a, 0x5a, 0x5b, + 0x5e, 0x60, 0x62, 0x64, 0x68, 0x6c, 0x6f, 0x70, 0x70, 0x6f, 0x6e, 0x6b, + 0x6a, 0x69, 0x69, 0x6c, 0x6e, 0x70, 0x73, 0x75, 0x73, 0x70, 0x6e, 0x6c, + 0x6b, 0x6b, 0x6a, 0x6a, 0x6a, 0x69, 0x6a, 0x6a, 0x6a, 0x6b, 0x72, 0x77, + 0x7c, 0x7f, 0x83, 0x85, 0x86, 0x86, 0x86, 0x85, 0x83, 0x7f, 0x7e, 0x7d, + 0x7a, 0x79, 0x76, 0x74, 0x74, 0x73, 0x73, 0x71, 0x71, 0x71, 0x70, 0x6e, + 0x78, 0x76, 0x74, 0x72, 0x6f, 0x6d, 0x69, 0x65, 0x63, 0x61, 0x5d, 0x5b, + 0x59, 0x59, 0x59, 0x5a, 0x5c, 0x5c, 0x5d, 0x5d, 0x60, 0x60, 0x60, 0x61, + 0x61, 0x62, 0x63, 0x65, 0x66, 0x66, 0x65, 0x64, 0x62, 0x67, 0x82, 0xc5, + 0xd3, 0xd0, 0xd1, 0xd4, 0xd5, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd9, 0xd9, + 0xd9, 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xdc, 0xdc, 0xdc, 0xde, 0xde, 0xdd, + 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xde, + 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xdd, 0xdd, 0xdc, 0xdc, 0xdc, 0xdb, + 0xdb, 0xda, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd7, 0xd6, 0xd6, 0xd6, 0xd6, + 0xd5, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, + 0xd8, 0xd8, 0xd8, 0xd8, 0xd7, 0xd6, 0xd5, 0xd6, 0xd7, 0xd8, 0xd8, 0xd8, + 0xd7, 0xd6, 0xd6, 0xd5, 0xd4, 0xd1, 0xce, 0xcb, 0xcb, 0xca, 0xc7, 0xc0, + 0xb7, 0xb9, 0xc0, 0xc4, 0xc4, 0xbd, 0xb8, 0xb9, 0xba, 0xbb, 0xbb, 0xbb, + 0xbd, 0xbe, 0xbc, 0xb7, 0xb4, 0xb2, 0xb1, 0xaf, 0xaa, 0xa3, 0x9e, 0x98, + 0x8e, 0x7d, 0x77, 0x79, 0x7e, 0x88, 0x92, 0x97, 0x99, 0x99, 0x99, 0x97, + 0x90, 0x89, 0x80, 0x72, 0x6a, 0x69, 0x7e, 0x8f, 0xa0, 0x9b, 0x78, 0x63, + 0x5c, 0x5d, 0x6a, 0x7d, 0x7d, 0x7e, 0x8a, 0xa4, 0xb1, 0xa9, 0x9e, 0x92, + 0x9e, 0x87, 0x62, 0x53, 0x4d, 0x4c, 0x5f, 0x6d, 0x5f, 0x5a, 0x63, 0x7e, + 0x9b, 0x92, 0x8c, 0x8c, 0x82, 0x6e, 0x59, 0x54, 0x5d, 0x5c, 0x4a, 0x3f, + 0x3f, 0x49, 0x54, 0x58, 0x5a, 0x5c, 0x60, 0x64, 0x65, 0x66, 0x66, 0x66, + 0x67, 0x68, 0x68, 0x68, 0x69, 0x67, 0x68, 0x69, 0x69, 0x69, 0x6a, 0x69, + 0x6a, 0x6a, 0x69, 0x67, 0x68, 0x6b, 0x6c, 0x6d, 0x6a, 0x64, 0x61, 0x5f, + 0x5b, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5c, 0x5f, 0x61, 0x63, 0x66, + 0x69, 0x6d, 0x6f, 0x70, 0x72, 0x72, 0x6f, 0x6c, 0x6a, 0x69, 0x69, 0x6c, + 0x70, 0x72, 0x74, 0x75, 0x74, 0x71, 0x6f, 0x6c, 0x6a, 0x6b, 0x6b, 0x6b, + 0x6b, 0x69, 0x66, 0x65, 0x64, 0x65, 0x69, 0x6c, 0x6f, 0x71, 0x74, 0x76, + 0x78, 0x79, 0x79, 0x79, 0x77, 0x76, 0x76, 0x75, 0x74, 0x72, 0x71, 0x70, + 0x6f, 0x6f, 0x6e, 0x6d, 0x6d, 0x6d, 0x6c, 0x6a, 0x77, 0x75, 0x71, 0x70, + 0x6e, 0x6b, 0x68, 0x64, 0x62, 0x60, 0x5b, 0x58, 0x57, 0x57, 0x58, 0x59, + 0x5a, 0x5c, 0x5d, 0x5e, 0x61, 0x62, 0x61, 0x61, 0x61, 0x62, 0x66, 0x68, + 0x68, 0x66, 0x65, 0x64, 0x62, 0x6b, 0x8c, 0xc8, 0xd3, 0xd1, 0xd1, 0xd3, + 0xd4, 0xd7, 0xd8, 0xd8, 0xd7, 0xd8, 0xd8, 0xd9, 0xd9, 0xda, 0xd9, 0xd9, + 0xda, 0xda, 0xdb, 0xdc, 0xdc, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, 0xdd, + 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xde, 0xdd, 0xdd, 0xdd, 0xde, + 0xdf, 0xde, 0xdf, 0xdf, 0xdf, 0xdd, 0xde, 0xde, 0xdd, 0xdb, 0xdb, 0xda, + 0xda, 0xda, 0xd9, 0xd8, 0xd8, 0xd6, 0xd5, 0xd5, 0xd5, 0xd5, 0xd6, 0xd6, + 0xd5, 0xd5, 0xd5, 0xd6, 0xd6, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd6, + 0xd5, 0xd5, 0xd5, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd5, 0xd5, 0xd4, + 0xd4, 0xd4, 0xd1, 0xcd, 0xcb, 0xcb, 0xca, 0xc6, 0xbb, 0xb5, 0xb8, 0xbd, + 0xc3, 0xc3, 0xba, 0xb6, 0xb6, 0xb9, 0xb9, 0xb9, 0xbc, 0xbd, 0xbc, 0xb8, + 0xb4, 0xb2, 0xb0, 0xaf, 0xab, 0xa5, 0xa0, 0x9c, 0x93, 0x82, 0x74, 0x71, + 0x75, 0x81, 0x8d, 0x94, 0x98, 0x99, 0x98, 0x96, 0x91, 0x8b, 0x83, 0x75, + 0x6b, 0x68, 0x78, 0x88, 0x9c, 0x9a, 0x79, 0x65, 0x5d, 0x5b, 0x66, 0x7a, + 0x81, 0x82, 0x87, 0xa1, 0xb4, 0xaf, 0xa2, 0x91, 0x9c, 0x89, 0x68, 0x58, + 0x51, 0x4c, 0x5a, 0x6c, 0x65, 0x61, 0x67, 0x81, 0xa5, 0x9b, 0x95, 0x97, + 0x8c, 0x75, 0x5d, 0x55, 0x58, 0x59, 0x4f, 0x46, 0x46, 0x4e, 0x56, 0x58, + 0x5b, 0x5d, 0x61, 0x63, 0x64, 0x65, 0x65, 0x66, 0x67, 0x67, 0x67, 0x66, + 0x66, 0x68, 0x68, 0x69, 0x69, 0x69, 0x6a, 0x69, 0x6a, 0x6a, 0x69, 0x68, + 0x68, 0x6a, 0x6b, 0x6c, 0x68, 0x62, 0x5f, 0x5d, 0x5b, 0x5a, 0x5a, 0x5a, + 0x5a, 0x5b, 0x5c, 0x5e, 0x60, 0x62, 0x64, 0x67, 0x6b, 0x6f, 0x72, 0x73, + 0x74, 0x74, 0x6f, 0x6c, 0x6a, 0x69, 0x6a, 0x6e, 0x71, 0x73, 0x74, 0x74, + 0x74, 0x72, 0x6f, 0x6d, 0x6b, 0x6a, 0x6a, 0x6a, 0x6a, 0x68, 0x64, 0x61, + 0x60, 0x60, 0x62, 0x65, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x71, 0x71, 0x71, + 0x70, 0x70, 0x70, 0x70, 0x6f, 0x6f, 0x6d, 0x6d, 0x6c, 0x6b, 0x6b, 0x6b, + 0x6a, 0x6a, 0x69, 0x67, 0x76, 0x74, 0x71, 0x6f, 0x6d, 0x6a, 0x66, 0x62, + 0x60, 0x5e, 0x5a, 0x56, 0x56, 0x56, 0x57, 0x58, 0x59, 0x5b, 0x5c, 0x5d, + 0x61, 0x62, 0x61, 0x61, 0x62, 0x63, 0x67, 0x69, 0x69, 0x67, 0x67, 0x64, + 0x62, 0x6d, 0x94, 0xca, 0xd4, 0xd2, 0xd1, 0xd2, 0xd4, 0xd6, 0xd8, 0xd8, + 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda, 0xdb, 0xdc, + 0xdc, 0xdd, 0xdd, 0xdd, 0xdc, 0xdc, 0xdc, 0xdc, 0xde, 0xde, 0xdf, 0xdf, + 0xde, 0xde, 0xde, 0xde, 0xdd, 0xdd, 0xdd, 0xde, 0xdf, 0xdf, 0xe1, 0xe1, + 0xe1, 0xdf, 0xdf, 0xe0, 0xdf, 0xdd, 0xdd, 0xdc, 0xdc, 0xdc, 0xda, 0xd9, + 0xd9, 0xd8, 0xd7, 0xd7, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd5, 0xd5, + 0xd5, 0xd6, 0xd5, 0xd4, 0xd4, 0xd4, 0xd4, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, + 0xd6, 0xd6, 0xd5, 0xd5, 0xd5, 0xd4, 0xd5, 0xd4, 0xd5, 0xd5, 0xd3, 0xd0, + 0xcc, 0xcb, 0xca, 0xc8, 0xc0, 0xb7, 0xb5, 0xb9, 0xc0, 0xc4, 0xbd, 0xb6, + 0xb5, 0xb8, 0xb9, 0xb8, 0xbb, 0xbc, 0xbb, 0xb8, 0xb4, 0xb2, 0xb0, 0xaf, + 0xac, 0xa7, 0xa2, 0x9e, 0x96, 0x87, 0x76, 0x71, 0x73, 0x7d, 0x8a, 0x92, + 0x96, 0x98, 0x97, 0x96, 0x91, 0x8b, 0x85, 0x79, 0x6c, 0x68, 0x74, 0x83, + 0x9a, 0x9a, 0x7b, 0x65, 0x5d, 0x5b, 0x63, 0x76, 0x82, 0x85, 0x88, 0x9f, + 0xb3, 0xb1, 0xa3, 0x8f, 0x99, 0x8a, 0x6d, 0x5d, 0x55, 0x4f, 0x5b, 0x6e, + 0x6b, 0x67, 0x6a, 0x80, 0xa3, 0x97, 0x8f, 0x92, 0x8f, 0x79, 0x60, 0x57, + 0x55, 0x57, 0x51, 0x4b, 0x4c, 0x51, 0x58, 0x58, 0x5c, 0x5e, 0x60, 0x62, + 0x63, 0x63, 0x64, 0x65, 0x66, 0x67, 0x66, 0x65, 0x65, 0x68, 0x68, 0x69, + 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6a, 0x69, 0x68, 0x68, 0x69, 0x6a, 0x6b, + 0x66, 0x60, 0x5d, 0x5b, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5d, 0x60, + 0x61, 0x63, 0x64, 0x68, 0x6d, 0x72, 0x74, 0x75, 0x76, 0x73, 0x6e, 0x6b, + 0x6a, 0x69, 0x6a, 0x6e, 0x72, 0x73, 0x74, 0x74, 0x74, 0x72, 0x6f, 0x6d, + 0x6b, 0x6a, 0x6a, 0x6a, 0x69, 0x67, 0x62, 0x5f, 0x5f, 0x5d, 0x5e, 0x61, + 0x64, 0x66, 0x68, 0x69, 0x6b, 0x6c, 0x6d, 0x6d, 0x6d, 0x6c, 0x6d, 0x6d, + 0x6d, 0x6c, 0x6a, 0x6a, 0x69, 0x69, 0x69, 0x69, 0x68, 0x68, 0x67, 0x65, + 0x75, 0x73, 0x71, 0x6f, 0x6c, 0x68, 0x64, 0x60, 0x5e, 0x5b, 0x57, 0x53, + 0x53, 0x53, 0x54, 0x58, 0x58, 0x5a, 0x5b, 0x5d, 0x60, 0x62, 0x62, 0x62, + 0x63, 0x65, 0x68, 0x6a, 0x6b, 0x69, 0x68, 0x63, 0x60, 0x6f, 0x9f, 0xcc, + 0xd2, 0xd1, 0xd1, 0xd1, 0xd3, 0xd4, 0xd7, 0xd8, 0xd8, 0xd8, 0xd8, 0xd7, + 0xd8, 0xd8, 0xd9, 0xd9, 0xda, 0xdb, 0xdb, 0xdc, 0xdc, 0xdd, 0xde, 0xdd, + 0xdc, 0xdc, 0xdc, 0xdc, 0xde, 0xdf, 0xdf, 0xdf, 0xde, 0xde, 0xde, 0xde, + 0xdd, 0xdd, 0xdd, 0xdd, 0xe0, 0xe1, 0xe2, 0xe2, 0xe2, 0xe0, 0xe0, 0xe1, + 0xe1, 0xe1, 0xe0, 0xdf, 0xdf, 0xdf, 0xde, 0xdc, 0xdc, 0xdb, 0xdb, 0xdb, + 0xd9, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd7, 0xd7, 0xd7, 0xd8, 0xd6, 0xd5, + 0xd5, 0xd5, 0xd5, 0xd6, 0xd4, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd4, 0xd4, + 0xd5, 0xd5, 0xd5, 0xd5, 0xd4, 0xd4, 0xd4, 0xd3, 0xce, 0xcc, 0xcb, 0xc9, + 0xc6, 0xbd, 0xb7, 0xb6, 0xba, 0xc2, 0xc1, 0xba, 0xb7, 0xb6, 0xb8, 0xba, + 0xbb, 0xbc, 0xbc, 0xb9, 0xb6, 0xb3, 0xb1, 0xb0, 0xac, 0xa8, 0xa4, 0xa1, + 0x9a, 0x8d, 0x7d, 0x76, 0x74, 0x78, 0x86, 0x8f, 0x95, 0x96, 0x97, 0x95, + 0x91, 0x8c, 0x87, 0x7e, 0x71, 0x69, 0x6e, 0x7b, 0x95, 0x9a, 0x7b, 0x66, + 0x5d, 0x5a, 0x5f, 0x70, 0x82, 0x89, 0x8d, 0x9d, 0xaf, 0xad, 0xa0, 0x8a, + 0x96, 0x8b, 0x75, 0x66, 0x5d, 0x56, 0x5d, 0x71, 0x73, 0x70, 0x6e, 0x7d, + 0x96, 0x86, 0x7c, 0x7f, 0x8b, 0x79, 0x65, 0x5b, 0x53, 0x53, 0x51, 0x4f, + 0x51, 0x56, 0x59, 0x58, 0x5c, 0x5e, 0x5f, 0x61, 0x62, 0x61, 0x62, 0x64, + 0x64, 0x65, 0x65, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6a, 0x6a, + 0x6a, 0x6a, 0x69, 0x67, 0x67, 0x68, 0x68, 0x68, 0x63, 0x5e, 0x5b, 0x5a, + 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5b, 0x5e, 0x60, 0x61, 0x63, 0x65, 0x69, + 0x70, 0x76, 0x79, 0x79, 0x78, 0x73, 0x6d, 0x6a, 0x68, 0x68, 0x6a, 0x6e, + 0x71, 0x73, 0x73, 0x74, 0x74, 0x71, 0x6f, 0x6d, 0x6b, 0x69, 0x68, 0x68, + 0x67, 0x64, 0x5f, 0x5c, 0x5b, 0x5a, 0x59, 0x5b, 0x5e, 0x60, 0x61, 0x62, + 0x63, 0x65, 0x66, 0x67, 0x67, 0x67, 0x68, 0x68, 0x68, 0x67, 0x66, 0x66, + 0x65, 0x64, 0x64, 0x64, 0x64, 0x64, 0x63, 0x61, 0x75, 0x73, 0x70, 0x6e, + 0x6a, 0x66, 0x62, 0x5d, 0x5a, 0x57, 0x54, 0x50, 0x50, 0x50, 0x52, 0x56, + 0x58, 0x5a, 0x5c, 0x5e, 0x61, 0x63, 0x63, 0x63, 0x64, 0x66, 0x6a, 0x6c, + 0x6d, 0x6d, 0x6b, 0x65, 0x60, 0x73, 0xab, 0xce, 0xd1, 0xcf, 0xd0, 0xd1, + 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, + 0xd9, 0xda, 0xdb, 0xdc, 0xdc, 0xdd, 0xde, 0xdd, 0xdc, 0xdd, 0xdc, 0xdc, + 0xdd, 0xdd, 0xde, 0xde, 0xdd, 0xdc, 0xdc, 0xdc, 0xde, 0xde, 0xde, 0xde, + 0xe0, 0xe0, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe2, 0xe2, 0xe2, + 0xe1, 0xe1, 0xe0, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xde, 0xdd, 0xdd, 0xdc, + 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xda, 0xdb, 0xda, 0xd9, 0xd8, 0xd9, 0xd9, + 0xd7, 0xd8, 0xd7, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd7, 0xd6, 0xd6, 0xd5, + 0xd5, 0xd6, 0xd4, 0xd4, 0xd2, 0xd0, 0xce, 0xcb, 0xc9, 0xc5, 0xbf, 0xbc, + 0xb8, 0xbb, 0xc1, 0xc1, 0xbd, 0xb7, 0xb5, 0xb9, 0xba, 0xba, 0xba, 0xba, + 0xb7, 0xb5, 0xb3, 0xb0, 0xac, 0xa9, 0xa6, 0xa4, 0x9e, 0x94, 0x87, 0x7e, + 0x78, 0x73, 0x7e, 0x8b, 0x91, 0x94, 0x95, 0x94, 0x91, 0x8c, 0x89, 0x83, + 0x76, 0x6a, 0x69, 0x73, 0x8e, 0x99, 0x7c, 0x67, 0x5e, 0x5a, 0x5b, 0x6a, + 0x7d, 0x87, 0x92, 0x9d, 0xa9, 0xa7, 0x9a, 0x82, 0x8f, 0x8d, 0x7c, 0x6e, + 0x66, 0x5c, 0x5d, 0x70, 0x79, 0x79, 0x73, 0x7c, 0x87, 0x75, 0x6d, 0x73, + 0x7e, 0x73, 0x67, 0x5d, 0x4f, 0x4f, 0x4e, 0x51, 0x55, 0x59, 0x59, 0x58, + 0x5c, 0x5e, 0x5f, 0x60, 0x60, 0x61, 0x61, 0x62, 0x63, 0x64, 0x64, 0x64, + 0x64, 0x66, 0x67, 0x68, 0x68, 0x69, 0x69, 0x69, 0x69, 0x69, 0x68, 0x67, + 0x66, 0x66, 0x66, 0x64, 0x5f, 0x5b, 0x5a, 0x59, 0x59, 0x5a, 0x59, 0x5a, + 0x5b, 0x5c, 0x5d, 0x60, 0x64, 0x65, 0x67, 0x6d, 0x73, 0x78, 0x7b, 0x7b, + 0x78, 0x70, 0x6b, 0x68, 0x68, 0x67, 0x69, 0x6e, 0x72, 0x73, 0x73, 0x72, + 0x72, 0x70, 0x6e, 0x6c, 0x6a, 0x68, 0x67, 0x67, 0x65, 0x61, 0x5c, 0x58, + 0x56, 0x55, 0x55, 0x57, 0x58, 0x59, 0x59, 0x5a, 0x5b, 0x5d, 0x5e, 0x5e, + 0x60, 0x61, 0x60, 0x61, 0x61, 0x60, 0x5f, 0x60, 0x60, 0x60, 0x5e, 0x5e, + 0x5f, 0x5f, 0x5e, 0x5c, 0x72, 0x71, 0x6e, 0x6c, 0x67, 0x63, 0x5f, 0x5b, + 0x58, 0x54, 0x4f, 0x4c, 0x4d, 0x4e, 0x52, 0x56, 0x58, 0x5b, 0x5c, 0x5f, + 0x61, 0x62, 0x63, 0x63, 0x65, 0x67, 0x6b, 0x6e, 0x6f, 0x6f, 0x6c, 0x66, + 0x62, 0x79, 0xb6, 0xd0, 0xd0, 0xcf, 0xd0, 0xd1, 0xd2, 0xd4, 0xd4, 0xd5, + 0xd7, 0xd8, 0xd8, 0xd7, 0xd6, 0xd6, 0xd7, 0xd8, 0xd8, 0xd8, 0xd9, 0xdb, + 0xdb, 0xdc, 0xdd, 0xdc, 0xdb, 0xdc, 0xdb, 0xdc, 0xdd, 0xdc, 0xdd, 0xdd, + 0xdc, 0xdb, 0xdb, 0xdb, 0xde, 0xde, 0xde, 0xdd, 0xdd, 0xde, 0xdf, 0xe0, + 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe1, 0xe1, 0xe2, 0xe1, 0xe1, 0xe0, 0xe1, + 0xe1, 0xe1, 0xe1, 0xe1, 0xe0, 0xdf, 0xdf, 0xde, 0xde, 0xde, 0xdd, 0xdd, + 0xdd, 0xdc, 0xdd, 0xdc, 0xdc, 0xdb, 0xdb, 0xda, 0xd9, 0xd9, 0xd9, 0xd9, + 0xda, 0xd8, 0xd7, 0xd8, 0xd8, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd6, 0xd5, + 0xd4, 0xd2, 0xd1, 0xd0, 0xcc, 0xc8, 0xc6, 0xc4, 0xbd, 0xb6, 0xb9, 0xc0, + 0xc1, 0xbc, 0xb4, 0xb4, 0xb7, 0xb8, 0xb9, 0xb9, 0xb8, 0xb5, 0xb3, 0xb1, + 0xad, 0xa9, 0xa7, 0xa5, 0xa1, 0x98, 0x8f, 0x87, 0x80, 0x75, 0x74, 0x84, + 0x8d, 0x90, 0x93, 0x93, 0x91, 0x8f, 0x8c, 0x85, 0x79, 0x6c, 0x67, 0x70, + 0x88, 0x96, 0x7c, 0x67, 0x5e, 0x5a, 0x59, 0x64, 0x73, 0x7f, 0x8f, 0x9d, + 0xa2, 0x9e, 0x8f, 0x77, 0x88, 0x8e, 0x82, 0x75, 0x6d, 0x63, 0x5c, 0x68, + 0x72, 0x74, 0x73, 0x7b, 0x7f, 0x6e, 0x67, 0x6a, 0x72, 0x6f, 0x69, 0x5f, + 0x4d, 0x49, 0x4b, 0x4f, 0x53, 0x59, 0x5a, 0x58, 0x5a, 0x5c, 0x5e, 0x5f, + 0x5f, 0x60, 0x61, 0x62, 0x62, 0x63, 0x63, 0x64, 0x65, 0x67, 0x68, 0x67, + 0x66, 0x66, 0x67, 0x66, 0x67, 0x67, 0x65, 0x66, 0x65, 0x65, 0x64, 0x61, + 0x5d, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5c, 0x5e, 0x5f, 0x62, + 0x66, 0x69, 0x6b, 0x70, 0x77, 0x7a, 0x7b, 0x7a, 0x75, 0x6d, 0x68, 0x67, + 0x66, 0x67, 0x69, 0x6d, 0x72, 0x73, 0x71, 0x6f, 0x6f, 0x6c, 0x6b, 0x6a, + 0x67, 0x65, 0x65, 0x64, 0x62, 0x5e, 0x58, 0x54, 0x53, 0x52, 0x53, 0x54, + 0x55, 0x55, 0x54, 0x54, 0x56, 0x57, 0x57, 0x57, 0x58, 0x5a, 0x5a, 0x5a, + 0x5a, 0x5a, 0x5b, 0x5b, 0x5a, 0x5a, 0x59, 0x59, 0x5a, 0x5a, 0x58, 0x56, + 0x70, 0x6f, 0x6c, 0x6a, 0x66, 0x61, 0x5d, 0x59, 0x57, 0x53, 0x4d, 0x4b, + 0x4c, 0x4e, 0x51, 0x56, 0x59, 0x5b, 0x5d, 0x5f, 0x61, 0x62, 0x63, 0x64, + 0x66, 0x69, 0x6c, 0x70, 0x71, 0x70, 0x6c, 0x67, 0x65, 0x7e, 0xbc, 0xd1, + 0xcf, 0xcf, 0xcf, 0xd0, 0xd3, 0xd3, 0xd4, 0xd5, 0xd7, 0xd7, 0xd7, 0xd6, + 0xd6, 0xd5, 0xd5, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xdb, 0xdc, 0xdb, + 0xda, 0xdb, 0xdb, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdb, 0xdb, 0xdb, + 0xde, 0xde, 0xde, 0xdc, 0xdc, 0xdd, 0xde, 0xdf, 0xdf, 0xe0, 0xe0, 0xe1, + 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe0, 0xdf, 0xdf, 0xe0, 0xdf, 0xdf, 0xe0, + 0xe0, 0xde, 0xdf, 0xde, 0xdd, 0xdc, 0xdc, 0xdd, 0xdd, 0xdb, 0xdb, 0xdb, + 0xdb, 0xda, 0xda, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xd9, 0xd8, 0xd8, + 0xd9, 0xd8, 0xd8, 0xd8, 0xd9, 0xd8, 0xd7, 0xd7, 0xd6, 0xd4, 0xd3, 0xd3, + 0xd2, 0xcd, 0xca, 0xc9, 0xc4, 0xba, 0xb4, 0xb8, 0xbc, 0xbf, 0xb7, 0xb1, + 0xb4, 0xb6, 0xb8, 0xb9, 0xb8, 0xb6, 0xb4, 0xb1, 0xae, 0xaa, 0xa8, 0xa6, + 0xa3, 0x9c, 0x94, 0x8e, 0x87, 0x79, 0x70, 0x7e, 0x89, 0x8d, 0x90, 0x92, + 0x91, 0x8f, 0x8c, 0x86, 0x7a, 0x6e, 0x69, 0x6f, 0x85, 0x93, 0x7b, 0x66, + 0x5e, 0x59, 0x59, 0x61, 0x6d, 0x78, 0x89, 0x9a, 0x9d, 0x95, 0x86, 0x6f, + 0x83, 0x8f, 0x85, 0x78, 0x70, 0x65, 0x5b, 0x5e, 0x66, 0x6a, 0x6f, 0x78, + 0x7a, 0x6d, 0x67, 0x66, 0x6c, 0x70, 0x6b, 0x61, 0x4d, 0x4a, 0x4b, 0x4e, + 0x52, 0x59, 0x5b, 0x59, 0x5a, 0x5b, 0x5d, 0x5e, 0x5e, 0x5f, 0x60, 0x61, + 0x62, 0x63, 0x64, 0x64, 0x65, 0x67, 0x67, 0x66, 0x65, 0x65, 0x66, 0x65, + 0x66, 0x66, 0x64, 0x65, 0x63, 0x62, 0x61, 0x5e, 0x5b, 0x59, 0x5a, 0x5a, + 0x5a, 0x5a, 0x59, 0x5b, 0x5e, 0x5f, 0x60, 0x64, 0x68, 0x6b, 0x6f, 0x74, + 0x7a, 0x7b, 0x7c, 0x79, 0x73, 0x6c, 0x68, 0x67, 0x66, 0x67, 0x69, 0x6c, + 0x71, 0x72, 0x70, 0x6d, 0x6d, 0x6b, 0x6a, 0x68, 0x65, 0x63, 0x63, 0x61, + 0x5f, 0x5b, 0x55, 0x52, 0x51, 0x51, 0x51, 0x52, 0x51, 0x51, 0x51, 0x52, + 0x53, 0x54, 0x55, 0x54, 0x55, 0x56, 0x56, 0x56, 0x57, 0x56, 0x57, 0x57, + 0x56, 0x57, 0x55, 0x56, 0x56, 0x56, 0x54, 0x53, 0x6f, 0x6d, 0x6a, 0x68, + 0x64, 0x5f, 0x5b, 0x58, 0x56, 0x51, 0x4c, 0x49, 0x4a, 0x4d, 0x51, 0x55, + 0x59, 0x5b, 0x5c, 0x5f, 0x61, 0x62, 0x63, 0x64, 0x66, 0x69, 0x6d, 0x71, + 0x72, 0x71, 0x6d, 0x68, 0x69, 0x82, 0xbe, 0xd1, 0xcf, 0xce, 0xcf, 0xd0, + 0xd2, 0xd2, 0xd4, 0xd5, 0xd6, 0xd7, 0xd7, 0xd6, 0xd6, 0xd5, 0xd6, 0xd7, + 0xd7, 0xd8, 0xd8, 0xd8, 0xd9, 0xda, 0xda, 0xdb, 0xda, 0xdb, 0xdb, 0xdb, + 0xdc, 0xdc, 0xdb, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdd, 0xdd, 0xdd, 0xdc, + 0xdc, 0xdd, 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xe0, 0xe0, 0xdf, 0xdf, 0xe0, + 0xdf, 0xdf, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdc, 0xdd, 0xdd, + 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xda, 0xd9, 0xda, 0xd9, 0xd9, 0xd8, 0xd8, + 0xd9, 0xd9, 0xd9, 0xda, 0xda, 0xd8, 0xd8, 0xd9, 0xd9, 0xd8, 0xd8, 0xd9, + 0xd8, 0xd8, 0xd7, 0xd7, 0xd7, 0xd5, 0xd4, 0xd5, 0xd4, 0xd0, 0xcd, 0xcb, + 0xc8, 0xbf, 0xb6, 0xb4, 0xb8, 0xbe, 0xbb, 0xb1, 0xb1, 0xb3, 0xb7, 0xb9, + 0xb8, 0xb6, 0xb4, 0xb2, 0xae, 0xab, 0xa9, 0xa8, 0xa4, 0x9e, 0x96, 0x90, + 0x8a, 0x7d, 0x6f, 0x7b, 0x86, 0x8b, 0x8f, 0x92, 0x91, 0x8f, 0x8c, 0x86, + 0x7b, 0x6e, 0x69, 0x6f, 0x82, 0x91, 0x7a, 0x67, 0x5e, 0x5a, 0x59, 0x5f, + 0x6a, 0x73, 0x84, 0x94, 0x98, 0x90, 0x81, 0x6d, 0x81, 0x8f, 0x85, 0x78, + 0x70, 0x66, 0x5a, 0x58, 0x5d, 0x62, 0x6a, 0x75, 0x76, 0x6c, 0x66, 0x64, + 0x6a, 0x70, 0x6c, 0x61, 0x4d, 0x4a, 0x4d, 0x4d, 0x51, 0x57, 0x5b, 0x5a, + 0x5a, 0x5a, 0x5c, 0x5e, 0x5e, 0x5f, 0x5f, 0x61, 0x62, 0x63, 0x64, 0x64, + 0x65, 0x67, 0x67, 0x65, 0x65, 0x65, 0x66, 0x65, 0x65, 0x65, 0x64, 0x63, + 0x62, 0x61, 0x5f, 0x5d, 0x5a, 0x59, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5c, + 0x5f, 0x60, 0x62, 0x66, 0x6a, 0x6e, 0x71, 0x76, 0x7b, 0x7b, 0x7b, 0x78, + 0x71, 0x6a, 0x67, 0x66, 0x66, 0x67, 0x69, 0x6c, 0x70, 0x71, 0x6e, 0x6c, + 0x6c, 0x6a, 0x69, 0x67, 0x64, 0x61, 0x61, 0x5f, 0x5d, 0x59, 0x54, 0x51, + 0x50, 0x50, 0x50, 0x51, 0x50, 0x50, 0x50, 0x50, 0x51, 0x53, 0x53, 0x53, + 0x53, 0x54, 0x54, 0x54, 0x55, 0x55, 0x55, 0x55, 0x54, 0x55, 0x53, 0x54, + 0x54, 0x54, 0x52, 0x51, 0x6f, 0x6b, 0x68, 0x65, 0x61, 0x5d, 0x59, 0x56, + 0x54, 0x4f, 0x4a, 0x47, 0x49, 0x4b, 0x50, 0x54, 0x58, 0x5a, 0x5b, 0x5d, + 0x62, 0x64, 0x65, 0x65, 0x66, 0x68, 0x6d, 0x71, 0x73, 0x73, 0x6f, 0x6b, + 0x6f, 0x88, 0xc1, 0xd0, 0xce, 0xce, 0xce, 0xd0, 0xd2, 0xd2, 0xd4, 0xd5, + 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd6, 0xd6, 0xd6, 0xd7, 0xd7, 0xd8, 0xd9, + 0xd8, 0xd9, 0xd9, 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xda, 0xdb, + 0xdc, 0xdc, 0xdc, 0xdc, 0xdd, 0xdd, 0xdd, 0xdb, 0xdc, 0xdd, 0xdd, 0xdd, + 0xdc, 0xdd, 0xdd, 0xdf, 0xdf, 0xde, 0xde, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdc, 0xdb, 0xdc, 0xda, 0xda, 0xda, 0xda, 0xd8, 0xd9, 0xd9, 0xda, + 0xda, 0xda, 0xd8, 0xd8, 0xd7, 0xd7, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd9, + 0xd9, 0xd7, 0xd7, 0xd7, 0xd8, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd5, 0xd6, + 0xd6, 0xd5, 0xd5, 0xd4, 0xd4, 0xd4, 0xd1, 0xd0, 0xcd, 0xc7, 0xbe, 0xb7, + 0xb5, 0xb9, 0xbc, 0xb4, 0xae, 0xae, 0xb2, 0xb7, 0xb8, 0xb6, 0xb4, 0xb3, + 0xaf, 0xac, 0xab, 0xaa, 0xa6, 0xa0, 0x98, 0x93, 0x8e, 0x82, 0x71, 0x75, + 0x80, 0x86, 0x8c, 0x90, 0x90, 0x8e, 0x8b, 0x86, 0x7d, 0x70, 0x6a, 0x6e, + 0x7e, 0x8d, 0x78, 0x66, 0x5f, 0x5a, 0x59, 0x5c, 0x65, 0x6e, 0x7a, 0x8a, + 0x8f, 0x89, 0x7c, 0x6b, 0x7c, 0x8b, 0x84, 0x78, 0x70, 0x66, 0x59, 0x52, + 0x52, 0x56, 0x62, 0x72, 0x71, 0x67, 0x62, 0x60, 0x67, 0x6d, 0x6a, 0x5f, + 0x4d, 0x4c, 0x4f, 0x4e, 0x4f, 0x56, 0x5a, 0x5b, 0x5a, 0x5a, 0x5c, 0x5e, + 0x5f, 0x5e, 0x5f, 0x60, 0x61, 0x63, 0x63, 0x64, 0x65, 0x66, 0x66, 0x65, + 0x64, 0x65, 0x65, 0x64, 0x64, 0x64, 0x63, 0x62, 0x61, 0x5f, 0x5e, 0x5c, + 0x5a, 0x59, 0x58, 0x59, 0x59, 0x59, 0x5a, 0x5d, 0x60, 0x61, 0x64, 0x68, + 0x6d, 0x71, 0x75, 0x78, 0x7b, 0x79, 0x76, 0x74, 0x6f, 0x69, 0x66, 0x66, + 0x66, 0x67, 0x68, 0x6b, 0x6e, 0x6e, 0x6c, 0x6a, 0x69, 0x68, 0x67, 0x63, + 0x60, 0x5e, 0x5d, 0x5c, 0x5a, 0x56, 0x51, 0x4e, 0x4e, 0x4e, 0x4f, 0x4e, + 0x4e, 0x4e, 0x4e, 0x4f, 0x50, 0x51, 0x51, 0x50, 0x51, 0x52, 0x52, 0x53, + 0x53, 0x53, 0x53, 0x53, 0x52, 0x52, 0x51, 0x52, 0x51, 0x51, 0x50, 0x4f, + 0x6b, 0x66, 0x63, 0x61, 0x5e, 0x5a, 0x56, 0x52, 0x4f, 0x4c, 0x47, 0x45, + 0x47, 0x4a, 0x4e, 0x52, 0x57, 0x5a, 0x5c, 0x5e, 0x62, 0x64, 0x66, 0x66, + 0x67, 0x69, 0x6e, 0x73, 0x76, 0x76, 0x72, 0x6e, 0x76, 0x90, 0xc3, 0xd0, + 0xcf, 0xce, 0xce, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd4, 0xd3, 0xd4, 0xd4, + 0xd4, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd7, 0xd8, 0xd7, 0xd8, 0xd9, + 0xd9, 0xda, 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xda, 0xdc, 0xdc, 0xdb, 0xdb, + 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xda, 0xdb, 0xdc, + 0xdc, 0xdb, 0xdc, 0xda, 0xda, 0xda, 0xdb, 0xda, 0xda, 0xdc, 0xdc, 0xdb, + 0xd9, 0xd9, 0xd9, 0xd9, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, + 0xd8, 0xd8, 0xd9, 0xd9, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd8, 0xd8, 0xd8, + 0xd7, 0xd6, 0xd6, 0xd6, 0xd6, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, + 0xd5, 0xd5, 0xd5, 0xd4, 0xd3, 0xd1, 0xcc, 0xc4, 0xbe, 0xb7, 0xb9, 0xb9, + 0xb3, 0xaf, 0xad, 0xb3, 0xb6, 0xb6, 0xb5, 0xb3, 0xb0, 0xad, 0xac, 0xab, + 0xa7, 0xa1, 0x9b, 0x96, 0x93, 0x89, 0x76, 0x6d, 0x78, 0x81, 0x87, 0x8d, + 0x8f, 0x8e, 0x8c, 0x87, 0x7e, 0x73, 0x6c, 0x6e, 0x7b, 0x88, 0x75, 0x66, + 0x5f, 0x5b, 0x59, 0x5a, 0x61, 0x68, 0x71, 0x7d, 0x86, 0x84, 0x7a, 0x67, + 0x6f, 0x87, 0x84, 0x79, 0x72, 0x69, 0x58, 0x4f, 0x4b, 0x4e, 0x5b, 0x6c, + 0x6a, 0x62, 0x5d, 0x59, 0x5e, 0x68, 0x69, 0x61, 0x4f, 0x4c, 0x4e, 0x4d, + 0x4f, 0x55, 0x5b, 0x5c, 0x59, 0x59, 0x5b, 0x5d, 0x5f, 0x5f, 0x5f, 0x5f, + 0x61, 0x62, 0x62, 0x63, 0x63, 0x65, 0x65, 0x64, 0x63, 0x64, 0x64, 0x62, + 0x63, 0x62, 0x61, 0x60, 0x5f, 0x5d, 0x5c, 0x5b, 0x58, 0x57, 0x58, 0x58, + 0x59, 0x5a, 0x5b, 0x5f, 0x62, 0x64, 0x65, 0x6a, 0x70, 0x76, 0x79, 0x7a, + 0x7a, 0x76, 0x71, 0x6e, 0x6a, 0x67, 0x64, 0x65, 0x65, 0x66, 0x68, 0x6a, + 0x6a, 0x6a, 0x68, 0x66, 0x64, 0x63, 0x61, 0x5e, 0x5b, 0x5a, 0x58, 0x57, + 0x56, 0x53, 0x4f, 0x4d, 0x4d, 0x4e, 0x4e, 0x4d, 0x4e, 0x4e, 0x4e, 0x4f, + 0x4f, 0x50, 0x50, 0x4f, 0x50, 0x50, 0x50, 0x50, 0x51, 0x50, 0x50, 0x4f, + 0x4f, 0x4f, 0x4d, 0x4d, 0x4d, 0x4c, 0x4d, 0x4c, 0x67, 0x63, 0x61, 0x5f, + 0x5b, 0x57, 0x53, 0x4f, 0x4d, 0x49, 0x47, 0x46, 0x47, 0x49, 0x4c, 0x52, + 0x58, 0x5a, 0x5c, 0x5e, 0x62, 0x64, 0x66, 0x67, 0x68, 0x6b, 0x70, 0x76, + 0x78, 0x78, 0x74, 0x71, 0x80, 0x98, 0xc4, 0xcf, 0xce, 0xce, 0xce, 0xcf, + 0xd0, 0xd1, 0xd3, 0xd3, 0xd3, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd4, + 0xd4, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd8, 0xd9, 0xda, 0xda, 0xda, 0xd9, + 0xd9, 0xd9, 0xdb, 0xdc, 0xdb, 0xda, 0xdb, 0xda, 0xdb, 0xda, 0xda, 0xdb, + 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xda, 0xdb, 0xda, 0xda, 0xd9, 0xdb, 0xdb, + 0xda, 0xda, 0xda, 0xd9, 0xd9, 0xda, 0xdb, 0xdc, 0xda, 0xda, 0xdb, 0xdb, + 0xda, 0xdb, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdb, 0xdb, 0xdb, 0xdb, + 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xda, 0xda, 0xd9, 0xd8, + 0xd7, 0xd8, 0xd6, 0xd5, 0xd4, 0xd5, 0xd4, 0xd4, 0xd5, 0xd4, 0xd4, 0xd4, + 0xd4, 0xd4, 0xd3, 0xd0, 0xcb, 0xc3, 0xbd, 0xbc, 0xba, 0xb5, 0xad, 0xac, + 0xb3, 0xb6, 0xb6, 0xb4, 0xb1, 0xaf, 0xae, 0xac, 0xa7, 0xa2, 0x9c, 0x99, + 0x96, 0x8e, 0x7f, 0x6c, 0x71, 0x78, 0x84, 0x8a, 0x8c, 0x8d, 0x8b, 0x86, + 0x80, 0x75, 0x6d, 0x6e, 0x77, 0x83, 0x73, 0x65, 0x5f, 0x5c, 0x59, 0x59, + 0x5d, 0x63, 0x6c, 0x76, 0x7f, 0x83, 0x7b, 0x64, 0x5a, 0x7d, 0x83, 0x7a, + 0x74, 0x6b, 0x5b, 0x50, 0x4c, 0x4e, 0x59, 0x68, 0x66, 0x61, 0x5d, 0x57, + 0x59, 0x64, 0x6a, 0x66, 0x56, 0x4d, 0x4f, 0x4e, 0x4e, 0x53, 0x59, 0x5c, + 0x59, 0x58, 0x5a, 0x5c, 0x5e, 0x5e, 0x5e, 0x5e, 0x60, 0x60, 0x62, 0x62, + 0x63, 0x64, 0x64, 0x64, 0x64, 0x63, 0x62, 0x62, 0x61, 0x61, 0x60, 0x5e, + 0x5d, 0x5b, 0x5a, 0x58, 0x57, 0x57, 0x58, 0x58, 0x59, 0x5a, 0x5c, 0x60, + 0x63, 0x65, 0x67, 0x6d, 0x74, 0x78, 0x7a, 0x7b, 0x78, 0x73, 0x6d, 0x6a, + 0x68, 0x65, 0x63, 0x64, 0x64, 0x65, 0x66, 0x67, 0x67, 0x65, 0x64, 0x62, + 0x5f, 0x5d, 0x5c, 0x5a, 0x56, 0x55, 0x54, 0x54, 0x53, 0x51, 0x4e, 0x4d, + 0x4c, 0x4d, 0x4d, 0x4c, 0x4c, 0x4d, 0x4f, 0x50, 0x50, 0x50, 0x50, 0x50, + 0x50, 0x4f, 0x4f, 0x4f, 0x4f, 0x4e, 0x4e, 0x4c, 0x4c, 0x4c, 0x4b, 0x4b, + 0x4a, 0x49, 0x48, 0x4a, 0x64, 0x61, 0x5f, 0x5c, 0x58, 0x55, 0x52, 0x4e, + 0x4c, 0x49, 0x47, 0x45, 0x45, 0x47, 0x4c, 0x51, 0x59, 0x5b, 0x5d, 0x5f, + 0x62, 0x65, 0x68, 0x69, 0x6a, 0x6e, 0x73, 0x79, 0x7b, 0x7a, 0x74, 0x73, + 0x88, 0xa1, 0xc6, 0xcf, 0xcd, 0xcd, 0xcd, 0xce, 0xcf, 0xd2, 0xd3, 0xd3, + 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd3, 0xd5, 0xd5, 0xd5, 0xd5, 0xd6, + 0xd6, 0xd7, 0xd7, 0xd7, 0xd9, 0xd9, 0xd9, 0xd9, 0xd8, 0xd8, 0xdb, 0xdc, + 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xda, 0xdb, 0xdb, + 0xdb, 0xdb, 0xda, 0xdb, 0xdb, 0xda, 0xda, 0xdb, 0xdb, 0xda, 0xda, 0xda, + 0xda, 0xdc, 0xdd, 0xdd, 0xdc, 0xdc, 0xdd, 0xdd, 0xdc, 0xdc, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, 0xdc, 0xdd, 0xdd, 0xdc, 0xdc, 0xdc, 0xdc, + 0xdc, 0xdd, 0xdc, 0xdb, 0xdb, 0xdc, 0xdb, 0xda, 0xd9, 0xd9, 0xd9, 0xd6, + 0xd6, 0xd5, 0xd5, 0xd4, 0xd5, 0xd5, 0xd4, 0xd4, 0xd4, 0xd5, 0xd4, 0xd3, + 0xd2, 0xce, 0xc7, 0xc2, 0xc0, 0xbc, 0xb2, 0xab, 0xb0, 0xb5, 0xb6, 0xb4, + 0xb2, 0xb0, 0xae, 0xac, 0xa8, 0xa3, 0x9e, 0x9b, 0x98, 0x91, 0x83, 0x70, + 0x6a, 0x70, 0x7f, 0x88, 0x8b, 0x8b, 0x8a, 0x87, 0x81, 0x76, 0x6e, 0x6e, + 0x75, 0x7f, 0x71, 0x65, 0x5f, 0x5c, 0x59, 0x58, 0x5b, 0x60, 0x69, 0x73, + 0x7d, 0x83, 0x7d, 0x64, 0x4b, 0x72, 0x80, 0x79, 0x74, 0x6e, 0x5f, 0x54, + 0x4f, 0x50, 0x59, 0x66, 0x65, 0x62, 0x5e, 0x55, 0x54, 0x5f, 0x6b, 0x6a, + 0x5c, 0x51, 0x51, 0x50, 0x4e, 0x4f, 0x57, 0x5b, 0x58, 0x57, 0x5a, 0x5b, + 0x5c, 0x5c, 0x5c, 0x5c, 0x5e, 0x5f, 0x61, 0x62, 0x62, 0x62, 0x62, 0x63, + 0x64, 0x63, 0x61, 0x60, 0x60, 0x60, 0x5f, 0x5d, 0x5c, 0x5b, 0x5a, 0x58, + 0x57, 0x57, 0x58, 0x58, 0x59, 0x5b, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6f, + 0x76, 0x78, 0x78, 0x77, 0x75, 0x70, 0x6b, 0x69, 0x65, 0x63, 0x62, 0x63, + 0x63, 0x63, 0x63, 0x63, 0x63, 0x61, 0x60, 0x5e, 0x5b, 0x59, 0x58, 0x55, + 0x53, 0x51, 0x51, 0x51, 0x51, 0x4f, 0x4d, 0x4c, 0x4c, 0x4c, 0x4b, 0x4b, + 0x4c, 0x4d, 0x4f, 0x4f, 0x50, 0x51, 0x51, 0x50, 0x51, 0x4f, 0x4f, 0x4e, + 0x4d, 0x4c, 0x4c, 0x4b, 0x4a, 0x4a, 0x4a, 0x49, 0x47, 0x47, 0x47, 0x48, + 0x62, 0x5f, 0x5d, 0x5b, 0x57, 0x54, 0x50, 0x4d, 0x4b, 0x48, 0x46, 0x44, + 0x44, 0x46, 0x4b, 0x52, 0x59, 0x5c, 0x5d, 0x5f, 0x63, 0x65, 0x68, 0x6a, + 0x6b, 0x6e, 0x74, 0x7a, 0x7c, 0x7b, 0x74, 0x73, 0x8d, 0xa6, 0xc7, 0xcf, + 0xcd, 0xcc, 0xcd, 0xcd, 0xcf, 0xd1, 0xd2, 0xd2, 0xd2, 0xd4, 0xd4, 0xd3, + 0xd3, 0xd4, 0xd3, 0xd4, 0xd4, 0xd3, 0xd4, 0xd5, 0xd5, 0xd6, 0xd6, 0xd6, + 0xd8, 0xd8, 0xd8, 0xd9, 0xd8, 0xd8, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, + 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdc, + 0xdc, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xde, 0xde, + 0xde, 0xde, 0xdd, 0xdd, 0xdc, 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, 0xdd, 0xdd, 0xdd, 0xdc, + 0xdb, 0xdc, 0xdb, 0xdb, 0xda, 0xda, 0xda, 0xd7, 0xd7, 0xd6, 0xd5, 0xd4, + 0xd5, 0xd5, 0xd5, 0xd5, 0xd4, 0xd5, 0xd4, 0xd3, 0xd3, 0xd2, 0xcd, 0xc7, + 0xc4, 0xc1, 0xb8, 0xac, 0xae, 0xb2, 0xb4, 0xb4, 0xb2, 0xb0, 0xae, 0xac, + 0xa9, 0xa5, 0x9f, 0x9c, 0x99, 0x93, 0x85, 0x74, 0x68, 0x6a, 0x7b, 0x86, + 0x8a, 0x8a, 0x89, 0x86, 0x81, 0x77, 0x6f, 0x6e, 0x74, 0x7c, 0x70, 0x64, + 0x5f, 0x5d, 0x59, 0x58, 0x5b, 0x5e, 0x67, 0x72, 0x7b, 0x84, 0x7f, 0x65, + 0x45, 0x65, 0x7b, 0x78, 0x74, 0x6f, 0x61, 0x56, 0x51, 0x51, 0x58, 0x65, + 0x64, 0x61, 0x5d, 0x55, 0x51, 0x5b, 0x69, 0x6a, 0x5f, 0x54, 0x52, 0x50, + 0x4e, 0x4e, 0x56, 0x5b, 0x57, 0x56, 0x59, 0x5a, 0x5c, 0x5b, 0x5b, 0x5c, + 0x5d, 0x5f, 0x60, 0x61, 0x61, 0x61, 0x61, 0x62, 0x63, 0x62, 0x61, 0x60, + 0x60, 0x5f, 0x5e, 0x5c, 0x5b, 0x5b, 0x5a, 0x58, 0x57, 0x57, 0x57, 0x58, + 0x59, 0x5c, 0x60, 0x63, 0x66, 0x68, 0x6a, 0x70, 0x76, 0x77, 0x77, 0x75, + 0x71, 0x6d, 0x6a, 0x67, 0x64, 0x61, 0x61, 0x62, 0x62, 0x61, 0x61, 0x61, + 0x60, 0x5f, 0x5c, 0x5b, 0x58, 0x57, 0x56, 0x53, 0x51, 0x50, 0x50, 0x50, + 0x50, 0x4e, 0x4c, 0x4b, 0x4b, 0x4c, 0x4b, 0x4b, 0x4d, 0x4d, 0x4f, 0x4f, + 0x50, 0x51, 0x51, 0x50, 0x51, 0x4f, 0x4e, 0x4d, 0x4b, 0x4a, 0x4b, 0x49, + 0x49, 0x48, 0x49, 0x48, 0x46, 0x45, 0x45, 0x46, 0x60, 0x5d, 0x5b, 0x59, + 0x56, 0x52, 0x4e, 0x4c, 0x49, 0x47, 0x45, 0x42, 0x42, 0x45, 0x4a, 0x51, + 0x59, 0x5d, 0x5e, 0x60, 0x63, 0x66, 0x69, 0x6b, 0x6c, 0x6f, 0x75, 0x7b, + 0x7d, 0x7c, 0x75, 0x73, 0x93, 0xac, 0xc8, 0xcf, 0xcd, 0xcd, 0xcd, 0xce, + 0xcf, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd2, 0xd3, + 0xd3, 0xd2, 0xd3, 0xd4, 0xd5, 0xd5, 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, + 0xd8, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xdb, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, + 0xdc, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdf, 0xdf, 0xde, 0xe0, 0xdf, 0xde, 0xde, + 0xdd, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, + 0xdd, 0xdd, 0xdd, 0xde, 0xdd, 0xde, 0xdd, 0xdc, 0xdb, 0xdc, 0xdd, 0xdc, + 0xdc, 0xdc, 0xdb, 0xd9, 0xd8, 0xd7, 0xd7, 0xd6, 0xd6, 0xd6, 0xd5, 0xd5, + 0xd5, 0xd5, 0xd4, 0xd4, 0xd3, 0xd3, 0xd1, 0xcd, 0xca, 0xc8, 0xc2, 0xb5, + 0xab, 0xad, 0xb0, 0xb2, 0xb1, 0xb0, 0xae, 0xad, 0xa9, 0xa5, 0xa1, 0x9e, + 0x9b, 0x95, 0x8a, 0x79, 0x6a, 0x68, 0x75, 0x81, 0x86, 0x87, 0x87, 0x85, + 0x80, 0x77, 0x70, 0x6f, 0x72, 0x79, 0x6f, 0x64, 0x60, 0x5c, 0x59, 0x58, + 0x59, 0x5d, 0x64, 0x6e, 0x79, 0x83, 0x81, 0x6a, 0x42, 0x50, 0x6f, 0x75, + 0x74, 0x6f, 0x63, 0x59, 0x54, 0x53, 0x57, 0x63, 0x62, 0x5f, 0x5b, 0x54, + 0x4f, 0x55, 0x61, 0x65, 0x62, 0x58, 0x52, 0x4f, 0x4d, 0x4c, 0x55, 0x5b, + 0x57, 0x56, 0x58, 0x59, 0x5a, 0x5b, 0x5b, 0x5c, 0x5d, 0x5f, 0x60, 0x60, + 0x5e, 0x5e, 0x5f, 0x61, 0x62, 0x61, 0x5f, 0x5f, 0x5f, 0x5e, 0x5d, 0x5c, + 0x5a, 0x5a, 0x59, 0x58, 0x57, 0x57, 0x58, 0x59, 0x59, 0x5d, 0x61, 0x64, + 0x67, 0x69, 0x6c, 0x72, 0x74, 0x74, 0x73, 0x71, 0x6e, 0x69, 0x66, 0x65, + 0x62, 0x60, 0x5f, 0x60, 0x60, 0x60, 0x5e, 0x5d, 0x5c, 0x5a, 0x59, 0x57, + 0x55, 0x52, 0x51, 0x50, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4d, 0x4b, 0x4a, + 0x4a, 0x4b, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x4f, 0x51, 0x51, 0x50, 0x50, + 0x50, 0x4d, 0x4c, 0x4b, 0x4a, 0x49, 0x48, 0x48, 0x47, 0x46, 0x46, 0x46, + 0x45, 0x44, 0x44, 0x45, 0x5f, 0x5c, 0x58, 0x56, 0x52, 0x50, 0x4d, 0x4a, + 0x47, 0x45, 0x42, 0x42, 0x41, 0x43, 0x49, 0x51, 0x58, 0x5d, 0x5f, 0x61, + 0x64, 0x69, 0x6b, 0x6c, 0x6e, 0x71, 0x77, 0x7c, 0x7e, 0x7d, 0x75, 0x75, + 0x9d, 0xb7, 0xca, 0xce, 0xce, 0xce, 0xce, 0xcd, 0xce, 0xd1, 0xd1, 0xd1, + 0xd1, 0xd3, 0xd3, 0xd3, 0xd3, 0xd1, 0xd1, 0xd3, 0xd3, 0xd2, 0xd3, 0xd2, + 0xd3, 0xd5, 0xd5, 0xd4, 0xd6, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd9, 0xd8, + 0xd8, 0xd9, 0xda, 0xdb, 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, + 0xdb, 0xdb, 0xdb, 0xdc, 0xdd, 0xdd, 0xdc, 0xde, 0xde, 0xde, 0xde, 0xde, + 0xde, 0xdf, 0xdf, 0xdf, 0xe0, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, + 0xe0, 0xe0, 0xe0, 0xe0, 0xde, 0xde, 0xdf, 0xde, 0xde, 0xde, 0xde, 0xdf, + 0xdf, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdd, 0xdb, + 0xd9, 0xd8, 0xd8, 0xd8, 0xd7, 0xd7, 0xd6, 0xd5, 0xd6, 0xd6, 0xd5, 0xd5, + 0xd5, 0xd3, 0xd2, 0xd1, 0xce, 0xcd, 0xca, 0xc1, 0xb2, 0xaa, 0xaa, 0xae, + 0xb0, 0xaf, 0xae, 0xac, 0xa9, 0xa5, 0xa1, 0x9f, 0x9c, 0x97, 0x8f, 0x81, + 0x71, 0x6a, 0x6d, 0x7a, 0x82, 0x85, 0x84, 0x83, 0x7c, 0x75, 0x71, 0x6f, + 0x71, 0x75, 0x6d, 0x63, 0x5e, 0x5d, 0x5a, 0x59, 0x59, 0x5b, 0x62, 0x6c, + 0x77, 0x81, 0x80, 0x6c, 0x42, 0x3b, 0x59, 0x6d, 0x72, 0x6f, 0x66, 0x5e, + 0x58, 0x56, 0x57, 0x62, 0x61, 0x5c, 0x58, 0x52, 0x4c, 0x4e, 0x56, 0x5c, + 0x62, 0x5b, 0x53, 0x4e, 0x4c, 0x4c, 0x54, 0x5a, 0x57, 0x56, 0x58, 0x57, + 0x57, 0x59, 0x59, 0x5c, 0x5e, 0x5f, 0x5f, 0x5f, 0x5e, 0x5e, 0x5f, 0x60, + 0x60, 0x5f, 0x5e, 0x5e, 0x5d, 0x5d, 0x5c, 0x5a, 0x59, 0x58, 0x58, 0x58, + 0x58, 0x58, 0x59, 0x5a, 0x5b, 0x5f, 0x62, 0x66, 0x68, 0x69, 0x6d, 0x72, + 0x71, 0x70, 0x6e, 0x6c, 0x68, 0x64, 0x61, 0x60, 0x5f, 0x5f, 0x5d, 0x5c, + 0x5c, 0x5c, 0x5a, 0x57, 0x56, 0x55, 0x54, 0x52, 0x4f, 0x4e, 0x4e, 0x4d, + 0x4d, 0x4f, 0x50, 0x50, 0x4e, 0x4c, 0x4a, 0x49, 0x49, 0x4a, 0x4b, 0x4c, + 0x4e, 0x4f, 0x50, 0x50, 0x50, 0x51, 0x51, 0x50, 0x4e, 0x4c, 0x4a, 0x4a, + 0x49, 0x47, 0x46, 0x46, 0x46, 0x46, 0x44, 0x43, 0x43, 0x42, 0x42, 0x42, + 0x5d, 0x59, 0x56, 0x54, 0x50, 0x4e, 0x4b, 0x47, 0x45, 0x43, 0x41, 0x41, + 0x41, 0x42, 0x49, 0x51, 0x59, 0x5e, 0x60, 0x63, 0x66, 0x6a, 0x6d, 0x6e, + 0x71, 0x75, 0x7b, 0x7e, 0x7f, 0x7e, 0x76, 0x78, 0xa7, 0xc0, 0xcc, 0xce, + 0xcf, 0xce, 0xce, 0xcd, 0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xd1, 0xd1, 0xd2, + 0xd2, 0xd1, 0xd0, 0xd1, 0xd2, 0xd2, 0xd3, 0xd3, 0xd3, 0xd4, 0xd5, 0xd4, + 0xd5, 0xd7, 0xd8, 0xd8, 0xd8, 0xd8, 0xda, 0xd9, 0xd8, 0xd9, 0xdb, 0xdb, + 0xdb, 0xdc, 0xdc, 0xdb, 0xdb, 0xdb, 0xdc, 0xdb, 0xdb, 0xdb, 0xdb, 0xdc, + 0xdc, 0xdc, 0xdc, 0xde, 0xde, 0xde, 0xde, 0xdf, 0xde, 0xdf, 0xe0, 0xe0, + 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, + 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdd, 0xde, 0xdc, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdc, 0xdc, 0xdc, 0xdd, 0xdd, 0xdc, 0xd9, 0xd8, 0xd8, 0xd8, + 0xd9, 0xd9, 0xd7, 0xd7, 0xd7, 0xd7, 0xd6, 0xd6, 0xd6, 0xd5, 0xd4, 0xd3, + 0xd1, 0xd0, 0xce, 0xca, 0xc0, 0xb6, 0xb1, 0xaf, 0xae, 0xad, 0xad, 0xac, + 0xa9, 0xa6, 0xa1, 0x9f, 0x9d, 0x9a, 0x92, 0x86, 0x7a, 0x70, 0x67, 0x72, + 0x7d, 0x81, 0x82, 0x80, 0x7a, 0x74, 0x70, 0x6e, 0x70, 0x73, 0x6b, 0x61, + 0x5d, 0x5c, 0x5a, 0x59, 0x59, 0x5b, 0x62, 0x6c, 0x78, 0x80, 0x7e, 0x6e, + 0x44, 0x2f, 0x42, 0x5b, 0x65, 0x68, 0x64, 0x60, 0x5a, 0x55, 0x52, 0x5e, + 0x5f, 0x5a, 0x56, 0x4f, 0x46, 0x44, 0x4a, 0x53, 0x60, 0x5d, 0x54, 0x4e, + 0x4b, 0x4a, 0x51, 0x58, 0x56, 0x55, 0x57, 0x56, 0x56, 0x57, 0x58, 0x5a, + 0x5d, 0x5e, 0x5e, 0x5e, 0x5d, 0x5d, 0x5e, 0x5f, 0x5f, 0x5d, 0x5e, 0x5d, + 0x5c, 0x5b, 0x5b, 0x59, 0x58, 0x58, 0x58, 0x58, 0x57, 0x58, 0x5a, 0x5b, + 0x5d, 0x60, 0x63, 0x67, 0x69, 0x6a, 0x6c, 0x6f, 0x6d, 0x6a, 0x68, 0x67, + 0x64, 0x60, 0x5e, 0x5d, 0x5c, 0x5b, 0x5a, 0x59, 0x58, 0x56, 0x55, 0x53, + 0x52, 0x50, 0x4f, 0x4d, 0x4c, 0x4b, 0x4b, 0x4b, 0x4d, 0x4f, 0x50, 0x50, + 0x4f, 0x4d, 0x4b, 0x4a, 0x49, 0x4a, 0x4b, 0x4d, 0x4e, 0x4f, 0x50, 0x51, + 0x51, 0x50, 0x50, 0x50, 0x4e, 0x4b, 0x49, 0x48, 0x48, 0x46, 0x44, 0x43, + 0x44, 0x44, 0x43, 0x42, 0x41, 0x42, 0x43, 0x43, 0x5c, 0x58, 0x55, 0x52, + 0x4f, 0x4c, 0x48, 0x45, 0x43, 0x42, 0x40, 0x40, 0x3f, 0x41, 0x48, 0x52, + 0x59, 0x5e, 0x60, 0x63, 0x67, 0x6b, 0x6d, 0x6e, 0x71, 0x77, 0x7c, 0x80, + 0x81, 0x7f, 0x77, 0x7c, 0xaf, 0xc7, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcc, + 0xcd, 0xce, 0xce, 0xce, 0xcf, 0xd0, 0xd1, 0xd1, 0xd1, 0xd0, 0xcf, 0xcf, + 0xd0, 0xd1, 0xd3, 0xd3, 0xd2, 0xd4, 0xd4, 0xd4, 0xd4, 0xd7, 0xd8, 0xd8, + 0xd8, 0xd8, 0xd9, 0xd8, 0xda, 0xda, 0xda, 0xda, 0xdb, 0xdc, 0xdc, 0xdb, + 0xdb, 0xdc, 0xdc, 0xdc, 0xdc, 0xdb, 0xda, 0xdc, 0xdc, 0xdc, 0xdd, 0xdf, + 0xdf, 0xdf, 0xdf, 0xdf, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, + 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdd, 0xdc, 0xdd, 0xde, + 0xdd, 0xde, 0xde, 0xdc, 0xdc, 0xdd, 0xdd, 0xdd, 0xdc, 0xdc, 0xdc, 0xdc, + 0xdc, 0xdc, 0xdc, 0xda, 0xda, 0xd9, 0xd8, 0xd8, 0xd9, 0xd9, 0xd8, 0xd8, + 0xd8, 0xd7, 0xd7, 0xd7, 0xd6, 0xd6, 0xd6, 0xd4, 0xd3, 0xd3, 0xd1, 0xce, + 0xca, 0xc3, 0xbd, 0xb7, 0xb0, 0xac, 0xac, 0xac, 0xaa, 0xa6, 0xa1, 0x9f, + 0x9e, 0x9b, 0x94, 0x8a, 0x80, 0x76, 0x67, 0x6c, 0x78, 0x7f, 0x80, 0x7e, + 0x78, 0x73, 0x70, 0x6f, 0x6f, 0x72, 0x6a, 0x60, 0x5d, 0x5c, 0x5a, 0x59, + 0x5a, 0x5d, 0x63, 0x6d, 0x79, 0x80, 0x7e, 0x6e, 0x47, 0x2b, 0x32, 0x46, + 0x51, 0x5b, 0x5f, 0x5f, 0x5a, 0x54, 0x4f, 0x59, 0x5d, 0x59, 0x55, 0x4e, + 0x44, 0x41, 0x44, 0x4d, 0x5c, 0x5d, 0x56, 0x4f, 0x4b, 0x4a, 0x50, 0x57, + 0x56, 0x55, 0x56, 0x56, 0x56, 0x57, 0x57, 0x59, 0x5d, 0x5e, 0x5e, 0x5d, + 0x5d, 0x5d, 0x5e, 0x5d, 0x5d, 0x5d, 0x5d, 0x5c, 0x5b, 0x5a, 0x5a, 0x59, + 0x58, 0x57, 0x57, 0x58, 0x58, 0x58, 0x5a, 0x5b, 0x5d, 0x61, 0x64, 0x68, + 0x6a, 0x6b, 0x6b, 0x6c, 0x6a, 0x67, 0x65, 0x64, 0x61, 0x5e, 0x5d, 0x5b, + 0x59, 0x58, 0x57, 0x56, 0x55, 0x54, 0x52, 0x50, 0x4e, 0x4d, 0x4b, 0x4a, + 0x4a, 0x4a, 0x4a, 0x4b, 0x4e, 0x50, 0x50, 0x50, 0x4f, 0x4d, 0x4a, 0x49, + 0x49, 0x4a, 0x4c, 0x4e, 0x4f, 0x50, 0x50, 0x50, 0x51, 0x50, 0x50, 0x4f, + 0x4d, 0x4a, 0x49, 0x48, 0x47, 0x45, 0x43, 0x43, 0x43, 0x43, 0x42, 0x41, + 0x41, 0x41, 0x42, 0x42, 0x5b, 0x57, 0x53, 0x51, 0x4e, 0x4b, 0x47, 0x44, + 0x43, 0x42, 0x40, 0x3f, 0x40, 0x41, 0x48, 0x52, 0x5a, 0x5e, 0x60, 0x63, + 0x68, 0x6c, 0x6e, 0x6f, 0x72, 0x78, 0x7d, 0x80, 0x81, 0x7f, 0x77, 0x80, + 0xb3, 0xca, 0xcd, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0xcf, 0xce, + 0xce, 0xd0, 0xd1, 0xd1, 0xd1, 0xd0, 0xcf, 0xcf, 0xcf, 0xd0, 0xd2, 0xd3, + 0xd2, 0xd3, 0xd4, 0xd3, 0xd4, 0xd6, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd8, + 0xd9, 0xda, 0xda, 0xda, 0xdb, 0xdc, 0xdc, 0xdb, 0xdb, 0xdc, 0xdc, 0xdc, + 0xdc, 0xdb, 0xdb, 0xdc, 0xdc, 0xdc, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, + 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, + 0xdf, 0xdf, 0xdf, 0xdf, 0xdd, 0xdc, 0xdc, 0xdd, 0xdc, 0xde, 0xdd, 0xdb, + 0xdb, 0xdd, 0xdd, 0xdd, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xd9, + 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd8, 0xd7, 0xd7, 0xd7, 0xd8, 0xd7, + 0xd6, 0xd6, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd0, 0xcd, 0xc9, 0xc5, 0xbe, + 0xb5, 0xae, 0xac, 0xab, 0xaa, 0xa6, 0xa1, 0x9f, 0x9e, 0x9b, 0x95, 0x8c, + 0x84, 0x7a, 0x69, 0x68, 0x74, 0x7c, 0x7e, 0x7c, 0x77, 0x72, 0x70, 0x6f, + 0x6f, 0x72, 0x69, 0x60, 0x5c, 0x5b, 0x59, 0x59, 0x5a, 0x5d, 0x64, 0x6d, + 0x78, 0x7f, 0x7e, 0x6f, 0x49, 0x2a, 0x2c, 0x39, 0x42, 0x4e, 0x58, 0x5c, + 0x57, 0x52, 0x4c, 0x54, 0x5a, 0x58, 0x54, 0x4d, 0x43, 0x41, 0x43, 0x4a, + 0x58, 0x5c, 0x56, 0x50, 0x4c, 0x4a, 0x50, 0x56, 0x55, 0x54, 0x56, 0x56, + 0x57, 0x57, 0x57, 0x59, 0x5c, 0x5e, 0x5d, 0x5d, 0x5d, 0x5e, 0x5d, 0x5d, + 0x5d, 0x5d, 0x5d, 0x5b, 0x59, 0x59, 0x59, 0x57, 0x57, 0x57, 0x57, 0x58, + 0x57, 0x58, 0x59, 0x5b, 0x5e, 0x62, 0x64, 0x68, 0x6a, 0x6a, 0x6a, 0x69, + 0x67, 0x65, 0x63, 0x62, 0x5f, 0x5d, 0x5b, 0x5a, 0x58, 0x56, 0x55, 0x54, + 0x53, 0x52, 0x51, 0x4f, 0x4c, 0x4b, 0x49, 0x48, 0x48, 0x49, 0x4a, 0x4b, + 0x4e, 0x50, 0x50, 0x50, 0x4f, 0x4d, 0x4a, 0x49, 0x49, 0x4a, 0x4c, 0x4e, + 0x4f, 0x50, 0x50, 0x4f, 0x50, 0x4f, 0x4f, 0x4e, 0x4c, 0x49, 0x48, 0x47, + 0x46, 0x44, 0x43, 0x42, 0x43, 0x42, 0x41, 0x42, 0x41, 0x41, 0x42, 0x42, + 0x59, 0x55, 0x51, 0x4f, 0x4c, 0x49, 0x45, 0x43, 0x42, 0x41, 0x3f, 0x40, + 0x40, 0x42, 0x48, 0x54, 0x5c, 0x5f, 0x61, 0x63, 0x69, 0x6d, 0x6f, 0x70, + 0x73, 0x7a, 0x7f, 0x81, 0x81, 0x7f, 0x78, 0x86, 0xb8, 0xcd, 0xcc, 0xcc, + 0xcd, 0xcc, 0xcc, 0xcb, 0xcc, 0xce, 0xcf, 0xcf, 0xce, 0xcf, 0xd0, 0xd0, + 0xd0, 0xcf, 0xd0, 0xcf, 0xcf, 0xcf, 0xd2, 0xd3, 0xd2, 0xd3, 0xd3, 0xd3, + 0xd5, 0xd5, 0xd6, 0xd7, 0xd9, 0xd9, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, + 0xdb, 0xdc, 0xdc, 0xdb, 0xdb, 0xdc, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, + 0xdc, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xde, 0xde, 0xde, + 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, + 0xdc, 0xdb, 0xdc, 0xdc, 0xdc, 0xdd, 0xdc, 0xdb, 0xdb, 0xdc, 0xdc, 0xdc, + 0xdb, 0xdc, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xd9, 0xd8, 0xd9, 0xda, 0xd9, + 0xd8, 0xd8, 0xd8, 0xd8, 0xd7, 0xd7, 0xd7, 0xd7, 0xd6, 0xd5, 0xd6, 0xd5, + 0xd5, 0xd4, 0xd3, 0xd2, 0xd0, 0xcd, 0xcc, 0xc8, 0xc0, 0xb6, 0xaf, 0xac, + 0xa9, 0xa5, 0xa2, 0xa1, 0xa0, 0x9d, 0x96, 0x8d, 0x86, 0x7e, 0x6f, 0x66, + 0x6d, 0x77, 0x79, 0x78, 0x75, 0x71, 0x6f, 0x6e, 0x6f, 0x71, 0x68, 0x5f, + 0x5b, 0x5a, 0x5a, 0x59, 0x5a, 0x5c, 0x63, 0x6b, 0x75, 0x7b, 0x7b, 0x6e, + 0x4c, 0x2b, 0x28, 0x2c, 0x30, 0x39, 0x48, 0x52, 0x51, 0x4c, 0x46, 0x4a, + 0x54, 0x53, 0x4f, 0x49, 0x41, 0x40, 0x40, 0x45, 0x51, 0x5a, 0x58, 0x52, + 0x4f, 0x4d, 0x50, 0x54, 0x53, 0x53, 0x56, 0x57, 0x58, 0x57, 0x58, 0x59, + 0x5c, 0x5c, 0x5b, 0x5b, 0x5b, 0x5d, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5a, + 0x58, 0x58, 0x58, 0x56, 0x56, 0x57, 0x57, 0x57, 0x57, 0x58, 0x5a, 0x5c, + 0x60, 0x63, 0x65, 0x67, 0x68, 0x68, 0x68, 0x66, 0x64, 0x62, 0x60, 0x5d, + 0x5b, 0x5a, 0x58, 0x57, 0x55, 0x53, 0x52, 0x50, 0x50, 0x4f, 0x4e, 0x4c, + 0x49, 0x48, 0x48, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4f, 0x50, 0x50, 0x4f, + 0x4e, 0x4b, 0x49, 0x49, 0x49, 0x49, 0x4c, 0x4d, 0x4e, 0x4f, 0x4f, 0x4e, + 0x4e, 0x4e, 0x4d, 0x4c, 0x4a, 0x48, 0x46, 0x46, 0x45, 0x44, 0x43, 0x42, + 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x41, 0x41, 0x57, 0x52, 0x4e, 0x4c, + 0x4a, 0x47, 0x44, 0x42, 0x42, 0x40, 0x3f, 0x41, 0x41, 0x42, 0x48, 0x53, + 0x5d, 0x61, 0x63, 0x65, 0x6a, 0x6e, 0x6f, 0x72, 0x76, 0x7d, 0x81, 0x82, + 0x81, 0x7f, 0x7b, 0x90, 0xbe, 0xcf, 0xcd, 0xcc, 0xcd, 0xcd, 0xcc, 0xcb, + 0xcc, 0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xce, 0xce, 0xcf, 0xd0, 0xd0, 0xd0, + 0xcf, 0xcf, 0xd1, 0xd2, 0xd2, 0xd3, 0xd3, 0xd3, 0xd5, 0xd5, 0xd6, 0xd7, + 0xd9, 0xd9, 0xd9, 0xd8, 0xd9, 0xda, 0xda, 0xd9, 0xdb, 0xdc, 0xdc, 0xdb, + 0xdb, 0xdc, 0xdd, 0xdd, 0xdc, 0xde, 0xde, 0xdc, 0xdc, 0xde, 0xdf, 0xdf, + 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, + 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xde, 0xdc, 0xdc, 0xdd, 0xdd, + 0xde, 0xde, 0xdd, 0xdc, 0xdd, 0xdd, 0xdd, 0xdc, 0xdc, 0xdc, 0xdb, 0xdb, + 0xdb, 0xdc, 0xdc, 0xda, 0xd9, 0xd9, 0xda, 0xd9, 0xd9, 0xd9, 0xd9, 0xd8, + 0xd7, 0xd8, 0xd7, 0xd7, 0xd6, 0xd5, 0xd6, 0xd5, 0xd5, 0xd5, 0xd4, 0xd4, + 0xd2, 0xd0, 0xd0, 0xcf, 0xcb, 0xc2, 0xb9, 0xb3, 0xac, 0xa4, 0xa3, 0xa2, + 0xa1, 0x9d, 0x97, 0x8e, 0x89, 0x84, 0x77, 0x66, 0x67, 0x6f, 0x72, 0x72, + 0x72, 0x70, 0x6e, 0x6d, 0x6e, 0x70, 0x66, 0x5d, 0x5a, 0x59, 0x59, 0x59, + 0x59, 0x5b, 0x62, 0x6b, 0x72, 0x76, 0x74, 0x6c, 0x50, 0x2f, 0x28, 0x26, + 0x25, 0x28, 0x38, 0x44, 0x44, 0x40, 0x3a, 0x3b, 0x4a, 0x4c, 0x49, 0x44, + 0x3d, 0x3d, 0x3c, 0x3f, 0x49, 0x54, 0x57, 0x55, 0x53, 0x51, 0x51, 0x53, + 0x52, 0x52, 0x57, 0x58, 0x58, 0x58, 0x59, 0x58, 0x59, 0x5b, 0x5a, 0x5a, + 0x5a, 0x5b, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x59, 0x57, 0x57, 0x57, 0x55, + 0x56, 0x56, 0x57, 0x57, 0x57, 0x58, 0x5b, 0x5d, 0x61, 0x64, 0x66, 0x67, + 0x66, 0x65, 0x64, 0x63, 0x60, 0x5e, 0x5b, 0x58, 0x56, 0x55, 0x54, 0x53, + 0x51, 0x50, 0x4e, 0x4d, 0x4c, 0x4c, 0x4a, 0x47, 0x47, 0x47, 0x46, 0x47, + 0x4a, 0x4b, 0x4c, 0x4d, 0x4f, 0x50, 0x50, 0x4f, 0x4d, 0x4a, 0x49, 0x49, + 0x49, 0x49, 0x4c, 0x4d, 0x4e, 0x4e, 0x4e, 0x4d, 0x4d, 0x4c, 0x4b, 0x4a, + 0x48, 0x47, 0x45, 0x44, 0x44, 0x42, 0x42, 0x41, 0x40, 0x41, 0x42, 0x41, + 0x42, 0x42, 0x41, 0x42, 0x80, 0x72, 0x80, 0x72, 0x7f, 0x72, 0x7f, 0x72, + 0x7f, 0x71, 0x7f, 0x70, 0x7f, 0x70, 0x7f, 0x70, 0x7f, 0x70, 0x7f, 0x70, + 0x7e, 0x71, 0x7d, 0x70, 0x7d, 0x70, 0x7e, 0x70, 0x7f, 0x71, 0x79, 0x6d, + 0x6e, 0x68, 0x5b, 0x64, 0x3f, 0x63, 0x39, 0x62, 0x39, 0x60, 0x3c, 0x5d, + 0x3c, 0x5d, 0x3d, 0x5d, 0x3c, 0x5c, 0x3b, 0x5e, 0x3b, 0x60, 0x3c, 0x5e, + 0x3e, 0x5d, 0x40, 0x5d, 0x41, 0x5a, 0x43, 0x5a, 0x45, 0x5b, 0x46, 0x5c, + 0x47, 0x5c, 0x47, 0x56, 0x46, 0x57, 0x45, 0x57, 0x43, 0x58, 0x41, 0x5a, + 0x40, 0x5b, 0x3e, 0x5a, 0x3e, 0x5b, 0x3f, 0x5c, 0x40, 0x5d, 0x3f, 0x5f, + 0x40, 0x5f, 0x41, 0x5f, 0x42, 0x60, 0x43, 0x5f, 0x43, 0x5f, 0x41, 0x5d, + 0x41, 0x5d, 0x3f, 0x60, 0x3e, 0x61, 0x3e, 0x61, 0x3e, 0x62, 0x3e, 0x61, + 0x3d, 0x60, 0x3e, 0x61, 0x3e, 0x63, 0x3f, 0x64, 0x3e, 0x64, 0x3e, 0x64, + 0x3e, 0x65, 0x40, 0x65, 0x42, 0x66, 0x47, 0x68, 0x4f, 0x6b, 0x55, 0x6b, + 0x57, 0x6c, 0x5a, 0x6d, 0x5a, 0x6e, 0x5a, 0x6e, 0x59, 0x6e, 0x5a, 0x70, + 0x5d, 0x71, 0x60, 0x74, 0x60, 0x75, 0x61, 0x74, 0x60, 0x74, 0x5f, 0x75, + 0x60, 0x76, 0x60, 0x76, 0x5f, 0x75, 0x60, 0x76, 0x62, 0x77, 0x62, 0x77, + 0x63, 0x77, 0x63, 0x78, 0x64, 0x78, 0x64, 0x79, 0x66, 0x7a, 0x67, 0x7a, + 0x68, 0x7a, 0x69, 0x7a, 0x68, 0x7b, 0x68, 0x7b, 0x68, 0x7b, 0x68, 0x7b, + 0x68, 0x7a, 0x64, 0x79, 0x62, 0x79, 0x61, 0x78, 0x5e, 0x77, 0x5f, 0x77, + 0x5f, 0x77, 0x60, 0x77, 0x60, 0x77, 0x5f, 0x77, 0x60, 0x78, 0x5f, 0x78, + 0x5e, 0x77, 0x5e, 0x77, 0x5e, 0x77, 0x5d, 0x77, 0x5d, 0x77, 0x5d, 0x77, + 0x5c, 0x77, 0x5a, 0x77, 0x5a, 0x76, 0x5a, 0x76, 0x57, 0x74, 0x55, 0x72, + 0x50, 0x73, 0x50, 0x73, 0x51, 0x74, 0x55, 0x75, 0x58, 0x75, 0x62, 0x75, + 0x6e, 0x72, 0x76, 0x72, 0x7a, 0x71, 0x7a, 0x71, 0x7a, 0x70, 0x7a, 0x71, + 0x7a, 0x73, 0x7b, 0x72, 0x7b, 0x72, 0x7d, 0x72, 0x7c, 0x71, 0x7c, 0x71, + 0x7d, 0x74, 0x7d, 0x74, 0x7c, 0x75, 0x7d, 0x75, 0x7d, 0x75, 0x7c, 0x79, + 0x7d, 0x7d, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x80, + 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x80, 0x72, 0x80, 0x72, 0x7f, 0x72, 0x7f, 0x72, 0x7f, 0x71, 0x7f, 0x70, + 0x7f, 0x70, 0x7f, 0x70, 0x7f, 0x70, 0x7f, 0x70, 0x7e, 0x70, 0x7d, 0x70, + 0x7e, 0x70, 0x7e, 0x70, 0x7c, 0x70, 0x73, 0x6a, 0x62, 0x66, 0x4b, 0x64, + 0x39, 0x63, 0x37, 0x62, 0x38, 0x60, 0x3a, 0x5e, 0x3b, 0x5e, 0x3b, 0x5e, + 0x3b, 0x5d, 0x3b, 0x5f, 0x3b, 0x5f, 0x3c, 0x5e, 0x3e, 0x5c, 0x40, 0x5c, + 0x42, 0x5a, 0x44, 0x5a, 0x45, 0x5a, 0x46, 0x5a, 0x46, 0x5a, 0x46, 0x57, + 0x45, 0x58, 0x43, 0x58, 0x42, 0x59, 0x40, 0x5c, 0x3f, 0x5d, 0x3e, 0x5c, + 0x3e, 0x5d, 0x3f, 0x5d, 0x40, 0x5e, 0x40, 0x5f, 0x41, 0x5f, 0x42, 0x5f, + 0x42, 0x5f, 0x43, 0x5f, 0x42, 0x5f, 0x41, 0x5e, 0x41, 0x5d, 0x3f, 0x60, + 0x3e, 0x60, 0x3e, 0x61, 0x3e, 0x62, 0x3e, 0x61, 0x3d, 0x60, 0x3e, 0x61, + 0x3e, 0x63, 0x3e, 0x63, 0x3e, 0x63, 0x3e, 0x64, 0x3e, 0x65, 0x40, 0x65, + 0x42, 0x66, 0x47, 0x68, 0x4e, 0x6b, 0x54, 0x6b, 0x55, 0x6c, 0x57, 0x6d, + 0x58, 0x6e, 0x59, 0x6e, 0x5a, 0x6e, 0x5b, 0x70, 0x5e, 0x72, 0x5f, 0x73, + 0x60, 0x75, 0x61, 0x75, 0x60, 0x74, 0x60, 0x75, 0x61, 0x76, 0x60, 0x76, + 0x5f, 0x75, 0x5f, 0x76, 0x60, 0x77, 0x60, 0x77, 0x62, 0x77, 0x62, 0x78, + 0x63, 0x78, 0x63, 0x78, 0x64, 0x7a, 0x64, 0x7a, 0x66, 0x7a, 0x68, 0x7a, + 0x68, 0x7b, 0x68, 0x7b, 0x68, 0x7b, 0x68, 0x7b, 0x67, 0x7a, 0x65, 0x7a, + 0x62, 0x7a, 0x61, 0x78, 0x5e, 0x78, 0x5f, 0x77, 0x5f, 0x77, 0x60, 0x77, + 0x60, 0x77, 0x5f, 0x77, 0x60, 0x78, 0x5f, 0x78, 0x5e, 0x77, 0x5d, 0x77, + 0x5c, 0x78, 0x5c, 0x77, 0x5d, 0x77, 0x5d, 0x77, 0x5c, 0x77, 0x59, 0x77, + 0x59, 0x75, 0x58, 0x76, 0x56, 0x74, 0x55, 0x73, 0x52, 0x73, 0x52, 0x72, + 0x53, 0x74, 0x56, 0x75, 0x5a, 0x75, 0x64, 0x75, 0x70, 0x72, 0x78, 0x72, + 0x7b, 0x71, 0x7b, 0x70, 0x7b, 0x70, 0x7b, 0x72, 0x7a, 0x73, 0x7b, 0x72, + 0x7b, 0x72, 0x7c, 0x72, 0x7c, 0x72, 0x7d, 0x70, 0x7d, 0x73, 0x7d, 0x75, + 0x7c, 0x74, 0x7d, 0x75, 0x7d, 0x75, 0x7c, 0x79, 0x7d, 0x7d, 0x80, 0x7f, + 0x7f, 0x80, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x80, 0x7f, + 0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x72, 0x80, 0x72, + 0x7f, 0x72, 0x7f, 0x72, 0x7f, 0x71, 0x7f, 0x71, 0x7f, 0x70, 0x7f, 0x70, + 0x7f, 0x70, 0x7f, 0x70, 0x7e, 0x71, 0x7d, 0x70, 0x7e, 0x71, 0x7d, 0x70, + 0x79, 0x70, 0x6b, 0x68, 0x54, 0x62, 0x40, 0x63, 0x37, 0x63, 0x37, 0x62, + 0x37, 0x60, 0x39, 0x5f, 0x39, 0x5f, 0x39, 0x5e, 0x39, 0x5f, 0x3a, 0x5f, + 0x3b, 0x5f, 0x3c, 0x5e, 0x3e, 0x5c, 0x40, 0x5c, 0x43, 0x5a, 0x45, 0x5a, + 0x45, 0x59, 0x45, 0x58, 0x45, 0x58, 0x45, 0x58, 0x43, 0x5a, 0x42, 0x5a, + 0x41, 0x5a, 0x3f, 0x5d, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5e, 0x3f, 0x5e, + 0x41, 0x5f, 0x42, 0x5f, 0x43, 0x5f, 0x44, 0x60, 0x44, 0x5f, 0x43, 0x5f, + 0x43, 0x5f, 0x41, 0x5d, 0x40, 0x5d, 0x3f, 0x5f, 0x3e, 0x60, 0x3e, 0x61, + 0x3e, 0x62, 0x3e, 0x61, 0x3e, 0x60, 0x3e, 0x62, 0x3e, 0x63, 0x3e, 0x63, + 0x3e, 0x63, 0x3e, 0x63, 0x3e, 0x65, 0x40, 0x65, 0x43, 0x66, 0x47, 0x68, + 0x4c, 0x6b, 0x52, 0x6b, 0x54, 0x6c, 0x57, 0x6d, 0x57, 0x6e, 0x57, 0x6e, + 0x5a, 0x6e, 0x5c, 0x71, 0x5f, 0x72, 0x5f, 0x72, 0x60, 0x74, 0x60, 0x75, + 0x60, 0x74, 0x61, 0x74, 0x61, 0x76, 0x60, 0x76, 0x5f, 0x75, 0x5f, 0x75, + 0x5f, 0x77, 0x5f, 0x77, 0x60, 0x77, 0x60, 0x77, 0x61, 0x78, 0x63, 0x78, + 0x63, 0x7a, 0x63, 0x7a, 0x64, 0x7a, 0x66, 0x7a, 0x68, 0x7a, 0x68, 0x7b, + 0x68, 0x7b, 0x68, 0x7b, 0x68, 0x7a, 0x65, 0x7a, 0x63, 0x79, 0x61, 0x78, + 0x5f, 0x77, 0x5f, 0x77, 0x60, 0x77, 0x60, 0x77, 0x60, 0x77, 0x5f, 0x77, + 0x60, 0x78, 0x5f, 0x78, 0x5e, 0x77, 0x5c, 0x77, 0x5b, 0x78, 0x5c, 0x78, + 0x5d, 0x77, 0x5d, 0x77, 0x5c, 0x77, 0x59, 0x77, 0x57, 0x76, 0x57, 0x76, + 0x56, 0x74, 0x55, 0x73, 0x54, 0x73, 0x53, 0x73, 0x54, 0x74, 0x57, 0x75, + 0x5b, 0x75, 0x64, 0x74, 0x72, 0x72, 0x7a, 0x71, 0x7b, 0x71, 0x7b, 0x70, + 0x7a, 0x70, 0x7b, 0x72, 0x7b, 0x73, 0x7b, 0x72, 0x7b, 0x72, 0x7c, 0x72, + 0x7c, 0x72, 0x7c, 0x70, 0x7d, 0x73, 0x7c, 0x75, 0x7c, 0x74, 0x7e, 0x75, + 0x7e, 0x75, 0x7c, 0x79, 0x7e, 0x7c, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80, + 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x70, 0x80, 0x71, 0x80, 0x71, 0x80, 0x71, + 0x7f, 0x72, 0x7f, 0x72, 0x7f, 0x71, 0x7f, 0x70, 0x7f, 0x70, 0x7f, 0x70, + 0x7e, 0x71, 0x7e, 0x70, 0x7d, 0x70, 0x7b, 0x6f, 0x74, 0x6e, 0x5d, 0x65, + 0x44, 0x60, 0x39, 0x62, 0x36, 0x62, 0x36, 0x61, 0x37, 0x60, 0x38, 0x5e, + 0x38, 0x5d, 0x38, 0x5e, 0x38, 0x5f, 0x3a, 0x5f, 0x3b, 0x5d, 0x3d, 0x5d, + 0x3f, 0x5b, 0x41, 0x5a, 0x44, 0x5a, 0x45, 0x5a, 0x45, 0x5a, 0x45, 0x5a, + 0x45, 0x59, 0x44, 0x59, 0x43, 0x5a, 0x42, 0x5a, 0x40, 0x5b, 0x3f, 0x5e, + 0x3f, 0x5e, 0x3f, 0x5d, 0x3f, 0x5e, 0x41, 0x60, 0x42, 0x60, 0x43, 0x61, + 0x45, 0x61, 0x46, 0x62, 0x44, 0x61, 0x42, 0x60, 0x43, 0x60, 0x41, 0x5e, + 0x40, 0x5f, 0x3e, 0x61, 0x3e, 0x61, 0x3e, 0x62, 0x3e, 0x63, 0x3f, 0x63, + 0x3e, 0x63, 0x3e, 0x63, 0x3e, 0x63, 0x3e, 0x63, 0x3f, 0x63, 0x3e, 0x64, + 0x3f, 0x65, 0x40, 0x65, 0x44, 0x66, 0x49, 0x68, 0x4d, 0x6a, 0x53, 0x6b, + 0x55, 0x6c, 0x56, 0x6c, 0x55, 0x6d, 0x57, 0x6e, 0x5a, 0x6e, 0x5b, 0x70, + 0x5f, 0x72, 0x5f, 0x73, 0x5f, 0x75, 0x5f, 0x75, 0x5f, 0x75, 0x60, 0x75, + 0x5f, 0x75, 0x5e, 0x75, 0x5d, 0x75, 0x5e, 0x75, 0x60, 0x75, 0x5f, 0x75, + 0x5f, 0x77, 0x5f, 0x77, 0x60, 0x77, 0x62, 0x77, 0x62, 0x79, 0x64, 0x78, + 0x65, 0x79, 0x65, 0x7a, 0x66, 0x7a, 0x68, 0x7a, 0x68, 0x7a, 0x67, 0x7b, + 0x67, 0x7b, 0x66, 0x7a, 0x65, 0x78, 0x64, 0x78, 0x61, 0x78, 0x60, 0x78, + 0x60, 0x79, 0x60, 0x77, 0x60, 0x77, 0x60, 0x77, 0x60, 0x77, 0x5f, 0x78, + 0x5c, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, + 0x5a, 0x77, 0x5a, 0x77, 0x58, 0x77, 0x57, 0x77, 0x56, 0x75, 0x56, 0x75, + 0x56, 0x75, 0x55, 0x74, 0x56, 0x73, 0x59, 0x73, 0x5c, 0x75, 0x67, 0x74, + 0x74, 0x71, 0x79, 0x70, 0x7b, 0x70, 0x7a, 0x70, 0x7b, 0x70, 0x7b, 0x70, + 0x7a, 0x71, 0x7b, 0x73, 0x7a, 0x73, 0x7b, 0x72, 0x7c, 0x72, 0x7d, 0x71, + 0x7c, 0x72, 0x7c, 0x73, 0x7d, 0x73, 0x7d, 0x74, 0x7e, 0x73, 0x7e, 0x75, + 0x7f, 0x7b, 0x80, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x7f, + 0x80, 0x70, 0x80, 0x70, 0x80, 0x70, 0x80, 0x70, 0x7f, 0x72, 0x7f, 0x72, + 0x7f, 0x71, 0x7f, 0x71, 0x7f, 0x70, 0x7f, 0x70, 0x7e, 0x70, 0x7d, 0x70, + 0x7d, 0x70, 0x79, 0x6e, 0x6f, 0x6b, 0x55, 0x63, 0x3e, 0x60, 0x37, 0x62, + 0x36, 0x62, 0x36, 0x61, 0x36, 0x60, 0x37, 0x5e, 0x37, 0x5e, 0x37, 0x5f, + 0x38, 0x5f, 0x3b, 0x5e, 0x3c, 0x5d, 0x3e, 0x5d, 0x40, 0x5b, 0x42, 0x5a, + 0x44, 0x5a, 0x45, 0x5a, 0x44, 0x5a, 0x44, 0x5a, 0x44, 0x5b, 0x43, 0x5b, + 0x42, 0x5a, 0x41, 0x5a, 0x40, 0x5b, 0x3f, 0x5e, 0x3f, 0x5f, 0x40, 0x5d, + 0x40, 0x5f, 0x43, 0x61, 0x44, 0x62, 0x45, 0x62, 0x46, 0x62, 0x46, 0x62, + 0x43, 0x62, 0x42, 0x60, 0x43, 0x60, 0x41, 0x5e, 0x40, 0x60, 0x3e, 0x62, + 0x3f, 0x61, 0x3e, 0x62, 0x3f, 0x64, 0x3f, 0x63, 0x3e, 0x63, 0x3d, 0x63, + 0x3d, 0x63, 0x3e, 0x63, 0x3f, 0x63, 0x3f, 0x64, 0x3f, 0x65, 0x41, 0x65, + 0x44, 0x66, 0x49, 0x68, 0x4d, 0x6a, 0x54, 0x6c, 0x56, 0x6d, 0x56, 0x6c, + 0x55, 0x6d, 0x57, 0x6e, 0x5a, 0x6f, 0x5b, 0x70, 0x5e, 0x72, 0x5f, 0x73, + 0x5f, 0x75, 0x5f, 0x75, 0x5f, 0x75, 0x5f, 0x75, 0x5f, 0x75, 0x5e, 0x75, + 0x5d, 0x75, 0x5e, 0x75, 0x5e, 0x74, 0x5e, 0x74, 0x5e, 0x76, 0x5e, 0x77, + 0x5f, 0x77, 0x60, 0x77, 0x61, 0x78, 0x63, 0x78, 0x64, 0x79, 0x64, 0x7a, + 0x64, 0x7a, 0x67, 0x79, 0x67, 0x7a, 0x67, 0x7b, 0x66, 0x7a, 0x66, 0x79, + 0x66, 0x78, 0x65, 0x78, 0x61, 0x78, 0x60, 0x78, 0x60, 0x78, 0x60, 0x77, + 0x60, 0x77, 0x60, 0x77, 0x60, 0x77, 0x5f, 0x77, 0x5d, 0x77, 0x5c, 0x77, + 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5a, 0x77, 0x5a, 0x77, 0x5a, 0x77, + 0x59, 0x77, 0x57, 0x77, 0x56, 0x75, 0x56, 0x75, 0x56, 0x75, 0x56, 0x75, + 0x58, 0x73, 0x5a, 0x74, 0x5d, 0x76, 0x68, 0x73, 0x74, 0x70, 0x79, 0x70, + 0x7b, 0x70, 0x7b, 0x70, 0x7b, 0x70, 0x7b, 0x70, 0x7b, 0x72, 0x7b, 0x73, + 0x7b, 0x73, 0x7a, 0x72, 0x7b, 0x72, 0x7d, 0x72, 0x7c, 0x72, 0x7d, 0x73, + 0x7d, 0x73, 0x7e, 0x74, 0x7e, 0x72, 0x7d, 0x75, 0x7e, 0x7b, 0x80, 0x7f, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x80, 0x70, 0x80, 0x70, + 0x80, 0x70, 0x80, 0x70, 0x7f, 0x71, 0x7f, 0x72, 0x7f, 0x71, 0x7f, 0x70, + 0x7f, 0x70, 0x7f, 0x70, 0x7e, 0x70, 0x7d, 0x71, 0x7c, 0x70, 0x73, 0x6c, + 0x65, 0x67, 0x48, 0x60, 0x3a, 0x60, 0x38, 0x62, 0x36, 0x62, 0x36, 0x61, + 0x36, 0x60, 0x35, 0x60, 0x36, 0x60, 0x37, 0x5f, 0x39, 0x5f, 0x3b, 0x5e, + 0x3d, 0x5e, 0x3f, 0x5d, 0x42, 0x5b, 0x44, 0x5a, 0x44, 0x5a, 0x44, 0x5a, + 0x44, 0x5a, 0x43, 0x5b, 0x42, 0x5c, 0x42, 0x5d, 0x42, 0x5b, 0x41, 0x5a, + 0x40, 0x5c, 0x3f, 0x5e, 0x40, 0x60, 0x42, 0x61, 0x42, 0x62, 0x45, 0x63, + 0x46, 0x63, 0x47, 0x64, 0x47, 0x63, 0x46, 0x62, 0x44, 0x62, 0x43, 0x60, + 0x43, 0x60, 0x41, 0x60, 0x3f, 0x62, 0x3f, 0x62, 0x3f, 0x62, 0x3e, 0x62, + 0x3e, 0x63, 0x3e, 0x63, 0x3e, 0x63, 0x3e, 0x62, 0x3e, 0x63, 0x3e, 0x63, + 0x3f, 0x64, 0x3e, 0x64, 0x3f, 0x65, 0x41, 0x65, 0x44, 0x66, 0x49, 0x68, + 0x4e, 0x6a, 0x54, 0x6c, 0x56, 0x6d, 0x56, 0x6c, 0x55, 0x6e, 0x57, 0x6e, + 0x5a, 0x6e, 0x5b, 0x70, 0x5e, 0x72, 0x5f, 0x72, 0x5f, 0x74, 0x5f, 0x75, + 0x5f, 0x75, 0x5f, 0x75, 0x5f, 0x75, 0x5e, 0x75, 0x5d, 0x75, 0x5d, 0x74, + 0x5d, 0x75, 0x5c, 0x75, 0x5d, 0x74, 0x5c, 0x75, 0x5c, 0x77, 0x5e, 0x77, + 0x5f, 0x78, 0x61, 0x78, 0x62, 0x7a, 0x62, 0x7a, 0x63, 0x79, 0x65, 0x79, + 0x66, 0x7a, 0x67, 0x7b, 0x67, 0x7a, 0x66, 0x7a, 0x65, 0x79, 0x63, 0x78, + 0x61, 0x78, 0x60, 0x78, 0x60, 0x78, 0x60, 0x77, 0x60, 0x77, 0x60, 0x77, + 0x60, 0x77, 0x5f, 0x77, 0x5d, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, + 0x5b, 0x77, 0x5b, 0x77, 0x5a, 0x77, 0x5a, 0x77, 0x59, 0x77, 0x57, 0x77, + 0x56, 0x76, 0x56, 0x75, 0x58, 0x76, 0x58, 0x76, 0x5a, 0x76, 0x5c, 0x76, + 0x5f, 0x76, 0x6b, 0x73, 0x75, 0x70, 0x79, 0x70, 0x7b, 0x70, 0x7a, 0x70, + 0x7b, 0x70, 0x7b, 0x70, 0x7b, 0x71, 0x7b, 0x73, 0x7b, 0x72, 0x7a, 0x72, + 0x7b, 0x72, 0x7c, 0x72, 0x7c, 0x72, 0x7c, 0x73, 0x7c, 0x73, 0x7e, 0x74, + 0x7d, 0x72, 0x7b, 0x75, 0x7c, 0x7a, 0x7f, 0x7e, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x80, 0x7f, 0x80, 0x7f, 0x80, 0x70, 0x80, 0x70, 0x80, 0x70, 0x7f, 0x70, + 0x7f, 0x71, 0x7f, 0x71, 0x7f, 0x71, 0x7f, 0x70, 0x7f, 0x70, 0x7f, 0x70, + 0x7f, 0x70, 0x7e, 0x70, 0x7c, 0x70, 0x6e, 0x6a, 0x5d, 0x64, 0x3e, 0x61, + 0x37, 0x61, 0x37, 0x62, 0x36, 0x62, 0x35, 0x61, 0x35, 0x61, 0x35, 0x61, + 0x36, 0x61, 0x38, 0x60, 0x3a, 0x5f, 0x3c, 0x5e, 0x3e, 0x5e, 0x40, 0x5c, + 0x43, 0x5b, 0x44, 0x5a, 0x43, 0x5b, 0x43, 0x5b, 0x43, 0x5c, 0x43, 0x5d, + 0x41, 0x5d, 0x41, 0x5e, 0x41, 0x5c, 0x41, 0x5d, 0x40, 0x5f, 0x40, 0x5f, + 0x41, 0x5f, 0x43, 0x61, 0x43, 0x63, 0x45, 0x64, 0x47, 0x64, 0x48, 0x66, + 0x48, 0x65, 0x46, 0x63, 0x44, 0x61, 0x43, 0x61, 0x43, 0x62, 0x40, 0x62, + 0x40, 0x62, 0x3f, 0x63, 0x40, 0x63, 0x3f, 0x63, 0x3e, 0x63, 0x3e, 0x64, + 0x3e, 0x65, 0x3e, 0x64, 0x3e, 0x64, 0x3e, 0x65, 0x3e, 0x65, 0x3e, 0x65, + 0x40, 0x65, 0x41, 0x65, 0x45, 0x68, 0x4a, 0x6a, 0x4e, 0x6b, 0x53, 0x6d, + 0x55, 0x6e, 0x56, 0x6d, 0x56, 0x6f, 0x57, 0x6f, 0x5a, 0x6f, 0x5b, 0x71, + 0x5e, 0x73, 0x5e, 0x72, 0x5f, 0x74, 0x5f, 0x75, 0x5f, 0x75, 0x5e, 0x75, + 0x5d, 0x75, 0x5d, 0x75, 0x5d, 0x75, 0x5c, 0x74, 0x5c, 0x73, 0x5c, 0x73, + 0x5b, 0x75, 0x5b, 0x75, 0x5c, 0x77, 0x5e, 0x77, 0x5e, 0x79, 0x60, 0x79, + 0x61, 0x78, 0x61, 0x78, 0x62, 0x78, 0x63, 0x78, 0x64, 0x79, 0x66, 0x7a, + 0x67, 0x7b, 0x65, 0x7b, 0x65, 0x7a, 0x63, 0x79, 0x62, 0x79, 0x60, 0x77, + 0x60, 0x78, 0x61, 0x77, 0x61, 0x77, 0x5f, 0x77, 0x60, 0x77, 0x5f, 0x77, + 0x5c, 0x77, 0x5b, 0x77, 0x5d, 0x78, 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, + 0x5b, 0x77, 0x5b, 0x77, 0x59, 0x77, 0x57, 0x77, 0x56, 0x76, 0x56, 0x75, + 0x57, 0x75, 0x58, 0x75, 0x5b, 0x76, 0x5d, 0x76, 0x63, 0x75, 0x6d, 0x72, + 0x77, 0x6f, 0x7a, 0x70, 0x7b, 0x6f, 0x7a, 0x6f, 0x7b, 0x70, 0x7b, 0x70, + 0x7a, 0x71, 0x7a, 0x73, 0x7b, 0x72, 0x7b, 0x72, 0x7b, 0x72, 0x7b, 0x72, + 0x7b, 0x72, 0x7b, 0x73, 0x7b, 0x72, 0x7d, 0x72, 0x7d, 0x72, 0x7b, 0x76, + 0x7c, 0x7b, 0x7f, 0x7e, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, + 0x80, 0x70, 0x80, 0x70, 0x7f, 0x70, 0x7f, 0x70, 0x7f, 0x70, 0x7f, 0x70, + 0x7f, 0x70, 0x7f, 0x70, 0x7f, 0x70, 0x7f, 0x70, 0x7f, 0x70, 0x7e, 0x6f, + 0x7a, 0x6e, 0x6a, 0x68, 0x57, 0x63, 0x3b, 0x62, 0x36, 0x62, 0x37, 0x62, + 0x37, 0x62, 0x36, 0x63, 0x35, 0x62, 0x35, 0x61, 0x37, 0x60, 0x39, 0x61, + 0x3b, 0x5f, 0x3e, 0x5d, 0x40, 0x5c, 0x41, 0x5a, 0x43, 0x5a, 0x43, 0x5a, + 0x42, 0x5b, 0x42, 0x5b, 0x42, 0x5d, 0x41, 0x5d, 0x41, 0x5d, 0x41, 0x5d, + 0x41, 0x5c, 0x40, 0x5e, 0x40, 0x61, 0x40, 0x61, 0x41, 0x60, 0x43, 0x63, + 0x44, 0x65, 0x47, 0x66, 0x49, 0x66, 0x49, 0x66, 0x48, 0x66, 0x46, 0x64, + 0x44, 0x61, 0x44, 0x62, 0x43, 0x62, 0x40, 0x63, 0x40, 0x63, 0x40, 0x63, + 0x40, 0x63, 0x40, 0x63, 0x3f, 0x63, 0x3f, 0x64, 0x3e, 0x65, 0x3e, 0x65, + 0x3e, 0x65, 0x3d, 0x65, 0x3d, 0x66, 0x3d, 0x66, 0x40, 0x65, 0x42, 0x66, + 0x48, 0x69, 0x4d, 0x6b, 0x50, 0x6b, 0x53, 0x6e, 0x55, 0x6e, 0x56, 0x6e, + 0x55, 0x6f, 0x58, 0x6f, 0x5a, 0x6f, 0x5b, 0x71, 0x5e, 0x73, 0x5e, 0x73, + 0x5f, 0x74, 0x5f, 0x75, 0x5f, 0x75, 0x5e, 0x75, 0x5d, 0x75, 0x5d, 0x75, + 0x5c, 0x75, 0x5b, 0x74, 0x5b, 0x73, 0x5b, 0x72, 0x59, 0x74, 0x5a, 0x74, + 0x5c, 0x75, 0x5c, 0x75, 0x5d, 0x78, 0x5f, 0x78, 0x60, 0x77, 0x60, 0x77, + 0x61, 0x77, 0x61, 0x77, 0x62, 0x78, 0x64, 0x79, 0x66, 0x7a, 0x66, 0x7b, + 0x65, 0x7a, 0x65, 0x7a, 0x63, 0x79, 0x61, 0x78, 0x61, 0x78, 0x61, 0x78, + 0x60, 0x78, 0x5f, 0x76, 0x5f, 0x77, 0x5f, 0x77, 0x5b, 0x77, 0x5c, 0x77, + 0x5d, 0x77, 0x5c, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, + 0x59, 0x77, 0x57, 0x77, 0x55, 0x75, 0x55, 0x76, 0x55, 0x75, 0x57, 0x76, + 0x5b, 0x76, 0x5e, 0x75, 0x65, 0x74, 0x6f, 0x72, 0x78, 0x6f, 0x7a, 0x6f, + 0x7b, 0x6e, 0x7a, 0x6e, 0x7a, 0x70, 0x7b, 0x70, 0x7b, 0x71, 0x7a, 0x72, + 0x7b, 0x72, 0x7b, 0x72, 0x7b, 0x72, 0x7b, 0x72, 0x7b, 0x72, 0x7a, 0x72, + 0x7a, 0x72, 0x7c, 0x72, 0x7d, 0x72, 0x7b, 0x75, 0x7d, 0x7a, 0x7f, 0x7e, + 0x80, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x71, 0x80, 0x71, + 0x7f, 0x71, 0x7f, 0x70, 0x7f, 0x70, 0x7f, 0x70, 0x7f, 0x70, 0x7f, 0x70, + 0x7f, 0x70, 0x7f, 0x70, 0x7f, 0x6f, 0x7e, 0x6f, 0x7a, 0x6e, 0x65, 0x66, + 0x50, 0x61, 0x39, 0x61, 0x36, 0x61, 0x37, 0x62, 0x37, 0x63, 0x36, 0x62, + 0x35, 0x62, 0x35, 0x60, 0x37, 0x60, 0x3a, 0x61, 0x3d, 0x5f, 0x40, 0x5c, + 0x42, 0x5a, 0x42, 0x58, 0x41, 0x5a, 0x41, 0x5a, 0x41, 0x5b, 0x41, 0x5b, + 0x41, 0x5d, 0x41, 0x5d, 0x41, 0x5d, 0x41, 0x5d, 0x41, 0x5c, 0x41, 0x5d, + 0x40, 0x62, 0x40, 0x63, 0x42, 0x63, 0x43, 0x67, 0x46, 0x68, 0x48, 0x68, + 0x4a, 0x68, 0x49, 0x66, 0x48, 0x66, 0x46, 0x64, 0x44, 0x62, 0x44, 0x63, + 0x43, 0x62, 0x41, 0x63, 0x40, 0x63, 0x40, 0x62, 0x40, 0x63, 0x40, 0x63, + 0x3f, 0x63, 0x3f, 0x64, 0x3f, 0x65, 0x3e, 0x65, 0x3d, 0x65, 0x3d, 0x65, + 0x3d, 0x65, 0x3d, 0x65, 0x40, 0x65, 0x42, 0x66, 0x4a, 0x69, 0x4e, 0x6a, + 0x52, 0x6b, 0x55, 0x6e, 0x56, 0x6e, 0x56, 0x6e, 0x55, 0x6f, 0x58, 0x6f, + 0x5a, 0x6f, 0x5b, 0x71, 0x5d, 0x74, 0x5e, 0x73, 0x5f, 0x74, 0x60, 0x75, + 0x5f, 0x75, 0x5f, 0x75, 0x5e, 0x74, 0x5e, 0x75, 0x5d, 0x75, 0x5b, 0x75, + 0x59, 0x73, 0x59, 0x73, 0x57, 0x72, 0x58, 0x71, 0x5a, 0x72, 0x5b, 0x73, + 0x5b, 0x76, 0x5d, 0x76, 0x5e, 0x77, 0x5d, 0x77, 0x5f, 0x77, 0x5f, 0x77, + 0x5f, 0x78, 0x62, 0x77, 0x65, 0x78, 0x66, 0x78, 0x65, 0x79, 0x65, 0x7a, + 0x64, 0x79, 0x63, 0x78, 0x63, 0x78, 0x60, 0x78, 0x60, 0x78, 0x60, 0x77, + 0x60, 0x77, 0x5f, 0x77, 0x5c, 0x77, 0x5c, 0x77, 0x5d, 0x77, 0x5b, 0x78, + 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x58, 0x77, 0x56, 0x77, + 0x55, 0x75, 0x55, 0x76, 0x56, 0x75, 0x59, 0x75, 0x5b, 0x75, 0x5e, 0x75, + 0x67, 0x74, 0x70, 0x72, 0x78, 0x6f, 0x7a, 0x6f, 0x7b, 0x6f, 0x7b, 0x6f, + 0x7b, 0x70, 0x7b, 0x70, 0x7a, 0x72, 0x7a, 0x73, 0x7a, 0x72, 0x7a, 0x72, + 0x7b, 0x72, 0x7b, 0x73, 0x7b, 0x72, 0x7b, 0x72, 0x7b, 0x72, 0x7d, 0x72, + 0x7d, 0x72, 0x7b, 0x74, 0x7c, 0x76, 0x7f, 0x7e, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x70, 0x7f, 0x70, 0x7f, 0x70, 0x7f, 0x70, + 0x80, 0x70, 0x80, 0x70, 0x7f, 0x70, 0x7f, 0x70, 0x7f, 0x70, 0x7f, 0x70, + 0x7f, 0x70, 0x7e, 0x6f, 0x78, 0x6d, 0x62, 0x64, 0x4b, 0x61, 0x38, 0x62, + 0x36, 0x62, 0x37, 0x61, 0x37, 0x62, 0x36, 0x62, 0x36, 0x62, 0x36, 0x61, + 0x38, 0x60, 0x3b, 0x60, 0x3e, 0x5e, 0x40, 0x5c, 0x42, 0x59, 0x42, 0x59, + 0x41, 0x5b, 0x41, 0x5a, 0x41, 0x5a, 0x41, 0x5a, 0x41, 0x5c, 0x41, 0x5c, + 0x41, 0x5c, 0x40, 0x5d, 0x40, 0x5d, 0x40, 0x5e, 0x40, 0x63, 0x41, 0x65, + 0x42, 0x66, 0x44, 0x68, 0x47, 0x69, 0x49, 0x6a, 0x4a, 0x69, 0x48, 0x66, + 0x47, 0x65, 0x45, 0x64, 0x44, 0x62, 0x44, 0x62, 0x43, 0x62, 0x41, 0x63, + 0x41, 0x62, 0x40, 0x63, 0x41, 0x64, 0x40, 0x63, 0x40, 0x63, 0x3f, 0x63, + 0x3e, 0x64, 0x3d, 0x65, 0x3d, 0x65, 0x3d, 0x65, 0x3d, 0x65, 0x3f, 0x66, + 0x40, 0x66, 0x43, 0x66, 0x4b, 0x69, 0x4f, 0x6b, 0x52, 0x6b, 0x56, 0x6e, + 0x57, 0x6f, 0x57, 0x6e, 0x56, 0x6f, 0x57, 0x6f, 0x5a, 0x70, 0x5b, 0x71, + 0x5d, 0x73, 0x5d, 0x73, 0x5e, 0x73, 0x5e, 0x74, 0x5f, 0x74, 0x5e, 0x74, + 0x5d, 0x74, 0x5e, 0x74, 0x5c, 0x74, 0x5a, 0x73, 0x58, 0x73, 0x57, 0x72, + 0x57, 0x71, 0x57, 0x72, 0x58, 0x72, 0x59, 0x72, 0x59, 0x74, 0x5c, 0x74, + 0x5d, 0x76, 0x5d, 0x76, 0x5e, 0x77, 0x60, 0x77, 0x5f, 0x76, 0x61, 0x76, + 0x64, 0x77, 0x65, 0x78, 0x66, 0x78, 0x65, 0x7a, 0x65, 0x79, 0x64, 0x79, + 0x63, 0x78, 0x60, 0x78, 0x61, 0x78, 0x5f, 0x77, 0x60, 0x77, 0x5f, 0x77, + 0x5c, 0x77, 0x5c, 0x77, 0x5c, 0x77, 0x5c, 0x77, 0x5b, 0x77, 0x5b, 0x77, + 0x5b, 0x77, 0x5b, 0x77, 0x59, 0x77, 0x58, 0x77, 0x56, 0x75, 0x56, 0x75, + 0x56, 0x75, 0x58, 0x75, 0x59, 0x76, 0x5f, 0x75, 0x68, 0x73, 0x71, 0x71, + 0x79, 0x6f, 0x7a, 0x6f, 0x7b, 0x6f, 0x7b, 0x6f, 0x7a, 0x70, 0x7b, 0x70, + 0x7b, 0x71, 0x7b, 0x72, 0x7b, 0x71, 0x7b, 0x72, 0x7b, 0x72, 0x7b, 0x72, + 0x7a, 0x71, 0x7b, 0x72, 0x7b, 0x72, 0x7d, 0x72, 0x7c, 0x71, 0x7b, 0x72, + 0x7d, 0x76, 0x7f, 0x7e, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x7f, 0x7f, + 0x7d, 0x6f, 0x7d, 0x6f, 0x7f, 0x70, 0x7f, 0x70, 0x80, 0x70, 0x80, 0x70, + 0x7f, 0x70, 0x7f, 0x70, 0x7f, 0x70, 0x7f, 0x70, 0x7e, 0x70, 0x7e, 0x6e, + 0x76, 0x6b, 0x5f, 0x63, 0x48, 0x63, 0x36, 0x64, 0x36, 0x62, 0x36, 0x60, + 0x36, 0x60, 0x37, 0x61, 0x37, 0x62, 0x37, 0x60, 0x39, 0x61, 0x3c, 0x5e, + 0x3e, 0x5d, 0x40, 0x5c, 0x41, 0x5b, 0x41, 0x5c, 0x40, 0x5d, 0x40, 0x5c, + 0x41, 0x5b, 0x41, 0x5b, 0x41, 0x5c, 0x41, 0x5c, 0x40, 0x5c, 0x40, 0x5f, + 0x40, 0x60, 0x40, 0x61, 0x40, 0x64, 0x42, 0x67, 0x44, 0x69, 0x46, 0x68, + 0x47, 0x69, 0x48, 0x6a, 0x48, 0x6a, 0x47, 0x68, 0x47, 0x65, 0x45, 0x65, + 0x44, 0x64, 0x44, 0x62, 0x43, 0x62, 0x42, 0x63, 0x42, 0x63, 0x41, 0x65, + 0x41, 0x66, 0x41, 0x64, 0x41, 0x63, 0x40, 0x63, 0x3e, 0x63, 0x3c, 0x65, + 0x3d, 0x66, 0x3d, 0x66, 0x3e, 0x66, 0x41, 0x66, 0x42, 0x67, 0x44, 0x68, + 0x4b, 0x69, 0x50, 0x6b, 0x53, 0x6c, 0x57, 0x6f, 0x58, 0x6f, 0x59, 0x6f, + 0x57, 0x6f, 0x58, 0x6f, 0x5a, 0x71, 0x5b, 0x72, 0x5c, 0x71, 0x5c, 0x71, + 0x5d, 0x72, 0x5d, 0x73, 0x5e, 0x73, 0x5d, 0x72, 0x5d, 0x73, 0x5d, 0x72, + 0x5b, 0x72, 0x5a, 0x72, 0x57, 0x72, 0x56, 0x72, 0x57, 0x72, 0x57, 0x73, + 0x57, 0x73, 0x56, 0x73, 0x57, 0x73, 0x5a, 0x73, 0x5c, 0x74, 0x5c, 0x74, + 0x5c, 0x75, 0x60, 0x76, 0x5f, 0x75, 0x61, 0x77, 0x62, 0x79, 0x64, 0x78, + 0x66, 0x79, 0x66, 0x7a, 0x66, 0x7a, 0x65, 0x7a, 0x63, 0x79, 0x60, 0x78, + 0x60, 0x78, 0x5f, 0x77, 0x60, 0x77, 0x5e, 0x77, 0x5d, 0x77, 0x5d, 0x77, + 0x5d, 0x77, 0x5d, 0x77, 0x5d, 0x77, 0x5c, 0x77, 0x5b, 0x77, 0x5b, 0x77, + 0x5a, 0x77, 0x5a, 0x77, 0x58, 0x75, 0x58, 0x75, 0x57, 0x74, 0x57, 0x74, + 0x59, 0x76, 0x61, 0x73, 0x69, 0x73, 0x73, 0x70, 0x7a, 0x6f, 0x7a, 0x6f, + 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x70, 0x7b, 0x70, + 0x7b, 0x70, 0x7b, 0x72, 0x7a, 0x71, 0x7a, 0x70, 0x7a, 0x70, 0x7b, 0x73, + 0x7a, 0x72, 0x7d, 0x71, 0x7d, 0x70, 0x7c, 0x70, 0x7e, 0x76, 0x7f, 0x7e, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x7f, 0x7e, 0x6f, 0x7e, 0x6f, + 0x7f, 0x70, 0x7f, 0x70, 0x80, 0x70, 0x80, 0x70, 0x7f, 0x70, 0x7f, 0x70, + 0x7f, 0x70, 0x7f, 0x71, 0x7f, 0x70, 0x7d, 0x6e, 0x76, 0x6b, 0x5e, 0x63, + 0x46, 0x63, 0x36, 0x64, 0x36, 0x61, 0x36, 0x60, 0x36, 0x61, 0x37, 0x63, + 0x37, 0x62, 0x37, 0x61, 0x3a, 0x60, 0x3d, 0x5e, 0x3e, 0x5d, 0x3f, 0x5d, + 0x3f, 0x5d, 0x40, 0x5d, 0x40, 0x5e, 0x41, 0x5e, 0x41, 0x5e, 0x41, 0x5d, + 0x41, 0x5e, 0x41, 0x5d, 0x41, 0x5e, 0x40, 0x61, 0x40, 0x64, 0x40, 0x65, + 0x41, 0x66, 0x43, 0x68, 0x47, 0x6b, 0x48, 0x6b, 0x48, 0x6a, 0x48, 0x6a, + 0x48, 0x6a, 0x46, 0x67, 0x46, 0x65, 0x44, 0x65, 0x44, 0x64, 0x43, 0x64, + 0x43, 0x63, 0x42, 0x66, 0x41, 0x65, 0x41, 0x64, 0x40, 0x65, 0x40, 0x63, + 0x41, 0x63, 0x40, 0x62, 0x3e, 0x63, 0x3d, 0x65, 0x3d, 0x66, 0x3d, 0x66, + 0x3e, 0x65, 0x41, 0x65, 0x44, 0x67, 0x46, 0x68, 0x4d, 0x69, 0x52, 0x6b, + 0x55, 0x6c, 0x58, 0x6f, 0x5a, 0x6f, 0x5b, 0x6f, 0x59, 0x6e, 0x59, 0x6f, + 0x5b, 0x72, 0x5c, 0x73, 0x5d, 0x72, 0x5d, 0x72, 0x5d, 0x72, 0x5e, 0x73, + 0x5e, 0x73, 0x5e, 0x73, 0x5d, 0x73, 0x5d, 0x72, 0x5b, 0x72, 0x5a, 0x72, + 0x57, 0x72, 0x55, 0x72, 0x56, 0x72, 0x55, 0x72, 0x55, 0x73, 0x55, 0x73, + 0x56, 0x73, 0x59, 0x73, 0x5b, 0x75, 0x5a, 0x75, 0x5b, 0x75, 0x5e, 0x76, + 0x5f, 0x75, 0x60, 0x77, 0x62, 0x79, 0x64, 0x78, 0x66, 0x79, 0x66, 0x7a, + 0x66, 0x7a, 0x65, 0x7a, 0x62, 0x79, 0x60, 0x78, 0x61, 0x78, 0x5f, 0x77, + 0x5f, 0x78, 0x5e, 0x77, 0x5d, 0x77, 0x5d, 0x77, 0x5d, 0x77, 0x5d, 0x77, + 0x5d, 0x77, 0x5c, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5a, 0x77, 0x59, 0x77, + 0x57, 0x75, 0x57, 0x75, 0x57, 0x75, 0x58, 0x74, 0x5a, 0x76, 0x62, 0x73, + 0x6a, 0x73, 0x74, 0x71, 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x70, + 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x70, 0x7a, 0x71, 0x7b, 0x71, 0x7b, 0x73, + 0x7a, 0x71, 0x7a, 0x70, 0x7a, 0x71, 0x7a, 0x73, 0x7a, 0x72, 0x7c, 0x6f, + 0x7c, 0x70, 0x7c, 0x71, 0x7d, 0x75, 0x7f, 0x7e, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x7f, 0x80, 0x7f, 0x7d, 0x6f, 0x7d, 0x6f, 0x7f, 0x70, 0x7f, 0x70, + 0x80, 0x70, 0x80, 0x70, 0x7f, 0x70, 0x7f, 0x70, 0x7f, 0x70, 0x7f, 0x6f, + 0x7e, 0x70, 0x7e, 0x6f, 0x73, 0x6b, 0x5b, 0x64, 0x45, 0x63, 0x35, 0x63, + 0x36, 0x61, 0x36, 0x60, 0x37, 0x60, 0x37, 0x61, 0x37, 0x61, 0x38, 0x60, + 0x3a, 0x60, 0x3c, 0x5e, 0x3e, 0x5d, 0x3e, 0x5e, 0x3e, 0x5e, 0x3f, 0x5e, + 0x40, 0x5f, 0x40, 0x5e, 0x41, 0x5f, 0x41, 0x5e, 0x41, 0x60, 0x41, 0x5f, + 0x40, 0x60, 0x40, 0x62, 0x40, 0x65, 0x40, 0x67, 0x43, 0x67, 0x46, 0x69, + 0x4a, 0x6b, 0x4c, 0x6c, 0x4a, 0x6a, 0x47, 0x6a, 0x46, 0x69, 0x45, 0x67, + 0x45, 0x65, 0x44, 0x64, 0x43, 0x65, 0x43, 0x65, 0x43, 0x65, 0x42, 0x67, + 0x42, 0x66, 0x41, 0x64, 0x41, 0x65, 0x40, 0x63, 0x40, 0x63, 0x3f, 0x62, + 0x3d, 0x64, 0x3c, 0x65, 0x3c, 0x66, 0x3d, 0x66, 0x3e, 0x66, 0x42, 0x66, + 0x45, 0x67, 0x47, 0x67, 0x4e, 0x6a, 0x53, 0x6b, 0x56, 0x6e, 0x5a, 0x6f, + 0x5c, 0x70, 0x5b, 0x6f, 0x5b, 0x6f, 0x5b, 0x6f, 0x5b, 0x71, 0x5b, 0x72, + 0x5c, 0x72, 0x5d, 0x73, 0x5d, 0x73, 0x5e, 0x73, 0x5e, 0x73, 0x5d, 0x73, + 0x5c, 0x73, 0x5c, 0x73, 0x5a, 0x72, 0x59, 0x72, 0x57, 0x72, 0x55, 0x72, + 0x54, 0x72, 0x54, 0x72, 0x53, 0x72, 0x54, 0x73, 0x56, 0x73, 0x58, 0x73, + 0x59, 0x74, 0x59, 0x74, 0x5a, 0x74, 0x5c, 0x74, 0x5e, 0x75, 0x60, 0x77, + 0x61, 0x78, 0x63, 0x78, 0x66, 0x79, 0x65, 0x7b, 0x65, 0x7a, 0x65, 0x7a, + 0x63, 0x7a, 0x61, 0x78, 0x61, 0x78, 0x5f, 0x78, 0x60, 0x78, 0x5f, 0x77, + 0x5d, 0x77, 0x5c, 0x77, 0x5d, 0x77, 0x5c, 0x77, 0x5c, 0x77, 0x5c, 0x77, + 0x5b, 0x77, 0x5b, 0x77, 0x5a, 0x77, 0x59, 0x76, 0x58, 0x75, 0x58, 0x75, + 0x57, 0x75, 0x57, 0x75, 0x5b, 0x75, 0x64, 0x74, 0x6c, 0x72, 0x75, 0x70, + 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x6f, + 0x7a, 0x6f, 0x7a, 0x71, 0x7a, 0x71, 0x7b, 0x71, 0x7a, 0x71, 0x7a, 0x70, + 0x7a, 0x70, 0x7a, 0x72, 0x7a, 0x72, 0x7d, 0x6f, 0x7d, 0x71, 0x7c, 0x72, + 0x7d, 0x75, 0x7f, 0x7e, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x7f, 0x80, 0x7f, + 0x7b, 0x70, 0x7c, 0x70, 0x7d, 0x70, 0x7e, 0x6f, 0x7e, 0x70, 0x7e, 0x70, + 0x7f, 0x70, 0x7f, 0x70, 0x7f, 0x70, 0x7f, 0x6f, 0x7e, 0x6f, 0x7c, 0x6e, + 0x6f, 0x6b, 0x58, 0x65, 0x43, 0x63, 0x35, 0x62, 0x35, 0x60, 0x36, 0x60, + 0x37, 0x60, 0x38, 0x60, 0x39, 0x60, 0x39, 0x60, 0x3a, 0x5f, 0x3b, 0x5f, + 0x3c, 0x5f, 0x3d, 0x5f, 0x3d, 0x5f, 0x3e, 0x5f, 0x3f, 0x5f, 0x40, 0x5f, + 0x41, 0x5f, 0x41, 0x5f, 0x40, 0x61, 0x40, 0x62, 0x3f, 0x63, 0x3e, 0x65, + 0x41, 0x65, 0x43, 0x67, 0x47, 0x69, 0x4b, 0x6a, 0x4e, 0x6c, 0x4e, 0x6b, + 0x4c, 0x6a, 0x46, 0x6a, 0x43, 0x6a, 0x44, 0x67, 0x44, 0x65, 0x44, 0x65, + 0x42, 0x65, 0x42, 0x65, 0x42, 0x66, 0x41, 0x66, 0x41, 0x66, 0x41, 0x65, + 0x41, 0x65, 0x42, 0x64, 0x3f, 0x63, 0x3f, 0x62, 0x3d, 0x65, 0x3b, 0x66, + 0x3b, 0x65, 0x3d, 0x66, 0x3f, 0x68, 0x41, 0x67, 0x46, 0x66, 0x48, 0x67, + 0x4f, 0x6b, 0x53, 0x6e, 0x58, 0x70, 0x5c, 0x70, 0x5e, 0x70, 0x5b, 0x70, + 0x5b, 0x71, 0x5b, 0x71, 0x5b, 0x71, 0x5b, 0x70, 0x5c, 0x72, 0x5d, 0x73, + 0x5d, 0x73, 0x5d, 0x73, 0x5d, 0x73, 0x5c, 0x73, 0x5b, 0x72, 0x5b, 0x72, + 0x59, 0x72, 0x58, 0x72, 0x56, 0x72, 0x53, 0x72, 0x53, 0x72, 0x53, 0x72, + 0x53, 0x72, 0x53, 0x72, 0x55, 0x73, 0x56, 0x73, 0x55, 0x73, 0x57, 0x73, + 0x59, 0x72, 0x5b, 0x72, 0x5c, 0x72, 0x5e, 0x76, 0x5f, 0x77, 0x62, 0x78, + 0x64, 0x7b, 0x65, 0x7b, 0x64, 0x7b, 0x64, 0x7a, 0x65, 0x7a, 0x63, 0x77, + 0x60, 0x78, 0x5f, 0x79, 0x60, 0x79, 0x5f, 0x78, 0x5c, 0x77, 0x5d, 0x77, + 0x5d, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5c, 0x78, 0x5c, 0x77, + 0x5a, 0x77, 0x5a, 0x76, 0x58, 0x76, 0x58, 0x76, 0x57, 0x75, 0x57, 0x75, + 0x5c, 0x75, 0x66, 0x74, 0x6e, 0x70, 0x75, 0x70, 0x7a, 0x6f, 0x7a, 0x70, + 0x7a, 0x6e, 0x7a, 0x6e, 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x71, + 0x7a, 0x70, 0x7a, 0x70, 0x7b, 0x70, 0x7b, 0x70, 0x7b, 0x70, 0x7b, 0x71, + 0x7a, 0x70, 0x7d, 0x6f, 0x7d, 0x71, 0x7d, 0x71, 0x7c, 0x74, 0x7e, 0x7d, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x7f, 0x80, 0x7f, 0x80, 0x80, 0x7f, 0x7f, 0x7a, 0x6f, 0x7a, 0x6f, + 0x7b, 0x6f, 0x7c, 0x6f, 0x7e, 0x70, 0x7f, 0x70, 0x7f, 0x70, 0x7f, 0x70, + 0x7e, 0x70, 0x7d, 0x6f, 0x7d, 0x6f, 0x7b, 0x6c, 0x6e, 0x69, 0x57, 0x65, + 0x41, 0x63, 0x35, 0x62, 0x35, 0x60, 0x36, 0x60, 0x37, 0x61, 0x38, 0x60, + 0x39, 0x60, 0x39, 0x61, 0x3a, 0x60, 0x3a, 0x61, 0x3b, 0x61, 0x3c, 0x60, + 0x3d, 0x60, 0x3e, 0x60, 0x3f, 0x60, 0x3f, 0x60, 0x41, 0x60, 0x40, 0x60, + 0x40, 0x62, 0x3f, 0x63, 0x3e, 0x64, 0x3f, 0x66, 0x45, 0x67, 0x47, 0x69, + 0x4b, 0x69, 0x4d, 0x6c, 0x50, 0x6d, 0x4f, 0x6d, 0x4d, 0x6b, 0x47, 0x6a, + 0x44, 0x6a, 0x44, 0x67, 0x44, 0x65, 0x44, 0x65, 0x43, 0x65, 0x43, 0x65, + 0x42, 0x65, 0x41, 0x66, 0x41, 0x66, 0x41, 0x65, 0x41, 0x65, 0x42, 0x64, + 0x3f, 0x63, 0x3f, 0x62, 0x3d, 0x64, 0x3b, 0x66, 0x3d, 0x65, 0x3f, 0x67, + 0x40, 0x68, 0x43, 0x68, 0x47, 0x68, 0x49, 0x68, 0x50, 0x6b, 0x55, 0x6e, + 0x58, 0x70, 0x5c, 0x70, 0x5e, 0x70, 0x5b, 0x70, 0x5b, 0x70, 0x5c, 0x70, + 0x5b, 0x70, 0x5b, 0x70, 0x5c, 0x72, 0x5d, 0x73, 0x5d, 0x73, 0x5d, 0x73, + 0x5d, 0x73, 0x5c, 0x73, 0x5b, 0x72, 0x5b, 0x72, 0x59, 0x72, 0x58, 0x72, + 0x56, 0x72, 0x53, 0x72, 0x53, 0x72, 0x53, 0x72, 0x53, 0x72, 0x53, 0x72, + 0x54, 0x73, 0x55, 0x73, 0x54, 0x73, 0x56, 0x73, 0x58, 0x73, 0x5b, 0x72, + 0x5c, 0x72, 0x5e, 0x76, 0x5f, 0x76, 0x62, 0x78, 0x64, 0x7b, 0x65, 0x7b, + 0x64, 0x7b, 0x65, 0x7a, 0x65, 0x7a, 0x63, 0x77, 0x60, 0x77, 0x5f, 0x78, + 0x60, 0x78, 0x60, 0x77, 0x5c, 0x77, 0x5c, 0x77, 0x5d, 0x77, 0x5c, 0x77, + 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5a, 0x77, 0x5a, 0x77, + 0x59, 0x75, 0x58, 0x75, 0x59, 0x75, 0x58, 0x75, 0x5e, 0x74, 0x67, 0x74, + 0x6f, 0x71, 0x77, 0x70, 0x7a, 0x70, 0x7a, 0x6f, 0x7a, 0x6e, 0x7a, 0x6e, + 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x70, 0x7a, 0x70, 0x7a, 0x70, 0x7a, 0x70, + 0x7b, 0x70, 0x7a, 0x70, 0x7a, 0x70, 0x7b, 0x70, 0x7b, 0x70, 0x7c, 0x6f, + 0x7d, 0x71, 0x7d, 0x71, 0x7c, 0x74, 0x7e, 0x7d, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, + 0x80, 0x80, 0x7f, 0x80, 0x79, 0x6f, 0x79, 0x6f, 0x7a, 0x6f, 0x7a, 0x6f, + 0x7d, 0x70, 0x7f, 0x70, 0x7f, 0x70, 0x7f, 0x70, 0x7d, 0x70, 0x7c, 0x6f, + 0x7b, 0x6e, 0x79, 0x6b, 0x6c, 0x68, 0x54, 0x65, 0x40, 0x63, 0x35, 0x62, + 0x35, 0x60, 0x36, 0x60, 0x38, 0x60, 0x39, 0x5f, 0x38, 0x60, 0x39, 0x62, + 0x39, 0x62, 0x3a, 0x61, 0x3a, 0x62, 0x3c, 0x62, 0x3d, 0x62, 0x3e, 0x63, + 0x3f, 0x62, 0x3f, 0x62, 0x40, 0x62, 0x40, 0x62, 0x3f, 0x64, 0x3e, 0x65, + 0x40, 0x66, 0x46, 0x68, 0x4b, 0x69, 0x4d, 0x6b, 0x4f, 0x6c, 0x51, 0x6d, + 0x52, 0x6e, 0x51, 0x6e, 0x4e, 0x6c, 0x49, 0x6a, 0x44, 0x6a, 0x43, 0x67, + 0x43, 0x65, 0x43, 0x65, 0x43, 0x65, 0x43, 0x66, 0x42, 0x65, 0x42, 0x65, + 0x41, 0x65, 0x42, 0x64, 0x41, 0x64, 0x41, 0x63, 0x3f, 0x63, 0x3f, 0x62, + 0x3d, 0x64, 0x3b, 0x66, 0x3e, 0x65, 0x41, 0x66, 0x43, 0x67, 0x46, 0x69, + 0x49, 0x6a, 0x4b, 0x6a, 0x52, 0x6b, 0x57, 0x6e, 0x59, 0x71, 0x5c, 0x71, + 0x5d, 0x70, 0x5b, 0x70, 0x5b, 0x71, 0x5b, 0x71, 0x5b, 0x71, 0x5c, 0x71, + 0x5c, 0x72, 0x5c, 0x73, 0x5d, 0x73, 0x5d, 0x73, 0x5d, 0x73, 0x5c, 0x73, + 0x5b, 0x73, 0x5b, 0x73, 0x59, 0x72, 0x58, 0x72, 0x57, 0x72, 0x54, 0x72, + 0x53, 0x72, 0x53, 0x72, 0x53, 0x72, 0x52, 0x72, 0x53, 0x72, 0x53, 0x72, + 0x53, 0x73, 0x54, 0x73, 0x57, 0x73, 0x5b, 0x72, 0x5b, 0x73, 0x5e, 0x75, + 0x5f, 0x76, 0x61, 0x77, 0x64, 0x7a, 0x64, 0x7b, 0x65, 0x7b, 0x64, 0x7a, + 0x64, 0x7a, 0x63, 0x78, 0x61, 0x78, 0x5f, 0x77, 0x60, 0x78, 0x60, 0x78, + 0x5d, 0x77, 0x5c, 0x77, 0x5d, 0x77, 0x5c, 0x78, 0x5b, 0x77, 0x5a, 0x77, + 0x5a, 0x77, 0x5a, 0x77, 0x5a, 0x77, 0x5a, 0x77, 0x58, 0x76, 0x58, 0x76, + 0x59, 0x75, 0x5b, 0x75, 0x60, 0x74, 0x6a, 0x73, 0x72, 0x70, 0x78, 0x70, + 0x79, 0x6f, 0x79, 0x6f, 0x7a, 0x6e, 0x7a, 0x6e, 0x7a, 0x6f, 0x7a, 0x6f, + 0x7a, 0x70, 0x7a, 0x70, 0x7a, 0x70, 0x7a, 0x70, 0x7b, 0x70, 0x7b, 0x71, + 0x7b, 0x71, 0x7b, 0x71, 0x7b, 0x71, 0x7c, 0x6f, 0x7c, 0x71, 0x7c, 0x70, + 0x7c, 0x74, 0x7e, 0x7d, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x7f, 0x80, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, + 0x78, 0x6f, 0x79, 0x6f, 0x79, 0x6f, 0x7c, 0x6f, 0x7e, 0x6f, 0x7e, 0x6f, + 0x7f, 0x6f, 0x7e, 0x6f, 0x7c, 0x70, 0x7b, 0x6f, 0x78, 0x6d, 0x76, 0x6b, + 0x69, 0x66, 0x52, 0x63, 0x3f, 0x63, 0x35, 0x62, 0x35, 0x60, 0x36, 0x60, + 0x38, 0x60, 0x38, 0x5f, 0x39, 0x60, 0x39, 0x63, 0x39, 0x62, 0x39, 0x63, + 0x3a, 0x64, 0x3a, 0x65, 0x3b, 0x65, 0x3d, 0x65, 0x3e, 0x64, 0x3e, 0x64, + 0x3f, 0x64, 0x3f, 0x64, 0x3d, 0x65, 0x3f, 0x68, 0x44, 0x68, 0x4c, 0x6a, + 0x50, 0x6c, 0x50, 0x6c, 0x51, 0x6d, 0x52, 0x6d, 0x53, 0x6e, 0x51, 0x6e, + 0x4f, 0x6d, 0x4a, 0x6b, 0x45, 0x69, 0x42, 0x68, 0x42, 0x67, 0x42, 0x66, + 0x42, 0x67, 0x41, 0x67, 0x41, 0x68, 0x42, 0x66, 0x42, 0x64, 0x42, 0x64, + 0x41, 0x62, 0x40, 0x62, 0x3f, 0x62, 0x3e, 0x62, 0x3c, 0x65, 0x3b, 0x66, + 0x3e, 0x66, 0x43, 0x65, 0x46, 0x67, 0x47, 0x69, 0x49, 0x6b, 0x4d, 0x6b, + 0x51, 0x6b, 0x56, 0x6e, 0x5a, 0x72, 0x5c, 0x72, 0x5c, 0x72, 0x5b, 0x72, + 0x5a, 0x70, 0x59, 0x70, 0x5b, 0x71, 0x5c, 0x72, 0x5b, 0x72, 0x5b, 0x72, + 0x5b, 0x72, 0x5b, 0x72, 0x5b, 0x71, 0x5b, 0x73, 0x5b, 0x73, 0x5c, 0x72, + 0x59, 0x71, 0x58, 0x72, 0x57, 0x72, 0x54, 0x72, 0x53, 0x72, 0x53, 0x72, + 0x53, 0x72, 0x51, 0x72, 0x52, 0x72, 0x53, 0x72, 0x52, 0x72, 0x54, 0x72, + 0x57, 0x73, 0x59, 0x72, 0x5c, 0x74, 0x5e, 0x75, 0x5f, 0x77, 0x60, 0x78, + 0x63, 0x78, 0x64, 0x7a, 0x64, 0x7a, 0x63, 0x7a, 0x63, 0x7a, 0x62, 0x7a, + 0x62, 0x7a, 0x60, 0x77, 0x60, 0x78, 0x60, 0x78, 0x60, 0x78, 0x5e, 0x78, + 0x5d, 0x77, 0x5b, 0x77, 0x5a, 0x77, 0x5a, 0x77, 0x5a, 0x77, 0x5a, 0x77, + 0x5a, 0x77, 0x59, 0x77, 0x58, 0x77, 0x58, 0x77, 0x5a, 0x76, 0x5e, 0x75, + 0x64, 0x75, 0x6d, 0x71, 0x75, 0x6f, 0x78, 0x6f, 0x78, 0x6f, 0x78, 0x6f, + 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x6f, + 0x7a, 0x70, 0x7a, 0x72, 0x7a, 0x72, 0x7b, 0x72, 0x7b, 0x73, 0x7b, 0x73, + 0x7b, 0x72, 0x7b, 0x71, 0x7b, 0x70, 0x7c, 0x70, 0x7c, 0x74, 0x7e, 0x7c, + 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x7f, + 0x80, 0x80, 0x80, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x77, 0x6f, 0x77, 0x6f, + 0x78, 0x6f, 0x7b, 0x6f, 0x7c, 0x6f, 0x7c, 0x6f, 0x7d, 0x6e, 0x7b, 0x6e, + 0x79, 0x6e, 0x78, 0x6d, 0x76, 0x6b, 0x74, 0x6a, 0x67, 0x65, 0x50, 0x63, + 0x3e, 0x63, 0x36, 0x63, 0x36, 0x60, 0x37, 0x60, 0x38, 0x60, 0x38, 0x60, + 0x39, 0x62, 0x39, 0x64, 0x38, 0x64, 0x38, 0x65, 0x38, 0x66, 0x39, 0x66, + 0x39, 0x67, 0x3b, 0x67, 0x3d, 0x65, 0x3d, 0x65, 0x3d, 0x65, 0x3d, 0x65, + 0x3e, 0x67, 0x44, 0x69, 0x4b, 0x6a, 0x50, 0x6c, 0x53, 0x6d, 0x53, 0x6d, + 0x53, 0x6e, 0x53, 0x6f, 0x53, 0x6e, 0x51, 0x6e, 0x4f, 0x6d, 0x4a, 0x6b, + 0x46, 0x69, 0x42, 0x68, 0x41, 0x68, 0x42, 0x68, 0x41, 0x68, 0x41, 0x67, + 0x41, 0x68, 0x42, 0x67, 0x42, 0x65, 0x42, 0x64, 0x41, 0x62, 0x40, 0x61, + 0x3f, 0x62, 0x3e, 0x62, 0x3c, 0x64, 0x3c, 0x66, 0x3f, 0x66, 0x44, 0x66, + 0x45, 0x67, 0x47, 0x69, 0x4a, 0x6a, 0x4e, 0x6c, 0x52, 0x6c, 0x57, 0x6f, + 0x5a, 0x72, 0x5c, 0x72, 0x5b, 0x72, 0x5b, 0x72, 0x5a, 0x70, 0x5a, 0x70, + 0x5b, 0x72, 0x5c, 0x73, 0x5b, 0x72, 0x5b, 0x72, 0x5b, 0x72, 0x5b, 0x72, + 0x5b, 0x72, 0x5b, 0x72, 0x5b, 0x73, 0x5c, 0x72, 0x5a, 0x72, 0x57, 0x72, + 0x56, 0x72, 0x54, 0x72, 0x53, 0x72, 0x53, 0x72, 0x53, 0x72, 0x51, 0x72, + 0x51, 0x72, 0x50, 0x72, 0x50, 0x72, 0x52, 0x72, 0x55, 0x72, 0x58, 0x72, + 0x5a, 0x74, 0x5d, 0x75, 0x5f, 0x77, 0x60, 0x78, 0x63, 0x79, 0x64, 0x7a, + 0x63, 0x7a, 0x63, 0x7a, 0x63, 0x7a, 0x62, 0x79, 0x62, 0x7a, 0x60, 0x77, + 0x60, 0x78, 0x60, 0x78, 0x60, 0x78, 0x5e, 0x77, 0x5c, 0x77, 0x5b, 0x77, + 0x5a, 0x77, 0x5a, 0x77, 0x5a, 0x77, 0x5a, 0x77, 0x5b, 0x77, 0x5a, 0x77, + 0x59, 0x77, 0x59, 0x77, 0x5d, 0x75, 0x62, 0x75, 0x67, 0x75, 0x70, 0x72, + 0x75, 0x6f, 0x78, 0x6f, 0x78, 0x6f, 0x78, 0x6f, 0x79, 0x6f, 0x7a, 0x6f, + 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x70, 0x7a, 0x72, + 0x7a, 0x72, 0x7a, 0x72, 0x7b, 0x73, 0x7b, 0x73, 0x7b, 0x72, 0x7a, 0x71, + 0x7b, 0x70, 0x7c, 0x70, 0x7c, 0x74, 0x7e, 0x7d, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x80, 0x80, 0x80, 0x80, 0x75, 0x6f, 0x75, 0x6f, 0x76, 0x6f, 0x79, 0x6f, + 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x6d, 0x78, 0x6c, 0x75, 0x6c, 0x74, 0x6b, + 0x71, 0x69, 0x6f, 0x67, 0x63, 0x64, 0x4e, 0x63, 0x3d, 0x63, 0x36, 0x62, + 0x36, 0x60, 0x37, 0x60, 0x38, 0x60, 0x38, 0x61, 0x39, 0x64, 0x38, 0x66, + 0x39, 0x66, 0x37, 0x66, 0x37, 0x67, 0x38, 0x68, 0x38, 0x69, 0x3a, 0x69, + 0x3b, 0x66, 0x3c, 0x67, 0x3c, 0x67, 0x3c, 0x67, 0x40, 0x69, 0x4a, 0x6b, + 0x52, 0x6c, 0x54, 0x6e, 0x57, 0x6f, 0x57, 0x6f, 0x55, 0x70, 0x55, 0x70, + 0x54, 0x6f, 0x52, 0x6e, 0x4f, 0x6d, 0x4a, 0x6b, 0x46, 0x69, 0x43, 0x68, + 0x41, 0x69, 0x40, 0x6a, 0x41, 0x6a, 0x41, 0x67, 0x40, 0x68, 0x42, 0x68, + 0x42, 0x65, 0x41, 0x64, 0x41, 0x63, 0x3f, 0x62, 0x3e, 0x62, 0x3d, 0x62, + 0x3c, 0x64, 0x3c, 0x66, 0x42, 0x66, 0x45, 0x66, 0x45, 0x68, 0x47, 0x69, + 0x4c, 0x6a, 0x50, 0x6c, 0x55, 0x6e, 0x59, 0x71, 0x5a, 0x72, 0x5c, 0x72, + 0x5b, 0x72, 0x5b, 0x72, 0x5a, 0x70, 0x5a, 0x70, 0x5b, 0x72, 0x5b, 0x72, + 0x5b, 0x72, 0x5b, 0x72, 0x5b, 0x72, 0x5b, 0x72, 0x5b, 0x72, 0x5c, 0x72, + 0x5c, 0x73, 0x5c, 0x72, 0x5a, 0x72, 0x57, 0x72, 0x56, 0x72, 0x54, 0x71, + 0x53, 0x72, 0x53, 0x72, 0x54, 0x72, 0x51, 0x72, 0x4f, 0x72, 0x4f, 0x72, + 0x4f, 0x72, 0x51, 0x72, 0x53, 0x72, 0x56, 0x72, 0x58, 0x74, 0x5b, 0x75, + 0x5f, 0x76, 0x61, 0x78, 0x63, 0x79, 0x64, 0x7a, 0x63, 0x7a, 0x63, 0x7a, + 0x63, 0x7a, 0x62, 0x79, 0x62, 0x7a, 0x60, 0x78, 0x60, 0x78, 0x60, 0x78, + 0x5f, 0x78, 0x5e, 0x78, 0x5c, 0x77, 0x5b, 0x77, 0x5a, 0x77, 0x5a, 0x77, + 0x5a, 0x77, 0x5a, 0x77, 0x5a, 0x77, 0x5a, 0x77, 0x5b, 0x77, 0x5c, 0x77, + 0x61, 0x76, 0x66, 0x76, 0x6b, 0x75, 0x73, 0x72, 0x76, 0x6f, 0x78, 0x6f, + 0x79, 0x6e, 0x78, 0x6f, 0x79, 0x6f, 0x7a, 0x6f, 0x7a, 0x70, 0x7a, 0x6f, + 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x70, 0x7a, 0x72, 0x7a, 0x72, 0x7a, 0x72, + 0x7b, 0x72, 0x7a, 0x72, 0x7a, 0x73, 0x7b, 0x71, 0x7b, 0x70, 0x7c, 0x70, + 0x7c, 0x73, 0x7e, 0x7d, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x80, 0x80, 0x80, 0x80, + 0x74, 0x6e, 0x73, 0x6e, 0x75, 0x6f, 0x77, 0x6f, 0x79, 0x6f, 0x78, 0x6f, + 0x77, 0x6d, 0x75, 0x6b, 0x73, 0x6a, 0x71, 0x6a, 0x6e, 0x67, 0x6c, 0x66, + 0x61, 0x63, 0x4a, 0x62, 0x3c, 0x61, 0x36, 0x62, 0x35, 0x63, 0x36, 0x61, + 0x37, 0x61, 0x38, 0x63, 0x39, 0x65, 0x38, 0x64, 0x37, 0x66, 0x37, 0x68, + 0x36, 0x69, 0x37, 0x69, 0x38, 0x69, 0x39, 0x69, 0x3a, 0x68, 0x3a, 0x69, + 0x3c, 0x69, 0x3f, 0x68, 0x45, 0x6a, 0x4d, 0x6d, 0x53, 0x6e, 0x55, 0x6f, + 0x57, 0x70, 0x58, 0x70, 0x56, 0x70, 0x56, 0x70, 0x54, 0x70, 0x51, 0x6d, + 0x50, 0x6d, 0x4b, 0x6a, 0x46, 0x68, 0x44, 0x69, 0x41, 0x69, 0x40, 0x69, + 0x41, 0x69, 0x41, 0x68, 0x41, 0x68, 0x42, 0x67, 0x41, 0x65, 0x41, 0x63, + 0x40, 0x63, 0x3f, 0x62, 0x3d, 0x63, 0x3d, 0x63, 0x3b, 0x65, 0x3d, 0x67, + 0x42, 0x67, 0x46, 0x67, 0x46, 0x68, 0x49, 0x69, 0x4c, 0x6c, 0x51, 0x6d, + 0x56, 0x6f, 0x59, 0x72, 0x5b, 0x72, 0x5c, 0x72, 0x5b, 0x72, 0x5a, 0x72, + 0x59, 0x70, 0x59, 0x70, 0x5a, 0x71, 0x5b, 0x70, 0x5b, 0x71, 0x5c, 0x70, + 0x5b, 0x71, 0x5a, 0x72, 0x5a, 0x72, 0x5b, 0x72, 0x5c, 0x72, 0x5b, 0x72, + 0x5a, 0x72, 0x59, 0x72, 0x57, 0x72, 0x56, 0x72, 0x54, 0x72, 0x54, 0x72, + 0x54, 0x72, 0x50, 0x72, 0x4f, 0x70, 0x50, 0x71, 0x4f, 0x72, 0x52, 0x72, + 0x54, 0x73, 0x57, 0x72, 0x59, 0x73, 0x5b, 0x75, 0x5e, 0x76, 0x60, 0x77, + 0x62, 0x78, 0x61, 0x79, 0x62, 0x79, 0x63, 0x7a, 0x62, 0x7a, 0x62, 0x79, + 0x62, 0x7a, 0x60, 0x78, 0x5f, 0x78, 0x5f, 0x78, 0x60, 0x78, 0x5e, 0x78, + 0x5c, 0x78, 0x5b, 0x77, 0x5b, 0x77, 0x5a, 0x77, 0x59, 0x77, 0x59, 0x77, + 0x59, 0x78, 0x5b, 0x77, 0x5d, 0x76, 0x5e, 0x76, 0x63, 0x76, 0x68, 0x74, + 0x6d, 0x73, 0x75, 0x71, 0x77, 0x6f, 0x77, 0x6f, 0x78, 0x6e, 0x78, 0x6e, + 0x79, 0x6f, 0x79, 0x70, 0x78, 0x70, 0x79, 0x6f, 0x79, 0x6f, 0x7a, 0x6f, + 0x7a, 0x6f, 0x7a, 0x71, 0x7a, 0x71, 0x7b, 0x71, 0x7b, 0x71, 0x7b, 0x72, + 0x7b, 0x72, 0x7b, 0x70, 0x7b, 0x70, 0x7c, 0x70, 0x7c, 0x74, 0x7e, 0x7c, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x72, 0x6d, 0x72, 0x6e, + 0x74, 0x6e, 0x75, 0x6e, 0x76, 0x6d, 0x73, 0x6d, 0x72, 0x6b, 0x70, 0x68, + 0x6d, 0x67, 0x6b, 0x65, 0x68, 0x63, 0x68, 0x63, 0x5d, 0x61, 0x46, 0x5f, + 0x3c, 0x5f, 0x37, 0x62, 0x35, 0x64, 0x36, 0x63, 0x37, 0x63, 0x38, 0x65, + 0x39, 0x66, 0x38, 0x64, 0x37, 0x67, 0x36, 0x6a, 0x37, 0x6b, 0x39, 0x6a, + 0x3b, 0x6b, 0x3a, 0x6b, 0x38, 0x6a, 0x39, 0x6a, 0x3c, 0x6a, 0x43, 0x6a, + 0x4a, 0x6c, 0x50, 0x6f, 0x54, 0x70, 0x56, 0x70, 0x57, 0x70, 0x57, 0x70, + 0x56, 0x70, 0x56, 0x70, 0x54, 0x70, 0x51, 0x6d, 0x50, 0x6c, 0x4a, 0x69, + 0x45, 0x68, 0x44, 0x6a, 0x42, 0x69, 0x42, 0x68, 0x41, 0x68, 0x41, 0x68, + 0x41, 0x68, 0x41, 0x65, 0x41, 0x63, 0x41, 0x62, 0x40, 0x62, 0x3e, 0x63, + 0x3c, 0x63, 0x3c, 0x63, 0x3b, 0x66, 0x3e, 0x68, 0x42, 0x68, 0x47, 0x68, + 0x49, 0x68, 0x4b, 0x68, 0x4e, 0x6c, 0x52, 0x6d, 0x57, 0x6f, 0x59, 0x72, + 0x5b, 0x73, 0x5c, 0x72, 0x5a, 0x72, 0x5a, 0x72, 0x59, 0x70, 0x58, 0x70, + 0x59, 0x71, 0x59, 0x71, 0x59, 0x70, 0x5a, 0x70, 0x5a, 0x71, 0x5b, 0x73, + 0x5a, 0x72, 0x5b, 0x72, 0x5b, 0x72, 0x5a, 0x72, 0x5b, 0x72, 0x5a, 0x72, + 0x58, 0x72, 0x57, 0x73, 0x55, 0x72, 0x55, 0x72, 0x53, 0x72, 0x50, 0x72, + 0x50, 0x70, 0x50, 0x70, 0x4e, 0x72, 0x50, 0x73, 0x54, 0x72, 0x57, 0x72, + 0x59, 0x73, 0x5c, 0x75, 0x5c, 0x77, 0x5f, 0x77, 0x60, 0x77, 0x60, 0x77, + 0x61, 0x78, 0x62, 0x7a, 0x62, 0x7a, 0x62, 0x7a, 0x62, 0x79, 0x60, 0x78, + 0x5e, 0x78, 0x5e, 0x78, 0x5e, 0x78, 0x5e, 0x78, 0x5d, 0x78, 0x5b, 0x78, + 0x5b, 0x77, 0x59, 0x77, 0x58, 0x77, 0x58, 0x77, 0x5a, 0x77, 0x5d, 0x77, + 0x5f, 0x75, 0x61, 0x75, 0x67, 0x74, 0x6c, 0x72, 0x71, 0x71, 0x76, 0x6f, + 0x78, 0x6f, 0x77, 0x6f, 0x77, 0x6e, 0x77, 0x6e, 0x78, 0x6f, 0x78, 0x6f, + 0x78, 0x6f, 0x78, 0x6f, 0x79, 0x6f, 0x7a, 0x6f, 0x7a, 0x6f, 0x7b, 0x70, + 0x7a, 0x70, 0x7a, 0x70, 0x7b, 0x71, 0x7b, 0x72, 0x7b, 0x73, 0x7b, 0x70, + 0x7b, 0x70, 0x7c, 0x71, 0x7d, 0x75, 0x7e, 0x7c, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x7f, 0x80, 0x7f, 0x70, 0x6e, 0x70, 0x6d, 0x73, 0x6c, 0x73, 0x6c, + 0x73, 0x6b, 0x71, 0x6b, 0x6e, 0x69, 0x6b, 0x67, 0x68, 0x64, 0x66, 0x62, + 0x63, 0x60, 0x61, 0x5f, 0x55, 0x5d, 0x43, 0x5d, 0x3d, 0x5d, 0x39, 0x62, + 0x37, 0x64, 0x36, 0x64, 0x37, 0x64, 0x38, 0x65, 0x39, 0x65, 0x38, 0x65, + 0x37, 0x68, 0x36, 0x6b, 0x38, 0x6c, 0x3e, 0x6c, 0x3e, 0x6c, 0x3d, 0x6c, + 0x3b, 0x6c, 0x3b, 0x6c, 0x42, 0x6c, 0x49, 0x6c, 0x4d, 0x6d, 0x53, 0x71, + 0x56, 0x72, 0x58, 0x71, 0x58, 0x70, 0x57, 0x70, 0x56, 0x70, 0x56, 0x70, + 0x54, 0x70, 0x52, 0x6d, 0x50, 0x6c, 0x49, 0x69, 0x43, 0x69, 0x43, 0x6a, + 0x42, 0x6a, 0x44, 0x68, 0x43, 0x68, 0x41, 0x68, 0x41, 0x68, 0x41, 0x64, + 0x41, 0x61, 0x40, 0x60, 0x40, 0x60, 0x3f, 0x62, 0x3c, 0x63, 0x3b, 0x62, + 0x3c, 0x66, 0x40, 0x68, 0x42, 0x68, 0x48, 0x67, 0x4b, 0x68, 0x4d, 0x68, + 0x50, 0x6b, 0x54, 0x6d, 0x57, 0x6e, 0x59, 0x72, 0x5b, 0x73, 0x5b, 0x72, + 0x5b, 0x72, 0x5a, 0x72, 0x59, 0x71, 0x58, 0x71, 0x57, 0x71, 0x57, 0x71, + 0x58, 0x70, 0x58, 0x71, 0x59, 0x71, 0x5b, 0x73, 0x5b, 0x73, 0x5b, 0x73, + 0x5c, 0x73, 0x5a, 0x72, 0x5a, 0x72, 0x59, 0x72, 0x57, 0x72, 0x57, 0x73, + 0x55, 0x72, 0x55, 0x72, 0x53, 0x72, 0x50, 0x72, 0x50, 0x70, 0x50, 0x70, + 0x4d, 0x72, 0x4f, 0x72, 0x53, 0x72, 0x57, 0x72, 0x59, 0x73, 0x5c, 0x75, + 0x5c, 0x77, 0x5f, 0x77, 0x61, 0x77, 0x60, 0x78, 0x61, 0x78, 0x62, 0x7a, + 0x62, 0x7a, 0x62, 0x7a, 0x62, 0x79, 0x60, 0x78, 0x5e, 0x78, 0x5d, 0x78, + 0x5c, 0x78, 0x5d, 0x78, 0x5d, 0x78, 0x5b, 0x77, 0x5b, 0x77, 0x59, 0x76, + 0x58, 0x77, 0x59, 0x77, 0x5c, 0x78, 0x5e, 0x77, 0x61, 0x75, 0x63, 0x76, + 0x6a, 0x73, 0x6f, 0x70, 0x75, 0x70, 0x76, 0x6d, 0x77, 0x6f, 0x77, 0x6f, + 0x77, 0x6e, 0x77, 0x6e, 0x78, 0x6e, 0x78, 0x6f, 0x78, 0x6f, 0x78, 0x6f, + 0x79, 0x6f, 0x7a, 0x6e, 0x7a, 0x6f, 0x7a, 0x71, 0x7a, 0x70, 0x7a, 0x70, + 0x7b, 0x70, 0x7b, 0x72, 0x7b, 0x72, 0x7b, 0x71, 0x7a, 0x70, 0x7c, 0x71, + 0x7c, 0x75, 0x7e, 0x7c, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x7f, 0x80, 0x7f, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x7f, 0x80, 0x7f, + 0x6f, 0x6d, 0x6f, 0x6d, 0x71, 0x6d, 0x70, 0x6b, 0x70, 0x6a, 0x6e, 0x68, + 0x6a, 0x67, 0x67, 0x65, 0x63, 0x62, 0x61, 0x5f, 0x5a, 0x5e, 0x56, 0x5d, + 0x4d, 0x5c, 0x43, 0x5c, 0x3f, 0x5c, 0x3a, 0x62, 0x37, 0x65, 0x36, 0x65, + 0x37, 0x65, 0x37, 0x65, 0x38, 0x66, 0x37, 0x68, 0x37, 0x6a, 0x37, 0x6c, + 0x3a, 0x6d, 0x40, 0x6d, 0x41, 0x6d, 0x42, 0x6c, 0x41, 0x6c, 0x42, 0x6d, + 0x48, 0x6e, 0x4e, 0x6e, 0x51, 0x70, 0x55, 0x71, 0x58, 0x72, 0x58, 0x71, + 0x58, 0x71, 0x57, 0x71, 0x56, 0x70, 0x56, 0x70, 0x54, 0x6f, 0x51, 0x6d, + 0x4d, 0x6b, 0x46, 0x6a, 0x45, 0x6a, 0x44, 0x6a, 0x44, 0x6a, 0x45, 0x69, + 0x42, 0x6a, 0x40, 0x69, 0x41, 0x68, 0x41, 0x64, 0x41, 0x62, 0x40, 0x61, + 0x3f, 0x61, 0x3d, 0x62, 0x3c, 0x64, 0x3b, 0x65, 0x3d, 0x67, 0x41, 0x68, + 0x44, 0x68, 0x49, 0x69, 0x4b, 0x69, 0x4d, 0x6a, 0x50, 0x6c, 0x54, 0x6e, + 0x57, 0x6f, 0x59, 0x71, 0x5b, 0x72, 0x5b, 0x72, 0x5a, 0x72, 0x59, 0x72, + 0x57, 0x71, 0x57, 0x71, 0x57, 0x70, 0x56, 0x70, 0x56, 0x70, 0x56, 0x70, + 0x57, 0x70, 0x58, 0x71, 0x59, 0x72, 0x5a, 0x71, 0x5b, 0x71, 0x5a, 0x71, + 0x5b, 0x72, 0x59, 0x72, 0x57, 0x72, 0x58, 0x72, 0x57, 0x72, 0x56, 0x72, + 0x54, 0x72, 0x51, 0x72, 0x50, 0x70, 0x50, 0x70, 0x4d, 0x72, 0x4e, 0x72, + 0x51, 0x72, 0x55, 0x72, 0x57, 0x73, 0x5a, 0x75, 0x5c, 0x77, 0x5e, 0x77, + 0x60, 0x78, 0x60, 0x78, 0x62, 0x79, 0x62, 0x79, 0x63, 0x79, 0x62, 0x7a, + 0x62, 0x7a, 0x60, 0x78, 0x5d, 0x78, 0x5b, 0x77, 0x5b, 0x77, 0x5c, 0x78, + 0x5d, 0x78, 0x5c, 0x77, 0x5c, 0x77, 0x5a, 0x77, 0x59, 0x77, 0x5a, 0x77, + 0x5c, 0x76, 0x5e, 0x76, 0x63, 0x76, 0x66, 0x75, 0x6e, 0x71, 0x71, 0x70, + 0x76, 0x6f, 0x76, 0x6e, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x70, 0x77, 0x6f, + 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x78, 0x6f, 0x78, 0x6f, 0x7a, 0x70, + 0x7a, 0x70, 0x7a, 0x71, 0x7a, 0x70, 0x7a, 0x70, 0x7a, 0x70, 0x7a, 0x71, + 0x7a, 0x71, 0x7b, 0x70, 0x7a, 0x72, 0x7b, 0x73, 0x7b, 0x75, 0x7d, 0x7c, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x80, + 0x7f, 0x80, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x6d, 0x6d, 0x6d, 0x6d, + 0x6e, 0x6d, 0x6c, 0x6a, 0x6b, 0x68, 0x69, 0x65, 0x65, 0x63, 0x60, 0x61, + 0x5c, 0x5f, 0x57, 0x5d, 0x4e, 0x5a, 0x4c, 0x58, 0x4b, 0x59, 0x45, 0x5a, + 0x41, 0x5b, 0x3c, 0x61, 0x38, 0x67, 0x36, 0x67, 0x36, 0x67, 0x36, 0x67, + 0x37, 0x68, 0x37, 0x6b, 0x38, 0x6b, 0x3a, 0x6d, 0x3e, 0x6e, 0x41, 0x6d, + 0x44, 0x6e, 0x45, 0x6d, 0x47, 0x6e, 0x49, 0x70, 0x4d, 0x70, 0x51, 0x70, + 0x54, 0x72, 0x57, 0x72, 0x59, 0x72, 0x58, 0x72, 0x58, 0x72, 0x59, 0x72, + 0x57, 0x70, 0x56, 0x71, 0x53, 0x6f, 0x4f, 0x6d, 0x4b, 0x6b, 0x44, 0x6a, + 0x47, 0x6b, 0x45, 0x6a, 0x46, 0x6a, 0x45, 0x6a, 0x42, 0x6a, 0x40, 0x69, + 0x41, 0x66, 0x40, 0x63, 0x40, 0x61, 0x3e, 0x62, 0x3e, 0x62, 0x3c, 0x62, + 0x3b, 0x65, 0x3a, 0x66, 0x3d, 0x67, 0x41, 0x68, 0x45, 0x68, 0x49, 0x69, + 0x4a, 0x6a, 0x4d, 0x6b, 0x50, 0x6e, 0x54, 0x6f, 0x56, 0x71, 0x59, 0x70, + 0x5a, 0x72, 0x5b, 0x72, 0x5a, 0x72, 0x57, 0x72, 0x56, 0x71, 0x56, 0x70, + 0x56, 0x70, 0x56, 0x70, 0x56, 0x70, 0x55, 0x70, 0x55, 0x70, 0x56, 0x70, + 0x57, 0x70, 0x59, 0x70, 0x5a, 0x70, 0x5a, 0x71, 0x5b, 0x72, 0x5a, 0x72, + 0x58, 0x72, 0x58, 0x72, 0x59, 0x73, 0x56, 0x72, 0x55, 0x72, 0x52, 0x72, + 0x50, 0x70, 0x50, 0x70, 0x4e, 0x72, 0x4d, 0x72, 0x50, 0x72, 0x54, 0x73, + 0x56, 0x74, 0x59, 0x76, 0x5b, 0x77, 0x5d, 0x77, 0x5e, 0x77, 0x5f, 0x78, + 0x62, 0x79, 0x62, 0x78, 0x62, 0x78, 0x63, 0x7a, 0x63, 0x7a, 0x60, 0x78, + 0x5e, 0x78, 0x5b, 0x77, 0x5b, 0x76, 0x5c, 0x77, 0x5c, 0x78, 0x5b, 0x78, + 0x5b, 0x77, 0x5b, 0x78, 0x5a, 0x77, 0x5b, 0x76, 0x5e, 0x75, 0x62, 0x76, + 0x67, 0x75, 0x6b, 0x73, 0x72, 0x71, 0x74, 0x70, 0x77, 0x6f, 0x77, 0x6f, + 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x71, 0x77, 0x71, 0x77, 0x70, 0x77, 0x6f, + 0x77, 0x6f, 0x78, 0x6e, 0x79, 0x6f, 0x7a, 0x70, 0x7a, 0x70, 0x7a, 0x70, + 0x7a, 0x70, 0x7a, 0x70, 0x7a, 0x70, 0x7a, 0x70, 0x7a, 0x70, 0x7b, 0x70, + 0x7a, 0x72, 0x7a, 0x74, 0x7a, 0x74, 0x7d, 0x7b, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x7f, + 0x80, 0x7f, 0x80, 0x7f, 0x6b, 0x6d, 0x6c, 0x6d, 0x6c, 0x6c, 0x69, 0x69, + 0x67, 0x67, 0x64, 0x65, 0x60, 0x61, 0x5b, 0x5e, 0x53, 0x5c, 0x4d, 0x5c, + 0x4b, 0x57, 0x4c, 0x54, 0x4c, 0x54, 0x47, 0x55, 0x43, 0x59, 0x3d, 0x61, + 0x39, 0x66, 0x37, 0x69, 0x36, 0x69, 0x36, 0x69, 0x36, 0x69, 0x36, 0x6a, + 0x39, 0x6a, 0x3d, 0x6d, 0x41, 0x6e, 0x44, 0x6d, 0x45, 0x6d, 0x47, 0x6e, + 0x4b, 0x6f, 0x4d, 0x71, 0x50, 0x71, 0x54, 0x71, 0x55, 0x73, 0x58, 0x73, + 0x59, 0x74, 0x59, 0x74, 0x58, 0x72, 0x59, 0x72, 0x57, 0x70, 0x56, 0x70, + 0x53, 0x70, 0x4e, 0x6d, 0x49, 0x6b, 0x44, 0x6b, 0x47, 0x6b, 0x47, 0x6a, + 0x46, 0x6a, 0x44, 0x69, 0x42, 0x6a, 0x40, 0x68, 0x41, 0x65, 0x40, 0x62, + 0x40, 0x60, 0x3e, 0x61, 0x3e, 0x62, 0x3c, 0x61, 0x3a, 0x64, 0x3a, 0x66, + 0x3d, 0x67, 0x41, 0x67, 0x45, 0x68, 0x4a, 0x69, 0x4a, 0x6a, 0x4c, 0x6a, + 0x4f, 0x6e, 0x54, 0x6f, 0x56, 0x71, 0x59, 0x70, 0x5b, 0x72, 0x5a, 0x72, + 0x5a, 0x72, 0x57, 0x72, 0x56, 0x71, 0x56, 0x70, 0x56, 0x70, 0x56, 0x71, + 0x56, 0x71, 0x56, 0x71, 0x56, 0x70, 0x57, 0x70, 0x57, 0x70, 0x5a, 0x70, + 0x5b, 0x70, 0x5b, 0x71, 0x5b, 0x72, 0x5a, 0x72, 0x58, 0x72, 0x58, 0x72, + 0x58, 0x72, 0x55, 0x72, 0x54, 0x72, 0x52, 0x72, 0x50, 0x70, 0x50, 0x70, + 0x4e, 0x73, 0x4d, 0x72, 0x50, 0x73, 0x54, 0x73, 0x56, 0x74, 0x5a, 0x75, + 0x5c, 0x77, 0x5e, 0x77, 0x5f, 0x78, 0x60, 0x78, 0x62, 0x78, 0x62, 0x78, + 0x62, 0x78, 0x62, 0x7a, 0x62, 0x7a, 0x61, 0x78, 0x5e, 0x78, 0x5b, 0x77, + 0x5b, 0x77, 0x5c, 0x78, 0x5d, 0x78, 0x5c, 0x78, 0x5b, 0x78, 0x5c, 0x78, + 0x5b, 0x77, 0x5c, 0x76, 0x60, 0x75, 0x66, 0x76, 0x6a, 0x74, 0x6e, 0x72, + 0x75, 0x70, 0x77, 0x70, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, + 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x6f, 0x77, 0x6f, 0x78, 0x6f, + 0x79, 0x6f, 0x7a, 0x70, 0x7b, 0x70, 0x7a, 0x71, 0x7a, 0x70, 0x7a, 0x70, + 0x7a, 0x70, 0x7a, 0x70, 0x7a, 0x70, 0x7b, 0x70, 0x7b, 0x72, 0x7a, 0x74, + 0x7a, 0x75, 0x7d, 0x7b, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x80, 0x7f, + 0x6a, 0x6c, 0x68, 0x6b, 0x69, 0x69, 0x65, 0x66, 0x62, 0x64, 0x5e, 0x62, + 0x58, 0x5f, 0x51, 0x5c, 0x49, 0x5a, 0x47, 0x59, 0x4a, 0x54, 0x4c, 0x51, + 0x4d, 0x50, 0x4a, 0x53, 0x46, 0x56, 0x40, 0x5f, 0x3c, 0x65, 0x39, 0x68, + 0x37, 0x6b, 0x38, 0x6b, 0x3a, 0x6a, 0x3b, 0x6b, 0x3b, 0x6b, 0x40, 0x6c, + 0x43, 0x6d, 0x47, 0x6e, 0x48, 0x6f, 0x4b, 0x6f, 0x4f, 0x71, 0x51, 0x73, + 0x53, 0x72, 0x56, 0x72, 0x57, 0x74, 0x59, 0x75, 0x58, 0x75, 0x58, 0x75, + 0x58, 0x73, 0x57, 0x72, 0x56, 0x71, 0x55, 0x70, 0x51, 0x6f, 0x4d, 0x6d, + 0x4a, 0x6b, 0x47, 0x6b, 0x48, 0x6b, 0x48, 0x6a, 0x46, 0x6b, 0x43, 0x6a, + 0x40, 0x68, 0x40, 0x65, 0x41, 0x62, 0x40, 0x60, 0x40, 0x5f, 0x3e, 0x62, + 0x3e, 0x62, 0x3c, 0x61, 0x3b, 0x65, 0x3b, 0x67, 0x3e, 0x67, 0x42, 0x68, + 0x46, 0x68, 0x49, 0x6a, 0x4b, 0x6b, 0x4d, 0x6a, 0x4f, 0x6c, 0x53, 0x6f, + 0x56, 0x71, 0x58, 0x70, 0x5a, 0x72, 0x59, 0x72, 0x59, 0x72, 0x57, 0x71, + 0x56, 0x71, 0x56, 0x70, 0x56, 0x70, 0x56, 0x71, 0x56, 0x71, 0x55, 0x71, + 0x55, 0x70, 0x55, 0x70, 0x57, 0x70, 0x59, 0x71, 0x59, 0x71, 0x59, 0x72, + 0x59, 0x72, 0x59, 0x71, 0x59, 0x72, 0x58, 0x72, 0x58, 0x72, 0x56, 0x72, + 0x55, 0x72, 0x53, 0x72, 0x50, 0x71, 0x50, 0x72, 0x4e, 0x73, 0x4d, 0x72, + 0x50, 0x73, 0x54, 0x73, 0x56, 0x74, 0x58, 0x75, 0x5b, 0x77, 0x5d, 0x77, + 0x5f, 0x77, 0x5f, 0x78, 0x61, 0x78, 0x62, 0x78, 0x62, 0x78, 0x62, 0x79, + 0x62, 0x79, 0x60, 0x78, 0x5e, 0x77, 0x5c, 0x77, 0x5b, 0x77, 0x5c, 0x78, + 0x5c, 0x78, 0x5b, 0x77, 0x5b, 0x77, 0x5d, 0x77, 0x5e, 0x76, 0x5f, 0x76, + 0x65, 0x75, 0x6a, 0x75, 0x6f, 0x72, 0x73, 0x71, 0x77, 0x70, 0x78, 0x70, + 0x78, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, + 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x78, 0x6f, 0x79, 0x70, + 0x79, 0x70, 0x79, 0x71, 0x79, 0x70, 0x7a, 0x70, 0x7a, 0x70, 0x7a, 0x70, + 0x7a, 0x70, 0x7b, 0x70, 0x7b, 0x70, 0x7b, 0x74, 0x7c, 0x75, 0x7d, 0x7b, + 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, + 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x7f, 0x68, 0x6b, 0x65, 0x68, + 0x65, 0x66, 0x60, 0x64, 0x5d, 0x62, 0x57, 0x5f, 0x50, 0x5d, 0x49, 0x5b, + 0x46, 0x58, 0x47, 0x56, 0x49, 0x53, 0x4a, 0x50, 0x4d, 0x4f, 0x4d, 0x52, + 0x4a, 0x54, 0x43, 0x5d, 0x3f, 0x65, 0x3b, 0x65, 0x3a, 0x6c, 0x3e, 0x6c, + 0x3f, 0x6b, 0x40, 0x6c, 0x3e, 0x6c, 0x41, 0x6d, 0x45, 0x6e, 0x48, 0x6f, + 0x4a, 0x71, 0x4d, 0x71, 0x50, 0x73, 0x52, 0x73, 0x55, 0x72, 0x57, 0x73, + 0x58, 0x74, 0x58, 0x75, 0x58, 0x75, 0x59, 0x75, 0x58, 0x74, 0x56, 0x72, + 0x55, 0x71, 0x53, 0x70, 0x50, 0x6d, 0x4c, 0x6c, 0x4a, 0x6c, 0x48, 0x6b, + 0x49, 0x6b, 0x48, 0x6b, 0x45, 0x6b, 0x41, 0x6b, 0x3f, 0x67, 0x40, 0x63, + 0x41, 0x60, 0x41, 0x60, 0x41, 0x61, 0x3e, 0x62, 0x3e, 0x62, 0x3d, 0x62, + 0x3c, 0x65, 0x3b, 0x67, 0x3f, 0x68, 0x44, 0x69, 0x46, 0x68, 0x48, 0x6a, + 0x4b, 0x6b, 0x4c, 0x6b, 0x4f, 0x6b, 0x52, 0x6e, 0x55, 0x70, 0x58, 0x70, + 0x58, 0x72, 0x58, 0x72, 0x57, 0x71, 0x57, 0x70, 0x56, 0x70, 0x56, 0x70, + 0x56, 0x70, 0x56, 0x71, 0x55, 0x71, 0x55, 0x70, 0x54, 0x70, 0x55, 0x70, + 0x56, 0x70, 0x57, 0x71, 0x57, 0x72, 0x57, 0x72, 0x58, 0x72, 0x58, 0x72, + 0x58, 0x73, 0x58, 0x73, 0x58, 0x73, 0x56, 0x72, 0x56, 0x72, 0x53, 0x72, + 0x50, 0x73, 0x50, 0x72, 0x4d, 0x72, 0x4d, 0x72, 0x51, 0x74, 0x54, 0x73, + 0x55, 0x73, 0x57, 0x76, 0x5a, 0x77, 0x5c, 0x77, 0x5f, 0x77, 0x5f, 0x77, + 0x5f, 0x77, 0x60, 0x78, 0x61, 0x78, 0x61, 0x78, 0x60, 0x78, 0x5e, 0x77, + 0x5d, 0x77, 0x5c, 0x78, 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5a, 0x77, + 0x5b, 0x78, 0x5e, 0x76, 0x5f, 0x75, 0x63, 0x75, 0x6a, 0x74, 0x6d, 0x73, + 0x72, 0x70, 0x76, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x71, 0x77, 0x70, + 0x77, 0x70, 0x77, 0x71, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, + 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x70, 0x78, 0x70, 0x78, 0x70, 0x77, 0x70, + 0x78, 0x70, 0x7a, 0x70, 0x7a, 0x70, 0x7a, 0x71, 0x7a, 0x70, 0x7b, 0x70, + 0x7a, 0x6f, 0x7c, 0x74, 0x7d, 0x76, 0x7e, 0x7b, 0x7f, 0x7f, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x80, 0x7f, 0x80, 0x7f, 0x64, 0x6a, 0x62, 0x67, 0x61, 0x65, 0x5b, 0x63, + 0x57, 0x61, 0x4e, 0x5e, 0x47, 0x5a, 0x46, 0x57, 0x47, 0x54, 0x47, 0x52, + 0x49, 0x51, 0x4a, 0x51, 0x4c, 0x4f, 0x4e, 0x50, 0x4c, 0x52, 0x47, 0x5c, + 0x42, 0x63, 0x3d, 0x65, 0x40, 0x6b, 0x45, 0x6d, 0x46, 0x6d, 0x45, 0x6e, + 0x43, 0x6e, 0x46, 0x6f, 0x46, 0x6f, 0x48, 0x6f, 0x4a, 0x71, 0x4d, 0x71, + 0x52, 0x73, 0x54, 0x72, 0x57, 0x74, 0x59, 0x75, 0x58, 0x74, 0x58, 0x75, + 0x58, 0x75, 0x58, 0x75, 0x58, 0x74, 0x56, 0x72, 0x53, 0x72, 0x51, 0x70, + 0x4e, 0x6d, 0x4a, 0x6c, 0x48, 0x6c, 0x47, 0x6b, 0x49, 0x6b, 0x48, 0x6b, + 0x45, 0x6b, 0x40, 0x6a, 0x3f, 0x67, 0x40, 0x64, 0x40, 0x61, 0x40, 0x60, + 0x40, 0x61, 0x3e, 0x62, 0x3d, 0x62, 0x3d, 0x62, 0x3c, 0x65, 0x3b, 0x67, + 0x3f, 0x68, 0x44, 0x69, 0x45, 0x68, 0x47, 0x69, 0x49, 0x6b, 0x4b, 0x6b, + 0x4f, 0x6c, 0x53, 0x6e, 0x55, 0x70, 0x58, 0x70, 0x59, 0x72, 0x58, 0x72, + 0x57, 0x70, 0x57, 0x70, 0x57, 0x70, 0x56, 0x70, 0x56, 0x70, 0x56, 0x70, + 0x55, 0x71, 0x55, 0x70, 0x55, 0x70, 0x55, 0x70, 0x56, 0x70, 0x58, 0x71, + 0x57, 0x72, 0x57, 0x72, 0x58, 0x72, 0x58, 0x72, 0x58, 0x73, 0x58, 0x74, + 0x58, 0x73, 0x56, 0x73, 0x55, 0x72, 0x52, 0x72, 0x50, 0x72, 0x50, 0x72, + 0x4d, 0x72, 0x4d, 0x72, 0x4f, 0x73, 0x52, 0x73, 0x54, 0x73, 0x57, 0x76, + 0x5a, 0x78, 0x5c, 0x77, 0x5d, 0x77, 0x5d, 0x77, 0x5e, 0x78, 0x5e, 0x78, + 0x5f, 0x78, 0x5f, 0x78, 0x5e, 0x78, 0x5c, 0x77, 0x5c, 0x77, 0x5c, 0x77, + 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5d, 0x77, 0x60, 0x76, + 0x62, 0x76, 0x67, 0x74, 0x6c, 0x72, 0x71, 0x72, 0x75, 0x70, 0x76, 0x70, + 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x71, + 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, + 0x77, 0x70, 0x78, 0x70, 0x78, 0x70, 0x78, 0x70, 0x78, 0x70, 0x7a, 0x70, + 0x7a, 0x70, 0x7a, 0x70, 0x7a, 0x70, 0x7a, 0x70, 0x7a, 0x6f, 0x7c, 0x74, + 0x7c, 0x76, 0x7d, 0x7b, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80, + 0x61, 0x67, 0x5e, 0x64, 0x5b, 0x63, 0x54, 0x60, 0x4e, 0x5f, 0x47, 0x5b, + 0x45, 0x56, 0x46, 0x53, 0x48, 0x50, 0x48, 0x4f, 0x49, 0x50, 0x4a, 0x51, + 0x4d, 0x4f, 0x4f, 0x4f, 0x50, 0x51, 0x4b, 0x5a, 0x45, 0x61, 0x41, 0x64, + 0x47, 0x6a, 0x4c, 0x6d, 0x4c, 0x6f, 0x4b, 0x70, 0x48, 0x70, 0x4a, 0x70, + 0x49, 0x71, 0x48, 0x70, 0x4a, 0x70, 0x4e, 0x71, 0x54, 0x73, 0x56, 0x73, + 0x58, 0x75, 0x5a, 0x76, 0x5a, 0x75, 0x59, 0x75, 0x58, 0x75, 0x58, 0x75, + 0x58, 0x74, 0x56, 0x72, 0x52, 0x71, 0x4f, 0x6f, 0x4c, 0x6d, 0x49, 0x6d, + 0x49, 0x6d, 0x49, 0x6b, 0x4a, 0x6b, 0x49, 0x6c, 0x42, 0x6b, 0x3f, 0x6a, + 0x3f, 0x66, 0x40, 0x63, 0x41, 0x61, 0x40, 0x5e, 0x40, 0x60, 0x3f, 0x61, + 0x3e, 0x62, 0x3e, 0x63, 0x3c, 0x65, 0x3c, 0x66, 0x3e, 0x67, 0x42, 0x68, + 0x44, 0x68, 0x47, 0x69, 0x47, 0x6b, 0x4b, 0x6a, 0x4e, 0x6c, 0x52, 0x6e, + 0x54, 0x70, 0x56, 0x70, 0x58, 0x72, 0x58, 0x72, 0x58, 0x71, 0x57, 0x70, + 0x57, 0x71, 0x56, 0x71, 0x56, 0x71, 0x57, 0x71, 0x56, 0x71, 0x55, 0x70, + 0x55, 0x70, 0x56, 0x70, 0x56, 0x70, 0x58, 0x71, 0x57, 0x72, 0x58, 0x72, + 0x59, 0x72, 0x59, 0x72, 0x58, 0x73, 0x58, 0x73, 0x57, 0x73, 0x57, 0x73, + 0x56, 0x73, 0x53, 0x72, 0x51, 0x72, 0x50, 0x72, 0x4e, 0x72, 0x4d, 0x72, + 0x4e, 0x72, 0x51, 0x73, 0x54, 0x74, 0x58, 0x76, 0x59, 0x76, 0x5b, 0x76, + 0x5d, 0x77, 0x5d, 0x77, 0x5c, 0x78, 0x5d, 0x78, 0x5c, 0x78, 0x5c, 0x78, + 0x5c, 0x78, 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, + 0x5b, 0x77, 0x5c, 0x77, 0x5e, 0x77, 0x62, 0x76, 0x66, 0x75, 0x6c, 0x73, + 0x70, 0x71, 0x75, 0x70, 0x77, 0x70, 0x76, 0x70, 0x77, 0x70, 0x77, 0x71, + 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x6f, 0x77, 0x6f, + 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x70, 0x78, 0x70, + 0x78, 0x71, 0x78, 0x70, 0x79, 0x70, 0x7a, 0x70, 0x7a, 0x70, 0x7a, 0x70, + 0x7a, 0x70, 0x7a, 0x70, 0x7a, 0x6e, 0x7c, 0x72, 0x7c, 0x76, 0x7e, 0x7b, + 0x80, 0x80, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x60, 0x65, 0x5b, 0x63, + 0x58, 0x62, 0x4e, 0x5f, 0x48, 0x5e, 0x45, 0x59, 0x46, 0x53, 0x47, 0x51, + 0x49, 0x4e, 0x49, 0x4f, 0x49, 0x50, 0x4c, 0x50, 0x4d, 0x50, 0x50, 0x4e, + 0x52, 0x50, 0x4f, 0x58, 0x47, 0x5f, 0x45, 0x64, 0x49, 0x69, 0x4d, 0x6b, + 0x4e, 0x6e, 0x4e, 0x70, 0x4c, 0x71, 0x4b, 0x70, 0x4a, 0x70, 0x49, 0x70, + 0x4b, 0x70, 0x4e, 0x71, 0x55, 0x73, 0x57, 0x74, 0x58, 0x74, 0x5a, 0x76, + 0x5b, 0x76, 0x5b, 0x75, 0x58, 0x75, 0x59, 0x75, 0x57, 0x73, 0x55, 0x70, + 0x51, 0x6e, 0x4d, 0x6d, 0x4b, 0x6c, 0x4a, 0x6d, 0x4a, 0x6d, 0x4a, 0x6c, + 0x4b, 0x6d, 0x48, 0x6d, 0x40, 0x6c, 0x3e, 0x69, 0x40, 0x65, 0x40, 0x60, + 0x40, 0x60, 0x40, 0x5d, 0x40, 0x5f, 0x3f, 0x60, 0x3e, 0x62, 0x3e, 0x65, + 0x3d, 0x66, 0x3d, 0x65, 0x3d, 0x66, 0x40, 0x68, 0x44, 0x69, 0x47, 0x69, + 0x48, 0x6a, 0x4b, 0x69, 0x4e, 0x6c, 0x51, 0x6e, 0x53, 0x6f, 0x56, 0x71, + 0x57, 0x72, 0x59, 0x72, 0x58, 0x72, 0x57, 0x72, 0x57, 0x72, 0x57, 0x72, + 0x57, 0x72, 0x57, 0x72, 0x56, 0x71, 0x56, 0x70, 0x56, 0x70, 0x57, 0x70, + 0x56, 0x70, 0x57, 0x72, 0x58, 0x73, 0x57, 0x73, 0x58, 0x72, 0x59, 0x72, + 0x58, 0x73, 0x58, 0x73, 0x58, 0x73, 0x58, 0x73, 0x57, 0x73, 0x54, 0x73, + 0x52, 0x72, 0x4f, 0x72, 0x4e, 0x72, 0x4c, 0x72, 0x4e, 0x72, 0x51, 0x73, + 0x54, 0x74, 0x58, 0x75, 0x58, 0x75, 0x59, 0x75, 0x5c, 0x76, 0x5d, 0x77, + 0x5d, 0x77, 0x5d, 0x77, 0x5d, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5a, 0x77, + 0x5a, 0x77, 0x5a, 0x77, 0x5a, 0x77, 0x5a, 0x77, 0x5c, 0x77, 0x5b, 0x77, + 0x5e, 0x76, 0x64, 0x75, 0x68, 0x75, 0x70, 0x73, 0x73, 0x71, 0x77, 0x6f, + 0x77, 0x6f, 0x77, 0x6f, 0x78, 0x71, 0x78, 0x71, 0x77, 0x6f, 0x77, 0x6f, + 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, + 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x78, 0x70, 0x79, 0x70, 0x78, 0x6f, + 0x79, 0x70, 0x7b, 0x71, 0x7a, 0x70, 0x7a, 0x70, 0x7a, 0x70, 0x7a, 0x70, + 0x7a, 0x6f, 0x7b, 0x70, 0x7d, 0x75, 0x7e, 0x7b, 0x80, 0x80, 0x81, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x7f, 0x80, 0x5e, 0x65, 0x59, 0x63, 0x53, 0x60, 0x48, 0x5d, + 0x44, 0x5c, 0x46, 0x57, 0x48, 0x54, 0x49, 0x52, 0x4a, 0x4e, 0x4b, 0x4e, + 0x4c, 0x50, 0x4e, 0x4f, 0x4f, 0x51, 0x50, 0x50, 0x51, 0x52, 0x50, 0x58, + 0x4b, 0x5f, 0x4a, 0x64, 0x4f, 0x6a, 0x51, 0x6c, 0x52, 0x6f, 0x52, 0x70, + 0x50, 0x71, 0x4d, 0x70, 0x4c, 0x70, 0x4a, 0x70, 0x4c, 0x70, 0x4e, 0x71, + 0x52, 0x73, 0x55, 0x74, 0x58, 0x73, 0x5a, 0x76, 0x5b, 0x75, 0x5b, 0x75, + 0x58, 0x74, 0x58, 0x75, 0x55, 0x73, 0x53, 0x71, 0x4f, 0x6f, 0x4c, 0x6d, + 0x49, 0x6d, 0x48, 0x6d, 0x49, 0x6d, 0x4a, 0x6c, 0x4a, 0x6d, 0x46, 0x6d, + 0x3f, 0x6b, 0x3e, 0x67, 0x3f, 0x63, 0x40, 0x60, 0x40, 0x60, 0x40, 0x5f, + 0x40, 0x61, 0x3f, 0x62, 0x3f, 0x65, 0x3e, 0x66, 0x3d, 0x65, 0x3c, 0x65, + 0x3d, 0x67, 0x40, 0x69, 0x44, 0x68, 0x47, 0x69, 0x48, 0x6a, 0x4b, 0x6a, + 0x4f, 0x6c, 0x52, 0x6e, 0x54, 0x6f, 0x56, 0x72, 0x57, 0x72, 0x59, 0x72, + 0x59, 0x72, 0x59, 0x72, 0x59, 0x73, 0x59, 0x73, 0x58, 0x72, 0x57, 0x72, + 0x57, 0x71, 0x56, 0x70, 0x56, 0x70, 0x56, 0x70, 0x56, 0x70, 0x57, 0x71, + 0x58, 0x72, 0x57, 0x72, 0x58, 0x72, 0x5a, 0x72, 0x5a, 0x73, 0x5a, 0x73, + 0x5a, 0x74, 0x5b, 0x74, 0x59, 0x73, 0x56, 0x73, 0x54, 0x72, 0x51, 0x72, + 0x50, 0x72, 0x4e, 0x72, 0x4e, 0x72, 0x51, 0x73, 0x53, 0x74, 0x56, 0x75, + 0x57, 0x76, 0x59, 0x75, 0x5d, 0x76, 0x5d, 0x77, 0x5d, 0x77, 0x5d, 0x77, + 0x5d, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5a, 0x77, 0x5a, 0x77, 0x5a, 0x77, + 0x5b, 0x77, 0x5a, 0x77, 0x5c, 0x77, 0x5d, 0x77, 0x60, 0x75, 0x67, 0x74, + 0x6d, 0x73, 0x74, 0x72, 0x76, 0x70, 0x77, 0x6f, 0x77, 0x6f, 0x78, 0x6f, + 0x77, 0x71, 0x77, 0x71, 0x77, 0x70, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, + 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, + 0x77, 0x6f, 0x78, 0x70, 0x78, 0x70, 0x78, 0x6f, 0x79, 0x70, 0x7a, 0x70, + 0x7a, 0x70, 0x7a, 0x70, 0x7a, 0x70, 0x7a, 0x6f, 0x7a, 0x6f, 0x79, 0x71, + 0x7a, 0x75, 0x7d, 0x7b, 0x80, 0x80, 0x81, 0x80, 0x80, 0x7f, 0x80, 0x80, + 0x80, 0x7f, 0x80, 0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x5d, 0x65, 0x58, 0x63, 0x4f, 0x60, 0x44, 0x5c, 0x44, 0x5a, 0x47, 0x55, + 0x4a, 0x53, 0x4a, 0x52, 0x4b, 0x4f, 0x4d, 0x4f, 0x4e, 0x50, 0x4f, 0x50, + 0x50, 0x51, 0x51, 0x53, 0x51, 0x54, 0x51, 0x58, 0x4f, 0x5f, 0x4e, 0x64, + 0x54, 0x6a, 0x54, 0x6c, 0x54, 0x6f, 0x55, 0x70, 0x52, 0x71, 0x50, 0x70, + 0x4d, 0x70, 0x4b, 0x70, 0x4b, 0x70, 0x4d, 0x70, 0x51, 0x73, 0x53, 0x73, + 0x57, 0x74, 0x5a, 0x76, 0x5b, 0x76, 0x5b, 0x75, 0x59, 0x74, 0x58, 0x75, + 0x54, 0x72, 0x52, 0x71, 0x4d, 0x6f, 0x4a, 0x6d, 0x48, 0x6d, 0x47, 0x6c, + 0x49, 0x6c, 0x4a, 0x6c, 0x4a, 0x6d, 0x44, 0x6d, 0x3e, 0x6a, 0x3e, 0x65, + 0x40, 0x61, 0x40, 0x60, 0x41, 0x60, 0x40, 0x61, 0x40, 0x63, 0x3f, 0x64, + 0x3f, 0x66, 0x3f, 0x66, 0x3e, 0x66, 0x3d, 0x65, 0x3d, 0x67, 0x40, 0x69, + 0x44, 0x68, 0x47, 0x68, 0x48, 0x6a, 0x4a, 0x6a, 0x4e, 0x6c, 0x52, 0x6e, + 0x54, 0x6f, 0x55, 0x71, 0x57, 0x72, 0x5a, 0x72, 0x5b, 0x72, 0x5b, 0x72, + 0x5a, 0x73, 0x5a, 0x73, 0x58, 0x72, 0x58, 0x72, 0x57, 0x71, 0x56, 0x70, + 0x56, 0x70, 0x56, 0x70, 0x56, 0x70, 0x57, 0x71, 0x57, 0x72, 0x57, 0x72, + 0x58, 0x72, 0x5b, 0x73, 0x5c, 0x73, 0x5c, 0x73, 0x5c, 0x76, 0x5c, 0x75, + 0x5b, 0x73, 0x57, 0x73, 0x55, 0x72, 0x53, 0x72, 0x51, 0x72, 0x50, 0x72, + 0x4e, 0x73, 0x51, 0x72, 0x52, 0x73, 0x55, 0x75, 0x57, 0x75, 0x5a, 0x75, + 0x5d, 0x77, 0x5d, 0x78, 0x5d, 0x78, 0x5d, 0x78, 0x5c, 0x78, 0x5b, 0x77, + 0x5b, 0x77, 0x5a, 0x77, 0x5b, 0x77, 0x5a, 0x77, 0x5a, 0x77, 0x5a, 0x77, + 0x5c, 0x77, 0x5e, 0x77, 0x62, 0x76, 0x6a, 0x73, 0x70, 0x71, 0x77, 0x70, + 0x77, 0x71, 0x77, 0x6f, 0x78, 0x6f, 0x77, 0x6f, 0x77, 0x71, 0x77, 0x71, + 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, + 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x70, 0x78, 0x70, 0x78, 0x71, + 0x77, 0x70, 0x78, 0x6f, 0x78, 0x6f, 0x7a, 0x70, 0x7a, 0x70, 0x7a, 0x70, + 0x7a, 0x71, 0x7a, 0x6d, 0x7a, 0x6f, 0x78, 0x71, 0x7a, 0x75, 0x7d, 0x7a, + 0x80, 0x80, 0x80, 0x81, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x5c, 0x65, 0x58, 0x62, + 0x4b, 0x5f, 0x45, 0x59, 0x46, 0x58, 0x49, 0x52, 0x4c, 0x4f, 0x4b, 0x51, + 0x4c, 0x50, 0x4e, 0x4e, 0x50, 0x51, 0x51, 0x52, 0x52, 0x52, 0x52, 0x53, + 0x52, 0x56, 0x51, 0x5a, 0x51, 0x60, 0x52, 0x63, 0x58, 0x67, 0x56, 0x6a, + 0x55, 0x6e, 0x57, 0x6f, 0x55, 0x71, 0x53, 0x72, 0x50, 0x72, 0x4b, 0x71, + 0x4a, 0x70, 0x4a, 0x70, 0x4f, 0x72, 0x52, 0x72, 0x58, 0x73, 0x5a, 0x76, + 0x5b, 0x75, 0x5b, 0x75, 0x5a, 0x75, 0x58, 0x73, 0x55, 0x71, 0x51, 0x70, + 0x4d, 0x6e, 0x49, 0x6e, 0x47, 0x6d, 0x49, 0x6c, 0x4b, 0x6d, 0x4a, 0x6e, + 0x48, 0x6d, 0x42, 0x6c, 0x3d, 0x67, 0x3e, 0x64, 0x40, 0x61, 0x41, 0x62, + 0x41, 0x62, 0x40, 0x61, 0x41, 0x64, 0x40, 0x65, 0x40, 0x65, 0x3f, 0x66, + 0x3e, 0x68, 0x3e, 0x68, 0x3d, 0x67, 0x3e, 0x67, 0x43, 0x68, 0x48, 0x69, + 0x4a, 0x6a, 0x4b, 0x6a, 0x4f, 0x6e, 0x53, 0x6f, 0x55, 0x6f, 0x58, 0x72, + 0x5a, 0x74, 0x5b, 0x74, 0x5c, 0x74, 0x5c, 0x74, 0x5a, 0x72, 0x5a, 0x73, + 0x59, 0x74, 0x58, 0x75, 0x56, 0x73, 0x57, 0x72, 0x57, 0x72, 0x57, 0x72, + 0x57, 0x72, 0x57, 0x73, 0x57, 0x73, 0x58, 0x74, 0x5b, 0x74, 0x5c, 0x74, + 0x5c, 0x75, 0x5d, 0x75, 0x5b, 0x76, 0x5c, 0x76, 0x5c, 0x75, 0x59, 0x75, + 0x58, 0x72, 0x56, 0x72, 0x53, 0x72, 0x51, 0x73, 0x50, 0x73, 0x50, 0x72, + 0x52, 0x72, 0x55, 0x73, 0x57, 0x73, 0x58, 0x75, 0x5b, 0x77, 0x5b, 0x77, + 0x5b, 0x77, 0x5b, 0x78, 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5a, 0x77, + 0x5a, 0x77, 0x59, 0x78, 0x58, 0x77, 0x59, 0x76, 0x5d, 0x75, 0x5f, 0x76, + 0x66, 0x74, 0x6f, 0x73, 0x73, 0x72, 0x76, 0x70, 0x77, 0x71, 0x77, 0x70, + 0x77, 0x6f, 0x77, 0x6f, 0x76, 0x70, 0x76, 0x71, 0x77, 0x6f, 0x77, 0x6f, + 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, + 0x77, 0x70, 0x77, 0x70, 0x77, 0x71, 0x78, 0x72, 0x78, 0x71, 0x78, 0x70, + 0x78, 0x70, 0x78, 0x70, 0x78, 0x70, 0x7a, 0x70, 0x7a, 0x70, 0x7b, 0x6f, + 0x7a, 0x70, 0x7a, 0x71, 0x7a, 0x74, 0x7d, 0x7b, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x7f, 0x80, 0x7f, + 0x80, 0x7f, 0x80, 0x7f, 0x59, 0x63, 0x52, 0x60, 0x48, 0x5d, 0x47, 0x57, + 0x49, 0x55, 0x4c, 0x50, 0x4d, 0x4e, 0x4d, 0x50, 0x4f, 0x51, 0x50, 0x51, + 0x52, 0x50, 0x53, 0x51, 0x52, 0x53, 0x53, 0x55, 0x53, 0x58, 0x52, 0x5a, + 0x52, 0x5f, 0x58, 0x63, 0x5e, 0x66, 0x5c, 0x68, 0x5a, 0x6b, 0x5a, 0x6e, + 0x57, 0x71, 0x55, 0x72, 0x53, 0x72, 0x4d, 0x71, 0x4b, 0x70, 0x4a, 0x71, + 0x4d, 0x72, 0x50, 0x72, 0x56, 0x73, 0x58, 0x75, 0x5a, 0x75, 0x5a, 0x75, + 0x5a, 0x76, 0x58, 0x73, 0x53, 0x71, 0x4f, 0x6f, 0x4c, 0x6e, 0x49, 0x6e, + 0x45, 0x6d, 0x48, 0x6c, 0x49, 0x6d, 0x48, 0x6e, 0x44, 0x6e, 0x3f, 0x6b, + 0x3d, 0x67, 0x3e, 0x64, 0x40, 0x62, 0x41, 0x62, 0x41, 0x62, 0x41, 0x63, + 0x41, 0x65, 0x41, 0x68, 0x41, 0x67, 0x40, 0x67, 0x3e, 0x67, 0x3e, 0x68, + 0x3d, 0x68, 0x3e, 0x67, 0x42, 0x68, 0x49, 0x69, 0x4b, 0x6a, 0x4b, 0x6a, + 0x51, 0x6e, 0x55, 0x6f, 0x58, 0x71, 0x5a, 0x73, 0x5d, 0x75, 0x5d, 0x75, + 0x5d, 0x74, 0x5c, 0x75, 0x5b, 0x74, 0x5b, 0x74, 0x5c, 0x75, 0x5a, 0x75, + 0x58, 0x74, 0x58, 0x73, 0x58, 0x73, 0x57, 0x73, 0x57, 0x72, 0x57, 0x73, + 0x57, 0x73, 0x59, 0x74, 0x5c, 0x75, 0x5c, 0x75, 0x5c, 0x75, 0x5e, 0x76, + 0x5d, 0x75, 0x5e, 0x75, 0x5e, 0x75, 0x5c, 0x75, 0x5b, 0x74, 0x58, 0x75, + 0x55, 0x73, 0x53, 0x72, 0x51, 0x73, 0x50, 0x73, 0x52, 0x72, 0x54, 0x73, + 0x57, 0x73, 0x58, 0x75, 0x5b, 0x77, 0x5c, 0x77, 0x5b, 0x77, 0x5b, 0x77, + 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5a, 0x77, 0x5a, 0x77, 0x59, 0x78, + 0x58, 0x77, 0x5a, 0x76, 0x5f, 0x75, 0x63, 0x75, 0x6a, 0x74, 0x72, 0x73, + 0x76, 0x72, 0x77, 0x70, 0x77, 0x71, 0x77, 0x71, 0x77, 0x6f, 0x77, 0x6f, + 0x76, 0x71, 0x75, 0x70, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, + 0x77, 0x71, 0x77, 0x71, 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, + 0x77, 0x71, 0x78, 0x72, 0x78, 0x71, 0x78, 0x70, 0x78, 0x70, 0x78, 0x70, + 0x78, 0x70, 0x7a, 0x70, 0x7a, 0x71, 0x7b, 0x72, 0x7b, 0x72, 0x7a, 0x72, + 0x7a, 0x73, 0x7d, 0x7b, 0x80, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x80, 0x7f, + 0x57, 0x61, 0x4d, 0x5e, 0x46, 0x5c, 0x49, 0x55, 0x4c, 0x52, 0x4e, 0x4f, + 0x4f, 0x4e, 0x50, 0x51, 0x51, 0x52, 0x52, 0x52, 0x54, 0x50, 0x54, 0x50, + 0x53, 0x55, 0x53, 0x57, 0x53, 0x59, 0x52, 0x5a, 0x53, 0x5e, 0x59, 0x62, + 0x5f, 0x66, 0x5f, 0x67, 0x5e, 0x6a, 0x5c, 0x6e, 0x58, 0x71, 0x57, 0x73, + 0x54, 0x73, 0x50, 0x71, 0x4d, 0x70, 0x4b, 0x71, 0x4c, 0x72, 0x4e, 0x72, + 0x55, 0x73, 0x57, 0x75, 0x58, 0x76, 0x59, 0x75, 0x5a, 0x75, 0x57, 0x74, + 0x51, 0x72, 0x4e, 0x6f, 0x4c, 0x6e, 0x48, 0x6d, 0x45, 0x6d, 0x46, 0x6c, + 0x48, 0x6d, 0x47, 0x6e, 0x42, 0x6e, 0x3d, 0x6c, 0x3d, 0x68, 0x3d, 0x63, + 0x40, 0x62, 0x41, 0x62, 0x41, 0x62, 0x40, 0x65, 0x40, 0x67, 0x41, 0x69, + 0x41, 0x69, 0x40, 0x68, 0x3f, 0x67, 0x3f, 0x67, 0x3e, 0x68, 0x3e, 0x67, + 0x43, 0x68, 0x49, 0x69, 0x4b, 0x6a, 0x4c, 0x6a, 0x53, 0x6d, 0x57, 0x6f, + 0x5a, 0x72, 0x5c, 0x75, 0x5e, 0x75, 0x5e, 0x75, 0x5d, 0x75, 0x5c, 0x75, + 0x5d, 0x76, 0x5d, 0x76, 0x5e, 0x75, 0x5c, 0x74, 0x5a, 0x73, 0x5a, 0x73, + 0x59, 0x72, 0x57, 0x72, 0x57, 0x72, 0x57, 0x72, 0x56, 0x73, 0x58, 0x74, + 0x5c, 0x75, 0x5c, 0x75, 0x5c, 0x75, 0x5e, 0x75, 0x5f, 0x75, 0x60, 0x75, + 0x60, 0x75, 0x5d, 0x75, 0x5c, 0x76, 0x59, 0x76, 0x57, 0x73, 0x55, 0x72, + 0x52, 0x73, 0x50, 0x73, 0x52, 0x72, 0x54, 0x73, 0x57, 0x73, 0x58, 0x75, + 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, + 0x5b, 0x77, 0x5a, 0x77, 0x5a, 0x77, 0x59, 0x77, 0x58, 0x77, 0x5b, 0x76, + 0x61, 0x75, 0x66, 0x76, 0x6d, 0x74, 0x74, 0x73, 0x77, 0x72, 0x78, 0x70, + 0x76, 0x70, 0x76, 0x70, 0x77, 0x6f, 0x77, 0x6f, 0x76, 0x70, 0x75, 0x70, + 0x78, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x70, 0x77, 0x71, + 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, 0x78, 0x72, + 0x78, 0x71, 0x78, 0x70, 0x78, 0x70, 0x78, 0x70, 0x78, 0x70, 0x7a, 0x71, + 0x7a, 0x71, 0x7b, 0x73, 0x7b, 0x73, 0x7a, 0x72, 0x7a, 0x73, 0x7c, 0x7b, + 0x7f, 0x7f, 0x80, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x7f, + 0x80, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x80, 0x80, 0x54, 0x5f, 0x49, 0x5b, + 0x48, 0x59, 0x4c, 0x52, 0x4e, 0x51, 0x50, 0x50, 0x51, 0x51, 0x52, 0x52, + 0x53, 0x51, 0x54, 0x50, 0x55, 0x50, 0x55, 0x53, 0x55, 0x58, 0x54, 0x59, + 0x54, 0x59, 0x53, 0x5b, 0x52, 0x60, 0x57, 0x64, 0x62, 0x65, 0x64, 0x67, + 0x61, 0x6a, 0x5f, 0x6d, 0x5c, 0x70, 0x58, 0x72, 0x55, 0x72, 0x52, 0x71, + 0x4f, 0x70, 0x4b, 0x70, 0x4c, 0x70, 0x4f, 0x70, 0x54, 0x73, 0x58, 0x75, + 0x58, 0x76, 0x58, 0x75, 0x58, 0x73, 0x55, 0x72, 0x50, 0x70, 0x4d, 0x6f, + 0x4b, 0x6f, 0x48, 0x6e, 0x46, 0x6e, 0x46, 0x6d, 0x47, 0x6d, 0x44, 0x6d, + 0x3f, 0x6d, 0x3c, 0x6b, 0x3c, 0x66, 0x3e, 0x63, 0x40, 0x60, 0x41, 0x5f, + 0x41, 0x62, 0x40, 0x66, 0x40, 0x69, 0x40, 0x6a, 0x40, 0x6a, 0x40, 0x69, + 0x40, 0x66, 0x40, 0x66, 0x3d, 0x66, 0x3d, 0x66, 0x43, 0x68, 0x49, 0x69, + 0x4b, 0x6a, 0x4f, 0x6c, 0x53, 0x6e, 0x57, 0x70, 0x5b, 0x72, 0x5d, 0x74, + 0x5f, 0x75, 0x5f, 0x75, 0x5e, 0x75, 0x5d, 0x75, 0x5e, 0x75, 0x5e, 0x75, + 0x5d, 0x74, 0x5c, 0x74, 0x5b, 0x74, 0x5a, 0x74, 0x59, 0x73, 0x58, 0x71, + 0x58, 0x72, 0x57, 0x73, 0x58, 0x75, 0x59, 0x75, 0x5c, 0x75, 0x5e, 0x76, + 0x5f, 0x77, 0x5f, 0x77, 0x62, 0x77, 0x62, 0x77, 0x60, 0x77, 0x5d, 0x77, + 0x5e, 0x76, 0x5b, 0x75, 0x58, 0x75, 0x56, 0x74, 0x54, 0x73, 0x51, 0x73, + 0x52, 0x73, 0x55, 0x73, 0x58, 0x74, 0x59, 0x75, 0x5b, 0x76, 0x5b, 0x77, + 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, + 0x5b, 0x77, 0x58, 0x76, 0x5a, 0x76, 0x5d, 0x76, 0x63, 0x74, 0x69, 0x73, + 0x6f, 0x72, 0x75, 0x72, 0x77, 0x72, 0x77, 0x71, 0x77, 0x71, 0x77, 0x70, + 0x77, 0x6e, 0x77, 0x6e, 0x77, 0x6f, 0x77, 0x70, 0x78, 0x6f, 0x77, 0x6f, + 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, + 0x78, 0x70, 0x77, 0x71, 0x77, 0x70, 0x78, 0x70, 0x78, 0x70, 0x78, 0x70, + 0x78, 0x70, 0x78, 0x70, 0x79, 0x70, 0x7a, 0x71, 0x7a, 0x71, 0x7b, 0x72, + 0x7b, 0x72, 0x7b, 0x72, 0x7a, 0x73, 0x7c, 0x79, 0x7f, 0x7f, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x80, 0x7f, + 0x80, 0x7f, 0x80, 0x7f, 0x4f, 0x5d, 0x48, 0x59, 0x4c, 0x55, 0x50, 0x51, + 0x51, 0x51, 0x54, 0x50, 0x54, 0x54, 0x54, 0x55, 0x55, 0x53, 0x55, 0x52, + 0x55, 0x53, 0x56, 0x56, 0x55, 0x5a, 0x53, 0x5c, 0x54, 0x5c, 0x53, 0x5d, + 0x52, 0x62, 0x54, 0x65, 0x5f, 0x65, 0x64, 0x67, 0x65, 0x6b, 0x63, 0x6b, + 0x60, 0x6d, 0x5b, 0x70, 0x58, 0x70, 0x55, 0x70, 0x51, 0x70, 0x4d, 0x70, + 0x4c, 0x70, 0x4d, 0x70, 0x51, 0x72, 0x55, 0x74, 0x56, 0x74, 0x56, 0x74, + 0x56, 0x72, 0x53, 0x72, 0x4f, 0x6f, 0x4d, 0x6f, 0x4a, 0x6f, 0x49, 0x6f, + 0x46, 0x6e, 0x45, 0x6e, 0x45, 0x6d, 0x41, 0x6d, 0x3d, 0x6c, 0x3b, 0x69, + 0x3d, 0x65, 0x3e, 0x62, 0x40, 0x60, 0x41, 0x61, 0x41, 0x64, 0x40, 0x67, + 0x40, 0x69, 0x40, 0x6a, 0x40, 0x6a, 0x40, 0x69, 0x41, 0x65, 0x40, 0x65, + 0x3e, 0x65, 0x3d, 0x65, 0x42, 0x67, 0x49, 0x69, 0x4b, 0x6a, 0x50, 0x6c, + 0x55, 0x6f, 0x59, 0x71, 0x5c, 0x72, 0x5e, 0x74, 0x60, 0x76, 0x5f, 0x75, + 0x5e, 0x75, 0x5e, 0x75, 0x5d, 0x75, 0x5d, 0x75, 0x5b, 0x74, 0x5a, 0x74, + 0x59, 0x75, 0x58, 0x75, 0x58, 0x74, 0x57, 0x72, 0x58, 0x72, 0x5a, 0x74, + 0x59, 0x75, 0x5a, 0x75, 0x5c, 0x76, 0x5f, 0x76, 0x60, 0x78, 0x5f, 0x77, + 0x62, 0x77, 0x62, 0x77, 0x62, 0x77, 0x5f, 0x77, 0x5f, 0x75, 0x5d, 0x75, + 0x5a, 0x75, 0x58, 0x75, 0x55, 0x73, 0x53, 0x73, 0x52, 0x73, 0x54, 0x72, + 0x57, 0x74, 0x58, 0x75, 0x5b, 0x76, 0x5c, 0x77, 0x5b, 0x77, 0x5b, 0x77, + 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5a, 0x76, + 0x5c, 0x75, 0x5f, 0x75, 0x65, 0x73, 0x6c, 0x72, 0x71, 0x72, 0x76, 0x72, + 0x77, 0x72, 0x77, 0x71, 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, + 0x78, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, + 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x78, 0x70, 0x77, 0x70, + 0x77, 0x71, 0x78, 0x70, 0x78, 0x70, 0x78, 0x70, 0x78, 0x70, 0x78, 0x70, + 0x78, 0x70, 0x7a, 0x70, 0x7a, 0x70, 0x79, 0x72, 0x79, 0x72, 0x7a, 0x72, + 0x7a, 0x73, 0x7c, 0x79, 0x80, 0x7f, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x80, 0x7f, + 0x4d, 0x5c, 0x4a, 0x57, 0x50, 0x53, 0x53, 0x51, 0x54, 0x52, 0x56, 0x50, + 0x56, 0x52, 0x56, 0x53, 0x57, 0x55, 0x56, 0x56, 0x56, 0x55, 0x56, 0x57, + 0x54, 0x5c, 0x53, 0x5f, 0x54, 0x5f, 0x53, 0x5e, 0x52, 0x63, 0x52, 0x66, + 0x5d, 0x67, 0x63, 0x68, 0x67, 0x6a, 0x66, 0x6a, 0x63, 0x6c, 0x5e, 0x6f, + 0x5b, 0x6f, 0x57, 0x70, 0x52, 0x70, 0x4f, 0x70, 0x4d, 0x70, 0x4b, 0x71, + 0x4e, 0x72, 0x53, 0x74, 0x54, 0x73, 0x55, 0x73, 0x54, 0x73, 0x52, 0x72, + 0x50, 0x6f, 0x4e, 0x6f, 0x4b, 0x6f, 0x49, 0x6f, 0x45, 0x6e, 0x43, 0x6e, + 0x43, 0x6d, 0x3e, 0x6c, 0x3b, 0x6b, 0x3b, 0x67, 0x3d, 0x64, 0x3e, 0x62, + 0x40, 0x60, 0x41, 0x63, 0x40, 0x65, 0x41, 0x67, 0x41, 0x69, 0x40, 0x6a, + 0x40, 0x6a, 0x40, 0x69, 0x41, 0x66, 0x41, 0x65, 0x3f, 0x65, 0x3d, 0x65, + 0x41, 0x68, 0x48, 0x6a, 0x4b, 0x6a, 0x51, 0x6c, 0x56, 0x6f, 0x5a, 0x71, + 0x5c, 0x72, 0x5e, 0x74, 0x5f, 0x76, 0x5f, 0x76, 0x5e, 0x75, 0x5e, 0x75, + 0x5c, 0x75, 0x5b, 0x75, 0x59, 0x74, 0x58, 0x75, 0x57, 0x75, 0x57, 0x75, + 0x56, 0x75, 0x56, 0x74, 0x59, 0x74, 0x5c, 0x74, 0x5b, 0x75, 0x5b, 0x75, + 0x5c, 0x75, 0x5e, 0x76, 0x5f, 0x77, 0x60, 0x77, 0x62, 0x77, 0x63, 0x76, + 0x63, 0x77, 0x60, 0x77, 0x61, 0x75, 0x5f, 0x75, 0x5b, 0x75, 0x5a, 0x75, + 0x57, 0x74, 0x55, 0x73, 0x53, 0x73, 0x54, 0x72, 0x57, 0x74, 0x59, 0x75, + 0x5b, 0x76, 0x5c, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, + 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x76, 0x5e, 0x75, 0x61, 0x75, + 0x67, 0x74, 0x6d, 0x72, 0x73, 0x72, 0x77, 0x72, 0x77, 0x72, 0x77, 0x71, + 0x77, 0x70, 0x77, 0x71, 0x77, 0x71, 0x77, 0x71, 0x77, 0x6e, 0x77, 0x6e, + 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, + 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x70, 0x77, 0x70, 0x77, 0x71, 0x78, 0x70, + 0x78, 0x70, 0x78, 0x70, 0x78, 0x70, 0x78, 0x70, 0x78, 0x70, 0x7a, 0x71, + 0x7a, 0x70, 0x78, 0x72, 0x78, 0x72, 0x7a, 0x72, 0x7a, 0x73, 0x7c, 0x78, + 0x80, 0x7f, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x4d, 0x5a, 0x51, 0x53, + 0x55, 0x52, 0x56, 0x53, 0x57, 0x53, 0x58, 0x52, 0x58, 0x52, 0x58, 0x53, + 0x57, 0x56, 0x57, 0x57, 0x56, 0x59, 0x55, 0x5c, 0x54, 0x5f, 0x53, 0x62, + 0x53, 0x61, 0x52, 0x62, 0x51, 0x63, 0x51, 0x67, 0x5b, 0x68, 0x62, 0x6a, + 0x67, 0x6b, 0x69, 0x6a, 0x66, 0x6b, 0x62, 0x6f, 0x5f, 0x6f, 0x5b, 0x6f, + 0x57, 0x6f, 0x53, 0x70, 0x4f, 0x71, 0x4b, 0x71, 0x4c, 0x72, 0x50, 0x72, + 0x53, 0x73, 0x53, 0x73, 0x52, 0x72, 0x50, 0x72, 0x4f, 0x70, 0x4d, 0x70, + 0x4a, 0x6f, 0x49, 0x6f, 0x46, 0x6e, 0x42, 0x6d, 0x41, 0x6e, 0x3c, 0x6c, + 0x3b, 0x6a, 0x3b, 0x66, 0x3e, 0x63, 0x40, 0x62, 0x41, 0x62, 0x40, 0x63, + 0x3f, 0x67, 0x3f, 0x6a, 0x40, 0x6a, 0x41, 0x6b, 0x3f, 0x6a, 0x40, 0x69, + 0x42, 0x66, 0x41, 0x65, 0x3f, 0x65, 0x3d, 0x66, 0x41, 0x69, 0x49, 0x69, + 0x4b, 0x6a, 0x50, 0x6d, 0x57, 0x70, 0x5a, 0x72, 0x5c, 0x75, 0x5d, 0x74, + 0x5e, 0x76, 0x5e, 0x76, 0x5e, 0x74, 0x5c, 0x73, 0x58, 0x73, 0x55, 0x71, + 0x55, 0x71, 0x57, 0x73, 0x57, 0x75, 0x57, 0x75, 0x57, 0x77, 0x59, 0x77, + 0x5a, 0x76, 0x5b, 0x75, 0x5c, 0x74, 0x5c, 0x75, 0x5c, 0x76, 0x5c, 0x76, + 0x5e, 0x77, 0x5f, 0x77, 0x60, 0x78, 0x61, 0x78, 0x62, 0x78, 0x62, 0x77, + 0x60, 0x76, 0x5d, 0x77, 0x5b, 0x75, 0x59, 0x75, 0x58, 0x75, 0x56, 0x74, + 0x54, 0x74, 0x54, 0x74, 0x57, 0x75, 0x58, 0x75, 0x5a, 0x77, 0x5b, 0x78, + 0x5b, 0x77, 0x5c, 0x78, 0x5c, 0x78, 0x5b, 0x78, 0x5b, 0x78, 0x5c, 0x77, + 0x5c, 0x78, 0x5c, 0x77, 0x60, 0x75, 0x63, 0x74, 0x6a, 0x74, 0x70, 0x73, + 0x74, 0x73, 0x77, 0x73, 0x77, 0x72, 0x77, 0x71, 0x77, 0x71, 0x77, 0x71, + 0x78, 0x71, 0x77, 0x71, 0x77, 0x70, 0x77, 0x70, 0x77, 0x6f, 0x77, 0x6f, + 0x77, 0x70, 0x77, 0x70, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x70, + 0x78, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x72, + 0x78, 0x72, 0x78, 0x70, 0x78, 0x70, 0x78, 0x72, 0x79, 0x71, 0x78, 0x72, + 0x78, 0x72, 0x79, 0x72, 0x79, 0x74, 0x7a, 0x78, 0x7f, 0x7f, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x50, 0x58, 0x56, 0x51, 0x58, 0x52, 0x58, 0x53, + 0x58, 0x53, 0x59, 0x52, 0x59, 0x52, 0x58, 0x55, 0x57, 0x58, 0x57, 0x5a, + 0x55, 0x5c, 0x54, 0x5e, 0x54, 0x60, 0x53, 0x62, 0x53, 0x63, 0x51, 0x63, + 0x51, 0x63, 0x50, 0x66, 0x58, 0x67, 0x5f, 0x69, 0x64, 0x6a, 0x68, 0x69, + 0x67, 0x6b, 0x65, 0x6e, 0x62, 0x6e, 0x5e, 0x6f, 0x5b, 0x6f, 0x56, 0x70, + 0x51, 0x71, 0x4d, 0x70, 0x4c, 0x72, 0x4e, 0x72, 0x50, 0x73, 0x50, 0x72, + 0x4f, 0x72, 0x4d, 0x72, 0x4d, 0x71, 0x4b, 0x70, 0x4a, 0x70, 0x48, 0x6f, + 0x46, 0x6e, 0x42, 0x6e, 0x3f, 0x6d, 0x3c, 0x6b, 0x3a, 0x68, 0x3c, 0x66, + 0x3f, 0x63, 0x41, 0x62, 0x41, 0x62, 0x40, 0x64, 0x3f, 0x69, 0x3f, 0x6c, + 0x41, 0x6b, 0x41, 0x6c, 0x3f, 0x6a, 0x40, 0x6a, 0x42, 0x66, 0x42, 0x65, + 0x40, 0x65, 0x3e, 0x66, 0x40, 0x69, 0x48, 0x69, 0x4b, 0x6b, 0x51, 0x6d, + 0x57, 0x70, 0x5a, 0x72, 0x5c, 0x75, 0x5d, 0x75, 0x5e, 0x76, 0x5e, 0x75, + 0x5c, 0x73, 0x58, 0x72, 0x55, 0x70, 0x56, 0x6e, 0x59, 0x70, 0x5a, 0x72, + 0x59, 0x72, 0x56, 0x73, 0x58, 0x76, 0x5b, 0x76, 0x59, 0x76, 0x58, 0x76, + 0x5a, 0x76, 0x5e, 0x77, 0x61, 0x78, 0x61, 0x77, 0x61, 0x78, 0x60, 0x78, + 0x61, 0x78, 0x61, 0x78, 0x62, 0x78, 0x62, 0x78, 0x5e, 0x77, 0x5d, 0x77, + 0x5b, 0x75, 0x5a, 0x75, 0x58, 0x75, 0x56, 0x75, 0x55, 0x75, 0x55, 0x74, + 0x57, 0x75, 0x58, 0x75, 0x59, 0x77, 0x5a, 0x78, 0x5a, 0x78, 0x5b, 0x78, + 0x5b, 0x78, 0x5b, 0x78, 0x5b, 0x78, 0x5d, 0x78, 0x5d, 0x78, 0x5d, 0x77, + 0x62, 0x74, 0x65, 0x74, 0x6d, 0x75, 0x72, 0x74, 0x75, 0x73, 0x77, 0x73, + 0x77, 0x72, 0x77, 0x71, 0x77, 0x71, 0x77, 0x71, 0x77, 0x70, 0x77, 0x70, + 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x6f, 0x77, 0x70, 0x77, 0x71, + 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x70, 0x77, 0x71, + 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x73, 0x77, 0x72, 0x78, 0x70, + 0x78, 0x70, 0x78, 0x72, 0x78, 0x72, 0x78, 0x72, 0x78, 0x72, 0x78, 0x72, + 0x77, 0x74, 0x79, 0x78, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, + 0x56, 0x55, 0x58, 0x52, 0x59, 0x51, 0x5a, 0x51, 0x5a, 0x52, 0x5a, 0x53, + 0x5a, 0x54, 0x59, 0x57, 0x57, 0x5b, 0x57, 0x5d, 0x56, 0x5e, 0x55, 0x5d, + 0x54, 0x60, 0x53, 0x64, 0x52, 0x63, 0x51, 0x63, 0x51, 0x63, 0x4f, 0x66, + 0x53, 0x67, 0x5b, 0x69, 0x61, 0x6a, 0x65, 0x69, 0x67, 0x6b, 0x68, 0x6d, + 0x66, 0x6d, 0x61, 0x6e, 0x5e, 0x6f, 0x5a, 0x70, 0x55, 0x71, 0x51, 0x70, + 0x4d, 0x72, 0x4b, 0x72, 0x4c, 0x71, 0x4e, 0x71, 0x4e, 0x72, 0x4c, 0x72, + 0x4b, 0x70, 0x49, 0x70, 0x48, 0x6f, 0x46, 0x70, 0x45, 0x6f, 0x40, 0x6e, + 0x3c, 0x6d, 0x3a, 0x69, 0x3b, 0x66, 0x3c, 0x63, 0x3f, 0x62, 0x40, 0x62, + 0x40, 0x62, 0x3f, 0x65, 0x3f, 0x6a, 0x41, 0x6d, 0x43, 0x6d, 0x41, 0x6c, + 0x3e, 0x6a, 0x40, 0x69, 0x42, 0x66, 0x42, 0x65, 0x40, 0x65, 0x3e, 0x66, + 0x3f, 0x68, 0x46, 0x69, 0x4b, 0x6b, 0x51, 0x6d, 0x57, 0x70, 0x5a, 0x72, + 0x5b, 0x74, 0x5d, 0x75, 0x5e, 0x76, 0x5e, 0x75, 0x5a, 0x73, 0x56, 0x72, + 0x57, 0x70, 0x59, 0x72, 0x5b, 0x72, 0x5a, 0x70, 0x57, 0x6f, 0x55, 0x70, + 0x56, 0x73, 0x59, 0x75, 0x5a, 0x74, 0x60, 0x77, 0x64, 0x78, 0x67, 0x78, + 0x6a, 0x79, 0x6a, 0x79, 0x67, 0x79, 0x63, 0x79, 0x63, 0x78, 0x63, 0x78, + 0x62, 0x78, 0x63, 0x78, 0x68, 0x77, 0x62, 0x77, 0x59, 0x75, 0x59, 0x75, + 0x5a, 0x75, 0x56, 0x75, 0x57, 0x74, 0x57, 0x75, 0x58, 0x75, 0x58, 0x76, + 0x59, 0x77, 0x5a, 0x77, 0x5b, 0x77, 0x5b, 0x78, 0x5b, 0x78, 0x5b, 0x78, + 0x5b, 0x78, 0x5d, 0x78, 0x5c, 0x78, 0x5d, 0x77, 0x63, 0x74, 0x68, 0x74, + 0x70, 0x74, 0x75, 0x73, 0x77, 0x73, 0x78, 0x73, 0x77, 0x72, 0x77, 0x71, + 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, + 0x77, 0x6f, 0x77, 0x6f, 0x78, 0x70, 0x78, 0x71, 0x77, 0x70, 0x77, 0x6f, + 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, + 0x77, 0x70, 0x77, 0x72, 0x77, 0x71, 0x78, 0x70, 0x78, 0x71, 0x78, 0x72, + 0x78, 0x72, 0x78, 0x72, 0x78, 0x72, 0x76, 0x72, 0x76, 0x75, 0x79, 0x78, + 0x7f, 0x7f, 0x80, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, + 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x58, 0x53, 0x59, 0x53, + 0x5a, 0x52, 0x5a, 0x54, 0x5a, 0x54, 0x5a, 0x54, 0x5a, 0x54, 0x59, 0x59, + 0x58, 0x5a, 0x57, 0x5d, 0x55, 0x5f, 0x54, 0x5f, 0x53, 0x62, 0x51, 0x65, + 0x51, 0x65, 0x50, 0x65, 0x50, 0x65, 0x4e, 0x66, 0x4f, 0x68, 0x55, 0x69, + 0x5f, 0x69, 0x64, 0x6a, 0x68, 0x6a, 0x6c, 0x6c, 0x69, 0x6d, 0x66, 0x6e, + 0x63, 0x6e, 0x5d, 0x6e, 0x58, 0x6e, 0x54, 0x6f, 0x50, 0x71, 0x4a, 0x71, + 0x4a, 0x70, 0x4c, 0x70, 0x4c, 0x70, 0x4a, 0x70, 0x48, 0x6f, 0x47, 0x70, + 0x45, 0x6f, 0x43, 0x6e, 0x3f, 0x6e, 0x3c, 0x6e, 0x3a, 0x6c, 0x3a, 0x69, + 0x3b, 0x66, 0x3d, 0x62, 0x3f, 0x60, 0x40, 0x61, 0x40, 0x63, 0x3e, 0x66, + 0x3d, 0x6a, 0x41, 0x6e, 0x44, 0x6e, 0x42, 0x6e, 0x3e, 0x6b, 0x41, 0x69, + 0x42, 0x66, 0x42, 0x65, 0x41, 0x65, 0x3f, 0x65, 0x3e, 0x68, 0x43, 0x6a, + 0x4a, 0x6a, 0x51, 0x6d, 0x55, 0x6f, 0x59, 0x72, 0x5d, 0x74, 0x5d, 0x74, + 0x60, 0x76, 0x5b, 0x74, 0x55, 0x74, 0x55, 0x73, 0x58, 0x72, 0x59, 0x74, + 0x57, 0x72, 0x55, 0x6f, 0x55, 0x6d, 0x54, 0x6f, 0x55, 0x71, 0x5b, 0x71, + 0x64, 0x72, 0x74, 0x75, 0x75, 0x76, 0x74, 0x77, 0x72, 0x78, 0x6e, 0x78, + 0x6a, 0x79, 0x65, 0x79, 0x63, 0x77, 0x62, 0x76, 0x62, 0x76, 0x70, 0x75, + 0x7f, 0x74, 0x6e, 0x74, 0x5c, 0x79, 0x5b, 0x79, 0x5a, 0x75, 0x59, 0x75, + 0x58, 0x75, 0x57, 0x75, 0x57, 0x76, 0x58, 0x76, 0x59, 0x77, 0x5b, 0x78, + 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5c, 0x79, 0x5d, 0x78, 0x5c, 0x78, + 0x5e, 0x78, 0x60, 0x77, 0x66, 0x76, 0x6b, 0x75, 0x73, 0x75, 0x77, 0x74, + 0x78, 0x73, 0x77, 0x73, 0x77, 0x73, 0x77, 0x72, 0x77, 0x72, 0x77, 0x72, + 0x77, 0x72, 0x77, 0x72, 0x77, 0x71, 0x77, 0x70, 0x77, 0x6f, 0x77, 0x70, + 0x76, 0x70, 0x76, 0x71, 0x76, 0x70, 0x76, 0x70, 0x76, 0x70, 0x76, 0x70, + 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x71, + 0x78, 0x71, 0x77, 0x71, 0x78, 0x72, 0x78, 0x72, 0x78, 0x72, 0x78, 0x73, + 0x78, 0x73, 0x76, 0x72, 0x76, 0x75, 0x79, 0x78, 0x7f, 0x7e, 0x7f, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, + 0x80, 0x80, 0x7f, 0x80, 0x58, 0x54, 0x58, 0x54, 0x59, 0x53, 0x59, 0x56, + 0x59, 0x55, 0x59, 0x54, 0x59, 0x53, 0x59, 0x59, 0x58, 0x59, 0x56, 0x5c, + 0x54, 0x5f, 0x54, 0x60, 0x52, 0x62, 0x50, 0x65, 0x50, 0x65, 0x4f, 0x66, + 0x4f, 0x66, 0x4e, 0x65, 0x4e, 0x68, 0x51, 0x68, 0x5d, 0x68, 0x62, 0x6a, + 0x66, 0x6a, 0x6b, 0x6b, 0x6a, 0x6d, 0x68, 0x6e, 0x66, 0x6e, 0x61, 0x6d, + 0x5b, 0x6d, 0x57, 0x6e, 0x53, 0x70, 0x4c, 0x70, 0x49, 0x70, 0x4a, 0x6f, + 0x4a, 0x6f, 0x47, 0x6f, 0x46, 0x6f, 0x44, 0x6f, 0x42, 0x6e, 0x40, 0x6d, + 0x3b, 0x6c, 0x3a, 0x6c, 0x39, 0x6b, 0x3a, 0x69, 0x3b, 0x66, 0x3d, 0x62, + 0x40, 0x5f, 0x41, 0x60, 0x40, 0x64, 0x3e, 0x67, 0x3e, 0x69, 0x42, 0x6e, + 0x44, 0x6e, 0x42, 0x6f, 0x3f, 0x6b, 0x41, 0x68, 0x43, 0x64, 0x43, 0x64, + 0x41, 0x64, 0x40, 0x65, 0x3e, 0x68, 0x42, 0x6a, 0x49, 0x6a, 0x50, 0x6d, + 0x55, 0x70, 0x59, 0x72, 0x5c, 0x75, 0x5c, 0x75, 0x5f, 0x75, 0x58, 0x73, + 0x51, 0x74, 0x54, 0x74, 0x58, 0x72, 0x56, 0x72, 0x54, 0x71, 0x54, 0x6f, + 0x54, 0x6e, 0x53, 0x6f, 0x5b, 0x71, 0x6a, 0x72, 0x75, 0x73, 0x7f, 0x75, + 0x7b, 0x74, 0x77, 0x75, 0x74, 0x76, 0x6f, 0x76, 0x6b, 0x78, 0x66, 0x78, + 0x63, 0x76, 0x67, 0x74, 0x6b, 0x73, 0x7e, 0x76, 0x85, 0x76, 0x70, 0x79, + 0x61, 0x7d, 0x5e, 0x7c, 0x5a, 0x75, 0x5b, 0x76, 0x59, 0x75, 0x57, 0x75, + 0x58, 0x76, 0x58, 0x77, 0x5a, 0x78, 0x5c, 0x78, 0x5b, 0x77, 0x5b, 0x77, + 0x5b, 0x77, 0x5d, 0x79, 0x5d, 0x79, 0x5d, 0x78, 0x5f, 0x78, 0x62, 0x77, + 0x69, 0x78, 0x6d, 0x76, 0x74, 0x75, 0x77, 0x74, 0x77, 0x73, 0x77, 0x73, + 0x77, 0x73, 0x77, 0x73, 0x77, 0x73, 0x77, 0x74, 0x77, 0x72, 0x77, 0x72, + 0x77, 0x71, 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, 0x75, 0x71, 0x75, 0x70, + 0x75, 0x70, 0x75, 0x70, 0x75, 0x70, 0x75, 0x70, 0x76, 0x70, 0x77, 0x70, + 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x71, 0x77, 0x72, + 0x77, 0x72, 0x78, 0x72, 0x78, 0x72, 0x78, 0x73, 0x78, 0x74, 0x78, 0x72, + 0x77, 0x75, 0x7a, 0x78, 0x7e, 0x7e, 0x7f, 0x80, 0x80, 0x80, 0x7f, 0x80, + 0x7f, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x7f, 0x80, + 0x58, 0x53, 0x58, 0x53, 0x58, 0x53, 0x57, 0x56, 0x57, 0x55, 0x57, 0x54, + 0x57, 0x54, 0x57, 0x58, 0x56, 0x5a, 0x54, 0x5d, 0x53, 0x5f, 0x52, 0x60, + 0x51, 0x62, 0x50, 0x65, 0x50, 0x65, 0x4f, 0x66, 0x4e, 0x66, 0x4e, 0x65, + 0x4e, 0x69, 0x4e, 0x68, 0x57, 0x68, 0x5e, 0x6a, 0x61, 0x6a, 0x67, 0x6a, + 0x6a, 0x6b, 0x6a, 0x6d, 0x69, 0x6e, 0x67, 0x6e, 0x61, 0x6e, 0x5d, 0x6e, + 0x57, 0x6e, 0x50, 0x6e, 0x4a, 0x6e, 0x45, 0x6e, 0x43, 0x6f, 0x41, 0x6f, + 0x41, 0x6d, 0x3f, 0x6d, 0x3e, 0x6c, 0x3c, 0x6b, 0x39, 0x6a, 0x39, 0x6a, + 0x38, 0x6a, 0x39, 0x68, 0x3b, 0x65, 0x3d, 0x62, 0x40, 0x5f, 0x41, 0x5f, + 0x40, 0x65, 0x3e, 0x69, 0x42, 0x6c, 0x47, 0x6e, 0x45, 0x6e, 0x41, 0x6e, + 0x3e, 0x6c, 0x40, 0x68, 0x42, 0x64, 0x43, 0x64, 0x42, 0x65, 0x41, 0x65, + 0x3e, 0x68, 0x41, 0x6a, 0x46, 0x6a, 0x4f, 0x6d, 0x55, 0x6f, 0x59, 0x71, + 0x5a, 0x75, 0x5a, 0x75, 0x5b, 0x73, 0x54, 0x71, 0x4e, 0x73, 0x54, 0x74, + 0x56, 0x72, 0x53, 0x73, 0x52, 0x73, 0x53, 0x71, 0x53, 0x6f, 0x55, 0x6f, + 0x5f, 0x72, 0x6a, 0x74, 0x6d, 0x75, 0x73, 0x76, 0x76, 0x75, 0x7a, 0x75, + 0x79, 0x74, 0x73, 0x75, 0x6c, 0x76, 0x68, 0x76, 0x67, 0x76, 0x72, 0x73, + 0x7e, 0x74, 0x83, 0x78, 0x79, 0x7d, 0x67, 0x81, 0x5e, 0x81, 0x61, 0x7f, + 0x5e, 0x77, 0x5a, 0x76, 0x5a, 0x76, 0x59, 0x75, 0x5a, 0x77, 0x5b, 0x78, + 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5d, 0x78, + 0x5d, 0x78, 0x5f, 0x78, 0x61, 0x78, 0x64, 0x78, 0x6a, 0x78, 0x6f, 0x77, + 0x75, 0x75, 0x78, 0x74, 0x77, 0x73, 0x77, 0x73, 0x77, 0x73, 0x77, 0x73, + 0x77, 0x73, 0x77, 0x73, 0x77, 0x72, 0x77, 0x72, 0x77, 0x70, 0x77, 0x70, + 0x77, 0x70, 0x77, 0x70, 0x75, 0x70, 0x75, 0x70, 0x76, 0x71, 0x75, 0x71, + 0x75, 0x71, 0x75, 0x70, 0x76, 0x71, 0x77, 0x71, 0x77, 0x71, 0x77, 0x70, + 0x77, 0x70, 0x77, 0x70, 0x77, 0x71, 0x77, 0x72, 0x77, 0x72, 0x78, 0x72, + 0x78, 0x72, 0x78, 0x72, 0x78, 0x73, 0x79, 0x73, 0x79, 0x74, 0x7a, 0x77, + 0x7e, 0x7e, 0x7f, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x80, 0x80, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x57, 0x53, 0x57, 0x53, + 0x58, 0x52, 0x57, 0x55, 0x56, 0x54, 0x57, 0x55, 0x56, 0x54, 0x55, 0x58, + 0x54, 0x5a, 0x54, 0x5b, 0x52, 0x5d, 0x51, 0x5e, 0x50, 0x61, 0x50, 0x63, + 0x50, 0x64, 0x4e, 0x66, 0x4e, 0x66, 0x4d, 0x65, 0x4d, 0x68, 0x4d, 0x68, + 0x52, 0x69, 0x59, 0x69, 0x5e, 0x69, 0x65, 0x68, 0x69, 0x69, 0x6b, 0x6c, + 0x6b, 0x6e, 0x6b, 0x6e, 0x66, 0x6e, 0x62, 0x6d, 0x5b, 0x6c, 0x54, 0x6c, + 0x4b, 0x6c, 0x42, 0x6d, 0x40, 0x6f, 0x3e, 0x6f, 0x3e, 0x6c, 0x3d, 0x6c, + 0x3b, 0x6a, 0x3a, 0x6a, 0x39, 0x69, 0x39, 0x69, 0x38, 0x67, 0x3a, 0x65, + 0x3b, 0x64, 0x3e, 0x62, 0x40, 0x60, 0x40, 0x60, 0x3f, 0x66, 0x3e, 0x6b, + 0x43, 0x6d, 0x48, 0x6e, 0x47, 0x6d, 0x42, 0x6e, 0x3e, 0x6b, 0x40, 0x68, + 0x43, 0x64, 0x43, 0x64, 0x42, 0x65, 0x40, 0x65, 0x3e, 0x67, 0x40, 0x69, + 0x45, 0x6a, 0x4f, 0x6c, 0x55, 0x6f, 0x58, 0x71, 0x59, 0x74, 0x59, 0x74, + 0x58, 0x71, 0x51, 0x70, 0x4d, 0x72, 0x54, 0x74, 0x55, 0x73, 0x54, 0x73, + 0x53, 0x74, 0x53, 0x71, 0x54, 0x6e, 0x59, 0x6f, 0x63, 0x72, 0x67, 0x74, + 0x65, 0x76, 0x65, 0x77, 0x70, 0x75, 0x79, 0x74, 0x7a, 0x73, 0x77, 0x74, + 0x70, 0x74, 0x6b, 0x75, 0x6c, 0x77, 0x75, 0x75, 0x84, 0x77, 0x7c, 0x78, + 0x6e, 0x7e, 0x5f, 0x81, 0x5b, 0x83, 0x6b, 0x82, 0x68, 0x7a, 0x5a, 0x75, + 0x5b, 0x76, 0x5b, 0x76, 0x5c, 0x76, 0x5c, 0x77, 0x5b, 0x77, 0x5b, 0x77, + 0x5b, 0x77, 0x5c, 0x77, 0x5c, 0x77, 0x5d, 0x78, 0x5e, 0x78, 0x60, 0x78, + 0x63, 0x78, 0x66, 0x77, 0x6c, 0x76, 0x71, 0x75, 0x76, 0x75, 0x78, 0x74, + 0x78, 0x73, 0x77, 0x73, 0x77, 0x72, 0x77, 0x73, 0x77, 0x73, 0x77, 0x73, + 0x77, 0x72, 0x77, 0x71, 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, + 0x76, 0x70, 0x76, 0x70, 0x76, 0x6f, 0x76, 0x6f, 0x76, 0x70, 0x76, 0x70, + 0x77, 0x70, 0x78, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x6f, + 0x77, 0x70, 0x77, 0x71, 0x78, 0x71, 0x78, 0x71, 0x78, 0x71, 0x79, 0x71, + 0x79, 0x73, 0x7a, 0x74, 0x7a, 0x74, 0x7b, 0x75, 0x7e, 0x7e, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x80, 0x7f, 0x80, 0x7f, 0x56, 0x50, 0x57, 0x50, 0x58, 0x4f, 0x57, 0x51, + 0x57, 0x51, 0x57, 0x52, 0x56, 0x55, 0x55, 0x57, 0x53, 0x59, 0x53, 0x5a, + 0x52, 0x5b, 0x51, 0x5d, 0x50, 0x5f, 0x4f, 0x61, 0x4f, 0x63, 0x4e, 0x66, + 0x4e, 0x66, 0x4d, 0x66, 0x4d, 0x66, 0x4d, 0x67, 0x4f, 0x68, 0x54, 0x68, + 0x5b, 0x68, 0x62, 0x68, 0x65, 0x69, 0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, + 0x6a, 0x6e, 0x68, 0x6d, 0x61, 0x6d, 0x5a, 0x6c, 0x51, 0x6c, 0x45, 0x6c, + 0x3e, 0x6d, 0x3b, 0x6e, 0x3c, 0x6c, 0x3c, 0x6a, 0x3b, 0x69, 0x3b, 0x69, + 0x3b, 0x68, 0x3a, 0x67, 0x3a, 0x65, 0x3b, 0x63, 0x3c, 0x63, 0x3e, 0x62, + 0x40, 0x61, 0x3f, 0x62, 0x3f, 0x68, 0x3f, 0x6b, 0x43, 0x6d, 0x48, 0x6e, + 0x49, 0x6e, 0x42, 0x6c, 0x3e, 0x6a, 0x40, 0x67, 0x43, 0x64, 0x44, 0x65, + 0x43, 0x65, 0x41, 0x64, 0x3f, 0x65, 0x3e, 0x67, 0x44, 0x68, 0x4e, 0x6b, + 0x54, 0x6e, 0x57, 0x70, 0x58, 0x72, 0x58, 0x72, 0x57, 0x70, 0x4f, 0x70, + 0x4d, 0x71, 0x54, 0x75, 0x55, 0x75, 0x5a, 0x72, 0x58, 0x72, 0x51, 0x70, + 0x58, 0x72, 0x70, 0x74, 0x6e, 0x74, 0x69, 0x77, 0x66, 0x79, 0x63, 0x78, + 0x67, 0x75, 0x6e, 0x73, 0x76, 0x73, 0x7e, 0x73, 0x78, 0x74, 0x6c, 0x76, + 0x6a, 0x76, 0x73, 0x75, 0x7e, 0x75, 0x74, 0x7d, 0x67, 0x80, 0x5d, 0x7e, + 0x63, 0x83, 0x78, 0x81, 0x6f, 0x7b, 0x5a, 0x75, 0x5b, 0x77, 0x5d, 0x78, + 0x5c, 0x76, 0x5b, 0x75, 0x5b, 0x76, 0x5b, 0x77, 0x5c, 0x77, 0x5d, 0x77, + 0x5d, 0x77, 0x5d, 0x78, 0x5f, 0x78, 0x61, 0x78, 0x66, 0x77, 0x69, 0x77, + 0x6e, 0x74, 0x74, 0x74, 0x77, 0x74, 0x78, 0x73, 0x78, 0x73, 0x78, 0x72, + 0x78, 0x72, 0x77, 0x72, 0x77, 0x72, 0x77, 0x72, 0x78, 0x70, 0x78, 0x70, + 0x77, 0x70, 0x77, 0x70, 0x77, 0x71, 0x77, 0x70, 0x77, 0x6f, 0x77, 0x6f, + 0x77, 0x6d, 0x77, 0x6e, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, + 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x78, 0x6f, 0x78, 0x6f, 0x78, 0x6f, + 0x78, 0x6f, 0x78, 0x70, 0x78, 0x70, 0x7a, 0x70, 0x7a, 0x72, 0x7a, 0x73, + 0x7a, 0x73, 0x7b, 0x74, 0x7e, 0x7d, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x80, 0x80, + 0x57, 0x4f, 0x57, 0x4f, 0x57, 0x4e, 0x57, 0x4f, 0x56, 0x50, 0x56, 0x53, + 0x55, 0x55, 0x54, 0x57, 0x53, 0x5a, 0x53, 0x5a, 0x52, 0x5b, 0x51, 0x5d, + 0x50, 0x5f, 0x4f, 0x62, 0x4f, 0x63, 0x4e, 0x63, 0x4d, 0x63, 0x4d, 0x65, + 0x4d, 0x66, 0x4d, 0x65, 0x4d, 0x66, 0x4f, 0x68, 0x54, 0x68, 0x5d, 0x69, + 0x62, 0x6a, 0x68, 0x6d, 0x6c, 0x6c, 0x6f, 0x6d, 0x6e, 0x6e, 0x6c, 0x6d, + 0x67, 0x6d, 0x61, 0x6d, 0x59, 0x6a, 0x4c, 0x6a, 0x3f, 0x6b, 0x3a, 0x6b, + 0x3c, 0x6a, 0x3c, 0x68, 0x3d, 0x68, 0x3d, 0x68, 0x3c, 0x66, 0x3b, 0x65, + 0x3b, 0x64, 0x3b, 0x63, 0x3c, 0x63, 0x3f, 0x61, 0x40, 0x62, 0x3f, 0x64, + 0x3e, 0x69, 0x40, 0x6b, 0x45, 0x6e, 0x48, 0x6e, 0x48, 0x6e, 0x41, 0x6c, + 0x3f, 0x69, 0x41, 0x68, 0x43, 0x64, 0x43, 0x64, 0x43, 0x65, 0x42, 0x64, + 0x40, 0x65, 0x3e, 0x68, 0x41, 0x68, 0x49, 0x6b, 0x52, 0x6e, 0x56, 0x70, + 0x56, 0x72, 0x57, 0x72, 0x55, 0x70, 0x4d, 0x70, 0x4e, 0x71, 0x53, 0x74, + 0x56, 0x75, 0x5d, 0x73, 0x51, 0x6f, 0x47, 0x74, 0x63, 0x7d, 0x74, 0x7f, + 0x69, 0x7c, 0x5f, 0x7d, 0x5f, 0x7c, 0x65, 0x79, 0x61, 0x77, 0x63, 0x74, + 0x72, 0x73, 0x7d, 0x73, 0x7b, 0x74, 0x71, 0x76, 0x6d, 0x76, 0x6d, 0x73, + 0x6f, 0x75, 0x69, 0x80, 0x61, 0x7e, 0x61, 0x7b, 0x77, 0x7f, 0x84, 0x80, + 0x6f, 0x7b, 0x5c, 0x75, 0x5c, 0x77, 0x5d, 0x78, 0x5c, 0x77, 0x5b, 0x75, + 0x5b, 0x76, 0x5c, 0x77, 0x5c, 0x77, 0x5d, 0x77, 0x5d, 0x77, 0x5f, 0x78, + 0x61, 0x78, 0x63, 0x77, 0x67, 0x78, 0x6c, 0x77, 0x72, 0x74, 0x76, 0x74, + 0x77, 0x75, 0x78, 0x73, 0x78, 0x73, 0x78, 0x72, 0x78, 0x72, 0x77, 0x72, + 0x77, 0x72, 0x77, 0x72, 0x78, 0x70, 0x78, 0x70, 0x77, 0x70, 0x77, 0x70, + 0x77, 0x71, 0x78, 0x71, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6e, 0x77, 0x6e, + 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, + 0x77, 0x6f, 0x78, 0x6f, 0x78, 0x6f, 0x78, 0x6f, 0x78, 0x6f, 0x78, 0x70, + 0x78, 0x70, 0x7a, 0x70, 0x7a, 0x71, 0x7a, 0x71, 0x7a, 0x71, 0x7b, 0x73, + 0x7f, 0x7d, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x80, + 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x56, 0x52, 0x56, 0x52, + 0x57, 0x51, 0x56, 0x53, 0x55, 0x54, 0x55, 0x56, 0x54, 0x57, 0x53, 0x57, + 0x53, 0x5a, 0x53, 0x5b, 0x52, 0x5b, 0x50, 0x5e, 0x50, 0x60, 0x4f, 0x61, + 0x4e, 0x63, 0x4d, 0x63, 0x4d, 0x63, 0x4d, 0x66, 0x4d, 0x66, 0x4c, 0x65, + 0x4d, 0x65, 0x4e, 0x67, 0x51, 0x68, 0x5a, 0x68, 0x5f, 0x6a, 0x66, 0x6b, + 0x6b, 0x6c, 0x6f, 0x6d, 0x71, 0x6e, 0x6f, 0x6d, 0x6b, 0x6d, 0x64, 0x6d, + 0x5d, 0x6a, 0x50, 0x69, 0x42, 0x6a, 0x3b, 0x6a, 0x3c, 0x69, 0x3c, 0x67, + 0x3e, 0x67, 0x3e, 0x67, 0x3d, 0x65, 0x3d, 0x64, 0x3c, 0x63, 0x3b, 0x63, + 0x3c, 0x63, 0x3e, 0x62, 0x3f, 0x63, 0x3e, 0x65, 0x3f, 0x6a, 0x42, 0x6b, + 0x46, 0x6d, 0x49, 0x6e, 0x48, 0x6e, 0x41, 0x6c, 0x3f, 0x69, 0x41, 0x68, + 0x44, 0x65, 0x44, 0x64, 0x43, 0x65, 0x42, 0x64, 0x40, 0x65, 0x3e, 0x67, + 0x3f, 0x69, 0x46, 0x6c, 0x50, 0x6f, 0x54, 0x71, 0x55, 0x72, 0x56, 0x72, + 0x53, 0x71, 0x4c, 0x70, 0x4f, 0x72, 0x53, 0x75, 0x54, 0x75, 0x59, 0x72, + 0x45, 0x71, 0x47, 0x7b, 0x66, 0x83, 0x62, 0x87, 0x62, 0x87, 0x5d, 0x7f, + 0x59, 0x7d, 0x63, 0x7b, 0x61, 0x79, 0x62, 0x77, 0x70, 0x73, 0x76, 0x73, + 0x78, 0x74, 0x75, 0x76, 0x74, 0x76, 0x6b, 0x75, 0x66, 0x76, 0x62, 0x7b, + 0x61, 0x7c, 0x68, 0x7a, 0x77, 0x7d, 0x74, 0x80, 0x66, 0x7c, 0x5d, 0x75, + 0x5d, 0x77, 0x5d, 0x78, 0x5c, 0x77, 0x5c, 0x75, 0x5b, 0x76, 0x5b, 0x77, + 0x5c, 0x78, 0x5d, 0x77, 0x5d, 0x77, 0x60, 0x78, 0x62, 0x78, 0x64, 0x77, + 0x68, 0x77, 0x6f, 0x77, 0x75, 0x75, 0x77, 0x74, 0x77, 0x75, 0x78, 0x74, + 0x78, 0x73, 0x78, 0x72, 0x78, 0x72, 0x77, 0x72, 0x77, 0x72, 0x77, 0x72, + 0x78, 0x70, 0x78, 0x70, 0x77, 0x70, 0x77, 0x71, 0x77, 0x70, 0x77, 0x70, + 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6e, 0x77, 0x6e, 0x77, 0x6f, 0x77, 0x6f, + 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x78, 0x6f, + 0x78, 0x6f, 0x78, 0x6f, 0x78, 0x6f, 0x78, 0x71, 0x78, 0x71, 0x7a, 0x70, + 0x7b, 0x71, 0x7a, 0x70, 0x7a, 0x70, 0x7b, 0x72, 0x7f, 0x7d, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x7f, 0x80, + 0x80, 0x7f, 0x80, 0x80, 0x53, 0x55, 0x53, 0x54, 0x55, 0x51, 0x54, 0x56, + 0x54, 0x56, 0x54, 0x56, 0x53, 0x59, 0x53, 0x59, 0x52, 0x5a, 0x52, 0x5c, + 0x51, 0x5d, 0x4f, 0x5f, 0x4f, 0x60, 0x4f, 0x61, 0x4e, 0x63, 0x4d, 0x65, + 0x4c, 0x65, 0x4c, 0x66, 0x4c, 0x65, 0x4c, 0x66, 0x4d, 0x67, 0x4e, 0x67, + 0x4f, 0x67, 0x54, 0x68, 0x5b, 0x68, 0x63, 0x69, 0x68, 0x6b, 0x6e, 0x6d, + 0x72, 0x6f, 0x72, 0x6f, 0x70, 0x6f, 0x68, 0x6c, 0x62, 0x6b, 0x54, 0x68, + 0x48, 0x68, 0x3e, 0x68, 0x3c, 0x68, 0x3c, 0x68, 0x3e, 0x67, 0x3f, 0x65, + 0x3e, 0x64, 0x3d, 0x64, 0x3d, 0x63, 0x3d, 0x63, 0x3d, 0x63, 0x3f, 0x63, + 0x3f, 0x65, 0x3e, 0x68, 0x3e, 0x6b, 0x44, 0x6e, 0x46, 0x6e, 0x4b, 0x6d, + 0x48, 0x6e, 0x40, 0x6b, 0x3f, 0x69, 0x41, 0x68, 0x43, 0x65, 0x44, 0x65, + 0x44, 0x66, 0x43, 0x65, 0x41, 0x65, 0x3f, 0x66, 0x3f, 0x69, 0x46, 0x6e, + 0x4e, 0x71, 0x50, 0x73, 0x54, 0x72, 0x53, 0x72, 0x4d, 0x72, 0x4c, 0x72, + 0x4f, 0x74, 0x50, 0x77, 0x51, 0x75, 0x4d, 0x72, 0x45, 0x73, 0x52, 0x7d, + 0x67, 0x83, 0x61, 0x87, 0x50, 0x8c, 0x57, 0x85, 0x53, 0x7f, 0x5d, 0x7c, + 0x61, 0x80, 0x65, 0x7f, 0x73, 0x75, 0x76, 0x74, 0x76, 0x74, 0x74, 0x74, + 0x72, 0x75, 0x6c, 0x77, 0x6a, 0x77, 0x62, 0x76, 0x63, 0x78, 0x72, 0x7c, + 0x73, 0x7e, 0x66, 0x7e, 0x5f, 0x79, 0x5d, 0x77, 0x5d, 0x77, 0x5e, 0x77, + 0x5d, 0x77, 0x5d, 0x77, 0x5c, 0x77, 0x5b, 0x77, 0x5b, 0x77, 0x5d, 0x77, + 0x5f, 0x77, 0x62, 0x78, 0x64, 0x78, 0x69, 0x78, 0x6d, 0x78, 0x73, 0x78, + 0x77, 0x77, 0x78, 0x75, 0x78, 0x74, 0x78, 0x76, 0x78, 0x75, 0x78, 0x74, + 0x78, 0x73, 0x78, 0x73, 0x78, 0x73, 0x78, 0x72, 0x77, 0x70, 0x77, 0x70, + 0x77, 0x70, 0x78, 0x70, 0x76, 0x70, 0x75, 0x70, 0x78, 0x6f, 0x77, 0x6f, + 0x76, 0x6f, 0x76, 0x6f, 0x77, 0x6f, 0x78, 0x6f, 0x77, 0x6f, 0x77, 0x6f, + 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x78, 0x6f, 0x78, 0x6f, + 0x78, 0x6f, 0x78, 0x70, 0x78, 0x70, 0x7a, 0x6f, 0x7b, 0x70, 0x7a, 0x70, + 0x7a, 0x70, 0x7a, 0x72, 0x7e, 0x7c, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x80, 0x7f, 0x80, 0x80, 0x80, 0x80, + 0x53, 0x55, 0x53, 0x54, 0x54, 0x52, 0x53, 0x57, 0x54, 0x57, 0x54, 0x56, + 0x53, 0x58, 0x53, 0x59, 0x52, 0x5a, 0x51, 0x5c, 0x50, 0x5d, 0x4e, 0x5e, + 0x4e, 0x60, 0x4e, 0x60, 0x4e, 0x63, 0x4c, 0x66, 0x4c, 0x66, 0x4b, 0x65, + 0x4c, 0x65, 0x4c, 0x67, 0x4c, 0x67, 0x4d, 0x67, 0x4f, 0x67, 0x51, 0x68, + 0x56, 0x68, 0x5f, 0x69, 0x65, 0x6b, 0x6a, 0x6e, 0x70, 0x70, 0x72, 0x70, + 0x72, 0x70, 0x6e, 0x6e, 0x68, 0x6d, 0x5b, 0x69, 0x50, 0x67, 0x44, 0x68, + 0x3c, 0x68, 0x3c, 0x68, 0x3e, 0x66, 0x3f, 0x63, 0x3f, 0x62, 0x3f, 0x63, + 0x3e, 0x63, 0x3e, 0x63, 0x3e, 0x64, 0x3e, 0x64, 0x3e, 0x66, 0x3d, 0x6a, + 0x3e, 0x6c, 0x44, 0x6e, 0x46, 0x6e, 0x4a, 0x6e, 0x47, 0x6d, 0x3e, 0x6b, + 0x3e, 0x68, 0x41, 0x67, 0x43, 0x64, 0x44, 0x65, 0x44, 0x66, 0x43, 0x66, + 0x41, 0x65, 0x3f, 0x66, 0x41, 0x68, 0x48, 0x6e, 0x4e, 0x71, 0x50, 0x73, + 0x52, 0x73, 0x51, 0x73, 0x4e, 0x72, 0x50, 0x71, 0x51, 0x73, 0x4f, 0x75, + 0x4d, 0x74, 0x49, 0x74, 0x4e, 0x77, 0x60, 0x7b, 0x8a, 0x83, 0x88, 0x86, + 0x5b, 0x8a, 0x51, 0x8b, 0x55, 0x85, 0x58, 0x7b, 0x61, 0x82, 0x67, 0x81, + 0x7b, 0x75, 0x7d, 0x75, 0x78, 0x75, 0x74, 0x75, 0x71, 0x75, 0x70, 0x74, + 0x71, 0x74, 0x68, 0x74, 0x67, 0x79, 0x75, 0x7d, 0x75, 0x7d, 0x67, 0x78, + 0x5d, 0x76, 0x5d, 0x77, 0x5d, 0x77, 0x5d, 0x77, 0x5e, 0x77, 0x5d, 0x77, + 0x5d, 0x77, 0x5c, 0x77, 0x5d, 0x77, 0x5f, 0x76, 0x61, 0x77, 0x65, 0x78, + 0x67, 0x78, 0x6b, 0x78, 0x70, 0x78, 0x75, 0x78, 0x78, 0x77, 0x78, 0x76, + 0x78, 0x75, 0x78, 0x75, 0x78, 0x75, 0x78, 0x74, 0x78, 0x73, 0x78, 0x73, + 0x78, 0x73, 0x78, 0x72, 0x77, 0x71, 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, + 0x76, 0x70, 0x75, 0x70, 0x77, 0x6f, 0x77, 0x6f, 0x76, 0x6f, 0x75, 0x6f, + 0x76, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, + 0x77, 0x6f, 0x77, 0x6f, 0x78, 0x6f, 0x78, 0x6f, 0x78, 0x6f, 0x78, 0x70, + 0x78, 0x70, 0x7a, 0x6f, 0x7b, 0x70, 0x7a, 0x70, 0x7a, 0x70, 0x7b, 0x72, + 0x7e, 0x7b, 0x80, 0x7f, 0x80, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x7f, 0x7f, 0x80, 0x7f, 0x80, 0x80, 0x52, 0x55, 0x53, 0x54, + 0x52, 0x54, 0x52, 0x58, 0x53, 0x57, 0x54, 0x56, 0x54, 0x57, 0x53, 0x57, + 0x51, 0x59, 0x51, 0x5c, 0x50, 0x5d, 0x4f, 0x5e, 0x4e, 0x60, 0x4e, 0x61, + 0x4e, 0x62, 0x4c, 0x65, 0x4c, 0x65, 0x4c, 0x66, 0x4c, 0x66, 0x4c, 0x67, + 0x4c, 0x67, 0x4d, 0x67, 0x4f, 0x67, 0x50, 0x67, 0x53, 0x67, 0x5b, 0x69, + 0x62, 0x6a, 0x68, 0x6d, 0x6e, 0x6f, 0x72, 0x70, 0x74, 0x71, 0x73, 0x6f, + 0x6e, 0x6e, 0x62, 0x6b, 0x58, 0x68, 0x4c, 0x68, 0x3e, 0x69, 0x3b, 0x68, + 0x3e, 0x65, 0x3f, 0x62, 0x40, 0x61, 0x40, 0x61, 0x40, 0x63, 0x3f, 0x64, + 0x3f, 0x65, 0x3e, 0x66, 0x3e, 0x68, 0x3d, 0x6b, 0x3f, 0x6e, 0x44, 0x6e, + 0x46, 0x6e, 0x48, 0x6e, 0x46, 0x6e, 0x3e, 0x6c, 0x3e, 0x68, 0x40, 0x68, + 0x43, 0x65, 0x44, 0x65, 0x44, 0x66, 0x44, 0x66, 0x42, 0x65, 0x41, 0x65, + 0x43, 0x68, 0x49, 0x6e, 0x4f, 0x71, 0x51, 0x73, 0x51, 0x74, 0x52, 0x74, + 0x54, 0x72, 0x64, 0x72, 0x6e, 0x73, 0x60, 0x75, 0x4f, 0x74, 0x55, 0x77, + 0x5e, 0x79, 0x66, 0x7a, 0x8c, 0x80, 0x8e, 0x81, 0x72, 0x85, 0x61, 0x8a, + 0x69, 0x85, 0x61, 0x7d, 0x6c, 0x81, 0x69, 0x7e, 0x7c, 0x76, 0x82, 0x77, + 0x7a, 0x76, 0x71, 0x77, 0x6a, 0x78, 0x6c, 0x77, 0x70, 0x77, 0x6a, 0x78, + 0x6c, 0x7b, 0x77, 0x7e, 0x75, 0x7c, 0x69, 0x79, 0x5c, 0x77, 0x5d, 0x77, + 0x5e, 0x77, 0x5e, 0x77, 0x5e, 0x77, 0x5e, 0x77, 0x5d, 0x77, 0x5e, 0x77, + 0x5f, 0x77, 0x60, 0x77, 0x63, 0x77, 0x68, 0x78, 0x6a, 0x78, 0x6e, 0x78, + 0x73, 0x78, 0x77, 0x78, 0x79, 0x77, 0x79, 0x77, 0x78, 0x77, 0x78, 0x76, + 0x78, 0x75, 0x79, 0x74, 0x78, 0x73, 0x78, 0x73, 0x78, 0x72, 0x78, 0x72, + 0x77, 0x71, 0x77, 0x70, 0x78, 0x70, 0x78, 0x71, 0x76, 0x70, 0x76, 0x71, + 0x77, 0x70, 0x78, 0x6f, 0x76, 0x6f, 0x75, 0x6f, 0x77, 0x6f, 0x77, 0x6f, + 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, + 0x78, 0x6f, 0x78, 0x6f, 0x78, 0x6f, 0x78, 0x70, 0x78, 0x70, 0x7a, 0x6f, + 0x7a, 0x71, 0x7a, 0x70, 0x7a, 0x70, 0x7a, 0x73, 0x7e, 0x7b, 0x80, 0x7f, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x80, 0x7f, 0x80, 0x7f, 0x51, 0x54, 0x51, 0x54, 0x51, 0x57, 0x51, 0x58, + 0x52, 0x57, 0x53, 0x57, 0x53, 0x58, 0x54, 0x57, 0x52, 0x59, 0x51, 0x5c, + 0x51, 0x5f, 0x4f, 0x60, 0x4e, 0x61, 0x4e, 0x62, 0x4e, 0x62, 0x4c, 0x64, + 0x4c, 0x66, 0x4c, 0x67, 0x4c, 0x67, 0x4c, 0x67, 0x4c, 0x67, 0x4d, 0x65, + 0x4e, 0x66, 0x4f, 0x67, 0x50, 0x67, 0x57, 0x69, 0x60, 0x6a, 0x66, 0x6c, + 0x6e, 0x6f, 0x71, 0x71, 0x75, 0x70, 0x77, 0x70, 0x74, 0x6f, 0x6a, 0x6c, + 0x60, 0x69, 0x56, 0x67, 0x47, 0x68, 0x3f, 0x68, 0x3c, 0x65, 0x3e, 0x63, + 0x40, 0x63, 0x41, 0x63, 0x41, 0x63, 0x40, 0x64, 0x40, 0x66, 0x3f, 0x67, + 0x3d, 0x6a, 0x3c, 0x6b, 0x40, 0x6f, 0x44, 0x6e, 0x46, 0x6e, 0x46, 0x6e, + 0x43, 0x6e, 0x3d, 0x6c, 0x3e, 0x69, 0x40, 0x69, 0x42, 0x67, 0x43, 0x66, + 0x44, 0x66, 0x44, 0x66, 0x43, 0x65, 0x42, 0x66, 0x45, 0x69, 0x4b, 0x70, + 0x52, 0x73, 0x54, 0x73, 0x54, 0x73, 0x57, 0x75, 0x5f, 0x76, 0x73, 0x76, + 0x80, 0x79, 0x73, 0x77, 0x56, 0x77, 0x63, 0x7d, 0x62, 0x7b, 0x5c, 0x7e, + 0x76, 0x80, 0x80, 0x80, 0x73, 0x84, 0x6e, 0x86, 0x73, 0x85, 0x6f, 0x82, + 0x7b, 0x83, 0x71, 0x7f, 0x72, 0x79, 0x7c, 0x78, 0x78, 0x79, 0x67, 0x7b, + 0x64, 0x7c, 0x65, 0x7f, 0x68, 0x84, 0x68, 0x86, 0x6e, 0x7f, 0x7a, 0x7e, + 0x6f, 0x7d, 0x65, 0x7d, 0x5c, 0x78, 0x5e, 0x78, 0x5f, 0x78, 0x5f, 0x78, + 0x5f, 0x77, 0x5f, 0x77, 0x5e, 0x77, 0x5f, 0x77, 0x61, 0x77, 0x63, 0x77, + 0x65, 0x77, 0x6a, 0x77, 0x6e, 0x77, 0x72, 0x78, 0x77, 0x77, 0x7a, 0x77, + 0x7b, 0x78, 0x7a, 0x77, 0x7a, 0x77, 0x7a, 0x76, 0x7a, 0x75, 0x7a, 0x74, + 0x7a, 0x74, 0x79, 0x73, 0x77, 0x73, 0x78, 0x72, 0x78, 0x72, 0x78, 0x72, + 0x77, 0x72, 0x77, 0x72, 0x77, 0x70, 0x77, 0x71, 0x78, 0x71, 0x77, 0x71, + 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, + 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x78, 0x6f, 0x78, 0x6f, 0x7a, 0x6f, + 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x71, 0x7b, 0x72, + 0x79, 0x73, 0x7a, 0x74, 0x7e, 0x7d, 0x80, 0x7f, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80, + 0x51, 0x55, 0x51, 0x55, 0x51, 0x57, 0x52, 0x58, 0x53, 0x58, 0x53, 0x58, + 0x53, 0x59, 0x53, 0x58, 0x52, 0x5a, 0x51, 0x5d, 0x50, 0x5f, 0x4f, 0x60, + 0x4e, 0x62, 0x4e, 0x62, 0x4e, 0x62, 0x4c, 0x65, 0x4c, 0x67, 0x4c, 0x67, + 0x4b, 0x67, 0x4c, 0x67, 0x4d, 0x67, 0x4d, 0x66, 0x4e, 0x66, 0x4f, 0x67, + 0x51, 0x67, 0x56, 0x69, 0x5c, 0x6a, 0x64, 0x6b, 0x6b, 0x6d, 0x6f, 0x70, + 0x75, 0x70, 0x78, 0x70, 0x76, 0x70, 0x6e, 0x6d, 0x66, 0x6b, 0x5c, 0x68, + 0x4e, 0x68, 0x45, 0x68, 0x3d, 0x67, 0x3d, 0x64, 0x40, 0x63, 0x42, 0x63, + 0x41, 0x62, 0x41, 0x65, 0x41, 0x66, 0x3f, 0x68, 0x3d, 0x6a, 0x3c, 0x6b, + 0x40, 0x6e, 0x42, 0x6e, 0x45, 0x6e, 0x44, 0x6e, 0x40, 0x6e, 0x3c, 0x6c, + 0x3e, 0x6a, 0x40, 0x69, 0x42, 0x68, 0x43, 0x66, 0x44, 0x65, 0x45, 0x65, + 0x44, 0x65, 0x42, 0x66, 0x45, 0x69, 0x4c, 0x70, 0x54, 0x73, 0x55, 0x72, + 0x55, 0x74, 0x5c, 0x77, 0x66, 0x78, 0x6e, 0x7a, 0x76, 0x7b, 0x73, 0x78, + 0x5b, 0x7b, 0x61, 0x7e, 0x5e, 0x7b, 0x57, 0x81, 0x5e, 0x83, 0x64, 0x83, + 0x5c, 0x85, 0x68, 0x85, 0x70, 0x83, 0x6e, 0x81, 0x70, 0x82, 0x6a, 0x80, + 0x70, 0x7d, 0x79, 0x7b, 0x76, 0x80, 0x68, 0x86, 0x68, 0x88, 0x66, 0x89, + 0x66, 0x8a, 0x6a, 0x86, 0x73, 0x80, 0x78, 0x7e, 0x6c, 0x7d, 0x63, 0x7d, + 0x5e, 0x78, 0x60, 0x78, 0x60, 0x78, 0x60, 0x78, 0x60, 0x77, 0x60, 0x77, + 0x60, 0x77, 0x62, 0x77, 0x64, 0x77, 0x65, 0x77, 0x68, 0x77, 0x6d, 0x77, + 0x71, 0x77, 0x76, 0x77, 0x79, 0x77, 0x7b, 0x77, 0x7b, 0x77, 0x7b, 0x77, + 0x7b, 0x77, 0x7a, 0x76, 0x7b, 0x75, 0x7a, 0x75, 0x7a, 0x75, 0x79, 0x74, + 0x78, 0x73, 0x78, 0x73, 0x78, 0x72, 0x78, 0x72, 0x77, 0x72, 0x77, 0x72, + 0x77, 0x70, 0x77, 0x70, 0x77, 0x71, 0x77, 0x71, 0x77, 0x6f, 0x77, 0x6f, + 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, + 0x78, 0x6f, 0x78, 0x6f, 0x78, 0x6f, 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x6f, + 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x71, 0x7b, 0x72, 0x79, 0x73, 0x7a, 0x74, + 0x7e, 0x7e, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x7f, + 0x7f, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x51, 0x57, 0x51, 0x58, + 0x51, 0x58, 0x51, 0x58, 0x52, 0x59, 0x53, 0x5a, 0x53, 0x59, 0x53, 0x5a, + 0x52, 0x5c, 0x51, 0x5f, 0x50, 0x60, 0x4f, 0x60, 0x4f, 0x62, 0x4e, 0x62, + 0x4e, 0x62, 0x4c, 0x64, 0x4c, 0x67, 0x4c, 0x67, 0x4b, 0x67, 0x4c, 0x67, + 0x4c, 0x67, 0x4d, 0x66, 0x4e, 0x66, 0x4f, 0x67, 0x51, 0x67, 0x54, 0x69, + 0x58, 0x6b, 0x60, 0x6a, 0x67, 0x6b, 0x6c, 0x6d, 0x75, 0x70, 0x77, 0x70, + 0x77, 0x72, 0x74, 0x6f, 0x6d, 0x6d, 0x64, 0x6a, 0x58, 0x68, 0x4f, 0x68, + 0x41, 0x68, 0x3d, 0x66, 0x40, 0x64, 0x42, 0x63, 0x42, 0x62, 0x42, 0x65, + 0x42, 0x67, 0x3f, 0x68, 0x3e, 0x6a, 0x3d, 0x6b, 0x3f, 0x6d, 0x41, 0x6e, + 0x42, 0x6e, 0x40, 0x6e, 0x3c, 0x6d, 0x3b, 0x6c, 0x3e, 0x6a, 0x3f, 0x69, + 0x42, 0x67, 0x43, 0x65, 0x44, 0x66, 0x44, 0x66, 0x44, 0x65, 0x42, 0x66, + 0x45, 0x69, 0x4d, 0x70, 0x56, 0x72, 0x57, 0x72, 0x5a, 0x76, 0x5d, 0x78, + 0x66, 0x79, 0x72, 0x7f, 0x77, 0x83, 0x76, 0x80, 0x5c, 0x80, 0x53, 0x7f, + 0x50, 0x7b, 0x53, 0x7d, 0x54, 0x85, 0x4d, 0x87, 0x55, 0x86, 0x6e, 0x83, + 0x68, 0x81, 0x62, 0x7f, 0x64, 0x80, 0x65, 0x7f, 0x70, 0x80, 0x7a, 0x82, + 0x76, 0x85, 0x6a, 0x89, 0x69, 0x88, 0x67, 0x85, 0x65, 0x82, 0x6f, 0x81, + 0x7b, 0x81, 0x73, 0x7e, 0x67, 0x7c, 0x62, 0x7c, 0x5f, 0x78, 0x62, 0x78, + 0x62, 0x78, 0x61, 0x78, 0x62, 0x78, 0x62, 0x77, 0x63, 0x77, 0x66, 0x77, + 0x68, 0x77, 0x69, 0x77, 0x6d, 0x77, 0x73, 0x77, 0x77, 0x78, 0x7b, 0x77, + 0x7b, 0x77, 0x7b, 0x77, 0x7b, 0x77, 0x7b, 0x77, 0x7b, 0x77, 0x7a, 0x76, + 0x7a, 0x76, 0x7a, 0x75, 0x7a, 0x75, 0x79, 0x74, 0x78, 0x72, 0x78, 0x73, + 0x78, 0x72, 0x78, 0x72, 0x77, 0x72, 0x77, 0x72, 0x77, 0x71, 0x77, 0x70, + 0x77, 0x71, 0x77, 0x70, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, + 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x78, 0x6f, + 0x79, 0x6f, 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x6f, + 0x7a, 0x71, 0x7a, 0x72, 0x79, 0x73, 0x7a, 0x74, 0x7e, 0x7d, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, + 0x80, 0x7f, 0x80, 0x7f, 0x52, 0x56, 0x51, 0x59, 0x51, 0x59, 0x51, 0x59, + 0x52, 0x5a, 0x53, 0x5a, 0x53, 0x58, 0x53, 0x5b, 0x52, 0x5f, 0x51, 0x5f, + 0x50, 0x60, 0x50, 0x61, 0x50, 0x62, 0x4e, 0x60, 0x4e, 0x61, 0x4d, 0x66, + 0x4e, 0x66, 0x4c, 0x67, 0x4b, 0x67, 0x4c, 0x67, 0x4c, 0x67, 0x4d, 0x66, + 0x4d, 0x66, 0x4f, 0x66, 0x50, 0x65, 0x53, 0x66, 0x56, 0x69, 0x5c, 0x6a, + 0x67, 0x6a, 0x6c, 0x6c, 0x73, 0x6e, 0x77, 0x70, 0x78, 0x71, 0x78, 0x70, + 0x74, 0x6e, 0x68, 0x6c, 0x5f, 0x69, 0x57, 0x69, 0x48, 0x68, 0x3e, 0x67, + 0x3f, 0x64, 0x41, 0x62, 0x42, 0x62, 0x43, 0x64, 0x42, 0x66, 0x40, 0x68, + 0x3e, 0x69, 0x3c, 0x6a, 0x3d, 0x6c, 0x40, 0x6d, 0x41, 0x6e, 0x3e, 0x6c, + 0x3b, 0x6c, 0x3b, 0x6a, 0x3d, 0x6a, 0x3f, 0x69, 0x41, 0x66, 0x42, 0x66, + 0x44, 0x68, 0x45, 0x66, 0x44, 0x65, 0x44, 0x66, 0x45, 0x6a, 0x4d, 0x70, + 0x5a, 0x71, 0x65, 0x72, 0x64, 0x77, 0x5d, 0x79, 0x63, 0x78, 0x7a, 0x80, + 0x82, 0x86, 0x75, 0x84, 0x59, 0x80, 0x4b, 0x7e, 0x47, 0x79, 0x4f, 0x79, + 0x62, 0x81, 0x64, 0x82, 0x6b, 0x82, 0x75, 0x82, 0x62, 0x80, 0x5a, 0x7c, + 0x61, 0x7e, 0x67, 0x7f, 0x6c, 0x81, 0x73, 0x85, 0x75, 0x86, 0x6e, 0x85, + 0x6a, 0x84, 0x66, 0x84, 0x66, 0x83, 0x72, 0x82, 0x7d, 0x82, 0x6c, 0x7d, + 0x5e, 0x79, 0x5f, 0x7e, 0x63, 0x7a, 0x64, 0x79, 0x63, 0x79, 0x61, 0x7a, + 0x61, 0x79, 0x63, 0x78, 0x66, 0x78, 0x67, 0x77, 0x69, 0x77, 0x6d, 0x77, + 0x72, 0x78, 0x76, 0x78, 0x79, 0x78, 0x7d, 0x78, 0x7d, 0x77, 0x7c, 0x77, + 0x7c, 0x77, 0x7c, 0x76, 0x7c, 0x76, 0x7b, 0x75, 0x7a, 0x75, 0x7b, 0x75, + 0x7a, 0x75, 0x7a, 0x74, 0x7b, 0x73, 0x7a, 0x73, 0x78, 0x72, 0x78, 0x72, + 0x77, 0x72, 0x77, 0x73, 0x77, 0x71, 0x77, 0x70, 0x77, 0x70, 0x77, 0x6f, + 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, + 0x78, 0x6f, 0x78, 0x6f, 0x78, 0x6f, 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x6f, + 0x7a, 0x6f, 0x7a, 0x70, 0x7b, 0x70, 0x7a, 0x6f, 0x7a, 0x70, 0x7a, 0x71, + 0x7a, 0x74, 0x7a, 0x74, 0x7e, 0x7c, 0x80, 0x7f, 0x80, 0x80, 0x80, 0x80, + 0x7f, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, + 0x52, 0x56, 0x52, 0x58, 0x51, 0x59, 0x51, 0x5a, 0x52, 0x5a, 0x53, 0x5a, + 0x54, 0x57, 0x53, 0x5b, 0x52, 0x60, 0x51, 0x5f, 0x51, 0x60, 0x51, 0x62, + 0x50, 0x62, 0x4e, 0x62, 0x4e, 0x63, 0x4d, 0x66, 0x4d, 0x65, 0x4c, 0x67, + 0x4b, 0x67, 0x4c, 0x67, 0x4c, 0x67, 0x4d, 0x66, 0x4d, 0x66, 0x4e, 0x65, + 0x50, 0x64, 0x52, 0x65, 0x55, 0x67, 0x5b, 0x69, 0x66, 0x6a, 0x6b, 0x6c, + 0x73, 0x6d, 0x77, 0x6f, 0x78, 0x71, 0x78, 0x70, 0x75, 0x6f, 0x6c, 0x6d, + 0x64, 0x6a, 0x5d, 0x6a, 0x52, 0x68, 0x44, 0x67, 0x40, 0x65, 0x40, 0x63, + 0x42, 0x63, 0x43, 0x64, 0x42, 0x66, 0x41, 0x68, 0x3e, 0x6a, 0x3d, 0x6a, + 0x3c, 0x6c, 0x3e, 0x6e, 0x3e, 0x6e, 0x3c, 0x6c, 0x3a, 0x6c, 0x3b, 0x6a, + 0x3d, 0x6a, 0x3f, 0x69, 0x41, 0x67, 0x42, 0x66, 0x44, 0x67, 0x45, 0x66, + 0x44, 0x64, 0x43, 0x65, 0x44, 0x6a, 0x4f, 0x70, 0x6a, 0x73, 0x79, 0x76, + 0x6a, 0x77, 0x5d, 0x77, 0x69, 0x78, 0x81, 0x82, 0x83, 0x85, 0x61, 0x86, + 0x4d, 0x80, 0x48, 0x7c, 0x45, 0x77, 0x47, 0x78, 0x44, 0x82, 0x54, 0x82, + 0x5d, 0x80, 0x60, 0x80, 0x56, 0x7f, 0x5b, 0x7c, 0x6c, 0x7e, 0x67, 0x7e, + 0x6a, 0x7f, 0x6e, 0x82, 0x73, 0x85, 0x72, 0x85, 0x6d, 0x85, 0x67, 0x85, + 0x69, 0x84, 0x74, 0x81, 0x7b, 0x7e, 0x68, 0x7b, 0x56, 0x7c, 0x5b, 0x82, + 0x63, 0x7b, 0x64, 0x7a, 0x63, 0x7a, 0x62, 0x7a, 0x62, 0x79, 0x65, 0x78, + 0x67, 0x78, 0x68, 0x77, 0x6c, 0x77, 0x70, 0x77, 0x75, 0x78, 0x79, 0x78, + 0x7b, 0x78, 0x7d, 0x77, 0x7e, 0x77, 0x7d, 0x77, 0x7c, 0x77, 0x7c, 0x76, + 0x7c, 0x75, 0x7b, 0x75, 0x7b, 0x75, 0x7b, 0x75, 0x7b, 0x75, 0x7a, 0x74, + 0x7a, 0x73, 0x7a, 0x72, 0x77, 0x72, 0x78, 0x72, 0x77, 0x72, 0x77, 0x73, + 0x77, 0x71, 0x77, 0x70, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, + 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x78, 0x6f, 0x78, 0x6f, + 0x78, 0x6f, 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x70, + 0x7b, 0x70, 0x7a, 0x6f, 0x7a, 0x70, 0x7a, 0x72, 0x7b, 0x73, 0x7a, 0x73, + 0x7e, 0x7c, 0x81, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x80, 0x7f, + 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x53, 0x58, 0x53, 0x55, + 0x52, 0x59, 0x51, 0x5a, 0x52, 0x5a, 0x53, 0x5a, 0x53, 0x57, 0x53, 0x5b, + 0x52, 0x60, 0x51, 0x5f, 0x51, 0x60, 0x51, 0x62, 0x50, 0x63, 0x4f, 0x65, + 0x4f, 0x65, 0x4d, 0x65, 0x4d, 0x65, 0x4c, 0x67, 0x4b, 0x67, 0x4b, 0x67, + 0x4b, 0x67, 0x4d, 0x66, 0x4d, 0x66, 0x4d, 0x65, 0x4f, 0x65, 0x52, 0x64, + 0x56, 0x65, 0x5b, 0x68, 0x64, 0x6b, 0x6a, 0x6c, 0x73, 0x6d, 0x77, 0x6f, + 0x78, 0x70, 0x78, 0x71, 0x77, 0x71, 0x72, 0x6f, 0x6d, 0x6c, 0x65, 0x6c, + 0x5a, 0x69, 0x51, 0x68, 0x44, 0x66, 0x40, 0x65, 0x41, 0x64, 0x42, 0x64, + 0x42, 0x66, 0x41, 0x68, 0x3f, 0x69, 0x3d, 0x69, 0x3b, 0x6c, 0x3a, 0x6e, + 0x3a, 0x6e, 0x3a, 0x6d, 0x39, 0x6c, 0x3a, 0x6a, 0x3c, 0x6a, 0x3e, 0x69, + 0x41, 0x66, 0x41, 0x66, 0x43, 0x67, 0x45, 0x66, 0x44, 0x65, 0x42, 0x65, + 0x44, 0x69, 0x53, 0x71, 0x78, 0x77, 0x80, 0x7c, 0x66, 0x7d, 0x5d, 0x7a, + 0x73, 0x7b, 0x8b, 0x88, 0x7f, 0x86, 0x51, 0x89, 0x47, 0x86, 0x43, 0x7e, + 0x3c, 0x77, 0x3e, 0x78, 0x2e, 0x86, 0x2e, 0x87, 0x38, 0x82, 0x49, 0x7e, + 0x54, 0x7c, 0x69, 0x7e, 0x70, 0x7f, 0x6a, 0x7f, 0x62, 0x7d, 0x61, 0x7c, + 0x6b, 0x82, 0x72, 0x86, 0x71, 0x86, 0x67, 0x85, 0x68, 0x84, 0x74, 0x81, + 0x73, 0x7d, 0x5e, 0x7d, 0x56, 0x7e, 0x5e, 0x80, 0x64, 0x7a, 0x63, 0x7a, + 0x63, 0x7a, 0x64, 0x7a, 0x64, 0x79, 0x67, 0x78, 0x6a, 0x78, 0x6d, 0x77, + 0x70, 0x77, 0x74, 0x77, 0x78, 0x77, 0x7d, 0x78, 0x7f, 0x78, 0x7d, 0x77, + 0x7e, 0x78, 0x7c, 0x77, 0x7c, 0x77, 0x7c, 0x76, 0x7c, 0x75, 0x7b, 0x75, + 0x7b, 0x75, 0x7a, 0x75, 0x7a, 0x75, 0x7a, 0x74, 0x7a, 0x73, 0x79, 0x72, + 0x77, 0x72, 0x78, 0x72, 0x77, 0x72, 0x77, 0x72, 0x77, 0x70, 0x77, 0x70, + 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, 0x77, 0x6f, + 0x77, 0x6f, 0x77, 0x6f, 0x78, 0x6f, 0x78, 0x6f, 0x78, 0x6f, 0x79, 0x6f, + 0x79, 0x6f, 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x70, 0x7b, 0x70, 0x7b, 0x6f, + 0x7b, 0x71, 0x7b, 0x72, 0x7a, 0x70, 0x7a, 0x71, 0x7e, 0x7c, 0x81, 0x7f, + 0x80, 0x81, 0x80, 0x80, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, + 0x7f, 0x80, 0x7f, 0x80, 0x54, 0x59, 0x54, 0x56, 0x53, 0x58, 0x52, 0x5b, + 0x52, 0x5b, 0x53, 0x5b, 0x53, 0x59, 0x52, 0x5c, 0x52, 0x5f, 0x52, 0x5f, + 0x51, 0x60, 0x50, 0x62, 0x50, 0x63, 0x50, 0x64, 0x4f, 0x65, 0x4e, 0x66, + 0x4e, 0x66, 0x4d, 0x66, 0x4c, 0x66, 0x4c, 0x67, 0x4b, 0x67, 0x4c, 0x68, + 0x4d, 0x66, 0x4d, 0x65, 0x4f, 0x65, 0x52, 0x65, 0x56, 0x65, 0x5b, 0x67, + 0x64, 0x6a, 0x6a, 0x6c, 0x72, 0x6e, 0x77, 0x70, 0x78, 0x70, 0x78, 0x71, + 0x77, 0x71, 0x76, 0x70, 0x70, 0x6d, 0x68, 0x6c, 0x5e, 0x6a, 0x56, 0x68, + 0x48, 0x66, 0x40, 0x66, 0x40, 0x65, 0x40, 0x65, 0x41, 0x67, 0x40, 0x67, + 0x3f, 0x69, 0x3d, 0x6a, 0x3b, 0x6b, 0x39, 0x6c, 0x39, 0x6c, 0x39, 0x6b, + 0x39, 0x6b, 0x3a, 0x6b, 0x3c, 0x69, 0x3d, 0x69, 0x3f, 0x66, 0x40, 0x66, + 0x42, 0x67, 0x44, 0x65, 0x44, 0x63, 0x43, 0x65, 0x44, 0x6a, 0x52, 0x72, + 0x7a, 0x7c, 0x81, 0x82, 0x62, 0x82, 0x5f, 0x7b, 0x79, 0x7c, 0x8a, 0x88, + 0x76, 0x86, 0x4b, 0x8c, 0x44, 0x8b, 0x3f, 0x82, 0x32, 0x7c, 0x36, 0x7a, + 0x31, 0x88, 0x2f, 0x89, 0x31, 0x83, 0x4d, 0x7e, 0x61, 0x7c, 0x6c, 0x7d, + 0x73, 0x80, 0x6d, 0x7f, 0x61, 0x7e, 0x61, 0x7e, 0x6b, 0x7f, 0x70, 0x83, + 0x71, 0x84, 0x68, 0x84, 0x65, 0x84, 0x6e, 0x82, 0x66, 0x7f, 0x56, 0x80, + 0x5a, 0x7c, 0x61, 0x7b, 0x65, 0x7a, 0x65, 0x7a, 0x65, 0x79, 0x66, 0x79, + 0x67, 0x78, 0x6a, 0x78, 0x6d, 0x78, 0x70, 0x77, 0x73, 0x77, 0x77, 0x77, + 0x7d, 0x77, 0x7f, 0x78, 0x80, 0x77, 0x7e, 0x77, 0x7e, 0x77, 0x7d, 0x77, + 0x7d, 0x78, 0x7d, 0x76, 0x7d, 0x75, 0x7c, 0x74, 0x7b, 0x75, 0x7b, 0x75, + 0x7b, 0x74, 0x7b, 0x74, 0x7a, 0x73, 0x7a, 0x72, 0x79, 0x72, 0x79, 0x72, + 0x77, 0x72, 0x77, 0x72, 0x77, 0x71, 0x77, 0x71, 0x78, 0x6f, 0x77, 0x6f, + 0x77, 0x70, 0x78, 0x70, 0x78, 0x70, 0x77, 0x70, 0x77, 0x6f, 0x77, 0x6f, + 0x78, 0x6f, 0x79, 0x6f, 0x79, 0x6f, 0x79, 0x6f, 0x7a, 0x6f, 0x7a, 0x6f, + 0x7b, 0x6f, 0x7b, 0x70, 0x7b, 0x70, 0x7b, 0x70, 0x7b, 0x71, 0x7b, 0x71, + 0x7b, 0x6f, 0x7a, 0x70, 0x7e, 0x7c, 0x80, 0x7f, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x7f, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x7f, + 0x54, 0x5b, 0x54, 0x59, 0x53, 0x5a, 0x53, 0x5d, 0x52, 0x5d, 0x52, 0x5d, + 0x52, 0x5d, 0x52, 0x5e, 0x51, 0x60, 0x52, 0x5f, 0x52, 0x60, 0x51, 0x62, + 0x51, 0x62, 0x51, 0x64, 0x50, 0x65, 0x4f, 0x65, 0x4e, 0x66, 0x4d, 0x66, + 0x4d, 0x65, 0x4c, 0x67, 0x4b, 0x67, 0x4c, 0x68, 0x4c, 0x66, 0x4d, 0x65, + 0x4e, 0x65, 0x51, 0x65, 0x55, 0x65, 0x5b, 0x66, 0x65, 0x68, 0x6b, 0x6c, + 0x71, 0x6f, 0x76, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, + 0x71, 0x6e, 0x6c, 0x6c, 0x64, 0x6a, 0x5b, 0x69, 0x51, 0x66, 0x44, 0x65, + 0x40, 0x66, 0x3f, 0x67, 0x3f, 0x67, 0x3f, 0x67, 0x3f, 0x68, 0x3e, 0x6a, + 0x3c, 0x6a, 0x3b, 0x6b, 0x3b, 0x6a, 0x39, 0x6a, 0x39, 0x6a, 0x39, 0x6b, + 0x3b, 0x69, 0x3d, 0x68, 0x3f, 0x66, 0x40, 0x65, 0x41, 0x65, 0x43, 0x64, + 0x44, 0x62, 0x44, 0x63, 0x44, 0x69, 0x52, 0x72, 0x80, 0x81, 0x8a, 0x85, + 0x63, 0x82, 0x65, 0x7a, 0x79, 0x7d, 0x77, 0x85, 0x65, 0x84, 0x46, 0x8b, + 0x34, 0x8c, 0x34, 0x85, 0x2d, 0x84, 0x31, 0x80, 0x2c, 0x88, 0x29, 0x89, + 0x2b, 0x85, 0x3a, 0x82, 0x42, 0x81, 0x42, 0x7f, 0x49, 0x7e, 0x4f, 0x7c, + 0x6f, 0x7f, 0x7b, 0x82, 0x6e, 0x81, 0x57, 0x80, 0x5c, 0x81, 0x5f, 0x80, + 0x55, 0x81, 0x5d, 0x81, 0x53, 0x7f, 0x50, 0x7f, 0x60, 0x7c, 0x68, 0x7a, + 0x65, 0x7a, 0x67, 0x7a, 0x67, 0x79, 0x6a, 0x78, 0x6c, 0x77, 0x6e, 0x77, + 0x71, 0x77, 0x74, 0x77, 0x79, 0x77, 0x7b, 0x77, 0x7f, 0x77, 0x7f, 0x77, + 0x7f, 0x77, 0x7f, 0x78, 0x7f, 0x77, 0x7d, 0x77, 0x7e, 0x77, 0x7e, 0x76, + 0x7e, 0x75, 0x7d, 0x74, 0x7d, 0x75, 0x7d, 0x75, 0x7d, 0x74, 0x7c, 0x74, + 0x7b, 0x73, 0x7a, 0x73, 0x7a, 0x72, 0x79, 0x72, 0x78, 0x72, 0x78, 0x72, + 0x77, 0x72, 0x77, 0x72, 0x77, 0x70, 0x77, 0x70, 0x78, 0x70, 0x78, 0x71, + 0x78, 0x70, 0x78, 0x70, 0x78, 0x6f, 0x78, 0x6f, 0x79, 0x6f, 0x7b, 0x6f, + 0x7a, 0x6f, 0x7a, 0x6f, 0x7b, 0x6f, 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x70, + 0x7b, 0x70, 0x7b, 0x70, 0x7b, 0x70, 0x7b, 0x70, 0x7b, 0x70, 0x7a, 0x70, + 0x7d, 0x7b, 0x7f, 0x7f, 0x80, 0x80, 0x7f, 0x7f, 0x80, 0x80, 0x7f, 0x80, + 0x7f, 0x80, 0x7f, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x54, 0x5f, 0x54, 0x5d, + 0x54, 0x5c, 0x53, 0x5e, 0x52, 0x5e, 0x51, 0x5e, 0x51, 0x5e, 0x51, 0x60, + 0x51, 0x61, 0x52, 0x61, 0x52, 0x61, 0x52, 0x62, 0x52, 0x61, 0x51, 0x65, + 0x50, 0x66, 0x4f, 0x65, 0x4f, 0x66, 0x4e, 0x66, 0x4d, 0x66, 0x4c, 0x67, + 0x4b, 0x67, 0x4c, 0x68, 0x4c, 0x66, 0x4d, 0x64, 0x4e, 0x65, 0x52, 0x65, + 0x54, 0x65, 0x5a, 0x66, 0x65, 0x69, 0x6b, 0x6b, 0x71, 0x6f, 0x76, 0x6f, + 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x71, 0x75, 0x70, 0x72, 0x6e, + 0x6b, 0x6b, 0x61, 0x69, 0x58, 0x66, 0x49, 0x66, 0x42, 0x66, 0x3e, 0x67, + 0x3f, 0x67, 0x3f, 0x67, 0x40, 0x68, 0x3f, 0x6b, 0x3c, 0x6b, 0x3b, 0x6b, + 0x3b, 0x6b, 0x39, 0x6b, 0x39, 0x6b, 0x39, 0x6b, 0x3b, 0x68, 0x3c, 0x68, + 0x3e, 0x66, 0x3f, 0x64, 0x42, 0x63, 0x44, 0x62, 0x44, 0x62, 0x43, 0x64, + 0x44, 0x6a, 0x53, 0x73, 0x80, 0x80, 0x85, 0x85, 0x5c, 0x82, 0x68, 0x7a, + 0x7a, 0x7f, 0x6b, 0x83, 0x5d, 0x83, 0x54, 0x88, 0x35, 0x8a, 0x29, 0x88, + 0x31, 0x88, 0x38, 0x86, 0x30, 0x88, 0x2b, 0x89, 0x30, 0x88, 0x2f, 0x88, + 0x2a, 0x89, 0x29, 0x8d, 0x28, 0x89, 0x38, 0x84, 0x5b, 0x84, 0x5f, 0x85, + 0x49, 0x86, 0x33, 0x85, 0x38, 0x84, 0x49, 0x7e, 0x49, 0x7d, 0x52, 0x7e, + 0x4e, 0x7f, 0x56, 0x7f, 0x67, 0x7c, 0x6c, 0x7a, 0x66, 0x79, 0x66, 0x7a, + 0x68, 0x79, 0x6b, 0x78, 0x6f, 0x77, 0x72, 0x77, 0x74, 0x77, 0x77, 0x77, + 0x7d, 0x77, 0x7e, 0x77, 0x7e, 0x77, 0x7f, 0x78, 0x7f, 0x78, 0x7f, 0x78, + 0x7f, 0x78, 0x7e, 0x77, 0x7e, 0x77, 0x7e, 0x76, 0x7d, 0x75, 0x7e, 0x75, + 0x7e, 0x74, 0x7d, 0x75, 0x7d, 0x74, 0x7b, 0x73, 0x7a, 0x73, 0x7a, 0x72, + 0x7a, 0x72, 0x7a, 0x71, 0x78, 0x71, 0x78, 0x72, 0x78, 0x72, 0x77, 0x72, + 0x77, 0x70, 0x77, 0x70, 0x78, 0x70, 0x78, 0x70, 0x78, 0x70, 0x78, 0x70, + 0x78, 0x70, 0x78, 0x6e, 0x79, 0x6f, 0x7a, 0x6e, 0x7a, 0x6f, 0x7b, 0x6f, + 0x7b, 0x6f, 0x7a, 0x6f, 0x7a, 0x6f, 0x7a, 0x70, 0x7a, 0x70, 0x7a, 0x70, + 0x7b, 0x70, 0x7b, 0x70, 0x7a, 0x70, 0x7b, 0x70, 0x7d, 0x7b, 0x7f, 0x7f, + 0x7f, 0x80, 0x7f, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x80, 0x7f, 0x7f, 0x55, 0x61, 0x54, 0x60, 0x54, 0x5f, 0x53, 0x60, + 0x52, 0x60, 0x51, 0x60, 0x51, 0x5f, 0x51, 0x61, 0x51, 0x63, 0x51, 0x62, + 0x52, 0x61, 0x51, 0x62, 0x51, 0x62, 0x51, 0x64, 0x50, 0x64, 0x50, 0x64, + 0x4f, 0x65, 0x4e, 0x65, 0x4d, 0x66, 0x4c, 0x67, 0x4b, 0x67, 0x4c, 0x68, + 0x4c, 0x66, 0x4d, 0x65, 0x4e, 0x65, 0x51, 0x66, 0x55, 0x67, 0x5b, 0x67, + 0x65, 0x69, 0x6c, 0x6c, 0x72, 0x6f, 0x76, 0x6f, 0x77, 0x70, 0x77, 0x70, + 0x77, 0x70, 0x78, 0x71, 0x76, 0x70, 0x75, 0x6f, 0x71, 0x6d, 0x67, 0x6a, + 0x5d, 0x67, 0x51, 0x66, 0x48, 0x66, 0x3f, 0x68, 0x3d, 0x67, 0x3e, 0x67, + 0x40, 0x68, 0x3f, 0x6a, 0x3c, 0x6a, 0x3b, 0x6b, 0x3b, 0x6a, 0x3a, 0x6a, + 0x3a, 0x6a, 0x3a, 0x6a, 0x3b, 0x69, 0x3b, 0x68, 0x3e, 0x65, 0x3f, 0x63, + 0x42, 0x62, 0x43, 0x62, 0x44, 0x61, 0x43, 0x66, 0x44, 0x6e, 0x51, 0x76, + 0x6d, 0x7f, 0x67, 0x83, 0x4e, 0x81, 0x66, 0x7b, 0x7e, 0x80, 0x6c, 0x83, + 0x60, 0x84, 0x6c, 0x85, 0x51, 0x87, 0x2a, 0x8a, 0x2a, 0x8b, 0x31, 0x89, + 0x3b, 0x89, 0x3a, 0x8a, 0x3b, 0x8a, 0x37, 0x8b, 0x33, 0x8c, 0x33, 0x8d, + 0x34, 0x8a, 0x36, 0x87, 0x39, 0x87, 0x3a, 0x87, 0x33, 0x88, 0x30, 0x88, + 0x35, 0x85, 0x4a, 0x80, 0x52, 0x7f, 0x54, 0x7f, 0x5c, 0x7f, 0x6b, 0x80, + 0x6a, 0x7c, 0x6a, 0x7a, 0x65, 0x7a, 0x66, 0x7c, 0x66, 0x7a, 0x6b, 0x78, + 0x70, 0x77, 0x75, 0x77, 0x77, 0x77, 0x79, 0x77, 0x80, 0x77, 0x80, 0x77, + 0x7f, 0x76, 0x7f, 0x76, 0x7f, 0x77, 0x80, 0x77, 0x7f, 0x77, 0x7d, 0x76, + 0x7d, 0x76, 0x7e, 0x76, 0x7e, 0x76, 0x7e, 0x75, 0x7e, 0x74, 0x7e, 0x74, + 0x7d, 0x74, 0x7c, 0x73, 0x7b, 0x73, 0x7b, 0x73, 0x7a, 0x72, 0x7a, 0x72, + 0x79, 0x72, 0x79, 0x72, 0x77, 0x72, 0x76, 0x72, 0x77, 0x71, 0x77, 0x71, + 0x78, 0x71, 0x78, 0x70, 0x78, 0x70, 0x78, 0x70, 0x78, 0x70, 0x79, 0x70, + 0x79, 0x70, 0x79, 0x6f, 0x79, 0x70, 0x7b, 0x6f, 0x7b, 0x6f, 0x7b, 0x6f, + 0x7b, 0x6f, 0x7b, 0x70, 0x7b, 0x71, 0x7a, 0x70, 0x7a, 0x70, 0x7a, 0x70, + 0x7a, 0x70, 0x7b, 0x71, 0x7d, 0x7c, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x7f, + 0x80, 0x7f, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x7f, + 0x55, 0x60, 0x55, 0x61, 0x53, 0x62, 0x53, 0x62, 0x52, 0x62, 0x51, 0x62, + 0x51, 0x61, 0x51, 0x63, 0x51, 0x65, 0x51, 0x64, 0x51, 0x61, 0x51, 0x62, + 0x51, 0x62, 0x51, 0x63, 0x51, 0x63, 0x50, 0x63, 0x51, 0x63, 0x4e, 0x65, + 0x4d, 0x66, 0x4c, 0x67, 0x4c, 0x67, 0x4c, 0x68, 0x4c, 0x67, 0x4c, 0x65, + 0x4e, 0x65, 0x51, 0x66, 0x56, 0x68, 0x5d, 0x67, 0x66, 0x69, 0x6e, 0x6c, + 0x73, 0x6f, 0x76, 0x6f, 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, + 0x76, 0x70, 0x76, 0x71, 0x74, 0x6f, 0x6c, 0x6c, 0x64, 0x69, 0x59, 0x67, + 0x51, 0x68, 0x46, 0x68, 0x3f, 0x67, 0x3d, 0x67, 0x3e, 0x68, 0x3e, 0x68, + 0x3e, 0x68, 0x3c, 0x69, 0x3b, 0x69, 0x3b, 0x68, 0x3b, 0x68, 0x3b, 0x68, + 0x3b, 0x68, 0x3b, 0x67, 0x3d, 0x64, 0x3e, 0x63, 0x41, 0x61, 0x42, 0x60, + 0x43, 0x60, 0x42, 0x68, 0x46, 0x72, 0x49, 0x79, 0x45, 0x7e, 0x44, 0x81, + 0x4d, 0x7f, 0x68, 0x7b, 0x80, 0x82, 0x6a, 0x85, 0x68, 0x86, 0x78, 0x84, + 0x76, 0x85, 0x4e, 0x8a, 0x26, 0x8e, 0x2a, 0x8c, 0x3a, 0x8b, 0x42, 0x89, + 0x47, 0x87, 0x44, 0x88, 0x42, 0x88, 0x41, 0x89, 0x45, 0x88, 0x47, 0x87, + 0x47, 0x86, 0x46, 0x86, 0x47, 0x85, 0x4d, 0x85, 0x51, 0x82, 0x53, 0x81, + 0x51, 0x82, 0x60, 0x82, 0x75, 0x81, 0x73, 0x81, 0x6a, 0x7b, 0x6a, 0x79, + 0x66, 0x79, 0x68, 0x7d, 0x62, 0x7d, 0x63, 0x7b, 0x6d, 0x77, 0x77, 0x75, + 0x7e, 0x75, 0x80, 0x75, 0x82, 0x76, 0x81, 0x77, 0x7f, 0x75, 0x7f, 0x76, + 0x7f, 0x78, 0x81, 0x74, 0x81, 0x74, 0x7e, 0x76, 0x7d, 0x75, 0x7f, 0x76, + 0x80, 0x77, 0x7e, 0x75, 0x7e, 0x75, 0x7e, 0x73, 0x7d, 0x73, 0x7d, 0x73, + 0x7d, 0x73, 0x7d, 0x73, 0x7b, 0x73, 0x7b, 0x73, 0x7a, 0x72, 0x7a, 0x72, + 0x78, 0x72, 0x77, 0x72, 0x78, 0x72, 0x78, 0x72, 0x78, 0x71, 0x78, 0x70, + 0x78, 0x70, 0x78, 0x70, 0x79, 0x70, 0x7a, 0x71, 0x7a, 0x71, 0x79, 0x71, + 0x7a, 0x71, 0x7b, 0x6f, 0x7b, 0x6f, 0x7c, 0x70, 0x7d, 0x71, 0x7d, 0x70, + 0x7d, 0x71, 0x7b, 0x70, 0x7b, 0x70, 0x7a, 0x70, 0x7a, 0x70, 0x7b, 0x72, + 0x7e, 0x7b, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x7f, + 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x55, 0x60, 0x55, 0x60, + 0x54, 0x63, 0x52, 0x63, 0x52, 0x63, 0x51, 0x63, 0x51, 0x61, 0x51, 0x63, + 0x50, 0x65, 0x51, 0x64, 0x51, 0x61, 0x51, 0x62, 0x51, 0x62, 0x51, 0x63, + 0x51, 0x63, 0x51, 0x63, 0x51, 0x63, 0x4f, 0x65, 0x4e, 0x66, 0x4c, 0x67, + 0x4b, 0x67, 0x4c, 0x68, 0x4c, 0x66, 0x4c, 0x65, 0x4e, 0x65, 0x51, 0x67, + 0x56, 0x67, 0x5d, 0x68, 0x67, 0x69, 0x6f, 0x6b, 0x73, 0x6f, 0x76, 0x6f, + 0x77, 0x71, 0x77, 0x70, 0x77, 0x70, 0x77, 0x70, 0x76, 0x70, 0x76, 0x70, + 0x75, 0x70, 0x70, 0x6d, 0x69, 0x6a, 0x61, 0x69, 0x5b, 0x69, 0x4e, 0x67, + 0x46, 0x68, 0x3f, 0x67, 0x3d, 0x68, 0x3e, 0x68, 0x3e, 0x68, 0x3d, 0x68, + 0x3c, 0x68, 0x3b, 0x68, 0x3b, 0x68, 0x3b, 0x67, 0x3b, 0x67, 0x3b, 0x66, + 0x3d, 0x63, 0x3e, 0x63, 0x40, 0x61, 0x42, 0x60, 0x43, 0x60, 0x43, 0x69, + 0x4b, 0x75, 0x4b, 0x7b, 0x3c, 0x7f, 0x44, 0x83, 0x53, 0x7f, 0x6d, 0x7c, + 0x81, 0x84, 0x6c, 0x83, 0x69, 0x86, 0x70, 0x84, 0x7d, 0x82, 0x75, 0x87, + 0x3a, 0x8d, 0x29, 0x90, 0x30, 0x8d, 0x47, 0x87, 0x56, 0x83, 0x57, 0x83, + 0x55, 0x83, 0x4f, 0x82, 0x4f, 0x82, 0x4e, 0x83, 0x4f, 0x85, 0x51, 0x84, + 0x4f, 0x82, 0x52, 0x81, 0x53, 0x81, 0x54, 0x81, 0x5b, 0x82, 0x71, 0x83, + 0x79, 0x83, 0x6f, 0x80, 0x69, 0x7b, 0x6e, 0x79, 0x67, 0x76, 0x68, 0x7c, + 0x5f, 0x81, 0x58, 0x80, 0x67, 0x75, 0x73, 0x72, 0x7e, 0x72, 0x7e, 0x74, + 0x77, 0x78, 0x73, 0x7a, 0x71, 0x7a, 0x70, 0x7c, 0x6f, 0x7e, 0x75, 0x7a, + 0x7f, 0x77, 0x80, 0x75, 0x7f, 0x76, 0x7f, 0x75, 0x7f, 0x75, 0x7e, 0x75, + 0x7d, 0x75, 0x7d, 0x73, 0x7d, 0x72, 0x7d, 0x73, 0x7d, 0x73, 0x7c, 0x73, + 0x7b, 0x73, 0x7b, 0x73, 0x7a, 0x72, 0x7a, 0x72, 0x79, 0x72, 0x78, 0x72, + 0x78, 0x72, 0x78, 0x72, 0x78, 0x71, 0x77, 0x70, 0x79, 0x70, 0x7a, 0x70, + 0x7a, 0x70, 0x7a, 0x70, 0x7a, 0x70, 0x7b, 0x71, 0x7b, 0x70, 0x7d, 0x6f, + 0x7c, 0x6f, 0x7c, 0x70, 0x7c, 0x70, 0x7c, 0x70, 0x7d, 0x70, 0x7d, 0x70, + 0x7d, 0x70, 0x7c, 0x71, 0x7c, 0x70, 0x7c, 0x72, 0x7e, 0x79, 0x7f, 0x7e, + 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x80, + 0x7f, 0x80, 0x7f, 0x7f, 0x56, 0x61, 0x55, 0x60, 0x53, 0x63, 0x52, 0x65, + 0x52, 0x65, 0x51, 0x64, 0x51, 0x62, 0x51, 0x63, 0x51, 0x65, 0x51, 0x63, + 0x51, 0x62, 0x50, 0x62, 0x51, 0x63, 0x51, 0x64, 0x51, 0x64, 0x50, 0x64, + 0x50, 0x64, 0x4e, 0x65, 0x4e, 0x66, 0x4d, 0x67, 0x4b, 0x67, 0x4c, 0x68, + 0x4c, 0x67, 0x4c, 0x65, 0x4e, 0x65, 0x51, 0x67, 0x57, 0x68, 0x5e, 0x67, + 0x69, 0x69, 0x70, 0x6c, 0x73, 0x6f, 0x75, 0x6f, 0x77, 0x70, 0x77, 0x70, + 0x77, 0x70, 0x77, 0x70, 0x75, 0x70, 0x75, 0x70, 0x76, 0x70, 0x74, 0x6f, + 0x6f, 0x6c, 0x6a, 0x6b, 0x64, 0x69, 0x59, 0x67, 0x51, 0x67, 0x48, 0x67, + 0x3f, 0x67, 0x3e, 0x68, 0x3d, 0x67, 0x3d, 0x66, 0x3d, 0x66, 0x3c, 0x67, + 0x3c, 0x68, 0x3c, 0x65, 0x3b, 0x65, 0x3b, 0x65, 0x3c, 0x63, 0x3d, 0x63, + 0x3f, 0x62, 0x42, 0x61, 0x42, 0x60, 0x45, 0x68, 0x54, 0x72, 0x59, 0x7b, + 0x55, 0x82, 0x5c, 0x85, 0x5b, 0x7d, 0x73, 0x7c, 0x7f, 0x84, 0x6c, 0x82, + 0x5b, 0x86, 0x5f, 0x85, 0x78, 0x7c, 0x80, 0x7e, 0x6d, 0x87, 0x4f, 0x8c, + 0x39, 0x8c, 0x50, 0x88, 0x5e, 0x82, 0x57, 0x80, 0x59, 0x80, 0x5c, 0x7e, + 0x5b, 0x80, 0x59, 0x80, 0x5c, 0x7f, 0x62, 0x7e, 0x6b, 0x7e, 0x6d, 0x7e, + 0x6f, 0x7d, 0x77, 0x7e, 0x78, 0x82, 0x6d, 0x8a, 0x6f, 0x86, 0x6e, 0x7f, + 0x66, 0x7b, 0x6d, 0x79, 0x61, 0x75, 0x62, 0x7a, 0x5c, 0x82, 0x50, 0x83, + 0x60, 0x72, 0x69, 0x6f, 0x70, 0x75, 0x6c, 0x7b, 0x68, 0x7f, 0x67, 0x81, + 0x63, 0x84, 0x60, 0x88, 0x5f, 0x8b, 0x61, 0x8e, 0x6e, 0x83, 0x7d, 0x76, + 0x81, 0x75, 0x7f, 0x74, 0x80, 0x74, 0x7f, 0x74, 0x7e, 0x74, 0x7e, 0x73, + 0x7e, 0x73, 0x7d, 0x73, 0x7c, 0x73, 0x7c, 0x73, 0x7a, 0x73, 0x7a, 0x73, + 0x7a, 0x72, 0x7a, 0x72, 0x7a, 0x72, 0x7a, 0x73, 0x79, 0x72, 0x78, 0x71, + 0x78, 0x71, 0x78, 0x70, 0x7a, 0x70, 0x7b, 0x70, 0x7b, 0x70, 0x7b, 0x70, + 0x7b, 0x70, 0x7c, 0x70, 0x7d, 0x70, 0x7e, 0x6f, 0x7e, 0x70, 0x7d, 0x70, + 0x7e, 0x6f, 0x7d, 0x70, 0x7e, 0x70, 0x7e, 0x70, 0x7e, 0x70, 0x7e, 0x70, + 0x7e, 0x70, 0x7d, 0x71, 0x7e, 0x79, 0x7f, 0x7e, 0x80, 0x7f, 0x7f, 0x7f, + 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x56, 0x63, 0x54, 0x63, 0x54, 0x63, 0x52, 0x65, 0x51, 0x66, 0x51, 0x66, + 0x51, 0x65, 0x51, 0x64, 0x50, 0x64, 0x50, 0x65, 0x50, 0x65, 0x50, 0x65, + 0x50, 0x65, 0x50, 0x65, 0x50, 0x65, 0x50, 0x65, 0x50, 0x65, 0x4f, 0x65, + 0x4e, 0x65, 0x4d, 0x66, 0x4b, 0x67, 0x4c, 0x67, 0x4c, 0x67, 0x4c, 0x67, + 0x4d, 0x67, 0x52, 0x67, 0x59, 0x67, 0x60, 0x67, 0x6a, 0x69, 0x70, 0x6d, + 0x72, 0x6f, 0x74, 0x70, 0x75, 0x6f, 0x76, 0x6f, 0x76, 0x70, 0x76, 0x70, + 0x76, 0x6f, 0x75, 0x6f, 0x76, 0x6f, 0x76, 0x6f, 0x73, 0x6f, 0x6d, 0x6d, + 0x68, 0x6b, 0x60, 0x68, 0x59, 0x67, 0x51, 0x67, 0x45, 0x68, 0x3e, 0x68, + 0x3c, 0x66, 0x3d, 0x65, 0x3d, 0x65, 0x3d, 0x66, 0x3c, 0x65, 0x3c, 0x65, + 0x3c, 0x65, 0x3c, 0x64, 0x3c, 0x63, 0x3d, 0x63, 0x3f, 0x62, 0x40, 0x60, + 0x42, 0x5e, 0x49, 0x67, 0x5c, 0x72, 0x60, 0x7c, 0x68, 0x83, 0x6f, 0x84, + 0x5d, 0x7b, 0x79, 0x79, 0x78, 0x7f, 0x62, 0x80, 0x55, 0x86, 0x62, 0x86, + 0x77, 0x77, 0x79, 0x77, 0x7d, 0x80, 0x7a, 0x83, 0x65, 0x8c, 0x62, 0x8c, + 0x65, 0x86, 0x63, 0x82, 0x64, 0x81, 0x62, 0x80, 0x64, 0x81, 0x6a, 0x81, + 0x70, 0x7e, 0x76, 0x7d, 0x7d, 0x7e, 0x7f, 0x7d, 0x7e, 0x7d, 0x7f, 0x7d, + 0x7a, 0x7e, 0x70, 0x85, 0x6d, 0x86, 0x6a, 0x81, 0x5f, 0x7c, 0x63, 0x7a, + 0x5d, 0x78, 0x66, 0x77, 0x67, 0x77, 0x56, 0x7c, 0x5f, 0x6e, 0x61, 0x72, + 0x68, 0x7d, 0x6a, 0x80, 0x6d, 0x80, 0x6c, 0x84, 0x66, 0x89, 0x5f, 0x8f, + 0x5f, 0x91, 0x69, 0x8e, 0x69, 0x8a, 0x78, 0x7c, 0x80, 0x74, 0x7f, 0x74, + 0x80, 0x74, 0x80, 0x74, 0x80, 0x73, 0x80, 0x73, 0x7f, 0x73, 0x7f, 0x73, + 0x7d, 0x73, 0x7d, 0x72, 0x7b, 0x73, 0x7a, 0x73, 0x7b, 0x73, 0x7a, 0x73, + 0x7a, 0x73, 0x7a, 0x73, 0x7a, 0x72, 0x7a, 0x71, 0x7a, 0x72, 0x7a, 0x70, + 0x7a, 0x70, 0x7b, 0x70, 0x7c, 0x70, 0x7d, 0x70, 0x7c, 0x70, 0x7d, 0x70, + 0x7d, 0x71, 0x7e, 0x70, 0x7e, 0x70, 0x7f, 0x6f, 0x7f, 0x6e, 0x7f, 0x70, + 0x7f, 0x70, 0x7f, 0x70, 0x7f, 0x70, 0x7e, 0x70, 0x7d, 0x70, 0x7f, 0x70, + 0x7f, 0x79, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x56, 0x65, 0x54, 0x65, + 0x54, 0x64, 0x52, 0x67, 0x51, 0x67, 0x51, 0x67, 0x50, 0x66, 0x4f, 0x66, + 0x4f, 0x66, 0x4e, 0x66, 0x4e, 0x66, 0x4e, 0x66, 0x4f, 0x66, 0x51, 0x65, + 0x50, 0x65, 0x50, 0x65, 0x50, 0x65, 0x4f, 0x65, 0x4e, 0x65, 0x4d, 0x67, + 0x4c, 0x67, 0x4c, 0x67, 0x4c, 0x67, 0x4b, 0x68, 0x4c, 0x69, 0x53, 0x68, + 0x5b, 0x68, 0x61, 0x67, 0x6a, 0x6b, 0x70, 0x6e, 0x72, 0x6f, 0x74, 0x6f, + 0x75, 0x6f, 0x76, 0x70, 0x76, 0x70, 0x76, 0x70, 0x76, 0x6f, 0x76, 0x6f, + 0x76, 0x6f, 0x76, 0x6f, 0x75, 0x70, 0x70, 0x6f, 0x6b, 0x6d, 0x64, 0x6a, + 0x5e, 0x67, 0x57, 0x67, 0x4d, 0x68, 0x44, 0x68, 0x3d, 0x66, 0x3d, 0x65, + 0x3d, 0x66, 0x3c, 0x66, 0x3c, 0x66, 0x3c, 0x65, 0x3c, 0x65, 0x3c, 0x64, + 0x3c, 0x63, 0x3c, 0x62, 0x3e, 0x62, 0x40, 0x5f, 0x42, 0x5b, 0x4b, 0x67, + 0x61, 0x74, 0x63, 0x7a, 0x66, 0x83, 0x6b, 0x85, 0x58, 0x7a, 0x7a, 0x76, + 0x76, 0x7b, 0x5e, 0x7c, 0x5a, 0x81, 0x6b, 0x85, 0x75, 0x74, 0x72, 0x74, + 0x6a, 0x7f, 0x6b, 0x85, 0x63, 0x8f, 0x61, 0x92, 0x6a, 0x8c, 0x76, 0x82, + 0x78, 0x7f, 0x74, 0x7f, 0x74, 0x7f, 0x77, 0x80, 0x7b, 0x7f, 0x7d, 0x7e, + 0x7f, 0x7e, 0x7e, 0x7d, 0x7e, 0x7d, 0x7c, 0x7c, 0x78, 0x7c, 0x70, 0x80, + 0x6d, 0x81, 0x69, 0x80, 0x5c, 0x7e, 0x61, 0x7c, 0x60, 0x7c, 0x6a, 0x78, + 0x6e, 0x78, 0x5b, 0x7b, 0x5f, 0x73, 0x61, 0x78, 0x6d, 0x80, 0x72, 0x7f, + 0x71, 0x80, 0x6f, 0x84, 0x65, 0x8c, 0x60, 0x90, 0x6e, 0x8d, 0x78, 0x82, + 0x71, 0x83, 0x76, 0x7e, 0x7f, 0x76, 0x80, 0x74, 0x81, 0x74, 0x80, 0x74, + 0x80, 0x73, 0x80, 0x73, 0x7f, 0x73, 0x7f, 0x73, 0x7d, 0x73, 0x7d, 0x73, + 0x7d, 0x73, 0x7d, 0x73, 0x7b, 0x73, 0x7b, 0x73, 0x7a, 0x73, 0x7a, 0x73, + 0x7a, 0x73, 0x7a, 0x73, 0x7a, 0x73, 0x7a, 0x72, 0x7a, 0x71, 0x7b, 0x72, + 0x7c, 0x71, 0x7c, 0x70, 0x7c, 0x70, 0x7c, 0x70, 0x7d, 0x70, 0x7d, 0x70, + 0x7d, 0x6f, 0x7f, 0x6f, 0x7f, 0x6f, 0x7f, 0x70, 0x7f, 0x70, 0x7f, 0x70, + 0x7f, 0x71, 0x7e, 0x71, 0x7d, 0x70, 0x7e, 0x6f, 0x7f, 0x79, 0x7f, 0x7f, + 0x80, 0x7f, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x56, 0x66, 0x54, 0x66, 0x53, 0x66, 0x52, 0x68, + 0x51, 0x68, 0x51, 0x68, 0x4f, 0x67, 0x4e, 0x67, 0x4e, 0x68, 0x4d, 0x67, + 0x4d, 0x67, 0x4d, 0x67, 0x4e, 0x66, 0x50, 0x64, 0x50, 0x65, 0x50, 0x64, + 0x51, 0x64, 0x4f, 0x65, 0x4f, 0x65, 0x4e, 0x66, 0x4c, 0x67, 0x4c, 0x67, + 0x4b, 0x68, 0x4b, 0x69, 0x4c, 0x6a, 0x54, 0x69, 0x5c, 0x68, 0x62, 0x68, + 0x6a, 0x6c, 0x6f, 0x6f, 0x72, 0x6f, 0x74, 0x6f, 0x75, 0x6f, 0x75, 0x6f, + 0x75, 0x70, 0x75, 0x70, 0x75, 0x6f, 0x75, 0x6f, 0x75, 0x6f, 0x75, 0x6f, + 0x76, 0x71, 0x73, 0x70, 0x71, 0x6e, 0x69, 0x6b, 0x63, 0x69, 0x5f, 0x68, + 0x58, 0x68, 0x50, 0x68, 0x44, 0x66, 0x3d, 0x65, 0x3d, 0x66, 0x3c, 0x66, + 0x3c, 0x65, 0x3c, 0x64, 0x3c, 0x64, 0x3c, 0x63, 0x3c, 0x64, 0x3c, 0x62, + 0x3d, 0x60, 0x3f, 0x61, 0x44, 0x60, 0x53, 0x6b, 0x66, 0x75, 0x69, 0x7a, + 0x5e, 0x83, 0x5e, 0x85, 0x50, 0x7a, 0x6e, 0x72, 0x78, 0x76, 0x61, 0x78, + 0x5e, 0x7b, 0x65, 0x81, 0x6e, 0x7d, 0x6a, 0x7e, 0x4e, 0x86, 0x4c, 0x89, + 0x53, 0x8e, 0x59, 0x92, 0x66, 0x92, 0x7d, 0x83, 0x7e, 0x7f, 0x7b, 0x80, + 0x7b, 0x80, 0x7b, 0x80, 0x7a, 0x7f, 0x7a, 0x7e, 0x79, 0x7e, 0x78, 0x7e, + 0x79, 0x7d, 0x76, 0x7e, 0x72, 0x7f, 0x6d, 0x80, 0x69, 0x7c, 0x5f, 0x85, + 0x56, 0x86, 0x5d, 0x84, 0x5f, 0x84, 0x5f, 0x87, 0x5b, 0x89, 0x5a, 0x82, + 0x62, 0x7e, 0x67, 0x7f, 0x73, 0x7f, 0x78, 0x7f, 0x79, 0x80, 0x71, 0x87, + 0x64, 0x90, 0x73, 0x8d, 0x7e, 0x85, 0x79, 0x7f, 0x70, 0x7c, 0x73, 0x79, + 0x7b, 0x77, 0x7d, 0x75, 0x7f, 0x75, 0x80, 0x73, 0x80, 0x73, 0x80, 0x73, + 0x7f, 0x73, 0x7e, 0x73, 0x7e, 0x73, 0x7e, 0x73, 0x7e, 0x73, 0x7e, 0x73, + 0x7b, 0x73, 0x7b, 0x73, 0x7a, 0x73, 0x7a, 0x73, 0x7a, 0x75, 0x7b, 0x75, + 0x7a, 0x75, 0x7a, 0x73, 0x7b, 0x72, 0x7b, 0x73, 0x7c, 0x72, 0x7c, 0x71, + 0x7d, 0x70, 0x7d, 0x70, 0x7e, 0x70, 0x7d, 0x71, 0x7e, 0x70, 0x7f, 0x6f, + 0x7f, 0x6f, 0x7f, 0x70, 0x7f, 0x70, 0x7f, 0x70, 0x7f, 0x71, 0x7f, 0x73, + 0x7d, 0x6f, 0x7e, 0x6e, 0x7f, 0x79, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x56, 0x65, 0x54, 0x67, 0x53, 0x68, 0x52, 0x67, 0x51, 0x66, 0x51, 0x65, + 0x50, 0x66, 0x4e, 0x69, 0x4e, 0x68, 0x4d, 0x66, 0x4e, 0x67, 0x4e, 0x67, + 0x4e, 0x66, 0x4f, 0x64, 0x50, 0x64, 0x50, 0x62, 0x50, 0x62, 0x4f, 0x65, + 0x4f, 0x66, 0x4e, 0x66, 0x4d, 0x65, 0x4b, 0x66, 0x4b, 0x68, 0x4b, 0x69, + 0x4e, 0x68, 0x56, 0x68, 0x5b, 0x68, 0x63, 0x69, 0x6c, 0x6c, 0x6f, 0x6e, + 0x71, 0x6f, 0x73, 0x6f, 0x74, 0x6f, 0x74, 0x6f, 0x75, 0x6f, 0x75, 0x6e, + 0x72, 0x6f, 0x72, 0x6f, 0x73, 0x6f, 0x72, 0x6f, 0x74, 0x70, 0x75, 0x70, + 0x75, 0x70, 0x6e, 0x6c, 0x67, 0x6b, 0x63, 0x6a, 0x5a, 0x68, 0x55, 0x68, + 0x4c, 0x66, 0x41, 0x66, 0x3e, 0x66, 0x3c, 0x66, 0x3b, 0x65, 0x3c, 0x62, + 0x3c, 0x63, 0x3c, 0x63, 0x3b, 0x63, 0x3c, 0x60, 0x40, 0x62, 0x47, 0x6d, + 0x51, 0x70, 0x5d, 0x76, 0x66, 0x79, 0x6a, 0x7b, 0x5f, 0x7f, 0x5f, 0x82, + 0x44, 0x7d, 0x5e, 0x70, 0x71, 0x74, 0x64, 0x77, 0x69, 0x76, 0x64, 0x7c, + 0x70, 0x85, 0x77, 0x88, 0x56, 0x8c, 0x57, 0x8c, 0x60, 0x8c, 0x56, 0x92, + 0x5c, 0x94, 0x75, 0x85, 0x75, 0x82, 0x70, 0x84, 0x6f, 0x83, 0x6f, 0x83, + 0x6e, 0x7f, 0x6f, 0x7f, 0x70, 0x80, 0x70, 0x80, 0x72, 0x80, 0x72, 0x7f, + 0x70, 0x80, 0x6d, 0x7f, 0x67, 0x7d, 0x57, 0x8e, 0x51, 0x95, 0x54, 0x94, + 0x55, 0x94, 0x4e, 0x94, 0x4a, 0x90, 0x5c, 0x80, 0x62, 0x82, 0x6b, 0x80, + 0x77, 0x7f, 0x7c, 0x7e, 0x7a, 0x81, 0x6a, 0x8c, 0x67, 0x91, 0x7b, 0x8a, + 0x7a, 0x83, 0x73, 0x83, 0x70, 0x7c, 0x74, 0x78, 0x75, 0x76, 0x76, 0x74, + 0x77, 0x72, 0x7b, 0x70, 0x7f, 0x72, 0x81, 0x74, 0x7f, 0x73, 0x7d, 0x73, + 0x7f, 0x73, 0x7f, 0x73, 0x7d, 0x73, 0x7d, 0x73, 0x7d, 0x75, 0x7d, 0x75, + 0x7b, 0x74, 0x7b, 0x73, 0x7b, 0x75, 0x7a, 0x75, 0x7b, 0x73, 0x7b, 0x73, + 0x7c, 0x73, 0x7d, 0x73, 0x7d, 0x73, 0x7d, 0x73, 0x7e, 0x72, 0x7f, 0x70, + 0x7f, 0x70, 0x80, 0x71, 0x80, 0x6f, 0x80, 0x6f, 0x80, 0x6f, 0x80, 0x6f, + 0x80, 0x6f, 0x80, 0x6f, 0x80, 0x71, 0x80, 0x73, 0x80, 0x6f, 0x80, 0x70, + 0x7f, 0x79, 0x7f, 0x7e, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x57, 0x65, 0x54, 0x67, + 0x53, 0x67, 0x53, 0x67, 0x52, 0x67, 0x51, 0x67, 0x50, 0x66, 0x4f, 0x69, + 0x4e, 0x69, 0x4d, 0x68, 0x4d, 0x68, 0x4d, 0x67, 0x4e, 0x67, 0x4f, 0x66, + 0x4f, 0x65, 0x50, 0x64, 0x50, 0x64, 0x4f, 0x65, 0x4e, 0x66, 0x4e, 0x66, + 0x4d, 0x66, 0x4c, 0x66, 0x4b, 0x68, 0x4b, 0x68, 0x50, 0x68, 0x57, 0x68, + 0x5d, 0x68, 0x64, 0x69, 0x6c, 0x6c, 0x6f, 0x6e, 0x71, 0x6f, 0x73, 0x6f, + 0x74, 0x6f, 0x75, 0x6f, 0x75, 0x6f, 0x75, 0x6f, 0x73, 0x6f, 0x73, 0x6f, + 0x73, 0x6f, 0x72, 0x6f, 0x74, 0x70, 0x76, 0x71, 0x76, 0x70, 0x71, 0x6d, + 0x6d, 0x6c, 0x68, 0x6c, 0x5f, 0x69, 0x5b, 0x68, 0x53, 0x65, 0x4c, 0x66, + 0x41, 0x65, 0x3e, 0x65, 0x3c, 0x65, 0x3c, 0x63, 0x3b, 0x63, 0x3d, 0x64, + 0x3d, 0x62, 0x45, 0x68, 0x58, 0x79, 0x64, 0x82, 0x68, 0x82, 0x6a, 0x83, + 0x69, 0x81, 0x68, 0x7e, 0x69, 0x7c, 0x6a, 0x7d, 0x4d, 0x7c, 0x49, 0x75, + 0x62, 0x74, 0x66, 0x75, 0x6c, 0x76, 0x76, 0x7b, 0x68, 0x81, 0x6d, 0x86, + 0x57, 0x8d, 0x5e, 0x8d, 0x65, 0x8c, 0x56, 0x90, 0x56, 0x8f, 0x65, 0x84, + 0x69, 0x82, 0x68, 0x84, 0x68, 0x84, 0x67, 0x83, 0x67, 0x80, 0x67, 0x7f, + 0x69, 0x80, 0x6b, 0x80, 0x6d, 0x80, 0x6e, 0x80, 0x6d, 0x7f, 0x6a, 0x7f, + 0x67, 0x7e, 0x5e, 0x89, 0x55, 0x94, 0x52, 0x98, 0x4c, 0x9a, 0x4b, 0x8f, + 0x53, 0x86, 0x60, 0x7e, 0x64, 0x82, 0x6d, 0x81, 0x76, 0x7f, 0x7a, 0x7e, + 0x73, 0x84, 0x60, 0x8d, 0x70, 0x8f, 0x7d, 0x87, 0x76, 0x84, 0x70, 0x83, + 0x73, 0x7e, 0x72, 0x7a, 0x71, 0x77, 0x70, 0x74, 0x70, 0x6f, 0x73, 0x6e, + 0x79, 0x70, 0x7e, 0x73, 0x7f, 0x73, 0x7f, 0x73, 0x7f, 0x73, 0x7f, 0x73, + 0x7d, 0x73, 0x7d, 0x73, 0x7c, 0x75, 0x7c, 0x74, 0x7b, 0x73, 0x7b, 0x73, + 0x7a, 0x75, 0x7b, 0x75, 0x7a, 0x73, 0x7a, 0x73, 0x7c, 0x73, 0x7d, 0x73, + 0x7d, 0x73, 0x7e, 0x73, 0x7e, 0x73, 0x7f, 0x72, 0x7f, 0x72, 0x80, 0x71, + 0x80, 0x6f, 0x80, 0x6f, 0x80, 0x6f, 0x80, 0x6f, 0x80, 0x6f, 0x80, 0x6f, + 0x80, 0x71, 0x80, 0x72, 0x80, 0x6f, 0x80, 0x71, 0x7f, 0x7a, 0x7f, 0x7f, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, + 0x80, 0x7f, 0x80, 0x80, 0x56, 0x65, 0x55, 0x67, 0x54, 0x67, 0x53, 0x68, + 0x52, 0x68, 0x51, 0x69, 0x4f, 0x67, 0x4e, 0x69, 0x4d, 0x6a, 0x4d, 0x6a, + 0x4d, 0x69, 0x4d, 0x68, 0x4d, 0x68, 0x4e, 0x67, 0x4e, 0x67, 0x4f, 0x66, + 0x50, 0x66, 0x4f, 0x65, 0x4e, 0x66, 0x4e, 0x66, 0x4d, 0x66, 0x4c, 0x66, + 0x4a, 0x68, 0x4c, 0x68, 0x52, 0x68, 0x59, 0x68, 0x5e, 0x68, 0x65, 0x69, + 0x6c, 0x6c, 0x6f, 0x6e, 0x71, 0x70, 0x73, 0x6f, 0x74, 0x6f, 0x74, 0x6f, + 0x74, 0x6f, 0x74, 0x6f, 0x73, 0x70, 0x73, 0x6f, 0x72, 0x6f, 0x72, 0x6e, + 0x74, 0x70, 0x76, 0x70, 0x76, 0x71, 0x75, 0x6f, 0x73, 0x6e, 0x6d, 0x6e, + 0x66, 0x6b, 0x62, 0x69, 0x5b, 0x66, 0x57, 0x66, 0x4c, 0x65, 0x40, 0x65, + 0x3d, 0x65, 0x3c, 0x63, 0x3b, 0x63, 0x3c, 0x62, 0x47, 0x6d, 0x5c, 0x81, + 0x6c, 0x8b, 0x6c, 0x89, 0x6f, 0x88, 0x75, 0x83, 0x79, 0x82, 0x6d, 0x83, + 0x6b, 0x80, 0x67, 0x7e, 0x63, 0x7c, 0x53, 0x7c, 0x54, 0x79, 0x59, 0x7d, + 0x55, 0x7c, 0x7c, 0x78, 0x71, 0x76, 0x56, 0x7d, 0x5b, 0x81, 0x66, 0x7e, + 0x6b, 0x7e, 0x61, 0x81, 0x5e, 0x80, 0x66, 0x7c, 0x67, 0x7c, 0x66, 0x7f, + 0x66, 0x80, 0x65, 0x80, 0x64, 0x80, 0x64, 0x7f, 0x66, 0x80, 0x6a, 0x80, + 0x68, 0x80, 0x69, 0x80, 0x69, 0x80, 0x66, 0x80, 0x65, 0x7f, 0x63, 0x83, + 0x5d, 0x88, 0x5b, 0x89, 0x51, 0x8b, 0x52, 0x81, 0x5b, 0x7d, 0x61, 0x81, + 0x68, 0x84, 0x6f, 0x83, 0x75, 0x80, 0x77, 0x80, 0x6a, 0x88, 0x60, 0x8e, + 0x76, 0x8f, 0x7a, 0x88, 0x75, 0x84, 0x72, 0x82, 0x72, 0x7f, 0x6e, 0x7c, + 0x6e, 0x79, 0x6d, 0x79, 0x6d, 0x70, 0x6b, 0x6b, 0x70, 0x6e, 0x7a, 0x71, + 0x7e, 0x72, 0x81, 0x73, 0x7f, 0x73, 0x7f, 0x73, 0x7d, 0x73, 0x7d, 0x73, + 0x7c, 0x75, 0x7d, 0x75, 0x7b, 0x72, 0x7b, 0x73, 0x7b, 0x75, 0x7b, 0x75, + 0x7a, 0x73, 0x7b, 0x73, 0x7c, 0x73, 0x7d, 0x73, 0x7d, 0x72, 0x7e, 0x72, + 0x7e, 0x73, 0x7f, 0x74, 0x80, 0x73, 0x80, 0x71, 0x80, 0x6f, 0x80, 0x6f, + 0x80, 0x6f, 0x81, 0x6f, 0x81, 0x6f, 0x80, 0x70, 0x80, 0x71, 0x80, 0x70, + 0x80, 0x71, 0x7f, 0x72, 0x7f, 0x7a, 0x7f, 0x7e, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x80, 0x7f, 0x80, 0x80, + 0x56, 0x66, 0x55, 0x66, 0x54, 0x66, 0x53, 0x68, 0x52, 0x69, 0x51, 0x6a, + 0x50, 0x69, 0x4e, 0x6a, 0x4d, 0x6b, 0x4c, 0x6b, 0x4c, 0x6a, 0x4c, 0x68, + 0x4c, 0x69, 0x4d, 0x68, 0x4d, 0x68, 0x4e, 0x66, 0x4e, 0x66, 0x4f, 0x65, + 0x4e, 0x66, 0x4d, 0x66, 0x4d, 0x65, 0x4c, 0x67, 0x4b, 0x68, 0x4c, 0x68, + 0x52, 0x68, 0x59, 0x69, 0x5f, 0x6a, 0x66, 0x6a, 0x6d, 0x6c, 0x6f, 0x6e, + 0x72, 0x6f, 0x73, 0x6f, 0x73, 0x6f, 0x73, 0x6f, 0x73, 0x6f, 0x73, 0x6f, + 0x72, 0x6f, 0x72, 0x6f, 0x72, 0x6e, 0x72, 0x6d, 0x73, 0x6f, 0x75, 0x70, + 0x75, 0x70, 0x75, 0x6f, 0x74, 0x6f, 0x70, 0x6e, 0x68, 0x6c, 0x64, 0x6a, + 0x5e, 0x67, 0x5a, 0x66, 0x54, 0x64, 0x47, 0x65, 0x41, 0x65, 0x3c, 0x65, + 0x3b, 0x63, 0x3e, 0x63, 0x56, 0x7c, 0x69, 0x8c, 0x73, 0x88, 0x72, 0x88, + 0x74, 0x89, 0x72, 0x85, 0x78, 0x84, 0x76, 0x83, 0x6c, 0x85, 0x66, 0x84, + 0x65, 0x7e, 0x64, 0x7b, 0x56, 0x7b, 0x3e, 0x8b, 0x39, 0x8f, 0x67, 0x7f, + 0x7d, 0x77, 0x63, 0x7a, 0x62, 0x7b, 0x67, 0x78, 0x6e, 0x77, 0x69, 0x78, + 0x69, 0x77, 0x69, 0x78, 0x69, 0x7a, 0x67, 0x7c, 0x66, 0x7d, 0x65, 0x7f, + 0x66, 0x7e, 0x65, 0x7d, 0x65, 0x80, 0x66, 0x7f, 0x66, 0x7e, 0x67, 0x80, + 0x69, 0x81, 0x67, 0x80, 0x65, 0x80, 0x62, 0x84, 0x5d, 0x83, 0x5a, 0x82, + 0x55, 0x81, 0x58, 0x7e, 0x5c, 0x7e, 0x62, 0x81, 0x6d, 0x82, 0x70, 0x83, + 0x74, 0x82, 0x76, 0x84, 0x67, 0x8a, 0x66, 0x8e, 0x77, 0x8c, 0x74, 0x8a, + 0x73, 0x86, 0x73, 0x82, 0x72, 0x7e, 0x6e, 0x7b, 0x6d, 0x79, 0x6e, 0x7c, + 0x71, 0x75, 0x6a, 0x6b, 0x6b, 0x6b, 0x76, 0x6e, 0x7b, 0x71, 0x82, 0x74, + 0x81, 0x72, 0x7f, 0x73, 0x7e, 0x74, 0x7e, 0x74, 0x7d, 0x75, 0x7e, 0x75, + 0x7d, 0x74, 0x7c, 0x74, 0x7b, 0x75, 0x7b, 0x75, 0x7c, 0x75, 0x7c, 0x74, + 0x7d, 0x72, 0x7d, 0x72, 0x7e, 0x72, 0x7f, 0x73, 0x7f, 0x73, 0x80, 0x73, + 0x80, 0x72, 0x81, 0x70, 0x82, 0x70, 0x81, 0x6f, 0x82, 0x70, 0x82, 0x70, + 0x82, 0x70, 0x81, 0x70, 0x80, 0x70, 0x81, 0x6f, 0x81, 0x72, 0x80, 0x74, + 0x80, 0x78, 0x80, 0x7e, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x56, 0x65, 0x55, 0x64, + 0x54, 0x65, 0x54, 0x68, 0x52, 0x6a, 0x51, 0x6a, 0x51, 0x69, 0x4e, 0x6a, + 0x4d, 0x6a, 0x4c, 0x6b, 0x4c, 0x6a, 0x4c, 0x6a, 0x4b, 0x6a, 0x4c, 0x68, + 0x4d, 0x68, 0x4e, 0x66, 0x4e, 0x66, 0x4e, 0x66, 0x4d, 0x66, 0x4e, 0x66, + 0x4d, 0x65, 0x4c, 0x67, 0x4c, 0x68, 0x4c, 0x68, 0x51, 0x68, 0x5a, 0x69, + 0x61, 0x6a, 0x68, 0x6a, 0x6d, 0x6c, 0x6f, 0x6e, 0x72, 0x6f, 0x72, 0x6f, + 0x73, 0x6f, 0x72, 0x6f, 0x73, 0x6f, 0x72, 0x6f, 0x72, 0x6f, 0x72, 0x70, + 0x72, 0x6e, 0x71, 0x6d, 0x72, 0x6f, 0x73, 0x6f, 0x73, 0x6e, 0x73, 0x6e, + 0x73, 0x6e, 0x71, 0x6d, 0x6d, 0x6e, 0x6a, 0x6c, 0x65, 0x69, 0x60, 0x68, + 0x5b, 0x66, 0x52, 0x65, 0x4b, 0x65, 0x42, 0x63, 0x41, 0x64, 0x4c, 0x6e, + 0x67, 0x86, 0x71, 0x82, 0x74, 0x7b, 0x79, 0x80, 0x82, 0x81, 0x7e, 0x83, + 0x79, 0x87, 0x76, 0x87, 0x6f, 0x88, 0x68, 0x89, 0x65, 0x84, 0x64, 0x7f, + 0x62, 0x7c, 0x47, 0x84, 0x32, 0x90, 0x3b, 0x96, 0x58, 0x8d, 0x67, 0x7f, + 0x66, 0x7d, 0x5f, 0x7f, 0x56, 0x83, 0x5b, 0x81, 0x66, 0x7a, 0x68, 0x76, + 0x68, 0x78, 0x68, 0x7b, 0x65, 0x7e, 0x65, 0x7e, 0x66, 0x7c, 0x66, 0x7b, + 0x65, 0x7b, 0x65, 0x7a, 0x64, 0x7b, 0x65, 0x7d, 0x66, 0x7d, 0x68, 0x80, + 0x66, 0x82, 0x62, 0x82, 0x5c, 0x81, 0x58, 0x81, 0x55, 0x80, 0x5a, 0x7f, + 0x5d, 0x80, 0x67, 0x80, 0x6f, 0x80, 0x70, 0x82, 0x73, 0x84, 0x73, 0x85, + 0x64, 0x8c, 0x72, 0x8e, 0x7a, 0x85, 0x70, 0x87, 0x6d, 0x83, 0x6f, 0x7e, + 0x6f, 0x7b, 0x6d, 0x7c, 0x72, 0x7b, 0x77, 0x7f, 0x7e, 0x7d, 0x75, 0x74, + 0x68, 0x6c, 0x6f, 0x6c, 0x76, 0x6f, 0x7d, 0x73, 0x7f, 0x73, 0x80, 0x73, + 0x7f, 0x75, 0x7f, 0x75, 0x7d, 0x75, 0x7e, 0x75, 0x7e, 0x75, 0x7e, 0x75, + 0x7c, 0x75, 0x7d, 0x75, 0x7d, 0x75, 0x7c, 0x75, 0x7d, 0x74, 0x7d, 0x74, + 0x7e, 0x73, 0x7f, 0x73, 0x80, 0x72, 0x80, 0x72, 0x80, 0x72, 0x82, 0x70, + 0x82, 0x70, 0x82, 0x6f, 0x82, 0x6f, 0x82, 0x70, 0x82, 0x70, 0x82, 0x70, + 0x82, 0x70, 0x83, 0x6f, 0x81, 0x71, 0x80, 0x73, 0x80, 0x78, 0x80, 0x7e, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x7f, 0x80, + 0x7f, 0x80, 0x7f, 0x80, 0x55, 0x63, 0x56, 0x63, 0x55, 0x65, 0x54, 0x68, + 0x53, 0x6a, 0x52, 0x6b, 0x50, 0x69, 0x4f, 0x69, 0x4d, 0x6a, 0x4d, 0x6b, + 0x4c, 0x6a, 0x4c, 0x6a, 0x4c, 0x6a, 0x4c, 0x67, 0x4c, 0x68, 0x4d, 0x66, + 0x4e, 0x66, 0x4e, 0x66, 0x4e, 0x66, 0x4e, 0x66, 0x4d, 0x66, 0x4c, 0x68, + 0x4c, 0x68, 0x4d, 0x68, 0x51, 0x68, 0x5a, 0x69, 0x63, 0x6a, 0x69, 0x6a, + 0x6d, 0x6c, 0x6f, 0x6e, 0x72, 0x70, 0x73, 0x70, 0x73, 0x6f, 0x73, 0x6f, + 0x73, 0x70, 0x73, 0x70, 0x72, 0x70, 0x72, 0x70, 0x72, 0x6e, 0x72, 0x6d, + 0x72, 0x6f, 0x71, 0x6f, 0x72, 0x6e, 0x71, 0x6c, 0x71, 0x6c, 0x71, 0x6e, + 0x71, 0x6e, 0x6f, 0x6e, 0x6a, 0x6b, 0x67, 0x6a, 0x62, 0x67, 0x5a, 0x65, + 0x56, 0x65, 0x4c, 0x62, 0x4d, 0x65, 0x5a, 0x77, 0x6f, 0x83, 0x73, 0x7c, + 0x74, 0x7b, 0x7c, 0x7d, 0x81, 0x7d, 0x85, 0x80, 0x86, 0x83, 0x75, 0x89, + 0x74, 0x89, 0x6e, 0x8b, 0x65, 0x89, 0x63, 0x84, 0x67, 0x80, 0x60, 0x79, + 0x4e, 0x7c, 0x30, 0x96, 0x3a, 0x97, 0x5d, 0x7b, 0x59, 0x81, 0x50, 0x8b, + 0x3c, 0x97, 0x3c, 0x99, 0x50, 0x89, 0x69, 0x73, 0x69, 0x75, 0x68, 0x7a, + 0x65, 0x7e, 0x65, 0x7e, 0x66, 0x7a, 0x66, 0x7a, 0x65, 0x7b, 0x65, 0x7b, + 0x63, 0x7d, 0x63, 0x7e, 0x63, 0x7d, 0x68, 0x82, 0x63, 0x82, 0x5e, 0x7f, + 0x58, 0x80, 0x58, 0x80, 0x57, 0x7f, 0x5b, 0x7f, 0x5f, 0x80, 0x6b, 0x80, + 0x6f, 0x80, 0x70, 0x82, 0x73, 0x84, 0x70, 0x85, 0x60, 0x8b, 0x7d, 0x8b, + 0x7e, 0x83, 0x6b, 0x84, 0x6a, 0x80, 0x6d, 0x7e, 0x6c, 0x7e, 0x6e, 0x7e, + 0x7c, 0x7e, 0x85, 0x7e, 0x83, 0x80, 0x80, 0x7d, 0x6a, 0x6e, 0x6b, 0x6b, + 0x71, 0x6e, 0x78, 0x73, 0x7d, 0x73, 0x80, 0x73, 0x7e, 0x74, 0x7f, 0x75, + 0x7d, 0x75, 0x7d, 0x75, 0x7e, 0x75, 0x7e, 0x74, 0x7d, 0x75, 0x7c, 0x75, + 0x7c, 0x75, 0x7c, 0x74, 0x7d, 0x75, 0x7d, 0x76, 0x7e, 0x74, 0x7f, 0x73, + 0x7f, 0x72, 0x80, 0x72, 0x81, 0x72, 0x82, 0x70, 0x82, 0x70, 0x82, 0x70, + 0x82, 0x6f, 0x82, 0x71, 0x82, 0x71, 0x84, 0x70, 0x84, 0x70, 0x83, 0x6f, + 0x81, 0x6f, 0x80, 0x70, 0x80, 0x78, 0x80, 0x7e, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x80, + 0x56, 0x60, 0x56, 0x61, 0x56, 0x63, 0x55, 0x66, 0x54, 0x67, 0x52, 0x6a, + 0x50, 0x69, 0x4f, 0x6a, 0x4d, 0x6b, 0x4d, 0x6b, 0x4c, 0x6a, 0x4b, 0x6a, + 0x4b, 0x6a, 0x4b, 0x69, 0x4b, 0x69, 0x4c, 0x67, 0x4d, 0x65, 0x4e, 0x66, + 0x4d, 0x65, 0x4d, 0x66, 0x4d, 0x67, 0x4c, 0x68, 0x4b, 0x68, 0x4c, 0x69, + 0x51, 0x69, 0x5c, 0x69, 0x63, 0x69, 0x69, 0x6b, 0x6d, 0x6d, 0x6f, 0x6d, + 0x71, 0x6e, 0x71, 0x6f, 0x73, 0x6e, 0x72, 0x6e, 0x71, 0x6f, 0x71, 0x6e, + 0x71, 0x6e, 0x71, 0x6f, 0x71, 0x6e, 0x71, 0x6e, 0x71, 0x6e, 0x71, 0x6e, + 0x71, 0x6d, 0x70, 0x6c, 0x6f, 0x6d, 0x70, 0x6e, 0x71, 0x6e, 0x70, 0x6e, + 0x6e, 0x6c, 0x6b, 0x6a, 0x66, 0x69, 0x61, 0x66, 0x5c, 0x64, 0x56, 0x63, + 0x57, 0x6a, 0x5f, 0x7b, 0x73, 0x7d, 0x78, 0x7c, 0x7a, 0x7d, 0x83, 0x7e, + 0x80, 0x80, 0x81, 0x80, 0x83, 0x82, 0x7f, 0x89, 0x77, 0x89, 0x72, 0x89, + 0x66, 0x8c, 0x62, 0x86, 0x60, 0x83, 0x61, 0x7c, 0x5e, 0x76, 0x4b, 0x7e, + 0x50, 0x80, 0x62, 0x6f, 0x55, 0x7b, 0x42, 0x8d, 0x31, 0x9e, 0x35, 0x9f, + 0x4f, 0x88, 0x6b, 0x72, 0x6b, 0x74, 0x67, 0x78, 0x66, 0x7a, 0x65, 0x7b, + 0x64, 0x7a, 0x64, 0x7a, 0x64, 0x7a, 0x63, 0x7a, 0x63, 0x7c, 0x62, 0x7c, + 0x63, 0x7d, 0x67, 0x82, 0x62, 0x83, 0x5b, 0x80, 0x57, 0x80, 0x5b, 0x80, + 0x5b, 0x82, 0x5c, 0x83, 0x62, 0x83, 0x6d, 0x80, 0x6e, 0x81, 0x70, 0x83, + 0x73, 0x85, 0x6e, 0x86, 0x61, 0x88, 0x83, 0x8a, 0x7a, 0x83, 0x67, 0x85, + 0x68, 0x81, 0x6a, 0x80, 0x6a, 0x80, 0x73, 0x7f, 0x84, 0x7d, 0x8b, 0x7c, + 0x84, 0x7f, 0x83, 0x7f, 0x6f, 0x73, 0x69, 0x6d, 0x6e, 0x6f, 0x74, 0x71, + 0x7a, 0x73, 0x7f, 0x74, 0x7f, 0x75, 0x7e, 0x74, 0x7d, 0x75, 0x7e, 0x75, + 0x7e, 0x75, 0x7e, 0x75, 0x7d, 0x75, 0x7d, 0x75, 0x7d, 0x75, 0x7d, 0x75, + 0x7e, 0x76, 0x7e, 0x76, 0x7f, 0x75, 0x7f, 0x74, 0x80, 0x73, 0x81, 0x72, + 0x81, 0x73, 0x83, 0x72, 0x82, 0x70, 0x83, 0x6f, 0x83, 0x6f, 0x84, 0x70, + 0x84, 0x6f, 0x85, 0x6f, 0x86, 0x70, 0x83, 0x70, 0x81, 0x6e, 0x81, 0x70, + 0x80, 0x76, 0x7f, 0x7d, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x57, 0x5e, 0x56, 0x61, + 0x56, 0x62, 0x56, 0x64, 0x55, 0x65, 0x52, 0x67, 0x50, 0x69, 0x4f, 0x6b, + 0x4d, 0x6b, 0x4c, 0x6b, 0x4b, 0x6a, 0x4a, 0x6b, 0x4b, 0x6a, 0x4b, 0x6a, + 0x4b, 0x6a, 0x4b, 0x69, 0x4b, 0x66, 0x4c, 0x66, 0x4c, 0x66, 0x4c, 0x67, + 0x4b, 0x68, 0x4b, 0x68, 0x4b, 0x68, 0x4c, 0x67, 0x51, 0x67, 0x5d, 0x68, + 0x64, 0x69, 0x68, 0x6c, 0x6e, 0x6d, 0x6f, 0x6d, 0x70, 0x6e, 0x70, 0x6e, + 0x72, 0x6d, 0x72, 0x6d, 0x70, 0x6e, 0x70, 0x6e, 0x70, 0x6e, 0x70, 0x6e, + 0x70, 0x6e, 0x70, 0x6e, 0x6f, 0x6d, 0x6f, 0x6d, 0x6f, 0x6d, 0x6f, 0x6d, + 0x6f, 0x6d, 0x6f, 0x6e, 0x6f, 0x6e, 0x70, 0x6e, 0x70, 0x6d, 0x6f, 0x6b, + 0x6b, 0x6c, 0x68, 0x69, 0x62, 0x66, 0x5e, 0x68, 0x60, 0x70, 0x6c, 0x7a, + 0x78, 0x7c, 0x7b, 0x7e, 0x7f, 0x7d, 0x7f, 0x80, 0x7e, 0x83, 0x77, 0x87, + 0x77, 0x8d, 0x81, 0x89, 0x7c, 0x88, 0x75, 0x86, 0x65, 0x8b, 0x61, 0x88, + 0x60, 0x83, 0x61, 0x80, 0x62, 0x7b, 0x5e, 0x76, 0x5e, 0x72, 0x60, 0x71, + 0x5d, 0x77, 0x4d, 0x82, 0x3a, 0x93, 0x43, 0x94, 0x5f, 0x82, 0x67, 0x78, + 0x67, 0x76, 0x66, 0x74, 0x65, 0x76, 0x65, 0x78, 0x63, 0x79, 0x63, 0x78, + 0x63, 0x77, 0x63, 0x78, 0x63, 0x78, 0x63, 0x79, 0x63, 0x7b, 0x65, 0x7e, + 0x65, 0x82, 0x5f, 0x80, 0x5a, 0x83, 0x5d, 0x85, 0x5e, 0x85, 0x5f, 0x85, + 0x69, 0x84, 0x6f, 0x7f, 0x6d, 0x84, 0x70, 0x86, 0x73, 0x87, 0x69, 0x8a, + 0x64, 0x88, 0x85, 0x88, 0x77, 0x82, 0x64, 0x85, 0x65, 0x82, 0x68, 0x80, + 0x68, 0x7f, 0x7c, 0x7f, 0x8a, 0x7d, 0x8d, 0x7c, 0x84, 0x7f, 0x82, 0x7f, + 0x74, 0x77, 0x65, 0x70, 0x69, 0x71, 0x6e, 0x71, 0x74, 0x73, 0x7a, 0x74, + 0x7e, 0x74, 0x7e, 0x74, 0x7d, 0x75, 0x7d, 0x75, 0x7d, 0x75, 0x7d, 0x75, + 0x7d, 0x75, 0x7d, 0x75, 0x7d, 0x75, 0x7d, 0x75, 0x7e, 0x75, 0x7f, 0x75, + 0x80, 0x75, 0x80, 0x75, 0x80, 0x74, 0x82, 0x73, 0x82, 0x73, 0x82, 0x73, + 0x83, 0x70, 0x85, 0x6f, 0x85, 0x6f, 0x85, 0x6e, 0x85, 0x6f, 0x86, 0x6f, + 0x85, 0x6f, 0x83, 0x70, 0x82, 0x6e, 0x82, 0x71, 0x80, 0x75, 0x7e, 0x7c, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x57, 0x5f, 0x56, 0x61, 0x56, 0x61, 0x56, 0x64, + 0x55, 0x65, 0x52, 0x66, 0x50, 0x69, 0x4f, 0x6b, 0x4e, 0x6b, 0x4d, 0x6a, + 0x4b, 0x6b, 0x4a, 0x6c, 0x4b, 0x6b, 0x4b, 0x69, 0x4b, 0x6a, 0x4a, 0x6a, + 0x4a, 0x68, 0x4b, 0x67, 0x4b, 0x68, 0x4c, 0x67, 0x4b, 0x67, 0x4b, 0x68, + 0x4b, 0x69, 0x4d, 0x66, 0x53, 0x66, 0x5e, 0x67, 0x63, 0x69, 0x69, 0x6c, + 0x6e, 0x6d, 0x6f, 0x6d, 0x70, 0x6e, 0x70, 0x6e, 0x71, 0x6e, 0x72, 0x6e, + 0x70, 0x6e, 0x70, 0x6e, 0x70, 0x6e, 0x70, 0x6e, 0x70, 0x6e, 0x71, 0x6e, + 0x6f, 0x6e, 0x6d, 0x6e, 0x6e, 0x6e, 0x6f, 0x6d, 0x6f, 0x6d, 0x6f, 0x6e, + 0x70, 0x6e, 0x70, 0x6e, 0x70, 0x6e, 0x72, 0x6d, 0x71, 0x6d, 0x6c, 0x6a, + 0x67, 0x6a, 0x62, 0x6b, 0x66, 0x73, 0x73, 0x79, 0x7a, 0x7b, 0x7c, 0x7e, + 0x7f, 0x7f, 0x7b, 0x81, 0x7d, 0x81, 0x75, 0x87, 0x72, 0x8e, 0x7b, 0x8b, + 0x80, 0x88, 0x7a, 0x86, 0x6b, 0x89, 0x61, 0x88, 0x60, 0x85, 0x61, 0x81, + 0x62, 0x7e, 0x5f, 0x7a, 0x5e, 0x74, 0x5f, 0x75, 0x5f, 0x79, 0x58, 0x7c, + 0x53, 0x81, 0x54, 0x81, 0x60, 0x7b, 0x64, 0x78, 0x63, 0x74, 0x63, 0x72, + 0x63, 0x75, 0x64, 0x77, 0x66, 0x78, 0x65, 0x77, 0x63, 0x76, 0x63, 0x76, + 0x63, 0x77, 0x62, 0x78, 0x61, 0x79, 0x63, 0x7d, 0x63, 0x81, 0x5f, 0x7e, + 0x5e, 0x81, 0x5e, 0x85, 0x60, 0x86, 0x62, 0x85, 0x6b, 0x82, 0x72, 0x7e, + 0x6f, 0x83, 0x6d, 0x87, 0x6c, 0x8a, 0x62, 0x8d, 0x68, 0x8a, 0x84, 0x84, + 0x76, 0x82, 0x62, 0x86, 0x62, 0x82, 0x69, 0x81, 0x71, 0x7f, 0x7f, 0x7f, + 0x89, 0x7d, 0x8b, 0x7d, 0x83, 0x7f, 0x81, 0x7f, 0x78, 0x79, 0x61, 0x72, + 0x64, 0x73, 0x6a, 0x72, 0x6f, 0x72, 0x76, 0x74, 0x7c, 0x75, 0x7f, 0x74, + 0x7e, 0x75, 0x7d, 0x75, 0x7d, 0x75, 0x7d, 0x75, 0x7d, 0x75, 0x7d, 0x75, + 0x7d, 0x75, 0x7d, 0x75, 0x7e, 0x75, 0x7f, 0x75, 0x7f, 0x75, 0x80, 0x75, + 0x80, 0x74, 0x82, 0x72, 0x82, 0x73, 0x82, 0x72, 0x83, 0x70, 0x85, 0x6f, + 0x86, 0x6f, 0x85, 0x6f, 0x85, 0x6f, 0x86, 0x6f, 0x85, 0x6f, 0x84, 0x70, + 0x83, 0x6e, 0x83, 0x71, 0x80, 0x75, 0x7f, 0x7d, 0x7f, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x7e, + 0x58, 0x5e, 0x57, 0x5e, 0x57, 0x60, 0x56, 0x63, 0x55, 0x63, 0x54, 0x64, + 0x52, 0x69, 0x50, 0x6b, 0x4f, 0x6a, 0x4d, 0x6a, 0x4c, 0x6c, 0x4b, 0x6d, + 0x4a, 0x6c, 0x49, 0x6a, 0x49, 0x6a, 0x49, 0x6a, 0x4a, 0x6a, 0x4a, 0x69, + 0x4a, 0x68, 0x4b, 0x67, 0x4b, 0x67, 0x4b, 0x67, 0x4b, 0x67, 0x4e, 0x66, + 0x56, 0x65, 0x60, 0x66, 0x65, 0x69, 0x69, 0x6b, 0x6d, 0x6c, 0x6f, 0x6b, + 0x70, 0x6c, 0x70, 0x6c, 0x70, 0x6d, 0x70, 0x6d, 0x70, 0x6e, 0x6f, 0x6e, + 0x70, 0x6d, 0x70, 0x6d, 0x6f, 0x6d, 0x6f, 0x6d, 0x6e, 0x6d, 0x6d, 0x6d, + 0x6e, 0x6d, 0x6e, 0x6d, 0x6e, 0x6d, 0x6e, 0x6d, 0x6f, 0x6d, 0x70, 0x6d, + 0x72, 0x6d, 0x75, 0x6e, 0x75, 0x6e, 0x6f, 0x6d, 0x69, 0x6d, 0x67, 0x6e, + 0x6b, 0x75, 0x73, 0x7a, 0x77, 0x7c, 0x7b, 0x7d, 0x7f, 0x7e, 0x7d, 0x80, + 0x7a, 0x83, 0x78, 0x84, 0x76, 0x85, 0x71, 0x8c, 0x7f, 0x89, 0x81, 0x85, + 0x73, 0x87, 0x5f, 0x8b, 0x5e, 0x89, 0x60, 0x85, 0x60, 0x84, 0x5f, 0x7e, + 0x5f, 0x7a, 0x60, 0x7a, 0x5e, 0x7b, 0x5c, 0x7a, 0x5f, 0x74, 0x5e, 0x71, + 0x62, 0x70, 0x62, 0x6f, 0x62, 0x6f, 0x62, 0x6f, 0x62, 0x72, 0x64, 0x74, + 0x66, 0x77, 0x65, 0x77, 0x63, 0x75, 0x63, 0x74, 0x63, 0x74, 0x63, 0x76, + 0x61, 0x79, 0x60, 0x7b, 0x5b, 0x7b, 0x5a, 0x7b, 0x5e, 0x7d, 0x5d, 0x81, + 0x60, 0x83, 0x64, 0x83, 0x6a, 0x7f, 0x75, 0x7c, 0x74, 0x80, 0x6a, 0x88, + 0x63, 0x8b, 0x5d, 0x8b, 0x6d, 0x8b, 0x7b, 0x88, 0x74, 0x82, 0x62, 0x85, + 0x64, 0x83, 0x6e, 0x7f, 0x80, 0x7d, 0x82, 0x7f, 0x86, 0x7c, 0x89, 0x7b, + 0x82, 0x7f, 0x81, 0x80, 0x7b, 0x7b, 0x60, 0x73, 0x60, 0x73, 0x65, 0x72, + 0x69, 0x72, 0x71, 0x74, 0x79, 0x74, 0x7d, 0x75, 0x7e, 0x75, 0x7d, 0x75, + 0x7d, 0x75, 0x7e, 0x75, 0x7d, 0x75, 0x7e, 0x75, 0x7d, 0x75, 0x7d, 0x75, + 0x7e, 0x75, 0x7e, 0x75, 0x7f, 0x75, 0x80, 0x75, 0x80, 0x74, 0x82, 0x72, + 0x82, 0x73, 0x83, 0x71, 0x85, 0x6f, 0x87, 0x6f, 0x87, 0x6f, 0x86, 0x6f, + 0x86, 0x6f, 0x86, 0x6f, 0x87, 0x6f, 0x85, 0x70, 0x85, 0x70, 0x83, 0x71, + 0x7f, 0x75, 0x7e, 0x7c, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x59, 0x5d, 0x58, 0x5d, + 0x57, 0x5f, 0x56, 0x61, 0x56, 0x61, 0x54, 0x63, 0x53, 0x68, 0x51, 0x69, + 0x4f, 0x68, 0x4d, 0x69, 0x4c, 0x6c, 0x4b, 0x6d, 0x49, 0x6d, 0x49, 0x6a, + 0x49, 0x6a, 0x49, 0x69, 0x49, 0x6a, 0x49, 0x69, 0x4a, 0x68, 0x49, 0x67, + 0x49, 0x67, 0x4b, 0x67, 0x4b, 0x67, 0x4e, 0x66, 0x57, 0x66, 0x62, 0x66, + 0x66, 0x68, 0x68, 0x6a, 0x6c, 0x6b, 0x6e, 0x6a, 0x6f, 0x6b, 0x6f, 0x6b, + 0x6f, 0x6d, 0x6f, 0x6d, 0x6f, 0x6d, 0x6f, 0x6d, 0x6f, 0x6d, 0x6f, 0x6c, + 0x6d, 0x6c, 0x6d, 0x6c, 0x6e, 0x6c, 0x6e, 0x6d, 0x6e, 0x6c, 0x6e, 0x6d, + 0x6e, 0x6d, 0x6d, 0x6c, 0x6e, 0x6c, 0x6f, 0x6c, 0x72, 0x6d, 0x75, 0x6e, + 0x75, 0x6e, 0x6e, 0x6e, 0x67, 0x6e, 0x69, 0x71, 0x70, 0x77, 0x76, 0x7c, + 0x78, 0x7d, 0x78, 0x7e, 0x79, 0x7d, 0x7a, 0x7f, 0x78, 0x85, 0x77, 0x86, + 0x77, 0x88, 0x6f, 0x89, 0x7a, 0x87, 0x80, 0x87, 0x70, 0x86, 0x5b, 0x8b, + 0x5e, 0x89, 0x61, 0x86, 0x5f, 0x87, 0x60, 0x81, 0x62, 0x7d, 0x63, 0x7c, + 0x5e, 0x7a, 0x5d, 0x77, 0x5f, 0x70, 0x60, 0x6e, 0x61, 0x6d, 0x62, 0x6e, + 0x62, 0x6e, 0x62, 0x6e, 0x62, 0x70, 0x62, 0x72, 0x62, 0x73, 0x62, 0x75, + 0x61, 0x75, 0x61, 0x75, 0x63, 0x73, 0x63, 0x76, 0x61, 0x79, 0x5d, 0x79, + 0x58, 0x76, 0x58, 0x78, 0x5a, 0x7d, 0x5a, 0x7f, 0x5f, 0x80, 0x63, 0x7f, + 0x6a, 0x7d, 0x78, 0x7c, 0x73, 0x80, 0x6a, 0x89, 0x62, 0x8a, 0x5c, 0x8a, + 0x6f, 0x8d, 0x75, 0x8f, 0x70, 0x84, 0x62, 0x84, 0x68, 0x83, 0x74, 0x7e, + 0x84, 0x7b, 0x85, 0x7d, 0x88, 0x7b, 0x89, 0x7a, 0x81, 0x7f, 0x81, 0x80, + 0x7b, 0x7c, 0x61, 0x73, 0x5f, 0x73, 0x62, 0x73, 0x65, 0x72, 0x6d, 0x74, + 0x76, 0x73, 0x7c, 0x75, 0x7e, 0x75, 0x7e, 0x75, 0x7e, 0x75, 0x7e, 0x75, + 0x7e, 0x74, 0x7e, 0x74, 0x7d, 0x75, 0x7c, 0x76, 0x7e, 0x75, 0x7f, 0x74, + 0x7f, 0x75, 0x80, 0x75, 0x80, 0x74, 0x82, 0x73, 0x82, 0x72, 0x84, 0x71, + 0x87, 0x6e, 0x87, 0x6e, 0x87, 0x6f, 0x87, 0x6f, 0x87, 0x6f, 0x87, 0x6f, + 0x88, 0x6f, 0x85, 0x6f, 0x84, 0x71, 0x83, 0x70, 0x7f, 0x75, 0x7e, 0x7c, + 0x7f, 0x80, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x7e, + 0x80, 0x7f, 0x80, 0x7f, 0x57, 0x5e, 0x58, 0x5e, 0x57, 0x5e, 0x57, 0x61, + 0x57, 0x62, 0x54, 0x63, 0x53, 0x67, 0x52, 0x68, 0x50, 0x68, 0x4e, 0x69, + 0x4c, 0x6c, 0x4b, 0x6d, 0x49, 0x6d, 0x49, 0x6a, 0x49, 0x6b, 0x49, 0x6a, + 0x49, 0x6a, 0x49, 0x69, 0x49, 0x69, 0x49, 0x67, 0x49, 0x67, 0x4a, 0x67, + 0x4b, 0x67, 0x4e, 0x66, 0x57, 0x65, 0x61, 0x66, 0x64, 0x69, 0x66, 0x6b, + 0x6a, 0x6b, 0x6c, 0x6b, 0x6e, 0x6b, 0x6d, 0x6b, 0x6f, 0x6d, 0x6f, 0x6d, + 0x6f, 0x6e, 0x6f, 0x6d, 0x70, 0x6d, 0x70, 0x6d, 0x6e, 0x6d, 0x6e, 0x6d, + 0x6e, 0x6c, 0x6e, 0x6d, 0x6e, 0x6d, 0x6e, 0x6d, 0x6e, 0x6d, 0x6d, 0x6d, + 0x6d, 0x6d, 0x6f, 0x6c, 0x73, 0x6d, 0x75, 0x6e, 0x75, 0x6e, 0x6c, 0x6e, + 0x65, 0x6e, 0x69, 0x72, 0x77, 0x77, 0x80, 0x7a, 0x82, 0x7f, 0x7e, 0x80, + 0x78, 0x7f, 0x76, 0x7f, 0x73, 0x82, 0x75, 0x85, 0x72, 0x88, 0x6c, 0x8a, + 0x76, 0x89, 0x7b, 0x8b, 0x75, 0x85, 0x63, 0x87, 0x5e, 0x8a, 0x5f, 0x88, + 0x5e, 0x87, 0x62, 0x83, 0x68, 0x81, 0x65, 0x7d, 0x5e, 0x7b, 0x5d, 0x77, + 0x5f, 0x6e, 0x60, 0x6d, 0x61, 0x6c, 0x63, 0x6e, 0x63, 0x6e, 0x62, 0x6d, + 0x62, 0x6f, 0x61, 0x6f, 0x60, 0x70, 0x5f, 0x73, 0x60, 0x77, 0x5f, 0x79, + 0x5f, 0x76, 0x5f, 0x75, 0x5f, 0x77, 0x5b, 0x77, 0x58, 0x77, 0x58, 0x79, + 0x58, 0x7d, 0x5a, 0x7d, 0x60, 0x7c, 0x63, 0x7c, 0x6b, 0x7c, 0x76, 0x7e, + 0x6f, 0x83, 0x66, 0x8b, 0x5c, 0x8a, 0x57, 0x89, 0x6d, 0x8c, 0x73, 0x8f, + 0x71, 0x85, 0x5f, 0x86, 0x68, 0x81, 0x7b, 0x7e, 0x84, 0x7b, 0x88, 0x7b, + 0x8c, 0x79, 0x8a, 0x79, 0x81, 0x7f, 0x81, 0x80, 0x7a, 0x7c, 0x5f, 0x73, + 0x5d, 0x72, 0x61, 0x71, 0x63, 0x70, 0x67, 0x72, 0x72, 0x74, 0x7a, 0x75, + 0x7e, 0x75, 0x7e, 0x75, 0x7e, 0x75, 0x7d, 0x75, 0x7b, 0x75, 0x7b, 0x74, + 0x7d, 0x75, 0x7d, 0x75, 0x7e, 0x75, 0x7f, 0x74, 0x7f, 0x75, 0x80, 0x75, + 0x81, 0x74, 0x82, 0x73, 0x82, 0x73, 0x85, 0x71, 0x87, 0x6e, 0x87, 0x6f, + 0x87, 0x6f, 0x87, 0x6f, 0x87, 0x6f, 0x87, 0x6f, 0x87, 0x6f, 0x85, 0x6f, + 0x84, 0x71, 0x83, 0x70, 0x80, 0x75, 0x7f, 0x7c, 0x7f, 0x80, 0x7f, 0x7f, + 0x80, 0x7f, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x7e, 0x80, 0x80, 0x80, 0x7f, + 0x57, 0x60, 0x58, 0x60, 0x57, 0x5e, 0x57, 0x61, 0x57, 0x62, 0x54, 0x64, + 0x53, 0x66, 0x51, 0x66, 0x4f, 0x67, 0x4e, 0x69, 0x4d, 0x6b, 0x4b, 0x6d, + 0x4a, 0x6c, 0x49, 0x6b, 0x49, 0x6b, 0x49, 0x6a, 0x49, 0x6a, 0x49, 0x69, + 0x49, 0x69, 0x49, 0x68, 0x49, 0x67, 0x4a, 0x68, 0x4b, 0x68, 0x4d, 0x66, + 0x57, 0x65, 0x60, 0x66, 0x63, 0x68, 0x65, 0x6a, 0x69, 0x6b, 0x6a, 0x6b, + 0x6c, 0x6b, 0x6c, 0x6b, 0x6f, 0x6c, 0x6f, 0x6d, 0x6f, 0x6e, 0x6f, 0x6e, + 0x6f, 0x6d, 0x6f, 0x6d, 0x6e, 0x6d, 0x6e, 0x6c, 0x6e, 0x6d, 0x6e, 0x6c, + 0x6e, 0x6c, 0x6e, 0x6c, 0x6e, 0x6d, 0x6e, 0x6d, 0x6d, 0x6c, 0x6f, 0x6d, + 0x72, 0x6d, 0x75, 0x6e, 0x75, 0x6e, 0x6a, 0x6d, 0x64, 0x6d, 0x6a, 0x71, + 0x7c, 0x75, 0x88, 0x74, 0x89, 0x81, 0x86, 0x83, 0x7e, 0x80, 0x75, 0x80, + 0x6f, 0x84, 0x70, 0x82, 0x6f, 0x82, 0x6e, 0x8a, 0x71, 0x88, 0x74, 0x8c, + 0x74, 0x84, 0x64, 0x85, 0x58, 0x8e, 0x5b, 0x8c, 0x5c, 0x88, 0x63, 0x84, + 0x6c, 0x83, 0x67, 0x7f, 0x5f, 0x7e, 0x5d, 0x7b, 0x5f, 0x6e, 0x60, 0x6b, + 0x61, 0x6b, 0x62, 0x6e, 0x62, 0x6e, 0x62, 0x6c, 0x62, 0x6d, 0x62, 0x70, + 0x62, 0x73, 0x61, 0x74, 0x5f, 0x78, 0x5e, 0x7d, 0x5d, 0x79, 0x5d, 0x75, + 0x5d, 0x76, 0x5a, 0x76, 0x58, 0x77, 0x58, 0x79, 0x59, 0x7e, 0x5e, 0x7b, + 0x62, 0x79, 0x63, 0x79, 0x69, 0x7a, 0x71, 0x80, 0x6b, 0x85, 0x64, 0x8b, + 0x59, 0x88, 0x54, 0x84, 0x69, 0x88, 0x70, 0x8c, 0x74, 0x83, 0x5d, 0x87, + 0x67, 0x80, 0x7e, 0x7f, 0x85, 0x7b, 0x8b, 0x79, 0x8f, 0x77, 0x8c, 0x78, + 0x81, 0x7f, 0x81, 0x80, 0x7a, 0x7c, 0x5f, 0x73, 0x5c, 0x73, 0x60, 0x71, + 0x61, 0x6f, 0x63, 0x71, 0x6e, 0x73, 0x79, 0x75, 0x7e, 0x75, 0x7e, 0x75, + 0x7e, 0x74, 0x7d, 0x74, 0x7a, 0x75, 0x7a, 0x75, 0x7c, 0x75, 0x7d, 0x76, + 0x7e, 0x75, 0x7f, 0x75, 0x80, 0x75, 0x80, 0x75, 0x81, 0x74, 0x82, 0x73, + 0x82, 0x73, 0x84, 0x71, 0x86, 0x6e, 0x87, 0x6f, 0x87, 0x6f, 0x87, 0x6f, + 0x87, 0x6f, 0x87, 0x6f, 0x87, 0x6f, 0x85, 0x6f, 0x85, 0x71, 0x83, 0x71, + 0x7f, 0x75, 0x7f, 0x7b, 0x7f, 0x80, 0x80, 0x7f, 0x80, 0x7f, 0x80, 0x80, + 0x7f, 0x7e, 0x80, 0x7e, 0x80, 0x7f, 0x80, 0x7f, 0x57, 0x5f, 0x57, 0x5f, + 0x57, 0x5f, 0x57, 0x61, 0x56, 0x62, 0x55, 0x64, 0x54, 0x65, 0x52, 0x65, + 0x50, 0x68, 0x4f, 0x69, 0x4d, 0x6b, 0x4b, 0x6d, 0x4a, 0x6c, 0x49, 0x6a, + 0x49, 0x6a, 0x49, 0x6a, 0x49, 0x6b, 0x49, 0x69, 0x49, 0x6a, 0x49, 0x69, + 0x49, 0x69, 0x49, 0x69, 0x4a, 0x68, 0x4e, 0x66, 0x58, 0x66, 0x60, 0x66, + 0x62, 0x68, 0x64, 0x6a, 0x68, 0x6a, 0x6a, 0x6a, 0x6b, 0x6a, 0x6c, 0x6a, + 0x6e, 0x6b, 0x6f, 0x6c, 0x6e, 0x6d, 0x6e, 0x6d, 0x6f, 0x6c, 0x6e, 0x6c, + 0x6e, 0x6b, 0x6d, 0x6b, 0x6d, 0x6b, 0x6d, 0x6b, 0x6d, 0x6c, 0x6d, 0x6d, + 0x6d, 0x6d, 0x6e, 0x6d, 0x6f, 0x6b, 0x70, 0x6b, 0x74, 0x6d, 0x76, 0x6e, + 0x75, 0x6e, 0x68, 0x6d, 0x61, 0x6e, 0x6b, 0x73, 0x80, 0x74, 0x8b, 0x75, + 0x91, 0x84, 0x8e, 0x82, 0x83, 0x80, 0x7c, 0x81, 0x72, 0x83, 0x6d, 0x82, + 0x6e, 0x84, 0x71, 0x87, 0x71, 0x89, 0x74, 0x8b, 0x74, 0x86, 0x5f, 0x89, + 0x56, 0x90, 0x5c, 0x89, 0x60, 0x86, 0x66, 0x83, 0x6a, 0x80, 0x68, 0x7e, + 0x61, 0x7f, 0x5c, 0x7b, 0x5d, 0x6d, 0x5f, 0x6b, 0x61, 0x6b, 0x62, 0x6c, + 0x62, 0x6c, 0x62, 0x6c, 0x62, 0x6d, 0x63, 0x70, 0x61, 0x74, 0x60, 0x74, + 0x5e, 0x76, 0x5c, 0x7b, 0x5d, 0x78, 0x5d, 0x74, 0x5d, 0x74, 0x5c, 0x75, + 0x5a, 0x77, 0x5a, 0x78, 0x5b, 0x7a, 0x5f, 0x79, 0x64, 0x7a, 0x64, 0x7b, + 0x67, 0x7c, 0x6d, 0x82, 0x68, 0x87, 0x63, 0x8b, 0x59, 0x86, 0x54, 0x84, + 0x66, 0x85, 0x72, 0x8a, 0x73, 0x84, 0x5b, 0x88, 0x6a, 0x81, 0x7f, 0x7f, + 0x86, 0x7c, 0x8a, 0x79, 0x8e, 0x79, 0x8a, 0x7a, 0x82, 0x7f, 0x80, 0x80, + 0x79, 0x7c, 0x60, 0x73, 0x5e, 0x72, 0x60, 0x71, 0x61, 0x70, 0x64, 0x71, + 0x6d, 0x72, 0x75, 0x75, 0x7d, 0x75, 0x7d, 0x75, 0x7c, 0x74, 0x7b, 0x74, + 0x7b, 0x74, 0x7b, 0x74, 0x7b, 0x74, 0x7c, 0x74, 0x7c, 0x74, 0x7e, 0x75, + 0x7f, 0x75, 0x80, 0x75, 0x82, 0x74, 0x83, 0x73, 0x84, 0x73, 0x85, 0x71, + 0x87, 0x6e, 0x88, 0x6f, 0x88, 0x6f, 0x87, 0x6e, 0x87, 0x6e, 0x88, 0x6f, + 0x87, 0x6f, 0x86, 0x6f, 0x86, 0x6f, 0x84, 0x70, 0x7f, 0x74, 0x7e, 0x7c, + 0x80, 0x80, 0x80, 0x7f, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7e, 0x7f, 0x7e, + 0x80, 0x7f, 0x80, 0x7f, 0x56, 0x60, 0x56, 0x60, 0x57, 0x61, 0x56, 0x60, + 0x56, 0x61, 0x55, 0x62, 0x54, 0x63, 0x52, 0x65, 0x50, 0x68, 0x50, 0x69, + 0x4d, 0x6a, 0x4c, 0x6b, 0x4b, 0x6b, 0x49, 0x69, 0x49, 0x6a, 0x48, 0x6b, + 0x48, 0x6b, 0x48, 0x6a, 0x48, 0x69, 0x48, 0x6a, 0x48, 0x6a, 0x48, 0x6a, + 0x49, 0x68, 0x50, 0x66, 0x59, 0x66, 0x5f, 0x66, 0x61, 0x69, 0x64, 0x6a, + 0x68, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6c, 0x6a, 0x6d, 0x6a, 0x6e, 0x6b, + 0x6d, 0x6d, 0x6d, 0x6c, 0x6e, 0x6a, 0x6e, 0x6b, 0x6d, 0x6b, 0x6d, 0x6b, + 0x6d, 0x6a, 0x6d, 0x6a, 0x6d, 0x6b, 0x6d, 0x6d, 0x6c, 0x6d, 0x6e, 0x6d, + 0x71, 0x6b, 0x73, 0x6c, 0x75, 0x6e, 0x75, 0x6f, 0x6e, 0x73, 0x66, 0x76, + 0x61, 0x75, 0x6f, 0x74, 0x84, 0x73, 0x8b, 0x78, 0x95, 0x86, 0x93, 0x81, + 0x8c, 0x81, 0x8d, 0x88, 0x7f, 0x83, 0x6b, 0x84, 0x6b, 0x85, 0x6c, 0x86, + 0x6c, 0x8c, 0x76, 0x89, 0x75, 0x87, 0x5b, 0x8c, 0x59, 0x8d, 0x64, 0x83, + 0x6a, 0x82, 0x70, 0x7f, 0x6e, 0x7d, 0x6a, 0x7d, 0x65, 0x7d, 0x5d, 0x7a, + 0x5c, 0x6e, 0x5f, 0x6b, 0x61, 0x6a, 0x62, 0x6a, 0x62, 0x6a, 0x62, 0x6b, + 0x62, 0x6b, 0x62, 0x6e, 0x5f, 0x72, 0x5e, 0x72, 0x5d, 0x74, 0x5b, 0x75, + 0x5d, 0x74, 0x5d, 0x72, 0x5d, 0x74, 0x5d, 0x75, 0x5c, 0x74, 0x5c, 0x74, + 0x5d, 0x75, 0x5f, 0x76, 0x66, 0x7b, 0x69, 0x7d, 0x68, 0x7d, 0x68, 0x82, + 0x63, 0x87, 0x5f, 0x8a, 0x5b, 0x84, 0x57, 0x81, 0x5d, 0x81, 0x6d, 0x86, + 0x75, 0x84, 0x5f, 0x86, 0x73, 0x81, 0x82, 0x7f, 0x88, 0x7d, 0x88, 0x7b, + 0x8a, 0x7b, 0x89, 0x7c, 0x83, 0x7f, 0x80, 0x80, 0x74, 0x7c, 0x5f, 0x72, + 0x5f, 0x72, 0x5f, 0x71, 0x60, 0x6f, 0x64, 0x6f, 0x6a, 0x71, 0x70, 0x74, + 0x7b, 0x75, 0x7d, 0x75, 0x7b, 0x73, 0x7a, 0x73, 0x7a, 0x72, 0x7a, 0x72, + 0x7a, 0x73, 0x7a, 0x72, 0x7b, 0x72, 0x7d, 0x73, 0x7e, 0x74, 0x80, 0x75, + 0x82, 0x74, 0x84, 0x73, 0x86, 0x73, 0x86, 0x71, 0x88, 0x6e, 0x88, 0x6f, + 0x89, 0x6f, 0x88, 0x6e, 0x88, 0x6e, 0x88, 0x6f, 0x88, 0x6f, 0x87, 0x70, + 0x87, 0x70, 0x85, 0x70, 0x80, 0x74, 0x7e, 0x7c, 0x80, 0x7f, 0x80, 0x7f, + 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7e, 0x7f, 0x7e, 0x7f, 0x7e, 0x7f, 0x7e, + 0x56, 0x61, 0x56, 0x61, 0x56, 0x60, 0x57, 0x61, 0x56, 0x61, 0x55, 0x61, + 0x55, 0x63, 0x53, 0x66, 0x51, 0x67, 0x51, 0x67, 0x4f, 0x69, 0x4d, 0x6a, + 0x4b, 0x6a, 0x49, 0x6a, 0x49, 0x6a, 0x48, 0x6b, 0x48, 0x6b, 0x49, 0x6a, + 0x4a, 0x6a, 0x49, 0x6a, 0x49, 0x6a, 0x48, 0x6a, 0x49, 0x68, 0x52, 0x66, + 0x5a, 0x65, 0x5d, 0x66, 0x62, 0x68, 0x65, 0x6a, 0x68, 0x6a, 0x69, 0x6a, + 0x6a, 0x6a, 0x6c, 0x6a, 0x6d, 0x6b, 0x6f, 0x6b, 0x6d, 0x6d, 0x6e, 0x6d, + 0x6e, 0x6b, 0x6e, 0x6b, 0x6d, 0x6b, 0x6d, 0x6b, 0x6d, 0x6b, 0x6d, 0x6a, + 0x6d, 0x6c, 0x6d, 0x6d, 0x6c, 0x6d, 0x6e, 0x6d, 0x72, 0x6d, 0x73, 0x6e, + 0x71, 0x71, 0x6e, 0x76, 0x68, 0x7d, 0x67, 0x81, 0x64, 0x7e, 0x74, 0x72, + 0x84, 0x72, 0x89, 0x78, 0x93, 0x86, 0x92, 0x84, 0x91, 0x85, 0x93, 0x88, + 0x8a, 0x83, 0x6f, 0x85, 0x6d, 0x83, 0x6a, 0x88, 0x65, 0x8b, 0x70, 0x86, + 0x73, 0x87, 0x62, 0x8c, 0x62, 0x87, 0x69, 0x80, 0x6e, 0x7f, 0x75, 0x7b, + 0x74, 0x7b, 0x6d, 0x7b, 0x66, 0x7b, 0x5f, 0x7a, 0x5d, 0x6f, 0x5f, 0x6a, + 0x61, 0x69, 0x63, 0x68, 0x62, 0x68, 0x62, 0x69, 0x62, 0x6a, 0x61, 0x6c, + 0x5d, 0x6e, 0x5d, 0x6f, 0x5d, 0x71, 0x5b, 0x6f, 0x5d, 0x70, 0x5d, 0x6f, + 0x5d, 0x73, 0x5d, 0x73, 0x5e, 0x71, 0x5e, 0x70, 0x5f, 0x71, 0x5f, 0x75, + 0x63, 0x7b, 0x6a, 0x7c, 0x6b, 0x7d, 0x68, 0x82, 0x60, 0x86, 0x5c, 0x88, + 0x59, 0x81, 0x58, 0x7e, 0x59, 0x7c, 0x65, 0x81, 0x78, 0x83, 0x68, 0x83, + 0x74, 0x7e, 0x82, 0x81, 0x86, 0x80, 0x85, 0x7e, 0x86, 0x7e, 0x88, 0x7c, + 0x84, 0x7e, 0x7e, 0x7f, 0x6f, 0x7a, 0x5f, 0x72, 0x5f, 0x73, 0x5f, 0x71, + 0x61, 0x6e, 0x63, 0x6e, 0x67, 0x70, 0x6d, 0x72, 0x78, 0x75, 0x7d, 0x75, + 0x7c, 0x72, 0x7a, 0x72, 0x78, 0x70, 0x78, 0x71, 0x78, 0x70, 0x78, 0x71, + 0x79, 0x71, 0x7c, 0x71, 0x7e, 0x73, 0x81, 0x75, 0x82, 0x74, 0x84, 0x73, + 0x86, 0x73, 0x86, 0x71, 0x88, 0x6e, 0x88, 0x6f, 0x88, 0x70, 0x88, 0x6e, + 0x88, 0x6e, 0x88, 0x6f, 0x88, 0x6f, 0x87, 0x71, 0x87, 0x72, 0x86, 0x71, + 0x82, 0x74, 0x7f, 0x7c, 0x80, 0x7f, 0x80, 0x7f, 0x80, 0x80, 0x80, 0x7f, + 0x7f, 0x7e, 0x7f, 0x7e, 0x7f, 0x7f, 0x7f, 0x7e, 0x56, 0x63, 0x56, 0x62, + 0x56, 0x60, 0x57, 0x60, 0x57, 0x5f, 0x56, 0x60, 0x56, 0x62, 0x54, 0x65, + 0x52, 0x67, 0x52, 0x67, 0x50, 0x68, 0x4e, 0x6a, 0x4c, 0x69, 0x4b, 0x69, + 0x4a, 0x6a, 0x49, 0x6b, 0x48, 0x6b, 0x49, 0x6a, 0x49, 0x6a, 0x49, 0x6b, + 0x49, 0x6b, 0x48, 0x6a, 0x49, 0x68, 0x52, 0x67, 0x59, 0x67, 0x5e, 0x67, + 0x61, 0x68, 0x64, 0x69, 0x67, 0x68, 0x69, 0x69, 0x6a, 0x69, 0x6c, 0x6a, + 0x6e, 0x6a, 0x70, 0x6b, 0x6e, 0x6c, 0x6e, 0x6c, 0x6d, 0x6b, 0x6d, 0x6a, + 0x6c, 0x6a, 0x6c, 0x6b, 0x6c, 0x6b, 0x6c, 0x6a, 0x6c, 0x6b, 0x6c, 0x6c, + 0x6d, 0x6c, 0x70, 0x6c, 0x72, 0x6b, 0x6e, 0x6e, 0x69, 0x77, 0x67, 0x80, + 0x67, 0x84, 0x66, 0x86, 0x65, 0x82, 0x77, 0x73, 0x85, 0x73, 0x8a, 0x79, + 0x91, 0x82, 0x8f, 0x81, 0x8f, 0x84, 0x90, 0x85, 0x8e, 0x7e, 0x79, 0x82, + 0x71, 0x83, 0x6b, 0x87, 0x60, 0x8c, 0x6b, 0x86, 0x73, 0x86, 0x75, 0x88, + 0x6f, 0x81, 0x6a, 0x7c, 0x6f, 0x7b, 0x74, 0x79, 0x76, 0x7a, 0x71, 0x7a, + 0x69, 0x79, 0x62, 0x79, 0x60, 0x72, 0x60, 0x6c, 0x60, 0x6a, 0x61, 0x6a, + 0x62, 0x6a, 0x63, 0x68, 0x62, 0x68, 0x61, 0x69, 0x5e, 0x6b, 0x5d, 0x6c, + 0x5c, 0x6f, 0x5b, 0x6e, 0x5d, 0x6e, 0x5d, 0x6d, 0x5d, 0x6e, 0x5d, 0x6e, + 0x5e, 0x6e, 0x5f, 0x6e, 0x5e, 0x71, 0x60, 0x75, 0x62, 0x7b, 0x66, 0x7d, + 0x69, 0x7f, 0x68, 0x84, 0x60, 0x87, 0x59, 0x87, 0x56, 0x81, 0x56, 0x7d, + 0x5b, 0x79, 0x61, 0x7d, 0x77, 0x81, 0x6b, 0x81, 0x6c, 0x7e, 0x78, 0x81, + 0x80, 0x80, 0x82, 0x7f, 0x88, 0x7e, 0x8b, 0x7d, 0x81, 0x7e, 0x77, 0x7a, + 0x6b, 0x77, 0x60, 0x71, 0x5f, 0x71, 0x5f, 0x6e, 0x61, 0x6d, 0x62, 0x6d, + 0x65, 0x6f, 0x6a, 0x72, 0x75, 0x74, 0x7c, 0x74, 0x7b, 0x72, 0x79, 0x71, + 0x77, 0x71, 0x77, 0x71, 0x77, 0x70, 0x77, 0x6f, 0x77, 0x71, 0x7a, 0x71, + 0x7c, 0x72, 0x7f, 0x74, 0x81, 0x73, 0x83, 0x72, 0x85, 0x72, 0x87, 0x71, + 0x89, 0x6f, 0x89, 0x6e, 0x89, 0x6e, 0x89, 0x6e, 0x89, 0x6e, 0x88, 0x6f, + 0x88, 0x6e, 0x88, 0x70, 0x87, 0x70, 0x86, 0x6f, 0x81, 0x73, 0x7f, 0x7b, + 0x80, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x7e, + 0x7f, 0x7e, 0x7f, 0x7f, 0x55, 0x66, 0x56, 0x63, 0x56, 0x61, 0x56, 0x61, + 0x57, 0x5e, 0x57, 0x60, 0x56, 0x62, 0x55, 0x64, 0x53, 0x66, 0x52, 0x66, + 0x51, 0x67, 0x50, 0x68, 0x4d, 0x67, 0x4b, 0x69, 0x4a, 0x6b, 0x49, 0x6a, + 0x48, 0x6a, 0x48, 0x6a, 0x48, 0x6a, 0x48, 0x6a, 0x47, 0x6a, 0x48, 0x6a, + 0x48, 0x68, 0x51, 0x67, 0x58, 0x68, 0x5f, 0x68, 0x5f, 0x68, 0x62, 0x67, + 0x64, 0x67, 0x66, 0x67, 0x68, 0x68, 0x6a, 0x68, 0x6d, 0x68, 0x6f, 0x6b, + 0x6e, 0x6a, 0x6e, 0x6b, 0x6d, 0x6a, 0x6d, 0x6a, 0x6b, 0x6b, 0x6b, 0x6b, + 0x6a, 0x6a, 0x6b, 0x6a, 0x6a, 0x6a, 0x6b, 0x6b, 0x6e, 0x6a, 0x70, 0x6b, + 0x6e, 0x6e, 0x69, 0x75, 0x65, 0x80, 0x65, 0x85, 0x65, 0x85, 0x64, 0x88, + 0x64, 0x84, 0x77, 0x78, 0x86, 0x77, 0x8a, 0x76, 0x8f, 0x78, 0x91, 0x78, + 0x8f, 0x7e, 0x92, 0x80, 0x95, 0x78, 0x88, 0x7d, 0x78, 0x81, 0x6d, 0x85, + 0x5f, 0x8d, 0x6a, 0x88, 0x75, 0x85, 0x7f, 0x81, 0x77, 0x7c, 0x70, 0x79, + 0x73, 0x78, 0x72, 0x78, 0x78, 0x7a, 0x77, 0x7a, 0x72, 0x79, 0x69, 0x78, + 0x63, 0x75, 0x60, 0x70, 0x5e, 0x6d, 0x60, 0x6b, 0x63, 0x6a, 0x63, 0x67, + 0x63, 0x67, 0x61, 0x67, 0x60, 0x68, 0x5f, 0x6a, 0x5d, 0x6b, 0x5d, 0x6b, + 0x5e, 0x6c, 0x5e, 0x6c, 0x5e, 0x6c, 0x5e, 0x6c, 0x5b, 0x6c, 0x5e, 0x6e, + 0x5f, 0x73, 0x62, 0x76, 0x66, 0x7c, 0x67, 0x7f, 0x67, 0x82, 0x62, 0x86, + 0x5c, 0x87, 0x58, 0x85, 0x54, 0x81, 0x56, 0x7d, 0x5b, 0x78, 0x5d, 0x79, + 0x74, 0x7e, 0x6c, 0x7c, 0x68, 0x7f, 0x69, 0x80, 0x72, 0x7e, 0x78, 0x7c, + 0x80, 0x7c, 0x80, 0x7d, 0x74, 0x7d, 0x73, 0x73, 0x68, 0x73, 0x5d, 0x70, + 0x5f, 0x6e, 0x60, 0x6c, 0x60, 0x6d, 0x61, 0x6c, 0x64, 0x6f, 0x68, 0x73, + 0x70, 0x74, 0x78, 0x72, 0x78, 0x71, 0x77, 0x71, 0x75, 0x70, 0x75, 0x70, + 0x75, 0x6f, 0x75, 0x6e, 0x76, 0x70, 0x78, 0x70, 0x7a, 0x70, 0x7d, 0x70, + 0x80, 0x71, 0x82, 0x72, 0x84, 0x72, 0x87, 0x71, 0x8a, 0x70, 0x8a, 0x6e, + 0x89, 0x6d, 0x8a, 0x6e, 0x89, 0x6e, 0x88, 0x6e, 0x88, 0x6e, 0x88, 0x6d, + 0x88, 0x6e, 0x86, 0x6d, 0x80, 0x73, 0x7e, 0x7a, 0x80, 0x80, 0x80, 0x81, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7e, 0x7f, 0x7e, 0x7f, 0x7e, + 0x56, 0x66, 0x56, 0x63, 0x56, 0x62, 0x56, 0x62, 0x57, 0x5f, 0x57, 0x60, + 0x56, 0x63, 0x55, 0x64, 0x54, 0x66, 0x53, 0x65, 0x52, 0x66, 0x51, 0x67, + 0x4e, 0x66, 0x4c, 0x69, 0x4b, 0x6b, 0x49, 0x6a, 0x48, 0x6a, 0x48, 0x6a, + 0x48, 0x6a, 0x47, 0x6a, 0x47, 0x6a, 0x48, 0x6a, 0x48, 0x68, 0x50, 0x67, + 0x56, 0x67, 0x5d, 0x68, 0x5e, 0x68, 0x60, 0x68, 0x63, 0x67, 0x65, 0x67, + 0x67, 0x68, 0x69, 0x68, 0x6b, 0x68, 0x6e, 0x6b, 0x6e, 0x6b, 0x6e, 0x6b, + 0x6d, 0x6a, 0x6d, 0x6a, 0x6b, 0x6b, 0x6a, 0x6b, 0x6a, 0x6a, 0x6b, 0x6a, + 0x6a, 0x6a, 0x6b, 0x6b, 0x6d, 0x6a, 0x6d, 0x6c, 0x68, 0x72, 0x63, 0x7a, + 0x63, 0x85, 0x64, 0x86, 0x64, 0x87, 0x60, 0x87, 0x62, 0x83, 0x76, 0x79, + 0x86, 0x79, 0x89, 0x77, 0x8e, 0x76, 0x90, 0x78, 0x92, 0x7b, 0x94, 0x7b, + 0x95, 0x78, 0x8f, 0x7a, 0x82, 0x7e, 0x6f, 0x83, 0x5e, 0x8b, 0x6a, 0x88, + 0x74, 0x84, 0x7b, 0x7e, 0x75, 0x7a, 0x72, 0x77, 0x74, 0x78, 0x72, 0x78, + 0x76, 0x7a, 0x78, 0x7a, 0x77, 0x79, 0x71, 0x78, 0x65, 0x78, 0x62, 0x75, + 0x60, 0x6f, 0x61, 0x6c, 0x62, 0x6a, 0x63, 0x68, 0x62, 0x69, 0x62, 0x68, + 0x61, 0x68, 0x61, 0x6a, 0x60, 0x68, 0x60, 0x69, 0x60, 0x6a, 0x60, 0x6b, + 0x60, 0x6c, 0x5f, 0x6d, 0x5c, 0x6e, 0x5f, 0x70, 0x63, 0x74, 0x65, 0x78, + 0x67, 0x7d, 0x68, 0x80, 0x68, 0x83, 0x5f, 0x88, 0x57, 0x87, 0x55, 0x84, + 0x53, 0x81, 0x54, 0x7e, 0x5a, 0x78, 0x5c, 0x78, 0x74, 0x7d, 0x70, 0x7b, + 0x69, 0x7d, 0x63, 0x80, 0x69, 0x7d, 0x6f, 0x7a, 0x76, 0x7a, 0x75, 0x7b, + 0x72, 0x7b, 0x75, 0x71, 0x65, 0x71, 0x5e, 0x6f, 0x5f, 0x6e, 0x60, 0x6d, + 0x61, 0x6d, 0x60, 0x6c, 0x62, 0x6f, 0x66, 0x72, 0x6d, 0x74, 0x74, 0x72, + 0x76, 0x70, 0x76, 0x70, 0x73, 0x6e, 0x73, 0x6e, 0x73, 0x6e, 0x73, 0x6d, + 0x74, 0x6e, 0x77, 0x6e, 0x79, 0x6f, 0x7c, 0x6f, 0x7e, 0x70, 0x82, 0x72, + 0x84, 0x72, 0x87, 0x70, 0x8a, 0x70, 0x8a, 0x6e, 0x89, 0x6e, 0x89, 0x6e, + 0x89, 0x6e, 0x88, 0x6d, 0x88, 0x6e, 0x88, 0x6e, 0x88, 0x6e, 0x86, 0x6f, + 0x80, 0x75, 0x7e, 0x7a, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x7f, 0x7f, 0x7f, 0x7e, 0x7f, 0x7e, 0x7f, 0x7e, 0x55, 0x65, 0x55, 0x62, + 0x56, 0x63, 0x57, 0x63, 0x57, 0x60, 0x56, 0x5f, 0x56, 0x61, 0x56, 0x63, + 0x55, 0x64, 0x54, 0x64, 0x53, 0x65, 0x52, 0x65, 0x50, 0x65, 0x4e, 0x69, + 0x4c, 0x6a, 0x4a, 0x69, 0x4a, 0x69, 0x49, 0x6a, 0x4a, 0x6a, 0x49, 0x6a, + 0x48, 0x6a, 0x48, 0x69, 0x49, 0x68, 0x4f, 0x68, 0x55, 0x67, 0x5b, 0x67, + 0x5d, 0x67, 0x60, 0x67, 0x63, 0x66, 0x64, 0x66, 0x66, 0x67, 0x68, 0x67, + 0x6a, 0x68, 0x6c, 0x6a, 0x6d, 0x6b, 0x6d, 0x6b, 0x6b, 0x69, 0x6c, 0x6a, + 0x6b, 0x6b, 0x6a, 0x6b, 0x6a, 0x6b, 0x6a, 0x6a, 0x69, 0x69, 0x6b, 0x6a, + 0x6e, 0x6b, 0x6a, 0x6d, 0x62, 0x75, 0x5e, 0x7c, 0x5f, 0x85, 0x62, 0x86, + 0x61, 0x85, 0x5c, 0x81, 0x5f, 0x7d, 0x75, 0x78, 0x84, 0x79, 0x87, 0x78, + 0x8d, 0x76, 0x8d, 0x78, 0x91, 0x78, 0x95, 0x77, 0x95, 0x78, 0x8f, 0x77, + 0x8b, 0x7a, 0x70, 0x82, 0x5c, 0x88, 0x67, 0x88, 0x72, 0x83, 0x74, 0x7a, + 0x6f, 0x78, 0x72, 0x77, 0x74, 0x77, 0x71, 0x78, 0x70, 0x79, 0x74, 0x79, + 0x77, 0x79, 0x77, 0x78, 0x70, 0x7a, 0x6b, 0x79, 0x67, 0x76, 0x63, 0x72, + 0x62, 0x71, 0x62, 0x6f, 0x62, 0x6d, 0x62, 0x6a, 0x62, 0x68, 0x62, 0x68, + 0x63, 0x66, 0x64, 0x67, 0x62, 0x69, 0x62, 0x6a, 0x63, 0x6c, 0x61, 0x6d, + 0x62, 0x6f, 0x64, 0x72, 0x66, 0x76, 0x65, 0x79, 0x63, 0x7e, 0x62, 0x82, + 0x63, 0x85, 0x5a, 0x89, 0x54, 0x87, 0x55, 0x82, 0x54, 0x7e, 0x54, 0x7d, + 0x59, 0x79, 0x5b, 0x77, 0x71, 0x7b, 0x71, 0x80, 0x6b, 0x7f, 0x6a, 0x7d, + 0x68, 0x7d, 0x6d, 0x7d, 0x70, 0x7d, 0x6d, 0x7b, 0x70, 0x78, 0x6e, 0x72, + 0x64, 0x73, 0x62, 0x70, 0x60, 0x6e, 0x60, 0x6c, 0x5f, 0x6b, 0x5f, 0x6c, + 0x61, 0x6f, 0x64, 0x73, 0x6a, 0x74, 0x71, 0x71, 0x75, 0x6f, 0x75, 0x6d, + 0x72, 0x6c, 0x73, 0x6d, 0x71, 0x6c, 0x72, 0x6c, 0x72, 0x6d, 0x75, 0x6d, + 0x77, 0x6d, 0x7a, 0x6f, 0x7d, 0x70, 0x82, 0x72, 0x83, 0x71, 0x86, 0x6f, + 0x8a, 0x6f, 0x8a, 0x6e, 0x89, 0x6e, 0x8a, 0x6d, 0x8a, 0x6d, 0x89, 0x6e, + 0x88, 0x6e, 0x89, 0x6e, 0x89, 0x6e, 0x87, 0x6e, 0x81, 0x74, 0x7f, 0x7a, + 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x7e, + 0x7f, 0x7d, 0x7f, 0x7e, 0x55, 0x64, 0x55, 0x61, 0x55, 0x62, 0x57, 0x63, + 0x56, 0x63, 0x56, 0x5f, 0x57, 0x5d, 0x57, 0x5f, 0x55, 0x61, 0x55, 0x63, + 0x54, 0x65, 0x52, 0x65, 0x51, 0x66, 0x4e, 0x68, 0x4c, 0x68, 0x4b, 0x68, + 0x4b, 0x68, 0x4c, 0x6a, 0x4c, 0x6a, 0x4b, 0x69, 0x49, 0x69, 0x48, 0x68, + 0x49, 0x68, 0x4e, 0x68, 0x55, 0x67, 0x5b, 0x67, 0x5d, 0x66, 0x60, 0x66, + 0x63, 0x66, 0x65, 0x66, 0x66, 0x66, 0x69, 0x65, 0x6b, 0x68, 0x6b, 0x68, + 0x6b, 0x6a, 0x6b, 0x6a, 0x69, 0x68, 0x6b, 0x6a, 0x6c, 0x6c, 0x6a, 0x6c, + 0x6a, 0x6c, 0x68, 0x6a, 0x68, 0x68, 0x6b, 0x69, 0x6c, 0x6b, 0x66, 0x6f, + 0x5e, 0x78, 0x5d, 0x7e, 0x5d, 0x83, 0x5e, 0x82, 0x5b, 0x7f, 0x57, 0x7b, + 0x5a, 0x77, 0x72, 0x7a, 0x80, 0x7d, 0x88, 0x77, 0x8d, 0x75, 0x8e, 0x77, + 0x91, 0x77, 0x92, 0x76, 0x91, 0x77, 0x90, 0x78, 0x8c, 0x7b, 0x72, 0x84, + 0x61, 0x86, 0x69, 0x85, 0x6c, 0x80, 0x6c, 0x76, 0x6b, 0x77, 0x73, 0x77, + 0x74, 0x78, 0x6f, 0x78, 0x6e, 0x79, 0x71, 0x79, 0x74, 0x79, 0x76, 0x79, + 0x76, 0x7a, 0x72, 0x7a, 0x6b, 0x7a, 0x65, 0x78, 0x63, 0x77, 0x62, 0x76, + 0x62, 0x73, 0x62, 0x6c, 0x63, 0x68, 0x62, 0x68, 0x63, 0x6a, 0x65, 0x6c, + 0x63, 0x69, 0x64, 0x6a, 0x63, 0x6a, 0x61, 0x6b, 0x64, 0x6f, 0x65, 0x74, + 0x64, 0x78, 0x64, 0x79, 0x61, 0x7e, 0x5f, 0x82, 0x5f, 0x85, 0x58, 0x87, + 0x55, 0x86, 0x58, 0x80, 0x58, 0x7a, 0x58, 0x7b, 0x59, 0x7a, 0x59, 0x75, + 0x6b, 0x79, 0x73, 0x81, 0x67, 0x80, 0x6e, 0x7b, 0x69, 0x7b, 0x6f, 0x7e, + 0x6d, 0x7d, 0x6b, 0x7a, 0x6e, 0x76, 0x66, 0x75, 0x67, 0x76, 0x63, 0x73, + 0x61, 0x6f, 0x5e, 0x6c, 0x5d, 0x6a, 0x5e, 0x6b, 0x60, 0x70, 0x62, 0x74, + 0x68, 0x73, 0x6f, 0x6f, 0x74, 0x6e, 0x74, 0x6b, 0x72, 0x6c, 0x72, 0x6c, + 0x70, 0x6c, 0x70, 0x6c, 0x72, 0x6d, 0x74, 0x6c, 0x74, 0x6c, 0x79, 0x6e, + 0x7c, 0x70, 0x80, 0x70, 0x83, 0x70, 0x86, 0x6e, 0x89, 0x6f, 0x8a, 0x6e, + 0x8a, 0x6e, 0x8a, 0x6c, 0x8a, 0x6c, 0x8a, 0x6e, 0x89, 0x6e, 0x89, 0x6e, + 0x8a, 0x6e, 0x88, 0x6d, 0x83, 0x72, 0x80, 0x79, 0x7f, 0x7f, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7e, 0x7f, 0x7e, + 0x55, 0x66, 0x55, 0x63, 0x55, 0x64, 0x56, 0x65, 0x56, 0x63, 0x56, 0x5f, + 0x57, 0x5c, 0x57, 0x5d, 0x57, 0x5f, 0x56, 0x61, 0x54, 0x64, 0x53, 0x65, + 0x51, 0x66, 0x50, 0x66, 0x4e, 0x67, 0x4b, 0x68, 0x4b, 0x68, 0x4b, 0x6a, + 0x4c, 0x6a, 0x4b, 0x6a, 0x49, 0x6a, 0x48, 0x69, 0x48, 0x68, 0x4c, 0x68, + 0x53, 0x68, 0x5a, 0x66, 0x5c, 0x65, 0x5e, 0x66, 0x61, 0x66, 0x63, 0x66, + 0x66, 0x65, 0x68, 0x65, 0x6a, 0x68, 0x6a, 0x68, 0x69, 0x6a, 0x69, 0x6a, + 0x6b, 0x6b, 0x6d, 0x6d, 0x6e, 0x6f, 0x6b, 0x70, 0x6b, 0x6f, 0x6d, 0x6e, + 0x6c, 0x6c, 0x69, 0x6b, 0x68, 0x6b, 0x61, 0x70, 0x5a, 0x79, 0x5b, 0x7e, + 0x5b, 0x7f, 0x59, 0x7d, 0x56, 0x7a, 0x55, 0x77, 0x58, 0x75, 0x6e, 0x7a, + 0x7e, 0x7e, 0x85, 0x7a, 0x8d, 0x77, 0x8e, 0x78, 0x90, 0x77, 0x92, 0x77, + 0x90, 0x7a, 0x8a, 0x7d, 0x81, 0x80, 0x6f, 0x82, 0x65, 0x87, 0x6c, 0x85, + 0x69, 0x7f, 0x66, 0x75, 0x6e, 0x77, 0x73, 0x77, 0x72, 0x78, 0x6f, 0x78, + 0x6e, 0x7a, 0x6d, 0x7b, 0x70, 0x7b, 0x73, 0x7b, 0x76, 0x7a, 0x76, 0x7a, + 0x72, 0x7a, 0x6b, 0x7a, 0x68, 0x7a, 0x64, 0x79, 0x63, 0x74, 0x62, 0x6f, + 0x62, 0x6d, 0x62, 0x6d, 0x61, 0x6f, 0x63, 0x71, 0x63, 0x6d, 0x63, 0x6c, + 0x63, 0x6c, 0x61, 0x6d, 0x66, 0x71, 0x66, 0x76, 0x66, 0x79, 0x66, 0x7b, + 0x61, 0x7f, 0x5f, 0x82, 0x5e, 0x84, 0x59, 0x83, 0x57, 0x81, 0x5a, 0x7a, + 0x5b, 0x75, 0x5b, 0x77, 0x5c, 0x79, 0x5a, 0x75, 0x62, 0x79, 0x77, 0x80, + 0x6a, 0x7e, 0x6c, 0x79, 0x71, 0x79, 0x6d, 0x7a, 0x6d, 0x79, 0x6e, 0x77, + 0x68, 0x75, 0x64, 0x75, 0x69, 0x76, 0x64, 0x73, 0x61, 0x71, 0x5e, 0x6e, + 0x5e, 0x6c, 0x5d, 0x6d, 0x5e, 0x70, 0x60, 0x74, 0x65, 0x73, 0x6c, 0x6f, + 0x72, 0x6e, 0x72, 0x6b, 0x70, 0x6b, 0x70, 0x6b, 0x6f, 0x6b, 0x6e, 0x6b, + 0x70, 0x6b, 0x72, 0x6b, 0x73, 0x6a, 0x76, 0x6c, 0x7b, 0x6e, 0x7e, 0x6f, + 0x81, 0x6f, 0x86, 0x6f, 0x89, 0x6f, 0x89, 0x6e, 0x89, 0x6e, 0x8a, 0x6c, + 0x8a, 0x6c, 0x8a, 0x6e, 0x89, 0x6e, 0x89, 0x6e, 0x8a, 0x6e, 0x88, 0x6d, + 0x83, 0x72, 0x80, 0x79, 0x7f, 0x7f, 0x80, 0x81, 0x80, 0x80, 0x80, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7e, 0x7f, 0x7e, 0x55, 0x67, 0x55, 0x65, + 0x55, 0x65, 0x55, 0x66, 0x56, 0x64, 0x56, 0x5f, 0x57, 0x5e, 0x57, 0x60, + 0x57, 0x60, 0x57, 0x60, 0x55, 0x62, 0x54, 0x64, 0x53, 0x65, 0x52, 0x65, + 0x50, 0x65, 0x4d, 0x67, 0x4b, 0x68, 0x4b, 0x6a, 0x4b, 0x6a, 0x4b, 0x6a, + 0x49, 0x6a, 0x49, 0x69, 0x49, 0x68, 0x4b, 0x67, 0x50, 0x67, 0x57, 0x66, + 0x5b, 0x65, 0x5c, 0x65, 0x60, 0x65, 0x62, 0x65, 0x66, 0x66, 0x69, 0x66, + 0x6a, 0x67, 0x69, 0x68, 0x68, 0x6b, 0x68, 0x6c, 0x6d, 0x6f, 0x6f, 0x71, + 0x70, 0x72, 0x6d, 0x73, 0x6d, 0x73, 0x72, 0x72, 0x70, 0x71, 0x68, 0x6e, + 0x64, 0x6b, 0x61, 0x71, 0x5c, 0x7a, 0x5a, 0x7d, 0x59, 0x7d, 0x58, 0x7d, + 0x57, 0x7a, 0x58, 0x77, 0x5a, 0x78, 0x69, 0x79, 0x74, 0x7b, 0x7e, 0x7d, + 0x85, 0x7d, 0x87, 0x7c, 0x89, 0x7c, 0x89, 0x7d, 0x82, 0x80, 0x78, 0x82, + 0x74, 0x82, 0x6d, 0x7f, 0x66, 0x85, 0x71, 0x84, 0x6a, 0x81, 0x69, 0x78, + 0x72, 0x78, 0x73, 0x78, 0x72, 0x78, 0x6f, 0x78, 0x6c, 0x7c, 0x68, 0x7d, + 0x6a, 0x7d, 0x6f, 0x7c, 0x72, 0x7c, 0x73, 0x7b, 0x75, 0x78, 0x75, 0x77, + 0x72, 0x79, 0x6a, 0x7a, 0x66, 0x77, 0x64, 0x73, 0x62, 0x72, 0x61, 0x71, + 0x60, 0x70, 0x63, 0x71, 0x63, 0x70, 0x64, 0x71, 0x67, 0x73, 0x67, 0x73, + 0x68, 0x74, 0x69, 0x78, 0x68, 0x7b, 0x68, 0x7d, 0x62, 0x7f, 0x60, 0x83, + 0x5d, 0x84, 0x5b, 0x7e, 0x59, 0x7a, 0x5b, 0x75, 0x5a, 0x70, 0x5a, 0x72, + 0x5d, 0x77, 0x5c, 0x75, 0x58, 0x78, 0x77, 0x7e, 0x71, 0x7d, 0x6b, 0x76, + 0x74, 0x72, 0x73, 0x77, 0x73, 0x72, 0x6e, 0x70, 0x62, 0x75, 0x65, 0x76, + 0x6a, 0x75, 0x64, 0x74, 0x60, 0x73, 0x5e, 0x70, 0x5e, 0x6e, 0x5d, 0x6e, + 0x5c, 0x71, 0x5e, 0x74, 0x62, 0x73, 0x68, 0x6e, 0x6f, 0x6d, 0x71, 0x6b, + 0x6e, 0x6a, 0x6f, 0x69, 0x6d, 0x69, 0x6d, 0x69, 0x6d, 0x69, 0x70, 0x69, + 0x71, 0x69, 0x75, 0x6a, 0x79, 0x6c, 0x7c, 0x6d, 0x80, 0x6e, 0x85, 0x6f, + 0x89, 0x6f, 0x8a, 0x6e, 0x8a, 0x6d, 0x8b, 0x6c, 0x8a, 0x6c, 0x8a, 0x6d, + 0x89, 0x6d, 0x89, 0x6e, 0x89, 0x6e, 0x89, 0x6d, 0x83, 0x73, 0x80, 0x79, + 0x80, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x7e, + 0x7f, 0x7d, 0x7f, 0x7e, 0x54, 0x66, 0x55, 0x64, 0x55, 0x64, 0x55, 0x65, + 0x56, 0x63, 0x57, 0x60, 0x57, 0x5e, 0x57, 0x5f, 0x57, 0x60, 0x57, 0x60, + 0x56, 0x60, 0x55, 0x61, 0x54, 0x63, 0x53, 0x65, 0x50, 0x65, 0x4e, 0x67, + 0x4c, 0x67, 0x4b, 0x69, 0x4b, 0x69, 0x4b, 0x69, 0x4b, 0x6a, 0x4a, 0x68, + 0x4a, 0x68, 0x4c, 0x67, 0x4e, 0x66, 0x54, 0x65, 0x59, 0x65, 0x5b, 0x65, + 0x5f, 0x65, 0x63, 0x65, 0x66, 0x66, 0x68, 0x66, 0x68, 0x67, 0x68, 0x6a, + 0x67, 0x6d, 0x69, 0x6f, 0x6e, 0x71, 0x71, 0x73, 0x71, 0x73, 0x6f, 0x74, + 0x6f, 0x74, 0x73, 0x74, 0x73, 0x73, 0x6c, 0x71, 0x65, 0x6e, 0x63, 0x70, + 0x60, 0x78, 0x5b, 0x7b, 0x58, 0x7d, 0x57, 0x7c, 0x59, 0x79, 0x5a, 0x77, + 0x5a, 0x78, 0x67, 0x78, 0x6e, 0x7b, 0x78, 0x7d, 0x7d, 0x80, 0x7e, 0x81, + 0x7e, 0x80, 0x7b, 0x81, 0x79, 0x81, 0x70, 0x82, 0x6b, 0x82, 0x71, 0x80, + 0x6a, 0x81, 0x77, 0x7d, 0x6b, 0x7e, 0x71, 0x7b, 0x76, 0x7a, 0x74, 0x7a, + 0x74, 0x78, 0x6e, 0x78, 0x6a, 0x7d, 0x65, 0x7e, 0x65, 0x7d, 0x6a, 0x7c, + 0x6e, 0x7c, 0x6f, 0x7c, 0x72, 0x79, 0x73, 0x77, 0x74, 0x78, 0x71, 0x79, + 0x6c, 0x7a, 0x69, 0x77, 0x65, 0x75, 0x62, 0x74, 0x62, 0x72, 0x64, 0x70, + 0x63, 0x72, 0x66, 0x74, 0x68, 0x75, 0x6c, 0x74, 0x6a, 0x77, 0x6b, 0x7a, + 0x6a, 0x7c, 0x68, 0x7d, 0x62, 0x7e, 0x60, 0x85, 0x5e, 0x84, 0x5c, 0x7b, + 0x5a, 0x77, 0x5b, 0x75, 0x59, 0x70, 0x59, 0x71, 0x5d, 0x74, 0x5d, 0x74, + 0x55, 0x76, 0x6d, 0x7b, 0x77, 0x7e, 0x6e, 0x76, 0x71, 0x70, 0x74, 0x72, + 0x72, 0x70, 0x67, 0x70, 0x5f, 0x74, 0x67, 0x76, 0x6b, 0x75, 0x64, 0x74, + 0x5f, 0x73, 0x5d, 0x71, 0x5e, 0x6e, 0x5e, 0x6f, 0x5c, 0x72, 0x5d, 0x74, + 0x62, 0x72, 0x66, 0x6d, 0x6c, 0x6c, 0x6d, 0x6a, 0x6d, 0x69, 0x6d, 0x69, + 0x6b, 0x68, 0x6b, 0x68, 0x6b, 0x67, 0x6d, 0x67, 0x71, 0x69, 0x75, 0x6a, + 0x77, 0x6a, 0x7c, 0x6b, 0x80, 0x6d, 0x83, 0x6e, 0x88, 0x6e, 0x8a, 0x6c, + 0x8c, 0x6c, 0x8b, 0x6b, 0x8a, 0x6b, 0x8a, 0x6c, 0x8b, 0x6c, 0x8a, 0x6e, + 0x89, 0x6e, 0x89, 0x6d, 0x84, 0x74, 0x80, 0x7a, 0x7f, 0x7f, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x7e, 0x7f, 0x7d, 0x7f, 0x7e, + 0x4f, 0x68, 0x54, 0x66, 0x55, 0x65, 0x55, 0x65, 0x56, 0x63, 0x57, 0x61, + 0x58, 0x5d, 0x57, 0x5f, 0x57, 0x61, 0x57, 0x60, 0x57, 0x60, 0x56, 0x61, + 0x54, 0x63, 0x53, 0x65, 0x51, 0x65, 0x50, 0x67, 0x4d, 0x68, 0x4c, 0x68, + 0x4c, 0x68, 0x4c, 0x69, 0x4b, 0x6a, 0x4a, 0x68, 0x4a, 0x67, 0x4b, 0x66, + 0x4c, 0x65, 0x51, 0x65, 0x55, 0x65, 0x58, 0x65, 0x5d, 0x65, 0x60, 0x65, + 0x62, 0x64, 0x65, 0x65, 0x64, 0x68, 0x64, 0x6b, 0x66, 0x6f, 0x6b, 0x72, + 0x71, 0x74, 0x72, 0x75, 0x73, 0x76, 0x71, 0x76, 0x6f, 0x76, 0x71, 0x76, + 0x73, 0x76, 0x71, 0x73, 0x6c, 0x70, 0x69, 0x71, 0x67, 0x75, 0x63, 0x77, + 0x5a, 0x79, 0x5a, 0x79, 0x5d, 0x77, 0x5e, 0x75, 0x5d, 0x76, 0x63, 0x74, + 0x73, 0x78, 0x71, 0x7b, 0x75, 0x7e, 0x76, 0x7f, 0x75, 0x7f, 0x74, 0x80, + 0x71, 0x81, 0x6b, 0x83, 0x6c, 0x81, 0x72, 0x80, 0x72, 0x7f, 0x7e, 0x77, + 0x6e, 0x7b, 0x74, 0x79, 0x77, 0x7a, 0x74, 0x7a, 0x72, 0x78, 0x6f, 0x78, + 0x6d, 0x7b, 0x69, 0x7c, 0x64, 0x7b, 0x65, 0x7b, 0x67, 0x7b, 0x69, 0x7b, + 0x6c, 0x79, 0x70, 0x78, 0x72, 0x78, 0x76, 0x79, 0x74, 0x7a, 0x6f, 0x79, + 0x6d, 0x78, 0x6c, 0x78, 0x67, 0x76, 0x67, 0x74, 0x68, 0x73, 0x6b, 0x76, + 0x6b, 0x76, 0x71, 0x76, 0x6f, 0x79, 0x69, 0x7c, 0x66, 0x7f, 0x64, 0x7f, + 0x61, 0x7f, 0x61, 0x85, 0x5f, 0x84, 0x5b, 0x7b, 0x5b, 0x76, 0x5b, 0x73, + 0x59, 0x6f, 0x58, 0x70, 0x5a, 0x71, 0x5c, 0x72, 0x57, 0x74, 0x5a, 0x76, + 0x6e, 0x7b, 0x76, 0x7b, 0x6f, 0x76, 0x6f, 0x71, 0x67, 0x70, 0x60, 0x70, + 0x5e, 0x72, 0x68, 0x75, 0x6b, 0x75, 0x64, 0x74, 0x5f, 0x73, 0x5e, 0x72, + 0x5e, 0x70, 0x5e, 0x71, 0x5a, 0x74, 0x59, 0x76, 0x60, 0x73, 0x65, 0x6f, + 0x69, 0x6c, 0x6a, 0x69, 0x6b, 0x67, 0x6b, 0x67, 0x6a, 0x68, 0x69, 0x68, + 0x69, 0x67, 0x6b, 0x67, 0x6f, 0x68, 0x73, 0x68, 0x75, 0x68, 0x7a, 0x6b, + 0x7e, 0x6d, 0x81, 0x6d, 0x87, 0x6c, 0x8a, 0x6c, 0x8c, 0x6c, 0x8a, 0x6b, + 0x8a, 0x6b, 0x8b, 0x6c, 0x8b, 0x6c, 0x8a, 0x6e, 0x89, 0x6e, 0x89, 0x6e, + 0x85, 0x74, 0x81, 0x7a, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x7f, + 0x7f, 0x7e, 0x7f, 0x7e, 0x7f, 0x7e, 0x7f, 0x7e, 0x4b, 0x6a, 0x52, 0x68, + 0x55, 0x65, 0x55, 0x65, 0x56, 0x64, 0x56, 0x60, 0x58, 0x5d, 0x58, 0x5f, + 0x57, 0x60, 0x56, 0x60, 0x57, 0x61, 0x56, 0x61, 0x55, 0x64, 0x53, 0x65, + 0x52, 0x65, 0x51, 0x67, 0x4e, 0x67, 0x4c, 0x68, 0x4c, 0x68, 0x4b, 0x69, + 0x4b, 0x6a, 0x4a, 0x68, 0x4a, 0x67, 0x4b, 0x66, 0x4b, 0x65, 0x4f, 0x66, + 0x52, 0x65, 0x55, 0x64, 0x5b, 0x65, 0x5e, 0x65, 0x5f, 0x63, 0x61, 0x63, + 0x61, 0x69, 0x61, 0x6d, 0x64, 0x70, 0x6c, 0x73, 0x72, 0x74, 0x74, 0x76, + 0x75, 0x78, 0x73, 0x77, 0x6f, 0x77, 0x6e, 0x77, 0x71, 0x77, 0x70, 0x75, + 0x6e, 0x73, 0x6e, 0x71, 0x6d, 0x71, 0x69, 0x73, 0x5e, 0x76, 0x5d, 0x77, + 0x5f, 0x75, 0x61, 0x74, 0x61, 0x74, 0x60, 0x71, 0x72, 0x75, 0x73, 0x78, + 0x75, 0x78, 0x78, 0x78, 0x70, 0x7e, 0x70, 0x82, 0x71, 0x82, 0x6d, 0x81, + 0x71, 0x7f, 0x6d, 0x7e, 0x73, 0x81, 0x7c, 0x7b, 0x6a, 0x7a, 0x75, 0x77, + 0x77, 0x79, 0x74, 0x7a, 0x70, 0x79, 0x71, 0x78, 0x71, 0x7a, 0x6c, 0x7a, + 0x67, 0x79, 0x66, 0x79, 0x66, 0x7b, 0x68, 0x7b, 0x6c, 0x79, 0x6f, 0x78, + 0x70, 0x78, 0x75, 0x79, 0x74, 0x7a, 0x71, 0x7b, 0x74, 0x7c, 0x75, 0x7b, + 0x70, 0x79, 0x6d, 0x77, 0x6d, 0x75, 0x6f, 0x77, 0x6f, 0x77, 0x74, 0x77, + 0x72, 0x7b, 0x67, 0x7d, 0x62, 0x80, 0x61, 0x80, 0x60, 0x80, 0x60, 0x85, + 0x5e, 0x84, 0x5b, 0x7b, 0x5a, 0x75, 0x5a, 0x71, 0x5a, 0x6d, 0x58, 0x6e, + 0x57, 0x70, 0x5b, 0x70, 0x59, 0x72, 0x52, 0x73, 0x5a, 0x77, 0x6d, 0x7a, + 0x69, 0x76, 0x66, 0x71, 0x63, 0x70, 0x60, 0x6f, 0x5c, 0x70, 0x64, 0x74, + 0x67, 0x75, 0x62, 0x74, 0x5f, 0x73, 0x5d, 0x72, 0x5e, 0x72, 0x5e, 0x72, + 0x59, 0x75, 0x56, 0x77, 0x5e, 0x75, 0x62, 0x70, 0x66, 0x6c, 0x67, 0x69, + 0x69, 0x66, 0x69, 0x66, 0x68, 0x67, 0x68, 0x68, 0x67, 0x68, 0x6a, 0x68, + 0x6d, 0x68, 0x72, 0x67, 0x73, 0x68, 0x78, 0x6b, 0x7d, 0x6c, 0x80, 0x6b, + 0x86, 0x6b, 0x8a, 0x6c, 0x8c, 0x6d, 0x8a, 0x6a, 0x8a, 0x6b, 0x8a, 0x6c, + 0x8b, 0x6c, 0x8a, 0x6e, 0x8a, 0x6e, 0x89, 0x6e, 0x84, 0x74, 0x80, 0x7a, + 0x7f, 0x7e, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7e, 0x7f, 0x7e, + 0x7f, 0x7e, 0x7f, 0x7e, 0x4e, 0x6b, 0x4d, 0x6b, 0x52, 0x68, 0x54, 0x65, + 0x55, 0x64, 0x56, 0x62, 0x57, 0x60, 0x57, 0x62, 0x56, 0x63, 0x56, 0x62, + 0x56, 0x61, 0x56, 0x61, 0x56, 0x63, 0x54, 0x65, 0x52, 0x66, 0x51, 0x67, + 0x4e, 0x67, 0x4d, 0x67, 0x4b, 0x69, 0x4c, 0x6b, 0x4c, 0x69, 0x4b, 0x68, + 0x4a, 0x69, 0x4c, 0x67, 0x4c, 0x65, 0x50, 0x65, 0x52, 0x66, 0x53, 0x65, + 0x57, 0x65, 0x5b, 0x65, 0x5f, 0x63, 0x61, 0x65, 0x60, 0x6c, 0x63, 0x70, + 0x66, 0x72, 0x6c, 0x73, 0x72, 0x73, 0x75, 0x75, 0x77, 0x77, 0x77, 0x77, + 0x73, 0x76, 0x6d, 0x76, 0x6b, 0x76, 0x6e, 0x76, 0x6c, 0x74, 0x6e, 0x72, + 0x70, 0x72, 0x6f, 0x73, 0x64, 0x76, 0x5f, 0x76, 0x62, 0x75, 0x63, 0x73, + 0x63, 0x73, 0x62, 0x72, 0x6a, 0x72, 0x73, 0x76, 0x78, 0x76, 0x7b, 0x77, + 0x73, 0x7e, 0x6f, 0x83, 0x71, 0x81, 0x70, 0x80, 0x70, 0x7e, 0x6b, 0x80, + 0x76, 0x81, 0x72, 0x7e, 0x69, 0x7a, 0x75, 0x79, 0x77, 0x79, 0x76, 0x78, + 0x72, 0x77, 0x70, 0x77, 0x70, 0x78, 0x6d, 0x78, 0x68, 0x77, 0x67, 0x76, + 0x69, 0x7b, 0x6a, 0x7c, 0x6c, 0x7c, 0x6d, 0x7b, 0x6d, 0x7b, 0x71, 0x7a, + 0x71, 0x7a, 0x6e, 0x7c, 0x71, 0x7e, 0x75, 0x7e, 0x74, 0x7d, 0x70, 0x7a, + 0x70, 0x79, 0x71, 0x79, 0x70, 0x78, 0x70, 0x79, 0x6e, 0x7b, 0x64, 0x7f, + 0x61, 0x80, 0x60, 0x80, 0x5e, 0x81, 0x5e, 0x83, 0x5e, 0x81, 0x5d, 0x7c, + 0x5c, 0x78, 0x5a, 0x73, 0x5c, 0x6d, 0x59, 0x6d, 0x56, 0x70, 0x5a, 0x6e, + 0x58, 0x70, 0x54, 0x72, 0x54, 0x77, 0x60, 0x7b, 0x65, 0x76, 0x63, 0x70, + 0x66, 0x70, 0x61, 0x6f, 0x5a, 0x70, 0x62, 0x74, 0x63, 0x76, 0x60, 0x75, + 0x5e, 0x73, 0x5c, 0x71, 0x5d, 0x72, 0x5d, 0x72, 0x59, 0x75, 0x57, 0x77, + 0x5c, 0x75, 0x62, 0x74, 0x64, 0x70, 0x65, 0x6a, 0x66, 0x67, 0x66, 0x65, + 0x66, 0x66, 0x66, 0x66, 0x67, 0x65, 0x69, 0x66, 0x6c, 0x67, 0x71, 0x67, + 0x74, 0x68, 0x77, 0x69, 0x7a, 0x6a, 0x7f, 0x6a, 0x84, 0x6b, 0x88, 0x6d, + 0x8a, 0x6d, 0x8a, 0x6c, 0x8a, 0x6c, 0x8a, 0x6e, 0x8b, 0x6f, 0x8a, 0x70, + 0x8a, 0x6e, 0x88, 0x6e, 0x83, 0x76, 0x80, 0x7a, 0x80, 0x7f, 0x80, 0x80, + 0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x7e, 0x7f, 0x7d, 0x7f, 0x7d, + 0x55, 0x6b, 0x4a, 0x6b, 0x4e, 0x69, 0x54, 0x66, 0x55, 0x65, 0x56, 0x62, + 0x56, 0x61, 0x56, 0x63, 0x56, 0x65, 0x56, 0x63, 0x56, 0x62, 0x56, 0x62, + 0x56, 0x61, 0x54, 0x63, 0x52, 0x65, 0x51, 0x66, 0x4f, 0x65, 0x4f, 0x66, + 0x4c, 0x69, 0x4b, 0x6b, 0x4c, 0x69, 0x4b, 0x68, 0x4b, 0x69, 0x4c, 0x67, + 0x4d, 0x65, 0x4e, 0x65, 0x4e, 0x64, 0x4f, 0x64, 0x54, 0x63, 0x58, 0x64, + 0x5d, 0x65, 0x5f, 0x6a, 0x60, 0x6f, 0x64, 0x72, 0x67, 0x73, 0x6c, 0x73, + 0x72, 0x73, 0x76, 0x75, 0x79, 0x77, 0x7a, 0x77, 0x77, 0x76, 0x6f, 0x75, + 0x6a, 0x76, 0x6c, 0x75, 0x6c, 0x75, 0x6c, 0x74, 0x6f, 0x73, 0x73, 0x73, + 0x6a, 0x76, 0x62, 0x77, 0x63, 0x74, 0x63, 0x73, 0x63, 0x73, 0x67, 0x73, + 0x65, 0x71, 0x6a, 0x76, 0x74, 0x77, 0x79, 0x78, 0x75, 0x7d, 0x71, 0x80, + 0x71, 0x7f, 0x6e, 0x7f, 0x6c, 0x7d, 0x6d, 0x7f, 0x75, 0x82, 0x67, 0x7f, + 0x6c, 0x7a, 0x75, 0x7a, 0x77, 0x79, 0x77, 0x77, 0x73, 0x76, 0x70, 0x76, + 0x6f, 0x76, 0x6d, 0x76, 0x69, 0x75, 0x68, 0x74, 0x6a, 0x79, 0x6b, 0x7a, + 0x6b, 0x7a, 0x6c, 0x7b, 0x6d, 0x7c, 0x6e, 0x7e, 0x6d, 0x7f, 0x6a, 0x7f, + 0x6a, 0x80, 0x6d, 0x80, 0x6e, 0x7f, 0x6e, 0x7d, 0x6f, 0x7c, 0x6f, 0x7c, + 0x6e, 0x7b, 0x6b, 0x7c, 0x67, 0x7e, 0x61, 0x81, 0x60, 0x81, 0x60, 0x81, + 0x5f, 0x82, 0x5f, 0x82, 0x5f, 0x81, 0x5e, 0x7e, 0x5d, 0x7a, 0x5b, 0x73, + 0x5d, 0x6c, 0x5a, 0x6c, 0x54, 0x6f, 0x56, 0x6c, 0x56, 0x6e, 0x55, 0x70, + 0x54, 0x72, 0x5d, 0x79, 0x65, 0x76, 0x65, 0x71, 0x68, 0x70, 0x61, 0x71, + 0x57, 0x71, 0x5e, 0x74, 0x5e, 0x75, 0x5e, 0x76, 0x5c, 0x74, 0x5a, 0x72, + 0x5b, 0x73, 0x5c, 0x73, 0x59, 0x75, 0x57, 0x77, 0x5a, 0x77, 0x61, 0x76, + 0x64, 0x73, 0x63, 0x6c, 0x63, 0x68, 0x63, 0x65, 0x65, 0x65, 0x64, 0x66, + 0x65, 0x65, 0x67, 0x65, 0x6a, 0x66, 0x6f, 0x68, 0x73, 0x68, 0x76, 0x69, + 0x78, 0x68, 0x7d, 0x6a, 0x83, 0x6b, 0x86, 0x6d, 0x88, 0x6d, 0x89, 0x6d, + 0x8a, 0x6d, 0x89, 0x6d, 0x89, 0x6f, 0x88, 0x6e, 0x88, 0x6c, 0x88, 0x6b, + 0x84, 0x74, 0x81, 0x7c, 0x80, 0x80, 0x80, 0x81, 0x80, 0x7f, 0x80, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7d, 0x7f, 0x7e, 0x57, 0x6b, 0x4e, 0x6b, + 0x4c, 0x69, 0x53, 0x66, 0x55, 0x65, 0x56, 0x62, 0x56, 0x60, 0x56, 0x63, + 0x56, 0x65, 0x56, 0x64, 0x56, 0x61, 0x56, 0x62, 0x56, 0x61, 0x54, 0x61, + 0x53, 0x63, 0x51, 0x64, 0x50, 0x64, 0x4f, 0x64, 0x4c, 0x67, 0x4b, 0x6a, + 0x4b, 0x69, 0x4b, 0x68, 0x4b, 0x69, 0x4c, 0x67, 0x4d, 0x65, 0x4f, 0x64, + 0x4f, 0x63, 0x4f, 0x63, 0x53, 0x62, 0x57, 0x62, 0x5c, 0x65, 0x5e, 0x6d, + 0x60, 0x70, 0x63, 0x73, 0x67, 0x73, 0x6b, 0x73, 0x71, 0x73, 0x75, 0x75, + 0x7a, 0x77, 0x7b, 0x78, 0x79, 0x76, 0x72, 0x75, 0x6c, 0x75, 0x69, 0x75, + 0x6c, 0x75, 0x6b, 0x75, 0x6f, 0x74, 0x74, 0x73, 0x6e, 0x76, 0x65, 0x77, + 0x63, 0x74, 0x63, 0x73, 0x63, 0x73, 0x69, 0x72, 0x66, 0x71, 0x63, 0x76, + 0x6f, 0x77, 0x75, 0x78, 0x74, 0x7c, 0x70, 0x7e, 0x6f, 0x7e, 0x71, 0x7e, + 0x6d, 0x7b, 0x71, 0x7e, 0x6f, 0x84, 0x61, 0x7f, 0x6e, 0x7a, 0x75, 0x7a, + 0x77, 0x79, 0x77, 0x77, 0x73, 0x75, 0x70, 0x74, 0x6f, 0x75, 0x6d, 0x74, + 0x6a, 0x74, 0x69, 0x73, 0x6a, 0x78, 0x6b, 0x77, 0x6b, 0x77, 0x6d, 0x7a, + 0x6f, 0x7d, 0x71, 0x7f, 0x6e, 0x7f, 0x6b, 0x80, 0x6a, 0x81, 0x6a, 0x81, + 0x6e, 0x80, 0x70, 0x7e, 0x6e, 0x7e, 0x6d, 0x7d, 0x6b, 0x7e, 0x68, 0x7f, + 0x63, 0x81, 0x5f, 0x81, 0x61, 0x82, 0x60, 0x82, 0x60, 0x82, 0x60, 0x82, + 0x60, 0x82, 0x5e, 0x7f, 0x5e, 0x7b, 0x5d, 0x74, 0x5d, 0x6b, 0x59, 0x6a, + 0x55, 0x6d, 0x58, 0x6b, 0x57, 0x6d, 0x55, 0x6e, 0x53, 0x6e, 0x5b, 0x76, + 0x63, 0x76, 0x67, 0x71, 0x6a, 0x70, 0x63, 0x72, 0x55, 0x73, 0x5a, 0x74, + 0x5b, 0x75, 0x5b, 0x77, 0x5b, 0x76, 0x58, 0x74, 0x59, 0x74, 0x5b, 0x74, + 0x59, 0x75, 0x57, 0x77, 0x5b, 0x78, 0x62, 0x78, 0x63, 0x74, 0x62, 0x6d, + 0x62, 0x68, 0x62, 0x66, 0x63, 0x66, 0x63, 0x66, 0x63, 0x66, 0x66, 0x66, + 0x69, 0x67, 0x6d, 0x67, 0x71, 0x68, 0x73, 0x68, 0x77, 0x68, 0x7b, 0x6a, + 0x82, 0x6b, 0x85, 0x6d, 0x87, 0x6c, 0x89, 0x6c, 0x8a, 0x6c, 0x88, 0x6b, + 0x88, 0x6d, 0x88, 0x6d, 0x87, 0x6b, 0x86, 0x6a, 0x82, 0x70, 0x7f, 0x77, + 0x7e, 0x7e, 0x80, 0x80, 0x81, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7e, 0x7f, 0x7e, 0x59, 0x6c, 0x56, 0x6b, 0x50, 0x6a, 0x50, 0x68, + 0x53, 0x66, 0x56, 0x63, 0x56, 0x62, 0x56, 0x63, 0x55, 0x64, 0x56, 0x64, + 0x57, 0x62, 0x56, 0x62, 0x56, 0x62, 0x55, 0x61, 0x54, 0x62, 0x53, 0x63, + 0x51, 0x65, 0x50, 0x66, 0x4d, 0x68, 0x4c, 0x69, 0x4b, 0x68, 0x4b, 0x68, + 0x4b, 0x68, 0x4c, 0x67, 0x4d, 0x66, 0x4f, 0x63, 0x51, 0x62, 0x51, 0x61, + 0x54, 0x62, 0x57, 0x63, 0x5c, 0x67, 0x5e, 0x6f, 0x61, 0x72, 0x64, 0x73, + 0x67, 0x73, 0x6c, 0x73, 0x72, 0x74, 0x75, 0x75, 0x7a, 0x78, 0x7c, 0x78, + 0x7b, 0x77, 0x76, 0x77, 0x70, 0x77, 0x67, 0x75, 0x68, 0x74, 0x6a, 0x75, + 0x70, 0x75, 0x77, 0x75, 0x73, 0x77, 0x6a, 0x77, 0x65, 0x75, 0x64, 0x72, + 0x64, 0x72, 0x69, 0x73, 0x68, 0x72, 0x61, 0x74, 0x65, 0x77, 0x6b, 0x78, + 0x72, 0x79, 0x73, 0x79, 0x6f, 0x77, 0x71, 0x79, 0x71, 0x7c, 0x74, 0x80, + 0x66, 0x82, 0x64, 0x7d, 0x72, 0x7a, 0x77, 0x7a, 0x77, 0x78, 0x75, 0x75, + 0x72, 0x74, 0x70, 0x73, 0x6f, 0x73, 0x6f, 0x73, 0x6d, 0x73, 0x6d, 0x73, + 0x6d, 0x74, 0x6e, 0x73, 0x6c, 0x76, 0x6d, 0x79, 0x6f, 0x7c, 0x72, 0x7e, + 0x71, 0x7d, 0x6f, 0x7e, 0x6d, 0x81, 0x6c, 0x82, 0x6f, 0x81, 0x73, 0x7e, + 0x70, 0x7d, 0x6c, 0x7e, 0x6b, 0x7f, 0x66, 0x81, 0x62, 0x83, 0x5e, 0x82, + 0x5e, 0x83, 0x5f, 0x84, 0x61, 0x84, 0x63, 0x84, 0x60, 0x84, 0x5d, 0x82, + 0x5f, 0x7d, 0x5f, 0x73, 0x5f, 0x6c, 0x5c, 0x6b, 0x5b, 0x6a, 0x5b, 0x6a, + 0x5b, 0x6b, 0x57, 0x6d, 0x58, 0x6e, 0x5d, 0x73, 0x5f, 0x75, 0x64, 0x72, + 0x6b, 0x6f, 0x64, 0x6f, 0x56, 0x73, 0x57, 0x74, 0x59, 0x75, 0x59, 0x77, + 0x5a, 0x78, 0x5a, 0x78, 0x58, 0x76, 0x59, 0x77, 0x58, 0x77, 0x58, 0x77, + 0x5b, 0x78, 0x62, 0x78, 0x62, 0x76, 0x60, 0x70, 0x60, 0x6b, 0x60, 0x67, + 0x61, 0x66, 0x62, 0x66, 0x63, 0x66, 0x64, 0x66, 0x68, 0x67, 0x6d, 0x67, + 0x70, 0x67, 0x73, 0x68, 0x76, 0x68, 0x7a, 0x6a, 0x7f, 0x6a, 0x82, 0x6b, + 0x85, 0x6c, 0x87, 0x6d, 0x88, 0x6c, 0x86, 0x6c, 0x85, 0x6c, 0x84, 0x6d, + 0x82, 0x6c, 0x80, 0x6c, 0x7a, 0x6f, 0x77, 0x71, 0x77, 0x74, 0x78, 0x77, + 0x7c, 0x7b, 0x7f, 0x7e, 0x7f, 0x7e, 0x7f, 0x7f, 0x80, 0x7e, 0x7f, 0x7e, + 0x5c, 0x6d, 0x5a, 0x6b, 0x54, 0x6b, 0x4e, 0x69, 0x51, 0x66, 0x55, 0x63, + 0x56, 0x63, 0x55, 0x63, 0x55, 0x63, 0x56, 0x63, 0x56, 0x63, 0x56, 0x62, + 0x56, 0x62, 0x55, 0x62, 0x56, 0x62, 0x53, 0x64, 0x51, 0x66, 0x50, 0x68, + 0x4d, 0x67, 0x4c, 0x68, 0x4b, 0x68, 0x4b, 0x68, 0x4b, 0x68, 0x4c, 0x67, + 0x4d, 0x66, 0x4f, 0x63, 0x51, 0x62, 0x51, 0x62, 0x54, 0x63, 0x58, 0x64, + 0x5e, 0x69, 0x60, 0x70, 0x62, 0x72, 0x65, 0x72, 0x69, 0x73, 0x6e, 0x73, + 0x72, 0x75, 0x76, 0x76, 0x79, 0x78, 0x7c, 0x78, 0x7c, 0x77, 0x78, 0x78, + 0x73, 0x78, 0x68, 0x76, 0x67, 0x74, 0x69, 0x74, 0x6f, 0x75, 0x77, 0x76, + 0x77, 0x78, 0x6e, 0x77, 0x66, 0x74, 0x65, 0x72, 0x65, 0x72, 0x6a, 0x73, + 0x69, 0x72, 0x62, 0x73, 0x5f, 0x7b, 0x64, 0x7d, 0x6c, 0x78, 0x72, 0x75, + 0x72, 0x74, 0x74, 0x76, 0x74, 0x7d, 0x6a, 0x83, 0x62, 0x81, 0x6c, 0x7e, + 0x76, 0x7a, 0x76, 0x7a, 0x76, 0x78, 0x73, 0x75, 0x71, 0x74, 0x70, 0x73, + 0x70, 0x72, 0x70, 0x72, 0x6f, 0x72, 0x6f, 0x72, 0x70, 0x72, 0x70, 0x71, + 0x69, 0x78, 0x66, 0x7c, 0x69, 0x7d, 0x70, 0x7e, 0x72, 0x7d, 0x72, 0x7d, + 0x71, 0x7f, 0x6f, 0x81, 0x6f, 0x80, 0x73, 0x7e, 0x71, 0x7d, 0x6c, 0x7d, + 0x6a, 0x7f, 0x65, 0x81, 0x63, 0x82, 0x5e, 0x82, 0x5b, 0x83, 0x5d, 0x84, + 0x61, 0x85, 0x65, 0x85, 0x62, 0x83, 0x5f, 0x7f, 0x5f, 0x7c, 0x60, 0x72, + 0x5f, 0x6e, 0x5f, 0x6b, 0x5f, 0x69, 0x5e, 0x6a, 0x5f, 0x6a, 0x5d, 0x6d, + 0x5e, 0x70, 0x5e, 0x70, 0x5d, 0x72, 0x5f, 0x73, 0x6a, 0x71, 0x66, 0x70, + 0x56, 0x74, 0x56, 0x74, 0x5a, 0x75, 0x5a, 0x76, 0x5c, 0x78, 0x5e, 0x78, + 0x5c, 0x76, 0x5a, 0x77, 0x58, 0x78, 0x58, 0x78, 0x5b, 0x78, 0x62, 0x77, + 0x63, 0x78, 0x60, 0x72, 0x5f, 0x6c, 0x5f, 0x67, 0x5f, 0x65, 0x62, 0x66, + 0x63, 0x66, 0x64, 0x65, 0x68, 0x67, 0x6b, 0x68, 0x6e, 0x68, 0x72, 0x68, + 0x74, 0x69, 0x78, 0x6a, 0x7b, 0x6a, 0x7e, 0x6a, 0x81, 0x6b, 0x83, 0x6d, + 0x82, 0x6d, 0x82, 0x6d, 0x80, 0x6d, 0x7c, 0x6c, 0x7a, 0x6d, 0x78, 0x6d, + 0x74, 0x6e, 0x6f, 0x6f, 0x6e, 0x6f, 0x6f, 0x6f, 0x71, 0x72, 0x78, 0x76, + 0x7b, 0x7a, 0x7d, 0x7c, 0x7e, 0x7e, 0x7f, 0x7f, 0x5d, 0x6e, 0x5b, 0x6b, + 0x57, 0x6a, 0x4e, 0x68, 0x51, 0x66, 0x55, 0x63, 0x56, 0x62, 0x55, 0x63, + 0x55, 0x63, 0x56, 0x63, 0x55, 0x63, 0x55, 0x61, 0x55, 0x62, 0x55, 0x62, + 0x56, 0x62, 0x53, 0x64, 0x51, 0x66, 0x4f, 0x67, 0x4e, 0x67, 0x4c, 0x68, + 0x4b, 0x68, 0x4b, 0x68, 0x4b, 0x69, 0x4c, 0x68, 0x4d, 0x66, 0x4f, 0x64, + 0x50, 0x64, 0x52, 0x63, 0x54, 0x62, 0x58, 0x64, 0x5f, 0x6b, 0x62, 0x72, + 0x64, 0x72, 0x67, 0x72, 0x6a, 0x72, 0x6f, 0x72, 0x72, 0x76, 0x75, 0x76, + 0x79, 0x77, 0x7b, 0x78, 0x7c, 0x77, 0x77, 0x77, 0x73, 0x77, 0x69, 0x76, + 0x68, 0x74, 0x68, 0x74, 0x6d, 0x75, 0x75, 0x76, 0x79, 0x78, 0x71, 0x77, + 0x66, 0x74, 0x65, 0x72, 0x64, 0x72, 0x6a, 0x73, 0x69, 0x72, 0x62, 0x73, + 0x5d, 0x7a, 0x5f, 0x7d, 0x66, 0x7c, 0x6d, 0x7a, 0x73, 0x78, 0x6f, 0x7b, + 0x68, 0x80, 0x5f, 0x80, 0x61, 0x7f, 0x6f, 0x7e, 0x77, 0x7a, 0x74, 0x7a, + 0x74, 0x78, 0x72, 0x75, 0x70, 0x74, 0x70, 0x72, 0x70, 0x71, 0x70, 0x70, + 0x70, 0x70, 0x6f, 0x71, 0x71, 0x70, 0x70, 0x72, 0x65, 0x7b, 0x63, 0x7f, + 0x67, 0x7f, 0x70, 0x7e, 0x74, 0x7e, 0x75, 0x7d, 0x74, 0x7e, 0x72, 0x80, + 0x71, 0x80, 0x72, 0x7e, 0x71, 0x7d, 0x6b, 0x7d, 0x69, 0x7e, 0x63, 0x81, + 0x61, 0x82, 0x5c, 0x82, 0x5a, 0x83, 0x5b, 0x84, 0x5f, 0x84, 0x62, 0x85, + 0x61, 0x81, 0x60, 0x7c, 0x60, 0x79, 0x60, 0x72, 0x60, 0x6f, 0x60, 0x6b, + 0x60, 0x69, 0x61, 0x6a, 0x61, 0x6a, 0x5e, 0x6e, 0x5e, 0x73, 0x5e, 0x71, + 0x5e, 0x73, 0x5f, 0x76, 0x64, 0x74, 0x64, 0x72, 0x56, 0x75, 0x58, 0x75, + 0x5c, 0x76, 0x5d, 0x75, 0x5f, 0x77, 0x62, 0x77, 0x60, 0x74, 0x5b, 0x75, + 0x58, 0x78, 0x58, 0x78, 0x5b, 0x78, 0x62, 0x78, 0x64, 0x79, 0x61, 0x73, + 0x5f, 0x6c, 0x5f, 0x66, 0x60, 0x65, 0x62, 0x66, 0x63, 0x65, 0x65, 0x65, + 0x67, 0x67, 0x6a, 0x68, 0x6c, 0x68, 0x70, 0x69, 0x73, 0x68, 0x75, 0x6a, + 0x78, 0x6a, 0x7b, 0x6a, 0x7e, 0x6b, 0x7e, 0x6c, 0x7e, 0x6d, 0x7d, 0x6d, + 0x7b, 0x6d, 0x77, 0x6c, 0x74, 0x6d, 0x73, 0x6c, 0x6e, 0x6d, 0x69, 0x6e, + 0x67, 0x6e, 0x68, 0x6e, 0x69, 0x70, 0x6e, 0x71, 0x72, 0x74, 0x77, 0x77, + 0x7c, 0x7a, 0x7f, 0x7e, 0x60, 0x6e, 0x5c, 0x6b, 0x58, 0x6a, 0x4f, 0x69, + 0x50, 0x67, 0x55, 0x64, 0x56, 0x63, 0x56, 0x62, 0x55, 0x62, 0x55, 0x63, + 0x55, 0x63, 0x56, 0x62, 0x55, 0x62, 0x55, 0x62, 0x55, 0x63, 0x53, 0x62, + 0x52, 0x64, 0x50, 0x66, 0x4f, 0x66, 0x4e, 0x68, 0x4c, 0x69, 0x4b, 0x68, + 0x4c, 0x68, 0x4c, 0x67, 0x4e, 0x65, 0x50, 0x64, 0x50, 0x64, 0x52, 0x62, + 0x55, 0x62, 0x59, 0x64, 0x60, 0x6d, 0x62, 0x73, 0x64, 0x74, 0x67, 0x74, + 0x6b, 0x74, 0x70, 0x74, 0x73, 0x75, 0x76, 0x75, 0x79, 0x78, 0x7b, 0x78, + 0x7b, 0x78, 0x79, 0x79, 0x74, 0x79, 0x6b, 0x77, 0x69, 0x75, 0x67, 0x74, + 0x6a, 0x74, 0x73, 0x76, 0x7a, 0x78, 0x73, 0x77, 0x66, 0x75, 0x66, 0x71, + 0x67, 0x71, 0x6a, 0x73, 0x6a, 0x73, 0x62, 0x72, 0x5f, 0x74, 0x5d, 0x77, + 0x5e, 0x7f, 0x64, 0x81, 0x61, 0x7f, 0x60, 0x7f, 0x5f, 0x80, 0x5b, 0x7b, + 0x63, 0x7a, 0x6a, 0x7a, 0x71, 0x78, 0x71, 0x78, 0x73, 0x77, 0x72, 0x76, + 0x71, 0x72, 0x6f, 0x71, 0x70, 0x71, 0x71, 0x71, 0x71, 0x70, 0x6f, 0x70, + 0x70, 0x6f, 0x6f, 0x73, 0x68, 0x7b, 0x68, 0x7d, 0x6c, 0x7d, 0x74, 0x7c, + 0x77, 0x7d, 0x78, 0x7c, 0x77, 0x7c, 0x76, 0x7e, 0x74, 0x80, 0x72, 0x7f, + 0x6f, 0x7d, 0x6a, 0x7f, 0x68, 0x81, 0x63, 0x82, 0x5f, 0x82, 0x5b, 0x82, + 0x5a, 0x82, 0x5b, 0x83, 0x5c, 0x84, 0x5e, 0x81, 0x60, 0x7c, 0x63, 0x7a, + 0x62, 0x75, 0x61, 0x72, 0x61, 0x6f, 0x62, 0x6c, 0x62, 0x69, 0x64, 0x69, + 0x62, 0x6b, 0x5c, 0x71, 0x5d, 0x76, 0x5f, 0x76, 0x5f, 0x76, 0x5f, 0x78, + 0x5f, 0x76, 0x61, 0x74, 0x59, 0x77, 0x59, 0x76, 0x5a, 0x75, 0x5d, 0x73, + 0x61, 0x74, 0x65, 0x76, 0x62, 0x73, 0x5c, 0x74, 0x58, 0x77, 0x59, 0x78, + 0x5d, 0x78, 0x63, 0x78, 0x64, 0x7a, 0x63, 0x76, 0x60, 0x6e, 0x5f, 0x69, + 0x61, 0x66, 0x63, 0x66, 0x64, 0x66, 0x64, 0x66, 0x66, 0x66, 0x68, 0x67, + 0x6b, 0x67, 0x6f, 0x68, 0x71, 0x68, 0x72, 0x6a, 0x75, 0x6a, 0x78, 0x6a, + 0x79, 0x6b, 0x7a, 0x6b, 0x7a, 0x6b, 0x78, 0x6c, 0x76, 0x6c, 0x72, 0x6c, + 0x70, 0x6c, 0x6d, 0x6b, 0x68, 0x6b, 0x64, 0x6c, 0x60, 0x6b, 0x60, 0x6c, + 0x62, 0x6e, 0x64, 0x6e, 0x67, 0x6c, 0x6e, 0x6e, 0x75, 0x70, 0x7a, 0x78, + 0x60, 0x6e, 0x5b, 0x6b, 0x58, 0x6a, 0x50, 0x6a, 0x51, 0x68, 0x55, 0x65, + 0x56, 0x63, 0x55, 0x63, 0x55, 0x63, 0x55, 0x63, 0x55, 0x64, 0x56, 0x64, + 0x55, 0x62, 0x55, 0x63, 0x54, 0x63, 0x53, 0x60, 0x53, 0x62, 0x51, 0x65, + 0x50, 0x65, 0x4f, 0x67, 0x4c, 0x68, 0x4c, 0x67, 0x4c, 0x67, 0x4d, 0x67, + 0x4f, 0x65, 0x50, 0x64, 0x50, 0x63, 0x53, 0x62, 0x56, 0x63, 0x5a, 0x65, + 0x5f, 0x6e, 0x62, 0x74, 0x64, 0x74, 0x67, 0x75, 0x6a, 0x75, 0x70, 0x75, + 0x74, 0x74, 0x76, 0x76, 0x7a, 0x78, 0x7b, 0x78, 0x7b, 0x7a, 0x7a, 0x7a, + 0x75, 0x7a, 0x6c, 0x78, 0x68, 0x77, 0x67, 0x75, 0x69, 0x73, 0x71, 0x76, + 0x78, 0x78, 0x71, 0x77, 0x67, 0x74, 0x68, 0x70, 0x68, 0x70, 0x6b, 0x72, + 0x6a, 0x73, 0x62, 0x72, 0x61, 0x73, 0x5e, 0x76, 0x5d, 0x7c, 0x64, 0x80, + 0x5e, 0x7f, 0x5f, 0x7d, 0x5f, 0x7c, 0x5d, 0x7a, 0x64, 0x79, 0x67, 0x79, + 0x6b, 0x77, 0x6d, 0x77, 0x72, 0x75, 0x73, 0x74, 0x71, 0x71, 0x6e, 0x70, + 0x6d, 0x71, 0x6f, 0x72, 0x71, 0x71, 0x6f, 0x70, 0x6e, 0x70, 0x6e, 0x74, + 0x6d, 0x79, 0x70, 0x7a, 0x74, 0x7a, 0x78, 0x7b, 0x78, 0x7c, 0x78, 0x7c, + 0x78, 0x7c, 0x78, 0x7d, 0x75, 0x7f, 0x72, 0x7f, 0x6e, 0x7e, 0x69, 0x82, + 0x67, 0x83, 0x63, 0x83, 0x5e, 0x82, 0x5c, 0x82, 0x5a, 0x81, 0x5c, 0x83, + 0x5c, 0x83, 0x5e, 0x7d, 0x61, 0x7a, 0x64, 0x7a, 0x62, 0x75, 0x60, 0x71, + 0x63, 0x70, 0x65, 0x6e, 0x64, 0x6a, 0x65, 0x69, 0x62, 0x6c, 0x5c, 0x73, + 0x5d, 0x77, 0x5f, 0x76, 0x5f, 0x76, 0x60, 0x7a, 0x5f, 0x77, 0x60, 0x75, + 0x5b, 0x78, 0x57, 0x77, 0x58, 0x73, 0x5b, 0x71, 0x5e, 0x71, 0x64, 0x73, + 0x64, 0x73, 0x5f, 0x73, 0x58, 0x76, 0x59, 0x78, 0x5d, 0x78, 0x63, 0x78, + 0x64, 0x7a, 0x63, 0x78, 0x61, 0x6f, 0x61, 0x6a, 0x62, 0x68, 0x64, 0x67, + 0x65, 0x68, 0x65, 0x67, 0x65, 0x67, 0x68, 0x68, 0x6a, 0x68, 0x6d, 0x69, + 0x6f, 0x69, 0x70, 0x6a, 0x73, 0x6a, 0x76, 0x6a, 0x76, 0x6a, 0x77, 0x6a, + 0x77, 0x6a, 0x75, 0x6a, 0x72, 0x6a, 0x6f, 0x6b, 0x6d, 0x6a, 0x68, 0x6a, + 0x64, 0x6b, 0x61, 0x6b, 0x5d, 0x6b, 0x5c, 0x6b, 0x5d, 0x6c, 0x5e, 0x6c, + 0x60, 0x6b, 0x68, 0x6b, 0x6e, 0x6d, 0x73, 0x6f, 0x60, 0x6d, 0x5b, 0x6a, + 0x58, 0x6a, 0x51, 0x6a, 0x52, 0x68, 0x55, 0x65, 0x55, 0x65, 0x55, 0x65, + 0x55, 0x65, 0x55, 0x65, 0x55, 0x65, 0x55, 0x64, 0x55, 0x62, 0x54, 0x63, + 0x54, 0x63, 0x54, 0x60, 0x53, 0x61, 0x51, 0x65, 0x50, 0x65, 0x4f, 0x65, + 0x4d, 0x66, 0x4c, 0x67, 0x4c, 0x67, 0x4e, 0x67, 0x4f, 0x64, 0x50, 0x63, + 0x52, 0x64, 0x54, 0x62, 0x58, 0x65, 0x5b, 0x67, 0x5f, 0x70, 0x62, 0x75, + 0x64, 0x75, 0x67, 0x75, 0x6a, 0x75, 0x70, 0x74, 0x74, 0x73, 0x76, 0x76, + 0x7a, 0x78, 0x7b, 0x78, 0x7b, 0x79, 0x79, 0x7a, 0x74, 0x7b, 0x6c, 0x7a, + 0x68, 0x79, 0x67, 0x77, 0x68, 0x75, 0x6f, 0x76, 0x76, 0x78, 0x70, 0x77, + 0x68, 0x74, 0x68, 0x70, 0x68, 0x71, 0x6a, 0x72, 0x6b, 0x73, 0x64, 0x72, + 0x63, 0x73, 0x61, 0x75, 0x5f, 0x7b, 0x64, 0x7e, 0x5e, 0x7d, 0x5e, 0x7b, + 0x5e, 0x7b, 0x5e, 0x78, 0x63, 0x77, 0x67, 0x77, 0x6c, 0x77, 0x6e, 0x77, + 0x72, 0x74, 0x73, 0x73, 0x73, 0x71, 0x70, 0x70, 0x6d, 0x72, 0x70, 0x72, + 0x71, 0x71, 0x6f, 0x70, 0x6e, 0x71, 0x70, 0x74, 0x72, 0x77, 0x74, 0x78, + 0x76, 0x78, 0x78, 0x7b, 0x77, 0x7c, 0x78, 0x7c, 0x78, 0x7d, 0x78, 0x7d, + 0x74, 0x7e, 0x72, 0x7e, 0x6e, 0x80, 0x68, 0x83, 0x65, 0x83, 0x62, 0x82, + 0x5e, 0x82, 0x5b, 0x81, 0x5a, 0x81, 0x5c, 0x83, 0x5d, 0x82, 0x5e, 0x7c, + 0x61, 0x7b, 0x61, 0x7d, 0x5f, 0x78, 0x5e, 0x73, 0x61, 0x72, 0x65, 0x72, + 0x64, 0x6d, 0x65, 0x6a, 0x61, 0x6e, 0x5b, 0x73, 0x5b, 0x76, 0x5f, 0x75, + 0x5a, 0x78, 0x5e, 0x7b, 0x63, 0x79, 0x62, 0x78, 0x5d, 0x79, 0x58, 0x7a, + 0x56, 0x77, 0x56, 0x74, 0x58, 0x72, 0x5f, 0x71, 0x61, 0x73, 0x5f, 0x73, + 0x56, 0x76, 0x58, 0x78, 0x5d, 0x78, 0x5f, 0x78, 0x63, 0x7a, 0x63, 0x77, + 0x62, 0x70, 0x63, 0x6a, 0x63, 0x69, 0x65, 0x69, 0x67, 0x69, 0x66, 0x69, + 0x66, 0x69, 0x68, 0x69, 0x6a, 0x6a, 0x6b, 0x6a, 0x6d, 0x6a, 0x6f, 0x6a, + 0x72, 0x6a, 0x73, 0x6a, 0x73, 0x6a, 0x72, 0x6a, 0x72, 0x6b, 0x70, 0x69, + 0x6e, 0x68, 0x6b, 0x69, 0x68, 0x68, 0x64, 0x6a, 0x5f, 0x6b, 0x5c, 0x6b, + 0x57, 0x6a, 0x56, 0x6b, 0x57, 0x6c, 0x59, 0x6d, 0x5b, 0x6e, 0x5f, 0x6d, + 0x64, 0x6d, 0x69, 0x6c, 0x5d, 0x6c, 0x5b, 0x6a, 0x56, 0x6a, 0x52, 0x6a, + 0x54, 0x67, 0x55, 0x65, 0x56, 0x65, 0x55, 0x66, 0x54, 0x66, 0x55, 0x66, + 0x55, 0x65, 0x55, 0x63, 0x55, 0x63, 0x54, 0x64, 0x54, 0x64, 0x53, 0x63, + 0x53, 0x62, 0x51, 0x64, 0x50, 0x64, 0x4f, 0x65, 0x4d, 0x65, 0x4c, 0x66, + 0x4d, 0x66, 0x4e, 0x67, 0x4f, 0x65, 0x51, 0x63, 0x53, 0x63, 0x54, 0x63, + 0x58, 0x66, 0x5c, 0x68, 0x5f, 0x71, 0x63, 0x76, 0x65, 0x74, 0x67, 0x74, + 0x6a, 0x74, 0x6f, 0x75, 0x74, 0x76, 0x76, 0x77, 0x7a, 0x78, 0x7a, 0x78, + 0x7b, 0x79, 0x79, 0x7a, 0x74, 0x7b, 0x6c, 0x7b, 0x69, 0x7a, 0x68, 0x78, + 0x67, 0x76, 0x6c, 0x76, 0x73, 0x78, 0x6e, 0x77, 0x69, 0x74, 0x69, 0x70, + 0x68, 0x70, 0x69, 0x72, 0x69, 0x73, 0x63, 0x72, 0x64, 0x73, 0x65, 0x73, + 0x61, 0x78, 0x5e, 0x7c, 0x5b, 0x7b, 0x5c, 0x7a, 0x5f, 0x79, 0x61, 0x77, + 0x65, 0x77, 0x69, 0x78, 0x70, 0x78, 0x71, 0x78, 0x73, 0x74, 0x73, 0x72, + 0x73, 0x71, 0x72, 0x70, 0x70, 0x71, 0x71, 0x71, 0x70, 0x71, 0x6e, 0x71, + 0x6e, 0x71, 0x72, 0x74, 0x75, 0x76, 0x76, 0x78, 0x76, 0x78, 0x77, 0x7a, + 0x77, 0x7b, 0x77, 0x7b, 0x78, 0x7c, 0x77, 0x7b, 0x75, 0x7c, 0x73, 0x7c, + 0x6f, 0x80, 0x68, 0x83, 0x64, 0x83, 0x60, 0x83, 0x5e, 0x83, 0x5c, 0x83, + 0x5b, 0x83, 0x5b, 0x84, 0x5b, 0x82, 0x5e, 0x7b, 0x61, 0x7a, 0x5e, 0x7c, + 0x5b, 0x79, 0x5d, 0x78, 0x60, 0x75, 0x60, 0x74, 0x60, 0x73, 0x61, 0x70, + 0x5f, 0x70, 0x58, 0x72, 0x58, 0x77, 0x61, 0x77, 0x5b, 0x7c, 0x59, 0x7f, + 0x69, 0x7a, 0x66, 0x77, 0x5f, 0x7b, 0x56, 0x7d, 0x53, 0x7d, 0x53, 0x7a, + 0x56, 0x77, 0x5a, 0x74, 0x5c, 0x73, 0x5a, 0x74, 0x54, 0x77, 0x55, 0x78, + 0x5c, 0x79, 0x5e, 0x78, 0x60, 0x7b, 0x62, 0x78, 0x63, 0x6e, 0x64, 0x6a, + 0x66, 0x6a, 0x66, 0x6a, 0x67, 0x6a, 0x67, 0x6a, 0x68, 0x6a, 0x69, 0x6a, + 0x69, 0x6a, 0x69, 0x6a, 0x6a, 0x6a, 0x6d, 0x6a, 0x6e, 0x6a, 0x6f, 0x6a, + 0x6f, 0x6a, 0x6e, 0x69, 0x6c, 0x69, 0x69, 0x68, 0x67, 0x68, 0x64, 0x68, + 0x62, 0x68, 0x5f, 0x69, 0x5b, 0x6a, 0x58, 0x6a, 0x53, 0x6a, 0x53, 0x6b, + 0x54, 0x6d, 0x55, 0x6d, 0x56, 0x6e, 0x58, 0x6d, 0x5b, 0x6d, 0x60, 0x70, + 0x5c, 0x6c, 0x59, 0x6c, 0x54, 0x6b, 0x54, 0x69, 0x55, 0x67, 0x55, 0x66, + 0x55, 0x65, 0x54, 0x65, 0x53, 0x66, 0x54, 0x66, 0x54, 0x65, 0x54, 0x64, + 0x54, 0x65, 0x54, 0x65, 0x54, 0x65, 0x53, 0x65, 0x53, 0x63, 0x50, 0x64, + 0x50, 0x64, 0x4f, 0x64, 0x4d, 0x65, 0x4d, 0x66, 0x4d, 0x65, 0x4e, 0x66, + 0x50, 0x66, 0x52, 0x62, 0x53, 0x63, 0x53, 0x65, 0x58, 0x66, 0x5c, 0x69, + 0x5f, 0x70, 0x64, 0x75, 0x64, 0x73, 0x67, 0x73, 0x6a, 0x74, 0x6f, 0x76, + 0x75, 0x78, 0x77, 0x78, 0x79, 0x78, 0x7a, 0x78, 0x7a, 0x79, 0x78, 0x7a, + 0x74, 0x7a, 0x6e, 0x7b, 0x69, 0x7a, 0x67, 0x78, 0x65, 0x78, 0x69, 0x77, + 0x71, 0x77, 0x6d, 0x77, 0x69, 0x74, 0x6b, 0x6f, 0x69, 0x6e, 0x69, 0x71, + 0x69, 0x71, 0x63, 0x72, 0x63, 0x72, 0x64, 0x72, 0x62, 0x76, 0x5e, 0x7a, + 0x5c, 0x7b, 0x5d, 0x79, 0x60, 0x78, 0x62, 0x78, 0x67, 0x78, 0x6c, 0x78, + 0x72, 0x78, 0x72, 0x78, 0x73, 0x75, 0x73, 0x74, 0x73, 0x72, 0x72, 0x72, + 0x70, 0x72, 0x70, 0x71, 0x6f, 0x71, 0x6d, 0x72, 0x6e, 0x72, 0x72, 0x74, + 0x76, 0x76, 0x77, 0x78, 0x77, 0x78, 0x77, 0x79, 0x77, 0x7a, 0x77, 0x7a, + 0x77, 0x7b, 0x76, 0x7b, 0x74, 0x7b, 0x75, 0x7b, 0x73, 0x7e, 0x6a, 0x84, + 0x64, 0x84, 0x5f, 0x84, 0x5e, 0x85, 0x5c, 0x84, 0x5b, 0x84, 0x5b, 0x84, + 0x59, 0x84, 0x5d, 0x7c, 0x61, 0x79, 0x5e, 0x79, 0x5b, 0x7a, 0x5d, 0x7a, + 0x60, 0x77, 0x60, 0x76, 0x5d, 0x78, 0x5d, 0x75, 0x5d, 0x73, 0x54, 0x77, + 0x52, 0x7b, 0x5e, 0x7d, 0x5c, 0x80, 0x59, 0x81, 0x68, 0x79, 0x66, 0x78, + 0x5f, 0x7f, 0x53, 0x7e, 0x4f, 0x7e, 0x54, 0x7d, 0x55, 0x7a, 0x59, 0x77, + 0x5b, 0x75, 0x59, 0x75, 0x55, 0x77, 0x55, 0x79, 0x5b, 0x7b, 0x5d, 0x7a, + 0x5f, 0x7b, 0x61, 0x77, 0x63, 0x6d, 0x65, 0x6a, 0x67, 0x6a, 0x67, 0x6a, + 0x68, 0x6b, 0x68, 0x6b, 0x69, 0x6b, 0x6a, 0x6b, 0x69, 0x6a, 0x68, 0x69, + 0x69, 0x6a, 0x6b, 0x6b, 0x6b, 0x6b, 0x6c, 0x6a, 0x6c, 0x6a, 0x6b, 0x68, + 0x68, 0x68, 0x66, 0x69, 0x64, 0x68, 0x61, 0x68, 0x5e, 0x68, 0x5c, 0x69, + 0x59, 0x6a, 0x56, 0x6a, 0x53, 0x6b, 0x53, 0x6b, 0x52, 0x6c, 0x52, 0x6d, + 0x55, 0x6f, 0x56, 0x6e, 0x58, 0x6c, 0x5d, 0x6e, 0x5b, 0x6d, 0x57, 0x69, + 0x57, 0x67, 0x57, 0x68, 0x56, 0x66, 0x55, 0x66, 0x54, 0x65, 0x54, 0x65, + 0x54, 0x65, 0x54, 0x65, 0x54, 0x66, 0x54, 0x66, 0x54, 0x66, 0x54, 0x65, + 0x54, 0x65, 0x53, 0x65, 0x52, 0x62, 0x50, 0x64, 0x50, 0x64, 0x4f, 0x65, + 0x4d, 0x66, 0x4d, 0x66, 0x4d, 0x66, 0x4e, 0x66, 0x50, 0x66, 0x52, 0x63, + 0x54, 0x63, 0x53, 0x65, 0x58, 0x67, 0x5b, 0x69, 0x5f, 0x6e, 0x64, 0x73, + 0x65, 0x73, 0x67, 0x72, 0x6a, 0x73, 0x6f, 0x76, 0x75, 0x78, 0x76, 0x78, + 0x79, 0x78, 0x7a, 0x77, 0x7a, 0x79, 0x77, 0x7a, 0x76, 0x7a, 0x71, 0x79, + 0x6c, 0x78, 0x68, 0x78, 0x66, 0x78, 0x68, 0x77, 0x6c, 0x77, 0x69, 0x77, + 0x68, 0x74, 0x6b, 0x71, 0x6c, 0x71, 0x68, 0x70, 0x64, 0x70, 0x63, 0x71, + 0x64, 0x72, 0x64, 0x72, 0x62, 0x76, 0x5f, 0x7b, 0x5e, 0x7b, 0x5f, 0x79, + 0x60, 0x78, 0x64, 0x78, 0x6b, 0x78, 0x6f, 0x78, 0x73, 0x78, 0x73, 0x78, + 0x73, 0x77, 0x73, 0x75, 0x72, 0x74, 0x72, 0x74, 0x72, 0x73, 0x73, 0x74, + 0x71, 0x73, 0x6f, 0x74, 0x6d, 0x74, 0x72, 0x76, 0x78, 0x78, 0x77, 0x78, + 0x77, 0x78, 0x77, 0x79, 0x77, 0x7a, 0x77, 0x7b, 0x77, 0x7b, 0x76, 0x7b, + 0x75, 0x7b, 0x75, 0x7a, 0x77, 0x7e, 0x6d, 0x84, 0x65, 0x86, 0x5f, 0x86, + 0x5e, 0x86, 0x5b, 0x86, 0x5b, 0x86, 0x5b, 0x86, 0x58, 0x85, 0x5b, 0x7e, + 0x61, 0x7a, 0x60, 0x7a, 0x5d, 0x7a, 0x60, 0x7a, 0x60, 0x79, 0x5d, 0x7a, + 0x5c, 0x7c, 0x5c, 0x7b, 0x5a, 0x79, 0x51, 0x7d, 0x50, 0x7e, 0x57, 0x83, + 0x5b, 0x82, 0x61, 0x7c, 0x64, 0x79, 0x65, 0x7c, 0x5e, 0x81, 0x50, 0x7e, + 0x4c, 0x7d, 0x51, 0x7e, 0x53, 0x7c, 0x57, 0x7a, 0x5a, 0x79, 0x5d, 0x79, + 0x5b, 0x79, 0x59, 0x7c, 0x5a, 0x7c, 0x5d, 0x79, 0x5f, 0x79, 0x62, 0x76, + 0x64, 0x6d, 0x67, 0x6a, 0x69, 0x6d, 0x69, 0x6d, 0x6a, 0x6d, 0x6a, 0x6d, + 0x6a, 0x6d, 0x6a, 0x6d, 0x69, 0x6c, 0x68, 0x6b, 0x69, 0x6b, 0x69, 0x6b, + 0x69, 0x6b, 0x68, 0x6a, 0x69, 0x6a, 0x67, 0x68, 0x65, 0x68, 0x62, 0x68, + 0x60, 0x68, 0x5d, 0x68, 0x5b, 0x69, 0x58, 0x69, 0x55, 0x6a, 0x53, 0x6a, + 0x53, 0x6a, 0x52, 0x6a, 0x51, 0x6a, 0x52, 0x6b, 0x55, 0x6e, 0x57, 0x6d, + 0x58, 0x6a, 0x59, 0x6c, 0x5a, 0x69, 0x5b, 0x64, 0x5b, 0x64, 0x58, 0x67, + 0x56, 0x66, 0x55, 0x65, 0x54, 0x66, 0x54, 0x66, 0x54, 0x66, 0x54, 0x66, + 0x54, 0x66, 0x54, 0x67, 0x54, 0x67, 0x54, 0x64, 0x54, 0x64, 0x53, 0x65, + 0x53, 0x63, 0x51, 0x65, 0x50, 0x65, 0x4f, 0x65, 0x4d, 0x66, 0x4e, 0x66, + 0x4e, 0x66, 0x4f, 0x66, 0x51, 0x66, 0x53, 0x63, 0x54, 0x62, 0x54, 0x65, + 0x58, 0x67, 0x5b, 0x69, 0x5e, 0x6d, 0x64, 0x72, 0x64, 0x73, 0x67, 0x73, + 0x69, 0x74, 0x6e, 0x76, 0x74, 0x78, 0x76, 0x78, 0x79, 0x78, 0x7a, 0x78, + 0x7a, 0x79, 0x77, 0x79, 0x76, 0x79, 0x74, 0x78, 0x70, 0x78, 0x6e, 0x78, + 0x6b, 0x77, 0x6a, 0x77, 0x6a, 0x77, 0x67, 0x77, 0x67, 0x75, 0x6b, 0x72, + 0x6d, 0x72, 0x63, 0x6f, 0x5c, 0x6f, 0x61, 0x71, 0x64, 0x72, 0x64, 0x72, + 0x62, 0x76, 0x60, 0x7a, 0x5f, 0x7b, 0x5f, 0x7a, 0x60, 0x78, 0x65, 0x78, + 0x6e, 0x78, 0x72, 0x78, 0x75, 0x78, 0x75, 0x78, 0x73, 0x78, 0x73, 0x77, + 0x72, 0x76, 0x73, 0x75, 0x74, 0x75, 0x74, 0x75, 0x73, 0x75, 0x71, 0x75, + 0x6d, 0x76, 0x73, 0x78, 0x79, 0x78, 0x77, 0x78, 0x77, 0x78, 0x77, 0x79, + 0x77, 0x7a, 0x77, 0x7a, 0x77, 0x7b, 0x76, 0x7b, 0x75, 0x7a, 0x75, 0x7b, + 0x75, 0x7e, 0x6a, 0x84, 0x64, 0x87, 0x5f, 0x87, 0x5e, 0x87, 0x5d, 0x87, + 0x5c, 0x87, 0x5c, 0x88, 0x57, 0x87, 0x5a, 0x7f, 0x5e, 0x7b, 0x5c, 0x7a, + 0x5d, 0x7a, 0x61, 0x7a, 0x60, 0x7c, 0x5c, 0x7d, 0x5b, 0x7f, 0x5c, 0x7e, + 0x5a, 0x7d, 0x54, 0x7d, 0x54, 0x7c, 0x57, 0x83, 0x61, 0x7f, 0x67, 0x78, + 0x63, 0x79, 0x66, 0x7c, 0x5d, 0x7e, 0x4e, 0x7c, 0x4a, 0x7d, 0x4f, 0x7d, + 0x52, 0x7d, 0x55, 0x7c, 0x59, 0x7c, 0x5f, 0x7c, 0x5e, 0x7b, 0x5d, 0x7d, + 0x5b, 0x7c, 0x5c, 0x79, 0x5f, 0x78, 0x62, 0x75, 0x66, 0x6c, 0x68, 0x69, + 0x6b, 0x6e, 0x6b, 0x6e, 0x6b, 0x6e, 0x6c, 0x6e, 0x6b, 0x6e, 0x6a, 0x6e, + 0x6a, 0x6e, 0x69, 0x6d, 0x68, 0x6d, 0x67, 0x6c, 0x67, 0x6b, 0x66, 0x6a, + 0x65, 0x6a, 0x64, 0x69, 0x61, 0x68, 0x5f, 0x68, 0x5d, 0x69, 0x5a, 0x69, + 0x58, 0x68, 0x56, 0x6a, 0x53, 0x6b, 0x52, 0x6a, 0x53, 0x6a, 0x54, 0x6a, + 0x54, 0x69, 0x54, 0x6a, 0x55, 0x6a, 0x58, 0x6a, 0x58, 0x6a, 0x58, 0x6c, + 0x5e, 0x66, 0x5d, 0x66, 0x5b, 0x64, 0x58, 0x67, 0x56, 0x66, 0x55, 0x65, + 0x54, 0x67, 0x54, 0x68, 0x54, 0x68, 0x54, 0x67, 0x54, 0x66, 0x54, 0x65, + 0x54, 0x66, 0x53, 0x66, 0x53, 0x65, 0x53, 0x65, 0x53, 0x65, 0x51, 0x65, + 0x51, 0x64, 0x4f, 0x63, 0x4e, 0x65, 0x4e, 0x66, 0x4e, 0x66, 0x4f, 0x66, + 0x51, 0x64, 0x54, 0x62, 0x54, 0x64, 0x55, 0x66, 0x59, 0x67, 0x5b, 0x68, + 0x5e, 0x6d, 0x62, 0x72, 0x63, 0x73, 0x66, 0x74, 0x6a, 0x75, 0x6c, 0x75, + 0x72, 0x77, 0x73, 0x77, 0x77, 0x77, 0x7a, 0x78, 0x79, 0x78, 0x77, 0x78, + 0x77, 0x78, 0x78, 0x78, 0x72, 0x78, 0x6f, 0x77, 0x6d, 0x77, 0x6f, 0x78, + 0x6e, 0x78, 0x6c, 0x78, 0x6a, 0x78, 0x69, 0x75, 0x6a, 0x73, 0x5d, 0x70, + 0x56, 0x72, 0x5e, 0x73, 0x61, 0x74, 0x62, 0x74, 0x61, 0x77, 0x60, 0x79, + 0x5e, 0x7a, 0x5c, 0x7b, 0x5e, 0x7a, 0x65, 0x79, 0x6d, 0x7b, 0x71, 0x7a, + 0x73, 0x78, 0x73, 0x78, 0x73, 0x78, 0x73, 0x78, 0x72, 0x78, 0x74, 0x77, + 0x75, 0x78, 0x75, 0x78, 0x75, 0x77, 0x75, 0x77, 0x73, 0x79, 0x78, 0x7a, + 0x78, 0x79, 0x77, 0x79, 0x77, 0x7a, 0x76, 0x7a, 0x77, 0x7a, 0x78, 0x7a, + 0x77, 0x7b, 0x75, 0x7a, 0x74, 0x7a, 0x74, 0x7c, 0x73, 0x7f, 0x68, 0x85, + 0x62, 0x88, 0x5f, 0x88, 0x60, 0x88, 0x5f, 0x88, 0x5e, 0x88, 0x5e, 0x88, + 0x59, 0x87, 0x58, 0x7f, 0x5c, 0x7c, 0x5d, 0x7c, 0x5f, 0x7d, 0x60, 0x7d, + 0x60, 0x7d, 0x5b, 0x7e, 0x5a, 0x7e, 0x5d, 0x7f, 0x5a, 0x7e, 0x57, 0x7e, + 0x5a, 0x7f, 0x64, 0x7d, 0x71, 0x78, 0x6e, 0x79, 0x6a, 0x7c, 0x6d, 0x7e, + 0x5c, 0x7c, 0x50, 0x7b, 0x4d, 0x7b, 0x53, 0x79, 0x53, 0x79, 0x54, 0x7b, + 0x58, 0x7c, 0x5d, 0x7d, 0x60, 0x7c, 0x61, 0x7c, 0x60, 0x7c, 0x60, 0x7a, + 0x60, 0x77, 0x63, 0x73, 0x67, 0x6c, 0x69, 0x6a, 0x6b, 0x6e, 0x6b, 0x6e, + 0x6b, 0x6f, 0x6b, 0x6f, 0x6b, 0x6f, 0x6b, 0x6f, 0x6a, 0x6f, 0x67, 0x6e, + 0x66, 0x6d, 0x65, 0x6c, 0x63, 0x6c, 0x63, 0x6b, 0x60, 0x6a, 0x60, 0x6a, + 0x5d, 0x6a, 0x5c, 0x69, 0x5a, 0x6a, 0x57, 0x6a, 0x56, 0x69, 0x56, 0x6a, + 0x54, 0x6b, 0x54, 0x6b, 0x55, 0x6a, 0x55, 0x6a, 0x55, 0x6b, 0x55, 0x6b, + 0x56, 0x6a, 0x56, 0x6b, 0x58, 0x6c, 0x5a, 0x6c, 0x60, 0x62, 0x5e, 0x62, + 0x5b, 0x63, 0x58, 0x65, 0x55, 0x65, 0x55, 0x66, 0x54, 0x66, 0x54, 0x66, + 0x54, 0x66, 0x54, 0x65, 0x54, 0x65, 0x54, 0x65, 0x53, 0x66, 0x53, 0x67, + 0x53, 0x65, 0x53, 0x65, 0x53, 0x65, 0x51, 0x65, 0x51, 0x64, 0x50, 0x63, + 0x4e, 0x65, 0x4e, 0x64, 0x4f, 0x63, 0x51, 0x64, 0x53, 0x62, 0x55, 0x62, + 0x53, 0x64, 0x55, 0x67, 0x5a, 0x68, 0x5b, 0x68, 0x5e, 0x6b, 0x62, 0x70, + 0x63, 0x73, 0x66, 0x74, 0x68, 0x75, 0x6a, 0x75, 0x70, 0x77, 0x72, 0x77, + 0x76, 0x78, 0x79, 0x78, 0x78, 0x78, 0x77, 0x78, 0x77, 0x79, 0x77, 0x7a, + 0x6d, 0x7a, 0x68, 0x78, 0x6b, 0x78, 0x6e, 0x78, 0x72, 0x78, 0x73, 0x78, + 0x73, 0x78, 0x6e, 0x79, 0x6b, 0x77, 0x5f, 0x72, 0x58, 0x77, 0x5b, 0x77, + 0x5f, 0x76, 0x5f, 0x76, 0x5f, 0x79, 0x5f, 0x7b, 0x5e, 0x7c, 0x5b, 0x7d, + 0x5c, 0x7c, 0x63, 0x7a, 0x69, 0x7b, 0x6d, 0x7b, 0x71, 0x7a, 0x71, 0x7a, + 0x71, 0x7a, 0x71, 0x7a, 0x70, 0x7a, 0x72, 0x7a, 0x74, 0x7b, 0x73, 0x7c, + 0x74, 0x7b, 0x75, 0x7a, 0x76, 0x7b, 0x7b, 0x7c, 0x78, 0x7c, 0x77, 0x7b, + 0x77, 0x7b, 0x76, 0x7b, 0x77, 0x7a, 0x79, 0x7a, 0x77, 0x7b, 0x74, 0x7b, + 0x73, 0x7c, 0x73, 0x7e, 0x6d, 0x81, 0x64, 0x87, 0x62, 0x88, 0x5f, 0x88, + 0x60, 0x86, 0x5f, 0x86, 0x5f, 0x86, 0x60, 0x86, 0x5d, 0x87, 0x59, 0x83, + 0x5a, 0x7f, 0x60, 0x7e, 0x60, 0x7e, 0x5f, 0x7e, 0x5e, 0x7e, 0x59, 0x7e, + 0x58, 0x7d, 0x5c, 0x7d, 0x5b, 0x7d, 0x61, 0x7e, 0x68, 0x7b, 0x73, 0x73, + 0x79, 0x75, 0x75, 0x7c, 0x70, 0x7e, 0x6e, 0x7c, 0x5b, 0x77, 0x51, 0x78, + 0x53, 0x77, 0x57, 0x74, 0x57, 0x75, 0x56, 0x78, 0x58, 0x7a, 0x5b, 0x7c, + 0x60, 0x7e, 0x62, 0x7e, 0x63, 0x7c, 0x63, 0x7a, 0x5f, 0x77, 0x61, 0x73, + 0x66, 0x6f, 0x68, 0x6d, 0x69, 0x6d, 0x6a, 0x6e, 0x69, 0x6f, 0x69, 0x6f, + 0x6a, 0x6f, 0x69, 0x6f, 0x69, 0x6f, 0x65, 0x6e, 0x64, 0x6d, 0x64, 0x6c, + 0x61, 0x6c, 0x5f, 0x6b, 0x5c, 0x6a, 0x5c, 0x6a, 0x59, 0x6a, 0x58, 0x6a, + 0x56, 0x69, 0x54, 0x6b, 0x54, 0x6b, 0x54, 0x6b, 0x55, 0x6b, 0x55, 0x6b, + 0x55, 0x6b, 0x55, 0x6b, 0x57, 0x6b, 0x56, 0x6a, 0x55, 0x6a, 0x56, 0x6b, + 0x58, 0x6b, 0x5b, 0x6a, 0x61, 0x5f, 0x5e, 0x5f, 0x5b, 0x62, 0x58, 0x63, + 0x56, 0x65, 0x55, 0x65, 0x55, 0x65, 0x55, 0x65, 0x55, 0x64, 0x55, 0x64, + 0x54, 0x64, 0x54, 0x65, 0x54, 0x66, 0x53, 0x66, 0x53, 0x65, 0x53, 0x65, + 0x53, 0x65, 0x51, 0x64, 0x51, 0x64, 0x50, 0x63, 0x4f, 0x64, 0x4e, 0x63, + 0x50, 0x62, 0x52, 0x63, 0x53, 0x62, 0x55, 0x61, 0x53, 0x65, 0x55, 0x67, + 0x5a, 0x67, 0x5c, 0x67, 0x5e, 0x6b, 0x62, 0x70, 0x63, 0x73, 0x66, 0x74, + 0x66, 0x75, 0x69, 0x75, 0x6e, 0x77, 0x71, 0x77, 0x74, 0x78, 0x77, 0x78, + 0x77, 0x78, 0x77, 0x78, 0x77, 0x7a, 0x71, 0x7b, 0x66, 0x7b, 0x63, 0x7a, + 0x67, 0x79, 0x69, 0x78, 0x6f, 0x78, 0x72, 0x77, 0x76, 0x78, 0x76, 0x7b, + 0x72, 0x79, 0x66, 0x77, 0x5e, 0x78, 0x5b, 0x77, 0x5f, 0x77, 0x5f, 0x77, + 0x5d, 0x7a, 0x5e, 0x7d, 0x5e, 0x7e, 0x5b, 0x7e, 0x5b, 0x7d, 0x61, 0x7b, + 0x67, 0x7b, 0x6b, 0x7b, 0x70, 0x7b, 0x70, 0x7c, 0x70, 0x7b, 0x6f, 0x7b, + 0x6f, 0x7b, 0x71, 0x7c, 0x73, 0x7d, 0x73, 0x7e, 0x75, 0x7d, 0x75, 0x7c, + 0x75, 0x7d, 0x78, 0x7e, 0x76, 0x7d, 0x77, 0x7c, 0x78, 0x7c, 0x76, 0x7b, + 0x77, 0x7a, 0x79, 0x7a, 0x77, 0x7a, 0x74, 0x7b, 0x72, 0x7e, 0x71, 0x80, + 0x68, 0x82, 0x62, 0x87, 0x62, 0x88, 0x5f, 0x88, 0x5f, 0x85, 0x5f, 0x85, + 0x60, 0x85, 0x60, 0x85, 0x5f, 0x86, 0x59, 0x85, 0x58, 0x81, 0x5e, 0x7f, + 0x5f, 0x7e, 0x5d, 0x7d, 0x5c, 0x7d, 0x58, 0x7e, 0x59, 0x7d, 0x60, 0x7c, + 0x60, 0x7c, 0x69, 0x79, 0x71, 0x75, 0x74, 0x75, 0x75, 0x7a, 0x75, 0x7d, + 0x70, 0x7a, 0x6b, 0x78, 0x5a, 0x75, 0x52, 0x76, 0x58, 0x75, 0x59, 0x72, + 0x5a, 0x73, 0x59, 0x76, 0x58, 0x78, 0x58, 0x7b, 0x5c, 0x7f, 0x5e, 0x7f, + 0x60, 0x7c, 0x60, 0x79, 0x5e, 0x7a, 0x60, 0x78, 0x65, 0x72, 0x66, 0x70, + 0x68, 0x6e, 0x68, 0x6e, 0x67, 0x6f, 0x68, 0x6f, 0x68, 0x6f, 0x68, 0x6f, + 0x68, 0x6e, 0x64, 0x6e, 0x63, 0x6d, 0x63, 0x6c, 0x5f, 0x6c, 0x5d, 0x6b, + 0x5a, 0x6a, 0x59, 0x6a, 0x56, 0x6a, 0x55, 0x6a, 0x53, 0x6a, 0x53, 0x6c, + 0x53, 0x6c, 0x54, 0x6b, 0x55, 0x6b, 0x56, 0x6c, 0x55, 0x6d, 0x56, 0x6c, + 0x58, 0x6b, 0x57, 0x6b, 0x56, 0x6b, 0x56, 0x6a, 0x58, 0x6a, 0x5a, 0x6a, + 0x62, 0x5d, 0x5e, 0x5f, 0x5b, 0x63, 0x58, 0x63, 0x56, 0x65, 0x56, 0x65, + 0x56, 0x65, 0x55, 0x65, 0x55, 0x65, 0x55, 0x65, 0x55, 0x65, 0x54, 0x66, + 0x54, 0x66, 0x53, 0x65, 0x53, 0x65, 0x51, 0x65, 0x51, 0x65, 0x51, 0x64, + 0x51, 0x62, 0x51, 0x63, 0x50, 0x64, 0x4f, 0x63, 0x51, 0x63, 0x53, 0x62, + 0x54, 0x61, 0x55, 0x63, 0x54, 0x66, 0x56, 0x67, 0x5a, 0x68, 0x5c, 0x68, + 0x5e, 0x6c, 0x61, 0x71, 0x63, 0x72, 0x66, 0x74, 0x67, 0x75, 0x69, 0x76, + 0x6e, 0x77, 0x72, 0x78, 0x73, 0x79, 0x75, 0x79, 0x76, 0x79, 0x76, 0x78, + 0x76, 0x79, 0x6e, 0x7a, 0x66, 0x7a, 0x61, 0x7b, 0x60, 0x7b, 0x62, 0x7b, + 0x68, 0x78, 0x6d, 0x78, 0x73, 0x78, 0x7a, 0x7b, 0x7c, 0x7b, 0x74, 0x7c, + 0x6b, 0x7a, 0x60, 0x78, 0x5c, 0x7b, 0x5d, 0x7b, 0x5c, 0x7c, 0x5b, 0x7f, + 0x5b, 0x80, 0x5a, 0x80, 0x5b, 0x81, 0x5f, 0x7e, 0x65, 0x7b, 0x69, 0x7d, + 0x6e, 0x7c, 0x6f, 0x7c, 0x6e, 0x7b, 0x6a, 0x7b, 0x69, 0x7c, 0x6c, 0x7c, + 0x6f, 0x7c, 0x71, 0x7e, 0x71, 0x7f, 0x72, 0x7e, 0x73, 0x7f, 0x71, 0x7f, + 0x6f, 0x7e, 0x71, 0x7d, 0x72, 0x7d, 0x71, 0x7c, 0x72, 0x7c, 0x74, 0x7c, + 0x71, 0x7c, 0x6f, 0x7d, 0x6c, 0x82, 0x68, 0x84, 0x63, 0x86, 0x62, 0x87, + 0x61, 0x87, 0x60, 0x87, 0x5f, 0x85, 0x5f, 0x85, 0x5f, 0x84, 0x5f, 0x84, + 0x60, 0x85, 0x5a, 0x85, 0x58, 0x84, 0x5a, 0x7f, 0x5c, 0x7c, 0x5c, 0x7c, + 0x5c, 0x7c, 0x5b, 0x7c, 0x5d, 0x7c, 0x67, 0x7c, 0x6c, 0x7c, 0x71, 0x78, + 0x74, 0x78, 0x76, 0x7b, 0x79, 0x77, 0x77, 0x77, 0x6d, 0x74, 0x65, 0x74, + 0x57, 0x77, 0x56, 0x74, 0x5a, 0x74, 0x5b, 0x73, 0x5a, 0x74, 0x5a, 0x76, + 0x58, 0x77, 0x56, 0x7a, 0x57, 0x7d, 0x59, 0x7c, 0x5c, 0x7d, 0x5e, 0x7c, + 0x5d, 0x7e, 0x5e, 0x82, 0x62, 0x7b, 0x65, 0x76, 0x66, 0x72, 0x64, 0x73, + 0x62, 0x72, 0x64, 0x70, 0x66, 0x6f, 0x66, 0x6e, 0x66, 0x6e, 0x63, 0x6d, + 0x61, 0x6d, 0x5f, 0x6c, 0x5d, 0x6c, 0x5b, 0x6c, 0x56, 0x69, 0x55, 0x6b, + 0x53, 0x6b, 0x52, 0x6b, 0x52, 0x6b, 0x52, 0x6c, 0x52, 0x6c, 0x53, 0x6d, + 0x54, 0x6c, 0x54, 0x6d, 0x54, 0x6d, 0x54, 0x6d, 0x55, 0x6c, 0x56, 0x6c, + 0x57, 0x6b, 0x57, 0x6a, 0x57, 0x6a, 0x58, 0x6a, 0x63, 0x5b, 0x5e, 0x5e, + 0x5b, 0x63, 0x59, 0x63, 0x57, 0x64, 0x55, 0x65, 0x55, 0x65, 0x55, 0x65, + 0x55, 0x65, 0x55, 0x65, 0x54, 0x65, 0x54, 0x66, 0x53, 0x66, 0x53, 0x65, + 0x52, 0x65, 0x51, 0x65, 0x51, 0x65, 0x51, 0x64, 0x51, 0x62, 0x51, 0x62, + 0x50, 0x63, 0x4f, 0x64, 0x51, 0x64, 0x54, 0x62, 0x54, 0x61, 0x55, 0x63, + 0x53, 0x66, 0x55, 0x67, 0x58, 0x68, 0x5b, 0x68, 0x5d, 0x6b, 0x5f, 0x70, + 0x62, 0x72, 0x65, 0x74, 0x66, 0x75, 0x68, 0x76, 0x6c, 0x77, 0x70, 0x78, + 0x73, 0x7a, 0x75, 0x7a, 0x76, 0x79, 0x74, 0x78, 0x73, 0x79, 0x70, 0x79, + 0x6e, 0x79, 0x69, 0x77, 0x60, 0x78, 0x5e, 0x79, 0x64, 0x79, 0x68, 0x79, + 0x6f, 0x79, 0x74, 0x7b, 0x7b, 0x7b, 0x7f, 0x7b, 0x79, 0x7b, 0x67, 0x7a, + 0x57, 0x7c, 0x58, 0x7d, 0x5a, 0x7f, 0x59, 0x81, 0x59, 0x81, 0x59, 0x82, + 0x59, 0x83, 0x5d, 0x80, 0x63, 0x7d, 0x66, 0x7f, 0x69, 0x7d, 0x6b, 0x7d, + 0x69, 0x7d, 0x66, 0x7d, 0x65, 0x7e, 0x65, 0x7e, 0x66, 0x7d, 0x68, 0x7f, + 0x6a, 0x80, 0x6e, 0x80, 0x6f, 0x80, 0x6a, 0x80, 0x67, 0x7f, 0x68, 0x7f, + 0x69, 0x7f, 0x6b, 0x7e, 0x6c, 0x7f, 0x6a, 0x80, 0x66, 0x81, 0x65, 0x81, + 0x64, 0x85, 0x62, 0x87, 0x62, 0x87, 0x62, 0x87, 0x61, 0x87, 0x60, 0x87, + 0x60, 0x85, 0x60, 0x85, 0x60, 0x84, 0x60, 0x84, 0x60, 0x85, 0x5c, 0x85, + 0x59, 0x85, 0x5b, 0x7f, 0x5d, 0x7b, 0x5d, 0x7b, 0x5e, 0x79, 0x60, 0x77, + 0x65, 0x7b, 0x70, 0x7c, 0x72, 0x7d, 0x75, 0x7e, 0x76, 0x7c, 0x79, 0x75, + 0x78, 0x75, 0x73, 0x74, 0x6c, 0x72, 0x62, 0x75, 0x54, 0x79, 0x57, 0x75, + 0x5a, 0x75, 0x5b, 0x75, 0x5a, 0x76, 0x59, 0x77, 0x57, 0x78, 0x55, 0x7b, + 0x57, 0x7c, 0x59, 0x7c, 0x59, 0x7d, 0x5b, 0x80, 0x5c, 0x83, 0x5c, 0x88, + 0x5c, 0x84, 0x61, 0x7f, 0x60, 0x79, 0x5f, 0x78, 0x60, 0x75, 0x62, 0x74, + 0x64, 0x72, 0x63, 0x6f, 0x64, 0x6e, 0x63, 0x6e, 0x61, 0x6f, 0x5e, 0x6f, + 0x5c, 0x6f, 0x5a, 0x6d, 0x55, 0x6a, 0x53, 0x6a, 0x51, 0x6b, 0x51, 0x6b, + 0x51, 0x6b, 0x50, 0x6c, 0x50, 0x6d, 0x52, 0x6d, 0x52, 0x6d, 0x53, 0x6d, + 0x53, 0x6d, 0x53, 0x6d, 0x55, 0x6c, 0x55, 0x6c, 0x56, 0x6a, 0x56, 0x6a, + 0x55, 0x6b, 0x56, 0x6b, 0x63, 0x5a, 0x5f, 0x5c, 0x5c, 0x62, 0x59, 0x63, + 0x57, 0x64, 0x55, 0x65, 0x55, 0x65, 0x55, 0x65, 0x55, 0x65, 0x55, 0x65, + 0x54, 0x65, 0x54, 0x65, 0x53, 0x65, 0x53, 0x65, 0x52, 0x65, 0x51, 0x65, + 0x51, 0x65, 0x51, 0x64, 0x51, 0x62, 0x51, 0x62, 0x50, 0x63, 0x50, 0x63, + 0x51, 0x63, 0x54, 0x62, 0x55, 0x62, 0x53, 0x63, 0x53, 0x65, 0x54, 0x67, + 0x56, 0x67, 0x58, 0x68, 0x5b, 0x69, 0x5e, 0x6e, 0x61, 0x72, 0x63, 0x74, + 0x64, 0x75, 0x67, 0x75, 0x6b, 0x77, 0x6e, 0x78, 0x73, 0x7a, 0x75, 0x7a, + 0x76, 0x79, 0x72, 0x78, 0x6d, 0x78, 0x6c, 0x7a, 0x6f, 0x79, 0x70, 0x78, + 0x6b, 0x78, 0x66, 0x78, 0x60, 0x7b, 0x63, 0x7b, 0x6a, 0x7b, 0x70, 0x7b, + 0x74, 0x7b, 0x7a, 0x7a, 0x7c, 0x7c, 0x74, 0x7c, 0x5f, 0x7e, 0x58, 0x80, + 0x59, 0x82, 0x57, 0x83, 0x57, 0x83, 0x57, 0x83, 0x57, 0x84, 0x5b, 0x82, + 0x60, 0x81, 0x63, 0x82, 0x65, 0x7f, 0x67, 0x7e, 0x64, 0x80, 0x62, 0x80, + 0x65, 0x7f, 0x63, 0x7f, 0x62, 0x7e, 0x65, 0x80, 0x65, 0x81, 0x69, 0x81, + 0x6f, 0x81, 0x69, 0x81, 0x64, 0x81, 0x65, 0x80, 0x66, 0x80, 0x67, 0x80, + 0x65, 0x81, 0x63, 0x83, 0x61, 0x86, 0x60, 0x86, 0x61, 0x88, 0x62, 0x89, + 0x62, 0x87, 0x62, 0x87, 0x61, 0x87, 0x61, 0x87, 0x62, 0x85, 0x61, 0x85, + 0x62, 0x84, 0x62, 0x84, 0x62, 0x85, 0x5d, 0x85, 0x5b, 0x84, 0x5d, 0x7f, + 0x5f, 0x7a, 0x5f, 0x79, 0x62, 0x78, 0x66, 0x79, 0x6c, 0x7d, 0x72, 0x7c, + 0x74, 0x7c, 0x78, 0x78, 0x79, 0x74, 0x77, 0x70, 0x70, 0x70, 0x6e, 0x6f, + 0x69, 0x71, 0x60, 0x76, 0x58, 0x7a, 0x59, 0x77, 0x5a, 0x77, 0x5b, 0x76, + 0x5a, 0x77, 0x59, 0x7a, 0x55, 0x7a, 0x55, 0x7c, 0x58, 0x7c, 0x5a, 0x7c, + 0x5c, 0x7e, 0x5f, 0x83, 0x5f, 0x87, 0x60, 0x8d, 0x5e, 0x8d, 0x5a, 0x88, + 0x59, 0x80, 0x5b, 0x7c, 0x5e, 0x78, 0x60, 0x77, 0x61, 0x74, 0x60, 0x71, + 0x62, 0x70, 0x63, 0x70, 0x61, 0x70, 0x5e, 0x72, 0x5c, 0x71, 0x59, 0x6f, + 0x54, 0x6c, 0x52, 0x6b, 0x4f, 0x6b, 0x4f, 0x6b, 0x50, 0x6a, 0x4f, 0x6b, + 0x50, 0x6c, 0x50, 0x6c, 0x50, 0x6d, 0x51, 0x6d, 0x54, 0x6d, 0x54, 0x6c, + 0x55, 0x6c, 0x55, 0x6b, 0x55, 0x6a, 0x55, 0x6b, 0x55, 0x6b, 0x54, 0x6b, + 0x63, 0x5d, 0x5f, 0x5e, 0x5d, 0x61, 0x59, 0x64, 0x57, 0x65, 0x55, 0x65, + 0x55, 0x64, 0x56, 0x63, 0x56, 0x62, 0x55, 0x63, 0x54, 0x65, 0x54, 0x65, + 0x53, 0x65, 0x52, 0x65, 0x52, 0x65, 0x51, 0x66, 0x51, 0x66, 0x51, 0x64, + 0x51, 0x63, 0x50, 0x63, 0x51, 0x63, 0x51, 0x62, 0x52, 0x62, 0x55, 0x61, + 0x55, 0x62, 0x53, 0x64, 0x52, 0x65, 0x53, 0x65, 0x54, 0x65, 0x54, 0x67, + 0x58, 0x68, 0x5e, 0x6d, 0x61, 0x73, 0x63, 0x75, 0x64, 0x75, 0x67, 0x75, + 0x6a, 0x77, 0x6c, 0x78, 0x71, 0x7a, 0x73, 0x7a, 0x73, 0x78, 0x6f, 0x78, + 0x6b, 0x79, 0x6a, 0x79, 0x6e, 0x7a, 0x71, 0x7b, 0x71, 0x7a, 0x6e, 0x79, + 0x65, 0x7b, 0x60, 0x7d, 0x64, 0x7e, 0x6e, 0x7d, 0x73, 0x7b, 0x71, 0x7b, + 0x71, 0x7d, 0x77, 0x7d, 0x71, 0x7d, 0x62, 0x81, 0x63, 0x8a, 0x69, 0x89, + 0x61, 0x86, 0x58, 0x88, 0x57, 0x89, 0x55, 0x88, 0x5c, 0x85, 0x63, 0x85, + 0x68, 0x84, 0x69, 0x7e, 0x67, 0x7f, 0x65, 0x82, 0x68, 0x7f, 0x67, 0x7c, + 0x67, 0x7d, 0x68, 0x7e, 0x68, 0x7f, 0x69, 0x7f, 0x6d, 0x7f, 0x6d, 0x7f, + 0x69, 0x7f, 0x66, 0x7f, 0x64, 0x7e, 0x63, 0x81, 0x61, 0x83, 0x5f, 0x86, + 0x5f, 0x89, 0x5f, 0x89, 0x60, 0x89, 0x63, 0x89, 0x65, 0x86, 0x62, 0x86, + 0x62, 0x87, 0x65, 0x87, 0x66, 0x86, 0x66, 0x86, 0x64, 0x85, 0x64, 0x85, + 0x63, 0x86, 0x60, 0x84, 0x5d, 0x81, 0x5f, 0x7c, 0x61, 0x7a, 0x64, 0x7b, + 0x68, 0x7e, 0x6b, 0x80, 0x71, 0x7d, 0x75, 0x79, 0x78, 0x75, 0x78, 0x70, + 0x75, 0x6e, 0x6f, 0x6f, 0x6a, 0x70, 0x67, 0x71, 0x62, 0x73, 0x5e, 0x77, + 0x5a, 0x7a, 0x56, 0x7a, 0x56, 0x79, 0x59, 0x76, 0x59, 0x76, 0x57, 0x79, + 0x53, 0x7b, 0x54, 0x7d, 0x5a, 0x7d, 0x5b, 0x7c, 0x5e, 0x7f, 0x62, 0x85, + 0x64, 0x8a, 0x68, 0x8e, 0x66, 0x90, 0x58, 0x8d, 0x55, 0x84, 0x5a, 0x7f, + 0x5d, 0x78, 0x5e, 0x77, 0x5d, 0x77, 0x5d, 0x73, 0x62, 0x73, 0x63, 0x75, + 0x61, 0x75, 0x60, 0x76, 0x5e, 0x75, 0x5a, 0x72, 0x56, 0x70, 0x53, 0x70, + 0x51, 0x6e, 0x4c, 0x6d, 0x4c, 0x6c, 0x4c, 0x6b, 0x4d, 0x6b, 0x4e, 0x6b, + 0x50, 0x6b, 0x51, 0x6b, 0x53, 0x6b, 0x55, 0x6c, 0x54, 0x6d, 0x54, 0x6c, + 0x54, 0x6c, 0x54, 0x6c, 0x54, 0x6d, 0x54, 0x6c, 0x62, 0x5e, 0x5e, 0x60, + 0x5d, 0x61, 0x59, 0x64, 0x57, 0x65, 0x55, 0x65, 0x55, 0x64, 0x56, 0x63, + 0x56, 0x61, 0x56, 0x62, 0x54, 0x65, 0x53, 0x65, 0x53, 0x65, 0x52, 0x65, + 0x52, 0x65, 0x51, 0x65, 0x51, 0x65, 0x51, 0x63, 0x51, 0x63, 0x50, 0x63, + 0x51, 0x64, 0x51, 0x62, 0x53, 0x62, 0x55, 0x61, 0x55, 0x61, 0x53, 0x65, + 0x52, 0x66, 0x52, 0x65, 0x53, 0x65, 0x53, 0x67, 0x56, 0x67, 0x5d, 0x6d, + 0x60, 0x72, 0x63, 0x75, 0x64, 0x75, 0x66, 0x75, 0x69, 0x77, 0x6b, 0x77, + 0x6f, 0x78, 0x70, 0x79, 0x70, 0x77, 0x6e, 0x79, 0x6c, 0x7a, 0x6b, 0x7a, + 0x6e, 0x7b, 0x70, 0x7c, 0x6f, 0x7b, 0x70, 0x7a, 0x6b, 0x7a, 0x62, 0x7a, + 0x5f, 0x80, 0x68, 0x7e, 0x73, 0x7c, 0x73, 0x7c, 0x6c, 0x7d, 0x70, 0x7d, + 0x7a, 0x7d, 0x71, 0x7f, 0x68, 0x88, 0x76, 0x8a, 0x74, 0x87, 0x6a, 0x8b, + 0x65, 0x8e, 0x5c, 0x8e, 0x5d, 0x8c, 0x62, 0x8c, 0x6a, 0x88, 0x6a, 0x82, + 0x6b, 0x81, 0x68, 0x83, 0x66, 0x80, 0x69, 0x7b, 0x69, 0x7c, 0x69, 0x7d, + 0x6a, 0x7e, 0x6a, 0x7f, 0x6b, 0x7d, 0x6b, 0x7c, 0x68, 0x7c, 0x64, 0x7c, + 0x64, 0x7c, 0x64, 0x7f, 0x63, 0x82, 0x61, 0x86, 0x61, 0x87, 0x61, 0x87, + 0x62, 0x87, 0x65, 0x87, 0x66, 0x85, 0x63, 0x85, 0x64, 0x86, 0x66, 0x86, + 0x68, 0x86, 0x68, 0x86, 0x66, 0x85, 0x66, 0x85, 0x65, 0x85, 0x62, 0x82, + 0x61, 0x80, 0x63, 0x7e, 0x65, 0x7f, 0x6a, 0x80, 0x70, 0x7e, 0x72, 0x7c, + 0x74, 0x78, 0x76, 0x74, 0x77, 0x71, 0x74, 0x70, 0x70, 0x6f, 0x6b, 0x6f, + 0x67, 0x71, 0x65, 0x72, 0x61, 0x74, 0x60, 0x77, 0x58, 0x7b, 0x51, 0x7d, + 0x54, 0x7a, 0x5c, 0x76, 0x59, 0x76, 0x54, 0x79, 0x54, 0x7b, 0x54, 0x7d, + 0x59, 0x7c, 0x5b, 0x7c, 0x5f, 0x7f, 0x65, 0x83, 0x67, 0x88, 0x6a, 0x8c, + 0x69, 0x8d, 0x58, 0x8d, 0x54, 0x85, 0x58, 0x7f, 0x5d, 0x79, 0x5e, 0x78, + 0x5c, 0x78, 0x5a, 0x77, 0x5e, 0x77, 0x63, 0x79, 0x64, 0x7b, 0x61, 0x7d, + 0x60, 0x7c, 0x5d, 0x79, 0x5a, 0x77, 0x59, 0x76, 0x57, 0x74, 0x50, 0x71, + 0x4d, 0x6f, 0x4c, 0x6c, 0x4b, 0x6c, 0x4c, 0x6b, 0x4f, 0x6b, 0x50, 0x6b, + 0x51, 0x6b, 0x54, 0x6b, 0x53, 0x6d, 0x53, 0x6c, 0x54, 0x6d, 0x54, 0x6d, + 0x54, 0x6d, 0x54, 0x6c, 0x63, 0x60, 0x5f, 0x61, 0x5d, 0x61, 0x59, 0x64, + 0x58, 0x65, 0x56, 0x65, 0x56, 0x64, 0x57, 0x63, 0x56, 0x62, 0x56, 0x63, + 0x54, 0x65, 0x53, 0x65, 0x53, 0x65, 0x53, 0x65, 0x53, 0x65, 0x52, 0x63, + 0x51, 0x63, 0x51, 0x63, 0x51, 0x63, 0x50, 0x63, 0x51, 0x63, 0x51, 0x62, + 0x54, 0x62, 0x54, 0x61, 0x54, 0x61, 0x53, 0x65, 0x53, 0x66, 0x53, 0x65, + 0x53, 0x66, 0x53, 0x67, 0x55, 0x64, 0x5b, 0x6b, 0x60, 0x73, 0x63, 0x75, + 0x62, 0x75, 0x64, 0x75, 0x67, 0x77, 0x69, 0x77, 0x6c, 0x77, 0x6c, 0x77, + 0x6b, 0x77, 0x6d, 0x78, 0x6c, 0x7a, 0x6b, 0x7a, 0x6d, 0x7a, 0x6e, 0x7b, + 0x6c, 0x7b, 0x6d, 0x7c, 0x6c, 0x7b, 0x66, 0x79, 0x61, 0x7c, 0x5d, 0x80, + 0x68, 0x7e, 0x74, 0x7c, 0x73, 0x7c, 0x6c, 0x7d, 0x71, 0x7d, 0x76, 0x7d, + 0x72, 0x80, 0x6a, 0x87, 0x71, 0x8b, 0x7b, 0x89, 0x7c, 0x89, 0x78, 0x8a, + 0x72, 0x8b, 0x70, 0x8a, 0x71, 0x87, 0x71, 0x85, 0x71, 0x85, 0x6e, 0x88, + 0x6d, 0x86, 0x6d, 0x82, 0x70, 0x83, 0x70, 0x82, 0x6f, 0x82, 0x6e, 0x81, + 0x6c, 0x80, 0x6c, 0x80, 0x6d, 0x7f, 0x6b, 0x7d, 0x69, 0x7d, 0x66, 0x7e, + 0x67, 0x80, 0x66, 0x83, 0x63, 0x85, 0x64, 0x85, 0x66, 0x85, 0x69, 0x85, + 0x68, 0x83, 0x65, 0x83, 0x66, 0x84, 0x68, 0x84, 0x6c, 0x84, 0x6c, 0x84, + 0x6a, 0x83, 0x6a, 0x82, 0x69, 0x83, 0x66, 0x81, 0x66, 0x80, 0x68, 0x83, + 0x6e, 0x82, 0x74, 0x7c, 0x79, 0x76, 0x78, 0x73, 0x76, 0x72, 0x78, 0x74, + 0x75, 0x72, 0x6e, 0x6e, 0x6b, 0x6f, 0x69, 0x6f, 0x65, 0x71, 0x63, 0x72, + 0x62, 0x74, 0x60, 0x76, 0x56, 0x7d, 0x55, 0x80, 0x58, 0x7a, 0x5c, 0x74, + 0x59, 0x76, 0x54, 0x79, 0x54, 0x7b, 0x55, 0x7d, 0x57, 0x7c, 0x5c, 0x7c, + 0x69, 0x77, 0x73, 0x77, 0x72, 0x79, 0x6f, 0x7c, 0x6a, 0x80, 0x5a, 0x88, + 0x53, 0x85, 0x56, 0x7f, 0x5c, 0x7a, 0x5e, 0x7b, 0x5c, 0x7b, 0x55, 0x7e, + 0x58, 0x80, 0x62, 0x85, 0x6b, 0x8a, 0x6b, 0x89, 0x6a, 0x88, 0x68, 0x85, + 0x65, 0x82, 0x63, 0x7f, 0x61, 0x7e, 0x5b, 0x7a, 0x56, 0x74, 0x4d, 0x6e, + 0x48, 0x6e, 0x48, 0x6c, 0x4d, 0x6b, 0x4e, 0x6b, 0x4f, 0x6b, 0x51, 0x6b, + 0x50, 0x6c, 0x51, 0x6d, 0x52, 0x6d, 0x52, 0x6d, 0x52, 0x6c, 0x52, 0x6c, + 0x64, 0x61, 0x60, 0x61, 0x5d, 0x62, 0x59, 0x64, 0x58, 0x63, 0x57, 0x63, + 0x57, 0x63, 0x57, 0x62, 0x56, 0x61, 0x56, 0x62, 0x56, 0x62, 0x55, 0x64, + 0x53, 0x65, 0x53, 0x64, 0x53, 0x64, 0x51, 0x62, 0x51, 0x63, 0x51, 0x63, + 0x50, 0x63, 0x50, 0x63, 0x51, 0x63, 0x51, 0x61, 0x54, 0x60, 0x54, 0x60, + 0x53, 0x61, 0x53, 0x65, 0x53, 0x65, 0x53, 0x64, 0x54, 0x64, 0x54, 0x64, + 0x55, 0x63, 0x58, 0x67, 0x60, 0x72, 0x63, 0x77, 0x62, 0x76, 0x63, 0x75, + 0x67, 0x77, 0x69, 0x78, 0x68, 0x77, 0x6a, 0x76, 0x67, 0x76, 0x6a, 0x79, + 0x6a, 0x7a, 0x6c, 0x7a, 0x6d, 0x7a, 0x6e, 0x7a, 0x6b, 0x7b, 0x69, 0x7c, + 0x67, 0x7c, 0x69, 0x7b, 0x66, 0x7a, 0x5b, 0x7f, 0x5d, 0x82, 0x70, 0x7f, + 0x79, 0x7c, 0x71, 0x7d, 0x65, 0x7f, 0x6a, 0x7e, 0x76, 0x7e, 0x6e, 0x84, + 0x65, 0x8c, 0x71, 0x8a, 0x7d, 0x86, 0x7f, 0x86, 0x7f, 0x86, 0x7e, 0x85, + 0x7e, 0x85, 0x80, 0x83, 0x7e, 0x85, 0x7e, 0x86, 0x7f, 0x84, 0x7e, 0x86, + 0x7b, 0x86, 0x7a, 0x87, 0x79, 0x8a, 0x75, 0x8c, 0x73, 0x8b, 0x78, 0x8a, + 0x7c, 0x88, 0x7a, 0x84, 0x76, 0x84, 0x6e, 0x82, 0x6a, 0x80, 0x67, 0x81, + 0x64, 0x83, 0x65, 0x84, 0x6a, 0x83, 0x6d, 0x84, 0x6b, 0x82, 0x69, 0x82, + 0x69, 0x84, 0x6a, 0x84, 0x6e, 0x81, 0x6f, 0x82, 0x6d, 0x80, 0x6d, 0x80, + 0x6b, 0x81, 0x68, 0x82, 0x68, 0x84, 0x6d, 0x85, 0x75, 0x7d, 0x79, 0x74, + 0x78, 0x70, 0x72, 0x71, 0x75, 0x74, 0x78, 0x76, 0x72, 0x70, 0x6c, 0x6d, + 0x69, 0x6f, 0x67, 0x6f, 0x65, 0x71, 0x63, 0x71, 0x65, 0x73, 0x5f, 0x75, + 0x58, 0x7f, 0x5c, 0x83, 0x5d, 0x7a, 0x5b, 0x75, 0x57, 0x77, 0x54, 0x79, + 0x54, 0x7b, 0x56, 0x7e, 0x57, 0x7f, 0x5f, 0x7c, 0x70, 0x70, 0x7a, 0x6a, + 0x79, 0x6a, 0x77, 0x6c, 0x73, 0x72, 0x64, 0x7e, 0x56, 0x84, 0x57, 0x81, + 0x5b, 0x7d, 0x5b, 0x7e, 0x5b, 0x7f, 0x54, 0x81, 0x54, 0x84, 0x62, 0x8d, + 0x6c, 0x92, 0x70, 0x91, 0x72, 0x8e, 0x71, 0x8d, 0x70, 0x89, 0x6b, 0x86, + 0x6a, 0x86, 0x67, 0x82, 0x5f, 0x79, 0x51, 0x70, 0x48, 0x6d, 0x49, 0x6c, + 0x4c, 0x6d, 0x4b, 0x6d, 0x4c, 0x6c, 0x4c, 0x6c, 0x4e, 0x6d, 0x4e, 0x6d, + 0x4f, 0x6e, 0x4e, 0x6e, 0x4f, 0x6b, 0x50, 0x6c, 0x63, 0x60, 0x60, 0x60, + 0x5d, 0x62, 0x59, 0x64, 0x58, 0x63, 0x56, 0x63, 0x56, 0x63, 0x56, 0x61, + 0x56, 0x60, 0x56, 0x61, 0x56, 0x60, 0x56, 0x62, 0x54, 0x64, 0x53, 0x63, + 0x53, 0x63, 0x51, 0x63, 0x51, 0x63, 0x51, 0x63, 0x50, 0x63, 0x50, 0x63, + 0x51, 0x63, 0x52, 0x61, 0x53, 0x60, 0x54, 0x60, 0x53, 0x61, 0x52, 0x64, + 0x52, 0x64, 0x52, 0x64, 0x54, 0x63, 0x53, 0x63, 0x53, 0x63, 0x56, 0x66, + 0x5f, 0x70, 0x63, 0x76, 0x63, 0x75, 0x63, 0x75, 0x67, 0x77, 0x68, 0x78, + 0x66, 0x76, 0x68, 0x75, 0x65, 0x77, 0x67, 0x7b, 0x69, 0x7c, 0x6c, 0x7b, + 0x6d, 0x7b, 0x70, 0x7b, 0x6d, 0x7c, 0x68, 0x7d, 0x65, 0x7c, 0x69, 0x7b, + 0x67, 0x7b, 0x66, 0x7a, 0x5d, 0x7d, 0x66, 0x81, 0x73, 0x80, 0x76, 0x7f, + 0x6b, 0x7f, 0x65, 0x80, 0x6e, 0x81, 0x70, 0x83, 0x60, 0x8d, 0x63, 0x91, + 0x71, 0x8d, 0x7a, 0x86, 0x7a, 0x87, 0x7a, 0x87, 0x7d, 0x84, 0x80, 0x82, + 0x80, 0x82, 0x80, 0x81, 0x80, 0x81, 0x80, 0x83, 0x7f, 0x81, 0x7e, 0x82, + 0x7e, 0x86, 0x7c, 0x88, 0x76, 0x8a, 0x78, 0x8a, 0x7b, 0x89, 0x7c, 0x89, + 0x7d, 0x89, 0x7a, 0x89, 0x75, 0x87, 0x6f, 0x85, 0x69, 0x85, 0x69, 0x84, + 0x6d, 0x82, 0x6e, 0x82, 0x6c, 0x83, 0x69, 0x83, 0x69, 0x84, 0x69, 0x84, + 0x6a, 0x84, 0x6c, 0x83, 0x6c, 0x82, 0x6c, 0x82, 0x6a, 0x83, 0x6d, 0x7f, + 0x70, 0x7d, 0x74, 0x78, 0x78, 0x74, 0x72, 0x75, 0x6a, 0x74, 0x68, 0x72, + 0x72, 0x74, 0x73, 0x72, 0x6f, 0x6e, 0x6b, 0x6d, 0x67, 0x6e, 0x64, 0x6f, + 0x63, 0x72, 0x63, 0x72, 0x63, 0x74, 0x5d, 0x76, 0x5b, 0x85, 0x5f, 0x84, + 0x5e, 0x7b, 0x5a, 0x76, 0x57, 0x77, 0x55, 0x7a, 0x53, 0x7b, 0x55, 0x7e, + 0x59, 0x7f, 0x64, 0x79, 0x76, 0x68, 0x80, 0x5f, 0x7e, 0x5f, 0x7e, 0x60, + 0x79, 0x67, 0x6b, 0x76, 0x5a, 0x82, 0x58, 0x82, 0x59, 0x7f, 0x59, 0x81, + 0x59, 0x82, 0x54, 0x81, 0x56, 0x81, 0x63, 0x89, 0x6c, 0x90, 0x6f, 0x92, + 0x72, 0x90, 0x72, 0x90, 0x72, 0x8e, 0x71, 0x8c, 0x72, 0x8c, 0x6d, 0x86, + 0x66, 0x7b, 0x5d, 0x6d, 0x56, 0x67, 0x54, 0x68, 0x53, 0x6a, 0x52, 0x6a, + 0x52, 0x68, 0x52, 0x69, 0x51, 0x6a, 0x50, 0x6a, 0x50, 0x6b, 0x50, 0x6b, + 0x50, 0x69, 0x53, 0x69, 0x62, 0x60, 0x60, 0x60, 0x5c, 0x63, 0x5a, 0x63, + 0x59, 0x63, 0x57, 0x63, 0x57, 0x63, 0x56, 0x61, 0x56, 0x61, 0x56, 0x61, + 0x56, 0x5f, 0x55, 0x61, 0x54, 0x62, 0x53, 0x63, 0x53, 0x63, 0x51, 0x63, + 0x51, 0x63, 0x51, 0x63, 0x50, 0x63, 0x50, 0x63, 0x51, 0x63, 0x52, 0x61, + 0x53, 0x60, 0x54, 0x60, 0x53, 0x61, 0x53, 0x62, 0x53, 0x62, 0x52, 0x62, + 0x51, 0x63, 0x52, 0x63, 0x51, 0x63, 0x53, 0x66, 0x5b, 0x6f, 0x63, 0x75, + 0x63, 0x75, 0x63, 0x75, 0x65, 0x77, 0x66, 0x77, 0x64, 0x76, 0x66, 0x75, + 0x63, 0x78, 0x65, 0x7d, 0x66, 0x7e, 0x66, 0x7d, 0x68, 0x7d, 0x6c, 0x7d, + 0x6a, 0x7d, 0x67, 0x7c, 0x63, 0x7c, 0x69, 0x7d, 0x6e, 0x7d, 0x6a, 0x7d, + 0x62, 0x7e, 0x62, 0x7f, 0x6a, 0x81, 0x70, 0x81, 0x67, 0x80, 0x69, 0x80, + 0x6a, 0x85, 0x67, 0x8a, 0x5c, 0x95, 0x61, 0x97, 0x65, 0x92, 0x68, 0x8c, + 0x75, 0x87, 0x79, 0x85, 0x79, 0x82, 0x7a, 0x7f, 0x7e, 0x7d, 0x7f, 0x7d, + 0x7e, 0x7d, 0x7d, 0x7c, 0x80, 0x7c, 0x80, 0x7e, 0x7f, 0x7f, 0x7f, 0x80, + 0x7d, 0x84, 0x7c, 0x84, 0x7c, 0x85, 0x7b, 0x86, 0x7c, 0x87, 0x79, 0x88, + 0x78, 0x8a, 0x77, 0x8a, 0x71, 0x89, 0x6e, 0x89, 0x6f, 0x87, 0x6d, 0x87, + 0x69, 0x85, 0x66, 0x85, 0x66, 0x85, 0x67, 0x85, 0x67, 0x85, 0x6a, 0x7f, + 0x6d, 0x7c, 0x6e, 0x7c, 0x6e, 0x79, 0x72, 0x74, 0x74, 0x72, 0x75, 0x75, + 0x76, 0x77, 0x6b, 0x79, 0x60, 0x78, 0x64, 0x76, 0x73, 0x73, 0x6f, 0x71, + 0x6b, 0x6e, 0x67, 0x6c, 0x64, 0x6e, 0x61, 0x71, 0x62, 0x74, 0x65, 0x74, + 0x61, 0x76, 0x5b, 0x7a, 0x5e, 0x87, 0x5e, 0x80, 0x5e, 0x7b, 0x5d, 0x77, + 0x5f, 0x78, 0x58, 0x7a, 0x54, 0x7b, 0x57, 0x7d, 0x5d, 0x7b, 0x6c, 0x72, + 0x7e, 0x60, 0x83, 0x57, 0x82, 0x56, 0x81, 0x56, 0x7c, 0x60, 0x6e, 0x73, + 0x5e, 0x82, 0x5a, 0x81, 0x57, 0x80, 0x58, 0x83, 0x57, 0x84, 0x54, 0x81, + 0x5a, 0x7e, 0x69, 0x7d, 0x72, 0x7e, 0x75, 0x83, 0x72, 0x8a, 0x71, 0x8d, + 0x71, 0x8f, 0x73, 0x8f, 0x73, 0x8f, 0x72, 0x83, 0x71, 0x74, 0x70, 0x64, + 0x6d, 0x5f, 0x6c, 0x60, 0x69, 0x62, 0x68, 0x63, 0x68, 0x62, 0x68, 0x63, + 0x66, 0x64, 0x64, 0x64, 0x63, 0x65, 0x63, 0x65, 0x63, 0x65, 0x65, 0x65, + 0x61, 0x61, 0x60, 0x60, 0x5d, 0x62, 0x5a, 0x63, 0x57, 0x63, 0x56, 0x63, + 0x56, 0x63, 0x56, 0x62, 0x56, 0x60, 0x56, 0x60, 0x57, 0x5e, 0x56, 0x5f, + 0x54, 0x62, 0x53, 0x62, 0x53, 0x63, 0x51, 0x64, 0x51, 0x63, 0x51, 0x63, + 0x51, 0x63, 0x50, 0x63, 0x51, 0x63, 0x51, 0x61, 0x53, 0x60, 0x53, 0x61, + 0x52, 0x62, 0x52, 0x62, 0x52, 0x61, 0x52, 0x62, 0x50, 0x63, 0x50, 0x64, + 0x50, 0x65, 0x52, 0x66, 0x5a, 0x6d, 0x62, 0x74, 0x63, 0x76, 0x63, 0x76, + 0x64, 0x77, 0x65, 0x77, 0x64, 0x76, 0x65, 0x76, 0x62, 0x79, 0x65, 0x7d, + 0x62, 0x7d, 0x60, 0x7e, 0x62, 0x7f, 0x66, 0x80, 0x66, 0x7f, 0x66, 0x7d, + 0x61, 0x7c, 0x69, 0x7e, 0x74, 0x81, 0x69, 0x89, 0x5f, 0x86, 0x64, 0x7e, + 0x6c, 0x7f, 0x69, 0x7f, 0x63, 0x7f, 0x6e, 0x7e, 0x6d, 0x89, 0x6e, 0x8c, + 0x61, 0x8e, 0x61, 0x90, 0x61, 0x8f, 0x5b, 0x90, 0x68, 0x8d, 0x70, 0x88, + 0x7b, 0x82, 0x80, 0x7e, 0x80, 0x7e, 0x80, 0x7e, 0x7f, 0x7b, 0x7d, 0x76, + 0x7e, 0x73, 0x80, 0x73, 0x7e, 0x76, 0x7e, 0x78, 0x80, 0x7d, 0x80, 0x7f, + 0x7f, 0x80, 0x7d, 0x82, 0x7b, 0x83, 0x7a, 0x83, 0x7b, 0x85, 0x7b, 0x88, + 0x76, 0x89, 0x72, 0x89, 0x70, 0x8a, 0x6d, 0x89, 0x6a, 0x86, 0x67, 0x85, + 0x68, 0x83, 0x69, 0x82, 0x6c, 0x7f, 0x6d, 0x7a, 0x70, 0x74, 0x71, 0x73, + 0x71, 0x70, 0x6f, 0x72, 0x6c, 0x76, 0x6c, 0x7e, 0x71, 0x80, 0x6c, 0x7c, + 0x62, 0x7a, 0x68, 0x78, 0x71, 0x73, 0x6c, 0x71, 0x69, 0x6e, 0x65, 0x6d, + 0x62, 0x6f, 0x60, 0x73, 0x63, 0x75, 0x67, 0x74, 0x60, 0x76, 0x5c, 0x7b, + 0x5e, 0x82, 0x5d, 0x7c, 0x5f, 0x7b, 0x62, 0x79, 0x63, 0x78, 0x58, 0x7a, + 0x55, 0x7c, 0x59, 0x7c, 0x62, 0x78, 0x71, 0x6f, 0x80, 0x5e, 0x83, 0x56, + 0x82, 0x54, 0x80, 0x56, 0x7b, 0x60, 0x6e, 0x76, 0x62, 0x84, 0x5c, 0x82, + 0x58, 0x81, 0x57, 0x84, 0x56, 0x85, 0x55, 0x81, 0x5c, 0x7c, 0x6f, 0x72, + 0x7a, 0x6d, 0x7c, 0x72, 0x76, 0x7e, 0x75, 0x83, 0x74, 0x89, 0x72, 0x8a, + 0x72, 0x8a, 0x76, 0x7d, 0x78, 0x6d, 0x79, 0x5f, 0x78, 0x5b, 0x79, 0x5c, + 0x78, 0x5e, 0x77, 0x5f, 0x76, 0x5f, 0x76, 0x60, 0x76, 0x62, 0x75, 0x62, + 0x73, 0x62, 0x73, 0x62, 0x72, 0x63, 0x74, 0x63, 0x60, 0x64, 0x60, 0x62, + 0x5d, 0x61, 0x59, 0x63, 0x57, 0x63, 0x56, 0x63, 0x57, 0x62, 0x57, 0x62, + 0x56, 0x60, 0x57, 0x5f, 0x57, 0x5e, 0x57, 0x5f, 0x55, 0x61, 0x54, 0x61, + 0x53, 0x61, 0x51, 0x63, 0x51, 0x61, 0x51, 0x63, 0x51, 0x63, 0x51, 0x61, + 0x51, 0x63, 0x51, 0x61, 0x52, 0x60, 0x51, 0x62, 0x51, 0x63, 0x50, 0x62, + 0x4f, 0x61, 0x4f, 0x63, 0x4d, 0x65, 0x4e, 0x65, 0x53, 0x67, 0x56, 0x67, + 0x5b, 0x6a, 0x61, 0x74, 0x64, 0x78, 0x62, 0x77, 0x62, 0x76, 0x63, 0x77, + 0x64, 0x76, 0x63, 0x77, 0x63, 0x7a, 0x62, 0x7a, 0x60, 0x7d, 0x64, 0x84, + 0x64, 0x83, 0x66, 0x83, 0x66, 0x82, 0x67, 0x80, 0x64, 0x7e, 0x6a, 0x80, + 0x6d, 0x82, 0x60, 0x83, 0x64, 0x7e, 0x6d, 0x7c, 0x6d, 0x7c, 0x67, 0x7c, + 0x6a, 0x83, 0x6a, 0x85, 0x6c, 0x93, 0x7c, 0x90, 0x71, 0x8d, 0x64, 0x8b, + 0x5c, 0x8a, 0x57, 0x8c, 0x5a, 0x8f, 0x5d, 0x8f, 0x6a, 0x8a, 0x71, 0x84, + 0x74, 0x83, 0x77, 0x83, 0x7b, 0x7d, 0x82, 0x6e, 0x80, 0x69, 0x80, 0x6a, + 0x84, 0x67, 0x84, 0x64, 0x84, 0x64, 0x83, 0x68, 0x83, 0x6a, 0x84, 0x6e, + 0x82, 0x70, 0x81, 0x73, 0x81, 0x74, 0x80, 0x75, 0x7d, 0x7b, 0x7b, 0x7e, + 0x77, 0x7e, 0x75, 0x7d, 0x73, 0x7a, 0x71, 0x77, 0x71, 0x77, 0x72, 0x74, + 0x72, 0x73, 0x72, 0x70, 0x74, 0x6e, 0x74, 0x71, 0x70, 0x75, 0x65, 0x79, + 0x60, 0x7f, 0x61, 0x80, 0x66, 0x81, 0x6a, 0x7f, 0x65, 0x7c, 0x6e, 0x78, + 0x6e, 0x72, 0x6a, 0x71, 0x67, 0x6e, 0x62, 0x6f, 0x5f, 0x72, 0x60, 0x74, + 0x66, 0x74, 0x68, 0x72, 0x5e, 0x76, 0x5b, 0x7b, 0x5d, 0x7d, 0x5e, 0x7c, + 0x61, 0x7b, 0x64, 0x79, 0x62, 0x78, 0x59, 0x7a, 0x58, 0x7b, 0x60, 0x78, + 0x6c, 0x70, 0x79, 0x67, 0x82, 0x59, 0x84, 0x54, 0x83, 0x54, 0x80, 0x57, + 0x7c, 0x63, 0x70, 0x7c, 0x67, 0x89, 0x61, 0x87, 0x5d, 0x83, 0x5a, 0x83, + 0x58, 0x80, 0x56, 0x7d, 0x5d, 0x78, 0x74, 0x67, 0x81, 0x60, 0x84, 0x60, + 0x81, 0x66, 0x7f, 0x6b, 0x7b, 0x73, 0x79, 0x76, 0x79, 0x75, 0x7d, 0x6c, + 0x7f, 0x63, 0x82, 0x59, 0x83, 0x58, 0x82, 0x5a, 0x83, 0x5b, 0x82, 0x5c, + 0x81, 0x5c, 0x80, 0x5d, 0x80, 0x60, 0x80, 0x60, 0x7f, 0x5e, 0x7f, 0x5f, + 0x7e, 0x60, 0x7e, 0x5f, 0x60, 0x66, 0x60, 0x63, 0x5d, 0x63, 0x59, 0x65, + 0x57, 0x64, 0x56, 0x63, 0x57, 0x62, 0x56, 0x62, 0x57, 0x60, 0x57, 0x5f, + 0x57, 0x5e, 0x57, 0x5f, 0x55, 0x60, 0x54, 0x60, 0x54, 0x60, 0x52, 0x62, + 0x51, 0x60, 0x51, 0x61, 0x51, 0x61, 0x51, 0x5f, 0x51, 0x62, 0x51, 0x61, + 0x51, 0x60, 0x50, 0x62, 0x4f, 0x63, 0x4f, 0x63, 0x4d, 0x63, 0x4d, 0x64, + 0x4f, 0x67, 0x52, 0x66, 0x58, 0x68, 0x5a, 0x67, 0x5d, 0x69, 0x63, 0x73, + 0x64, 0x78, 0x62, 0x77, 0x60, 0x75, 0x62, 0x77, 0x63, 0x76, 0x63, 0x77, + 0x64, 0x78, 0x61, 0x7b, 0x63, 0x81, 0x6d, 0x88, 0x6c, 0x85, 0x6a, 0x85, + 0x67, 0x84, 0x66, 0x82, 0x66, 0x7f, 0x64, 0x80, 0x64, 0x7d, 0x67, 0x78, + 0x6e, 0x7b, 0x70, 0x81, 0x69, 0x84, 0x68, 0x8b, 0x6b, 0x96, 0x68, 0x99, + 0x68, 0x9d, 0x7a, 0x98, 0x7a, 0x94, 0x6e, 0x8e, 0x62, 0x8c, 0x5a, 0x88, + 0x60, 0x87, 0x62, 0x87, 0x61, 0x86, 0x60, 0x86, 0x60, 0x86, 0x63, 0x86, + 0x68, 0x84, 0x7e, 0x6c, 0x85, 0x60, 0x84, 0x63, 0x8d, 0x5f, 0x8e, 0x5b, + 0x8c, 0x56, 0x89, 0x57, 0x88, 0x5a, 0x89, 0x5a, 0x8a, 0x5a, 0x88, 0x5b, + 0x88, 0x5a, 0x88, 0x58, 0x85, 0x5e, 0x83, 0x64, 0x80, 0x68, 0x7d, 0x68, + 0x77, 0x6b, 0x74, 0x69, 0x75, 0x6a, 0x76, 0x67, 0x79, 0x64, 0x79, 0x68, + 0x79, 0x77, 0x79, 0x7d, 0x72, 0x7e, 0x62, 0x7a, 0x60, 0x7d, 0x5e, 0x7e, + 0x5f, 0x7e, 0x63, 0x7e, 0x6b, 0x7e, 0x73, 0x79, 0x6d, 0x70, 0x69, 0x6f, + 0x65, 0x70, 0x5f, 0x71, 0x5e, 0x73, 0x61, 0x74, 0x68, 0x70, 0x66, 0x71, + 0x5d, 0x76, 0x5b, 0x7a, 0x5d, 0x7c, 0x60, 0x7b, 0x62, 0x7b, 0x64, 0x79, + 0x62, 0x78, 0x5c, 0x78, 0x60, 0x77, 0x68, 0x74, 0x75, 0x6b, 0x7f, 0x5f, + 0x85, 0x54, 0x84, 0x53, 0x83, 0x54, 0x80, 0x58, 0x7d, 0x66, 0x70, 0x7f, + 0x69, 0x8e, 0x67, 0x8c, 0x62, 0x87, 0x5f, 0x82, 0x5c, 0x7e, 0x59, 0x7b, + 0x60, 0x78, 0x76, 0x66, 0x83, 0x5c, 0x87, 0x56, 0x88, 0x57, 0x86, 0x59, + 0x83, 0x5d, 0x82, 0x60, 0x82, 0x60, 0x84, 0x5c, 0x86, 0x58, 0x88, 0x54, + 0x89, 0x54, 0x89, 0x56, 0x89, 0x57, 0x89, 0x58, 0x89, 0x59, 0x88, 0x59, + 0x87, 0x5a, 0x87, 0x5b, 0x87, 0x5b, 0x87, 0x5b, 0x86, 0x5b, 0x86, 0x5a, + 0x60, 0x67, 0x5f, 0x65, 0x5c, 0x64, 0x59, 0x66, 0x57, 0x65, 0x56, 0x63, + 0x56, 0x62, 0x56, 0x62, 0x57, 0x61, 0x57, 0x5f, 0x57, 0x5e, 0x57, 0x5e, + 0x56, 0x5f, 0x55, 0x5e, 0x54, 0x5f, 0x52, 0x60, 0x52, 0x5f, 0x51, 0x5f, + 0x51, 0x5f, 0x51, 0x5f, 0x51, 0x61, 0x52, 0x60, 0x51, 0x60, 0x4f, 0x62, + 0x4d, 0x63, 0x4c, 0x65, 0x4d, 0x65, 0x4f, 0x65, 0x56, 0x67, 0x5a, 0x67, + 0x5c, 0x67, 0x5e, 0x67, 0x5f, 0x68, 0x64, 0x71, 0x64, 0x77, 0x62, 0x77, + 0x5e, 0x76, 0x5f, 0x78, 0x62, 0x77, 0x63, 0x78, 0x61, 0x78, 0x62, 0x7c, + 0x68, 0x83, 0x73, 0x87, 0x71, 0x83, 0x6d, 0x85, 0x6b, 0x84, 0x6a, 0x82, + 0x6c, 0x81, 0x6f, 0x82, 0x71, 0x82, 0x74, 0x87, 0x72, 0x8e, 0x6e, 0x93, + 0x6b, 0x97, 0x6d, 0x9b, 0x6c, 0xa0, 0x6b, 0xa3, 0x67, 0xa4, 0x70, 0x9e, + 0x76, 0x98, 0x73, 0x91, 0x6d, 0x8e, 0x67, 0x87, 0x69, 0x85, 0x6a, 0x86, + 0x67, 0x8a, 0x67, 0x8d, 0x67, 0x8a, 0x69, 0x8a, 0x6a, 0x8b, 0x7c, 0x6e, + 0x86, 0x5d, 0x87, 0x5f, 0x8d, 0x5b, 0x8f, 0x56, 0x8e, 0x51, 0x8b, 0x52, + 0x89, 0x56, 0x8a, 0x56, 0x8c, 0x54, 0x8f, 0x51, 0x8f, 0x51, 0x8e, 0x50, + 0x8b, 0x52, 0x88, 0x55, 0x84, 0x5b, 0x81, 0x5e, 0x7f, 0x61, 0x80, 0x5e, + 0x84, 0x58, 0x86, 0x55, 0x87, 0x54, 0x81, 0x67, 0x7c, 0x81, 0x7b, 0x82, + 0x77, 0x80, 0x65, 0x78, 0x62, 0x7a, 0x60, 0x7d, 0x5d, 0x7d, 0x5d, 0x7e, + 0x6d, 0x7e, 0x74, 0x79, 0x6b, 0x70, 0x68, 0x6f, 0x63, 0x72, 0x5e, 0x72, + 0x5d, 0x74, 0x62, 0x73, 0x68, 0x6e, 0x64, 0x71, 0x5b, 0x77, 0x59, 0x79, + 0x5d, 0x7a, 0x61, 0x7a, 0x63, 0x7b, 0x64, 0x79, 0x61, 0x77, 0x60, 0x76, + 0x64, 0x77, 0x6c, 0x73, 0x7d, 0x65, 0x86, 0x57, 0x87, 0x51, 0x85, 0x51, + 0x83, 0x55, 0x80, 0x58, 0x7c, 0x63, 0x71, 0x7d, 0x6b, 0x91, 0x6b, 0x90, + 0x67, 0x8c, 0x64, 0x87, 0x60, 0x82, 0x5d, 0x80, 0x61, 0x7c, 0x71, 0x6c, + 0x7e, 0x5f, 0x85, 0x59, 0x89, 0x56, 0x8a, 0x56, 0x88, 0x57, 0x88, 0x59, + 0x88, 0x59, 0x89, 0x55, 0x8b, 0x55, 0x8b, 0x53, 0x8b, 0x52, 0x8a, 0x53, + 0x8a, 0x54, 0x8a, 0x55, 0x8b, 0x56, 0x8b, 0x57, 0x8b, 0x58, 0x8b, 0x58, + 0x8a, 0x5a, 0x89, 0x59, 0x89, 0x57, 0x88, 0x57, 0x61, 0x68, 0x5d, 0x65, + 0x5b, 0x65, 0x58, 0x65, 0x56, 0x66, 0x55, 0x64, 0x56, 0x63, 0x56, 0x62, + 0x57, 0x60, 0x58, 0x5f, 0x58, 0x5d, 0x58, 0x5d, 0x57, 0x5d, 0x56, 0x5e, + 0x55, 0x5d, 0x52, 0x60, 0x53, 0x60, 0x53, 0x5f, 0x53, 0x5d, 0x53, 0x5f, + 0x51, 0x62, 0x51, 0x61, 0x50, 0x61, 0x4e, 0x61, 0x4b, 0x62, 0x4c, 0x65, + 0x51, 0x66, 0x57, 0x66, 0x5d, 0x67, 0x5e, 0x68, 0x5e, 0x67, 0x61, 0x67, + 0x61, 0x68, 0x63, 0x6f, 0x64, 0x75, 0x62, 0x77, 0x5c, 0x77, 0x5d, 0x78, + 0x62, 0x77, 0x62, 0x79, 0x60, 0x7a, 0x63, 0x7d, 0x6d, 0x83, 0x74, 0x86, + 0x70, 0x87, 0x6e, 0x8a, 0x77, 0x8b, 0x7c, 0x88, 0x79, 0x89, 0x7b, 0x8d, + 0x78, 0x93, 0x72, 0x97, 0x6f, 0x99, 0x6f, 0x9c, 0x6f, 0x9d, 0x71, 0x9e, + 0x70, 0xa2, 0x6e, 0xa4, 0x6b, 0xa4, 0x71, 0x9f, 0x76, 0x9a, 0x73, 0x95, + 0x6f, 0x93, 0x6e, 0x8d, 0x6e, 0x8d, 0x6e, 0x8f, 0x71, 0x90, 0x71, 0x91, + 0x70, 0x8e, 0x71, 0x8c, 0x72, 0x8b, 0x7b, 0x6f, 0x85, 0x5c, 0x87, 0x5d, + 0x8b, 0x5b, 0x8d, 0x56, 0x90, 0x50, 0x8f, 0x4f, 0x8b, 0x53, 0x8a, 0x58, + 0x8c, 0x56, 0x90, 0x50, 0x93, 0x4d, 0x93, 0x4b, 0x91, 0x49, 0x8e, 0x4b, + 0x87, 0x59, 0x81, 0x63, 0x80, 0x68, 0x85, 0x5f, 0x8c, 0x50, 0x8c, 0x4f, + 0x8d, 0x50, 0x88, 0x5d, 0x7b, 0x80, 0x7b, 0x80, 0x79, 0x80, 0x6d, 0x7b, + 0x63, 0x79, 0x63, 0x7d, 0x61, 0x7d, 0x5d, 0x7d, 0x6c, 0x7f, 0x70, 0x7a, + 0x68, 0x72, 0x67, 0x70, 0x62, 0x73, 0x5d, 0x73, 0x5e, 0x73, 0x66, 0x71, + 0x67, 0x6e, 0x61, 0x72, 0x5b, 0x78, 0x59, 0x79, 0x5f, 0x78, 0x63, 0x79, + 0x63, 0x79, 0x62, 0x79, 0x62, 0x77, 0x63, 0x75, 0x65, 0x7b, 0x6f, 0x75, + 0x84, 0x5b, 0x8a, 0x4f, 0x87, 0x50, 0x87, 0x50, 0x83, 0x55, 0x80, 0x59, + 0x7d, 0x5d, 0x76, 0x77, 0x6e, 0x90, 0x6e, 0x92, 0x6e, 0x8f, 0x6c, 0x8b, + 0x69, 0x88, 0x63, 0x87, 0x60, 0x84, 0x66, 0x79, 0x71, 0x6e, 0x7c, 0x62, + 0x88, 0x57, 0x8b, 0x53, 0x8b, 0x53, 0x8c, 0x54, 0x8c, 0x52, 0x8d, 0x50, + 0x8d, 0x52, 0x8c, 0x53, 0x8d, 0x52, 0x8c, 0x52, 0x8c, 0x53, 0x8c, 0x54, + 0x8c, 0x54, 0x8c, 0x55, 0x8d, 0x56, 0x8c, 0x56, 0x8c, 0x57, 0x8c, 0x57, + 0x8c, 0x56, 0x8d, 0x56, 0x64, 0x68, 0x5d, 0x65, 0x5b, 0x65, 0x58, 0x65, + 0x56, 0x65, 0x55, 0x64, 0x56, 0x63, 0x57, 0x62, 0x57, 0x60, 0x58, 0x5e, + 0x58, 0x5c, 0x58, 0x5d, 0x57, 0x5d, 0x56, 0x5d, 0x55, 0x5c, 0x52, 0x60, + 0x53, 0x61, 0x53, 0x5f, 0x53, 0x5c, 0x53, 0x5e, 0x51, 0x61, 0x50, 0x61, + 0x4e, 0x60, 0x4c, 0x61, 0x4b, 0x62, 0x4f, 0x65, 0x55, 0x65, 0x5a, 0x66, + 0x5d, 0x68, 0x5f, 0x6a, 0x60, 0x69, 0x62, 0x69, 0x62, 0x69, 0x64, 0x6d, + 0x64, 0x72, 0x62, 0x76, 0x5e, 0x77, 0x5e, 0x77, 0x63, 0x77, 0x61, 0x79, + 0x5f, 0x7a, 0x62, 0x7d, 0x6c, 0x83, 0x75, 0x80, 0x70, 0x88, 0x6e, 0x91, + 0x76, 0x93, 0x7b, 0x91, 0x79, 0x91, 0x79, 0x93, 0x76, 0x97, 0x72, 0x97, + 0x71, 0x99, 0x70, 0x9c, 0x70, 0x9c, 0x71, 0x9d, 0x70, 0xa0, 0x6e, 0xa2, + 0x6b, 0xa3, 0x72, 0x9c, 0x77, 0x98, 0x75, 0x96, 0x71, 0x96, 0x70, 0x93, + 0x72, 0x92, 0x73, 0x92, 0x77, 0x8e, 0x76, 0x8f, 0x73, 0x8e, 0x73, 0x8c, + 0x75, 0x89, 0x7b, 0x6f, 0x83, 0x5d, 0x85, 0x5b, 0x87, 0x5e, 0x88, 0x5a, + 0x8d, 0x53, 0x8f, 0x4f, 0x8d, 0x50, 0x8b, 0x55, 0x8b, 0x57, 0x8e, 0x53, + 0x93, 0x4c, 0x95, 0x49, 0x95, 0x44, 0x95, 0x44, 0x8c, 0x51, 0x82, 0x60, + 0x80, 0x67, 0x87, 0x5a, 0x8e, 0x4a, 0x8b, 0x50, 0x8c, 0x51, 0x8a, 0x56, + 0x7b, 0x7c, 0x7a, 0x81, 0x7a, 0x80, 0x72, 0x7b, 0x67, 0x79, 0x64, 0x7b, + 0x62, 0x7c, 0x5f, 0x7d, 0x6c, 0x7e, 0x6c, 0x7a, 0x65, 0x72, 0x65, 0x72, + 0x62, 0x74, 0x5e, 0x74, 0x60, 0x74, 0x67, 0x71, 0x65, 0x6e, 0x61, 0x71, + 0x5b, 0x78, 0x5a, 0x78, 0x60, 0x77, 0x64, 0x77, 0x63, 0x78, 0x63, 0x78, + 0x63, 0x78, 0x63, 0x7a, 0x65, 0x80, 0x72, 0x74, 0x86, 0x54, 0x89, 0x4c, + 0x87, 0x4f, 0x87, 0x4f, 0x84, 0x52, 0x82, 0x59, 0x81, 0x57, 0x7a, 0x6d, + 0x70, 0x8c, 0x6f, 0x92, 0x71, 0x90, 0x71, 0x8d, 0x71, 0x8d, 0x69, 0x8d, + 0x63, 0x8b, 0x63, 0x84, 0x68, 0x7e, 0x74, 0x6c, 0x86, 0x58, 0x8b, 0x52, + 0x8b, 0x52, 0x8c, 0x53, 0x8c, 0x51, 0x8d, 0x4f, 0x8d, 0x51, 0x8c, 0x52, + 0x8d, 0x52, 0x8d, 0x53, 0x8c, 0x53, 0x8c, 0x53, 0x8c, 0x52, 0x8c, 0x53, + 0x8d, 0x55, 0x8c, 0x55, 0x8d, 0x56, 0x8d, 0x55, 0x8c, 0x54, 0x8c, 0x54, + 0x67, 0x68, 0x5e, 0x66, 0x59, 0x65, 0x58, 0x64, 0x56, 0x65, 0x55, 0x64, + 0x55, 0x63, 0x56, 0x62, 0x57, 0x5e, 0x58, 0x5c, 0x58, 0x5c, 0x58, 0x5d, + 0x57, 0x5d, 0x56, 0x5a, 0x55, 0x5a, 0x53, 0x5f, 0x53, 0x60, 0x53, 0x5f, + 0x53, 0x5c, 0x52, 0x5c, 0x50, 0x60, 0x4f, 0x61, 0x4d, 0x61, 0x4a, 0x62, + 0x4b, 0x63, 0x54, 0x64, 0x5b, 0x65, 0x5e, 0x67, 0x60, 0x6a, 0x61, 0x6b, + 0x62, 0x6a, 0x63, 0x6a, 0x64, 0x6b, 0x66, 0x6b, 0x64, 0x6e, 0x63, 0x76, + 0x5f, 0x78, 0x60, 0x77, 0x65, 0x77, 0x60, 0x7a, 0x5c, 0x7b, 0x63, 0x7c, + 0x6f, 0x7f, 0x7d, 0x77, 0x7c, 0x7e, 0x74, 0x90, 0x75, 0x91, 0x76, 0x91, + 0x77, 0x92, 0x77, 0x93, 0x75, 0x95, 0x74, 0x96, 0x73, 0x97, 0x72, 0x98, + 0x72, 0x98, 0x72, 0x9b, 0x70, 0x9e, 0x6f, 0xa0, 0x6b, 0xa0, 0x71, 0x9a, + 0x79, 0x96, 0x7a, 0x95, 0x7a, 0x92, 0x77, 0x94, 0x76, 0x93, 0x76, 0x90, + 0x78, 0x8d, 0x78, 0x8d, 0x78, 0x8e, 0x77, 0x8c, 0x79, 0x87, 0x7b, 0x6f, + 0x81, 0x5f, 0x84, 0x59, 0x83, 0x60, 0x83, 0x60, 0x89, 0x57, 0x8e, 0x4f, + 0x91, 0x4b, 0x8f, 0x4d, 0x8c, 0x51, 0x8b, 0x55, 0x91, 0x4e, 0x97, 0x46, + 0x9a, 0x40, 0x9c, 0x3d, 0x93, 0x45, 0x86, 0x58, 0x80, 0x64, 0x8c, 0x52, + 0x93, 0x42, 0x8c, 0x4e, 0x8c, 0x51, 0x8d, 0x4f, 0x7c, 0x75, 0x7a, 0x81, + 0x7a, 0x7f, 0x77, 0x7c, 0x6e, 0x78, 0x63, 0x79, 0x61, 0x7b, 0x60, 0x7d, + 0x6b, 0x7e, 0x67, 0x7a, 0x62, 0x73, 0x62, 0x73, 0x61, 0x76, 0x5f, 0x76, + 0x62, 0x75, 0x68, 0x71, 0x64, 0x6f, 0x61, 0x72, 0x5a, 0x78, 0x5d, 0x77, + 0x62, 0x75, 0x63, 0x76, 0x63, 0x77, 0x65, 0x77, 0x65, 0x79, 0x64, 0x81, + 0x66, 0x84, 0x77, 0x73, 0x88, 0x51, 0x89, 0x4d, 0x87, 0x4e, 0x88, 0x4d, + 0x86, 0x4f, 0x83, 0x58, 0x85, 0x55, 0x80, 0x5e, 0x73, 0x80, 0x71, 0x8c, + 0x70, 0x8e, 0x72, 0x8f, 0x73, 0x91, 0x71, 0x8f, 0x6e, 0x8e, 0x6a, 0x8d, + 0x69, 0x8d, 0x72, 0x78, 0x87, 0x57, 0x8b, 0x50, 0x8a, 0x50, 0x8c, 0x52, + 0x8c, 0x4f, 0x8d, 0x4e, 0x8d, 0x4f, 0x8d, 0x52, 0x8d, 0x53, 0x8d, 0x52, + 0x8d, 0x53, 0x8d, 0x53, 0x8d, 0x52, 0x8c, 0x52, 0x8d, 0x53, 0x8c, 0x52, + 0x8d, 0x54, 0x8d, 0x54, 0x8c, 0x53, 0x8c, 0x53, 0x68, 0x68, 0x61, 0x68, + 0x58, 0x66, 0x56, 0x64, 0x55, 0x65, 0x54, 0x65, 0x53, 0x64, 0x55, 0x62, + 0x56, 0x5e, 0x57, 0x5d, 0x57, 0x5d, 0x56, 0x5e, 0x56, 0x5d, 0x56, 0x5a, + 0x55, 0x5a, 0x54, 0x5e, 0x54, 0x5d, 0x52, 0x5f, 0x53, 0x5c, 0x52, 0x5b, + 0x50, 0x61, 0x4d, 0x62, 0x4b, 0x63, 0x49, 0x65, 0x4f, 0x65, 0x5b, 0x64, + 0x5e, 0x65, 0x61, 0x68, 0x63, 0x6a, 0x63, 0x6a, 0x64, 0x6b, 0x64, 0x6a, + 0x66, 0x6b, 0x65, 0x6a, 0x65, 0x6d, 0x65, 0x73, 0x61, 0x78, 0x60, 0x79, + 0x63, 0x79, 0x5e, 0x7b, 0x5f, 0x7a, 0x71, 0x77, 0x7f, 0x75, 0x84, 0x73, + 0x80, 0x7a, 0x76, 0x91, 0x75, 0x90, 0x76, 0x8f, 0x78, 0x91, 0x79, 0x91, + 0x77, 0x93, 0x76, 0x95, 0x76, 0x96, 0x74, 0x97, 0x74, 0x98, 0x73, 0x98, + 0x71, 0x9b, 0x6e, 0x9f, 0x6a, 0x96, 0x6d, 0x9b, 0x79, 0x97, 0x7b, 0x93, + 0x7a, 0x91, 0x77, 0x93, 0x76, 0x94, 0x76, 0x92, 0x78, 0x8f, 0x78, 0x8d, + 0x7a, 0x8c, 0x79, 0x8b, 0x79, 0x84, 0x7b, 0x6c, 0x7f, 0x61, 0x84, 0x58, + 0x83, 0x5b, 0x82, 0x5f, 0x88, 0x57, 0x8e, 0x4c, 0x95, 0x47, 0x95, 0x46, + 0x91, 0x49, 0x8c, 0x52, 0x8e, 0x52, 0x97, 0x47, 0x9d, 0x3e, 0x9c, 0x3b, + 0x9a, 0x3f, 0x8d, 0x4b, 0x82, 0x5f, 0x8f, 0x4d, 0x98, 0x3d, 0x8e, 0x4b, + 0x8b, 0x52, 0x8e, 0x4b, 0x7f, 0x6d, 0x7a, 0x7e, 0x7b, 0x7f, 0x7b, 0x7d, + 0x74, 0x7c, 0x64, 0x7a, 0x61, 0x7a, 0x5f, 0x7e, 0x69, 0x7f, 0x63, 0x7b, + 0x60, 0x74, 0x60, 0x74, 0x5f, 0x75, 0x60, 0x75, 0x65, 0x73, 0x68, 0x70, + 0x64, 0x71, 0x60, 0x73, 0x5b, 0x77, 0x62, 0x76, 0x63, 0x74, 0x63, 0x74, + 0x64, 0x75, 0x67, 0x78, 0x68, 0x7d, 0x67, 0x86, 0x6c, 0x82, 0x7c, 0x6d, + 0x87, 0x50, 0x87, 0x4e, 0x87, 0x4f, 0x89, 0x4d, 0x86, 0x4f, 0x83, 0x57, + 0x85, 0x55, 0x85, 0x56, 0x7a, 0x72, 0x75, 0x83, 0x71, 0x8b, 0x72, 0x8e, + 0x72, 0x91, 0x72, 0x91, 0x72, 0x90, 0x6f, 0x92, 0x6f, 0x8e, 0x77, 0x77, + 0x86, 0x53, 0x8a, 0x4d, 0x8b, 0x4e, 0x8c, 0x50, 0x8c, 0x50, 0x8e, 0x4e, + 0x8e, 0x50, 0x8d, 0x52, 0x8e, 0x54, 0x8e, 0x53, 0x8e, 0x53, 0x8d, 0x52, + 0x8d, 0x51, 0x8d, 0x51, 0x8d, 0x50, 0x8d, 0x4f, 0x8d, 0x52, 0x8c, 0x54, + 0x8b, 0x54, 0x8b, 0x53, 0x68, 0x68, 0x61, 0x68, 0x58, 0x68, 0x55, 0x65, + 0x54, 0x65, 0x53, 0x66, 0x53, 0x64, 0x55, 0x62, 0x56, 0x60, 0x57, 0x5f, + 0x57, 0x5d, 0x57, 0x5e, 0x56, 0x5d, 0x56, 0x5c, 0x55, 0x5c, 0x54, 0x5e, + 0x54, 0x5d, 0x53, 0x5e, 0x53, 0x5d, 0x52, 0x5d, 0x50, 0x60, 0x4d, 0x61, + 0x4b, 0x63, 0x4e, 0x65, 0x54, 0x65, 0x5d, 0x65, 0x60, 0x66, 0x63, 0x69, + 0x64, 0x6a, 0x64, 0x6a, 0x65, 0x6a, 0x66, 0x6b, 0x67, 0x6b, 0x67, 0x6b, + 0x66, 0x6e, 0x66, 0x70, 0x62, 0x78, 0x60, 0x78, 0x68, 0x76, 0x6f, 0x72, + 0x79, 0x72, 0x82, 0x73, 0x85, 0x73, 0x85, 0x73, 0x82, 0x76, 0x7b, 0x88, + 0x77, 0x91, 0x78, 0x90, 0x78, 0x8d, 0x7a, 0x8e, 0x77, 0x92, 0x76, 0x97, + 0x76, 0x97, 0x75, 0x96, 0x75, 0x97, 0x73, 0x98, 0x6f, 0x96, 0x70, 0x8d, + 0x76, 0x7c, 0x79, 0x85, 0x7b, 0x8e, 0x78, 0x97, 0x77, 0x97, 0x75, 0x96, + 0x75, 0x95, 0x76, 0x93, 0x78, 0x90, 0x78, 0x8f, 0x79, 0x8c, 0x7b, 0x81, + 0x7c, 0x71, 0x7e, 0x65, 0x80, 0x65, 0x83, 0x5b, 0x88, 0x51, 0x87, 0x57, + 0x8a, 0x55, 0x92, 0x48, 0x98, 0x42, 0x99, 0x3f, 0x97, 0x41, 0x92, 0x4c, + 0x8e, 0x52, 0x94, 0x4b, 0x9d, 0x3f, 0x9d, 0x3c, 0x9c, 0x41, 0x98, 0x40, + 0x88, 0x56, 0x90, 0x49, 0x9a, 0x38, 0x8f, 0x47, 0x8a, 0x52, 0x90, 0x49, + 0x84, 0x64, 0x7d, 0x77, 0x7c, 0x7e, 0x7c, 0x7d, 0x78, 0x7e, 0x69, 0x7b, + 0x64, 0x7b, 0x5f, 0x7f, 0x66, 0x7f, 0x60, 0x7b, 0x5e, 0x75, 0x5f, 0x74, + 0x62, 0x75, 0x64, 0x74, 0x67, 0x72, 0x67, 0x70, 0x64, 0x71, 0x5f, 0x74, + 0x5e, 0x78, 0x63, 0x76, 0x63, 0x74, 0x63, 0x74, 0x65, 0x75, 0x68, 0x7b, + 0x6a, 0x82, 0x6e, 0x82, 0x78, 0x77, 0x82, 0x61, 0x87, 0x51, 0x87, 0x50, + 0x87, 0x4f, 0x89, 0x4d, 0x87, 0x4e, 0x83, 0x56, 0x86, 0x55, 0x86, 0x50, + 0x84, 0x58, 0x7c, 0x6e, 0x74, 0x84, 0x72, 0x8a, 0x72, 0x8e, 0x72, 0x8e, + 0x71, 0x8d, 0x73, 0x8c, 0x75, 0x84, 0x7d, 0x6b, 0x88, 0x50, 0x8a, 0x4e, + 0x8b, 0x4e, 0x8c, 0x4e, 0x8c, 0x4e, 0x8d, 0x4d, 0x8e, 0x4f, 0x8d, 0x51, + 0x8d, 0x53, 0x8e, 0x52, 0x8e, 0x51, 0x8e, 0x51, 0x8e, 0x50, 0x8e, 0x50, + 0x8e, 0x4f, 0x8e, 0x4d, 0x8e, 0x4e, 0x8e, 0x52, 0x8c, 0x52, 0x8c, 0x52, + 0x67, 0x68, 0x61, 0x68, 0x59, 0x6a, 0x53, 0x67, 0x52, 0x66, 0x51, 0x66, + 0x52, 0x64, 0x54, 0x61, 0x56, 0x61, 0x56, 0x61, 0x56, 0x5e, 0x57, 0x5d, + 0x56, 0x5d, 0x55, 0x5e, 0x55, 0x5e, 0x54, 0x5e, 0x54, 0x5e, 0x54, 0x5c, + 0x53, 0x5f, 0x52, 0x60, 0x4f, 0x5f, 0x4c, 0x60, 0x4e, 0x63, 0x56, 0x65, + 0x5b, 0x65, 0x5f, 0x66, 0x63, 0x68, 0x65, 0x6a, 0x65, 0x6a, 0x66, 0x6a, + 0x67, 0x6b, 0x67, 0x6b, 0x67, 0x6b, 0x68, 0x6b, 0x69, 0x6d, 0x6b, 0x6d, + 0x72, 0x71, 0x75, 0x71, 0x81, 0x70, 0x86, 0x70, 0x87, 0x71, 0x85, 0x75, + 0x85, 0x76, 0x85, 0x77, 0x84, 0x77, 0x81, 0x7c, 0x7a, 0x89, 0x79, 0x8e, + 0x79, 0x8d, 0x7a, 0x8e, 0x77, 0x90, 0x74, 0x95, 0x75, 0x93, 0x77, 0x8f, + 0x79, 0x89, 0x7d, 0x82, 0x82, 0x77, 0x84, 0x6f, 0x8a, 0x68, 0x8b, 0x6a, + 0x88, 0x72, 0x7c, 0x82, 0x78, 0x89, 0x76, 0x90, 0x75, 0x95, 0x75, 0x93, + 0x78, 0x8e, 0x79, 0x89, 0x7d, 0x77, 0x83, 0x5d, 0x87, 0x51, 0x8b, 0x4f, + 0x85, 0x5a, 0x82, 0x5f, 0x91, 0x4c, 0x94, 0x4b, 0x90, 0x50, 0x99, 0x42, + 0x9d, 0x3e, 0x9c, 0x3d, 0x9d, 0x3c, 0x99, 0x41, 0x90, 0x4b, 0x90, 0x4d, + 0x9d, 0x41, 0xa0, 0x3a, 0x9b, 0x41, 0x9b, 0x48, 0x91, 0x48, 0x90, 0x49, + 0x9b, 0x39, 0x91, 0x46, 0x8b, 0x52, 0x93, 0x47, 0x8a, 0x58, 0x80, 0x6d, + 0x7d, 0x7b, 0x7e, 0x7d, 0x7c, 0x7e, 0x6f, 0x7e, 0x68, 0x7c, 0x60, 0x7e, + 0x63, 0x7f, 0x5b, 0x7b, 0x5a, 0x75, 0x5f, 0x75, 0x68, 0x74, 0x6a, 0x71, + 0x69, 0x6f, 0x65, 0x6f, 0x62, 0x71, 0x5d, 0x76, 0x62, 0x79, 0x63, 0x77, + 0x63, 0x74, 0x65, 0x74, 0x67, 0x75, 0x6a, 0x7b, 0x6e, 0x7f, 0x7a, 0x70, + 0x87, 0x5e, 0x89, 0x52, 0x87, 0x52, 0x87, 0x52, 0x87, 0x4e, 0x89, 0x4c, + 0x89, 0x4c, 0x86, 0x53, 0x88, 0x54, 0x88, 0x52, 0x8a, 0x4a, 0x87, 0x54, + 0x80, 0x6b, 0x7b, 0x76, 0x79, 0x7f, 0x79, 0x83, 0x78, 0x82, 0x7a, 0x7d, + 0x7e, 0x71, 0x85, 0x59, 0x8a, 0x4d, 0x8a, 0x4e, 0x8a, 0x4d, 0x8d, 0x4c, + 0x8c, 0x4c, 0x8d, 0x4b, 0x8e, 0x4c, 0x8d, 0x4e, 0x8e, 0x51, 0x8e, 0x50, + 0x8d, 0x4f, 0x8e, 0x4e, 0x90, 0x4d, 0x90, 0x4e, 0x90, 0x4c, 0x90, 0x4a, + 0x90, 0x4b, 0x90, 0x4e, 0x8f, 0x50, 0x8f, 0x4f, 0x66, 0x6a, 0x60, 0x6a, + 0x5b, 0x69, 0x52, 0x68, 0x51, 0x67, 0x51, 0x65, 0x51, 0x64, 0x53, 0x62, + 0x55, 0x60, 0x55, 0x60, 0x56, 0x60, 0x57, 0x5d, 0x56, 0x5d, 0x55, 0x5e, + 0x55, 0x5e, 0x54, 0x5f, 0x53, 0x5f, 0x54, 0x5c, 0x53, 0x5e, 0x52, 0x5e, + 0x4f, 0x5e, 0x4d, 0x61, 0x51, 0x64, 0x5b, 0x65, 0x5f, 0x66, 0x62, 0x69, + 0x65, 0x6a, 0x67, 0x6a, 0x66, 0x6b, 0x66, 0x6b, 0x69, 0x6d, 0x67, 0x6b, + 0x68, 0x6a, 0x70, 0x6a, 0x77, 0x68, 0x7d, 0x6a, 0x85, 0x6e, 0x86, 0x6f, + 0x86, 0x72, 0x85, 0x72, 0x85, 0x76, 0x85, 0x78, 0x84, 0x78, 0x84, 0x79, + 0x84, 0x79, 0x84, 0x73, 0x80, 0x7b, 0x7a, 0x89, 0x77, 0x8f, 0x78, 0x90, + 0x76, 0x90, 0x77, 0x8c, 0x7c, 0x86, 0x81, 0x79, 0x87, 0x71, 0x8b, 0x6d, + 0x8d, 0x6c, 0x8c, 0x6e, 0x8a, 0x6e, 0x8a, 0x6d, 0x8a, 0x6b, 0x87, 0x6b, + 0x85, 0x6b, 0x83, 0x6e, 0x7d, 0x7b, 0x7d, 0x7a, 0x7c, 0x70, 0x7f, 0x67, + 0x86, 0x57, 0x8d, 0x4a, 0x93, 0x47, 0x98, 0x47, 0x92, 0x47, 0x89, 0x58, + 0x92, 0x4e, 0x9a, 0x4b, 0x95, 0x4f, 0x9c, 0x42, 0x9d, 0x43, 0x9d, 0x45, + 0x9d, 0x41, 0x9b, 0x3b, 0x94, 0x42, 0x91, 0x4c, 0x98, 0x46, 0x9f, 0x3b, + 0xa0, 0x3b, 0x99, 0x51, 0x97, 0x42, 0x8f, 0x49, 0x99, 0x3d, 0x95, 0x42, + 0x8b, 0x51, 0x93, 0x46, 0x8d, 0x4f, 0x83, 0x63, 0x7f, 0x75, 0x7e, 0x7e, + 0x7d, 0x7e, 0x74, 0x80, 0x6a, 0x7d, 0x63, 0x7e, 0x60, 0x7f, 0x59, 0x7a, + 0x5a, 0x77, 0x61, 0x76, 0x69, 0x72, 0x6d, 0x6e, 0x69, 0x6c, 0x64, 0x70, + 0x60, 0x73, 0x5c, 0x78, 0x62, 0x78, 0x64, 0x76, 0x63, 0x73, 0x66, 0x72, + 0x67, 0x75, 0x6e, 0x7a, 0x77, 0x74, 0x87, 0x5e, 0x8d, 0x52, 0x8a, 0x4d, + 0x86, 0x52, 0x87, 0x51, 0x89, 0x4b, 0x89, 0x49, 0x89, 0x4b, 0x86, 0x52, + 0x88, 0x53, 0x88, 0x53, 0x89, 0x4d, 0x8b, 0x47, 0x89, 0x51, 0x86, 0x61, + 0x82, 0x6a, 0x81, 0x70, 0x82, 0x70, 0x83, 0x6a, 0x85, 0x5f, 0x8a, 0x4c, + 0x89, 0x4a, 0x8a, 0x4c, 0x8a, 0x4c, 0x8d, 0x4b, 0x8d, 0x4b, 0x8f, 0x4a, + 0x8f, 0x4a, 0x8f, 0x4c, 0x8e, 0x4f, 0x8f, 0x4f, 0x8f, 0x4c, 0x8f, 0x4a, + 0x91, 0x4a, 0x91, 0x4b, 0x92, 0x4b, 0x91, 0x48, 0x91, 0x49, 0x91, 0x4b, + 0x90, 0x4e, 0x93, 0x49, 0x65, 0x6a, 0x61, 0x6a, 0x5d, 0x69, 0x52, 0x68, + 0x50, 0x67, 0x50, 0x65, 0x51, 0x64, 0x52, 0x63, 0x54, 0x60, 0x55, 0x60, + 0x55, 0x60, 0x56, 0x5e, 0x55, 0x5c, 0x55, 0x5e, 0x55, 0x5d, 0x54, 0x5e, + 0x54, 0x5e, 0x54, 0x5b, 0x53, 0x5d, 0x52, 0x5d, 0x4f, 0x5e, 0x4e, 0x61, + 0x55, 0x64, 0x5d, 0x65, 0x60, 0x66, 0x63, 0x69, 0x66, 0x6a, 0x67, 0x6a, + 0x67, 0x6a, 0x67, 0x6a, 0x6c, 0x6b, 0x72, 0x67, 0x79, 0x69, 0x82, 0x6b, + 0x86, 0x6c, 0x86, 0x6f, 0x86, 0x72, 0x85, 0x74, 0x84, 0x76, 0x85, 0x76, + 0x84, 0x77, 0x85, 0x77, 0x84, 0x77, 0x84, 0x76, 0x83, 0x76, 0x85, 0x70, + 0x8a, 0x6b, 0x87, 0x72, 0x80, 0x7d, 0x7f, 0x7f, 0x82, 0x79, 0x87, 0x6f, + 0x89, 0x6d, 0x8b, 0x6c, 0x8b, 0x6d, 0x8b, 0x6f, 0x8a, 0x70, 0x8a, 0x71, + 0x88, 0x71, 0x88, 0x70, 0x88, 0x6f, 0x89, 0x6d, 0x8a, 0x6a, 0x8a, 0x66, + 0x8f, 0x5b, 0x92, 0x5c, 0x8a, 0x5b, 0x89, 0x54, 0x8f, 0x54, 0x94, 0x55, + 0x95, 0x55, 0x97, 0x54, 0x99, 0x51, 0x95, 0x4c, 0x95, 0x4c, 0x9a, 0x4a, + 0x96, 0x56, 0x97, 0x47, 0x9b, 0x48, 0x9b, 0x4b, 0x9b, 0x48, 0x9c, 0x3f, + 0x9a, 0x3d, 0x96, 0x46, 0x95, 0x4b, 0x9b, 0x45, 0x9f, 0x3b, 0x9b, 0x43, + 0x97, 0x48, 0x93, 0x41, 0x95, 0x40, 0x95, 0x40, 0x8c, 0x50, 0x93, 0x46, + 0x91, 0x49, 0x88, 0x5b, 0x86, 0x65, 0x83, 0x74, 0x7d, 0x7e, 0x78, 0x80, + 0x72, 0x80, 0x67, 0x80, 0x5b, 0x7f, 0x58, 0x79, 0x5e, 0x79, 0x63, 0x78, + 0x6a, 0x72, 0x6c, 0x6e, 0x68, 0x6d, 0x62, 0x72, 0x5e, 0x74, 0x5e, 0x79, + 0x64, 0x77, 0x65, 0x76, 0x65, 0x74, 0x67, 0x6f, 0x6b, 0x73, 0x7a, 0x6f, + 0x83, 0x64, 0x8c, 0x57, 0x8d, 0x4f, 0x8a, 0x4d, 0x88, 0x51, 0x88, 0x50, + 0x89, 0x4b, 0x89, 0x49, 0x8a, 0x48, 0x88, 0x50, 0x88, 0x51, 0x88, 0x51, + 0x89, 0x4f, 0x8b, 0x4a, 0x8d, 0x46, 0x8d, 0x4e, 0x8c, 0x53, 0x8b, 0x56, + 0x8c, 0x57, 0x8d, 0x52, 0x8d, 0x4d, 0x8d, 0x45, 0x8b, 0x47, 0x8b, 0x4a, + 0x8b, 0x4a, 0x8e, 0x4a, 0x8f, 0x4a, 0x8f, 0x4a, 0x8f, 0x4a, 0x8f, 0x4b, + 0x8e, 0x4d, 0x8f, 0x4e, 0x8f, 0x4c, 0x90, 0x4a, 0x90, 0x4a, 0x90, 0x4b, + 0x91, 0x4a, 0x92, 0x46, 0x92, 0x45, 0x92, 0x46, 0x92, 0x47, 0x94, 0x41, + 0x66, 0x69, 0x60, 0x6a, 0x5e, 0x69, 0x54, 0x68, 0x50, 0x67, 0x4f, 0x65, + 0x51, 0x64, 0x53, 0x63, 0x54, 0x61, 0x54, 0x61, 0x54, 0x60, 0x55, 0x5e, + 0x54, 0x5d, 0x55, 0x5d, 0x55, 0x5d, 0x54, 0x5c, 0x53, 0x5c, 0x54, 0x59, + 0x54, 0x5b, 0x52, 0x5c, 0x4f, 0x5e, 0x51, 0x61, 0x59, 0x63, 0x5f, 0x65, + 0x62, 0x67, 0x63, 0x69, 0x65, 0x6a, 0x66, 0x69, 0x6c, 0x68, 0x75, 0x68, + 0x7f, 0x6a, 0x85, 0x6e, 0x86, 0x6f, 0x85, 0x70, 0x84, 0x72, 0x84, 0x74, + 0x85, 0x72, 0x85, 0x74, 0x85, 0x76, 0x84, 0x76, 0x84, 0x77, 0x84, 0x78, + 0x85, 0x78, 0x84, 0x79, 0x84, 0x78, 0x84, 0x77, 0x86, 0x71, 0x87, 0x6f, + 0x89, 0x6f, 0x8a, 0x6f, 0x89, 0x6e, 0x8b, 0x6c, 0x8a, 0x6c, 0x8a, 0x6d, + 0x8a, 0x70, 0x89, 0x71, 0x88, 0x71, 0x87, 0x73, 0x86, 0x74, 0x86, 0x74, + 0x86, 0x74, 0x86, 0x73, 0x87, 0x71, 0x87, 0x6d, 0x8a, 0x64, 0x8f, 0x5c, + 0x8e, 0x62, 0x90, 0x53, 0x96, 0x57, 0x95, 0x66, 0x92, 0x65, 0x94, 0x5e, + 0x95, 0x59, 0x99, 0x52, 0x99, 0x49, 0x9b, 0x48, 0x96, 0x5b, 0x94, 0x54, + 0x99, 0x4a, 0x99, 0x52, 0x99, 0x51, 0x9a, 0x49, 0x9a, 0x3e, 0x99, 0x3e, + 0x92, 0x49, 0x96, 0x4b, 0x9e, 0x3f, 0x9e, 0x36, 0x9a, 0x4b, 0x9a, 0x3b, + 0x9a, 0x36, 0x95, 0x40, 0x8d, 0x51, 0x93, 0x46, 0x96, 0x43, 0x8d, 0x51, + 0x8d, 0x55, 0x8f, 0x58, 0x85, 0x6b, 0x7c, 0x7c, 0x74, 0x83, 0x66, 0x82, + 0x57, 0x7d, 0x5a, 0x78, 0x5f, 0x7b, 0x65, 0x7a, 0x6b, 0x75, 0x69, 0x6e, + 0x66, 0x6d, 0x61, 0x74, 0x5e, 0x77, 0x5f, 0x79, 0x65, 0x77, 0x67, 0x76, + 0x67, 0x73, 0x67, 0x70, 0x70, 0x72, 0x87, 0x5f, 0x8c, 0x56, 0x8d, 0x51, + 0x8c, 0x4c, 0x8a, 0x4c, 0x8a, 0x4f, 0x8a, 0x4e, 0x89, 0x4b, 0x89, 0x49, + 0x8c, 0x45, 0x89, 0x4c, 0x88, 0x4f, 0x88, 0x4f, 0x89, 0x52, 0x8b, 0x51, + 0x8f, 0x45, 0x91, 0x43, 0x93, 0x47, 0x93, 0x49, 0x93, 0x49, 0x93, 0x48, + 0x93, 0x46, 0x91, 0x42, 0x8e, 0x46, 0x8d, 0x49, 0x8e, 0x49, 0x91, 0x4a, + 0x91, 0x4a, 0x8f, 0x4b, 0x8f, 0x4a, 0x8f, 0x4a, 0x8f, 0x4b, 0x8f, 0x4e, + 0x8f, 0x4c, 0x8f, 0x4a, 0x90, 0x4b, 0x90, 0x4a, 0x91, 0x48, 0x92, 0x45, + 0x94, 0x45, 0x93, 0x45, 0x94, 0x43, 0x97, 0x3e, 0x63, 0x6a, 0x5f, 0x6a, + 0x5c, 0x68, 0x53, 0x67, 0x4f, 0x67, 0x4f, 0x66, 0x50, 0x65, 0x52, 0x64, + 0x54, 0x62, 0x54, 0x61, 0x54, 0x60, 0x54, 0x5f, 0x54, 0x5d, 0x54, 0x5d, + 0x54, 0x5e, 0x54, 0x5c, 0x53, 0x5c, 0x54, 0x59, 0x54, 0x5b, 0x52, 0x5b, + 0x4e, 0x5f, 0x51, 0x62, 0x58, 0x64, 0x60, 0x66, 0x63, 0x67, 0x63, 0x68, + 0x66, 0x68, 0x6c, 0x67, 0x7b, 0x68, 0x84, 0x6b, 0x87, 0x70, 0x87, 0x73, + 0x86, 0x74, 0x84, 0x74, 0x84, 0x74, 0x85, 0x75, 0x85, 0x74, 0x84, 0x74, + 0x85, 0x76, 0x84, 0x76, 0x84, 0x77, 0x85, 0x78, 0x84, 0x79, 0x83, 0x7a, + 0x83, 0x79, 0x84, 0x78, 0x83, 0x76, 0x85, 0x76, 0x88, 0x77, 0x87, 0x75, + 0x86, 0x75, 0x87, 0x73, 0x87, 0x72, 0x87, 0x70, 0x88, 0x70, 0x88, 0x70, + 0x87, 0x6f, 0x87, 0x71, 0x86, 0x74, 0x86, 0x74, 0x85, 0x75, 0x85, 0x75, + 0x86, 0x73, 0x86, 0x70, 0x87, 0x6c, 0x89, 0x62, 0x8e, 0x5e, 0x91, 0x58, + 0x96, 0x55, 0x92, 0x6a, 0x90, 0x69, 0x91, 0x61, 0x93, 0x5b, 0x96, 0x5a, + 0x98, 0x4b, 0x9a, 0x47, 0x98, 0x58, 0x92, 0x63, 0x96, 0x4e, 0x9a, 0x50, + 0x9a, 0x53, 0x98, 0x4f, 0x99, 0x46, 0x99, 0x3f, 0x94, 0x43, 0x94, 0x4a, + 0x9e, 0x40, 0xa0, 0x36, 0x9c, 0x44, 0x9a, 0x48, 0x9c, 0x3b, 0x96, 0x3f, + 0x8c, 0x50, 0x91, 0x48, 0x96, 0x41, 0x91, 0x4a, 0x8f, 0x51, 0x94, 0x4b, + 0x8e, 0x57, 0x7d, 0x75, 0x70, 0x86, 0x60, 0x84, 0x57, 0x7c, 0x5b, 0x77, + 0x5e, 0x7c, 0x65, 0x7b, 0x6a, 0x74, 0x68, 0x6e, 0x63, 0x6f, 0x60, 0x76, + 0x5e, 0x78, 0x63, 0x79, 0x67, 0x76, 0x66, 0x74, 0x66, 0x73, 0x69, 0x73, + 0x76, 0x6e, 0x8b, 0x59, 0x8f, 0x53, 0x8d, 0x4e, 0x8b, 0x4d, 0x89, 0x4d, + 0x89, 0x4e, 0x8a, 0x4d, 0x8a, 0x4b, 0x8c, 0x48, 0x8d, 0x44, 0x8a, 0x49, + 0x8a, 0x4f, 0x8a, 0x4e, 0x8a, 0x51, 0x8a, 0x51, 0x8d, 0x4b, 0x91, 0x44, + 0x92, 0x43, 0x94, 0x43, 0x95, 0x44, 0x96, 0x44, 0x96, 0x43, 0x93, 0x42, + 0x8e, 0x48, 0x8e, 0x49, 0x8f, 0x49, 0x90, 0x4a, 0x90, 0x4a, 0x91, 0x4a, + 0x91, 0x4a, 0x90, 0x49, 0x8f, 0x4c, 0x8f, 0x4d, 0x8f, 0x4c, 0x90, 0x4a, + 0x91, 0x4b, 0x91, 0x4a, 0x92, 0x47, 0x92, 0x46, 0x92, 0x47, 0x93, 0x47, + 0x94, 0x45, 0x97, 0x40, 0x60, 0x6a, 0x5e, 0x6a, 0x5a, 0x69, 0x52, 0x66, + 0x4d, 0x66, 0x4e, 0x67, 0x50, 0x66, 0x50, 0x65, 0x53, 0x63, 0x53, 0x62, + 0x54, 0x61, 0x54, 0x5f, 0x54, 0x5f, 0x54, 0x5d, 0x54, 0x5f, 0x54, 0x5d, + 0x54, 0x5d, 0x54, 0x5a, 0x54, 0x5a, 0x51, 0x5a, 0x4d, 0x5f, 0x52, 0x63, + 0x58, 0x65, 0x5f, 0x67, 0x5f, 0x67, 0x67, 0x67, 0x74, 0x68, 0x7f, 0x6b, + 0x86, 0x70, 0x86, 0x72, 0x85, 0x73, 0x85, 0x72, 0x86, 0x75, 0x85, 0x75, + 0x84, 0x75, 0x84, 0x74, 0x85, 0x75, 0x84, 0x75, 0x84, 0x77, 0x85, 0x77, + 0x84, 0x77, 0x84, 0x76, 0x83, 0x76, 0x82, 0x76, 0x83, 0x76, 0x85, 0x77, + 0x85, 0x75, 0x86, 0x73, 0x86, 0x73, 0x86, 0x74, 0x86, 0x74, 0x87, 0x75, + 0x87, 0x75, 0x87, 0x73, 0x87, 0x73, 0x87, 0x72, 0x87, 0x72, 0x87, 0x73, + 0x87, 0x73, 0x86, 0x73, 0x85, 0x75, 0x86, 0x75, 0x87, 0x73, 0x87, 0x70, + 0x87, 0x6d, 0x87, 0x6b, 0x8c, 0x61, 0x8e, 0x5e, 0x94, 0x52, 0x93, 0x60, + 0x90, 0x6a, 0x90, 0x65, 0x92, 0x61, 0x95, 0x5c, 0x97, 0x54, 0x98, 0x4b, + 0x9a, 0x4d, 0x95, 0x61, 0x93, 0x5f, 0x99, 0x49, 0x9a, 0x49, 0x98, 0x54, + 0x98, 0x50, 0x9a, 0x47, 0x98, 0x3d, 0x95, 0x44, 0x9b, 0x44, 0xa3, 0x38, + 0x9f, 0x39, 0x97, 0x52, 0x96, 0x4f, 0x95, 0x45, 0x8c, 0x4e, 0x8f, 0x4a, + 0x94, 0x43, 0x94, 0x44, 0x93, 0x4b, 0x96, 0x46, 0x95, 0x4b, 0x7a, 0x72, + 0x63, 0x8a, 0x59, 0x85, 0x5b, 0x7b, 0x5c, 0x79, 0x60, 0x7d, 0x67, 0x7b, + 0x68, 0x72, 0x66, 0x6e, 0x62, 0x72, 0x60, 0x77, 0x5f, 0x79, 0x65, 0x78, + 0x68, 0x76, 0x66, 0x73, 0x68, 0x73, 0x6e, 0x73, 0x80, 0x63, 0x8f, 0x52, + 0x8f, 0x4f, 0x8d, 0x4a, 0x8a, 0x4d, 0x89, 0x4d, 0x89, 0x4c, 0x89, 0x4c, + 0x8b, 0x4a, 0x8d, 0x45, 0x8e, 0x41, 0x8b, 0x44, 0x8a, 0x4d, 0x8b, 0x4e, + 0x8b, 0x51, 0x8a, 0x51, 0x8c, 0x4e, 0x8e, 0x48, 0x91, 0x43, 0x94, 0x41, + 0x95, 0x41, 0x95, 0x43, 0x95, 0x45, 0x92, 0x47, 0x8e, 0x4b, 0x8f, 0x4a, + 0x8f, 0x4a, 0x8f, 0x4b, 0x90, 0x4a, 0x91, 0x48, 0x92, 0x49, 0x91, 0x49, + 0x90, 0x4b, 0x90, 0x4b, 0x90, 0x4a, 0x91, 0x4a, 0x91, 0x49, 0x92, 0x49, + 0x91, 0x49, 0x91, 0x49, 0x91, 0x48, 0x92, 0x48, 0x93, 0x46, 0x95, 0x43, + 0x5f, 0x6a, 0x5d, 0x6a, 0x5b, 0x69, 0x52, 0x66, 0x4d, 0x66, 0x4e, 0x67, + 0x50, 0x66, 0x50, 0x65, 0x52, 0x63, 0x53, 0x62, 0x53, 0x61, 0x54, 0x5f, + 0x54, 0x5f, 0x54, 0x5e, 0x54, 0x5c, 0x54, 0x5d, 0x54, 0x5d, 0x54, 0x5a, + 0x54, 0x5a, 0x52, 0x5a, 0x4e, 0x60, 0x54, 0x63, 0x5a, 0x65, 0x5e, 0x67, + 0x61, 0x67, 0x77, 0x69, 0x82, 0x6f, 0x86, 0x73, 0x86, 0x74, 0x86, 0x74, + 0x86, 0x72, 0x86, 0x72, 0x86, 0x75, 0x86, 0x75, 0x84, 0x75, 0x84, 0x74, + 0x85, 0x75, 0x85, 0x75, 0x84, 0x77, 0x84, 0x78, 0x84, 0x77, 0x84, 0x76, + 0x83, 0x77, 0x82, 0x77, 0x83, 0x77, 0x84, 0x78, 0x84, 0x77, 0x84, 0x76, + 0x85, 0x76, 0x84, 0x76, 0x84, 0x76, 0x86, 0x74, 0x87, 0x74, 0x87, 0x73, + 0x87, 0x73, 0x87, 0x73, 0x87, 0x74, 0x87, 0x74, 0x87, 0x73, 0x86, 0x74, + 0x85, 0x75, 0x86, 0x75, 0x87, 0x73, 0x87, 0x70, 0x87, 0x70, 0x87, 0x71, + 0x89, 0x68, 0x8b, 0x5f, 0x93, 0x54, 0x94, 0x56, 0x90, 0x67, 0x90, 0x68, + 0x91, 0x64, 0x93, 0x5f, 0x95, 0x59, 0x97, 0x52, 0x99, 0x48, 0x99, 0x51, + 0x93, 0x67, 0x95, 0x52, 0x98, 0x48, 0x97, 0x52, 0x96, 0x53, 0x98, 0x4d, + 0x9b, 0x40, 0x99, 0x3c, 0x98, 0x45, 0xa2, 0x38, 0xa2, 0x33, 0x99, 0x4d, + 0x95, 0x54, 0x96, 0x46, 0x8c, 0x4c, 0x8f, 0x4b, 0x92, 0x45, 0x94, 0x42, + 0x95, 0x45, 0x98, 0x44, 0x96, 0x4c, 0x72, 0x77, 0x57, 0x8a, 0x56, 0x82, + 0x5d, 0x7b, 0x5e, 0x7b, 0x63, 0x7e, 0x6a, 0x7a, 0x68, 0x6f, 0x64, 0x70, + 0x62, 0x73, 0x61, 0x77, 0x62, 0x79, 0x66, 0x79, 0x67, 0x75, 0x65, 0x73, + 0x6a, 0x73, 0x74, 0x71, 0x87, 0x59, 0x8e, 0x4e, 0x8e, 0x4b, 0x8d, 0x46, + 0x8a, 0x4c, 0x89, 0x4b, 0x89, 0x4a, 0x89, 0x4b, 0x8b, 0x4a, 0x8d, 0x41, + 0x8f, 0x3d, 0x8d, 0x40, 0x8a, 0x4b, 0x8b, 0x4f, 0x8b, 0x53, 0x8b, 0x53, + 0x8a, 0x50, 0x8c, 0x4d, 0x8f, 0x48, 0x92, 0x44, 0x93, 0x45, 0x92, 0x48, + 0x91, 0x4b, 0x8f, 0x4d, 0x8f, 0x4d, 0x8f, 0x4b, 0x8f, 0x4b, 0x90, 0x4b, + 0x90, 0x4b, 0x91, 0x49, 0x91, 0x49, 0x90, 0x48, 0x90, 0x49, 0x91, 0x49, + 0x92, 0x49, 0x92, 0x48, 0x91, 0x47, 0x91, 0x48, 0x91, 0x49, 0x91, 0x49, + 0x92, 0x4a, 0x91, 0x49, 0x91, 0x46, 0x94, 0x46, 0x5e, 0x6a, 0x5c, 0x69, + 0x59, 0x67, 0x51, 0x66, 0x4c, 0x67, 0x4c, 0x66, 0x4f, 0x66, 0x4f, 0x66, + 0x51, 0x64, 0x52, 0x63, 0x53, 0x61, 0x54, 0x5f, 0x54, 0x60, 0x54, 0x5f, + 0x54, 0x5c, 0x55, 0x5b, 0x55, 0x5a, 0x54, 0x59, 0x54, 0x5a, 0x52, 0x5a, + 0x4e, 0x60, 0x53, 0x62, 0x5b, 0x64, 0x64, 0x65, 0x71, 0x68, 0x83, 0x70, + 0x85, 0x73, 0x84, 0x75, 0x84, 0x74, 0x85, 0x73, 0x85, 0x73, 0x85, 0x73, + 0x85, 0x75, 0x85, 0x75, 0x84, 0x74, 0x84, 0x75, 0x85, 0x76, 0x85, 0x76, + 0x85, 0x78, 0x85, 0x78, 0x84, 0x78, 0x83, 0x78, 0x83, 0x78, 0x82, 0x79, + 0x83, 0x79, 0x84, 0x78, 0x84, 0x78, 0x84, 0x78, 0x84, 0x78, 0x84, 0x79, + 0x84, 0x78, 0x85, 0x77, 0x85, 0x77, 0x86, 0x74, 0x86, 0x73, 0x87, 0x73, + 0x87, 0x72, 0x87, 0x72, 0x88, 0x73, 0x86, 0x73, 0x85, 0x73, 0x86, 0x74, + 0x87, 0x73, 0x87, 0x71, 0x87, 0x70, 0x87, 0x70, 0x88, 0x6c, 0x89, 0x66, + 0x8e, 0x5b, 0x95, 0x50, 0x92, 0x5f, 0x8f, 0x6a, 0x8f, 0x65, 0x92, 0x61, + 0x94, 0x5c, 0x96, 0x57, 0x97, 0x4b, 0x98, 0x48, 0x96, 0x59, 0x93, 0x61, + 0x96, 0x54, 0x97, 0x4d, 0x96, 0x54, 0x98, 0x52, 0x9a, 0x47, 0x9c, 0x3b, + 0x99, 0x3f, 0x9c, 0x3d, 0xa1, 0x33, 0x9a, 0x48, 0x96, 0x50, 0x99, 0x41, + 0x8d, 0x4a, 0x8f, 0x4a, 0x91, 0x46, 0x94, 0x42, 0x97, 0x42, 0x98, 0x42, + 0x8f, 0x52, 0x66, 0x81, 0x54, 0x86, 0x55, 0x81, 0x5b, 0x7c, 0x5f, 0x7d, + 0x64, 0x7d, 0x6a, 0x76, 0x68, 0x6e, 0x62, 0x72, 0x61, 0x76, 0x61, 0x77, + 0x61, 0x7a, 0x66, 0x79, 0x66, 0x74, 0x64, 0x73, 0x6c, 0x73, 0x7e, 0x64, + 0x8d, 0x52, 0x8f, 0x4b, 0x8f, 0x46, 0x8e, 0x46, 0x8b, 0x49, 0x8b, 0x49, + 0x8a, 0x49, 0x8a, 0x49, 0x8b, 0x48, 0x8e, 0x41, 0x90, 0x3c, 0x8e, 0x41, + 0x8b, 0x4a, 0x8a, 0x50, 0x8a, 0x55, 0x8a, 0x54, 0x8b, 0x50, 0x8c, 0x4d, + 0x8d, 0x4a, 0x8f, 0x4b, 0x90, 0x4c, 0x8f, 0x4f, 0x8e, 0x51, 0x8d, 0x50, + 0x8e, 0x4d, 0x8f, 0x4a, 0x8f, 0x49, 0x91, 0x49, 0x91, 0x4a, 0x92, 0x49, + 0x92, 0x49, 0x91, 0x48, 0x90, 0x49, 0x91, 0x49, 0x93, 0x48, 0x92, 0x47, + 0x92, 0x46, 0x92, 0x46, 0x91, 0x48, 0x92, 0x48, 0x92, 0x49, 0x92, 0x49, + 0x91, 0x46, 0x92, 0x47, 0x5d, 0x6b, 0x5b, 0x68, 0x57, 0x66, 0x4f, 0x66, + 0x4a, 0x67, 0x4b, 0x64, 0x4d, 0x65, 0x4f, 0x65, 0x50, 0x65, 0x50, 0x63, + 0x52, 0x61, 0x53, 0x5f, 0x53, 0x5e, 0x54, 0x5e, 0x54, 0x5c, 0x56, 0x59, + 0x56, 0x57, 0x55, 0x57, 0x53, 0x5a, 0x50, 0x5a, 0x4e, 0x60, 0x53, 0x62, + 0x5c, 0x60, 0x79, 0x66, 0x84, 0x6e, 0x84, 0x75, 0x85, 0x75, 0x85, 0x75, + 0x85, 0x75, 0x84, 0x74, 0x84, 0x75, 0x84, 0x75, 0x84, 0x75, 0x84, 0x75, + 0x84, 0x76, 0x85, 0x76, 0x85, 0x78, 0x85, 0x78, 0x85, 0x79, 0x85, 0x78, + 0x83, 0x78, 0x83, 0x78, 0x83, 0x78, 0x83, 0x78, 0x83, 0x78, 0x83, 0x78, + 0x84, 0x78, 0x85, 0x78, 0x84, 0x78, 0x85, 0x78, 0x85, 0x78, 0x84, 0x78, + 0x84, 0x78, 0x84, 0x77, 0x85, 0x77, 0x86, 0x75, 0x86, 0x73, 0x87, 0x70, + 0x88, 0x70, 0x87, 0x71, 0x86, 0x71, 0x86, 0x72, 0x87, 0x72, 0x87, 0x71, + 0x87, 0x70, 0x87, 0x70, 0x88, 0x6c, 0x87, 0x6b, 0x8a, 0x65, 0x91, 0x51, + 0x92, 0x53, 0x8f, 0x68, 0x8f, 0x67, 0x91, 0x63, 0x93, 0x5f, 0x95, 0x5b, + 0x96, 0x53, 0x97, 0x4a, 0x99, 0x48, 0x96, 0x59, 0x95, 0x5c, 0x97, 0x4b, + 0x98, 0x4f, 0x96, 0x54, 0x98, 0x4e, 0x9b, 0x41, 0x9c, 0x39, 0x99, 0x41, + 0x9e, 0x37, 0x9b, 0x44, 0x97, 0x51, 0x9a, 0x3e, 0x91, 0x48, 0x8f, 0x4a, + 0x91, 0x46, 0x94, 0x42, 0x98, 0x3f, 0x96, 0x44, 0x82, 0x62, 0x5a, 0x88, + 0x55, 0x83, 0x57, 0x80, 0x5b, 0x7d, 0x60, 0x7f, 0x65, 0x7b, 0x66, 0x72, + 0x66, 0x6e, 0x5e, 0x75, 0x60, 0x79, 0x63, 0x79, 0x60, 0x7b, 0x64, 0x79, + 0x62, 0x73, 0x60, 0x76, 0x6f, 0x72, 0x87, 0x56, 0x91, 0x4b, 0x90, 0x45, + 0x90, 0x41, 0x8f, 0x44, 0x8d, 0x45, 0x8e, 0x45, 0x8c, 0x46, 0x8c, 0x46, + 0x8d, 0x44, 0x8f, 0x40, 0x90, 0x3c, 0x8e, 0x43, 0x8c, 0x4d, 0x8a, 0x51, + 0x8a, 0x56, 0x8b, 0x54, 0x8b, 0x50, 0x8d, 0x4c, 0x8d, 0x4b, 0x8d, 0x4d, + 0x8d, 0x4f, 0x8d, 0x51, 0x8d, 0x52, 0x8d, 0x4f, 0x8e, 0x4b, 0x90, 0x48, + 0x90, 0x46, 0x92, 0x47, 0x92, 0x49, 0x92, 0x49, 0x92, 0x48, 0x92, 0x48, + 0x92, 0x48, 0x93, 0x48, 0x93, 0x46, 0x93, 0x44, 0x95, 0x44, 0x94, 0x44, + 0x93, 0x45, 0x93, 0x46, 0x93, 0x46, 0x93, 0x46, 0x93, 0x45, 0x93, 0x45, + 0x5a, 0x6b, 0x57, 0x68, 0x55, 0x66, 0x4d, 0x66, 0x48, 0x65, 0x4a, 0x62, + 0x4d, 0x63, 0x4f, 0x63, 0x50, 0x63, 0x51, 0x61, 0x52, 0x60, 0x53, 0x5f, + 0x53, 0x5d, 0x54, 0x5c, 0x54, 0x5a, 0x56, 0x59, 0x56, 0x57, 0x55, 0x57, + 0x52, 0x5a, 0x50, 0x5a, 0x4d, 0x60, 0x53, 0x64, 0x67, 0x61, 0x83, 0x6d, + 0x86, 0x73, 0x84, 0x76, 0x85, 0x76, 0x85, 0x76, 0x85, 0x76, 0x85, 0x76, + 0x85, 0x76, 0x85, 0x76, 0x84, 0x75, 0x84, 0x75, 0x84, 0x78, 0x85, 0x78, + 0x85, 0x77, 0x84, 0x78, 0x84, 0x78, 0x84, 0x78, 0x83, 0x78, 0x83, 0x78, + 0x83, 0x78, 0x83, 0x78, 0x83, 0x78, 0x82, 0x78, 0x84, 0x78, 0x85, 0x78, + 0x84, 0x78, 0x84, 0x78, 0x85, 0x78, 0x85, 0x77, 0x85, 0x76, 0x85, 0x77, + 0x85, 0x77, 0x85, 0x77, 0x85, 0x74, 0x85, 0x71, 0x86, 0x6f, 0x87, 0x70, + 0x87, 0x70, 0x87, 0x71, 0x87, 0x72, 0x87, 0x72, 0x87, 0x70, 0x87, 0x70, + 0x88, 0x6e, 0x89, 0x6c, 0x89, 0x69, 0x8d, 0x5c, 0x8f, 0x54, 0x90, 0x65, + 0x8f, 0x6a, 0x92, 0x64, 0x92, 0x61, 0x93, 0x5e, 0x95, 0x59, 0x96, 0x51, + 0x97, 0x48, 0x99, 0x4a, 0x99, 0x52, 0x97, 0x4e, 0x97, 0x47, 0x95, 0x52, + 0x97, 0x53, 0x9a, 0x4a, 0x9b, 0x39, 0x9b, 0x3f, 0x9b, 0x3d, 0x9d, 0x3e, + 0x97, 0x4f, 0x9a, 0x3d, 0x94, 0x44, 0x90, 0x4a, 0x91, 0x46, 0x94, 0x42, + 0x97, 0x3e, 0x91, 0x4c, 0x75, 0x73, 0x58, 0x88, 0x57, 0x84, 0x59, 0x81, + 0x5d, 0x7f, 0x61, 0x80, 0x65, 0x79, 0x63, 0x71, 0x63, 0x70, 0x5b, 0x77, + 0x5e, 0x7a, 0x66, 0x7a, 0x5f, 0x79, 0x62, 0x77, 0x5f, 0x75, 0x5e, 0x7a, + 0x73, 0x6e, 0x8b, 0x50, 0x92, 0x47, 0x90, 0x42, 0x90, 0x3e, 0x8f, 0x41, + 0x8f, 0x42, 0x8f, 0x42, 0x8e, 0x44, 0x8e, 0x44, 0x8f, 0x41, 0x91, 0x3d, + 0x91, 0x3b, 0x8e, 0x43, 0x8c, 0x4e, 0x8a, 0x53, 0x8a, 0x56, 0x8b, 0x54, + 0x8b, 0x51, 0x8d, 0x4e, 0x8d, 0x4d, 0x8d, 0x4f, 0x8d, 0x51, 0x8d, 0x51, + 0x8e, 0x4f, 0x8f, 0x4d, 0x90, 0x49, 0x90, 0x47, 0x90, 0x44, 0x91, 0x45, + 0x91, 0x48, 0x92, 0x49, 0x92, 0x49, 0x92, 0x47, 0x93, 0x47, 0x94, 0x46, + 0x94, 0x43, 0x95, 0x41, 0x96, 0x41, 0x96, 0x42, 0x95, 0x44, 0x94, 0x44, + 0x94, 0x43, 0x94, 0x44, 0x95, 0x44, 0x95, 0x44, 0x57, 0x6a, 0x54, 0x68, + 0x52, 0x66, 0x4a, 0x65, 0x47, 0x65, 0x49, 0x63, 0x4c, 0x62, 0x4e, 0x62, + 0x50, 0x62, 0x51, 0x61, 0x52, 0x5f, 0x52, 0x5e, 0x53, 0x5d, 0x55, 0x59, + 0x55, 0x58, 0x55, 0x58, 0x55, 0x56, 0x55, 0x56, 0x52, 0x58, 0x50, 0x59, + 0x4f, 0x5f, 0x5c, 0x60, 0x7c, 0x69, 0x83, 0x74, 0x84, 0x75, 0x85, 0x78, + 0x85, 0x78, 0x85, 0x78, 0x85, 0x78, 0x85, 0x78, 0x85, 0x77, 0x85, 0x77, + 0x85, 0x77, 0x85, 0x77, 0x85, 0x78, 0x85, 0x78, 0x84, 0x78, 0x84, 0x78, + 0x83, 0x79, 0x83, 0x79, 0x83, 0x79, 0x83, 0x79, 0x83, 0x79, 0x82, 0x78, + 0x83, 0x78, 0x83, 0x78, 0x84, 0x78, 0x85, 0x78, 0x85, 0x78, 0x84, 0x77, + 0x84, 0x78, 0x84, 0x75, 0x84, 0x76, 0x84, 0x74, 0x85, 0x74, 0x85, 0x75, + 0x84, 0x74, 0x85, 0x73, 0x85, 0x73, 0x86, 0x71, 0x87, 0x6f, 0x87, 0x70, + 0x87, 0x70, 0x88, 0x70, 0x87, 0x70, 0x87, 0x70, 0x88, 0x6f, 0x88, 0x6d, + 0x88, 0x6a, 0x89, 0x64, 0x8c, 0x5e, 0x91, 0x5e, 0x90, 0x67, 0x91, 0x66, + 0x91, 0x61, 0x92, 0x60, 0x93, 0x5c, 0x94, 0x56, 0x96, 0x50, 0x97, 0x46, + 0x99, 0x46, 0x99, 0x50, 0x96, 0x49, 0x96, 0x4f, 0x96, 0x57, 0x97, 0x55, + 0x9a, 0x43, 0x9b, 0x39, 0x97, 0x44, 0x9d, 0x3a, 0x9a, 0x4a, 0x9a, 0x3e, + 0x96, 0x3e, 0x90, 0x4a, 0x91, 0x47, 0x93, 0x44, 0x97, 0x40, 0x7f, 0x64, + 0x61, 0x84, 0x58, 0x85, 0x5a, 0x83, 0x5b, 0x80, 0x5e, 0x80, 0x63, 0x80, + 0x65, 0x76, 0x62, 0x6f, 0x5f, 0x73, 0x5a, 0x79, 0x5f, 0x7b, 0x66, 0x7b, + 0x61, 0x78, 0x5f, 0x75, 0x5c, 0x76, 0x5d, 0x7a, 0x7d, 0x62, 0x8f, 0x49, + 0x92, 0x43, 0x90, 0x3f, 0x91, 0x3d, 0x90, 0x3e, 0x91, 0x3f, 0x91, 0x3f, + 0x90, 0x41, 0x90, 0x40, 0x90, 0x3e, 0x91, 0x3b, 0x91, 0x3b, 0x8e, 0x43, + 0x8b, 0x51, 0x8a, 0x55, 0x8a, 0x57, 0x8b, 0x55, 0x8c, 0x52, 0x8d, 0x4f, + 0x8d, 0x4e, 0x8e, 0x50, 0x8d, 0x51, 0x8d, 0x50, 0x8e, 0x4d, 0x90, 0x4a, + 0x90, 0x4a, 0x8f, 0x47, 0x91, 0x41, 0x92, 0x42, 0x92, 0x45, 0x93, 0x48, + 0x93, 0x47, 0x94, 0x45, 0x95, 0x43, 0x95, 0x42, 0x96, 0x3f, 0x96, 0x3e, + 0x97, 0x3d, 0x97, 0x3f, 0x96, 0x42, 0x96, 0x41, 0x96, 0x40, 0x96, 0x41, + 0x96, 0x42, 0x97, 0x43, 0x55, 0x6a, 0x53, 0x67, 0x51, 0x64, 0x49, 0x64, + 0x46, 0x64, 0x49, 0x65, 0x4c, 0x62, 0x4e, 0x62, 0x4f, 0x60, 0x50, 0x60, + 0x51, 0x5f, 0x51, 0x5e, 0x52, 0x5d, 0x55, 0x57, 0x55, 0x56, 0x54, 0x56, + 0x54, 0x58, 0x55, 0x55, 0x52, 0x57, 0x52, 0x59, 0x55, 0x5b, 0x73, 0x62, + 0x83, 0x71, 0x84, 0x74, 0x85, 0x75, 0x85, 0x78, 0x85, 0x77, 0x85, 0x77, + 0x85, 0x77, 0x85, 0x78, 0x85, 0x77, 0x85, 0x77, 0x85, 0x79, 0x84, 0x78, + 0x84, 0x78, 0x84, 0x78, 0x83, 0x7a, 0x82, 0x7a, 0x82, 0x7a, 0x82, 0x7a, + 0x83, 0x7b, 0x83, 0x7a, 0x83, 0x7a, 0x83, 0x77, 0x84, 0x78, 0x84, 0x77, + 0x85, 0x77, 0x86, 0x79, 0x85, 0x78, 0x84, 0x77, 0x84, 0x77, 0x84, 0x77, + 0x84, 0x77, 0x85, 0x75, 0x86, 0x75, 0x86, 0x73, 0x86, 0x72, 0x85, 0x73, + 0x85, 0x73, 0x86, 0x72, 0x87, 0x70, 0x88, 0x6f, 0x88, 0x6d, 0x87, 0x6e, + 0x88, 0x70, 0x88, 0x70, 0x88, 0x6e, 0x88, 0x6c, 0x89, 0x6a, 0x8a, 0x68, + 0x8b, 0x63, 0x8e, 0x58, 0x90, 0x5f, 0x90, 0x65, 0x92, 0x62, 0x93, 0x5f, + 0x92, 0x5d, 0x93, 0x58, 0x95, 0x52, 0x97, 0x4a, 0x98, 0x44, 0x98, 0x4a, + 0x97, 0x4b, 0x97, 0x4b, 0x96, 0x57, 0x95, 0x57, 0x99, 0x4c, 0x9a, 0x3a, + 0x96, 0x44, 0x9c, 0x3b, 0x9d, 0x44, 0x99, 0x44, 0x96, 0x3b, 0x90, 0x4a, + 0x91, 0x48, 0x93, 0x45, 0x97, 0x47, 0x6e, 0x79, 0x58, 0x88, 0x57, 0x85, + 0x59, 0x82, 0x5c, 0x80, 0x60, 0x81, 0x64, 0x7f, 0x65, 0x74, 0x62, 0x6e, + 0x5d, 0x75, 0x5c, 0x7a, 0x60, 0x7a, 0x64, 0x7b, 0x62, 0x78, 0x5f, 0x75, + 0x5c, 0x77, 0x62, 0x78, 0x87, 0x58, 0x91, 0x45, 0x91, 0x41, 0x92, 0x3e, + 0x91, 0x3e, 0x92, 0x3e, 0x93, 0x3e, 0x93, 0x3f, 0x91, 0x40, 0x91, 0x3f, + 0x91, 0x3c, 0x91, 0x3b, 0x90, 0x3c, 0x8e, 0x43, 0x89, 0x55, 0x89, 0x57, + 0x89, 0x58, 0x8a, 0x55, 0x8c, 0x50, 0x8e, 0x4f, 0x8e, 0x50, 0x8d, 0x50, + 0x8d, 0x50, 0x8f, 0x4f, 0x8f, 0x4c, 0x90, 0x4a, 0x8f, 0x4d, 0x90, 0x49, + 0x92, 0x3f, 0x92, 0x3e, 0x92, 0x43, 0x94, 0x46, 0x94, 0x44, 0x96, 0x43, + 0x95, 0x40, 0x96, 0x3f, 0x97, 0x3e, 0x97, 0x3c, 0x98, 0x3c, 0x98, 0x3f, + 0x97, 0x40, 0x97, 0x3f, 0x97, 0x3e, 0x97, 0x3e, 0x97, 0x3e, 0x97, 0x40, + 0x54, 0x68, 0x51, 0x65, 0x4f, 0x63, 0x4a, 0x63, 0x47, 0x63, 0x49, 0x63, + 0x4b, 0x62, 0x4d, 0x62, 0x50, 0x60, 0x50, 0x60, 0x51, 0x5f, 0x51, 0x5d, + 0x52, 0x5d, 0x53, 0x5b, 0x54, 0x58, 0x54, 0x57, 0x54, 0x5c, 0x53, 0x59, + 0x52, 0x57, 0x52, 0x59, 0x63, 0x5b, 0x80, 0x6e, 0x83, 0x76, 0x85, 0x74, + 0x85, 0x75, 0x85, 0x78, 0x85, 0x77, 0x85, 0x77, 0x85, 0x77, 0x85, 0x77, + 0x85, 0x77, 0x85, 0x77, 0x84, 0x78, 0x85, 0x77, 0x85, 0x77, 0x84, 0x77, + 0x83, 0x7a, 0x83, 0x7a, 0x82, 0x7a, 0x82, 0x7a, 0x82, 0x7a, 0x83, 0x7a, + 0x83, 0x79, 0x83, 0x78, 0x84, 0x78, 0x85, 0x78, 0x85, 0x77, 0x85, 0x76, + 0x86, 0x76, 0x85, 0x75, 0x85, 0x75, 0x85, 0x75, 0x85, 0x75, 0x85, 0x75, + 0x86, 0x75, 0x85, 0x73, 0x85, 0x73, 0x85, 0x72, 0x85, 0x72, 0x86, 0x71, + 0x87, 0x70, 0x87, 0x6f, 0x88, 0x6d, 0x88, 0x6e, 0x88, 0x6f, 0x88, 0x6f, + 0x88, 0x6e, 0x88, 0x6c, 0x89, 0x6b, 0x89, 0x69, 0x8a, 0x66, 0x8d, 0x5c, + 0x90, 0x58, 0x90, 0x5f, 0x92, 0x62, 0x92, 0x5f, 0x92, 0x5d, 0x94, 0x59, + 0x95, 0x55, 0x95, 0x51, 0x96, 0x49, 0x97, 0x46, 0x98, 0x4e, 0x97, 0x48, + 0x96, 0x54, 0x95, 0x58, 0x97, 0x54, 0x99, 0x46, 0x98, 0x41, 0x9a, 0x3f, + 0x9d, 0x3e, 0x98, 0x4a, 0x98, 0x3a, 0x90, 0x4b, 0x90, 0x4c, 0x92, 0x4a, + 0x88, 0x5d, 0x60, 0x85, 0x59, 0x88, 0x58, 0x84, 0x5a, 0x82, 0x5f, 0x82, + 0x66, 0x81, 0x66, 0x7d, 0x62, 0x74, 0x61, 0x73, 0x5d, 0x78, 0x5e, 0x7a, + 0x62, 0x7a, 0x64, 0x7b, 0x62, 0x78, 0x5f, 0x75, 0x62, 0x75, 0x70, 0x6d, + 0x8c, 0x4e, 0x91, 0x42, 0x91, 0x3f, 0x91, 0x3d, 0x91, 0x3e, 0x91, 0x3e, + 0x92, 0x3e, 0x92, 0x3e, 0x92, 0x3e, 0x93, 0x3e, 0x92, 0x3c, 0x91, 0x3c, + 0x90, 0x3c, 0x8e, 0x46, 0x89, 0x56, 0x89, 0x59, 0x8a, 0x57, 0x8c, 0x54, + 0x8e, 0x4e, 0x8f, 0x4d, 0x90, 0x4c, 0x8e, 0x4a, 0x90, 0x4b, 0x91, 0x49, + 0x91, 0x47, 0x91, 0x49, 0x90, 0x4c, 0x8f, 0x48, 0x92, 0x3f, 0x92, 0x3c, + 0x93, 0x41, 0x94, 0x46, 0x95, 0x44, 0x95, 0x41, 0x95, 0x3e, 0x96, 0x3d, + 0x97, 0x3c, 0x97, 0x3b, 0x98, 0x3c, 0x98, 0x3f, 0x97, 0x40, 0x97, 0x3f, + 0x97, 0x3c, 0x97, 0x3c, 0x97, 0x3c, 0x97, 0x3f, 0x52, 0x66, 0x50, 0x64, + 0x4e, 0x62, 0x4b, 0x61, 0x48, 0x61, 0x49, 0x62, 0x4b, 0x61, 0x4c, 0x62, + 0x4f, 0x62, 0x50, 0x61, 0x51, 0x5f, 0x51, 0x5e, 0x52, 0x5d, 0x52, 0x5d, + 0x53, 0x5b, 0x54, 0x5a, 0x54, 0x5a, 0x52, 0x5a, 0x51, 0x58, 0x56, 0x57, + 0x78, 0x66, 0x84, 0x73, 0x85, 0x75, 0x84, 0x74, 0x85, 0x75, 0x85, 0x77, + 0x85, 0x78, 0x85, 0x77, 0x85, 0x77, 0x85, 0x77, 0x85, 0x77, 0x85, 0x77, + 0x84, 0x78, 0x85, 0x78, 0x85, 0x78, 0x84, 0x78, 0x82, 0x79, 0x83, 0x7a, + 0x83, 0x7a, 0x83, 0x7a, 0x83, 0x7a, 0x83, 0x7a, 0x83, 0x79, 0x83, 0x78, + 0x83, 0x78, 0x85, 0x78, 0x85, 0x77, 0x85, 0x75, 0x85, 0x76, 0x86, 0x74, + 0x86, 0x73, 0x87, 0x73, 0x87, 0x73, 0x86, 0x74, 0x86, 0x75, 0x86, 0x74, + 0x86, 0x73, 0x86, 0x72, 0x86, 0x70, 0x86, 0x70, 0x87, 0x70, 0x87, 0x6f, + 0x88, 0x6e, 0x88, 0x6e, 0x88, 0x6d, 0x88, 0x6d, 0x88, 0x6f, 0x88, 0x6d, + 0x89, 0x6d, 0x89, 0x69, 0x89, 0x66, 0x8b, 0x62, 0x8e, 0x58, 0x8f, 0x58, + 0x91, 0x61, 0x93, 0x5f, 0x92, 0x5c, 0x93, 0x5b, 0x94, 0x58, 0x94, 0x57, + 0x95, 0x53, 0x96, 0x49, 0x97, 0x46, 0x96, 0x46, 0x97, 0x50, 0x95, 0x5a, + 0x95, 0x5c, 0x97, 0x53, 0x99, 0x41, 0x97, 0x43, 0x9c, 0x3c, 0x98, 0x4b, + 0x9a, 0x3f, 0x91, 0x4d, 0x8b, 0x58, 0x84, 0x61, 0x6b, 0x7e, 0x5b, 0x8b, + 0x5c, 0x88, 0x5a, 0x85, 0x5b, 0x84, 0x62, 0x84, 0x6c, 0x81, 0x67, 0x7b, + 0x5f, 0x74, 0x5f, 0x78, 0x5d, 0x7a, 0x61, 0x79, 0x63, 0x79, 0x63, 0x7b, + 0x63, 0x77, 0x5f, 0x74, 0x69, 0x71, 0x80, 0x5d, 0x91, 0x45, 0x91, 0x40, + 0x91, 0x3e, 0x91, 0x3d, 0x92, 0x3e, 0x92, 0x3e, 0x93, 0x3f, 0x93, 0x3e, + 0x94, 0x3c, 0x94, 0x3e, 0x92, 0x3d, 0x91, 0x3b, 0x91, 0x3d, 0x8d, 0x4b, + 0x89, 0x58, 0x88, 0x5b, 0x8b, 0x58, 0x8e, 0x52, 0x91, 0x48, 0x92, 0x40, + 0x94, 0x3d, 0x95, 0x3e, 0x95, 0x3e, 0x95, 0x3e, 0x95, 0x3d, 0x94, 0x40, + 0x93, 0x44, 0x91, 0x45, 0x92, 0x40, 0x93, 0x3d, 0x93, 0x40, 0x93, 0x44, + 0x93, 0x44, 0x95, 0x42, 0x96, 0x3d, 0x97, 0x3c, 0x97, 0x3a, 0x98, 0x3b, + 0x98, 0x3d, 0x97, 0x3f, 0x97, 0x40, 0x97, 0x42, 0x96, 0x41, 0x96, 0x40, + 0x97, 0x41, 0x97, 0x42, 0x4f, 0x65, 0x4f, 0x64, 0x4d, 0x62, 0x49, 0x62, + 0x47, 0x62, 0x49, 0x62, 0x4a, 0x60, 0x4c, 0x61, 0x4e, 0x63, 0x50, 0x61, + 0x51, 0x5f, 0x51, 0x5e, 0x52, 0x5c, 0x53, 0x5b, 0x53, 0x5b, 0x53, 0x59, + 0x53, 0x57, 0x52, 0x5a, 0x51, 0x57, 0x5d, 0x56, 0x81, 0x6d, 0x85, 0x73, + 0x86, 0x74, 0x84, 0x75, 0x85, 0x75, 0x85, 0x76, 0x85, 0x78, 0x85, 0x77, + 0x85, 0x77, 0x85, 0x77, 0x84, 0x78, 0x84, 0x78, 0x84, 0x78, 0x85, 0x78, + 0x85, 0x7a, 0x84, 0x7a, 0x82, 0x7a, 0x83, 0x7a, 0x83, 0x7a, 0x83, 0x7a, + 0x83, 0x7a, 0x83, 0x7a, 0x83, 0x79, 0x83, 0x78, 0x84, 0x78, 0x85, 0x78, + 0x85, 0x78, 0x85, 0x77, 0x85, 0x77, 0x85, 0x75, 0x86, 0x73, 0x87, 0x72, + 0x87, 0x72, 0x88, 0x71, 0x88, 0x74, 0x88, 0x73, 0x88, 0x72, 0x88, 0x71, + 0x88, 0x71, 0x87, 0x70, 0x87, 0x6f, 0x87, 0x6f, 0x88, 0x6e, 0x88, 0x6d, + 0x88, 0x6c, 0x87, 0x6c, 0x88, 0x6f, 0x88, 0x6e, 0x89, 0x6d, 0x8a, 0x69, + 0x8a, 0x66, 0x8b, 0x63, 0x8c, 0x5c, 0x8d, 0x56, 0x91, 0x5d, 0x93, 0x5e, + 0x93, 0x5c, 0x92, 0x5b, 0x94, 0x58, 0x95, 0x56, 0x95, 0x55, 0x95, 0x4d, + 0x97, 0x45, 0x96, 0x45, 0x98, 0x4e, 0x96, 0x59, 0x95, 0x5d, 0x95, 0x59, + 0x98, 0x44, 0x96, 0x44, 0x9b, 0x3e, 0x9b, 0x47, 0x9a, 0x47, 0x91, 0x4e, + 0x78, 0x6a, 0x6d, 0x79, 0x5f, 0x88, 0x5c, 0x88, 0x5e, 0x88, 0x63, 0x88, + 0x64, 0x86, 0x65, 0x84, 0x6e, 0x80, 0x65, 0x7a, 0x5e, 0x76, 0x60, 0x79, + 0x5e, 0x7b, 0x62, 0x79, 0x63, 0x7b, 0x63, 0x7b, 0x63, 0x75, 0x61, 0x73, + 0x72, 0x68, 0x89, 0x53, 0x92, 0x43, 0x91, 0x3f, 0x90, 0x3e, 0x92, 0x3e, + 0x94, 0x3e, 0x94, 0x3f, 0x94, 0x40, 0x95, 0x3e, 0x95, 0x3c, 0x93, 0x40, + 0x91, 0x3f, 0x91, 0x3b, 0x91, 0x3e, 0x8c, 0x50, 0x89, 0x59, 0x88, 0x5c, + 0x8c, 0x55, 0x91, 0x4a, 0x95, 0x3f, 0x95, 0x3b, 0x96, 0x39, 0x97, 0x39, + 0x96, 0x3b, 0x95, 0x3c, 0x95, 0x3c, 0x96, 0x3b, 0x96, 0x3d, 0x95, 0x40, + 0x92, 0x42, 0x94, 0x43, 0x94, 0x41, 0x92, 0x41, 0x92, 0x44, 0x96, 0x42, + 0x98, 0x3d, 0x98, 0x39, 0x98, 0x39, 0x98, 0x3a, 0x98, 0x3b, 0x98, 0x3e, + 0x97, 0x41, 0x96, 0x44, 0x95, 0x43, 0x95, 0x42, 0x97, 0x42, 0x97, 0x43, + 0x4a, 0x63, 0x49, 0x63, 0x47, 0x61, 0x47, 0x61, 0x47, 0x62, 0x49, 0x62, + 0x4a, 0x60, 0x4c, 0x61, 0x4e, 0x62, 0x4f, 0x60, 0x51, 0x5f, 0x51, 0x5e, + 0x52, 0x5b, 0x53, 0x5b, 0x53, 0x5b, 0x53, 0x59, 0x53, 0x57, 0x52, 0x58, + 0x57, 0x57, 0x6f, 0x5d, 0x85, 0x71, 0x86, 0x73, 0x86, 0x74, 0x84, 0x76, + 0x84, 0x75, 0x84, 0x76, 0x85, 0x77, 0x85, 0x77, 0x85, 0x77, 0x85, 0x77, + 0x84, 0x78, 0x84, 0x78, 0x85, 0x78, 0x85, 0x78, 0x85, 0x7a, 0x85, 0x7a, + 0x82, 0x7a, 0x82, 0x7a, 0x82, 0x7a, 0x82, 0x7a, 0x82, 0x7a, 0x83, 0x7a, + 0x83, 0x79, 0x83, 0x78, 0x83, 0x78, 0x84, 0x78, 0x85, 0x77, 0x85, 0x77, + 0x85, 0x78, 0x85, 0x75, 0x86, 0x73, 0x87, 0x72, 0x87, 0x72, 0x88, 0x6f, + 0x88, 0x6e, 0x88, 0x6f, 0x88, 0x71, 0x88, 0x70, 0x88, 0x6f, 0x88, 0x6e, + 0x88, 0x6e, 0x87, 0x6d, 0x88, 0x6c, 0x88, 0x6c, 0x88, 0x6c, 0x88, 0x6c, + 0x88, 0x6c, 0x88, 0x6c, 0x89, 0x6b, 0x89, 0x6b, 0x8a, 0x68, 0x8a, 0x65, + 0x8b, 0x61, 0x8e, 0x5b, 0x8f, 0x55, 0x91, 0x59, 0x93, 0x5d, 0x92, 0x5b, + 0x94, 0x59, 0x95, 0x57, 0x95, 0x56, 0x95, 0x51, 0x97, 0x4a, 0x97, 0x44, + 0x95, 0x4a, 0x96, 0x52, 0x95, 0x5d, 0x95, 0x5c, 0x97, 0x48, 0x97, 0x43, + 0x99, 0x40, 0x9c, 0x40, 0x98, 0x4f, 0x8d, 0x4f, 0x63, 0x7e, 0x5b, 0x86, + 0x5b, 0x85, 0x5d, 0x88, 0x60, 0x89, 0x70, 0x89, 0x6f, 0x87, 0x69, 0x84, + 0x6b, 0x80, 0x63, 0x7a, 0x5f, 0x7b, 0x5c, 0x7c, 0x5d, 0x7c, 0x5f, 0x7d, + 0x61, 0x7f, 0x64, 0x7b, 0x64, 0x72, 0x66, 0x6e, 0x82, 0x57, 0x90, 0x49, + 0x93, 0x41, 0x93, 0x3e, 0x92, 0x3d, 0x94, 0x3e, 0x95, 0x3e, 0x95, 0x3e, + 0x94, 0x3e, 0x95, 0x3e, 0x94, 0x3d, 0x92, 0x42, 0x92, 0x44, 0x92, 0x40, + 0x8f, 0x44, 0x8c, 0x55, 0x8a, 0x5b, 0x8d, 0x54, 0x92, 0x45, 0x95, 0x3e, + 0x94, 0x3d, 0x93, 0x40, 0x94, 0x41, 0x95, 0x40, 0x95, 0x41, 0x95, 0x42, + 0x96, 0x42, 0x98, 0x3d, 0x98, 0x3a, 0x96, 0x3c, 0x94, 0x43, 0x94, 0x44, + 0x94, 0x41, 0x94, 0x3f, 0x94, 0x3f, 0x96, 0x3a, 0x98, 0x39, 0x98, 0x39, + 0x98, 0x3b, 0x97, 0x3c, 0x96, 0x3c, 0x96, 0x3f, 0x97, 0x42, 0x96, 0x42, + 0x95, 0x42, 0x96, 0x42, 0x97, 0x41, 0x97, 0x40, 0x45, 0x61, 0x45, 0x61, + 0x44, 0x5f, 0x46, 0x5f, 0x47, 0x61, 0x49, 0x62, 0x4b, 0x60, 0x4c, 0x62, + 0x4e, 0x62, 0x4f, 0x60, 0x51, 0x5f, 0x51, 0x5e, 0x52, 0x5b, 0x53, 0x5b, + 0x53, 0x5b, 0x53, 0x59, 0x53, 0x57, 0x53, 0x56, 0x61, 0x58, 0x7a, 0x66, + 0x86, 0x71, 0x86, 0x72, 0x86, 0x74, 0x84, 0x75, 0x84, 0x75, 0x84, 0x76, + 0x84, 0x78, 0x85, 0x77, 0x85, 0x77, 0x85, 0x77, 0x84, 0x78, 0x84, 0x78, + 0x84, 0x78, 0x85, 0x78, 0x85, 0x7a, 0x85, 0x7a, 0x82, 0x7a, 0x83, 0x7a, + 0x82, 0x7a, 0x83, 0x7a, 0x83, 0x7a, 0x83, 0x7a, 0x82, 0x79, 0x82, 0x78, + 0x83, 0x78, 0x84, 0x78, 0x84, 0x78, 0x85, 0x77, 0x85, 0x77, 0x85, 0x75, + 0x85, 0x73, 0x87, 0x73, 0x87, 0x72, 0x88, 0x71, 0x88, 0x6f, 0x88, 0x6e, + 0x88, 0x6f, 0x88, 0x6e, 0x88, 0x6d, 0x89, 0x6d, 0x8a, 0x6c, 0x88, 0x6b, + 0x88, 0x6a, 0x88, 0x6c, 0x88, 0x6d, 0x88, 0x6c, 0x88, 0x6a, 0x88, 0x6b, + 0x89, 0x69, 0x89, 0x6c, 0x8a, 0x6a, 0x8a, 0x66, 0x8c, 0x61, 0x8e, 0x5f, + 0x8e, 0x55, 0x8f, 0x56, 0x92, 0x5c, 0x92, 0x5c, 0x93, 0x5a, 0x95, 0x58, + 0x96, 0x57, 0x95, 0x53, 0x96, 0x4d, 0x98, 0x44, 0x94, 0x45, 0x97, 0x4c, + 0x95, 0x5c, 0x95, 0x5f, 0x97, 0x4b, 0x97, 0x41, 0x97, 0x40, 0x9d, 0x39, + 0x97, 0x4f, 0x93, 0x4f, 0x66, 0x7f, 0x5b, 0x88, 0x59, 0x82, 0x5e, 0x87, + 0x5f, 0x8a, 0x68, 0x8b, 0x6b, 0x88, 0x66, 0x85, 0x67, 0x7f, 0x61, 0x7a, + 0x61, 0x7e, 0x5a, 0x7f, 0x5b, 0x7c, 0x5e, 0x80, 0x60, 0x82, 0x66, 0x7b, + 0x65, 0x6f, 0x6e, 0x67, 0x8b, 0x4e, 0x92, 0x45, 0x95, 0x3f, 0x95, 0x3d, + 0x94, 0x3d, 0x94, 0x3e, 0x94, 0x3e, 0x95, 0x3d, 0x94, 0x3c, 0x95, 0x3d, + 0x95, 0x3f, 0x93, 0x43, 0x92, 0x49, 0x92, 0x44, 0x8c, 0x4a, 0x8c, 0x58, + 0x8b, 0x58, 0x91, 0x48, 0x94, 0x3d, 0x93, 0x3f, 0x91, 0x43, 0x91, 0x43, + 0x93, 0x43, 0x94, 0x43, 0x94, 0x44, 0x95, 0x44, 0x96, 0x42, 0x99, 0x3e, + 0x99, 0x38, 0x98, 0x3a, 0x95, 0x42, 0x94, 0x44, 0x94, 0x41, 0x95, 0x3e, + 0x95, 0x3b, 0x97, 0x38, 0x98, 0x3b, 0x98, 0x3d, 0x98, 0x40, 0x97, 0x41, + 0x95, 0x42, 0x95, 0x44, 0x97, 0x43, 0x96, 0x41, 0x95, 0x42, 0x95, 0x42, + 0x97, 0x40, 0x97, 0x3f, 0x44, 0x60, 0x43, 0x5e, 0x44, 0x5d, 0x47, 0x5f, + 0x48, 0x60, 0x49, 0x61, 0x4c, 0x60, 0x4d, 0x62, 0x4f, 0x64, 0x50, 0x62, + 0x51, 0x61, 0x51, 0x5f, 0x52, 0x5c, 0x53, 0x5d, 0x53, 0x5d, 0x53, 0x57, + 0x53, 0x55, 0x54, 0x55, 0x6d, 0x5d, 0x83, 0x6c, 0x85, 0x71, 0x86, 0x74, + 0x85, 0x76, 0x85, 0x74, 0x85, 0x75, 0x85, 0x75, 0x85, 0x75, 0x85, 0x76, + 0x85, 0x77, 0x85, 0x77, 0x84, 0x78, 0x84, 0x78, 0x84, 0x78, 0x85, 0x78, + 0x85, 0x78, 0x85, 0x78, 0x84, 0x78, 0x84, 0x79, 0x84, 0x79, 0x84, 0x78, + 0x84, 0x78, 0x84, 0x78, 0x84, 0x78, 0x84, 0x78, 0x84, 0x78, 0x85, 0x78, + 0x84, 0x78, 0x84, 0x78, 0x85, 0x78, 0x85, 0x77, 0x85, 0x76, 0x86, 0x75, + 0x86, 0x75, 0x86, 0x73, 0x86, 0x70, 0x87, 0x6f, 0x88, 0x6d, 0x88, 0x6c, + 0x88, 0x6c, 0x88, 0x6c, 0x89, 0x6b, 0x8a, 0x69, 0x8b, 0x6a, 0x88, 0x6a, + 0x89, 0x6c, 0x89, 0x6b, 0x8a, 0x6b, 0x8a, 0x6b, 0x89, 0x6a, 0x89, 0x6b, + 0x8a, 0x6b, 0x8b, 0x67, 0x8d, 0x63, 0x8e, 0x60, 0x8e, 0x59, 0x8f, 0x53, + 0x90, 0x59, 0x92, 0x5b, 0x94, 0x59, 0x95, 0x58, 0x94, 0x58, 0x95, 0x56, + 0x95, 0x51, 0x97, 0x47, 0x95, 0x43, 0x95, 0x4a, 0x96, 0x59, 0x94, 0x60, + 0x97, 0x4f, 0x96, 0x41, 0x99, 0x40, 0x9e, 0x39, 0x9a, 0x44, 0x97, 0x4f, + 0x73, 0x7b, 0x61, 0x8a, 0x5b, 0x81, 0x5e, 0x85, 0x5c, 0x89, 0x64, 0x8c, + 0x6e, 0x8c, 0x6a, 0x86, 0x63, 0x81, 0x60, 0x80, 0x5d, 0x81, 0x5a, 0x7f, + 0x5c, 0x7e, 0x5d, 0x82, 0x60, 0x81, 0x65, 0x78, 0x68, 0x6f, 0x77, 0x62, + 0x8f, 0x4a, 0x92, 0x44, 0x94, 0x3f, 0x95, 0x3e, 0x95, 0x3f, 0x94, 0x41, + 0x94, 0x40, 0x95, 0x3e, 0x94, 0x3d, 0x94, 0x3f, 0x93, 0x43, 0x90, 0x49, + 0x90, 0x4c, 0x90, 0x46, 0x8e, 0x4c, 0x8d, 0x55, 0x8f, 0x4f, 0x93, 0x40, + 0x92, 0x41, 0x92, 0x44, 0x93, 0x45, 0x94, 0x43, 0x95, 0x42, 0x96, 0x43, + 0x95, 0x45, 0x96, 0x44, 0x97, 0x41, 0x9a, 0x3c, 0x9a, 0x38, 0x9a, 0x38, + 0x99, 0x3f, 0x95, 0x45, 0x94, 0x40, 0x95, 0x3c, 0x96, 0x3c, 0x96, 0x3d, + 0x96, 0x40, 0x95, 0x42, 0x95, 0x44, 0x94, 0x44, 0x94, 0x45, 0x94, 0x46, + 0x96, 0x45, 0x96, 0x43, 0x97, 0x42, 0x97, 0x40, 0x98, 0x40, 0x98, 0x40, + 0x43, 0x60, 0x44, 0x5d, 0x46, 0x5c, 0x47, 0x5e, 0x49, 0x61, 0x4a, 0x61, + 0x4d, 0x60, 0x4e, 0x62, 0x50, 0x64, 0x51, 0x62, 0x51, 0x5f, 0x52, 0x5f, + 0x52, 0x5e, 0x53, 0x5d, 0x54, 0x5d, 0x53, 0x59, 0x53, 0x57, 0x58, 0x56, + 0x7b, 0x63, 0x87, 0x6f, 0x86, 0x72, 0x85, 0x74, 0x85, 0x75, 0x85, 0x75, + 0x86, 0x75, 0x85, 0x75, 0x85, 0x75, 0x85, 0x76, 0x85, 0x77, 0x85, 0x77, + 0x84, 0x78, 0x84, 0x78, 0x84, 0x78, 0x84, 0x78, 0x84, 0x78, 0x84, 0x78, + 0x84, 0x78, 0x84, 0x78, 0x84, 0x78, 0x85, 0x78, 0x84, 0x78, 0x84, 0x78, + 0x84, 0x78, 0x85, 0x78, 0x84, 0x78, 0x84, 0x78, 0x85, 0x78, 0x84, 0x78, + 0x84, 0x78, 0x85, 0x77, 0x84, 0x78, 0x85, 0x75, 0x85, 0x75, 0x86, 0x74, + 0x85, 0x72, 0x86, 0x70, 0x87, 0x6e, 0x87, 0x6d, 0x88, 0x6c, 0x89, 0x6c, + 0x8a, 0x6a, 0x8a, 0x68, 0x8b, 0x69, 0x8a, 0x69, 0x8a, 0x6a, 0x8a, 0x6a, + 0x8b, 0x6a, 0x8b, 0x6a, 0x8a, 0x6a, 0x8a, 0x6a, 0x8a, 0x69, 0x8b, 0x66, + 0x8d, 0x65, 0x8d, 0x61, 0x8f, 0x5b, 0x8f, 0x55, 0x90, 0x56, 0x92, 0x58, + 0x94, 0x58, 0x94, 0x58, 0x94, 0x58, 0x95, 0x57, 0x95, 0x54, 0x97, 0x4c, + 0x96, 0x44, 0x94, 0x46, 0x95, 0x54, 0x93, 0x5e, 0x97, 0x52, 0x95, 0x43, + 0x98, 0x3f, 0x9e, 0x3a, 0x9c, 0x3d, 0x98, 0x51, 0x80, 0x70, 0x6a, 0x85, + 0x61, 0x82, 0x60, 0x83, 0x5f, 0x86, 0x63, 0x89, 0x72, 0x8b, 0x72, 0x89, + 0x67, 0x8a, 0x5d, 0x8d, 0x56, 0x85, 0x5a, 0x80, 0x5f, 0x82, 0x61, 0x84, + 0x65, 0x80, 0x68, 0x77, 0x6f, 0x6a, 0x83, 0x57, 0x94, 0x46, 0x94, 0x42, + 0x94, 0x3f, 0x94, 0x3d, 0x94, 0x3e, 0x94, 0x42, 0x94, 0x42, 0x94, 0x40, + 0x94, 0x41, 0x93, 0x44, 0x90, 0x4a, 0x90, 0x4c, 0x8f, 0x4b, 0x90, 0x48, + 0x91, 0x4a, 0x91, 0x48, 0x94, 0x40, 0x91, 0x42, 0x91, 0x46, 0x92, 0x46, + 0x94, 0x44, 0x97, 0x41, 0x97, 0x40, 0x98, 0x41, 0x97, 0x43, 0x98, 0x42, + 0x99, 0x3f, 0x9a, 0x3c, 0x9a, 0x3b, 0x9a, 0x3a, 0x9a, 0x3c, 0x96, 0x43, + 0x96, 0x41, 0x96, 0x3a, 0x94, 0x3c, 0x94, 0x45, 0x94, 0x48, 0x93, 0x48, + 0x92, 0x47, 0x93, 0x47, 0x94, 0x46, 0x94, 0x46, 0x95, 0x45, 0x96, 0x43, + 0x97, 0x42, 0x97, 0x3f, 0x98, 0x3d, 0x98, 0x3d, 0x44, 0x60, 0x44, 0x5d, + 0x46, 0x5c, 0x48, 0x5e, 0x49, 0x61, 0x4c, 0x61, 0x4f, 0x60, 0x4f, 0x62, + 0x50, 0x63, 0x51, 0x62, 0x52, 0x5e, 0x52, 0x5e, 0x52, 0x5f, 0x53, 0x5d, + 0x53, 0x5d, 0x53, 0x5a, 0x52, 0x58, 0x5c, 0x59, 0x83, 0x67, 0x88, 0x6f, + 0x86, 0x71, 0x85, 0x74, 0x85, 0x75, 0x85, 0x75, 0x86, 0x75, 0x86, 0x75, + 0x85, 0x75, 0x85, 0x76, 0x84, 0x78, 0x84, 0x77, 0x85, 0x78, 0x84, 0x78, + 0x84, 0x78, 0x84, 0x78, 0x84, 0x78, 0x84, 0x78, 0x84, 0x78, 0x84, 0x78, + 0x84, 0x78, 0x84, 0x78, 0x84, 0x78, 0x85, 0x78, 0x84, 0x77, 0x84, 0x78, + 0x84, 0x78, 0x85, 0x78, 0x85, 0x78, 0x84, 0x78, 0x84, 0x78, 0x85, 0x77, + 0x85, 0x77, 0x85, 0x75, 0x85, 0x75, 0x86, 0x76, 0x86, 0x73, 0x85, 0x72, + 0x85, 0x6f, 0x86, 0x6e, 0x88, 0x6d, 0x89, 0x6c, 0x8a, 0x6a, 0x89, 0x68, + 0x8a, 0x67, 0x8c, 0x68, 0x8a, 0x69, 0x8a, 0x68, 0x8b, 0x68, 0x8a, 0x68, + 0x8a, 0x6a, 0x89, 0x6a, 0x8a, 0x68, 0x8b, 0x65, 0x8d, 0x66, 0x8d, 0x62, + 0x8e, 0x5d, 0x8f, 0x58, 0x90, 0x53, 0x93, 0x54, 0x94, 0x58, 0x94, 0x58, + 0x94, 0x58, 0x95, 0x58, 0x95, 0x54, 0x97, 0x50, 0x96, 0x46, 0x94, 0x44, + 0x95, 0x50, 0x93, 0x5d, 0x97, 0x54, 0x94, 0x44, 0x97, 0x3f, 0x9c, 0x3b, + 0x9c, 0x40, 0x98, 0x50, 0x84, 0x66, 0x6c, 0x82, 0x64, 0x84, 0x63, 0x82, + 0x63, 0x83, 0x62, 0x86, 0x6c, 0x89, 0x72, 0x8c, 0x70, 0x91, 0x61, 0x96, + 0x56, 0x88, 0x5a, 0x80, 0x63, 0x85, 0x66, 0x87, 0x69, 0x81, 0x6b, 0x78, + 0x74, 0x65, 0x8a, 0x4f, 0x94, 0x45, 0x94, 0x42, 0x95, 0x3f, 0x93, 0x3c, + 0x94, 0x3d, 0x94, 0x40, 0x94, 0x3f, 0x94, 0x3d, 0x94, 0x3f, 0x93, 0x43, + 0x93, 0x46, 0x95, 0x44, 0x95, 0x40, 0x95, 0x40, 0x94, 0x40, 0x94, 0x40, + 0x94, 0x41, 0x91, 0x46, 0x92, 0x48, 0x92, 0x47, 0x95, 0x43, 0x98, 0x3f, + 0x99, 0x3e, 0x99, 0x40, 0x98, 0x42, 0x99, 0x40, 0x9b, 0x3d, 0x9b, 0x3c, + 0x9a, 0x3e, 0x9a, 0x3c, 0x99, 0x3a, 0x98, 0x3d, 0x98, 0x3d, 0x98, 0x3d, + 0x94, 0x42, 0x91, 0x48, 0x92, 0x4b, 0x92, 0x4b, 0x91, 0x4a, 0x92, 0x48, + 0x94, 0x47, 0x94, 0x47, 0x95, 0x45, 0x96, 0x43, 0x97, 0x42, 0x97, 0x3e, + 0x98, 0x3a, 0x98, 0x3a, 0x45, 0x61, 0x44, 0x60, 0x46, 0x60, 0x49, 0x5f, + 0x4b, 0x5f, 0x4e, 0x60, 0x50, 0x60, 0x51, 0x62, 0x52, 0x64, 0x53, 0x62, + 0x52, 0x5f, 0x51, 0x60, 0x51, 0x60, 0x52, 0x5f, 0x52, 0x5e, 0x50, 0x5c, + 0x51, 0x5c, 0x5f, 0x5c, 0x84, 0x6c, 0x88, 0x6f, 0x88, 0x70, 0x87, 0x73, + 0x86, 0x73, 0x87, 0x73, 0x87, 0x74, 0x86, 0x74, 0x86, 0x75, 0x85, 0x75, + 0x85, 0x78, 0x85, 0x77, 0x85, 0x77, 0x85, 0x77, 0x84, 0x78, 0x84, 0x78, + 0x84, 0x78, 0x84, 0x78, 0x84, 0x78, 0x84, 0x78, 0x85, 0x79, 0x85, 0x78, + 0x85, 0x77, 0x85, 0x77, 0x85, 0x77, 0x85, 0x78, 0x85, 0x78, 0x84, 0x77, + 0x84, 0x77, 0x84, 0x77, 0x83, 0x78, 0x86, 0x77, 0x86, 0x77, 0x85, 0x76, + 0x85, 0x76, 0x86, 0x76, 0x86, 0x75, 0x85, 0x73, 0x85, 0x72, 0x86, 0x71, + 0x87, 0x6e, 0x88, 0x6c, 0x89, 0x6b, 0x89, 0x69, 0x89, 0x67, 0x8c, 0x65, + 0x8b, 0x65, 0x89, 0x66, 0x89, 0x67, 0x8c, 0x66, 0x8c, 0x68, 0x8b, 0x69, + 0x8a, 0x68, 0x8a, 0x66, 0x8c, 0x65, 0x8d, 0x62, 0x8e, 0x5d, 0x8e, 0x5b, + 0x8e, 0x55, 0x91, 0x51, 0x93, 0x55, 0x93, 0x58, 0x93, 0x58, 0x94, 0x59, + 0x96, 0x55, 0x96, 0x52, 0x96, 0x4a, 0x95, 0x44, 0x96, 0x4b, 0x96, 0x5b, + 0x97, 0x54, 0x94, 0x45, 0x95, 0x41, 0x9c, 0x3c, 0x9d, 0x47, 0x99, 0x4f, + 0x8b, 0x5b, 0x71, 0x79, 0x67, 0x83, 0x67, 0x83, 0x65, 0x82, 0x64, 0x83, + 0x65, 0x87, 0x6f, 0x8e, 0x7a, 0x95, 0x68, 0x9a, 0x58, 0x8a, 0x59, 0x83, + 0x64, 0x86, 0x68, 0x87, 0x6b, 0x80, 0x6d, 0x75, 0x7d, 0x5d, 0x8f, 0x4a, + 0x92, 0x45, 0x93, 0x41, 0x94, 0x3e, 0x94, 0x3c, 0x95, 0x3c, 0x95, 0x3c, + 0x96, 0x3a, 0x96, 0x3b, 0x96, 0x3c, 0x96, 0x3d, 0x97, 0x3e, 0x98, 0x3c, + 0x99, 0x3a, 0x97, 0x39, 0x95, 0x3d, 0x93, 0x43, 0x91, 0x49, 0x91, 0x49, + 0x92, 0x48, 0x93, 0x47, 0x97, 0x43, 0x9a, 0x3f, 0x99, 0x3d, 0x99, 0x3f, + 0x99, 0x40, 0x99, 0x3f, 0x9a, 0x3d, 0x9a, 0x3f, 0x9a, 0x3e, 0x9a, 0x3b, + 0x9a, 0x3b, 0x9a, 0x3b, 0x9a, 0x3b, 0x98, 0x40, 0x94, 0x47, 0x91, 0x4a, + 0x91, 0x4c, 0x91, 0x4d, 0x92, 0x4c, 0x92, 0x4b, 0x92, 0x49, 0x93, 0x48, + 0x95, 0x46, 0x96, 0x42, 0x96, 0x3e, 0x97, 0x3c, 0x99, 0x39, 0x98, 0x36, + 0x47, 0x61, 0x45, 0x61, 0x47, 0x62, 0x49, 0x5f, 0x4c, 0x5f, 0x4f, 0x60, + 0x52, 0x5f, 0x53, 0x61, 0x53, 0x64, 0x54, 0x63, 0x53, 0x60, 0x51, 0x60, + 0x51, 0x60, 0x52, 0x5f, 0x51, 0x5f, 0x50, 0x5e, 0x51, 0x5d, 0x69, 0x5f, + 0x87, 0x6c, 0x88, 0x6e, 0x88, 0x6f, 0x87, 0x73, 0x87, 0x73, 0x87, 0x72, + 0x87, 0x73, 0x86, 0x74, 0x85, 0x74, 0x85, 0x75, 0x85, 0x77, 0x85, 0x77, + 0x85, 0x77, 0x85, 0x77, 0x84, 0x78, 0x84, 0x78, 0x84, 0x78, 0x84, 0x78, + 0x84, 0x78, 0x84, 0x78, 0x86, 0x78, 0x86, 0x78, 0x86, 0x77, 0x86, 0x77, + 0x86, 0x77, 0x85, 0x78, 0x85, 0x77, 0x85, 0x75, 0x85, 0x76, 0x85, 0x76, + 0x85, 0x76, 0x86, 0x76, 0x86, 0x75, 0x86, 0x75, 0x85, 0x75, 0x86, 0x75, + 0x86, 0x75, 0x85, 0x73, 0x85, 0x73, 0x86, 0x73, 0x87, 0x6f, 0x87, 0x6d, + 0x88, 0x6c, 0x89, 0x6a, 0x89, 0x68, 0x8b, 0x64, 0x8c, 0x61, 0x8b, 0x61, + 0x8b, 0x65, 0x8c, 0x66, 0x8c, 0x66, 0x8d, 0x66, 0x8c, 0x66, 0x8b, 0x66, + 0x8d, 0x64, 0x8c, 0x61, 0x8d, 0x5e, 0x8d, 0x5c, 0x8d, 0x59, 0x8f, 0x53, + 0x91, 0x51, 0x92, 0x55, 0x92, 0x57, 0x94, 0x58, 0x96, 0x56, 0x95, 0x53, + 0x95, 0x4c, 0x95, 0x44, 0x96, 0x48, 0x96, 0x57, 0x97, 0x54, 0x94, 0x45, + 0x94, 0x44, 0x9c, 0x3a, 0x9d, 0x44, 0x99, 0x52, 0x91, 0x56, 0x78, 0x70, + 0x69, 0x82, 0x67, 0x82, 0x64, 0x81, 0x64, 0x82, 0x65, 0x85, 0x70, 0x8f, + 0x7e, 0x95, 0x6f, 0x99, 0x5c, 0x8c, 0x5a, 0x85, 0x62, 0x85, 0x69, 0x85, + 0x6a, 0x7f, 0x6f, 0x70, 0x84, 0x57, 0x92, 0x48, 0x92, 0x43, 0x94, 0x41, + 0x94, 0x3e, 0x95, 0x3d, 0x96, 0x3c, 0x97, 0x3c, 0x97, 0x3c, 0x96, 0x3c, + 0x97, 0x3c, 0x97, 0x3d, 0x97, 0x3e, 0x97, 0x3d, 0x98, 0x3b, 0x95, 0x3d, + 0x94, 0x42, 0x91, 0x47, 0x91, 0x4a, 0x91, 0x4a, 0x93, 0x48, 0x95, 0x46, + 0x98, 0x41, 0x99, 0x3d, 0x99, 0x3d, 0x99, 0x3f, 0x99, 0x40, 0x99, 0x3e, + 0x99, 0x3d, 0x99, 0x40, 0x99, 0x3e, 0x9a, 0x3b, 0x9a, 0x3c, 0x9a, 0x3d, + 0x9a, 0x3c, 0x97, 0x3d, 0x95, 0x42, 0x93, 0x48, 0x92, 0x4b, 0x93, 0x4e, + 0x93, 0x4c, 0x93, 0x4b, 0x93, 0x48, 0x94, 0x46, 0x96, 0x42, 0x96, 0x3d, + 0x97, 0x3b, 0x98, 0x3a, 0x99, 0x39, 0x99, 0x38, 0x4a, 0x61, 0x48, 0x61, + 0x48, 0x61, 0x4c, 0x60, 0x4e, 0x5f, 0x52, 0x5f, 0x54, 0x60, 0x54, 0x61, + 0x55, 0x65, 0x56, 0x65, 0x54, 0x62, 0x51, 0x60, 0x51, 0x60, 0x51, 0x5f, + 0x51, 0x5f, 0x50, 0x60, 0x52, 0x5f, 0x70, 0x63, 0x87, 0x6b, 0x87, 0x6c, + 0x88, 0x70, 0x87, 0x73, 0x87, 0x73, 0x86, 0x73, 0x87, 0x73, 0x86, 0x74, + 0x85, 0x75, 0x85, 0x75, 0x85, 0x77, 0x85, 0x77, 0x84, 0x77, 0x85, 0x77, + 0x84, 0x79, 0x84, 0x79, 0x84, 0x79, 0x84, 0x79, 0x84, 0x78, 0x84, 0x78, + 0x85, 0x78, 0x86, 0x78, 0x85, 0x77, 0x85, 0x77, 0x85, 0x76, 0x85, 0x75, + 0x85, 0x75, 0x86, 0x74, 0x87, 0x74, 0x86, 0x73, 0x86, 0x74, 0x85, 0x74, + 0x86, 0x74, 0x85, 0x73, 0x86, 0x73, 0x85, 0x73, 0x85, 0x73, 0x85, 0x73, + 0x85, 0x73, 0x86, 0x73, 0x87, 0x71, 0x87, 0x6f, 0x87, 0x6e, 0x88, 0x6a, + 0x8a, 0x68, 0x8a, 0x66, 0x8c, 0x63, 0x8d, 0x5f, 0x8e, 0x62, 0x8c, 0x66, + 0x8c, 0x65, 0x8d, 0x65, 0x8d, 0x65, 0x8d, 0x65, 0x8d, 0x64, 0x8c, 0x61, + 0x8d, 0x5f, 0x8d, 0x5d, 0x8c, 0x5b, 0x8d, 0x57, 0x90, 0x4f, 0x93, 0x4f, + 0x92, 0x53, 0x94, 0x57, 0x95, 0x56, 0x95, 0x54, 0x95, 0x4c, 0x95, 0x43, + 0x96, 0x44, 0x96, 0x50, 0x97, 0x54, 0x94, 0x45, 0x92, 0x46, 0x9a, 0x3c, + 0x9d, 0x3d, 0x99, 0x53, 0x95, 0x55, 0x81, 0x67, 0x6a, 0x81, 0x66, 0x80, + 0x62, 0x80, 0x62, 0x81, 0x65, 0x85, 0x75, 0x8f, 0x82, 0x95, 0x79, 0x97, + 0x61, 0x8f, 0x5b, 0x86, 0x5f, 0x83, 0x6a, 0x81, 0x6b, 0x7b, 0x73, 0x69, + 0x8c, 0x50, 0x92, 0x45, 0x92, 0x41, 0x93, 0x41, 0x94, 0x3f, 0x95, 0x3e, + 0x95, 0x3e, 0x96, 0x3e, 0x97, 0x3e, 0x97, 0x3e, 0x97, 0x3e, 0x97, 0x3f, + 0x97, 0x3f, 0x97, 0x3e, 0x96, 0x3e, 0x94, 0x42, 0x93, 0x47, 0x90, 0x49, + 0x91, 0x4a, 0x92, 0x4a, 0x94, 0x47, 0x96, 0x44, 0x99, 0x3f, 0x99, 0x3b, + 0x99, 0x3c, 0x99, 0x3f, 0x99, 0x41, 0x99, 0x3e, 0x99, 0x3d, 0x99, 0x42, + 0x9a, 0x3f, 0x9a, 0x3d, 0x9a, 0x3d, 0x9a, 0x3e, 0x9a, 0x3e, 0x99, 0x3e, + 0x97, 0x3f, 0x95, 0x41, 0x95, 0x43, 0x95, 0x46, 0x95, 0x46, 0x96, 0x43, + 0x98, 0x40, 0x98, 0x3e, 0x97, 0x3b, 0x98, 0x39, 0x99, 0x39, 0x99, 0x39, + 0x99, 0x39, 0x99, 0x3b, 0x4d, 0x61, 0x4b, 0x61, 0x4a, 0x60, 0x4e, 0x60, + 0x51, 0x5f, 0x55, 0x5d, 0x57, 0x5e, 0x56, 0x61, 0x58, 0x64, 0x58, 0x65, + 0x55, 0x63, 0x53, 0x62, 0x53, 0x61, 0x52, 0x60, 0x51, 0x60, 0x51, 0x60, + 0x56, 0x5d, 0x78, 0x64, 0x88, 0x6c, 0x88, 0x6b, 0x89, 0x6f, 0x87, 0x71, + 0x87, 0x71, 0x87, 0x72, 0x87, 0x72, 0x87, 0x73, 0x86, 0x74, 0x86, 0x74, + 0x85, 0x76, 0x85, 0x76, 0x85, 0x77, 0x85, 0x77, 0x85, 0x77, 0x84, 0x77, + 0x84, 0x77, 0x85, 0x77, 0x85, 0x78, 0x85, 0x79, 0x85, 0x78, 0x85, 0x78, + 0x85, 0x78, 0x85, 0x77, 0x85, 0x77, 0x86, 0x75, 0x86, 0x75, 0x87, 0x74, + 0x87, 0x74, 0x88, 0x73, 0x87, 0x73, 0x87, 0x73, 0x87, 0x72, 0x87, 0x71, + 0x87, 0x71, 0x87, 0x72, 0x87, 0x73, 0x87, 0x72, 0x86, 0x73, 0x87, 0x72, + 0x87, 0x71, 0x87, 0x70, 0x86, 0x6f, 0x87, 0x6e, 0x88, 0x6c, 0x88, 0x69, + 0x8a, 0x65, 0x8b, 0x61, 0x8d, 0x5f, 0x8d, 0x62, 0x8c, 0x64, 0x8e, 0x62, + 0x8e, 0x62, 0x8e, 0x63, 0x8d, 0x64, 0x8d, 0x62, 0x8d, 0x60, 0x8d, 0x5e, + 0x8d, 0x5b, 0x8d, 0x5a, 0x8f, 0x52, 0x92, 0x4c, 0x92, 0x50, 0x94, 0x56, + 0x95, 0x57, 0x95, 0x54, 0x95, 0x4e, 0x96, 0x44, 0x96, 0x42, 0x97, 0x4a, + 0x98, 0x52, 0x95, 0x46, 0x91, 0x48, 0x98, 0x41, 0x9c, 0x3d, 0x98, 0x4f, + 0x97, 0x5b, 0x89, 0x62, 0x69, 0x80, 0x63, 0x7f, 0x61, 0x7f, 0x62, 0x81, + 0x66, 0x86, 0x7b, 0x8f, 0x8a, 0x93, 0x86, 0x94, 0x6d, 0x91, 0x60, 0x88, + 0x5d, 0x81, 0x67, 0x7d, 0x68, 0x7a, 0x78, 0x64, 0x92, 0x4b, 0x92, 0x44, + 0x92, 0x42, 0x93, 0x41, 0x94, 0x40, 0x95, 0x40, 0x95, 0x41, 0x95, 0x40, + 0x95, 0x3f, 0x95, 0x3f, 0x95, 0x3e, 0x95, 0x40, 0x97, 0x3f, 0x97, 0x3d, + 0x96, 0x41, 0x93, 0x47, 0x91, 0x4a, 0x90, 0x4a, 0x91, 0x4a, 0x92, 0x48, + 0x96, 0x45, 0x97, 0x42, 0x99, 0x3d, 0x99, 0x3d, 0x99, 0x3c, 0x98, 0x3e, + 0x99, 0x40, 0x99, 0x40, 0x98, 0x41, 0x99, 0x44, 0x9a, 0x40, 0x9a, 0x3d, + 0x9a, 0x3e, 0x9b, 0x3e, 0x9a, 0x3f, 0x98, 0x42, 0x96, 0x44, 0x96, 0x41, + 0x97, 0x3e, 0x96, 0x3d, 0x97, 0x3c, 0x98, 0x3b, 0x99, 0x3a, 0x99, 0x39, + 0x99, 0x3a, 0x99, 0x3b, 0x98, 0x3c, 0x97, 0x3c, 0x98, 0x3d, 0x98, 0x3e, + 0x4f, 0x62, 0x4d, 0x62, 0x4c, 0x60, 0x50, 0x61, 0x53, 0x60, 0x57, 0x5d, + 0x59, 0x5e, 0x58, 0x61, 0x59, 0x63, 0x5a, 0x63, 0x56, 0x63, 0x55, 0x63, + 0x55, 0x60, 0x55, 0x61, 0x55, 0x60, 0x54, 0x5f, 0x5c, 0x5c, 0x81, 0x63, + 0x89, 0x6d, 0x89, 0x6c, 0x8a, 0x6e, 0x88, 0x70, 0x88, 0x70, 0x88, 0x71, + 0x88, 0x72, 0x87, 0x72, 0x87, 0x73, 0x87, 0x73, 0x85, 0x75, 0x85, 0x75, + 0x86, 0x78, 0x86, 0x77, 0x86, 0x77, 0x86, 0x77, 0x86, 0x77, 0x86, 0x77, + 0x86, 0x78, 0x86, 0x79, 0x85, 0x78, 0x84, 0x78, 0x84, 0x78, 0x84, 0x77, + 0x84, 0x77, 0x85, 0x77, 0x85, 0x76, 0x86, 0x76, 0x86, 0x75, 0x86, 0x74, + 0x87, 0x74, 0x88, 0x73, 0x88, 0x73, 0x88, 0x72, 0x88, 0x72, 0x88, 0x72, + 0x88, 0x72, 0x88, 0x72, 0x87, 0x72, 0x87, 0x71, 0x87, 0x70, 0x87, 0x70, + 0x87, 0x6f, 0x87, 0x70, 0x87, 0x6f, 0x87, 0x6b, 0x89, 0x66, 0x89, 0x64, + 0x8b, 0x5d, 0x8e, 0x5d, 0x8e, 0x60, 0x8d, 0x62, 0x8d, 0x61, 0x8d, 0x62, + 0x8d, 0x65, 0x8d, 0x63, 0x8e, 0x61, 0x8d, 0x5f, 0x8d, 0x5c, 0x8d, 0x5a, + 0x8e, 0x56, 0x90, 0x4e, 0x92, 0x4f, 0x94, 0x54, 0x95, 0x57, 0x95, 0x53, + 0x95, 0x50, 0x96, 0x47, 0x96, 0x41, 0x96, 0x46, 0x98, 0x50, 0x96, 0x46, + 0x91, 0x49, 0x96, 0x43, 0x9b, 0x43, 0x98, 0x4f, 0x98, 0x5d, 0x8c, 0x61, + 0x68, 0x7e, 0x63, 0x7e, 0x60, 0x7f, 0x60, 0x82, 0x67, 0x86, 0x7c, 0x8f, + 0x89, 0x92, 0x88, 0x93, 0x74, 0x90, 0x64, 0x88, 0x5e, 0x81, 0x61, 0x7c, + 0x63, 0x7a, 0x79, 0x62, 0x91, 0x49, 0x91, 0x45, 0x92, 0x44, 0x93, 0x43, + 0x94, 0x42, 0x94, 0x42, 0x95, 0x42, 0x95, 0x40, 0x95, 0x3f, 0x95, 0x3e, + 0x95, 0x3e, 0x95, 0x40, 0x96, 0x40, 0x96, 0x3f, 0x95, 0x44, 0x92, 0x49, + 0x92, 0x4b, 0x91, 0x4b, 0x91, 0x4a, 0x93, 0x47, 0x97, 0x44, 0x97, 0x41, + 0x98, 0x3f, 0x99, 0x43, 0x98, 0x3f, 0x98, 0x3e, 0x98, 0x40, 0x98, 0x40, + 0x98, 0x43, 0x99, 0x43, 0x9a, 0x3f, 0x9a, 0x3d, 0x9b, 0x3e, 0x9c, 0x3f, + 0x99, 0x41, 0x96, 0x46, 0x94, 0x49, 0x95, 0x48, 0x95, 0x44, 0x95, 0x42, + 0x96, 0x40, 0x96, 0x3f, 0x97, 0x3e, 0x97, 0x3e, 0x98, 0x3f, 0x97, 0x40, + 0x96, 0x41, 0x95, 0x41, 0x96, 0x41, 0x96, 0x43, 0x53, 0x62, 0x51, 0x62, + 0x4f, 0x61, 0x54, 0x61, 0x57, 0x60, 0x5b, 0x5d, 0x5c, 0x5e, 0x5a, 0x61, + 0x5c, 0x63, 0x5c, 0x64, 0x59, 0x63, 0x59, 0x62, 0x59, 0x60, 0x5b, 0x61, + 0x5b, 0x61, 0x5a, 0x60, 0x66, 0x5d, 0x87, 0x67, 0x89, 0x6d, 0x89, 0x6c, + 0x8a, 0x6f, 0x88, 0x71, 0x88, 0x70, 0x88, 0x71, 0x88, 0x72, 0x87, 0x73, + 0x87, 0x73, 0x86, 0x73, 0x85, 0x76, 0x85, 0x75, 0x85, 0x78, 0x85, 0x78, + 0x85, 0x78, 0x85, 0x77, 0x85, 0x78, 0x85, 0x78, 0x86, 0x78, 0x86, 0x78, + 0x84, 0x79, 0x84, 0x78, 0x84, 0x78, 0x84, 0x77, 0x84, 0x78, 0x83, 0x79, + 0x83, 0x78, 0x85, 0x78, 0x85, 0x77, 0x84, 0x76, 0x85, 0x76, 0x86, 0x75, + 0x86, 0x75, 0x86, 0x74, 0x86, 0x74, 0x86, 0x72, 0x86, 0x72, 0x86, 0x72, + 0x87, 0x72, 0x87, 0x71, 0x87, 0x71, 0x88, 0x71, 0x87, 0x6f, 0x87, 0x6f, + 0x87, 0x6f, 0x87, 0x6c, 0x87, 0x6b, 0x87, 0x69, 0x89, 0x63, 0x8b, 0x5e, + 0x8e, 0x5c, 0x8c, 0x5f, 0x8d, 0x60, 0x8d, 0x60, 0x8d, 0x62, 0x8e, 0x63, + 0x8d, 0x62, 0x8d, 0x5f, 0x8d, 0x5d, 0x8d, 0x5c, 0x8d, 0x59, 0x8e, 0x51, + 0x8f, 0x4e, 0x93, 0x4f, 0x94, 0x55, 0x95, 0x53, 0x95, 0x52, 0x96, 0x4c, + 0x96, 0x42, 0x95, 0x44, 0x98, 0x4d, 0x96, 0x46, 0x91, 0x49, 0x92, 0x47, + 0x9a, 0x43, 0x98, 0x4e, 0x9a, 0x55, 0x8d, 0x57, 0x68, 0x7c, 0x67, 0x7d, + 0x64, 0x7d, 0x64, 0x82, 0x6b, 0x88, 0x7c, 0x8f, 0x84, 0x92, 0x84, 0x93, + 0x76, 0x91, 0x68, 0x8a, 0x61, 0x7f, 0x5f, 0x7c, 0x60, 0x7a, 0x77, 0x63, + 0x8f, 0x4a, 0x91, 0x46, 0x92, 0x46, 0x93, 0x45, 0x94, 0x44, 0x94, 0x43, + 0x95, 0x42, 0x95, 0x41, 0x96, 0x41, 0x95, 0x40, 0x95, 0x40, 0x95, 0x41, + 0x94, 0x42, 0x94, 0x44, 0x93, 0x49, 0x90, 0x4a, 0x91, 0x4b, 0x91, 0x4b, + 0x93, 0x48, 0x95, 0x46, 0x97, 0x42, 0x98, 0x41, 0x97, 0x44, 0x97, 0x47, + 0x97, 0x40, 0x97, 0x3f, 0x97, 0x40, 0x97, 0x41, 0x98, 0x42, 0x99, 0x41, + 0x9a, 0x3e, 0x9a, 0x3e, 0x9b, 0x41, 0x9a, 0x43, 0x97, 0x45, 0x92, 0x4c, + 0x90, 0x4e, 0x90, 0x4f, 0x90, 0x4d, 0x91, 0x4d, 0x92, 0x4b, 0x92, 0x4a, + 0x93, 0x48, 0x93, 0x48, 0x93, 0x48, 0x94, 0x48, 0x94, 0x49, 0x95, 0x49, + 0x95, 0x49, 0x94, 0x4b, 0x55, 0x63, 0x53, 0x63, 0x51, 0x61, 0x56, 0x5f, + 0x59, 0x5f, 0x5e, 0x5d, 0x5e, 0x5e, 0x5a, 0x61, 0x5c, 0x63, 0x5c, 0x63, + 0x5b, 0x63, 0x5b, 0x61, 0x5c, 0x60, 0x5f, 0x61, 0x5f, 0x61, 0x5e, 0x5f, + 0x6d, 0x5e, 0x88, 0x69, 0x8a, 0x6c, 0x8a, 0x6c, 0x89, 0x6e, 0x89, 0x71, + 0x88, 0x70, 0x88, 0x71, 0x88, 0x72, 0x88, 0x73, 0x87, 0x74, 0x87, 0x73, + 0x86, 0x75, 0x86, 0x75, 0x85, 0x76, 0x86, 0x77, 0x85, 0x77, 0x85, 0x77, + 0x86, 0x77, 0x86, 0x77, 0x86, 0x77, 0x86, 0x77, 0x85, 0x78, 0x85, 0x77, + 0x85, 0x77, 0x85, 0x77, 0x84, 0x78, 0x83, 0x79, 0x83, 0x78, 0x84, 0x78, + 0x84, 0x78, 0x84, 0x77, 0x84, 0x76, 0x85, 0x75, 0x84, 0x75, 0x85, 0x74, + 0x85, 0x74, 0x85, 0x72, 0x85, 0x72, 0x86, 0x71, 0x87, 0x71, 0x87, 0x70, + 0x87, 0x70, 0x87, 0x6f, 0x87, 0x6f, 0x87, 0x6e, 0x87, 0x6d, 0x87, 0x6c, + 0x86, 0x6c, 0x86, 0x6c, 0x87, 0x69, 0x89, 0x64, 0x8b, 0x5e, 0x8e, 0x59, + 0x8e, 0x5b, 0x8e, 0x5e, 0x8f, 0x60, 0x8e, 0x64, 0x8d, 0x63, 0x8d, 0x5f, + 0x8e, 0x5e, 0x8e, 0x5d, 0x8d, 0x5b, 0x8d, 0x55, 0x8d, 0x4f, 0x92, 0x4c, + 0x95, 0x53, 0x95, 0x53, 0x95, 0x52, 0x96, 0x4f, 0x97, 0x43, 0x95, 0x42, + 0x98, 0x4b, 0x96, 0x45, 0x92, 0x49, 0x90, 0x49, 0x9a, 0x3f, 0x9b, 0x4a, + 0x9b, 0x4c, 0x8f, 0x4e, 0x68, 0x7a, 0x69, 0x7a, 0x69, 0x7a, 0x69, 0x83, + 0x6d, 0x88, 0x7d, 0x8f, 0x85, 0x93, 0x83, 0x93, 0x75, 0x91, 0x6a, 0x8a, + 0x64, 0x7e, 0x62, 0x7b, 0x62, 0x7b, 0x74, 0x69, 0x8e, 0x4c, 0x91, 0x48, + 0x92, 0x47, 0x92, 0x46, 0x93, 0x44, 0x95, 0x43, 0x96, 0x42, 0x95, 0x41, + 0x95, 0x42, 0x95, 0x42, 0x96, 0x42, 0x94, 0x43, 0x92, 0x45, 0x92, 0x47, + 0x91, 0x4b, 0x90, 0x4a, 0x90, 0x4b, 0x91, 0x4a, 0x93, 0x47, 0x97, 0x43, + 0x97, 0x3f, 0x97, 0x41, 0x97, 0x45, 0x96, 0x44, 0x96, 0x3f, 0x97, 0x41, + 0x97, 0x41, 0x98, 0x41, 0x98, 0x42, 0x9a, 0x3f, 0x9a, 0x3e, 0x99, 0x40, + 0x99, 0x43, 0x97, 0x46, 0x95, 0x49, 0x90, 0x50, 0x8e, 0x52, 0x8e, 0x51, + 0x8e, 0x51, 0x8f, 0x51, 0x8f, 0x50, 0x8f, 0x4f, 0x91, 0x4f, 0x91, 0x4e, + 0x91, 0x4d, 0x92, 0x4d, 0x93, 0x4e, 0x93, 0x4e, 0x93, 0x4e, 0x93, 0x50, + 0x56, 0x63, 0x54, 0x63, 0x54, 0x60, 0x59, 0x5d, 0x5c, 0x5c, 0x60, 0x5b, + 0x5f, 0x5c, 0x5b, 0x60, 0x5b, 0x63, 0x5c, 0x63, 0x5c, 0x62, 0x5d, 0x60, + 0x5d, 0x61, 0x60, 0x62, 0x62, 0x62, 0x60, 0x5f, 0x72, 0x60, 0x87, 0x68, + 0x8a, 0x6b, 0x89, 0x6b, 0x89, 0x6d, 0x89, 0x6f, 0x8a, 0x6f, 0x89, 0x70, + 0x88, 0x70, 0x88, 0x72, 0x88, 0x73, 0x88, 0x73, 0x88, 0x74, 0x88, 0x74, + 0x87, 0x75, 0x86, 0x75, 0x87, 0x75, 0x87, 0x75, 0x87, 0x76, 0x86, 0x76, + 0x85, 0x75, 0x85, 0x75, 0x85, 0x75, 0x85, 0x75, 0x85, 0x75, 0x85, 0x75, + 0x85, 0x75, 0x85, 0x75, 0x85, 0x75, 0x85, 0x75, 0x85, 0x75, 0x85, 0x76, + 0x85, 0x75, 0x85, 0x74, 0x85, 0x74, 0x85, 0x73, 0x85, 0x73, 0x86, 0x73, + 0x86, 0x73, 0x86, 0x71, 0x87, 0x70, 0x86, 0x70, 0x86, 0x70, 0x86, 0x6f, + 0x86, 0x6f, 0x87, 0x6f, 0x87, 0x6d, 0x87, 0x6b, 0x87, 0x6b, 0x87, 0x6b, + 0x87, 0x6b, 0x87, 0x68, 0x89, 0x64, 0x8c, 0x5c, 0x8e, 0x5a, 0x8f, 0x5c, + 0x91, 0x5d, 0x8f, 0x60, 0x8f, 0x62, 0x8f, 0x60, 0x8e, 0x5f, 0x8d, 0x5e, + 0x8d, 0x5c, 0x8d, 0x58, 0x8d, 0x54, 0x90, 0x4b, 0x94, 0x4e, 0x95, 0x51, + 0x96, 0x4f, 0x96, 0x4f, 0x97, 0x43, 0x98, 0x40, 0x98, 0x48, 0x96, 0x43, + 0x92, 0x48, 0x90, 0x4a, 0x99, 0x41, 0x9e, 0x40, 0x9b, 0x44, 0x92, 0x4b, + 0x6a, 0x7a, 0x68, 0x76, 0x6b, 0x77, 0x69, 0x81, 0x69, 0x85, 0x7d, 0x8f, + 0x85, 0x93, 0x84, 0x92, 0x75, 0x90, 0x66, 0x88, 0x63, 0x7f, 0x63, 0x7c, + 0x63, 0x7c, 0x6e, 0x6e, 0x8c, 0x4f, 0x91, 0x48, 0x91, 0x47, 0x92, 0x46, + 0x92, 0x45, 0x95, 0x43, 0x95, 0x42, 0x95, 0x42, 0x94, 0x43, 0x94, 0x43, + 0x95, 0x43, 0x94, 0x45, 0x91, 0x47, 0x91, 0x49, 0x91, 0x4b, 0x91, 0x4b, + 0x90, 0x4b, 0x92, 0x48, 0x93, 0x44, 0x98, 0x41, 0x98, 0x41, 0x98, 0x44, + 0x98, 0x44, 0x98, 0x40, 0x97, 0x40, 0x96, 0x42, 0x97, 0x41, 0x98, 0x41, + 0x98, 0x40, 0x9a, 0x40, 0x97, 0x42, 0x97, 0x44, 0x96, 0x48, 0x94, 0x4a, + 0x91, 0x4d, 0x8f, 0x52, 0x8f, 0x53, 0x8e, 0x53, 0x8e, 0x53, 0x8f, 0x52, + 0x8f, 0x51, 0x90, 0x51, 0x90, 0x51, 0x90, 0x50, 0x91, 0x50, 0x90, 0x50, + 0x90, 0x51, 0x90, 0x52, 0x90, 0x52, 0x90, 0x53, 0x56, 0x61, 0x54, 0x61, + 0x57, 0x60, 0x5b, 0x5c, 0x5e, 0x59, 0x61, 0x5a, 0x61, 0x5c, 0x5c, 0x61, + 0x5c, 0x64, 0x5c, 0x63, 0x5e, 0x62, 0x60, 0x60, 0x60, 0x61, 0x62, 0x62, + 0x63, 0x62, 0x63, 0x61, 0x79, 0x61, 0x89, 0x68, 0x8b, 0x6b, 0x89, 0x6b, + 0x89, 0x6e, 0x89, 0x6f, 0x89, 0x6f, 0x88, 0x70, 0x88, 0x70, 0x88, 0x71, + 0x88, 0x71, 0x88, 0x72, 0x88, 0x72, 0x88, 0x73, 0x86, 0x74, 0x87, 0x75, + 0x87, 0x76, 0x87, 0x75, 0x87, 0x76, 0x87, 0x75, 0x85, 0x76, 0x85, 0x75, + 0x85, 0x74, 0x85, 0x74, 0x85, 0x75, 0x85, 0x75, 0x85, 0x75, 0x85, 0x75, + 0x85, 0x75, 0x85, 0x75, 0x85, 0x75, 0x85, 0x75, 0x85, 0x75, 0x86, 0x75, + 0x86, 0x76, 0x85, 0x74, 0x85, 0x74, 0x84, 0x75, 0x85, 0x75, 0x84, 0x74, + 0x85, 0x75, 0x85, 0x75, 0x85, 0x75, 0x85, 0x74, 0x85, 0x73, 0x85, 0x72, + 0x87, 0x71, 0x87, 0x6e, 0x87, 0x6b, 0x87, 0x6c, 0x87, 0x6c, 0x87, 0x6a, + 0x87, 0x6c, 0x8a, 0x67, 0x8b, 0x62, 0x8b, 0x5f, 0x8d, 0x5c, 0x8e, 0x5b, + 0x8f, 0x5d, 0x8f, 0x5e, 0x8d, 0x60, 0x8d, 0x5e, 0x8d, 0x5c, 0x8d, 0x59, + 0x8d, 0x57, 0x8e, 0x4e, 0x92, 0x49, 0x94, 0x4e, 0x95, 0x4e, 0x95, 0x4d, + 0x97, 0x43, 0x99, 0x3e, 0x99, 0x41, 0x96, 0x42, 0x93, 0x47, 0x90, 0x4b, + 0x95, 0x47, 0x9c, 0x3c, 0x9d, 0x40, 0x98, 0x47, 0x72, 0x75, 0x69, 0x76, + 0x6b, 0x75, 0x6b, 0x7d, 0x69, 0x82, 0x7b, 0x8d, 0x84, 0x91, 0x83, 0x90, + 0x74, 0x8e, 0x64, 0x87, 0x61, 0x81, 0x64, 0x7e, 0x66, 0x7e, 0x6c, 0x73, + 0x8a, 0x53, 0x91, 0x4a, 0x91, 0x48, 0x92, 0x49, 0x93, 0x47, 0x93, 0x44, + 0x93, 0x44, 0x94, 0x44, 0x94, 0x44, 0x94, 0x45, 0x92, 0x45, 0x93, 0x48, + 0x91, 0x49, 0x91, 0x4b, 0x91, 0x4c, 0x91, 0x4c, 0x91, 0x4a, 0x94, 0x46, + 0x97, 0x42, 0x99, 0x41, 0x98, 0x45, 0x98, 0x45, 0x98, 0x42, 0x98, 0x40, + 0x97, 0x42, 0x96, 0x43, 0x97, 0x43, 0x98, 0x42, 0x98, 0x42, 0x96, 0x45, + 0x93, 0x49, 0x93, 0x4b, 0x93, 0x4e, 0x92, 0x4f, 0x8f, 0x51, 0x8f, 0x54, + 0x8e, 0x54, 0x8e, 0x55, 0x8e, 0x54, 0x8f, 0x52, 0x90, 0x51, 0x90, 0x51, + 0x90, 0x52, 0x8f, 0x52, 0x90, 0x53, 0x8f, 0x55, 0x8e, 0x55, 0x8e, 0x56, + 0x8e, 0x57, 0x8d, 0x57, 0x55, 0x61, 0x55, 0x5f, 0x58, 0x5e, 0x5c, 0x5d, + 0x5f, 0x5b, 0x62, 0x5c, 0x63, 0x5c, 0x5e, 0x60, 0x5f, 0x64, 0x5e, 0x63, + 0x60, 0x62, 0x63, 0x60, 0x62, 0x61, 0x63, 0x62, 0x65, 0x62, 0x65, 0x62, + 0x7d, 0x62, 0x8a, 0x68, 0x8a, 0x6b, 0x89, 0x6b, 0x89, 0x6d, 0x89, 0x6f, + 0x89, 0x6f, 0x89, 0x70, 0x88, 0x70, 0x88, 0x70, 0x88, 0x6f, 0x88, 0x70, + 0x88, 0x71, 0x88, 0x72, 0x87, 0x74, 0x87, 0x74, 0x87, 0x75, 0x87, 0x76, + 0x87, 0x76, 0x87, 0x75, 0x85, 0x76, 0x85, 0x75, 0x85, 0x75, 0x85, 0x75, + 0x85, 0x75, 0x86, 0x75, 0x86, 0x75, 0x85, 0x75, 0x85, 0x75, 0x85, 0x75, + 0x85, 0x76, 0x85, 0x75, 0x86, 0x76, 0x86, 0x78, 0x86, 0x78, 0x85, 0x76, + 0x85, 0x76, 0x83, 0x76, 0x83, 0x76, 0x83, 0x76, 0x84, 0x77, 0x84, 0x77, + 0x84, 0x77, 0x84, 0x76, 0x84, 0x75, 0x85, 0x74, 0x87, 0x73, 0x87, 0x71, + 0x87, 0x70, 0x87, 0x70, 0x87, 0x6e, 0x87, 0x6c, 0x86, 0x6c, 0x88, 0x6b, + 0x89, 0x69, 0x88, 0x64, 0x8a, 0x60, 0x8d, 0x5d, 0x8f, 0x5a, 0x8f, 0x5d, + 0x8e, 0x5f, 0x8d, 0x5e, 0x8d, 0x5b, 0x8e, 0x58, 0x8e, 0x58, 0x8e, 0x54, + 0x90, 0x49, 0x94, 0x4a, 0x95, 0x4c, 0x95, 0x4b, 0x98, 0x42, 0x99, 0x3c, + 0x99, 0x3e, 0x95, 0x41, 0x92, 0x47, 0x90, 0x4b, 0x93, 0x49, 0x9a, 0x3f, + 0x9e, 0x3e, 0x9c, 0x43, 0x7a, 0x72, 0x6e, 0x77, 0x6d, 0x73, 0x6b, 0x7a, + 0x68, 0x80, 0x7a, 0x8c, 0x83, 0x8f, 0x83, 0x8e, 0x76, 0x8c, 0x68, 0x86, + 0x63, 0x81, 0x64, 0x7f, 0x68, 0x7f, 0x6b, 0x75, 0x89, 0x55, 0x91, 0x4b, + 0x91, 0x4a, 0x92, 0x4a, 0x92, 0x48, 0x92, 0x46, 0x92, 0x46, 0x93, 0x46, + 0x94, 0x45, 0x93, 0x46, 0x91, 0x47, 0x92, 0x49, 0x91, 0x4a, 0x91, 0x4c, + 0x91, 0x4c, 0x91, 0x4b, 0x93, 0x49, 0x96, 0x44, 0x9a, 0x41, 0x99, 0x42, + 0x99, 0x43, 0x99, 0x41, 0x98, 0x40, 0x98, 0x41, 0x97, 0x44, 0x96, 0x45, + 0x97, 0x45, 0x98, 0x46, 0x96, 0x48, 0x93, 0x4a, 0x91, 0x4e, 0x90, 0x50, + 0x90, 0x52, 0x90, 0x52, 0x8e, 0x53, 0x8f, 0x55, 0x8e, 0x55, 0x8e, 0x55, + 0x8e, 0x53, 0x8f, 0x52, 0x90, 0x51, 0x90, 0x51, 0x90, 0x52, 0x8f, 0x54, + 0x8e, 0x56, 0x8d, 0x57, 0x8d, 0x58, 0x8c, 0x58, 0x8c, 0x59, 0x8c, 0x5a, + 0x54, 0x62, 0x58, 0x5d, 0x5b, 0x5b, 0x5f, 0x5b, 0x62, 0x5c, 0x64, 0x5d, + 0x63, 0x5d, 0x5f, 0x5f, 0x61, 0x64, 0x62, 0x63, 0x63, 0x62, 0x64, 0x61, + 0x63, 0x62, 0x64, 0x63, 0x66, 0x63, 0x67, 0x62, 0x82, 0x64, 0x8b, 0x69, + 0x8a, 0x6a, 0x8a, 0x6a, 0x8a, 0x6b, 0x89, 0x6e, 0x89, 0x6f, 0x89, 0x6f, + 0x89, 0x6f, 0x8a, 0x6f, 0x8a, 0x6f, 0x8a, 0x70, 0x89, 0x70, 0x89, 0x71, + 0x88, 0x73, 0x88, 0x73, 0x86, 0x74, 0x87, 0x75, 0x87, 0x75, 0x87, 0x74, + 0x87, 0x76, 0x87, 0x75, 0x86, 0x77, 0x86, 0x77, 0x86, 0x77, 0x86, 0x77, + 0x86, 0x77, 0x85, 0x77, 0x85, 0x77, 0x84, 0x77, 0x84, 0x77, 0x85, 0x77, + 0x85, 0x78, 0x85, 0x78, 0x85, 0x78, 0x84, 0x77, 0x84, 0x77, 0x84, 0x77, + 0x84, 0x78, 0x85, 0x76, 0x86, 0x75, 0x85, 0x75, 0x85, 0x75, 0x85, 0x75, + 0x85, 0x75, 0x85, 0x74, 0x85, 0x73, 0x85, 0x73, 0x85, 0x73, 0x86, 0x73, + 0x87, 0x70, 0x87, 0x70, 0x87, 0x6e, 0x87, 0x6d, 0x87, 0x6c, 0x87, 0x68, + 0x89, 0x68, 0x8a, 0x62, 0x8c, 0x5b, 0x8f, 0x5b, 0x8f, 0x5d, 0x8f, 0x5e, + 0x8f, 0x5d, 0x8f, 0x5a, 0x8f, 0x59, 0x8d, 0x57, 0x8e, 0x4d, 0x95, 0x48, + 0x95, 0x49, 0x96, 0x49, 0x99, 0x3f, 0x99, 0x3b, 0x9a, 0x3c, 0x93, 0x43, + 0x91, 0x48, 0x91, 0x4b, 0x92, 0x4a, 0x99, 0x42, 0x9d, 0x3f, 0x9b, 0x41, + 0x81, 0x6f, 0x72, 0x7c, 0x70, 0x75, 0x6d, 0x76, 0x6b, 0x7b, 0x79, 0x88, + 0x83, 0x8f, 0x83, 0x8d, 0x7b, 0x8b, 0x6e, 0x85, 0x67, 0x7d, 0x66, 0x7f, + 0x68, 0x7e, 0x67, 0x76, 0x86, 0x55, 0x90, 0x4d, 0x90, 0x4c, 0x91, 0x4b, + 0x91, 0x47, 0x91, 0x47, 0x91, 0x48, 0x92, 0x46, 0x93, 0x47, 0x91, 0x47, + 0x8f, 0x49, 0x90, 0x4a, 0x90, 0x4b, 0x90, 0x4c, 0x90, 0x4c, 0x91, 0x4a, + 0x94, 0x47, 0x98, 0x43, 0x9a, 0x40, 0x9a, 0x41, 0x9c, 0x40, 0x9a, 0x3f, + 0x98, 0x43, 0x96, 0x46, 0x94, 0x48, 0x94, 0x49, 0x93, 0x4a, 0x92, 0x4d, + 0x91, 0x4f, 0x8f, 0x51, 0x8e, 0x54, 0x8d, 0x55, 0x8f, 0x53, 0x8e, 0x52, + 0x8e, 0x53, 0x8f, 0x56, 0x8e, 0x56, 0x8f, 0x55, 0x8f, 0x52, 0x90, 0x51, + 0x90, 0x51, 0x90, 0x51, 0x90, 0x54, 0x8e, 0x56, 0x8e, 0x58, 0x8c, 0x5a, + 0x8a, 0x5a, 0x8b, 0x5b, 0x8c, 0x5c, 0x8c, 0x5b, 0x56, 0x61, 0x5a, 0x5c, + 0x5d, 0x5b, 0x61, 0x5b, 0x63, 0x5c, 0x64, 0x5d, 0x64, 0x5d, 0x60, 0x5f, + 0x63, 0x64, 0x64, 0x64, 0x63, 0x62, 0x64, 0x62, 0x64, 0x62, 0x64, 0x63, + 0x66, 0x63, 0x6a, 0x62, 0x86, 0x65, 0x8b, 0x6a, 0x8a, 0x69, 0x8a, 0x6a, + 0x8a, 0x6b, 0x8a, 0x6d, 0x8a, 0x6e, 0x89, 0x6e, 0x8a, 0x6f, 0x89, 0x6f, + 0x89, 0x6f, 0x8a, 0x70, 0x8a, 0x71, 0x8a, 0x71, 0x88, 0x73, 0x87, 0x72, + 0x86, 0x74, 0x87, 0x75, 0x87, 0x74, 0x87, 0x75, 0x87, 0x75, 0x87, 0x75, + 0x85, 0x77, 0x85, 0x77, 0x86, 0x78, 0x86, 0x78, 0x85, 0x77, 0x85, 0x77, + 0x85, 0x77, 0x84, 0x78, 0x84, 0x77, 0x85, 0x77, 0x85, 0x77, 0x85, 0x77, + 0x85, 0x77, 0x85, 0x77, 0x85, 0x77, 0x85, 0x77, 0x85, 0x77, 0x85, 0x76, + 0x85, 0x75, 0x85, 0x75, 0x85, 0x75, 0x85, 0x75, 0x85, 0x75, 0x86, 0x73, + 0x85, 0x72, 0x85, 0x72, 0x85, 0x73, 0x86, 0x73, 0x87, 0x70, 0x87, 0x70, + 0x87, 0x6f, 0x87, 0x6f, 0x87, 0x6f, 0x87, 0x6c, 0x88, 0x6c, 0x88, 0x69, + 0x89, 0x64, 0x8b, 0x5e, 0x8e, 0x5c, 0x8f, 0x5e, 0x8f, 0x5d, 0x8f, 0x5b, + 0x8f, 0x5a, 0x8e, 0x57, 0x8c, 0x52, 0x91, 0x47, 0x95, 0x45, 0x97, 0x46, + 0x9a, 0x3c, 0x9a, 0x3b, 0x9a, 0x3b, 0x93, 0x43, 0x90, 0x48, 0x91, 0x4b, + 0x92, 0x4a, 0x98, 0x42, 0x9c, 0x42, 0x9b, 0x3f, 0x85, 0x6a, 0x76, 0x7e, + 0x74, 0x79, 0x71, 0x77, 0x70, 0x79, 0x78, 0x84, 0x82, 0x8d, 0x83, 0x8b, + 0x7d, 0x89, 0x73, 0x87, 0x6a, 0x7c, 0x68, 0x7c, 0x66, 0x7e, 0x64, 0x78, + 0x84, 0x57, 0x8f, 0x4d, 0x90, 0x4d, 0x91, 0x4c, 0x92, 0x48, 0x91, 0x48, + 0x91, 0x48, 0x91, 0x48, 0x91, 0x48, 0x90, 0x48, 0x8f, 0x4a, 0x8f, 0x4c, + 0x8f, 0x4c, 0x90, 0x4c, 0x90, 0x4c, 0x92, 0x4a, 0x95, 0x46, 0x98, 0x42, + 0x99, 0x3e, 0x99, 0x3f, 0x99, 0x41, 0x97, 0x44, 0x95, 0x47, 0x93, 0x49, + 0x91, 0x4c, 0x90, 0x4e, 0x90, 0x4f, 0x8e, 0x51, 0x8e, 0x55, 0x8d, 0x58, + 0x8d, 0x57, 0x8d, 0x55, 0x8f, 0x52, 0x8e, 0x51, 0x8f, 0x53, 0x8e, 0x56, + 0x8e, 0x56, 0x8f, 0x54, 0x90, 0x52, 0x8f, 0x52, 0x90, 0x52, 0x90, 0x52, + 0x8e, 0x55, 0x8c, 0x57, 0x8c, 0x59, 0x8c, 0x5b, 0x8a, 0x5b, 0x8a, 0x5c, + 0x8c, 0x5c, 0x8c, 0x5c, 0x58, 0x60, 0x5c, 0x5b, 0x5f, 0x5b, 0x62, 0x5b, + 0x64, 0x5c, 0x64, 0x5d, 0x64, 0x5d, 0x5f, 0x5f, 0x63, 0x64, 0x65, 0x64, + 0x63, 0x62, 0x63, 0x62, 0x63, 0x62, 0x64, 0x63, 0x65, 0x63, 0x6c, 0x62, + 0x86, 0x66, 0x8a, 0x6a, 0x8a, 0x6a, 0x8a, 0x6a, 0x8a, 0x6b, 0x89, 0x6c, + 0x89, 0x6c, 0x89, 0x6e, 0x89, 0x6f, 0x89, 0x6f, 0x89, 0x6f, 0x8a, 0x6f, + 0x8a, 0x70, 0x8a, 0x71, 0x88, 0x72, 0x88, 0x72, 0x87, 0x74, 0x87, 0x75, + 0x87, 0x75, 0x87, 0x75, 0x87, 0x75, 0x87, 0x75, 0x85, 0x77, 0x85, 0x77, + 0x85, 0x77, 0x85, 0x77, 0x85, 0x77, 0x85, 0x77, 0x85, 0x77, 0x84, 0x77, + 0x85, 0x77, 0x85, 0x77, 0x85, 0x77, 0x85, 0x77, 0x85, 0x77, 0x85, 0x77, + 0x85, 0x77, 0x85, 0x77, 0x85, 0x77, 0x85, 0x76, 0x85, 0x75, 0x85, 0x75, + 0x85, 0x75, 0x85, 0x75, 0x86, 0x75, 0x86, 0x74, 0x85, 0x72, 0x86, 0x72, + 0x85, 0x72, 0x85, 0x72, 0x87, 0x70, 0x87, 0x70, 0x87, 0x71, 0x87, 0x71, + 0x87, 0x71, 0x87, 0x6f, 0x87, 0x6c, 0x86, 0x6a, 0x87, 0x69, 0x89, 0x68, + 0x8d, 0x60, 0x8f, 0x5d, 0x8f, 0x5d, 0x8f, 0x5b, 0x8f, 0x59, 0x8e, 0x57, + 0x8a, 0x57, 0x8e, 0x4a, 0x95, 0x41, 0x99, 0x3f, 0x9a, 0x3b, 0x9a, 0x3c, + 0x9a, 0x3b, 0x93, 0x44, 0x91, 0x4a, 0x91, 0x4b, 0x92, 0x4a, 0x98, 0x42, + 0x9c, 0x3f, 0x9b, 0x3f, 0x87, 0x63, 0x7a, 0x7a, 0x79, 0x7b, 0x76, 0x78, + 0x74, 0x78, 0x77, 0x80, 0x82, 0x8c, 0x83, 0x8a, 0x7f, 0x88, 0x77, 0x88, + 0x6c, 0x7c, 0x6a, 0x79, 0x63, 0x7e, 0x63, 0x79, 0x83, 0x58, 0x8f, 0x4d, + 0x90, 0x4c, 0x91, 0x4c, 0x92, 0x4a, 0x91, 0x49, 0x91, 0x4a, 0x90, 0x4a, + 0x8f, 0x49, 0x8f, 0x4a, 0x8f, 0x4c, 0x8f, 0x4d, 0x8f, 0x4d, 0x8f, 0x4c, + 0x90, 0x4c, 0x92, 0x4a, 0x95, 0x44, 0x97, 0x41, 0x97, 0x41, 0x97, 0x42, + 0x96, 0x45, 0x95, 0x49, 0x92, 0x4c, 0x90, 0x4e, 0x8f, 0x50, 0x8e, 0x52, + 0x8d, 0x53, 0x8b, 0x55, 0x8c, 0x58, 0x8b, 0x59, 0x8c, 0x56, 0x8d, 0x55, + 0x8f, 0x52, 0x8e, 0x52, 0x8f, 0x54, 0x8e, 0x57, 0x8e, 0x56, 0x8f, 0x54, + 0x8f, 0x53, 0x90, 0x53, 0x90, 0x53, 0x8f, 0x54, 0x8d, 0x57, 0x8a, 0x59, + 0x89, 0x5a, 0x8a, 0x5c, 0x8a, 0x5c, 0x8b, 0x5c, 0x8c, 0x5c, 0x8c, 0x5c +}; +unsigned int test_d3d9_nv12_yuv_len = 153600; diff --git a/utils/dxvk-1.10.3/tests/d3d9/test_d3d9_triangle.cpp b/utils/dxvk-1.10.3/tests/d3d9/test_d3d9_triangle.cpp new file mode 100644 index 00000000000..5a1bb4a2d66 --- /dev/null +++ b/utils/dxvk-1.10.3/tests/d3d9/test_d3d9_triangle.cpp @@ -0,0 +1,529 @@ +#include + +#include +#include + +#include "../test_utils.h" + +using namespace dxvk; + +struct Extent2D { + uint32_t w, h; +}; + +const std::string g_vertexShaderCode = R"( + +struct VS_INPUT { + float3 Position : POSITION; +}; + +struct VS_OUTPUT { + float4 Position : POSITION; +}; + +VS_OUTPUT main( VS_INPUT IN ) { + VS_OUTPUT OUT; + OUT.Position = float4(IN.Position, 0.6f); + + return OUT; +} + +)"; + +const std::string g_pixelShaderCode = R"( + +struct VS_OUTPUT { + float4 Position : POSITION; +}; + +struct PS_OUTPUT { + float4 Colour : COLOR; +}; + +sampler g_texDepth : register( s0 ); + +PS_OUTPUT main( VS_OUTPUT IN ) { + PS_OUTPUT OUT; + + OUT.Colour = tex2D(g_texDepth, float2(0, 0)); + OUT.Colour = 1.0; + + return OUT; +} + + +)"; + +Logger Logger::s_instance("triangle.log"); + +class TriangleApp { + +public: + + TriangleApp(HINSTANCE instance, HWND window) + : m_window(window) { + HRESULT status = Direct3DCreate9Ex(D3D_SDK_VERSION, &m_d3d); + + if (FAILED(status)) + throw DxvkError("Failed to create D3D9 interface"); + + UINT adapter = D3DADAPTER_DEFAULT; + + D3DADAPTER_IDENTIFIER9 adapterId; + m_d3d->GetAdapterIdentifier(adapter, 0, &adapterId); + + Logger::info(str::format("Using adapter: ", adapterId.Description)); + + auto CheckSRGBFormat = [&](D3DFORMAT fmt, const char* name) { + HRESULT status = m_d3d->CheckDeviceFormat(adapter, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, fmt); + Logger::warn(str::format("(linear) ", name, ": ", SUCCEEDED(status) ? "ok" : "nope")); + + status = m_d3d->CheckDeviceFormat(adapter, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_SRGBREAD, D3DRTYPE_TEXTURE, fmt); + Logger::warn(str::format("(srgb) ", name, ": ", SUCCEEDED(status) ? "ok" : "nope")); + }; + + CheckSRGBFormat(D3DFMT_R5G6B5, "R5G6B5"); + CheckSRGBFormat(D3DFMT_X1R5G5B5, "X1R5G5B5"); + CheckSRGBFormat(D3DFMT_A1R5G5B5, "A1R5G5B5"); + CheckSRGBFormat(D3DFMT_A4R4G4B4, "A4R4G4B4"); + CheckSRGBFormat(D3DFMT_X4R4G4B4, "X4R4G4B4"); + CheckSRGBFormat(D3DFMT_G16R16, "G16R16"); + CheckSRGBFormat(D3DFMT_A2R10G10B10, "A2R10G10B10"); + CheckSRGBFormat(D3DFMT_A16B16G16R16, "A16B16G16R16"); + + // + + DWORD quality; + status = m_d3d->CheckDepthStencilMatch(adapter, D3DDEVTYPE_HAL, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, D3DFMT_D24S8); + status = m_d3d->CheckDeviceFormat(adapter, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0, D3DRTYPE_SURFACE, D3DFMT_A8R8G8B8); + status = m_d3d->CheckDeviceFormatConversion(adapter, D3DDEVTYPE_HAL, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8); + status = m_d3d->CheckDeviceMultiSampleType(adapter, D3DDEVTYPE_HAL, D3DFMT_A8R8G8B8, FALSE, D3DMULTISAMPLE_NONE, &quality); + status = m_d3d->CheckDeviceMultiSampleType(adapter, D3DDEVTYPE_HAL, D3DFMT_A8R8G8B8, TRUE, D3DMULTISAMPLE_NONE, &quality); + status = m_d3d->CheckDeviceType(adapter, D3DDEVTYPE_HAL, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FALSE); + status = m_d3d->CheckDeviceType(adapter, D3DDEVTYPE_HAL, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, TRUE); + + // NULL + constexpr D3DFORMAT NullFormat = D3DFORMAT(MAKEFOURCC('N', 'U', 'L', 'L')); + + status = m_d3d->CheckDepthStencilMatch(adapter, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, NullFormat, D3DFMT_D24S8); + status = m_d3d->CheckDeviceFormat(adapter, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, NullFormat); + status = m_d3d->CheckDeviceFormat(adapter, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, NullFormat); + status = m_d3d->CheckDeviceFormatConversion(adapter, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, NullFormat); + status = m_d3d->CheckDeviceType(adapter, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, NullFormat, false); + status = m_d3d->CheckDeviceType(adapter, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, NullFormat, true); + // + + D3DPRESENT_PARAMETERS params; + getPresentParams(params); + + status = m_d3d->CreateDeviceEx( + adapter, + D3DDEVTYPE_HAL, + m_window, + D3DCREATE_HARDWARE_VERTEXPROCESSING, + ¶ms, + nullptr, + &m_device); + + if (FAILED(status)) + throw DxvkError("Failed to create D3D9 device"); + + // Funny Swapchain Refcounting + // "One of the things COM does really well, is lifecycle management" + // Implicit Swapchain + { + IDirect3DSurface9* pSurface1 = nullptr; + IDirect3DSurface9* pSurface2 = nullptr; + status = m_device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pSurface1); + D3DPRESENT_PARAMETERS newParams = params; + newParams.BackBufferWidth = 10; + newParams.BackBufferHeight = 10; + status = m_device->Reset(&newParams); + status = m_device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pSurface2); + + IDirect3DSwapChain9* pSwapChain2 = nullptr; + IDirect3DSwapChain9* pSwapChain3 = nullptr; + status = pSurface1->GetContainer(__uuidof(IDirect3DSwapChain9), reinterpret_cast(&pSwapChain2)); + status = pSurface2->GetContainer(__uuidof(IDirect3DSwapChain9), reinterpret_cast(&pSwapChain3)); + + printf("E_NOINTERFACE! for pSwapchain2"); + status = m_device->Reset(¶ms); + } + // Additional swapchain + { + IDirect3DSwapChain9* pSwapChain2 = nullptr; + IDirect3DSwapChain9* pSwapChain3 = nullptr; + IDirect3DSwapChain9* pSwapChain4 = nullptr; + IDirect3DSurface9* pSurface = nullptr; + status = m_device->CreateAdditionalSwapChain(¶ms, &pSwapChain2); + status = pSwapChain2->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pSurface); + status = pSurface->GetContainer(__uuidof(IDirect3DSwapChain9), reinterpret_cast(&pSwapChain3)); + pSwapChain2->Release(); + UINT count = pSwapChain2->Release(); + printf("Count: %u - Should be 0 and swapchain dead!", count); + status = pSurface->GetContainer(__uuidof(IDirect3DSwapChain9), reinterpret_cast(&pSwapChain4)); + // E_NOINTERFACE ! + printf("E_NOINTERFACE!"); + } + + m_device->AddRef(); + + Com backbuffer; + m_device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer); + + m_device->AddRef(); + + Com swapchain; + m_device->GetSwapChain(0, &swapchain); + + m_device->AddRef(); + + DWORD bias = 0xDEADBEEF; + status = m_device->GetSamplerState(0, D3DSAMP_MIPMAPLODBIAS, &bias); + status = m_device->SetSamplerState(0, D3DSAMP_MIPMAPLODBIAS, MAKEFOURCC('G', 'E', 'T', '4')); + status = m_device->GetSamplerState(0, D3DSAMP_MIPMAPLODBIAS, &bias); + status = m_device->SetSamplerState(0, D3DSAMP_MIPMAPLODBIAS, MAKEFOURCC('G', 'E', 'T', '1')); + status = m_device->GetSamplerState(0, D3DSAMP_MIPMAPLODBIAS, &bias); + + // Vertex Shader + { + Com blob; + + status = D3DCompile( + g_vertexShaderCode.data(), + g_vertexShaderCode.length(), + nullptr, nullptr, nullptr, + "main", + "vs_2_0", + 0, 0, &blob, + nullptr); + + if (FAILED(status)) + throw DxvkError("Failed to compile vertex shader"); + + status = m_device->CreateVertexShader(reinterpret_cast(blob->GetBufferPointer()), &m_vs); + + if (FAILED(status)) + throw DxvkError("Failed to create vertex shader"); + } + + // Pixel Shader + { + Com blob; + + status = D3DCompile( + g_pixelShaderCode.data(), + g_pixelShaderCode.length(), + nullptr, nullptr, nullptr, + "main", + "ps_2_0", + 0, 0, &blob, + nullptr); + + if (FAILED(status)) + throw DxvkError("Failed to compile pixel shader"); + + status = m_device->CreatePixelShader(reinterpret_cast(blob->GetBufferPointer()), &m_ps); + + if (FAILED(status)) + throw DxvkError("Failed to create pixel shader"); + } + + m_device->SetVertexShader(m_vs.ptr()); + m_device->SetPixelShader(m_ps.ptr()); + + m_device->AddRef(); + + Com nullSurface; + status = m_device->CreateRenderTarget(64, 64, D3DFORMAT(MAKEFOURCC('N', 'U', 'L', 'L')), D3DMULTISAMPLE_NONE, 0, FALSE, &nullSurface, nullptr); + + status = m_device->ColorFill(nullSurface.ptr(), nullptr, D3DCOLOR_RGBA(255, 0, 0, 255)); + + Com defaultTexture; + status = m_device->CreateTexture(64, 64, 1, 0, D3DFMT_DXT3, D3DPOOL_DEFAULT, &defaultTexture, nullptr); + + m_device->AddRef(); + + Com surface; + status = defaultTexture->GetSurfaceLevel(0, &surface); + + m_device->AddRef(); + + Com sysmemTexture; + status = m_device->CreateTexture(64, 64, 1, 0, D3DFMT_DXT3, D3DPOOL_SYSTEMMEM, &sysmemTexture, nullptr); + + Com offscreenSurface; + status = m_device->CreateOffscreenPlainSurfaceEx(64, 64, D3DFMT_DXT3, D3DPOOL_DEFAULT, &offscreenSurface, nullptr, 0); + + D3DLOCKED_RECT offscreenLock; + status = offscreenSurface->LockRect(&offscreenLock, nullptr, 0); + + std::memset(offscreenLock.pBits, 0xFF, offscreenLock.Pitch * (64 / 4)); + + status = offscreenSurface->UnlockRect(); + + //status = m_device->ColorFill(offscreenSurface.ptr(), nullptr, D3DCOLOR_ARGB(255, 255, 0, 0)); + + D3DLOCKED_RECT sysmemLock; + status = sysmemTexture->LockRect(0, &sysmemLock, nullptr, 0); + + //D3DLOCKED_RECT offscreenLock; + status = offscreenSurface->LockRect(&offscreenLock, nullptr, 0); + + std::memcpy(sysmemLock.pBits, offscreenLock.pBits, offscreenLock.Pitch * (64 / 4)); + + sysmemTexture->UnlockRect(0); + offscreenSurface->UnlockRect(); + + status = m_device->UpdateTexture(sysmemTexture.ptr(), defaultTexture.ptr()); + + status = m_device->SetTexture(0, defaultTexture.ptr()); + + Com rt; + status = m_device->CreateRenderTarget(1280, 720, D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &rt, nullptr); + + m_device->AddRef(); + + Com rt2; + status = m_device->CreateRenderTarget(1280, 720, D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &rt2, nullptr); + + m_device->AddRef(); + + rt2 = nullptr; + + m_device->AddRef(); + + RECT stretchRect1 = { 0, 0, 640, 720 }; + RECT stretchRect2 = { 640, 0, 1280, 720 }; + status = m_device->StretchRect(rt.ptr(), &stretchRect1, rt.ptr(), &stretchRect2, D3DTEXF_LINEAR); + + /// + + Com ds; + //status = m_device->CreateDepthStencilSurface(1274, 695, D3DFMT_D24X8, D3DMULTISAMPLE_NONE, 0, FALSE, &ds, nullptr); + status = m_device->CreateDepthStencilSurface(1280, 720, D3DFMT_D24X8, D3DMULTISAMPLE_NONE, 0, FALSE, &ds, nullptr); + + status = m_device->SetDepthStencilSurface(ds.ptr()); + status = m_device->SetRenderState(D3DRS_ZWRITEENABLE, 1); + status = m_device->SetRenderState(D3DRS_ZENABLE, 1); + status = m_device->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL); + + + + std::array vertices = { + 0.0f, 0.5f, 0.0f, + 0.5f, -0.5f, 0.0f, + -0.5f, -0.5f, 0.0f, + }; + + const size_t vbSize = vertices.size() * sizeof(float); + + status = m_device->CreateVertexBuffer(vbSize, 0, 0, D3DPOOL_DEFAULT, &m_vb, nullptr); + if (FAILED(status)) + throw DxvkError("Failed to create vertex buffer"); + + void* data = nullptr; + status = m_vb->Lock(0, 0, &data, 0); + if (FAILED(status)) + throw DxvkError("Failed to lock vertex buffer"); + + std::memcpy(data, vertices.data(), vbSize); + + status = m_vb->Unlock(); + if (FAILED(status)) + throw DxvkError("Failed to unlock vertex buffer"); + + m_device->SetStreamSource(0, m_vb.ptr(), 0, 3 * sizeof(float)); + + std::array elements; + + elements[0].Method = 0; + elements[0].Offset = 0; + elements[0].Stream = 0; + elements[0].Type = D3DDECLTYPE_FLOAT3; + elements[0].Usage = D3DDECLUSAGE_POSITION; + elements[0].UsageIndex = 0; + + elements[1] = D3DDECL_END(); + + HRESULT result = m_device->CreateVertexDeclaration(elements.data(), &m_decl); + if (FAILED(result)) + throw DxvkError("Failed to create vertex decl"); + + m_device->SetVertexDeclaration(m_decl.ptr()); + + /// + + Com myRT; + status = m_device->CreateTexture(512, 256, 1, 0, D3DFMT_DXT1, D3DPOOL_DEFAULT, &myRT, nullptr); + + Com myRTSurf; + myRT->GetSurfaceLevel(0, &myRTSurf); + + Com myCopyThing; + status = m_device->CreateTexture(512, 256, 1, 0, D3DFMT_DXT1, D3DPOOL_DEFAULT, &myCopyThing, nullptr); + + Com myCopyThingSurf; + myCopyThing->GetSurfaceLevel(0, &myCopyThingSurf); + + status = m_device->StretchRect(myRTSurf.ptr(), nullptr, myCopyThingSurf.ptr(), nullptr, D3DTEXF_NONE); + + D3DLOCKED_RECT rect; + status = myCopyThing->LockRect(0, &rect, nullptr, D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK); + + m_device->SetRenderState(D3DRS_ALPHAREF, 256 + 255); + m_device->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_LESSEQUAL); + m_device->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE); + } + + void run() { + this->adjustBackBuffer(); + + m_device->BeginScene(); + + m_device->Clear( + 0, + nullptr, + D3DCLEAR_TARGET, + D3DCOLOR_RGBA(44, 62, 80, 0), + 0, + 0); + + m_device->Clear( + 0, + nullptr, + D3DCLEAR_ZBUFFER, + 0, + 0.5f, + 0); + + m_device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1); + + m_device->EndScene(); + + m_device->PresentEx( + nullptr, + nullptr, + nullptr, + nullptr, + 0); + } + + void adjustBackBuffer() { + RECT windowRect = { 0, 0, 1024, 600 }; + GetClientRect(m_window, &windowRect); + + Extent2D newSize = { + static_cast(windowRect.right - windowRect.left), + static_cast(windowRect.bottom - windowRect.top), + }; + + if (m_windowSize.w != newSize.w + || m_windowSize.h != newSize.h) { + m_windowSize = newSize; + + D3DPRESENT_PARAMETERS params; + getPresentParams(params); + HRESULT status = m_device->ResetEx(¶ms, nullptr); + + if (FAILED(status)) + throw DxvkError("Device reset failed"); + } + } + + void getPresentParams(D3DPRESENT_PARAMETERS& params) { + params.AutoDepthStencilFormat = D3DFMT_UNKNOWN; + params.BackBufferCount = 1; + params.BackBufferFormat = D3DFMT_X8R8G8B8; + params.BackBufferWidth = m_windowSize.w; + params.BackBufferHeight = m_windowSize.h; + params.EnableAutoDepthStencil = 0; + params.Flags = 0; + params.FullScreen_RefreshRateInHz = 0; + params.hDeviceWindow = m_window; + params.MultiSampleQuality = 0; + params.MultiSampleType = D3DMULTISAMPLE_NONE; + params.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + params.SwapEffect = D3DSWAPEFFECT_DISCARD; + params.Windowed = TRUE; + } + +private: + + HWND m_window; + Extent2D m_windowSize = { 1024, 600 }; + + Com m_d3d; + Com m_device; + + Com m_vs; + Com m_ps; + Com m_vb; + Com m_decl; + +}; + +LRESULT CALLBACK WindowProc(HWND hWnd, + UINT message, + WPARAM wParam, + LPARAM lParam); + +int WINAPI WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) { + HWND hWnd; + WNDCLASSEXW wc; + ZeroMemory(&wc, sizeof(WNDCLASSEX)); + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = WindowProc; + wc.hInstance = hInstance; + wc.hCursor = LoadCursor(nullptr, IDC_ARROW); + wc.hbrBackground = (HBRUSH)COLOR_WINDOW; + wc.lpszClassName = L"WindowClass1"; + RegisterClassExW(&wc); + + hWnd = CreateWindowExW(0, + L"WindowClass1", + L"Our First Windowed Program", + WS_OVERLAPPEDWINDOW, + 300, 300, + 640, 480, + nullptr, + nullptr, + hInstance, + nullptr); + ShowWindow(hWnd, nCmdShow); + + MSG msg; + + try { + TriangleApp app(hInstance, hWnd); + + while (true) { + if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + + if (msg.message == WM_QUIT) + return msg.wParam; + } else { + app.run(); + } + } + } catch (const dxvk::DxvkError& e) { + std::cerr << e.message() << std::endl; + return msg.wParam; + } +} + +LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { + switch (message) { + case WM_CLOSE: + PostQuitMessage(0); + return 0; + } + + return DefWindowProc(hWnd, message, wParam, lParam); +} diff --git a/utils/dxvk-1.10.3/tests/d3d9/test_d3d9_up.cpp b/utils/dxvk-1.10.3/tests/d3d9/test_d3d9_up.cpp new file mode 100644 index 00000000000..8ef137c9af3 --- /dev/null +++ b/utils/dxvk-1.10.3/tests/d3d9/test_d3d9_up.cpp @@ -0,0 +1,429 @@ +#include + +#include +#include + +#include "../test_utils.h" + +using namespace dxvk; + +struct Extent2D { + uint32_t w, h; +}; + +const std::string g_vertexShaderCode = R"( + +struct VS_INPUT { + float3 Position : POSITION; + float3 TexCoord : TEXCOORD0; +}; + +struct VS_OUTPUT { + float4 Position : POSITION; + float3 TexCoord : TEXCOORD0; +}; + +VS_OUTPUT main( VS_INPUT IN ) { + VS_OUTPUT OUT; + OUT.Position = float4(IN.Position, 0.6f); + OUT.TexCoord = IN.TexCoord; + + return OUT; +} + +)"; + +const std::string g_pixelShaderCode = R"( + +struct VS_OUTPUT { + float4 Position : POSITION; + float3 TexCoord : TEXCOORD0; +}; + +struct PS_OUTPUT { + float4 Colour : COLOR; +}; + +sampler g_texDepth : register( s0 ); + +PS_OUTPUT main( VS_OUTPUT IN ) { + PS_OUTPUT OUT; + + //OUT.Colour = tex2D(g_texDepth, float2(0, 0)); + //OUT.Colour = 1.0; + + OUT.Colour = float4(IN.TexCoord.xyz, 1.0); + + return OUT; +} + + +)"; + +Logger Logger::s_instance("triangle.log"); + +class TriangleApp { + +public: + + TriangleApp(HINSTANCE instance, HWND window) + : m_window(window) { + HRESULT status = Direct3DCreate9Ex(D3D_SDK_VERSION, &m_d3d); + + if (FAILED(status)) + throw DxvkError("Failed to create D3D9 interface"); + + UINT adapter = D3DADAPTER_DEFAULT; + + D3DADAPTER_IDENTIFIER9 adapterId; + m_d3d->GetAdapterIdentifier(adapter, 0, &adapterId); + + Logger::info(str::format("Using adapter: ", adapterId.Description)); + + auto CheckSRGBFormat = [&](D3DFORMAT fmt, const char* name) { + HRESULT status = m_d3d->CheckDeviceFormat(adapter, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, fmt); + Logger::warn(str::format("(linear) ", name, ": ", SUCCEEDED(status) ? "ok" : "nope")); + + status = m_d3d->CheckDeviceFormat(adapter, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_SRGBREAD, D3DRTYPE_TEXTURE, fmt); + Logger::warn(str::format("(srgb) ", name, ": ", SUCCEEDED(status) ? "ok" : "nope")); + }; + + CheckSRGBFormat(D3DFMT_R5G6B5, "R5G6B5"); + CheckSRGBFormat(D3DFMT_X1R5G5B5, "X1R5G5B5"); + CheckSRGBFormat(D3DFMT_A1R5G5B5, "A1R5G5B5"); + CheckSRGBFormat(D3DFMT_A4R4G4B4, "A4R4G4B4"); + CheckSRGBFormat(D3DFMT_X4R4G4B4, "X4R4G4B4"); + CheckSRGBFormat(D3DFMT_G16R16, "G16R16"); + CheckSRGBFormat(D3DFMT_A2R10G10B10, "A2R10G10B10"); + CheckSRGBFormat(D3DFMT_A16B16G16R16, "A16B16G16R16"); + + // + + DWORD quality; + status = m_d3d->CheckDepthStencilMatch(adapter, D3DDEVTYPE_HAL, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, D3DFMT_D24S8); + status = m_d3d->CheckDeviceFormat(adapter, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0, D3DRTYPE_SURFACE, D3DFMT_A8R8G8B8); + status = m_d3d->CheckDeviceFormatConversion(adapter, D3DDEVTYPE_HAL, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8); + status = m_d3d->CheckDeviceMultiSampleType(adapter, D3DDEVTYPE_HAL, D3DFMT_A8R8G8B8, FALSE, D3DMULTISAMPLE_NONE, &quality); + status = m_d3d->CheckDeviceMultiSampleType(adapter, D3DDEVTYPE_HAL, D3DFMT_A8R8G8B8, TRUE, D3DMULTISAMPLE_NONE, &quality); + status = m_d3d->CheckDeviceType(adapter, D3DDEVTYPE_HAL, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FALSE); + status = m_d3d->CheckDeviceType(adapter, D3DDEVTYPE_HAL, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, TRUE); + + // NULL + constexpr D3DFORMAT NullFormat = D3DFORMAT(MAKEFOURCC('N', 'U', 'L', 'L')); + + status = m_d3d->CheckDepthStencilMatch(adapter, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, NullFormat, D3DFMT_D24S8); + status = m_d3d->CheckDeviceFormat(adapter, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, NullFormat); + status = m_d3d->CheckDeviceFormat(adapter, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, NullFormat); + status = m_d3d->CheckDeviceFormatConversion(adapter, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, NullFormat); + status = m_d3d->CheckDeviceType(adapter, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, NullFormat, false); + status = m_d3d->CheckDeviceType(adapter, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, NullFormat, true); + // + + D3DPRESENT_PARAMETERS params; + getPresentParams(params); + + status = m_d3d->CreateDeviceEx( + adapter, + D3DDEVTYPE_HAL, + m_window, + D3DCREATE_HARDWARE_VERTEXPROCESSING, + ¶ms, + nullptr, + &m_device); + + if (FAILED(status)) + throw DxvkError("Failed to create D3D9 device"); + + // Funny Swapchain Refcounting + // "One of the things COM does really well, is lifecycle management" + // Implicit Swapchain + { + IDirect3DSurface9* pSurface1 = nullptr; + IDirect3DSurface9* pSurface2 = nullptr; + status = m_device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pSurface1); + D3DPRESENT_PARAMETERS newParams = params; + newParams.BackBufferWidth = 10; + newParams.BackBufferHeight = 10; + status = m_device->Reset(&newParams); + status = m_device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pSurface2); + + IDirect3DSwapChain9* pSwapChain2 = nullptr; + IDirect3DSwapChain9* pSwapChain3 = nullptr; + status = pSurface1->GetContainer(__uuidof(IDirect3DSwapChain9), reinterpret_cast(&pSwapChain2)); + status = pSurface2->GetContainer(__uuidof(IDirect3DSwapChain9), reinterpret_cast(&pSwapChain3)); + + printf("E_NOINTERFACE! for pSwapchain2"); + status = m_device->Reset(¶ms); + } + // Additional swapchain + { + IDirect3DSwapChain9* pSwapChain2 = nullptr; + IDirect3DSwapChain9* pSwapChain3 = nullptr; + IDirect3DSwapChain9* pSwapChain4 = nullptr; + IDirect3DSurface9* pSurface = nullptr; + status = m_device->CreateAdditionalSwapChain(¶ms, &pSwapChain2); + status = pSwapChain2->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pSurface); + status = pSurface->GetContainer(__uuidof(IDirect3DSwapChain9), reinterpret_cast(&pSwapChain3)); + pSwapChain2->Release(); + UINT count = pSwapChain2->Release(); + printf("Count: %u - Should be 0 and swapchain dead!", count); + status = pSurface->GetContainer(__uuidof(IDirect3DSwapChain9), reinterpret_cast(&pSwapChain4)); + // E_NOINTERFACE ! + printf("E_NOINTERFACE!"); + } + + m_device->AddRef(); + + Com backbuffer; + m_device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer); + + m_device->AddRef(); + + Com swapchain; + m_device->GetSwapChain(0, &swapchain); + + m_device->AddRef(); + + DWORD bias = 0xDEADBEEF; + status = m_device->GetSamplerState(0, D3DSAMP_MIPMAPLODBIAS, &bias); + status = m_device->SetSamplerState(0, D3DSAMP_MIPMAPLODBIAS, MAKEFOURCC('G', 'E', 'T', '4')); + status = m_device->GetSamplerState(0, D3DSAMP_MIPMAPLODBIAS, &bias); + status = m_device->SetSamplerState(0, D3DSAMP_MIPMAPLODBIAS, MAKEFOURCC('G', 'E', 'T', '1')); + status = m_device->GetSamplerState(0, D3DSAMP_MIPMAPLODBIAS, &bias); + + // Vertex Shader + { + Com blob; + + status = D3DCompile( + g_vertexShaderCode.data(), + g_vertexShaderCode.length(), + nullptr, nullptr, nullptr, + "main", + "vs_2_0", + 0, 0, &blob, + nullptr); + + if (FAILED(status)) + throw DxvkError("Failed to compile vertex shader"); + + status = m_device->CreateVertexShader(reinterpret_cast(blob->GetBufferPointer()), &m_vs); + + if (FAILED(status)) + throw DxvkError("Failed to create vertex shader"); + } + + // Pixel Shader + { + Com blob; + + status = D3DCompile( + g_pixelShaderCode.data(), + g_pixelShaderCode.length(), + nullptr, nullptr, nullptr, + "main", + "ps_2_0", + 0, 0, &blob, + nullptr); + + if (FAILED(status)) + throw DxvkError("Failed to compile pixel shader"); + + status = m_device->CreatePixelShader(reinterpret_cast(blob->GetBufferPointer()), &m_ps); + + if (FAILED(status)) + throw DxvkError("Failed to create pixel shader"); + } + + m_device->SetVertexShader(m_vs.ptr()); + m_device->SetPixelShader(m_ps.ptr()); + + m_device->AddRef(); + } + + void run() { + this->adjustBackBuffer(); + + m_device->BeginScene(); + + m_device->Clear( + 0, + nullptr, + D3DCLEAR_TARGET, + D3DCOLOR_RGBA(44, 62, 80, 0), + 0, + 0); + + m_device->Clear( + 0, + nullptr, + D3DCLEAR_ZBUFFER, + 0, + 0.5f, + 0); + + m_decl = nullptr; + + std::array elements; + + elements[0].Method = 0; + elements[0].Offset = 0; + elements[0].Stream = 0; + elements[0].Type = D3DDECLTYPE_FLOAT3; + elements[0].Usage = D3DDECLUSAGE_POSITION; + elements[0].UsageIndex = 0; + + elements[1].Method = 0; + elements[1].Offset = 12; + elements[1].Stream = 0; + elements[1].Type = D3DDECLTYPE_FLOAT3; + elements[1].Usage = D3DDECLUSAGE_TEXCOORD; + elements[1].UsageIndex = 0; + + elements[2] = D3DDECL_END(); + + HRESULT result = m_device->CreateVertexDeclaration(elements.data(), &m_decl); + if (FAILED(result)) + throw DxvkError("Failed to create vertex decl"); + + m_device->SetVertexDeclaration(m_decl.ptr()); + + float vertexData[] = { + -1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, -1, 0, 1, 1, -1, -1, 0, 0, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + }; + + m_device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, vertexData, 20); + //m_device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 3, vertexData, 20); + + //m_device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1); + + m_device->EndScene(); + + m_device->PresentEx( + nullptr, + nullptr, + nullptr, + nullptr, + 0); + } + + void adjustBackBuffer() { + RECT windowRect = { 0, 0, 1024, 600 }; + GetClientRect(m_window, &windowRect); + + Extent2D newSize = { + static_cast(windowRect.right - windowRect.left), + static_cast(windowRect.bottom - windowRect.top), + }; + + if (m_windowSize.w != newSize.w + || m_windowSize.h != newSize.h) { + m_windowSize = newSize; + + D3DPRESENT_PARAMETERS params; + getPresentParams(params); + HRESULT status = m_device->ResetEx(¶ms, nullptr); + + if (FAILED(status)) + throw DxvkError("Device reset failed"); + } + } + + void getPresentParams(D3DPRESENT_PARAMETERS& params) { + params.AutoDepthStencilFormat = D3DFMT_UNKNOWN; + params.BackBufferCount = 1; + params.BackBufferFormat = D3DFMT_X8R8G8B8; + params.BackBufferWidth = m_windowSize.w; + params.BackBufferHeight = m_windowSize.h; + params.EnableAutoDepthStencil = 0; + params.Flags = 0; + params.FullScreen_RefreshRateInHz = 0; + params.hDeviceWindow = m_window; + params.MultiSampleQuality = 0; + params.MultiSampleType = D3DMULTISAMPLE_NONE; + params.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + params.SwapEffect = D3DSWAPEFFECT_DISCARD; + params.Windowed = TRUE; + } + +private: + + HWND m_window; + Extent2D m_windowSize = { 1024, 600 }; + + Com m_d3d; + Com m_device; + + Com m_vs; + Com m_ps; + Com m_vb; + Com m_decl; + +}; + +LRESULT CALLBACK WindowProc(HWND hWnd, + UINT message, + WPARAM wParam, + LPARAM lParam); + +int WINAPI WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) { + HWND hWnd; + WNDCLASSEXW wc; + ZeroMemory(&wc, sizeof(WNDCLASSEX)); + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = WindowProc; + wc.hInstance = hInstance; + wc.hCursor = LoadCursor(nullptr, IDC_ARROW); + wc.hbrBackground = (HBRUSH)COLOR_WINDOW; + wc.lpszClassName = L"WindowClass1"; + RegisterClassExW(&wc); + + hWnd = CreateWindowExW(0, + L"WindowClass1", + L"Our First Windowed Program", + WS_OVERLAPPEDWINDOW, + 300, 300, + 640, 480, + nullptr, + nullptr, + hInstance, + nullptr); + ShowWindow(hWnd, nCmdShow); + + MSG msg; + + try { + TriangleApp app(hInstance, hWnd); + + while (true) { + if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + + if (msg.message == WM_QUIT) + return msg.wParam; + } else { + app.run(); + } + } + } catch (const dxvk::DxvkError& e) { + std::cerr << e.message() << std::endl; + return msg.wParam; + } +} + +LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { + switch (message) { + case WM_CLOSE: + PostQuitMessage(0); + return 0; + } + + return DefWindowProc(hWnd, message, wParam, lParam); +} diff --git a/utils/dxvk-1.10.3/tests/dxbc/meson.build b/utils/dxvk-1.10.3/tests/dxbc/meson.build new file mode 100644 index 00000000000..54a3533e428 --- /dev/null +++ b/utils/dxvk-1.10.3/tests/dxbc/meson.build @@ -0,0 +1,6 @@ +test_dxbc_deps = [ dxbc_dep, dxvk_dep ] + +executable('dxbc-compiler'+exe_ext, files('test_dxbc_compiler.cpp'), dependencies : test_dxbc_deps, install : true, gui_app : true) +executable('dxbc-disasm'+exe_ext, files('test_dxbc_disasm.cpp'), dependencies : [ test_dxbc_deps, lib_d3dcompiler_47 ], install : true, gui_app : true) +executable('hlsl-compiler'+exe_ext, files('test_hlsl_compiler.cpp'), dependencies : [ test_dxbc_deps, lib_d3dcompiler_47 ], install : true, gui_app : true) + diff --git a/utils/dxvk-1.10.3/tests/dxbc/test_dxbc_compiler.cpp b/utils/dxvk-1.10.3/tests/dxbc/test_dxbc_compiler.cpp new file mode 100644 index 00000000000..735604d77fd --- /dev/null +++ b/utils/dxvk-1.10.3/tests/dxbc/test_dxbc_compiler.cpp @@ -0,0 +1,58 @@ +#include +#include + +#include "../../src/dxbc/dxbc_module.h" +#include "../../src/dxvk/dxvk_shader.h" + +#include +#include +#include + +namespace dxvk { + Logger Logger::s_instance("dxbc-compiler.log"); +} + +using namespace dxvk; + +int WINAPI WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) { + int argc = 0; + LPWSTR* argv = CommandLineToArgvW( + GetCommandLineW(), &argc); + + if (argc < 3) { + Logger::err("Usage: dxbc-compiler input.dxbc output.spv"); + return 1; + } + + try { + std::string ifileName = str::fromws(argv[1]); + std::ifstream ifile(ifileName, std::ios::binary); + ifile.ignore(std::numeric_limits::max()); + std::streamsize length = ifile.gcount(); + ifile.clear(); + + ifile.seekg(0, std::ios_base::beg); + std::vector dxbcCode(length); + ifile.read(dxbcCode.data(), length); + + DxbcReader reader(dxbcCode.data(), dxbcCode.size()); + DxbcModule module(reader); + + DxbcModuleInfo moduleInfo; + moduleInfo.options.useSubgroupOpsForAtomicCounters = true; + moduleInfo.options.useDemoteToHelperInvocation = true; + moduleInfo.options.minSsboAlignment = 4; + moduleInfo.xfb = nullptr; + + Rc shader = module.compile(moduleInfo, ifileName); + std::ofstream ofile(str::fromws(argv[2]), std::ios::binary); + shader->dump(ofile); + return 0; + } catch (const DxvkError& e) { + Logger::err(e.message()); + return 1; + } +} diff --git a/utils/dxvk-1.10.3/tests/dxbc/test_dxbc_disasm.cpp b/utils/dxvk-1.10.3/tests/dxbc/test_dxbc_disasm.cpp new file mode 100644 index 00000000000..c87ec352920 --- /dev/null +++ b/utils/dxvk-1.10.3/tests/dxbc/test_dxbc_disasm.cpp @@ -0,0 +1,60 @@ +#include +#include + +#include + +#include +#include +#include + +#include "../../src/util/com/com_pointer.h" + +using namespace dxvk; + +int WINAPI WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) { + int argc = 0; + LPWSTR* argv = CommandLineToArgvW( + GetCommandLineW(), &argc); + + if (argc < 2 || argc > 3) { + std::cerr << "Usage: dxbc-disasm input.dxbc [output]" << std::endl; + return 1; + } + + Com assembly; + Com binary; + + // input file + if (FAILED(D3DReadFileToBlob(argv[1], &binary))) { + std::cerr << "Failed to read shader" << std::endl; + return 1; + } + + HRESULT hr = D3DDisassemble( + binary->GetBufferPointer(), + binary->GetBufferSize(), + D3D_DISASM_ENABLE_INSTRUCTION_NUMBERING, nullptr, + &assembly); + + if (FAILED(hr)) { + std::cerr << "Failed to disassemble shader" << std::endl; + return 1; + } + + // output file variant + if (argc == 3 && FAILED(D3DWriteBlobToFile(assembly.ptr(), argv[2], 1))) { + std::cerr << "Failed to write shader" << std::endl; + return 1; + } + + // stdout variant + if (argc == 2) { + std::string data((const char *)assembly->GetBufferPointer(), assembly->GetBufferSize()); + std::cout << data; + } + + return 0; +} diff --git a/utils/dxvk-1.10.3/tests/dxbc/test_hlsl_compiler.cpp b/utils/dxvk-1.10.3/tests/dxbc/test_hlsl_compiler.cpp new file mode 100644 index 00000000000..29707e3bb86 --- /dev/null +++ b/utils/dxvk-1.10.3/tests/dxbc/test_hlsl_compiler.cpp @@ -0,0 +1,110 @@ +#include +#include +#include + +#include + +#include +#include +#include + +#include "../test_utils.h" + +using namespace dxvk; + +int WINAPI WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) { + int argc = 0; + LPWSTR* argv = CommandLineToArgvW( + GetCommandLineW(), &argc); + + if (argc < 5) { + std::cerr << "Usage: hlsl-compiler target entrypoint input.hlsl output.dxbc [--strip] [--text]" << std::endl; + return 1; + } + + bool strip = false; + bool text = false; + + for (int i = 5; i < argc; i++) { + strip |= str::fromws(argv[i]) == "--strip"; + text |= str::fromws(argv[i]) == "--text"; + } + + const LPWSTR target = argv[1]; + const LPWSTR entryPoint = argv[2]; + const LPWSTR inputFile = argv[3]; + const LPWSTR outputFile = argv[4]; + + std::ifstream ifile(str::fromws(inputFile), std::ios::binary); + ifile.ignore(std::numeric_limits::max()); + std::streamsize length = ifile.gcount(); + ifile.clear(); + + ifile.seekg(0, std::ios_base::beg); + std::vector hlslCode(length); + ifile.read(hlslCode.data(), length); + + Com binary; + Com errors; + + HRESULT hr = D3DCompile( + hlslCode.data(), + hlslCode.size(), + "Shader", nullptr, + D3D_COMPILE_STANDARD_FILE_INCLUDE, + str::fromws(entryPoint).c_str(), + str::fromws(target).c_str(), + D3DCOMPILE_OPTIMIZATION_LEVEL3 | + D3DCOMPILE_ENABLE_UNBOUNDED_DESCRIPTOR_TABLES, + 0, &binary, &errors); + + if (FAILED(hr)) { + if (errors != nullptr) + std::cerr << reinterpret_cast(errors->GetBufferPointer()) << std::endl; + return 1; + } + + if (strip) { + Com strippedBlob; + + hr = D3DStripShader(binary->GetBufferPointer(), binary->GetBufferSize(), + D3DCOMPILER_STRIP_REFLECTION_DATA | D3DCOMPILER_STRIP_DEBUG_INFO, + &strippedBlob); + + if (FAILED(hr)) { + std::cerr << "Failed to strip shader" << std::endl; + return 1; + } + + binary = strippedBlob; + } + + std::ofstream file; + + if (str::fromws(outputFile) != "-") + file = std::ofstream(str::fromws(outputFile), std::ios::binary | std::ios::trunc); + + std::ostream& outputStream = file.is_open() ? file : std::cout; + + if (text) { + auto data = reinterpret_cast(binary->GetBufferPointer()); + auto size = binary->GetBufferSize() / sizeof(uint32_t); + + outputStream << std::hex; + + for (uint32_t i = 0; i < size; i++) { + if (i && !(i & 0x7)) + outputStream << std::endl; + outputStream << "0x" << std::setfill('0') << std::setw(8) << data[i] << ", "; + } + + outputStream << std::endl; + } else { + outputStream.write(reinterpret_cast(binary->GetBufferPointer()), binary->GetBufferSize()); + } + + return 0; +} diff --git a/utils/dxvk-1.10.3/tests/dxgi/meson.build b/utils/dxvk-1.10.3/tests/dxgi/meson.build new file mode 100644 index 00000000000..0151d90cb21 --- /dev/null +++ b/utils/dxvk-1.10.3/tests/dxgi/meson.build @@ -0,0 +1,3 @@ +test_dxgi_deps = [ util_dep, lib_dxgi ] + +executable('dxgi-factory'+exe_ext, files('test_dxgi_factory.cpp'), dependencies : test_dxgi_deps, install: true, gui_app : true) diff --git a/utils/dxvk-1.10.3/tests/dxgi/test_dxgi_factory.cpp b/utils/dxvk-1.10.3/tests/dxgi/test_dxgi_factory.cpp new file mode 100644 index 00000000000..526be92ed6f --- /dev/null +++ b/utils/dxvk-1.10.3/tests/dxgi/test_dxgi_factory.cpp @@ -0,0 +1,123 @@ +#include + +#include + +#include +#include + +#include "../test_utils.h" + +using namespace dxvk; + +int WINAPI WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) { + Com factory; + + if (CreateDXGIFactory(__uuidof(IDXGIFactory), + reinterpret_cast(&factory)) != S_OK) { + std::cerr << "Failed to create DXGI factory" << std::endl; + return 1; + } + + Com adapter; + + for (UINT i = 0; factory->EnumAdapters(i, &adapter) == S_OK; i++) { + DXGI_ADAPTER_DESC adapterDesc; + + if (adapter->GetDesc(&adapterDesc) != S_OK) { + std::cerr << "Failed to get DXGI adapter info" << std::endl; + return 1; + } + + DXGI_ADAPTER_DESC desc; + + if (adapter->GetDesc(&desc) != S_OK) { + std::cerr << "Failed to get DXGI adapter info" << std::endl; + return 1; + } + + std::cout << str::format("Adapter ", i, ":") << std::endl; + std::cout << str::format(" ", desc.Description) << std::endl; + std::cout << str::format(" Vendor: ", desc.VendorId) << std::endl; + std::cout << str::format(" Device: ", desc.DeviceId) << std::endl; + std::cout << str::format(" Dedicated RAM: ", desc.DedicatedVideoMemory) << std::endl; + std::cout << str::format(" Shared RAM: ", desc.SharedSystemMemory) << std::endl; + + Com output; + + for (UINT j = 0; adapter->EnumOutputs(j, &output) == S_OK; j++) { + std::vector modes; + + DXGI_OUTPUT_DESC desc; + + if (output->GetDesc(&desc) != S_OK) { + std::cerr << "Failed to get DXGI output info" << std::endl; + return 1; + } + + std::cout << str::format(" Output ", j, ":") << std::endl; + std::cout << str::format(" ", desc.DeviceName) << std::endl; + std::cout << str::format(" Coordinates: ", + desc.DesktopCoordinates.left, ",", + desc.DesktopCoordinates.top, ":", + desc.DesktopCoordinates.right - desc.DesktopCoordinates.left, "x", + desc.DesktopCoordinates.bottom - desc.DesktopCoordinates.top) << std::endl; + + HRESULT status = S_OK; + UINT displayModeCount = 0; + + do { + if (output->GetDisplayModeList( + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_ENUM_MODES_SCALING, + &displayModeCount, nullptr) != S_OK) { + std::cerr << "Failed to get DXGI output display mode count" << std::endl; + return 1; + } + + modes.resize(displayModeCount); + + status = output->GetDisplayModeList( + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_ENUM_MODES_SCALING, + &displayModeCount, modes.data()); + } while (status == DXGI_ERROR_MORE_DATA); + + if (status != S_OK) { + std::cerr << "Failed to get DXGI output display mode list" << std::endl; + return 1; + } + + for (auto mode : modes) { + std::cout << str::format(" ", + mode.Width, "x", mode.Height, " @ ", + mode.RefreshRate.Numerator / mode.RefreshRate.Denominator, + mode.Scaling == DXGI_MODE_SCALING_CENTERED ? " (native)" : "") << std::endl; + + //test matching modes + DXGI_MODE_DESC matched_mode{ 0 }; + status = output->FindClosestMatchingMode(&mode, &matched_mode, nullptr); + + if (status != S_OK) { + std::cerr << "Failed to get matching mode" << std::endl; + return 1; + } + + if (matched_mode.Width != mode.Width || + matched_mode.Height != mode.Height || + matched_mode.RefreshRate.Numerator != mode.RefreshRate.Numerator || + matched_mode.RefreshRate.Denominator != mode.RefreshRate.Denominator || + matched_mode.Format != mode.Format) + { + std::cerr << "Matched mode is incorrect" << std::endl; + return 1; + } + } + } + } + + return 0; +} + diff --git a/utils/dxvk-1.10.3/tests/meson.build b/utils/dxvk-1.10.3/tests/meson.build new file mode 100644 index 00000000000..54fb3d631bc --- /dev/null +++ b/utils/dxvk-1.10.3/tests/meson.build @@ -0,0 +1,4 @@ +subdir('d3d9') +subdir('d3d11') +subdir('dxbc') +subdir('dxgi') diff --git a/utils/dxvk-1.10.3/tests/test_utils.h b/utils/dxvk-1.10.3/tests/test_utils.h new file mode 100644 index 00000000000..363aa95fbab --- /dev/null +++ b/utils/dxvk-1.10.3/tests/test_utils.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +#include "../src/util/com/com_guid.h" +#include "../src/util/com/com_object.h" +#include "../src/util/com/com_pointer.h" + +#include "../src/util/log/log.h" +#include "../src/util/log/log_debug.h" + +#include "../src/util/rc/util_rc.h" +#include "../src/util/rc/util_rc_ptr.h" + +#include "../src/util/util_enum.h" +#include "../src/util/util_error.h" +#include "../src/util/util_string.h" diff --git a/utils/dxvk-1.10.3/version.h.in b/utils/dxvk-1.10.3/version.h.in new file mode 100644 index 00000000000..e9cc1c3a2e1 --- /dev/null +++ b/utils/dxvk-1.10.3/version.h.in @@ -0,0 +1,3 @@ +#pragma once + +#define DXVK_VERSION "@VCS_TAG@"