power_play/src/dxc.cpp
2025-07-25 13:43:47 -05:00

70 lines
2.3 KiB
C++

extern "C"
{
#include "dxc.h"
#include "arena.h"
#include "string.h"
}
#pragma clang diagnostic ignored "-Wlanguage-extension-token"
#include <Windows.h>
#include <atlbase.h>
#include <dxcapi.h>
#include <d3d12shader.h>
#pragma comment(lib, "d3dcompiler")
#pragma comment(lib, "dxcompiler")
/* https://github.com/microsoft/DirectXShaderCompiler/wiki/Using-dxc.exe-and-dxcompiler.dll */
struct dxc_compile_result dxc_compile(struct arena *arena, string shader_source, i32 num_args, struct string *args)
{
__prof;
struct arena_temp scratch = scratch_begin(arena);
struct dxc_compile_result res = ZI;
wchar_t **wstr_args = arena_push_array(scratch.arena, wchar_t *, num_args);
for (i32 i = 0; i < num_args; ++i) {
wstr_args[i] = wstr_from_string(scratch.arena, args[i]);
}
DxcBuffer dxc_src_buffer = ZI;
dxc_src_buffer.Ptr = shader_source.text;
dxc_src_buffer.Size = shader_source.len;
dxc_src_buffer.Encoding = DXC_CP_UTF8;
/* Init compiler */
CComPtr<IDxcUtils> dxc_utils;
CComPtr<IDxcCompiler3> dxc_compiler;
CComPtr<IDxcIncludeHandler> dxc_include_handler;
DxcCreateInstance(CLSID_DxcUtils, IID_PPV_ARGS(&dxc_utils));
DxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(&dxc_compiler));
dxc_utils->CreateDefaultIncludeHandler(&dxc_include_handler);
/* Compile */
CComPtr<IDxcResult> compile_results = 0;
dxc_compiler->Compile(&dxc_src_buffer, (LPCWSTR *)wstr_args, num_args, dxc_include_handler, IID_PPV_ARGS(&compile_results));
/* Copy errors */
CComPtr<IDxcBlobUtf8> dxc_errors = 0;
compile_results->GetOutput(DXC_OUT_ERRORS, IID_PPV_ARGS(&dxc_errors), 0);
if (dxc_errors != 0) {
res.errors = string_copy(arena, STRING(dxc_errors->GetStringLength(), (u8 *)dxc_errors->GetBufferPointer()));
}
/* Get status */
HRESULT dxc_hr = 0;
compile_results->GetStatus(&dxc_hr);
res.success = SUCCEEDED(dxc_hr);
/* Copy shader output */
if (res.success) {
CComPtr<IDxcBlob> dxc_shader = 0;
compile_results->GetOutput(DXC_OUT_OBJECT, IID_PPV_ARGS(&dxc_shader), 0);
if (dxc_shader != 0) {
res.dxc = string_copy(arena, STRING(dxc_shader->GetBufferSize(), (u8 *)dxc_shader->GetBufferPointer()));
}
}
scratch_end(scratch);
return res;
}