mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-04 20:38:06 +02:00
d3d12: use dxil_validator
Now that we have a shiny, new dxil validator interface, let's start using it in the D3D12 gallium driver. Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15751>
This commit is contained in:
parent
193cf76c09
commit
1e570962ef
5 changed files with 49 additions and 246 deletions
|
|
@ -46,57 +46,14 @@
|
|||
#include <directx/d3d12.h>
|
||||
#include <dxguids/dxguids.h>
|
||||
|
||||
#include <dxcapi.h>
|
||||
#include <wrl/client.h>
|
||||
|
||||
extern "C" {
|
||||
#include "tgsi/tgsi_parse.h"
|
||||
#include "tgsi/tgsi_point_sprite.h"
|
||||
}
|
||||
|
||||
using Microsoft::WRL::ComPtr;
|
||||
|
||||
struct d3d12_validation_tools
|
||||
{
|
||||
d3d12_validation_tools();
|
||||
|
||||
bool validate_and_sign(struct blob *dxil);
|
||||
|
||||
void disassemble(struct blob *dxil);
|
||||
|
||||
void load_dxil_dll();
|
||||
|
||||
struct HModule {
|
||||
HModule();
|
||||
~HModule();
|
||||
|
||||
bool load(LPCSTR file_name);
|
||||
operator util_dl_library *() const;
|
||||
private:
|
||||
util_dl_library *module;
|
||||
};
|
||||
|
||||
HModule dxil_module;
|
||||
HModule dxc_compiler_module;
|
||||
ComPtr<IDxcCompiler> compiler;
|
||||
ComPtr<IDxcValidator> validator;
|
||||
ComPtr<IDxcLibrary> library;
|
||||
};
|
||||
|
||||
struct d3d12_validation_tools *d3d12_validator_create()
|
||||
{
|
||||
d3d12_validation_tools *tools = new d3d12_validation_tools();
|
||||
if (tools->validator)
|
||||
return tools;
|
||||
delete tools;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void d3d12_validator_destroy(struct d3d12_validation_tools *validator)
|
||||
{
|
||||
delete validator;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "dxil_validator.h"
|
||||
#endif
|
||||
|
||||
const void *
|
||||
d3d12_get_compiler_options(struct pipe_screen *screen,
|
||||
|
|
@ -227,13 +184,34 @@ compile_nir(struct d3d12_context *ctx, struct d3d12_shader_selector *sel,
|
|||
shader->cb_bindings[shader->num_cb_bindings++].binding = i;
|
||||
}
|
||||
}
|
||||
if (ctx->validation_tools) {
|
||||
ctx->validation_tools->validate_and_sign(&tmp);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (ctx->dxil_validator) {
|
||||
if (!(d3d12_debug & D3D12_DEBUG_EXPERIMENTAL)) {
|
||||
char *err;
|
||||
if (!dxil_validate_module(ctx->dxil_validator, tmp.data,
|
||||
tmp.size, &err) && err) {
|
||||
debug_printf(
|
||||
"== VALIDATION ERROR =============================================\n"
|
||||
"%s\n"
|
||||
"== END ==========================================================\n",
|
||||
err);
|
||||
ralloc_free(err);
|
||||
}
|
||||
}
|
||||
|
||||
if (d3d12_debug & D3D12_DEBUG_DISASS) {
|
||||
ctx->validation_tools->disassemble(&tmp);
|
||||
char *str = dxil_disasm_module(ctx->dxil_validator, tmp.data,
|
||||
tmp.size);
|
||||
fprintf(stderr,
|
||||
"== BEGIN SHADER ============================================\n"
|
||||
"%s\n"
|
||||
"== END SHADER ==============================================\n",
|
||||
str);
|
||||
ralloc_free(str);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
blob_finish_get_buffer(&tmp, &shader->bytecode, &shader->bytecode_length);
|
||||
|
||||
|
|
@ -1467,183 +1445,3 @@ d3d12_shader_free(struct d3d12_shader_selector *sel)
|
|||
ralloc_free(sel->initial);
|
||||
ralloc_free(sel);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// Used to get path to self
|
||||
extern "C" extern IMAGE_DOS_HEADER __ImageBase;
|
||||
#endif
|
||||
|
||||
void d3d12_validation_tools::load_dxil_dll()
|
||||
{
|
||||
if (!dxil_module.load(UTIL_DL_PREFIX "dxil" UTIL_DL_EXT)) {
|
||||
#ifdef _WIN32
|
||||
char selfPath[MAX_PATH] = "";
|
||||
uint32_t pathSize = GetModuleFileNameA((HINSTANCE)&__ImageBase, selfPath, sizeof(selfPath));
|
||||
if (pathSize == 0 || pathSize == sizeof(selfPath)) {
|
||||
debug_printf("D3D12: Unable to get path to self");
|
||||
return;
|
||||
}
|
||||
|
||||
auto lastSlash = strrchr(selfPath, '\\');
|
||||
if (!lastSlash) {
|
||||
debug_printf("D3D12: Unable to get path to self");
|
||||
return;
|
||||
}
|
||||
|
||||
*(lastSlash + 1) = '\0';
|
||||
if (strcat_s(selfPath, "dxil.dll") != 0) {
|
||||
debug_printf("D3D12: Unable to get path to dxil.dll next to self");
|
||||
return;
|
||||
}
|
||||
|
||||
dxil_module.load(selfPath);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
d3d12_validation_tools::d3d12_validation_tools()
|
||||
{
|
||||
load_dxil_dll();
|
||||
DxcCreateInstanceProc dxil_create_func = (DxcCreateInstanceProc)util_dl_get_proc_address(dxil_module, "DxcCreateInstance");
|
||||
|
||||
if (dxil_create_func) {
|
||||
HRESULT hr = dxil_create_func(CLSID_DxcValidator, IID_PPV_ARGS(&validator));
|
||||
if (FAILED(hr)) {
|
||||
debug_printf("D3D12: Unable to create validator\n");
|
||||
}
|
||||
}
|
||||
#ifdef _WIN32
|
||||
else if (!(d3d12_debug & D3D12_DEBUG_EXPERIMENTAL)) {
|
||||
debug_printf("D3D12: Unable to load DXIL.dll\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
DxcCreateInstanceProc compiler_create_func = nullptr;
|
||||
if(dxc_compiler_module.load("dxcompiler.dll"))
|
||||
compiler_create_func = (DxcCreateInstanceProc)util_dl_get_proc_address(dxc_compiler_module, "DxcCreateInstance");
|
||||
|
||||
if (compiler_create_func) {
|
||||
HRESULT hr = compiler_create_func(CLSID_DxcLibrary, IID_PPV_ARGS(&library));
|
||||
if (FAILED(hr)) {
|
||||
debug_printf("D3D12: Unable to create library instance: %x\n", hr);
|
||||
}
|
||||
|
||||
if (d3d12_debug & D3D12_DEBUG_DISASS) {
|
||||
hr = compiler_create_func(CLSID_DxcCompiler, IID_PPV_ARGS(&compiler));
|
||||
if (FAILED(hr)) {
|
||||
debug_printf("D3D12: Unable to create compiler instance\n");
|
||||
}
|
||||
}
|
||||
} else if (d3d12_debug & D3D12_DEBUG_DISASS) {
|
||||
debug_printf("D3D12: Disassembly requested but compiler couldn't be loaded\n");
|
||||
}
|
||||
}
|
||||
|
||||
d3d12_validation_tools::HModule::HModule():
|
||||
module(0)
|
||||
{
|
||||
}
|
||||
|
||||
d3d12_validation_tools::HModule::~HModule()
|
||||
{
|
||||
if (module)
|
||||
util_dl_close(module);
|
||||
}
|
||||
|
||||
inline
|
||||
d3d12_validation_tools::HModule::operator util_dl_library * () const
|
||||
{
|
||||
return module;
|
||||
}
|
||||
|
||||
bool
|
||||
d3d12_validation_tools::HModule::load(LPCSTR file_name)
|
||||
{
|
||||
module = util_dl_open(file_name);
|
||||
return module != nullptr;
|
||||
}
|
||||
|
||||
|
||||
class ShaderBlob : public IDxcBlob {
|
||||
public:
|
||||
ShaderBlob(blob* data) : m_data(data) {}
|
||||
|
||||
LPVOID STDMETHODCALLTYPE GetBufferPointer(void) override { return m_data->data; }
|
||||
|
||||
SIZE_T STDMETHODCALLTYPE GetBufferSize() override { return m_data->size; }
|
||||
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void**) override { return E_NOINTERFACE; }
|
||||
|
||||
ULONG STDMETHODCALLTYPE AddRef() override { return 1; }
|
||||
|
||||
ULONG STDMETHODCALLTYPE Release() override { return 0; }
|
||||
|
||||
blob* m_data;
|
||||
};
|
||||
|
||||
bool d3d12_validation_tools::validate_and_sign(struct blob *dxil)
|
||||
{
|
||||
ShaderBlob source(dxil);
|
||||
|
||||
ComPtr<IDxcOperationResult> result;
|
||||
|
||||
validator->Validate(&source, DxcValidatorFlags_InPlaceEdit, &result);
|
||||
HRESULT validationStatus;
|
||||
result->GetStatus(&validationStatus);
|
||||
if (FAILED(validationStatus)) {
|
||||
if (!library) {
|
||||
debug_printf("D3D12: validation failed, but lacking "
|
||||
"IDxcLibrary for proper diagnostics.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
ComPtr<IDxcBlobEncoding> printBlob, printBlobUtf8;
|
||||
result->GetErrorBuffer(&printBlob);
|
||||
library->GetBlobAsUtf8(printBlob.Get(), printBlobUtf8.GetAddressOf());
|
||||
|
||||
char *errorString;
|
||||
if (printBlobUtf8) {
|
||||
errorString = reinterpret_cast<char*>(printBlobUtf8->GetBufferPointer());
|
||||
|
||||
errorString[printBlobUtf8->GetBufferSize() - 1] = 0;
|
||||
debug_printf("== VALIDATION ERROR =============================================\n%s\n"
|
||||
"== END ==========================================================\n",
|
||||
errorString);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
void d3d12_validation_tools::disassemble(struct blob *dxil)
|
||||
{
|
||||
if (!compiler) {
|
||||
fprintf(stderr, "D3D12: No Disassembler\n");
|
||||
return;
|
||||
}
|
||||
ShaderBlob source(dxil);
|
||||
IDxcBlobEncoding* pDisassembly = nullptr;
|
||||
|
||||
if (FAILED(compiler->Disassemble(&source, &pDisassembly))) {
|
||||
fprintf(stderr, "D3D12: Disassembler failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ComPtr<IDxcBlobEncoding> dissassably(pDisassembly);
|
||||
ComPtr<IDxcBlobEncoding> blobUtf8;
|
||||
library->GetBlobAsUtf8(pDisassembly, blobUtf8.GetAddressOf());
|
||||
if (!blobUtf8) {
|
||||
fprintf(stderr, "D3D12: Unable to get utf8 encoding\n");
|
||||
return;
|
||||
}
|
||||
|
||||
char *disassembly = reinterpret_cast<char*>(blobUtf8->GetBufferPointer());
|
||||
disassembly[blobUtf8->GetBufferSize() - 1] = 0;
|
||||
|
||||
fprintf(stderr, "== BEGIN SHADER ============================================\n"
|
||||
"%s\n"
|
||||
"== END SHADER ==============================================\n",
|
||||
disassembly);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,10 +59,6 @@ enum d3d12_state_var {
|
|||
|
||||
#define D3D12_MAX_POINT_SIZE 255.0f
|
||||
|
||||
struct d3d12_validation_tools *d3d12_validator_create();
|
||||
|
||||
void d3d12_validator_destroy(struct d3d12_validation_tools *validator);
|
||||
|
||||
const void *
|
||||
d3d12_get_compiler_options(struct pipe_screen *screen,
|
||||
enum pipe_shader_ir ir,
|
||||
|
|
|
|||
|
|
@ -57,12 +57,19 @@ extern "C" {
|
|||
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "dxil_validator.h"
|
||||
#endif
|
||||
|
||||
static void
|
||||
d3d12_context_destroy(struct pipe_context *pctx)
|
||||
{
|
||||
struct d3d12_context *ctx = d3d12_context(pctx);
|
||||
if (ctx->validation_tools)
|
||||
d3d12_validator_destroy(ctx->validation_tools);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (ctx->dxil_validator)
|
||||
dxil_destroy_validator(ctx->dxil_validator);
|
||||
#endif
|
||||
|
||||
if (ctx->timestamp_query)
|
||||
pctx->destroy_query(pctx, ctx->timestamp_query);
|
||||
|
|
@ -2511,7 +2518,11 @@ d3d12_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
|
|||
}
|
||||
d3d12_init_null_sampler(ctx);
|
||||
|
||||
ctx->validation_tools = d3d12_validator_create();
|
||||
#ifdef _WIN32
|
||||
if (!(d3d12_debug & D3D12_DEBUG_EXPERIMENTAL) ||
|
||||
(d3d12_debug & D3D12_DEBUG_DISASS))
|
||||
ctx->dxil_validator = dxil_create_validator(NULL);
|
||||
#endif
|
||||
|
||||
ctx->blitter = util_blitter_create(&ctx->base);
|
||||
if (!ctx->blitter)
|
||||
|
|
|
|||
|
|
@ -151,7 +151,10 @@ struct d3d12_shader_state {
|
|||
|
||||
struct blitter_context;
|
||||
struct primconvert_context;
|
||||
struct d3d12_validation_tools;
|
||||
|
||||
#ifdef _WIN32
|
||||
struct dxil_validator;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
class ResourceStateManager;
|
||||
|
|
@ -246,7 +249,9 @@ struct d3d12_context {
|
|||
struct d3d12_descriptor_handle null_sampler;
|
||||
|
||||
PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE D3D12SerializeVersionedRootSignature;
|
||||
struct d3d12_validation_tools *validation_tools;
|
||||
#ifdef _WIN32
|
||||
struct dxil_validator *dxil_validator;
|
||||
#endif
|
||||
|
||||
struct d3d12_resource *current_predication;
|
||||
bool predication_condition;
|
||||
|
|
|
|||
|
|
@ -813,14 +813,7 @@ create_device(IUnknown *adapter)
|
|||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
if (!(d3d12_debug & D3D12_DEBUG_EXPERIMENTAL)) {
|
||||
struct d3d12_validation_tools *validation_tools = d3d12_validator_create();
|
||||
if (!validation_tools) {
|
||||
debug_printf("D3D12: failed to initialize validator with experimental shader models disabled\n");
|
||||
return nullptr;
|
||||
}
|
||||
d3d12_validator_destroy(validation_tools);
|
||||
} else
|
||||
if (d3d12_debug & D3D12_DEBUG_EXPERIMENTAL)
|
||||
#endif
|
||||
{
|
||||
D3D12EnableExperimentalFeatures = (PFN_D3D12ENABLEEXPERIMENTALFEATURES)util_dl_get_proc_address(d3d12_mod, "D3D12EnableExperimentalFeatures");
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue