mirror of
https://github.com/hedge-dev/UnleashedRecomp.git
synced 2026-04-27 04:41:39 +00:00
Allow DXIL linking to happen in parallel.
This commit is contained in:
parent
1bcf0aacd8
commit
f3f9d969c8
3 changed files with 79 additions and 59 deletions
|
|
@ -472,12 +472,7 @@ static void DestructTempResources()
|
||||||
case ResourceType::VertexShader:
|
case ResourceType::VertexShader:
|
||||||
case ResourceType::PixelShader:
|
case ResourceType::PixelShader:
|
||||||
{
|
{
|
||||||
const auto shader = reinterpret_cast<GuestShader*>(resource);
|
reinterpret_cast<GuestShader*>(resource)->~GuestShader();
|
||||||
|
|
||||||
for (auto blob : shader->shaderBlobs)
|
|
||||||
blob->Release();
|
|
||||||
|
|
||||||
shader->~GuestShader();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2466,20 +2461,17 @@ static void ProcSetScissorRect(const RenderCommand& cmd)
|
||||||
SetDirtyValue<int32_t>(g_dirtyStates.scissorRect, g_scissorRect.right, args.right);
|
SetDirtyValue<int32_t>(g_dirtyStates.scissorRect, g_scissorRect.right, args.right);
|
||||||
}
|
}
|
||||||
|
|
||||||
static IDxcCompiler3* g_dxcCompiler;
|
static Mutex g_compiledSpecConstantLibraryBlobMutex;
|
||||||
static IDxcLinker* g_dxcLinker;
|
static ankerl::unordered_dense::map<uint32_t, ComPtr<IDxcBlob>> g_compiledSpecConstantLibraryBlobs;
|
||||||
static IDxcUtils* g_dxcUtils;
|
|
||||||
static ankerl::unordered_dense::set<uint32_t> g_compiledSpecConstantLibraryBlobs;
|
|
||||||
static Mutex g_linkMutex;
|
|
||||||
|
|
||||||
static RenderShader* GetOrLinkShader(GuestShader* guestShader, uint32_t specConstants)
|
static RenderShader* GetOrLinkShader(GuestShader* guestShader, uint32_t specConstants)
|
||||||
{
|
{
|
||||||
std::lock_guard lock(g_linkMutex); // TODO: VERY BAD!!!!!!!!!!
|
|
||||||
|
|
||||||
if (g_vulkan ||
|
if (g_vulkan ||
|
||||||
guestShader->shaderCacheEntry == nullptr ||
|
guestShader->shaderCacheEntry == nullptr ||
|
||||||
guestShader->shaderCacheEntry->specConstantsMask == 0)
|
guestShader->shaderCacheEntry->specConstantsMask == 0)
|
||||||
{
|
{
|
||||||
|
std::lock_guard lock(guestShader->mutex);
|
||||||
|
|
||||||
if (guestShader->shader == nullptr)
|
if (guestShader->shader == nullptr)
|
||||||
{
|
{
|
||||||
assert(guestShader->shaderCacheEntry != nullptr);
|
assert(guestShader->shaderCacheEntry != nullptr);
|
||||||
|
|
@ -2495,18 +2487,33 @@ static RenderShader* GetOrLinkShader(GuestShader* guestShader, uint32_t specCons
|
||||||
|
|
||||||
specConstants &= guestShader->shaderCacheEntry->specConstantsMask;
|
specConstants &= guestShader->shaderCacheEntry->specConstantsMask;
|
||||||
|
|
||||||
auto& shader = guestShader->linkedShaders[specConstants];
|
RenderShader* shader;
|
||||||
|
{
|
||||||
|
std::lock_guard lock(guestShader->mutex);
|
||||||
|
shader = guestShader->linkedShaders[specConstants].get();
|
||||||
|
}
|
||||||
|
|
||||||
if (shader == nullptr)
|
if (shader == nullptr)
|
||||||
{
|
{
|
||||||
|
thread_local ComPtr<IDxcCompiler3> s_dxcCompiler;
|
||||||
|
thread_local ComPtr<IDxcLinker> s_dxcLinker;
|
||||||
|
thread_local ComPtr<IDxcUtils> s_dxcUtils;
|
||||||
|
|
||||||
wchar_t specConstantsLibName[0x100];
|
wchar_t specConstantsLibName[0x100];
|
||||||
swprintf_s(specConstantsLibName, L"SpecConstants_%d", specConstants);
|
swprintf_s(specConstantsLibName, L"SpecConstants_%d", specConstants);
|
||||||
|
|
||||||
if (!g_compiledSpecConstantLibraryBlobs.contains(specConstants))
|
ComPtr<IDxcBlob> specConstantLibraryBlob;
|
||||||
{
|
{
|
||||||
if (g_dxcCompiler == nullptr)
|
std::lock_guard lock(g_compiledSpecConstantLibraryBlobMutex);
|
||||||
|
specConstantLibraryBlob = g_compiledSpecConstantLibraryBlobs[specConstants];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (specConstantLibraryBlob == nullptr)
|
||||||
{
|
{
|
||||||
HRESULT hr = DxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(&g_dxcCompiler));
|
if (s_dxcCompiler == nullptr)
|
||||||
assert(SUCCEEDED(hr) && g_dxcCompiler != nullptr);
|
{
|
||||||
|
HRESULT hr = DxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(s_dxcCompiler.GetAddressOf()));
|
||||||
|
assert(SUCCEEDED(hr) && s_dxcCompiler != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
char libraryHlsl[0x100];
|
char libraryHlsl[0x100];
|
||||||
|
|
@ -2519,74 +2526,83 @@ static RenderShader* GetOrLinkShader(GuestShader* guestShader, uint32_t specCons
|
||||||
const wchar_t* args[1];
|
const wchar_t* args[1];
|
||||||
args[0] = L"-T lib_6_3";
|
args[0] = L"-T lib_6_3";
|
||||||
|
|
||||||
IDxcResult* result = nullptr;
|
ComPtr<IDxcResult> result;
|
||||||
HRESULT hr = g_dxcCompiler->Compile(&buffer, args, std::size(args), nullptr, IID_PPV_ARGS(&result));
|
HRESULT hr = s_dxcCompiler->Compile(&buffer, args, std::size(args), nullptr, IID_PPV_ARGS(result.GetAddressOf()));
|
||||||
assert(SUCCEEDED(hr) && result != nullptr);
|
assert(SUCCEEDED(hr) && result != nullptr);
|
||||||
|
|
||||||
if (g_dxcLinker == nullptr)
|
hr = result->GetResult(specConstantLibraryBlob.GetAddressOf());
|
||||||
|
assert(SUCCEEDED(hr) && specConstantLibraryBlob != nullptr);
|
||||||
|
|
||||||
|
std::lock_guard lock(g_compiledSpecConstantLibraryBlobMutex);
|
||||||
|
g_compiledSpecConstantLibraryBlobs.emplace(specConstants, specConstantLibraryBlob);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s_dxcLinker == nullptr)
|
||||||
{
|
{
|
||||||
HRESULT hr = DxcCreateInstance(CLSID_DxcLinker, IID_PPV_ARGS(&g_dxcLinker));
|
HRESULT hr = DxcCreateInstance(CLSID_DxcLinker, IID_PPV_ARGS(s_dxcLinker.GetAddressOf()));
|
||||||
assert(SUCCEEDED(hr) && g_dxcLinker != nullptr);
|
assert(SUCCEEDED(hr) && s_dxcLinker != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
IDxcBlob* blob = nullptr;
|
s_dxcLinker->RegisterLibrary(specConstantsLibName, specConstantLibraryBlob.Get());
|
||||||
hr = result->GetResult(&blob);
|
|
||||||
assert(SUCCEEDED(hr) && blob != nullptr);
|
|
||||||
|
|
||||||
g_dxcLinker->RegisterLibrary(specConstantsLibName, blob);
|
|
||||||
|
|
||||||
blob->Release();
|
|
||||||
result->Release();
|
|
||||||
|
|
||||||
g_compiledSpecConstantLibraryBlobs.emplace(specConstants);
|
|
||||||
}
|
|
||||||
|
|
||||||
wchar_t shaderLibName[0x100];
|
wchar_t shaderLibName[0x100];
|
||||||
swprintf_s(shaderLibName, L"Shader_%d", guestShader->shaderCacheEntry->dxilOffset);
|
swprintf_s(shaderLibName, L"Shader_%d", guestShader->shaderCacheEntry->dxilOffset);
|
||||||
|
|
||||||
if (!guestShader->libraryRegistered)
|
ComPtr<IDxcBlobEncoding> shaderLibraryBlob;
|
||||||
{
|
{
|
||||||
if (g_dxcUtils == nullptr)
|
std::lock_guard lock(guestShader->mutex);
|
||||||
{
|
shaderLibraryBlob = guestShader->libraryBlob;
|
||||||
HRESULT hr = DxcCreateInstance(CLSID_DxcUtils, IID_PPV_ARGS(&g_dxcUtils));
|
|
||||||
assert(SUCCEEDED(hr) && g_dxcUtils != nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IDxcBlobEncoding* blob = nullptr;
|
if (shaderLibraryBlob == nullptr)
|
||||||
HRESULT hr = g_dxcUtils->CreateBlobFromPinned(
|
{
|
||||||
|
if (s_dxcUtils == nullptr)
|
||||||
|
{
|
||||||
|
HRESULT hr = DxcCreateInstance(CLSID_DxcUtils, IID_PPV_ARGS(s_dxcUtils.GetAddressOf()));
|
||||||
|
assert(SUCCEEDED(hr) && s_dxcUtils != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT hr = s_dxcUtils->CreateBlobFromPinned(
|
||||||
g_shaderCache.get() + guestShader->shaderCacheEntry->dxilOffset,
|
g_shaderCache.get() + guestShader->shaderCacheEntry->dxilOffset,
|
||||||
guestShader->shaderCacheEntry->dxilSize,
|
guestShader->shaderCacheEntry->dxilSize,
|
||||||
DXC_CP_ACP,
|
DXC_CP_ACP,
|
||||||
&blob);
|
shaderLibraryBlob.GetAddressOf());
|
||||||
|
|
||||||
assert(SUCCEEDED(hr) && blob != nullptr);
|
assert(SUCCEEDED(hr) && shaderLibraryBlob != nullptr);
|
||||||
|
|
||||||
g_dxcLinker->RegisterLibrary(shaderLibName, blob);
|
std::lock_guard lock(guestShader->mutex);
|
||||||
|
guestShader->libraryBlob = shaderLibraryBlob;
|
||||||
blob->Release();
|
|
||||||
|
|
||||||
guestShader->libraryRegistered = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s_dxcLinker->RegisterLibrary(shaderLibName, shaderLibraryBlob.Get());
|
||||||
|
|
||||||
const wchar_t* libraryNames[] = { specConstantsLibName, shaderLibName };
|
const wchar_t* libraryNames[] = { specConstantsLibName, shaderLibName };
|
||||||
|
|
||||||
IDxcOperationResult* result = nullptr;
|
ComPtr<IDxcOperationResult> result;
|
||||||
HRESULT hr = g_dxcLinker->Link(L"main", guestShader->type == ResourceType::VertexShader ? L"vs_6_0" : L"ps_6_0",
|
HRESULT hr = s_dxcLinker->Link(L"main", guestShader->type == ResourceType::VertexShader ? L"vs_6_0" : L"ps_6_0",
|
||||||
libraryNames, std::size(libraryNames), nullptr, 0, &result);
|
libraryNames, std::size(libraryNames), nullptr, 0, result.GetAddressOf());
|
||||||
|
|
||||||
assert(SUCCEEDED(hr) && result != nullptr);
|
assert(SUCCEEDED(hr) && result != nullptr);
|
||||||
|
|
||||||
IDxcBlob* blob = nullptr;
|
ComPtr<IDxcBlob> blob;
|
||||||
hr = result->GetResult(&blob);
|
hr = result->GetResult(blob.GetAddressOf());
|
||||||
assert(SUCCEEDED(hr) && blob != nullptr);
|
assert(SUCCEEDED(hr) && blob != nullptr);
|
||||||
|
|
||||||
shader = g_device->createShader(blob->GetBufferPointer(), blob->GetBufferSize(), "main", RenderShaderFormat::DXIL);
|
{
|
||||||
guestShader->shaderBlobs.push_back(blob);
|
std::lock_guard lock(guestShader->mutex);
|
||||||
|
|
||||||
result->Release();
|
auto& linkedShader = guestShader->linkedShaders[specConstants];
|
||||||
|
if (linkedShader == nullptr)
|
||||||
|
{
|
||||||
|
linkedShader = g_device->createShader(blob->GetBufferPointer(), blob->GetBufferSize(), "main", RenderShaderFormat::DXIL);
|
||||||
|
guestShader->shaderBlobs.push_back(std::move(blob));
|
||||||
}
|
}
|
||||||
|
|
||||||
return shader.get();
|
shader = linkedShader.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SanitizePipelineState(PipelineState& pipelineState)
|
static void SanitizePipelineState(PipelineState& pipelineState)
|
||||||
|
|
|
||||||
|
|
@ -240,11 +240,12 @@ struct GuestVertexDeclaration : GuestResource
|
||||||
// VertexShader/PixelShader
|
// VertexShader/PixelShader
|
||||||
struct GuestShader : GuestResource
|
struct GuestShader : GuestResource
|
||||||
{
|
{
|
||||||
|
Mutex mutex;
|
||||||
std::unique_ptr<RenderShader> shader;
|
std::unique_ptr<RenderShader> shader;
|
||||||
struct ShaderCacheEntry* shaderCacheEntry = nullptr;
|
struct ShaderCacheEntry* shaderCacheEntry = nullptr;
|
||||||
ankerl::unordered_dense::map<uint32_t, std::unique_ptr<RenderShader>> linkedShaders;
|
ankerl::unordered_dense::map<uint32_t, std::unique_ptr<RenderShader>> linkedShaders;
|
||||||
std::vector<IDxcBlob*> shaderBlobs;
|
std::vector<ComPtr<IDxcBlob>> shaderBlobs;
|
||||||
bool libraryRegistered = false;
|
ComPtr<IDxcBlobEncoding> libraryBlob;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GuestViewport
|
struct GuestViewport
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,9 @@
|
||||||
#include <imgui_impl_sdl2.h>
|
#include <imgui_impl_sdl2.h>
|
||||||
#include <o1heap.h>
|
#include <o1heap.h>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <wrl/client.h>
|
||||||
|
|
||||||
|
using Microsoft::WRL::ComPtr;
|
||||||
|
|
||||||
#include "framework.h"
|
#include "framework.h"
|
||||||
#include "mutex.h"
|
#include "mutex.h"
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue