mirror of
https://github.com/obsproject/obs-studio.git
synced 2026-08-29 02:03:03 +08:00
libobs-d3d11: Implement shader cache
Co-Authored-By: derrod <dennis@obsproject.com>
This commit is contained in:
@@ -567,6 +567,12 @@ static bool MakeUserDirs()
|
||||
return false;
|
||||
if (!do_mkdir(path))
|
||||
return false;
|
||||
|
||||
if (GetProgramDataPath(path, sizeof(path), "obs-studio/shader-cache") <=
|
||||
0)
|
||||
return false;
|
||||
if (!do_mkdir(path))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
#ifdef WHATSNEW_ENABLED
|
||||
|
||||
@@ -21,6 +21,11 @@
|
||||
#include <graphics/vec3.h>
|
||||
#include <graphics/matrix3.h>
|
||||
#include <graphics/matrix4.h>
|
||||
#include <util/platform.h>
|
||||
#include <util/util.hpp>
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
|
||||
void gs_vertex_shader::GetBuffersExpected(
|
||||
const vector<D3D11_INPUT_ELEMENT_DESC> &inputs)
|
||||
@@ -200,24 +205,63 @@ void gs_shader::BuildConstantBuffer()
|
||||
gs_shader_set_default(¶ms[i]);
|
||||
}
|
||||
|
||||
static uint64_t fnv1a_hash(const char *str)
|
||||
{
|
||||
const uint64_t FNV_OFFSET = 14695981039346656037ULL;
|
||||
const uint64_t FNV_PRIME = 1099511628211ULL;
|
||||
uint64_t hash = FNV_OFFSET;
|
||||
while (*str) {
|
||||
hash ^= (uint64_t)*str++;
|
||||
hash *= FNV_PRIME;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
void gs_shader::Compile(const char *shaderString, const char *file,
|
||||
const char *target, ID3D10Blob **shader)
|
||||
{
|
||||
ComPtr<ID3D10Blob> errorsBlob;
|
||||
HRESULT hr;
|
||||
|
||||
char hashstr[20];
|
||||
|
||||
if (!shaderString)
|
||||
throw "No shader string specified";
|
||||
|
||||
hr = device->d3dCompile(shaderString, strlen(shaderString), file, NULL,
|
||||
NULL, "main", target,
|
||||
D3D10_SHADER_OPTIMIZATION_LEVEL1, 0, shader,
|
||||
errorsBlob.Assign());
|
||||
if (FAILED(hr)) {
|
||||
if (errorsBlob != NULL && errorsBlob->GetBufferSize())
|
||||
throw ShaderError(errorsBlob, hr);
|
||||
else
|
||||
throw HRError("Failed to compile shader", hr);
|
||||
uint64_t hash = fnv1a_hash(shaderString);
|
||||
snprintf(hashstr, sizeof(hashstr), "%02llx", hash);
|
||||
|
||||
BPtr program_data =
|
||||
os_get_program_data_path_ptr("obs-studio/shader-cache");
|
||||
auto cachePath = filesystem::u8path(program_data.Get()) / hashstr;
|
||||
|
||||
std::fstream cacheFile;
|
||||
if (filesystem::exists(cachePath) && !filesystem::is_empty(cachePath))
|
||||
cacheFile.open(cachePath, ios::in | ios::binary | ios::ate);
|
||||
|
||||
if (cacheFile.is_open()) {
|
||||
streampos len = cacheFile.tellg();
|
||||
cacheFile.seekg(0, ios::beg);
|
||||
|
||||
device->d3dCreateBlob(len, shader);
|
||||
cacheFile.read((char *)(*shader)->GetBufferPointer(), len);
|
||||
} else {
|
||||
hr = device->d3dCompile(shaderString, strlen(shaderString),
|
||||
file, NULL, NULL, "main", target,
|
||||
D3D10_SHADER_OPTIMIZATION_LEVEL3, 0,
|
||||
shader, errorsBlob.Assign());
|
||||
if (FAILED(hr)) {
|
||||
if (errorsBlob != NULL && errorsBlob->GetBufferSize())
|
||||
throw ShaderError(errorsBlob, hr);
|
||||
else
|
||||
throw HRError("Failed to compile shader", hr);
|
||||
}
|
||||
|
||||
cacheFile.open(cachePath, ios::out | ios::binary);
|
||||
if (cacheFile.is_open()) {
|
||||
cacheFile.write((char *)(*shader)->GetBufferPointer(),
|
||||
(*shader)->GetBufferSize());
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DISASSEMBLE_SHADERS
|
||||
|
||||
@@ -294,12 +294,14 @@ void gs_device::InitCompiler()
|
||||
if (module) {
|
||||
d3dCompile = (pD3DCompile)GetProcAddress(module,
|
||||
"D3DCompile");
|
||||
d3dCreateBlob = (pD3DCreateBlob)GetProcAddress(
|
||||
module, "D3DCreateBlob");
|
||||
|
||||
#ifdef DISASSEMBLE_SHADERS
|
||||
d3dDisassemble = (pD3DDisassemble)GetProcAddress(
|
||||
module, "D3DDisassemble");
|
||||
#endif
|
||||
if (d3dCompile) {
|
||||
if (d3dCompile && d3dCreateBlob) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,9 @@
|
||||
|
||||
// #define DISASSEMBLE_SHADERS
|
||||
|
||||
typedef HRESULT(WINAPI *pD3DCreateBlob)(_In_ SIZE_T Size,
|
||||
_Out_ ID3DBlob **ppBlob);
|
||||
|
||||
struct shader_var;
|
||||
struct shader_sampler;
|
||||
struct gs_vertex_shader;
|
||||
@@ -1052,6 +1055,7 @@ struct gs_device {
|
||||
D3D11_PRIMITIVE_TOPOLOGY curToplogy;
|
||||
|
||||
pD3DCompile d3dCompile = nullptr;
|
||||
pD3DCreateBlob d3dCreateBlob = nullptr;
|
||||
#ifdef DISASSEMBLE_SHADERS
|
||||
pD3DDisassemble d3dDisassemble = nullptr;
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user