Mesa (main): microsoft/spirv_to_dxil: Add DXIL validation to spirv2dxil

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Nov 9 02:12:52 UTC 2021


Module: Mesa
Branch: main
Commit: 37c366e2830245511d6364b818adc838fc879401
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=37c366e2830245511d6364b818adc838fc879401

Author: Enrico Galli <enrico.galli at intel.com>
Date:   Wed Nov  3 11:18:30 2021 -0700

microsoft/spirv_to_dxil: Add DXIL validation to spirv2dxil

Reviewed-by: Jesse Natalie <jenatali at microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13655>

---

 src/microsoft/spirv_to_dxil/dxil_validation.cpp | 133 ++++++++++++++++++++++++
 src/microsoft/spirv_to_dxil/dxil_validation.h   |  41 ++++++++
 src/microsoft/spirv_to_dxil/meson.build         |   2 +
 src/microsoft/spirv_to_dxil/spirv2dxil.c        |  22 +++-
 4 files changed, 195 insertions(+), 3 deletions(-)

diff --git a/src/microsoft/spirv_to_dxil/dxil_validation.cpp b/src/microsoft/spirv_to_dxil/dxil_validation.cpp
new file mode 100644
index 00000000000..78a0e529b64
--- /dev/null
+++ b/src/microsoft/spirv_to_dxil/dxil_validation.cpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright © 2021 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "dxil_validation.h"
+
+#if DETECT_OS_WINDOWS
+
+#include <cstdio>
+#include <windows.h>
+#include <wrl/client.h>
+
+#include "dxcapi.h"
+
+using Microsoft::WRL::ComPtr;
+
+class DxilBlob : public IDxcBlob {
+ public:
+   DxilBlob(dxil_spirv_object *data) : m_data(data) {}
+
+   LPVOID STDMETHODCALLTYPE
+   GetBufferPointer() override
+   {
+      return m_data->binary.buffer;
+   }
+
+   SIZE_T STDMETHODCALLTYPE
+   GetBufferSize() override
+   {
+      return m_data->binary.size;
+   }
+
+   HRESULT STDMETHODCALLTYPE
+   QueryInterface(REFIID, void **) override
+   {
+      return E_NOINTERFACE;
+   }
+
+   ULONG STDMETHODCALLTYPE
+   AddRef() override
+   {
+      return 1;
+   }
+
+   ULONG STDMETHODCALLTYPE
+   Release() override
+   {
+      return 0;
+   }
+
+   dxil_spirv_object *m_data;
+};
+
+bool
+validate_dxil(dxil_spirv_object *dxil_obj)
+{
+   HMODULE dxil_dll = LoadLibraryA("dxil.dll");
+   if (!dxil_dll) {
+      fprintf(stderr, "Unable to load dxil.dll\n");
+      return false;
+   }
+   DxcCreateInstanceProc dxc_create_instance =
+      reinterpret_cast<DxcCreateInstanceProc>(
+         GetProcAddress(dxil_dll, "DxcCreateInstance"));
+
+   bool res = false;
+   DxilBlob blob(dxil_obj);
+   // Creating a block so that ComPtrs free before we call FreeLibrary
+   {
+      ComPtr<IDxcValidator> validator;
+      if (FAILED(dxc_create_instance(CLSID_DxcValidator,
+                                     IID_PPV_ARGS(&validator)))) {
+         fprintf(stderr, "Failed to create DxcValidator instance \n");
+         FreeLibrary(dxil_dll);
+         return false;
+      }
+
+      ComPtr<IDxcOperationResult> result;
+      validator->Validate(&blob, DxcValidatorFlags_InPlaceEdit, &result);
+      HRESULT status;
+      result->GetStatus(&status);
+      if (FAILED(status)) {
+         ComPtr<IDxcBlobEncoding> error;
+         result->GetErrorBuffer(&error);
+         BOOL known = false;
+         uint32_t cp = 0;
+         error->GetEncoding(&known, &cp);
+         fprintf(stderr, "DXIL: ");
+         if (cp == CP_UTF8 || cp == CP_ACP) {
+            fprintf(stderr, "%s\n",
+                    static_cast<char *>(error->GetBufferPointer()));
+         } else {
+            fwprintf(stderr, L"%ls\n",
+                     static_cast<wchar_t *>(error->GetBufferPointer()));
+         }
+      } else {
+         res = true;
+      }
+   }
+
+   FreeLibrary(dxil_dll);
+   return res;
+}
+
+#else
+
+bool
+validate_dxil(dxil_spirv_object *dxil_obj)
+{
+   fprintf(stderr, "DXIL validation only available in Windows.\n");
+   return false;
+}
+
+#endif
diff --git a/src/microsoft/spirv_to_dxil/dxil_validation.h b/src/microsoft/spirv_to_dxil/dxil_validation.h
new file mode 100644
index 00000000000..fcb58f4ed1b
--- /dev/null
+++ b/src/microsoft/spirv_to_dxil/dxil_validation.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright © 2021 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef DXIL_VALIDATION_H
+#define DXIL_VALIDATION_H
+
+#include "spirv_to_dxil.h"
+#include "util/detect_os.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool
+validate_dxil(struct dxil_spirv_object *dxil_obj);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DXIL_VALIDATION_H */
diff --git a/src/microsoft/spirv_to_dxil/meson.build b/src/microsoft/spirv_to_dxil/meson.build
index d3e32b98073..1033d283ec3 100644
--- a/src/microsoft/spirv_to_dxil/meson.build
+++ b/src/microsoft/spirv_to_dxil/meson.build
@@ -38,6 +38,8 @@ spirv_to_dxil = executable(
   'spirv2dxil',
   files(
     'spirv2dxil.c',
+    'dxil_validation.h',
+    'dxil_validation.cpp',
   ),
   dependencies : [idep_nir, idep_libdxil_compiler, idep_getopt],
   include_directories : [inc_include, inc_src, inc_compiler, inc_gallium],
diff --git a/src/microsoft/spirv_to_dxil/spirv2dxil.c b/src/microsoft/spirv_to_dxil/spirv2dxil.c
index 858f58c1a46..941d7590052 100644
--- a/src/microsoft/spirv_to_dxil/spirv2dxil.c
+++ b/src/microsoft/spirv_to_dxil/spirv2dxil.c
@@ -29,6 +29,7 @@
  */
 
 #include "nir_to_dxil.h"
+#include "dxil_validation.h"
 #include "spirv/nir_spirv.h"
 #include "spirv_to_dxil.h"
 
@@ -68,16 +69,20 @@ main(int argc, char **argv)
    char *entry_point = "main";
    char *output_file = "";
    int ch;
-
+   bool validate = false;
+   
    static struct option long_options[] = {
       {"stage", required_argument, 0, 's'},
       {"entry", required_argument, 0, 'e'},
       {"output", required_argument, 0, 'o'},
+      {"validate", no_argument, 0, 'v'},
       {0, 0, 0, 0}};
 
-   while ((ch = getopt_long(argc, argv, "s:e:o:", long_options, NULL)) !=
+
+   while ((ch = getopt_long(argc, argv, "s:e:o:v", long_options, NULL)) !=
           -1) {
-      switch (ch) {
+      switch(ch)
+      {
       case 's':
          shader_stage = stage_to_enum(optarg);
          if (shader_stage == MESA_SHADER_NONE) {
@@ -91,6 +96,9 @@ main(int argc, char **argv)
       case 'o':
          output_file = optarg;
          break;
+      case 'v':
+         validate = true;
+         break;
       default:
          fprintf(stderr, "Unrecognized option.\n");
          return 1;
@@ -132,6 +140,14 @@ main(int argc, char **argv)
    if (spirv_to_dxil((uint32_t *)file_contents, word_count, NULL, 0,
                      (dxil_spirv_shader_stage)shader_stage, entry_point,
                      &conf, &obj)) {
+
+      if (validate && !validate_dxil(&obj)) {
+         fprintf(stderr, "Failed to validate DXIL\n");
+         spirv_to_dxil_free(&obj);
+         free(file_contents);
+         return 1;
+      }
+
       FILE *file = fopen(output_file, "wb");
       if (!file) {
          fprintf(stderr, "Failed to open %s, %s\n", output_file,



More information about the mesa-commit mailing list